mirror of
https://github.com/strapi/strapi.git
synced 2025-12-28 07:33:17 +00:00
Merge pull request #16724 from strapi/ts-support-2/type-system
This commit is contained in:
commit
2a194c2c24
8
packages/core/strapi/lib/types/core/common/controller.d.ts
vendored
Normal file
8
packages/core/strapi/lib/types/core/common/controller.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
import type koa from 'koa';
|
||||
|
||||
export type ControllerHandler = <T>(
|
||||
context: koa.ExtendableContext,
|
||||
next: koa.Next
|
||||
) => Promise<T | void> | T | void;
|
||||
|
||||
export type Controller = Record<string, ControllerHandler>;
|
||||
2
packages/core/strapi/lib/types/core/common/index.d.ts
vendored
Normal file
2
packages/core/strapi/lib/types/core/common/index.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './controller';
|
||||
export * from './service';
|
||||
1
packages/core/strapi/lib/types/core/common/service.d.ts
vendored
Normal file
1
packages/core/strapi/lib/types/core/common/service.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export type Service = Record<keyof any, unknown>;
|
||||
@ -1,3 +1,8 @@
|
||||
export * from './attributes';
|
||||
export * from './schemas';
|
||||
export * from './strapi';
|
||||
|
||||
export * as Common from './common';
|
||||
export * as Namespace from './namespace';
|
||||
export * as UID from './uid';
|
||||
export * as Registry from './registry';
|
||||
|
||||
94
packages/core/strapi/lib/types/core/namespace.d.ts
vendored
Normal file
94
packages/core/strapi/lib/types/core/namespace.d.ts
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
import type * as Utils from '../utils';
|
||||
|
||||
/**
|
||||
* Namespace for admin resources
|
||||
*/
|
||||
export type Admin = 'admin';
|
||||
|
||||
/**
|
||||
* Namespace for strapi internal resources
|
||||
*/
|
||||
export type Strapi = 'strapi';
|
||||
|
||||
/**
|
||||
* Namespace for scoped APIs resources
|
||||
*/
|
||||
export type API<T extends string = string> = `api${ColonsSeparator}${T}`;
|
||||
|
||||
/**
|
||||
* Namespace for scoped plugins resources
|
||||
*/
|
||||
export type Plugin<T extends string = string> = `plugin${ColonsSeparator}${T}`;
|
||||
|
||||
/**
|
||||
* Namespace for global resources
|
||||
*/
|
||||
export type Global = 'global';
|
||||
|
||||
/**
|
||||
* Represents any namespace
|
||||
*/
|
||||
export type Any = API | Plugin | Admin | Strapi | Global;
|
||||
|
||||
/**
|
||||
* Return a {@link Separator} based on the given {@link Any} ({@link DotSeparator} for {@link Scoped} and {@link ColonsSeparator} for regular ones)
|
||||
*
|
||||
* @example
|
||||
* type S = GetSeparator<Admin>
|
||||
* // ^ '::'
|
||||
*
|
||||
* type S = GetSeparator<API>
|
||||
* // ^ '.'
|
||||
*
|
||||
* type S = GetSeparator<Admin | API>
|
||||
* // ^ '.' | '::'
|
||||
*/
|
||||
export type GetSeparator<T extends Any = Any> = T extends Scoped
|
||||
? // 'api::foo' | 'plugin::bar' => '.'
|
||||
DotSeparator
|
||||
: // 'admin' | 'strapi' | 'global' => '::'
|
||||
ColonsSeparator;
|
||||
|
||||
/**
|
||||
* Adds the corresponding separator (using {@link GetSeparator}) at the end of a namespace
|
||||
*
|
||||
* Warning: Using WithSeparator with a union type might produce undesired results as it'll distribute every matching suffix to every union member
|
||||
*
|
||||
* @example
|
||||
* type T = WithSeparator<Admin>
|
||||
* // ^ 'admin::'
|
||||
*
|
||||
* type T = WithSeparator<API>
|
||||
* // ^ 'api::{string}.'
|
||||
*
|
||||
* type T = WithSeparator<Admin | API>
|
||||
* // ^ 'admin::' | 'admin.' | 'api::{string}.' | 'api::{string}::'
|
||||
*
|
||||
* type T = WithSeparator<Admin> | WithSeparator<API>
|
||||
* // ^ 'admin::' | 'api::{string}.'
|
||||
*/
|
||||
export type WithSeparator<N extends Any> = Utils.Suffix<N, GetSeparator<N>>;
|
||||
|
||||
/**
|
||||
* Represents namespaces composed of an origin and a name, separated by colons
|
||||
*/
|
||||
export type Scoped<O extends string = string, S extends string = string> = Any &
|
||||
`${O}${ColonsSeparator}${S}`;
|
||||
|
||||
/**
|
||||
* Extract the scope from the given scoped namespace
|
||||
*/
|
||||
export type ExtractScope<T> = T extends `${string}${ColonsSeparator}${infer S}` ? S : never;
|
||||
|
||||
/**
|
||||
* Extract the origin from the given scoped namespace
|
||||
*/
|
||||
export type ExtractOrigin<T> = T extends `${infer S}${ColonsSeparator}${string}` ? S : never;
|
||||
|
||||
/**
|
||||
* Separators used to join the different parts of a namespace (e.g. building a uid)
|
||||
*/
|
||||
export type Separator = ColonsSeparator | DotSeparator;
|
||||
|
||||
type ColonsSeparator = '::';
|
||||
type DotSeparator = '.';
|
||||
59
packages/core/strapi/lib/types/core/registry.d.ts
vendored
Normal file
59
packages/core/strapi/lib/types/core/registry.d.ts
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
import type * as UID from './uid';
|
||||
|
||||
/**
|
||||
* Extract valid keys from a given registry.
|
||||
*
|
||||
* It looks for {@link UID.Any} by default but the search can be narrowed to any UID subset using the `U` generic.
|
||||
*
|
||||
* @example
|
||||
* interface Registry {
|
||||
* 'foo': unknown;
|
||||
* 'default.foo': 'unknown';
|
||||
* 'global::foo': unknown;
|
||||
* 'api::foo.bar': unknown;
|
||||
* }
|
||||
*
|
||||
* type T = Keys<Registry>;
|
||||
* // ^ 'default.foo' | 'global::foo' | 'api::foo.bar'
|
||||
* type T = Keys<Registry, UID.Policy>;
|
||||
* // ^ 'global::foo' | 'api::foo.bar'
|
||||
* type T = Keys<Registry, UID.Service>
|
||||
* // ^ 'api::foo.bar'
|
||||
*/
|
||||
export type Keys<R, U extends UID.Any = UID.Any> = Extract<keyof R, U>;
|
||||
|
||||
/**
|
||||
* Performs a `Q` filtering operation on the given `T` registry.
|
||||
*
|
||||
* `Q` needs to be a partial representation of a {@link UID.Parsed}
|
||||
*
|
||||
* Note: For additional filtering, the registry keys' type can be passed as the third generic.
|
||||
*
|
||||
* @example
|
||||
* interface Registry {
|
||||
* 'admin::foo': unknown;
|
||||
* 'admin::bar': unknown;
|
||||
* 'api::foo.bar': unknown;
|
||||
* 'api::foo.baz': unknown;
|
||||
* 'api::bar.foo': unknown;
|
||||
* 'plugin::foo.bar': unknown;
|
||||
* }
|
||||
*
|
||||
* type T = keyof WhereKeys<Registry, { namespace: Namespace.API }>;
|
||||
* // ^ "api::foo.bar" | "api::foo.baz" | "api::bar.foo"
|
||||
*
|
||||
* type T = keyof WhereKeys<Registry, { name: 'bar' }>;
|
||||
* // ^ "admin::bar" | "api::foo.bar" | "plugin::foo.bar"
|
||||
*
|
||||
* type T = keyof WhereKeys<Registry, { separator: '.' }>;
|
||||
* // ^ "api::foo.bar" | "api::foo.baz" | "api::bar.foo" | 'plugin::foo.bar"
|
||||
*
|
||||
* type T = keyof WhereKeys<Registry, { namespace: Namespace.Plugin | Namespace.Admin }>;
|
||||
* // ^ "plugin::foo.bar" | "admin::foo" | "admin::bar"
|
||||
*
|
||||
* type T = keyof WhereKeys<Registry, { namespace: Namespace.API; name: Utils.Includes<'b'> }>;
|
||||
* // ^ "api::foo.bar" | "api::foo.baz"
|
||||
*/
|
||||
export type WhereKeys<T, Q extends Partial<UID.Parsed>, U extends UID.Any = UID.Any> = {
|
||||
[uid in Keys<T, U> as UID.Parse<uid> extends Q ? uid : never]: T[uid];
|
||||
};
|
||||
154
packages/core/strapi/lib/types/core/uid.d.ts
vendored
Normal file
154
packages/core/strapi/lib/types/core/uid.d.ts
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
import type * as Namespace from './namespace';
|
||||
import type * as Utils from '../utils';
|
||||
|
||||
type StringSuffix<T extends string> = Utils.Suffix<T, string>;
|
||||
|
||||
/**
|
||||
* Template for services' unique identifier
|
||||
*/
|
||||
export type Service = StringSuffix<
|
||||
| Namespace.WithSeparator<Namespace.Admin>
|
||||
| Namespace.WithSeparator<Namespace.API>
|
||||
| Namespace.WithSeparator<Namespace.Plugin>
|
||||
>;
|
||||
|
||||
/**
|
||||
* Template for controllers' unique identifier
|
||||
*/
|
||||
export type Controller = StringSuffix<
|
||||
| Namespace.WithSeparator<Namespace.Admin>
|
||||
| Namespace.WithSeparator<Namespace.API>
|
||||
| Namespace.WithSeparator<Namespace.Plugin>
|
||||
>;
|
||||
|
||||
/**
|
||||
* Template for policies' unique identifier
|
||||
*/
|
||||
export type Policy = StringSuffix<
|
||||
| Namespace.WithSeparator<Namespace.Admin>
|
||||
| Namespace.WithSeparator<Namespace.Strapi>
|
||||
| Namespace.WithSeparator<Namespace.Global>
|
||||
| Namespace.WithSeparator<Namespace.API>
|
||||
| Namespace.WithSeparator<Namespace.Plugin>
|
||||
>;
|
||||
|
||||
/**
|
||||
* Template for middlewares' unique identifier
|
||||
*/
|
||||
export type Middleware = StringSuffix<
|
||||
| Namespace.WithSeparator<Namespace.Admin>
|
||||
| Namespace.WithSeparator<Namespace.Strapi>
|
||||
| Namespace.WithSeparator<Namespace.Global>
|
||||
| Namespace.WithSeparator<Namespace.API>
|
||||
| Namespace.WithSeparator<Namespace.Plugin>
|
||||
>;
|
||||
|
||||
/**
|
||||
* Template for content-types' unique identifier
|
||||
*/
|
||||
export type ContentType = StringSuffix<
|
||||
| Namespace.WithSeparator<Namespace.Admin>
|
||||
| Namespace.WithSeparator<Namespace.Strapi>
|
||||
| Namespace.WithSeparator<Namespace.API>
|
||||
| Namespace.WithSeparator<Namespace.Plugin>
|
||||
>;
|
||||
|
||||
/**
|
||||
* Template for components' unique identifier
|
||||
*
|
||||
* Warning: Can cause overlap with other UID formats.
|
||||
*/
|
||||
export type Component = `${string}.${string}`;
|
||||
|
||||
/**
|
||||
* Represents any UID
|
||||
*/
|
||||
export type Any = Service | Controller | Policy | Middleware | ContentType | Component;
|
||||
|
||||
/**
|
||||
* Type representation of every UID component.
|
||||
*
|
||||
* The separator type is automatically inferred from the given namespace
|
||||
*/
|
||||
export interface Parsed<N extends Namespace.Any = Namespace.Any, E extends string = string> {
|
||||
raw: `${N}${Namespace.GetSeparator<N>}${E}`;
|
||||
namespace: N;
|
||||
origin: N extends Namespace.Scoped ? Namespace.ExtractOrigin<N> : N;
|
||||
scope: N extends Namespace.Scoped ? Namespace.ExtractScope<N> : never;
|
||||
separator: Namespace.GetSeparator<N>;
|
||||
name: E;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a UID literal and returns a {@link Parsed} type.
|
||||
*
|
||||
* Warning: Using ParseUID with a union type might produce undesired results as it'll distribute every matching namespace parsing to every union member
|
||||
*
|
||||
* @example
|
||||
* type T = Parse<'admin::foo'>
|
||||
* // ^ { namespace: 'admin'; separator: '::'; name: 'foo'; }
|
||||
*
|
||||
* type T = Parse<'api::foo.bar'>
|
||||
* // ^ { namespace: 'api::foo'; separator: '.'; name: 'bar'; }
|
||||
*
|
||||
* type T = Parse<'admin::foo' | 'api::foo.bar'>
|
||||
* // ^ { namespace: 'admin' | 'api::foo' ; separator: '.' | '::'; name: 'foo' | 'bar' | 'foo.bar'; }
|
||||
*/
|
||||
export type Parse<U extends Any> = ExtractNamespace<U> extends infer B extends Namespace.Any
|
||||
? Namespace.GetSeparator<B> extends infer S extends Namespace.Separator
|
||||
? U extends `${infer N extends B}${S}${infer E extends string}`
|
||||
? Parsed<N, E>
|
||||
: never
|
||||
: never
|
||||
: never;
|
||||
|
||||
/**
|
||||
* Determines if the UID's namespace matches the given one.
|
||||
*
|
||||
* It returns N (the {@link Namespace.Any} literal) if there is a match, never otherwise.
|
||||
*
|
||||
* @example
|
||||
* type T = EnsureNamespaceMatches<'admin::foo', Namespace.Admin>
|
||||
* // ^ Namespace.Admin
|
||||
* @example
|
||||
* type T = EnsureNamespaceMatches<'foo.bar', Namespace.API>
|
||||
* // ^ never
|
||||
* @example
|
||||
* type T = EnsureNamespaceMatches<'api::foo.bar', Namespace.Plugin>
|
||||
* // ^ never
|
||||
*/
|
||||
export type EnsureNamespaceMatches<U extends Any, N extends Namespace.Any> = U extends StringSuffix<
|
||||
Namespace.WithSeparator<N>
|
||||
>
|
||||
? N
|
||||
: never;
|
||||
|
||||
/**
|
||||
* Get parsed properties from a given raw UID
|
||||
*/
|
||||
export type Get<U extends Any, P extends keyof Parsed> = Parse<U>[P];
|
||||
|
||||
/**
|
||||
* Pick parsed properties from a given raw UID
|
||||
*/
|
||||
export type Select<U extends Any, P extends keyof Parse<U>> = Pick<Parse<U>, P>;
|
||||
|
||||
/**
|
||||
* Extract the namespace literal from a given UID.
|
||||
*
|
||||
* @example
|
||||
* type T = ExtractNamespace<'admin::foo'>
|
||||
* // ^ Namespace.Admin
|
||||
* @example
|
||||
* type T = ExtractNamespace<'api::foo.bar'>
|
||||
* // ^ Namespace.API
|
||||
* @example
|
||||
* type T = ExtractNamespace<'admin::foo' | 'api::foo.bar'>
|
||||
* // ^ Namespace.Admin | Namespace.API
|
||||
*/
|
||||
export type ExtractNamespace<U extends Any> =
|
||||
| EnsureNamespaceMatches<U, Namespace.Global>
|
||||
| EnsureNamespaceMatches<U, Namespace.Admin>
|
||||
| EnsureNamespaceMatches<U, Namespace.Strapi>
|
||||
| EnsureNamespaceMatches<U, Namespace.API>
|
||||
| EnsureNamespaceMatches<U, Namespace.Plugin>;
|
||||
3
packages/core/strapi/lib/types/index.d.ts
vendored
3
packages/core/strapi/lib/types/index.d.ts
vendored
@ -1,4 +1,7 @@
|
||||
// Exports from core should already be modules
|
||||
export * from './core';
|
||||
|
||||
export * as utils from './utils';
|
||||
export * as factories from './factories';
|
||||
|
||||
export * as Shared from './shared';
|
||||
|
||||
1
packages/core/strapi/lib/types/shared/index.d.ts
vendored
Normal file
1
packages/core/strapi/lib/types/shared/index.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export * from './registries';
|
||||
29
packages/core/strapi/lib/types/shared/registries.d.ts
vendored
Normal file
29
packages/core/strapi/lib/types/shared/registries.d.ts
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Shared service registry
|
||||
*/
|
||||
export interface Services {}
|
||||
|
||||
/**
|
||||
* Shared controller registry
|
||||
*/
|
||||
export interface Controllers {}
|
||||
|
||||
/**
|
||||
* Shared policy registry
|
||||
*/
|
||||
export interface Policies {}
|
||||
|
||||
/**
|
||||
* Shared middleware registry
|
||||
*/
|
||||
export interface Middlewares {}
|
||||
|
||||
/**
|
||||
* Shared content-types registry
|
||||
*/
|
||||
export interface ContentTypes {}
|
||||
|
||||
/**
|
||||
* Shared component registry
|
||||
*/
|
||||
export interface Components {}
|
||||
46
packages/core/strapi/lib/types/utils.d.ts
vendored
46
packages/core/strapi/lib/types/utils.d.ts
vendored
@ -4,6 +4,52 @@
|
||||
*
|
||||
* */
|
||||
|
||||
/**
|
||||
* Alias for any literal type (useful for template string parameters)
|
||||
*/
|
||||
export type Literal = string | number | bigint | boolean;
|
||||
|
||||
/**
|
||||
* Used to check if a string includes a given literal
|
||||
*/
|
||||
export type Includes<S extends Literal> = `${string}${S}${string}`;
|
||||
|
||||
/**
|
||||
* Used to make sure the given string is not empty
|
||||
*/
|
||||
export type NonEmpty<T extends string> = T extends '' ? never : T;
|
||||
|
||||
/**
|
||||
* Split the given string into a tuple using the given `S` literal
|
||||
*/
|
||||
export type Split<T extends string, S extends Literal> = T extends `${infer A}${S}${infer B}`
|
||||
? [A, ...Split<B, S>]
|
||||
: T extends ''
|
||||
? []
|
||||
: [T];
|
||||
|
||||
/**
|
||||
* Aggregate the given tuple into a string, separated by the given `S` literal
|
||||
*/
|
||||
export type Join<T extends unknown[], S extends Literal> = T extends [
|
||||
infer F extends Literal,
|
||||
...infer R
|
||||
]
|
||||
? R['length'] extends 0
|
||||
? F
|
||||
: `${F}${S}${Join<R, S>}`
|
||||
: never;
|
||||
|
||||
/**
|
||||
* Add a literal suffix (`S`) at the end of the given string
|
||||
*/
|
||||
export type Suffix<T extends string, S extends Literal> = `${T}${S}`;
|
||||
|
||||
/**
|
||||
* Add a literal prefix (`S`) at the beginning of the given string
|
||||
*/
|
||||
export type Prefix<T extends string, S extends Literal> = `${S}${T}`;
|
||||
|
||||
/**
|
||||
*
|
||||
* Extract the array values into an union type
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user