Eric Bower
·
2025-06-06
api-type-template.mts
1import { writeFileSync } from "node:fs";
2
3console.log("writing api template file");
4createTemplateFile(createQueryApi());
5console.log("DONE!");
6
7function createQueryApi() {
8 const methods = [
9 "get",
10 "post",
11 "put",
12 "patch",
13 "delete",
14 "options",
15 "head",
16 "connect",
17 "trace",
18 ];
19
20 const uriTmpl = (method: string) =>
21 `/**
22 * Options only
23 */
24${method}(req: { supervisor?: Supervisor }): CreateAction<Ctx>;
25${method}<P>(
26 req: { supervisor?: Supervisor }
27): CreateActionWithPayload<Omit<Ctx, 'payload'> & Payload<P>, P>;
28${method}<P extends never, ApiSuccess, ApiError = unknown>(
29 req: { supervisor?: Supervisor }
30): CreateAction<Omit<Ctx, 'json'> & FetchJson<ApiSuccess, ApiError extends unknown ? Ctx["_error"] : ApiError>, ApiSuccess>;
31${method}<P, ApiSuccess, ApiError = unknown>(req: {
32 supervisor?: Supervisor;
33}): CreateActionWithPayload<
34 Omit<Ctx, 'payload' | 'json'> &
35 Payload<P> &
36 FetchJson<ApiSuccess, ApiError extends unknown ? Ctx["_error"] : ApiError>,
37 P,
38 ApiSuccess
39>;
40
41/**
42* Middleware only
43*/
44${method}(fn: MiddlewareApiCo<Ctx>): CreateAction<Ctx>;
45${method}<Gtx extends Ctx = Ctx>(
46 fn: MiddlewareApiCo<Gtx>,
47): CreateAction<Gtx>;
48${method}<P>(
49 fn: MiddlewareApiCo<Omit<Ctx, 'payload'> & Payload<P>>,
50): CreateActionWithPayload<Omit<Ctx, 'payload'> & Payload<P>, P>;
51${method}<P, Gtx extends Ctx = Ctx>(
52 fn: MiddlewareApiCo<Gtx>,
53): CreateActionWithPayload<Gtx, P>;
54${method}<P extends never, ApiSuccess, ApiError = unknown>(
55 fn: MiddlewareApiCo<Omit<Ctx, 'json'> & FetchJson<ApiSuccess, ApiError extends unknown ? Ctx["_error"] : ApiError>>,
56): CreateAction<Omit<Ctx, 'json'> & FetchJson<ApiSuccess, ApiError extends unknown ? Ctx["_error"] : ApiError>, ApiSuccess>;
57${method}<P, ApiSuccess, ApiError = unknown>(
58 fn: MiddlewareApiCo<Ctx>,
59): CreateActionWithPayload<
60 Omit<Ctx, 'payload' | 'json'> &
61 Payload<P> &
62 FetchJson<ApiSuccess, ApiError extends unknown ? Ctx["_error"] : ApiError>,
63 P,
64 ApiSuccess
65>;
66
67/**
68* Options and Middleware
69*/
70${method}(req: { supervisor?: Supervisor }, fn: MiddlewareApiCo<Ctx>): CreateAction<Ctx>;
71${method}<Gtx extends Ctx = Ctx>(
72 req: { supervisor?: Supervisor },
73 fn: MiddlewareApiCo<Gtx>,
74): CreateAction<Gtx>;
75${method}<P>(
76 req: { supervisor?: Supervisor },
77 fn: MiddlewareApiCo<Omit<Ctx, 'payload'> & Payload<P>>,
78): CreateActionWithPayload<Omit<Ctx, 'payload'> & Payload<P>, P>;
79${method}<P, Gtx extends Ctx = Ctx>(
80 req: { supervisor?: Supervisor },
81 fn: MiddlewareApiCo<Gtx>,
82): CreateActionWithPayload<Gtx, P>;
83${method}<P extends never, ApiSuccess, ApiError = unknown>(
84 req: { supervisor?: Supervisor },
85 fn: MiddlewareApiCo<Omit<Ctx, 'json'> & FetchJson<ApiSuccess, ApiError extends unknown ? Ctx["_error"] : ApiError>>,
86): CreateAction<Omit<Ctx, 'json'> & FetchJson<ApiSuccess, ApiError extends unknown ? Ctx["_error"] : ApiError>, ApiSuccess>;
87${method}<P, ApiSuccess, ApiError = unknown>(
88 req: { supervisor?: Supervisor },
89 fn: MiddlewareApiCo<Ctx>,
90): CreateActionWithPayload<
91 Omit<Ctx, 'payload' | 'json'> &
92 Payload<P> &
93 FetchJson<ApiSuccess, ApiError extends unknown ? Ctx["_error"] : ApiError>,
94 P,
95 ApiSuccess
96>;`;
97 const uriMethods = methods.map((m) => uriTmpl(m)).join("\n\n");
98
99 const methodTmpl = (method: string) =>
100 `/**
101 * Only name
102 */
103${method}(name: ApiName): CreateAction<Ctx>;
104${method}<P>(
105 name: ApiName,
106): CreateActionWithPayload<Omit<Ctx, 'payload'> & Payload<P>, P>;
107${method}<P extends never, ApiSuccess, ApiError = unknown>(
108 name: ApiName,
109): CreateAction<Omit<Ctx, 'json'> & FetchJson<ApiSuccess, ApiError extends unknown ? Ctx["_error"] : ApiError>, ApiSuccess>;
110${method}<P, ApiSuccess, ApiError = unknown>(
111 name: ApiName,
112): CreateActionWithPayload<
113 Omit<Ctx, 'payload' | 'json'> &
114 Payload<P> &
115 FetchJson<ApiSuccess, ApiError extends unknown ? Ctx["_error"] : ApiError>,
116 P,
117 ApiSuccess
118>;
119
120/**
121 * Name and options
122 */
123${method}(name: ApiName, req: { supervisor?: Supervisor }): CreateAction<Ctx>;
124${method}<P>(
125 name: ApiName,
126 req: { supervisor?: Supervisor }
127): CreateActionWithPayload<Omit<Ctx, 'payload'> & Payload<P>, P>;
128${method}<P, Gtx extends Ctx = Ctx>(
129 name: ApiName,
130 req: { supervisor?: Supervisor }
131): CreateActionWithPayload<Gtx, P>;
132${method}<P extends never, ApiSuccess, ApiError = unknown>(
133 name: ApiName,
134 req: { supervisor?: Supervisor }
135): CreateAction<Omit<Ctx, 'json'> & FetchJson<ApiSuccess, ApiError extends unknown ? Ctx["_error"] : ApiError>, ApiSuccess>;
136${method}<P, ApiSuccess, ApiError = unknown>(
137 name: ApiName,
138 req: { supervisor?: Supervisor },
139): CreateActionWithPayload<
140 Omit<Ctx, 'payload' | 'json'> &
141 Payload<P> &
142 FetchJson<ApiSuccess, ApiError extends unknown ? Ctx["_error"] : ApiError>,
143 P,
144 ApiSuccess
145>;
146
147/**
148 * Name and middleware
149 */
150${method}(name: ApiName, fn: MiddlewareApiCo<Ctx>): CreateAction<Ctx>;
151${method}<Gtx extends Ctx = Ctx>(
152 name: ApiName,
153 fn: MiddlewareApiCo<Gtx>,
154): CreateAction<Gtx>;
155${method}<P>(
156 name: ApiName,
157 fn: MiddlewareApiCo<Omit<Ctx, 'payload'> & Payload<P>>,
158): CreateActionWithPayload<Omit<Ctx, 'payload'> & Payload<P>, P>;
159${method}<P, Gtx extends Ctx = Ctx>(
160 name: ApiName,
161 fn: MiddlewareApiCo<Gtx>,
162): CreateActionWithPayload<Gtx, P>;
163${method}<P extends never, ApiSuccess, ApiError = unknown>(
164 name: ApiName,
165 fn: MiddlewareApiCo<Omit<Ctx, 'json'> & FetchJson<ApiSuccess, ApiError extends unknown ? Ctx["_error"] : ApiError>>,
166): CreateAction<Omit<Ctx, 'json'> & FetchJson<ApiSuccess, ApiError extends unknown ? Ctx["_error"] : ApiError>, ApiSuccess>;
167${method}<P, ApiSuccess, ApiError = unknown>(
168 name: ApiName,
169 fn: MiddlewareApiCo<
170 Omit<Ctx, 'payload' | 'json'> &
171 Payload<P> &
172 FetchJson<ApiSuccess, ApiError extends unknown ? Ctx["_error"] : ApiError>
173 >,
174): CreateActionWithPayload<
175 Omit<Ctx, 'payload' | 'json'> &
176 Payload<P> &
177 FetchJson<ApiSuccess, ApiError extends unknown ? Ctx["_error"] : ApiError>,
178 P,
179 ApiSuccess
180>;
181
182/**
183 * Name, options, and middleware
184 */
185${method}(
186 name: ApiName,
187 req: { supervisor?: Supervisor },
188 fn: MiddlewareApiCo<Ctx>,
189): CreateAction<Ctx>;
190${method}<Gtx extends Ctx = Ctx>(
191 name: ApiName,
192 req: { supervisor?: Supervisor },
193 fn: MiddlewareApiCo<Gtx>,
194): CreateAction<Gtx>;
195${method}<P>(
196 name: ApiName,
197 req: { supervisor?: Supervisor },
198 fn: MiddlewareApiCo<Omit<Ctx, 'payload'> & Payload<P>>,
199): CreateActionWithPayload<Omit<Ctx, 'payload'> & Payload<P>, P>;
200${method}<P, Gtx extends Ctx = Ctx>(
201 name: ApiName,
202 req: { supervisor?: Supervisor },
203 fn: MiddlewareApiCo<Gtx>,
204): CreateActionWithPayload<Gtx, P>;
205${method}<P extends never, ApiSuccess, ApiError = unknown>(
206 name: ApiName,
207 req: { supervisor?: Supervisor },
208 fn: MiddlewareApiCo<Omit<Ctx, 'json'> & FetchJson<ApiSuccess, ApiError extends unknown ? Ctx["_error"] : ApiError>>,
209): CreateAction<Omit<Ctx, 'json'> & FetchJson<ApiSuccess, ApiError extends unknown ? Ctx["_error"] : ApiError>, ApiSuccess>;
210${method}<P, ApiSuccess, ApiError = unknown>(
211 name: ApiName,
212 req: { supervisor?: Supervisor },
213 fn: MiddlewareApiCo<
214 Omit<Ctx, 'payload' | 'json'> &
215 Payload<P> &
216 FetchJson<ApiSuccess, ApiError extends unknown ? Ctx["_error"] : ApiError>
217 >,
218): CreateActionWithPayload<
219 Omit<Ctx, 'payload' | 'json'> &
220 Payload<P> &
221 FetchJson<ApiSuccess, ApiError extends unknown ? Ctx["_error"] : ApiError>,
222 P,
223 ApiSuccess
224>;`;
225 const regMethods = methods.map((m) => methodTmpl(m)).join("\n\n");
226
227 const tmpl = `/**
228* This is an auto-generated file, do not edit directly!
229* Run "yarn template" to generate this file.
230*/
231import type { ThunksApi } from "./thunk.js";
232import type {
233 ApiCtx,
234 CreateAction,
235 CreateActionWithPayload,
236 FetchJson,
237 MiddlewareApiCo,
238 Supervisor,
239} from "./types.js";
240import type { Next, Payload } from "../types.js";
241import type { Operation } from "effection";
242
243export type ApiName = string | string[];
244
245export interface QueryApi<Ctx extends ApiCtx = ApiCtx> extends ThunksApi<Ctx> {
246 request: (
247 r: Partial<RequestInit>,
248 ) => (ctx: Ctx, next: Next) => Operation<unknown>;
249 cache: () => (ctx: Ctx, next: Next) => Operation<unknown>;
250
251 uri: (uri: string) => {
252 ${uriMethods}
253 }
254
255${regMethods}
256}`;
257
258 return tmpl;
259}
260
261function createTemplateFile(tmpl: string) {
262 writeFileSync("./src/query/api-types.ts", tmpl);
263}