import fs from 'fs'; import util from 'util'; import prettier from 'prettier'; const write = util.promisify(fs.writeFile); function createSagaQueryApi() { const methods = [ 'get', 'post', 'put', 'patch', 'delete', 'options', 'head', 'connect', 'trace', ]; const uriTmpl = (method: string) => `/** * Options only */ ${method}(req: { saga?: any }): CreateAction; ${method}

( req: { saga?: any } ): CreateActionWithPayload & Payload

, P>; ${method}

( req: { saga?: any } ): CreateAction & FetchJson>; ${method}(req: { saga?: any; }): CreateActionWithPayload< Omit & Payload

& FetchJson, P >; /** * Middleware only */ ${method}(fn: MiddlewareApiCo): CreateAction; ${method}( fn: MiddlewareApiCo, ): CreateAction; ${method}

( fn: MiddlewareApiCo & Payload

>, ): CreateActionWithPayload & Payload

, P>; ${method}( fn: MiddlewareApiCo, ): CreateActionWithPayload; ${method}

( fn: MiddlewareApiCo & FetchJson>, ): CreateAction & FetchJson>; ${method}( fn: MiddlewareApiCo, ): CreateActionWithPayload< Omit & Payload

& FetchJson, P >; /** * Options and Middleware */ ${method}(req: { saga?: any }, fn: MiddlewareApiCo): CreateAction; ${method}( req: { saga?: any }, fn: MiddlewareApiCo, ): CreateAction; ${method}

( req: { saga?: any }, fn: MiddlewareApiCo & Payload

>, ): CreateActionWithPayload & Payload

, P>; ${method}( req: { saga?: any }, fn: MiddlewareApiCo, ): CreateActionWithPayload; ${method}

( req: { saga?: any }, fn: MiddlewareApiCo & FetchJson>, ): CreateAction & FetchJson>; ${method}( req: { saga?: any }, fn: MiddlewareApiCo, ): CreateActionWithPayload< Omit & Payload

& FetchJson, P >;`; const uriMethods = methods.map((m) => uriTmpl(m)).join('\n\n'); const methodTmpl = (method: string) => `/** * Only name */ ${method}(name: ApiName): CreateAction; ${method}

( name: ApiName, ): CreateActionWithPayload & Payload

, P>; ${method}

( name: ApiName, ): CreateAction & FetchJson>; ${method}( name: ApiName, ): CreateActionWithPayload< Omit & Payload

& FetchJson, P >; /** * Name and options */ ${method}(name: ApiName, req: { saga?: any }): CreateAction; ${method}

( name: ApiName, req: { saga?: any } ): CreateActionWithPayload & Payload

, P>; ${method}( name: ApiName, req: { saga?: any } ): CreateActionWithPayload; ${method}

( name: ApiName, req: { saga?: any } ): CreateAction & FetchJson>; ${method}( name: ApiName, req: { saga?: any }, ): CreateActionWithPayload< Omit & Payload

& FetchJson, P >; /** * Name and middleware */ ${method}(name: ApiName, fn: MiddlewareApiCo): CreateAction; ${method}( name: ApiName, fn: MiddlewareApiCo, ): CreateAction; ${method}

( name: ApiName, fn: MiddlewareApiCo & Payload

>, ): CreateActionWithPayload & Payload

, P>; ${method}( name: ApiName, fn: MiddlewareApiCo, ): CreateActionWithPayload; ${method}

( name: ApiName, fn: MiddlewareApiCo & FetchJson>, ): CreateAction & FetchJson>; ${method}( name: ApiName, fn: MiddlewareApiCo< Omit & Payload

& FetchJson >, ): CreateActionWithPayload< Omit & Payload

& FetchJson, P >; /** * Name, options, and middleware */ ${method}( name: ApiName, req: { saga?: any }, fn: MiddlewareApiCo, ): CreateAction; ${method}( name: ApiName, req: { saga?: any }, fn: MiddlewareApiCo, ): CreateAction; ${method}

( name: ApiName, req: { saga?: any }, fn: MiddlewareApiCo & Payload

>, ): CreateActionWithPayload & Payload

, P>; ${method}( name: ApiName, req: { saga?: any }, fn: MiddlewareApiCo, ): CreateActionWithPayload; ${method}

( name: ApiName, req: { saga?: any }, fn: MiddlewareApiCo & FetchJson>, ): CreateAction & FetchJson>; ${method}( name: ApiName, req: { saga?: any }, fn: MiddlewareApiCo< Omit & Payload

& FetchJson >, ): CreateActionWithPayload< Omit & Payload

& FetchJson, P >;`; const regMethods = methods.map((m) => methodTmpl(m)).join('\n\n'); const tmpl = `/** * This is an auto-generated file, do not edit directly! * Run "yarn template" to generate this file. */ import type { SagaIterator } from "redux-saga"; import type { SagaApi } from "./pipe"; import type { ApiCtx, CreateAction, CreateActionWithPayload, Next, FetchJson, MiddlewareApiCo, Payload, } from "./types"; export type ApiName = string | string[]; export interface SagaQueryApi extends SagaApi { request: ( r: Partial, ) => (ctx: Ctx, next: Next) => SagaIterator; cache: () => (ctx: Ctx, next: Next) => SagaIterator; uri: (uri: string) => { ${uriMethods} } ${regMethods} }`; return tmpl; } async function createTemplateFile(tmpl: string) { await write( './src/api-types.ts', prettier.format(tmpl, { parser: 'typescript', singleQuote: true, trailingComma: 'all', arrowParens: 'always', }), ); } createTemplateFile(createSagaQueryApi()).then(console.log).catch(console.error);