@koine/api 2.0.0-beta.55 → 2.0.0-beta.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
- export declare class ApiError<TResponseFail extends Koine.Api.ResponseFail = unknown> extends Error {
2
- constructor(result: Koine.Api.ResultFail<TResponseFail>);
1
+ import type { Api } from "./types";
2
+ export declare class ApiError<TResponseFail extends Api.ResponseFail = unknown> extends Error {
3
+ constructor(result: Api.ResultFail<TResponseFail>);
3
4
  }
4
- export declare let createApiResultOk: <T>(data?: T, msg?: string) => Koine.Api.ResultOk<T>;
5
- export declare let createApiResultFail: <T>(data?: T, msg?: string, status?: number) => Koine.Api.ResultFail<T>;
6
- export declare let createApi: <TEndpoints extends Koine.Api.Endpoints>(apiName: string, baseUrl: string, options?: Koine.Api.ClientOptions) => Koine.Api.Client<TEndpoints>;
5
+ export declare let createApiResultOk: <T>(data?: T, msg?: string) => Api.ResultOk<T>;
6
+ export declare let createApiResultFail: <T>(data?: T, msg?: string, status?: number) => Api.ResultFail<T>;
7
+ export declare let createApi: <TEndpoints extends Api.Endpoints>(apiName: string, baseUrl: string, options?: Api.ClientOptions) => Api.Client<TEndpoints>;
8
+ export type { Api } from "./types";
package/next.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import type { NextApiResponse } from "next";
2
2
  import { NextResponse } from "next/server";
3
3
  export declare let nextApiResponse: {
4
- ok<T>(data: T, msg?: string): NextResponse<Koine.Api.ResultOk<T>>;
5
- fail<T_1>(data: T_1, msg?: string, status?: number): NextResponse<Koine.Api.ResultFail<T_1>>;
4
+ ok<T>(data: T, msg?: string): NextResponse<import("./types").Api.ResultOk<T>>;
5
+ fail<T_1>(data: T_1, msg?: string, status?: number): NextResponse<import("./types").Api.ResultFail<T_1>>;
6
6
  };
7
7
  export declare let nextApiResponse12: (nextRes: NextApiResponse) => {
8
8
  ok<T>(data: T, msg?: string): void;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@koine/api",
3
3
  "sideEffects": false,
4
4
  "dependencies": {
5
- "@koine/utils": "2.0.0-beta.55"
5
+ "@koine/utils": "2.0.0-beta.56"
6
6
  },
7
7
  "peerDependencies": {
8
8
  "next": "^14.0.4",
@@ -41,5 +41,5 @@
41
41
  },
42
42
  "module": "./index.esm.js",
43
43
  "main": "./index.cjs.js",
44
- "version": "2.0.0-beta.55"
44
+ "version": "2.0.0-beta.56"
45
45
  }
package/swr-mutation.d.ts CHANGED
@@ -1,16 +1,17 @@
1
1
  import { type SWRMutationConfiguration, type SWRMutationResponse } from "swr/mutation";
2
2
  import { createUseApi } from "./swr";
3
- type MutationRequestMethod = Exclude<Koine.Api.RequestMethod, "get">;
4
- type MutationHookName = Exclude<keyof Koine.Api.HooksMapsByName, "use">;
5
- type KoineApiMethodHookSWR<THookName extends MutationHookName, TEndpoints extends Koine.Api.Endpoints> = <TEndpoint extends Koine.Api.EndpointUrl<TEndpoints>, TMethod extends MutationRequestMethod = Koine.Api.HooksMapsByName[THookName]>(endpoint: TEndpoint, options?: Koine.Api.EndpointOptions<TEndpoints, TEndpoint, TMethod>, config?: SWRMutationConfiguration<Koine.Api.EndpointResponseOk<TEndpoints, TEndpoint, TMethod>, Koine.Api.EndpointResponseFail<TEndpoints, TEndpoint, TMethod>, TEndpoint, Koine.Api.EndpointOptions<TEndpoints, TEndpoint, TMethod>>) => SWRMutationResponse<Koine.Api.EndpointResponseOk<TEndpoints, TEndpoint, TMethod>, Koine.Api.EndpointResponseFail<TEndpoints, TEndpoint, TMethod>, TEndpoint, Koine.Api.EndpointOptions<TEndpoints, TEndpoint, TMethod>>;
6
- export declare let createSwrMutationApi: <TEndpoints extends Koine.Api.Endpoints>(apiName: string, baseUrl: string, options?: Koine.Api.ClientOptions | undefined) => Koine.Api.Client<TEndpoints> & {
3
+ import type { Api } from "./types";
4
+ type MutationRequestMethod = Exclude<Api.RequestMethod, "get">;
5
+ type MutationHookName = Exclude<keyof Api.HooksMapsByName, "use">;
6
+ type KoineApiMethodHookSWR<THookName extends MutationHookName, TEndpoints extends Api.Endpoints> = <TEndpoint extends Api.EndpointUrl<TEndpoints>, TMethod extends MutationRequestMethod = Api.HooksMapsByName[THookName]>(endpoint: TEndpoint, options?: Api.EndpointOptions<TEndpoints, TEndpoint, TMethod>, config?: SWRMutationConfiguration<Api.EndpointResponseOk<TEndpoints, TEndpoint, TMethod>, Api.EndpointResponseFail<TEndpoints, TEndpoint, TMethod>, TEndpoint, Api.EndpointOptions<TEndpoints, TEndpoint, TMethod>>) => SWRMutationResponse<Api.EndpointResponseOk<TEndpoints, TEndpoint, TMethod>, Api.EndpointResponseFail<TEndpoints, TEndpoint, TMethod>, TEndpoint, Api.EndpointOptions<TEndpoints, TEndpoint, TMethod>>;
7
+ export declare let createSwrMutationApi: <TEndpoints extends Api.Endpoints>(apiName: string, baseUrl: string, options?: Api.ClientOptions | undefined) => Api.Client<TEndpoints> & {
7
8
  usePost: KoineApiMethodHookSWR<"usePost", TEndpoints>;
8
9
  usePut: KoineApiMethodHookSWR<"usePut", TEndpoints>;
9
10
  usePatch: KoineApiMethodHookSWR<"usePatch", TEndpoints>;
10
11
  useDelete: KoineApiMethodHookSWR<"useDelete", TEndpoints>;
11
12
  } & {
12
- use: <TEndpoint extends Extract<keyof TEndpoints, string>>(endpoint: TEndpoint, options?: Koine.Api.EndpointOptions<TEndpoints, TEndpoint, "get"> | undefined, config?: (Partial<import("swr/_internal").PublicConfiguration<Koine.Api.EndpointResponseOk<TEndpoints, TEndpoint, "get">, Koine.Api.EndpointResponseFail<TEndpoints, TEndpoint, "get">, import("swr/_internal").BareFetcher<any>>> & {
13
+ use: <TEndpoint extends Extract<keyof TEndpoints, string>>(endpoint: TEndpoint, options?: Api.EndpointOptions<TEndpoints, TEndpoint, "get"> | undefined, config?: (Partial<import("swr/_internal").PublicConfiguration<Api.EndpointResponseOk<TEndpoints, TEndpoint, "get">, Api.EndpointResponseFail<TEndpoints, TEndpoint, "get">, import("swr/_internal").BareFetcher<any>>> & {
13
14
  when?: boolean | (() => boolean) | undefined;
14
- }) | undefined) => import("swr/_internal").SWRResponse<Koine.Api.EndpointResponseOk<TEndpoints, TEndpoint, "get">, Koine.Api.EndpointResponseFail<TEndpoints, TEndpoint, "get">, any>;
15
+ }) | undefined) => import("swr/_internal").SWRResponse<Api.EndpointResponseOk<TEndpoints, TEndpoint, "get">, Api.EndpointResponseFail<TEndpoints, TEndpoint, "get">, any>;
15
16
  };
16
17
  export {};
package/swr.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import { type BareFetcher, type SWRConfiguration, type SWRResponse } from "swr";
2
+ import type { Api } from "./types";
2
3
  type SWRConfigurationExtended<Data = any, Error = any, Fn extends BareFetcher<any> = BareFetcher<any>> = SWRConfiguration<Data, Error, Fn> & {
3
4
  when?: boolean | (() => boolean);
4
5
  };
5
- export declare let createUseApi: <TEndpoints extends Koine.Api.Endpoints>(api: Koine.Api.Client<TEndpoints>) => <TEndpoint extends Extract<keyof TEndpoints, string>>(endpoint: TEndpoint, options?: Koine.Api.EndpointOptions<TEndpoints, TEndpoint, "get"> | undefined, config?: SWRConfigurationExtended<Koine.Api.EndpointResponseOk<TEndpoints, TEndpoint, "get">, Koine.Api.EndpointResponseFail<TEndpoints, TEndpoint, "get">, BareFetcher<any>> | undefined) => SWRResponse<Koine.Api.EndpointResponseOk<TEndpoints, TEndpoint, "get">, Koine.Api.EndpointResponseFail<TEndpoints, TEndpoint, "get">, any>;
6
- export declare let createSwrApi: <TEndpoints extends Koine.Api.Endpoints>(apiName: string, baseUrl: string, options?: Koine.Api.ClientOptions | undefined) => Koine.Api.Client<TEndpoints> & {
7
- use: <TEndpoint extends Extract<keyof TEndpoints, string>>(endpoint: TEndpoint, options?: Koine.Api.EndpointOptions<TEndpoints, TEndpoint, "get"> | undefined, config?: SWRConfigurationExtended<Koine.Api.EndpointResponseOk<TEndpoints, TEndpoint, "get">, Koine.Api.EndpointResponseFail<TEndpoints, TEndpoint, "get">, BareFetcher<any>> | undefined) => SWRResponse<Koine.Api.EndpointResponseOk<TEndpoints, TEndpoint, "get">, Koine.Api.EndpointResponseFail<TEndpoints, TEndpoint, "get">, any>;
6
+ export declare let createUseApi: <TEndpoints extends Api.Endpoints>(api: Api.Client<TEndpoints>) => <TEndpoint extends Extract<keyof TEndpoints, string>>(endpoint: TEndpoint, options?: Api.EndpointOptions<TEndpoints, TEndpoint, "get"> | undefined, config?: SWRConfigurationExtended<Api.EndpointResponseOk<TEndpoints, TEndpoint, "get">, Api.EndpointResponseFail<TEndpoints, TEndpoint, "get">, BareFetcher<any>> | undefined) => SWRResponse<Api.EndpointResponseOk<TEndpoints, TEndpoint, "get">, Api.EndpointResponseFail<TEndpoints, TEndpoint, "get">, any>;
7
+ export declare let createSwrApi: <TEndpoints extends Api.Endpoints>(apiName: string, baseUrl: string, options?: Api.ClientOptions | undefined) => Api.Client<TEndpoints> & {
8
+ use: <TEndpoint extends Extract<keyof TEndpoints, string>>(endpoint: TEndpoint, options?: Api.EndpointOptions<TEndpoints, TEndpoint, "get"> | undefined, config?: SWRConfigurationExtended<Api.EndpointResponseOk<TEndpoints, TEndpoint, "get">, Api.EndpointResponseFail<TEndpoints, TEndpoint, "get">, BareFetcher<any>> | undefined) => SWRResponse<Api.EndpointResponseOk<TEndpoints, TEndpoint, "get">, Api.EndpointResponseFail<TEndpoints, TEndpoint, "get">, any>;
8
9
  };
9
10
  export {};
package/types.d.ts ADDED
@@ -0,0 +1,126 @@
1
+ type _Response = Response;
2
+ type ExtractEndpointParams<T extends string> = string extends T ? Record<string, string> : T extends `${infer _Start}{${infer Param}}${infer Rest}` ? {
3
+ [k in Param | keyof ExtractEndpointParams<Rest>]: string | number;
4
+ } : T extends `${infer _Start}{${infer Param}}` ? {
5
+ [k in Param]: string | number;
6
+ } : never;
7
+ export declare namespace Api {
8
+ export type ClientOptions = {
9
+ headers?: RequestInit["headers"];
10
+ request?: Omit<RequestInit, "body" | "headers" | "method">;
11
+ throwErr?: boolean;
12
+ timeout?: number | false | null;
13
+ processReq?: RequestProcessor;
14
+ processRes?: ResponseProcessorRes;
15
+ processErr?: ResponseProcessorErr;
16
+ };
17
+ type ClientMethod<TMethod extends RequestMethod, TEndpoints extends Endpoints> = <TEndpoint extends EndpointUrl<TEndpoints>, TOptions extends EndpointOptions<TEndpoints, TEndpoint, TMethod>, TOk extends ResponseOk = EndpointResponseOk<TEndpoints, TEndpoint, TMethod>, TFail extends ResponseFail = EndpointResponseFail<TEndpoints, TEndpoint, TMethod>>(endpoint: TEndpoint, options?: TOptions) => Promise<EndpointResult<TEndpoints, TEndpoint, TMethod>>;
18
+ export type Client<TEndpoints extends Endpoints> = {
19
+ [TMethod in RequestMethod]: ClientMethod<TMethod, TEndpoints>;
20
+ };
21
+ export type GetDataType<TEndpoints extends Endpoints, TEndpoint extends EndpointUrl<TEndpoints>, TMethod extends RequestMethod, TDataType extends keyof DataTypes<Uppercase<TMethod>>> = TEndpoints[TEndpoint][Uppercase<TMethod>] extends DataTypes<Uppercase<TMethod>> ? TEndpoints[TEndpoint][Uppercase<TMethod>][TDataType] : never;
22
+ export type EndpointOptions<TEndpoints extends Endpoints, TEndpoint extends EndpointUrl<TEndpoints>, TMethod extends RequestMethod> = RequestOptions<TEndpoints, TEndpoint, TMethod, GetDataType<TEndpoints, TEndpoint, TMethod, "json">, GetDataType<TEndpoints, TEndpoint, TMethod, "query">>;
23
+ export type EndpointResponseOk<TEndpoints extends Endpoints, TEndpoint extends EndpointUrl<TEndpoints>, TMethod extends RequestMethod> = GetDataType<TEndpoints, TEndpoint, TMethod, "ok">;
24
+ export type EndpointResponseFail<TEndpoints extends Endpoints, TEndpoint extends EndpointUrl<TEndpoints>, TMethod extends RequestMethod> = GetDataType<TEndpoints, TEndpoint, TMethod, "fail">;
25
+ type EndpointResult<TEndpoints extends Endpoints, TEndpoint extends EndpointUrl<TEndpoints>, TMethod extends RequestMethod> = Result<EndpointResponseOk<TEndpoints, TEndpoint, TMethod>, EndpointResponseFail<TEndpoints, TEndpoint, TMethod>>;
26
+ export type Endpoints = Record<string, Endpoint>;
27
+ type Endpoint = {
28
+ [TMethod in Uppercase<RequestMethod>]?: DataTypes<TMethod>;
29
+ };
30
+ export type EndpointUrl<TEndpoints extends Endpoints> = Extract<keyof TEndpoints, string>;
31
+ type DataTypes<TMethod extends Uppercase<RequestMethod>> = {
32
+ json?: RequestJson;
33
+ query?: RequestQuery;
34
+ ok?: null | unknown;
35
+ fail?: null | unknown;
36
+ };
37
+ export type RequestMethod = "get" | "post" | "put" | "patch" | "delete";
38
+ type RequestJson = unknown;
39
+ type RequestQuery = unknown;
40
+ type RequestParams = unknown;
41
+ type RequestOptions<TEndpoints extends Endpoints, TEndpoint extends EndpointUrl<TEndpoints>, TMethod extends RequestMethod, TJson extends RequestJson, TQuery extends RequestQuery> = Omit<ClientOptions, "processReq"> & {
42
+ processReq?: EndpointRequestProcessor<TEndpoints, TEndpoint, TMethod>;
43
+ params?: ExtractEndpointParams<TEndpoint>;
44
+ query?: TQuery;
45
+ json?: TJson;
46
+ };
47
+ export type ResponseOk = unknown;
48
+ export type ResponseFail = unknown;
49
+ export type ResultOk<TResponse extends ResponseOk = ResponseOk> = {
50
+ status: _Response["status"];
51
+ msg: _Response["statusText"];
52
+ ok: true;
53
+ fail?: false;
54
+ data: TResponse;
55
+ };
56
+ export type ResultFail<TResponse extends ResponseFail = ResponseFail> = {
57
+ status: _Response["status"];
58
+ msg: Error["message"] | _Response["statusText"];
59
+ ok?: false;
60
+ fail: true;
61
+ data: TResponse;
62
+ };
63
+ export type Result<TResponseOk extends ResponseOk, TResponseFail extends ResponseFail> = {
64
+ status: _Response["status"];
65
+ msg: _Response["statusText"];
66
+ ok: true;
67
+ fail?: false;
68
+ data: TResponseOk;
69
+ } | {
70
+ status: _Response["status"];
71
+ msg: Error["message"] | _Response["statusText"];
72
+ ok?: false;
73
+ fail: true;
74
+ data: TResponseFail;
75
+ };
76
+ export type RequestProcessor = (method: RequestMethod, url: string, query: any, json: any, params: any, requestInit: RequestInit) => [
77
+ string,
78
+ RequestQuery,
79
+ RequestJson,
80
+ RequestParams,
81
+ RequestInit
82
+ ];
83
+ export type EndpointRequestProcessor<TEndpoints extends Endpoints, TEndpoint extends EndpointUrl<TEndpoints>, TMethod extends RequestMethod> = (method: TMethod, url: string, query: EndpointOptions<TEndpoints, TEndpoint, TMethod>["query"], json: EndpointOptions<TEndpoints, TEndpoint, TMethod>["json"], params: EndpointOptions<TEndpoints, TEndpoint, TMethod>["params"], requestInit: RequestInit) => [
84
+ string,
85
+ EndpointOptions<TEndpoints, TEndpoint, TMethod>["query"],
86
+ EndpointOptions<TEndpoints, TEndpoint, TMethod>["json"],
87
+ EndpointOptions<TEndpoints, TEndpoint, TMethod>["params"],
88
+ RequestInit
89
+ ];
90
+ type ResponseProcessorRes = <TResponseOk extends ResponseOk = ResponseOk, TResponseFail extends ResponseFail = ResponseFail>(response: _Response, options: any) => Promise<Result<TResponseOk, TResponseFail>>;
91
+ type ResponseProcessorErr = <TResponseOk extends ResponseOk = ResponseOk, TResponseFail extends ResponseFail = ResponseFail>(msg: string, options: any) => Promise<Result<TResponseOk, TResponseFail>>;
92
+ type HooksMaps = {
93
+ [TMethod in RequestMethod]: `use${TMethod extends "get" ? "" : Capitalize<TMethod>}`;
94
+ };
95
+ export type HooksMapsByName = {
96
+ [K in keyof HooksMaps as HooksMaps[K]]: K;
97
+ };
98
+ export {};
99
+ }
100
+ export declare namespace Api.Generate {
101
+ type ResultShortcuts<TEndpoints extends Endpoints> = {
102
+ [TMethod in RequestMethod]: {
103
+ [TEndpoint in Extract<keyof TEndpoints, string>]: {
104
+ ok: GetDataType<TEndpoints, TEndpoint, TMethod, "ok">;
105
+ fail: GetDataType<TEndpoints, TEndpoint, TMethod, "fail">;
106
+ };
107
+ };
108
+ };
109
+ type ResponseShortcuts<TEndpoints extends Endpoints> = {
110
+ [TMethod in RequestMethod]: {
111
+ [TEndpoint in Extract<keyof TEndpoints, string>]: GetDataType<TEndpoints, TEndpoint, TMethod, "ok">;
112
+ };
113
+ };
114
+ type RequestShortcuts<TEndpoints extends Endpoints> = {
115
+ [TMethod in RequestMethod]: {
116
+ [TEndpoint in Extract<keyof TEndpoints, string>]: TMethod extends "get" ? GetDataType<TEndpoints, TEndpoint, TMethod, "query"> : GetDataType<TEndpoints, TEndpoint, TMethod, "json">;
117
+ };
118
+ };
119
+ type GetShortcuts<TEndpoints extends Endpoints> = {
120
+ [TEndpoint in Extract<keyof TEndpoints, string>]: GetDataType<TEndpoints, TEndpoint, "get", "ok">;
121
+ };
122
+ type PostShortcuts<TEndpoints extends Endpoints> = {
123
+ [TEndpoint in Extract<keyof TEndpoints, string>]: GetDataType<TEndpoints, TEndpoint, "post", "ok">;
124
+ };
125
+ }
126
+ export {};
package/typings.d.ts CHANGED
@@ -1,534 +1,13 @@
1
- /* eslint-disable @typescript-eslint/no-unused-vars */
2
-
3
- type _Response = Response;
4
-
5
- /**
6
- * @borrows [awesome-template-literal-types](https://github.com/ghoullier/awesome-template-literal-types#router-params-parsing)
7
- */
8
- type ExtractEndpointParams<T extends string> = string extends T
9
- ? Record<string, string>
10
- : // eslint-disable-next-line @typescript-eslint/no-unused-vars
11
- T extends `${infer _Start}{${infer Param}}${infer Rest}`
12
- ? { [k in Param | keyof ExtractEndpointParams<Rest>]: string | number }
13
- : // eslint-disable-next-line @typescript-eslint/no-unused-vars
14
- T extends `${infer _Start}{${infer Param}}`
15
- ? { [k in Param]: string | number }
16
- : never;
17
-
18
- namespace Koine.Api {
19
- // @see https://stackoverflow.com/a/60702896/1938970
20
- // import { Exact } from "type-fest";
21
-
22
- //////////////////////////////////////////////////////////////////////////////
23
- //
24
- // Client
25
- //
26
- //////////////////////////////////////////////////////////////////////////////
27
-
28
- type ClientCreator<TEndpoints extends Endpoints> = (
29
- apiName: string,
30
- baseUrl: string,
31
- options?: ClientOptions,
32
- ) => Client<TEndpoints>;
33
-
34
- type ClientOptions = {
35
- /**
36
- * Headers will be merged with
37
- * ```
38
- * { "content-type": "application/json" }
39
- * ```
40
- *
41
- * @default {}
42
- */
43
- headers?: RequestInit["headers"];
44
- /**
45
- * Basic request options to supply to `fetch`
46
- *
47
- * @see RequestInit
48
- *
49
- * @default {}
50
- */
51
- request?: Omit<RequestInit, "body" | "headers" | "method">;
52
- /**
53
- * Flag to throw error within the catch block, by default we return a
54
- * normalised error result {@link ResultFail}
55
- *
56
- * @default false
57
- */
58
- throwErr?: boolean;
59
- /**
60
- * Timeout in `ms`, if `falsy` there is no timeout
61
- *
62
- * @default 10000
63
- */
64
- timeout?: number | false | null;
65
- /**
66
- * Process request before actual http call
67
- *
68
- * @default undefined
69
- */
70
- processReq?: RequestProcessor;
71
- /**
72
- * Process ok/failed response just after http response
73
- *
74
- * @default undefined
75
- */
76
- processRes?: ResponseProcessorRes;
77
- /**
78
- * Process maybe-thrown error originated either from `fetch` function
79
- * invokation or from its `response.json()` parsing
80
- *
81
- * @default undefined
82
- */
83
- processErr?: ResponseProcessorErr;
84
- };
85
-
86
- type ClientMethod<
87
- TMethod extends RequestMethod,
88
- TEndpoints extends Endpoints,
89
- > = <
90
- TEndpoint extends EndpointUrl<TEndpoints>,
91
- TOptions extends EndpointOptions<TEndpoints, TEndpoint, TMethod>,
92
- TOk extends ResponseOk = EndpointResponseOk<TEndpoints, TEndpoint, TMethod>,
93
- TFail extends ResponseFail = EndpointResponseFail<
94
- TEndpoints,
95
- TEndpoint,
96
- TMethod
97
- >,
98
- >(
99
- endpoint: TEndpoint,
100
- options?: TOptions,
101
- ) => Promise<EndpointResult<TEndpoints, TEndpoint, TMethod>>;
102
- // ) => Promise<Result<TOk, TFail>>;
103
-
104
- /**
105
- * The `api` interface generated by `createApi`
106
- */
107
- type Client<TEndpoints extends Endpoints> = {
108
- [TMethod in RequestMethod]: ClientMethod<TMethod, TEndpoints>;
109
- };
110
-
111
- //////////////////////////////////////////////////////////////////////////////
112
- //
113
- // Endpoints
114
- //
115
- //////////////////////////////////////////////////////////////////////////////
116
-
117
- type EndpointOptions<
118
- TEndpoints extends Endpoints,
119
- TEndpoint extends EndpointUrl<TEndpoints>,
120
- TMethod extends RequestMethod,
121
- > = RequestOptions<
122
- TEndpoints,
123
- TEndpoint,
124
- TMethod,
125
- TEndpoints[TEndpoint][Uppercase<TMethod>]["json"],
126
- TEndpoints[TEndpoint][Uppercase<TMethod>]["query"]
127
- >;
128
-
129
- type EndpointResultOk<
130
- TEndpoints extends Endpoints,
131
- TEndpoint extends EndpointUrl<TEndpoints>,
132
- TMethod extends RequestMethod,
133
- > = ResultOk<TEndpoints[TEndpoint][Uppercase<TMethod>]["ok"]>;
134
-
135
- type EndpointResultFail<
136
- TEndpoints extends Endpoints,
137
- TEndpoint extends EndpointUrl<TEndpoints>,
138
- TMethod extends RequestMethod,
139
- > = ResultFail<TEndpoints[TEndpoint][Uppercase<TMethod>]["fail"]>;
140
-
141
- type EndpointResponseOk<
142
- TEndpoints extends Endpoints,
143
- TEndpoint extends EndpointUrl<TEndpoints>,
144
- TMethod extends RequestMethod,
145
- > = TEndpoints[TEndpoint][Uppercase<TMethod>]["ok"];
146
-
147
- type EndpointResponseFail<
148
- TEndpoints extends Endpoints,
149
- TEndpoint extends EndpointUrl<TEndpoints>,
150
- TMethod extends RequestMethod,
151
- > = TEndpoints[TEndpoint][Uppercase<TMethod>]["fail"];
152
-
153
- type EndpointResult<
154
- TEndpoints extends Endpoints,
155
- TEndpoint extends EndpointUrl<TEndpoints>,
156
- TMethod extends RequestMethod,
157
- > = Result<
158
- EndpointResponseOk<TEndpoints, TEndpoint, TMethod>,
159
- EndpointResponseFail<TEndpoints, TEndpoint, TMethod>
160
- >;
161
-
162
- //////////////////////////////////////////////////////////////////////////////
163
- //
164
- // Definitions
165
- //
166
- //////////////////////////////////////////////////////////////////////////////
167
-
168
- /**
169
- * Validate the `Endpoints` definition against the `Endpoint` shape defined
170
- * here.
171
- *
172
- * FIXME: this does not work yet...constraining the API endpoints definitions
173
- *
174
- * @see https://github.com/sindresorhus/type-fest/blob/main/source/exact.d.ts
175
- * @see https://fettblog.eu/typescript-match-the-exact-object-shape/
176
- * @see https://stackoverflow.com/a/51496652/1938970
177
- * @see https://github.com/Microsoft/TypeScript/issues/12936
178
- */
179
- // type DefineEndpoint<T> =
180
- // T extends Endpoint ?
181
- // Exclude<keyof T, keyof Endpoint> extends never ?
182
- // T : "Endpoint must follow `Koine.Api.Endpoint` shape" : never;
183
- type DefineEndpoint<T extends EndpointShape> = T;
184
- type DefineEndpoints<T extends Endpoints> = {};
185
- type EndpointShape = {
186
- [TMethod in Uppercase<RequestMethod>]?: DataTypes<TMethod>;
187
- };
188
-
189
- type Endpoints = Record<string, Endpoint>;
190
- type Endpoint = {
191
- [TMethod in Uppercase<RequestMethod>]?: DataTypes<TMethod>;
192
- };
193
-
194
- type EndpointUrl<TEndpoints extends Endpoints> = Extract<
195
- keyof TEndpoints,
196
- string
197
- >;
198
-
199
- type DataTypes<TMethod extends Uppercase<RequestMethod>> = {
200
- /**
201
- * The request body of a non-GET request
202
- */
203
- json?: RequestJson;
204
- /**
205
- * The parameters to encode in the URL of the request
206
- */
207
- query?: RequestQuery;
208
- /**
209
- * The JSON response data returned by the request in case of success
210
- */
211
- ok?: null | unknown;
212
- /**
213
- * The shape of the error data returned by the request in case of
214
- * failure
215
- */
216
- fail?: null | unknown;
217
- };
218
-
219
- //////////////////////////////////////////////////////////////////////////////
220
- //
221
- // Request
222
- //
223
- //////////////////////////////////////////////////////////////////////////////
224
-
225
- type RequestMethod = "get" | "post" | "put" | "patch" | "delete";
226
-
227
- type RequestJson = unknown;
228
-
229
- type RequestQuery = unknown;
230
-
231
- type RequestParams = unknown;
232
-
233
- /**
234
- * Request options
235
- *
236
- * `ClientOptions` can be overriden here at the single request level.
237
- */
238
- type RequestOptions<
239
- TEndpoints extends Endpoints,
240
- TEndpoint extends EndpointUrl<TEndpoints>,
241
- TMethod extends RequestMethod,
242
- TJson extends RequestJson,
243
- TQuery extends RequestQuery,
244
- > = Omit<ClientOptions, "processReq"> & {
245
- processReq?: EndpointRequestProcessor<TEndpoints, TEndpoint, TMethod>;
246
- /**
247
- * A dictionary to dynamically interpolate endpoint url params, e.g.:
248
- *
249
- * ```js
250
- * myapi.get("user/{id}", { path: { id: "12" }})
251
- * ```
252
- * results in a call to the endpoint `"user/12"`
253
- */
254
- params?: ExtractEndpointParams<TEndpoint>;
255
- /**
256
- * Query parameters will be serialized into a string and appended to the URL
257
- */
258
- query?: TQuery;
259
- /**
260
- * JSON request body
261
- */
262
- json?: TJson;
263
- };
264
-
265
- //////////////////////////////////////////////////////////////////////////////
266
- //
267
- // Response/Result
268
- //
269
- //////////////////////////////////////////////////////////////////////////////
270
-
271
- type ResponseOk = unknown;
272
-
273
- type ResponseFail = unknown;
274
-
275
- type ResultShared<
276
- T extends Record<string, unknown> = Record<string, unknown>,
277
- > = T & {
278
- status: _Response["status"];
279
- msg: _Response["statusText"];
280
- };
281
-
282
- type ResultOk<TResponse extends ResponseOk = ResponseOk> = {
283
- status: _Response["status"];
284
- msg: _Response["statusText"];
285
- ok: true;
286
- fail?: false;
287
- data: TResponse;
288
- };
289
-
290
- type ResultFail<TResponse extends ResponseFail = ResponseFail> = {
291
- status: _Response["status"];
292
- msg: Error["message"] | _Response["statusText"];
293
- ok?: false;
294
- fail: true;
295
- data: TResponse;
296
- };
297
-
298
- type Result<
299
- TResponseOk extends ResponseOk,
300
- TResponseFail extends ResponseFail,
301
- > =
302
- | {
303
- status: _Response["status"];
304
- msg: _Response["statusText"];
305
- ok: true;
306
- fail?: false;
307
- data: TResponseOk;
308
- }
309
- | {
310
- status: _Response["status"];
311
- msg: Error["message"] | _Response["statusText"];
312
- ok?: false;
313
- fail: true;
314
- data: TResponseFail;
315
- };
316
-
317
- /**
318
- * The request processor at the client level, this is meant to apply global
319
- * transformations to all endpoints requests
320
- */
321
- type RequestProcessor = (
322
- method: RequestMethod,
323
- url: string,
324
- query: any,
325
- json: any,
326
- params: any,
327
- requestInit: RequestInit,
328
- ) => [
329
- string, // url
330
- RequestQuery, // query
331
- RequestJson, // json
332
- RequestParams, // params
333
- RequestInit, // requestInit
334
- ];
335
-
336
- /**
337
- * The request processor at the request level, this is meant to apply
338
- * transformations to a single endpoint request. Request processor applied at
339
- * the whole client level is still applied just before this one, hence one
340
- * might set some global processing and override it or undo it at the single
341
- * request level.
342
- */
343
- type EndpointRequestProcessor<
344
- TEndpoints extends Endpoints,
345
- TEndpoint extends EndpointUrl<TEndpoints>,
346
- TMethod extends RequestMethod,
347
- > = (
348
- method: TMethod,
349
- url: string,
350
- query: EndpointOptions<TEndpoints, TEndpoint, TMethod>["query"],
351
- json: EndpointOptions<TEndpoints, TEndpoint, TMethod>["json"],
352
- params: EndpointOptions<TEndpoints, TEndpoint, TMethod>["params"],
353
- requestInit: RequestInit,
354
- ) => [
355
- string, // url
356
- EndpointOptions<TEndpoints, TEndpoint, TMethod>["query"], // query
357
- EndpointOptions<TEndpoints, TEndpoint, TMethod>["json"], // json
358
- EndpointOptions<TEndpoints, TEndpoint, TMethod>["params"], // params
359
- RequestInit, // requestInit
360
- ];
361
-
362
- /**
363
- * The ok/fail response processor at the request level, this is meant to apply
364
- * transformations to a single or all endpoint responses
365
- */
366
- type ResponseProcessorRes = <TResponseOk extends ResponseOk = ResponseOk>(
367
- response: _Response,
368
- options: TOptions,
369
- ) => Promise<Koine.Api.Result<TResponseOk>>;
370
-
371
- /**
372
- * The error response processor at the request level, this is meant to apply
373
- * transformations to a single or all endpoint responses
374
- */
375
- type ResponseProcessorErr = <
376
- TResponseFail extends ResponseFailed = ResponseFailed,
377
- >(
378
- msg: string,
379
- options: TOptions,
380
- ) => Promise<Koine.Api.Result<TResponseFail>>;
381
-
382
- //////////////////////////////////////////////////////////////////////////////
383
- //
384
- // Hooks
385
- //
386
- //////////////////////////////////////////////////////////////////////////////
387
-
388
- /**
389
- * Api hooks map for `react`, each request method has its own `use{Method}`
390
- * hook.
391
- *
392
- * These hooks are implemented with different libraries or, in the future as
393
- * standalone hooks, see SWR ones to start with.
394
- */
395
- type HooksMaps = {
396
- [TMethod in RequestMethod]: `use${TMethod extends "get" ? "" : Capitalize<TMethod>}`;
397
- };
398
-
399
- type HooksMapsByName = { [K in keyof HooksMaps as HooksMaps[K]]: K };
400
-
401
- //////////////////////////////////////////////////////////////////////////////
402
- //
403
- // Generate shortcuts
404
- //
405
- //////////////////////////////////////////////////////////////////////////////
406
-
407
- /**
408
- * To generate all available helpers use in your `API` types:
409
- *
410
- * ```ts
411
- * type Response = Koine.Api.GenerateResponseHelpers<Endpoints>;
412
- * type Request = Koine.Api.GenerateRequestHelpers<Endpoints>;
413
- * type Get = Koine.Api.GenerateGetHelpers<Endpoints>;
414
- * type Post = Koine.Api.GeneratePostHelpers<Endpoints>;
415
- * ```
416
- */
417
- type Generate = "here just to read the example usage";
418
-
419
- type _ShortcutsMaps = {
420
- [TMethod in RequestMethod]: Capitalize<TMethod>;
421
- };
422
-
423
- type _ShortcutsMapsByMethod = {
424
- [K in keyof _ShortcutsMaps as _ShortcutsMaps[K]]: K;
425
- };
426
-
427
- /**
428
- * @example
429
- * ```ts
430
- * // define the type on your `API` types:
431
- * type Result = Koine.Api.GenerateResultShortcuts<Endpoints>;
432
- *
433
- * // consume the type wherever in your app:
434
- * type MyResult = API.Result["get"]["my/endpoint"];
435
- *
436
- * MyResult["ok"];
437
- * ^
438
- * MyResult["fail"];
439
- * ^
440
- * ```
441
- */
442
- type GenerateResultShortcuts<TEndpoints extends Endpoints> = {
443
- [TMethod in RequestMethod]: {
444
- [TEndpointUrl in keyof TEndpoints]: {
445
- ok: TEndpoints[TEndpointUrl][Uppercase<TMethod>]["ok"];
446
- fail: TEndpoints[TEndpointUrl][Uppercase<TMethod>]["fail"];
447
- };
448
- };
449
- };
450
-
451
- /**
452
- * @example
453
- * ```ts
454
- * // define the type on your `API` types:
455
- * type Response = Koine.Api.GenerateResponseShortcuts<Endpoints>;
456
- *
457
- * // consume the type wherever in your app:
458
- * type MyData = API.Response["get"]["my/endpoint"];
459
- * ```
460
- */
461
- type GenerateResponseShortcuts<TEndpoints extends Endpoints> = {
462
- [TMethod in RequestMethod]: {
463
- [TEndpointUrl in keyof TEndpoints]: TEndpoints[TEndpointUrl][Uppercase<TMethod>]["ok"];
464
- };
465
- };
466
-
467
- /**
468
- * @example
469
- * ```ts
470
- * // define the type on your `API` types:
471
- * type Request = Koine.Api.GenerateRequestShortcuts<Endpoints>;
472
- *
473
- * // consume the type wherever in your app:
474
- * type MyData = API.Request["get"]["my/endpoint"];
475
- * ```
476
- */
477
- type GenerateRequestShortcuts<TEndpoints extends Endpoints> = {
478
- [TMethod in RequestMethod]: {
479
- [TEndpointUrl in keyof TEndpoints]: TMethod extends "get"
480
- ? TEndpoints[TEndpointUrl][Uppercase<TMethod>]["query"]
481
- : TEndpoints[TEndpointUrl][Uppercase<TMethod>]["json"];
482
- };
483
- };
484
-
485
- /**
486
- * @example
487
- * ```ts
488
- * // define the type on your `API` types:
489
- * type Get = Koine.Api.GenerateResponseShortcuts<Endpoints>;
490
- *
491
- * // consume the type wherever in your app:
492
- * type MyData = API.Get["my/endpoint"];
493
- * ```
494
- */
495
- type GenerateGetShortcuts<TEndpoints extends Endpoints> = {
496
- [TEndpointUrl in keyof TEndpoints]: TEndpoints[TEndpointUrl]["GET"]["ok"];
497
- };
498
-
499
- /**
500
- * @example
501
- * ```ts
502
- * // define the type on your `API` types:
503
- * type Post = Koine.Api.GenerateResponseShortcuts<Endpoints>;
504
- *
505
- * // consume the type wherever in your app:
506
- * type MyData = API.Post["my/endpoint"];
507
- * ```
508
- */
509
- type GeneratePostShortcuts<TEndpoints extends Endpoints> = {
510
- [TEndpointUrl in keyof TEndpoints]: TEndpoints[TEndpointUrl]["POST"]["ok"];
511
- };
512
-
513
- /**
514
- * This is not useful as it is the same as doing
515
- * `API.Endpoints["my/endpoint"]["GET"]["ok"];`
516
- *
517
- * @example
518
- * ```ts
519
- * // define the type on your `API` types:
520
- * type Response = Koine.Api.GenerateResponseShortcuts<Endpoints>;
521
- *
522
- * // consume the type wherever in your app:
523
- * type MyData = API.$["my/endpoint"]["get"]["ok"];
524
- * ```
525
- * @deprecated
526
- */
527
- // type GenerateAllShortcuts<TEndpoints extends Endpoints> = {
528
- // [TEndpointUrl in keyof TEndpoints]: {
529
- // [TMethod in RequestMethod]: {
530
- // [DataType in EndpointDataType]: TEndpoints[TEndpointUrl][Uppercase<TMethod>][DataType];
531
- // }
532
- // }
533
- // }
1
+ declare namespace Koine.Api {
2
+ type Endpoints = import("./types").Api.Endpoints;
3
+ type GenerateGetShortcuts<E extends Endpoints> =
4
+ import("./types").Api.Generate.GetShortcuts<E>;
5
+ type GeneratePostShortcuts<E extends Endpoints> =
6
+ import("./types").Api.Generate.PostShortcuts<E>;
7
+ type GenerateRequestShortcuts<E extends Endpoints> =
8
+ import("./types").Api.Generate.RequestShortcuts<E>;
9
+ type GenerateResponseShortcuts<E extends Endpoints> =
10
+ import("./types").Api.Generate.ResponseShortcuts<E>;
11
+ type GenerateResultShortcuts<E extends Endpoints> =
12
+ import("./types").Api.Generate.ResultShortcuts<E>;
534
13
  }