Skip to content

refactor: move declarations to ambient modules #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,24 @@ A developers goodie for [Strapi Headless CMS](https://github.com/strapi/strapi)
yarn add -D strapi-typed@latest
```

and then use
After install typings should be automatically available if you import from `@strapi/strapi`.

If you want to use are internal utility types then use

```typescript
import { StringMap, OnlyStrings } from "@strapi/typed";
```

In few place plugin creator or Strapi consumer can extend couple of interfaces to add custom typings

For example

```typescript
import { IStrapi } from 'strapi-typed';
declare module '@strapi/strapi' {
export interface IStrapiRequestQueryFiltersExtra {
threadOf?: number | string | null;
}
}
```

Enjoy 🎉
Expand Down
229 changes: 143 additions & 86 deletions types/api.ts
Original file line number Diff line number Diff line change
@@ -1,93 +1,150 @@
import { StringMap, Primitive, TypeResult } from "./common";
import { PopulateClause, StrapiUser } from "./core";
import { OnlyStrings } from "./utils";

type SendStrapiContextFunction = (...args: unknown[]) => void;

type ThrowStrapiContextFunction = (...args: unknown[]) => void;

type StrapiHTTPErrorConstructor<T = StringMap<unknown>> = (message?: string, details?: T) => any

export type StrapiRequestContext<
TBody extends {} = StringMap<string | number>,
TQuery extends {} = StringMap<string | number>,
TParams extends {} = StringMap<string | number>
> = {
request: StrapiRequest<TBody>;
query: TQuery;
params: TParams;
pagination: StrapiPagination;
sort: StringMap<string | number>;
state: StrapiRequestContextState;

send: SendStrapiContextFunction;
throw: ThrowStrapiContextFunction;

// @see {https://github.com/jshttp/http-errors#list-of-all-constructors}
notFound: StrapiHTTPErrorConstructor;
badRequest: StrapiHTTPErrorConstructor;
unauthorized: StrapiHTTPErrorConstructor;
methodNotAllowed: StrapiHTTPErrorConstructor;
internalServerError: StrapiHTTPErrorConstructor;
notImplemented: StrapiHTTPErrorConstructor;
};

export type StrapiRequest<TBody extends {}> = {
body?: TBody;
};

export type StrapiRequestContextState = {
user?: StrapiUser
};

export type StrapiRequestQuery<T, TFields = keyof T> = {
filters?: {
threadOf?: number | string | null;
[key: string]: any;
} & {};
populate?: StrapiRequestQueryPopulateClause<OnlyStrings<TFields>>;
sort?: StringMap<any>;
fields?: StrapiRequestQueryFieldsClause<OnlyStrings<TFields>>;
pagination?: StrapiPagination;
}

export type StrapiRequestQueryFieldsClause<TKeys extends string = string> = Array<TKeys> | '*';

export type StrapiRequestQueryPopulateClause<TKeys extends string = string> = PopulateClause<TKeys>;

export type StrapiPagination = {
page?: number;
pageSize?: number;
start?: number;
limit?: number;
withCount?: boolean | string;
};

export type StrapiResponseMetaPagination = TypeResult<
Pick<StrapiPagination, "page" | "pageSize" | "start" | "limit"> & {
pageCount?: number;
total?: number;
import { StringMap, OnlyStrings, TypeResult, Primitive } from "@strapi/typed";

declare module "@strapi/strapi" {
type SendStrapiContextFunction = (...args: unknown[]) => void;

type ThrowStrapiContextFunction = (...args: unknown[]) => void;

type StrapiHTTPErrorConstructor<T = StringMap<unknown>> = (
message?: string,
details?: T
) => any;

export type StrapiRequestContext<
TBody extends {} = StringMap<string | number>,
TQuery extends {} = StringMap<string | number>,
TParams extends {} = StringMap<string | number>
> = {
request: StrapiRequest<TBody>;
query: TQuery;
params: TParams;
pagination: StrapiPagination;
sort: StringMap<string | number>;
state: StrapiRequestContextState;

send: SendStrapiContextFunction;
throw: ThrowStrapiContextFunction;

// @see {https://github.com/jshttp/http-errors#list-of-all-constructors}
notFound: StrapiHTTPErrorConstructor;
badRequest: StrapiHTTPErrorConstructor;
unauthorized: StrapiHTTPErrorConstructor;
methodNotAllowed: StrapiHTTPErrorConstructor;
internalServerError: StrapiHTTPErrorConstructor;
notImplemented: StrapiHTTPErrorConstructor;
};

export type StrapiRequest<TBody extends {}> = {
body?: TBody;
};

export type StrapiRequestContextState = {
user?: StrapiUser;
};

export type StrapiRequestQuery<T, TFields = keyof T> = {
filters?: {
threadOf?: number | string | null;
[key: string]: any;
} & {};
populate?: StrapiRequestQueryPopulateClause<OnlyStrings<TFields>>;
sort?: StringMap<any>;
fields?: StrapiRequestQueryFieldsClause<OnlyStrings<TFields>>;
pagination?: StrapiPagination;
};

export type StrapiRequestQueryFieldsClause<TKeys extends string = string> =
| Array<TKeys>
| "*";

export type StrapiRequestQueryPopulateClause<TKeys extends string = string> =
PopulateClause<TKeys>;
interface ISendStrapiContextFunction {
(...args: unknown[]): void;
}
>;

export type StrapiResponseMeta = {
pagination: StrapiResponseMetaPagination;
};

export type StrapiPaginatedResponse<T> = {
data: Array<T>;
meta?: StrapiResponseMeta;
};
interface IThrowStrapiContextFunction {
(...args: unknown[]): void;
}

export type StrapiQueryParams = StringMap<string>;
export interface IStrapiRequestContext<
TBody extends {} = StringMap<string | number>,
TQuery extends {} = StringMap<string | number>,
TParams extends {} = StringMap<string | number>
> {
request: StrapiRequest<TBody>;
query: TQuery;
params: TParams;
pagination: StrapiPagination;
sort: StringMap<string | number>;
state: StrapiRequestContextState;

send: ISendStrapiContextFunction;
throw: IThrowStrapiContextFunction;
}

export type StrapiQueryParamsParsed = StringMap<Primitive>;
export interface IStrapiController<
TBody extends {} = StringMap<string | number>,
TQuery extends {} = StringMap<string | number>,
TParams extends {} = StringMap<string | number>,
TResult = unknown
> {
(ctx: IStrapiRequestContext<TBody, TQuery, TParams>): TResult;
}

export type StrapiQueryParamsParsedOrderBy = string | Array<string>;
export interface IStrapiRequestQueryFiltersExtra {}

type StrapiQueryParamsParsedFilterValue<TKeys extends string = string> =
| Primitive
| Partial<Record<TKeys, unknown>>;
export interface IStrapiRequestQuery<T, TFields = keyof T> {
filters?: {
[key: string]: any;
} & IStrapiRequestQueryFiltersExtra;
populate?: StrapiRequestQueryPopulateClause<OnlyStrings<TFields>>;
sort?: StringMap<any>;
fields?: StrapiRequestQueryFieldsClause<OnlyStrings<TFields>>;
pagination?: StrapiPagination;
}

export type StrapiQueryParamsParsedFilters<TValue, TKeys = keyof TValue> =
Partial<Record<OnlyStrings<TKeys>, StrapiQueryParamsParsedFilterValue<OnlyStrings<TKeys>>>>;
export type StrapiPagination = {
page?: number;
pageSize?: number;
start?: number;
limit?: number;
withCount?: boolean | string;
};

export type StrapiResponseMetaPagination = TypeResult<
Pick<StrapiPagination, "page" | "pageSize" | "start" | "limit"> & {
pageCount?: number;
total?: number;
}
>;

export type StrapiResponseMeta = {
pagination: StrapiResponseMetaPagination;
};

export type StrapiPaginatedResponse<T> = {
data: Array<T>;
meta?: StrapiResponseMeta;
};

export type StrapiQueryParams = StringMap<string>;

export type StrapiQueryParamsParsed = StringMap<Primitive>;

export type StrapiQueryParamsParsedOrderBy = string | Array<string>;

type StrapiQueryParamsParsedFilterValue<TKeys extends string = string> =
| Primitive
| Partial<Record<TKeys, unknown>>;

export type StrapiQueryParamsParsedFilters<
TValue,
TKeys = keyof TValue
> = Partial<
Record<
OnlyStrings<TKeys>,
StrapiQueryParamsParsedFilterValue<OnlyStrings<TKeys>>
>
>;
}
20 changes: 11 additions & 9 deletions types/common.d.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
export type PropType<TObj, TProp extends keyof TObj> = TObj[TProp];
declare module "@strapi/typed" {
export type PropType<TObj, TProp extends keyof TObj> = TObj[TProp];

export type Primitive = string | number | object | boolean | null | undefined;
export type Primitive = string | number | object | boolean | null | undefined;

export type KeyValueSet<T> = Record<string, T | any>;
export type KeyValueSet<T> = Record<string, T | any>;

export type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
export type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";

export type StringMap<Type> = Record<string, Type>;
export type StringMap<Type> = Record<string, Type>;

export type TypeResult<T> = {
[K in keyof T]: T[K];
};
export type TypeResult<T> = {
[K in keyof T]: T[K];
};

export type Id = number | string;
export type Id = number | string;
}
Loading