UNPKG

@openapi-integration/swr-request-generator

Version:

A tool for generating TypeScript code and interface from swagger by using SWR and axios as client.

147 lines (133 loc) 17.9 kB
"use strict";var Re=Object.create;var U=Object.defineProperty;var Oe=Object.getOwnPropertyDescriptor;var Se=Object.getOwnPropertyNames;var be=Object.getPrototypeOf,Te=Object.prototype.hasOwnProperty;var xe=(r,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Se(e))!Te.call(r,o)&&o!==t&&U(r,o,{get:()=>e[o],enumerable:!(s=Oe(e,o))||s.enumerable});return r};var P=(r,e,t)=>(t=r!=null?Re(be(r)):{},xe(e||!r||!r.__esModule?U(t,"default",{value:r,enumerable:!0}):t,r));var d=P(require("fs"),1),le=P(require("js-yaml"),1);var me=require("moderndash");var a=(r,e,t)=>{if(!r||!e)return t;let o=(Array.isArray(e)?e:e?.match(/([^[.\]])+/g))?.reduce((n,i)=>n&&n[i],r);return o===void 0?t:o},B=(r,e)=>!r||!e?!1:!!e?.match(/([^[.\]])+/g)?.reduce((s,o)=>s&&s[o],r),H=r=>(e,t)=>e[r]>t[r]?1:t[r]>e[r]?-1:0,J=(r,e)=>e.reduce((t,s)=>(r.hasOwnProperty(s)&&(t[s]=r[s]),t),{}),w=(r,e)=>{for(let t in r)if(e(r[t]))return r[t]},V=(r,e="\\s")=>r.replace(new RegExp(`^(.*?)([${e}]*)$`),"$1");var K=r=>Array.isArray(r),l=r=>Object.prototype.toString.call(r)==="[object Object]",Q=r=>typeof r=="number",z=r=>!B(r,"$ref"),I=r=>!B(r,"$ref"),q=r=>/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(r);var y=require("moderndash"),ee=P(require("prettier"),1);var j={INVALID_JSON_FILE_ERROR:`Your json file is invalid, please check it! `,INVALID_FILE_FORMAT:`Your input file is invalid, please check if it json or yaml! `,FETCH_CLIENT_FAILED_ERROR:`Fetch client failed! Please check your network or ts-codegen.config.ts file. `},b={GENERATING:"generating...",SUCCESSFUL:"successful!!!",READING:`reading swagger schema from local file... `,GETTING_FROM_REMOTE:r=>`getting swagger schema from client ${r+1}... `},X=["get","post","put","delete","patch","options","head"],k="/",Y=` /* * this file is generated by @openapi-integration/swr-request-generator. * please do not modify it manually. */ `,f="#EnumTypeSuffix";var W=r=>console.log(`\x1B[32m${r}\x1B[39m`),Z=r=>console.log(`\x1B[33m${r}\x1B[39m`),$=r=>console.log(`\x1B[41m${r}\x1B[49m`);var u=r=>{if(!r)return"";let e=(0,y.camelCase)(r);return`${e.charAt(0).toUpperCase()}${e.slice(1)}`},te=(r=[])=>{let e={};return r.forEach(t=>{e[t]=t}),e},N=r=>ee.default.format(r,{printWidth:120,trailingComma:"all",arrowParens:"always",parser:"typescript"}),E=r=>{if((0,y.isEmpty)(r))return;let e=Object.entries(r).map(([t,s])=>l(s)&&Object.keys(s).length===1&&!(0,y.isEmpty)(w(s,o=>o==="FormData"))?`${M(t)}: FormData`:l(s)?`${M(t)}: ${JSON.stringify(s).replace(/"/g,"")};`:`${M(t)}: ${s.replace(f,"")};`);return r&&`{ ${e.sort().join(` `)} }`},re=r=>{let e=Object.entries(r.body??{}).map(([,n])=>l(n)&&Object.keys(n).length===1&&!(0,y.isEmpty)(w(n,i=>i==="FormData"))?"FormData;":l(n)?`${JSON.stringify(n).replace(/"/g,"")};`:`${n.replace(f,"")};`),t=(0,y.isEmpty)(e)?"":`body: ${e.sort().join(` `)}`;if(r.query&&Object.keys(r.query).length>0){let n=`query: ${E(r.query)}`;return`{ ${t} ${n} }`}let s=Object.entries(r.query||{}).map(([,n])=>l(n)?`${JSON.stringify(n).replace(/"/g,"")};`:`${n.replace(f,"")};`),o=(0,y.isEmpty)(s)?"":`query: ${s.sort().join(` `)}`;return`{ ${t} ${o} }`},M=r=>{let e=r.includes("?"),t=V(r,"?");return`'${q(t)?t:(0,y.camelCase)(u(t))}'${e?"?":""}`},se=(r,e=j.INVALID_JSON_FILE_ERROR,t=$)=>{if(typeof r=="string")try{return JSON.parse(r)}catch{t(e);return}},D=r=>{if(l(r))return JSON.stringify(r).replace(/"/g,"");if(r!=="")return r};var c=class{constructor(e){this.inputs=e}schemaType={};static of(e){return new c(e)}getSchemaType=()=>this.schemaType;resolve=e=>{let{schema:t={},results:s,parentKey:o,key:n}=this.inputs;if(t.$ref)return this.schemaType=this.resolveRef(t.$ref,e||t.type),this.schemaType=this.resolveNullable().getSchemaType(),this;if(t.oneOf||t.anyOf)return this.schemaType=this.resolveOneOfAndAnyOf(t.oneOf||t.anyOf),this.schemaType=this.resolveNullable().getSchemaType(),this;if(t.allOf)return this.schemaType=this.resolveAllOf(t.allOf),this.schemaType=this.resolveNullable().getSchemaType(),this;if(t.items)return this.schemaType=this.resolveItems(t.items,t.type,n,o),this.schemaType=this.resolveNullable().getSchemaType(),this;if(t.enum){let i=this.getEnumName(n,o);return s[i]=t.enum,this.schemaType=i,this.schemaType=this.resolveNullable().getSchemaType(),this}return t.type==="object"?t.properties?(this.schemaType=this.resolveProperties(t.properties,t.required,o),this.schemaType=this.resolveNullable().getSchemaType(),this):t.title?(this.schemaType=t.type,this.schemaType=this.resolveNullable().getSchemaType(),this):(this.schemaType="{[key:string]:any}",this.schemaType=this.resolveNullable().getSchemaType(),this):t.type==="string"&&t.format==="binary"?(this.schemaType="FormData",this.schemaType=this.resolveNullable().getSchemaType(),this):(this.schemaType=this.getBasicType(t.type,this.resolveRef(t.$ref,e||t.type)),this.schemaType=this.resolveNullable().getSchemaType(),this)};resolveNullable=()=>(this.inputs.schema?.nullable&&(this.schemaType=l(this.schemaType)?`${JSON.stringify(this.schemaType)} | null`:`${this.schemaType} | null`),this);getEnumName=(e,t="")=>`${u(t)}${u(e)}${f}`;resolveRef=(e,t)=>{if(!e)return"";let s=u(this.pickTypeByRef(e));return t==="array"?`${s}[]`:s};resolveOneOfAndAnyOf=e=>e.map(t=>{let s=c.of({results:{},schema:t}).resolve(t.type).getSchemaType();return JSON.stringify(s)}).join(" | ").replace(f,"").replace(/"/g,"");resolveAllOf=e=>e.map(t=>{let s=c.of({results:{},schema:t}).resolve(t.type).getSchemaType();return JSON.stringify(s)}).join(" & ").replace(f,"").replace(/"/g,"");getBasicType=(e,t)=>{switch(e){case"integer":return"number";case"array":return this.getTypeForArray(t);case void 0:return t||"";default:return e}};getTypeForArray=e=>e?`${e}[]`:"Array<any>";pickTypeByRef=e=>{if(!e)return;let t=e.split("/");return t[t.length-1]};resolveItems=(e,t,s,o)=>{if(!e)return{};let n=a(e,"items");if(t==="array"){if(n)return`${this.resolveItems(n,e.type,s,o)}[]`;if(!a(e,"$ref"))return`${a(e,"type")}[]`}return K(e)?e.map(i=>c.of({results:this.inputs.results,schema:i,key:s,parentKey:o}).resolve().getSchemaType()):c.of({results:this.inputs.results,schema:e,key:s,parentKey:o}).resolve(t).getSchemaType()};resolveProperties=(e={},t=[],s)=>Object.entries(e).reduce((o,[n,i])=>({...o,[`${n}${t.indexOf(n)>-1?"":"?"}`]:c.of({results:this.inputs.results,schema:i,key:n,parentKey:s}).resolve().getSchemaType()}),{})};var h=require("moderndash");var F=(r,e)=>{if((0,h.isEmpty)(r))return"";let t=r[e],s=t.some(n=>Q(n)),o=e.replace(f,"");return s?`export type ${o} = ${t.map(n=>JSON.stringify(n)).join("|")}`:`export enum ${o} ${JSON.stringify(te(t)).replace(/:/gi,"=")}`},L=r=>`use${u((0,h.camelCase)(r||""))}Request`,oe=r=>`useGetRequest<${D(r)}, ResponseError>`,ne=(r,e)=>`useMutationRequest<${e}, AxiosResponse<${D(r)}>, ResponseError>`,ie=(r,e,t="")=>(0,h.isEmpty)(r)&&(0,h.isEmpty)(e)?[void 0,void 0]:[`${u(t)}Request`,{query:e,body:r}],ae=r=>{let e={...r.TReqQuery,...r.TReqPath,...r.THeader},t=(0,h.isEmpty)(e)?void 0:E(e),s=[...r.pathParams??[],...r.queryParams??[],...Object.keys(r.THeader??{})].filter(Boolean).map(n=>q(n)?n:(0,h.camelCase)(n)),o=s.length===0?"":`{${s.join(",")}}:${t}`;return`${o?o+", ":""}SWRConfig?: SWRConfig<${D(r.TResp)}, ResponseError>, axiosConfig?: AxiosRequestConfig`},ce=(r,e)=>{let t={...r.TReqPath,...r.THeader},s=(0,h.isEmpty)(t)?void 0:E(t),o=[...r.pathParams??[],...Object.keys(r.THeader??{})].filter(Boolean).map(i=>q(i)?i:(0,h.camelCase)(i)),n=o.length===0?"":`{${o.join(",")}}:${s}`;return`${n?n+", ":""}mutationConfig?: SWRMutationConfig<${e}, AxiosResponse<${D(r.TResp)}>, ResponseError>, axiosConfig?: AxiosRequestConfig`},pe=(r,e,t,s)=>{let o=Object.entries(s??{}).reduce((i,[m])=>{let g=q(m)?m:(0,h.camelCase)(m);return i+`"${m}": `+g+", "},""),n=r?`"Content-Type": "${a(e,t??"","application/json")}"`:"";return`headers: { ${o}${n}},`},_=r=>r.includes('"Accept":')?'responseType: "blob",':"";var C=class{constructor(e){this.components=e}resolvedDefinitions={};static of(e){return new C(e)}scanDefinitions=()=>{let e={},t=a(this.components,"requestBodies",{}),s=a(this.components,"schemas",{});return Object.entries(t).forEach(([o,n])=>I(n)?e[o]=c.of({results:e,schema:a(n,"content.application/json.schema"),key:o,parentKey:o}).resolve().getSchemaType():e[o]=c.of({results:e,schema:n,key:o,parentKey:o}).resolve().getSchemaType()),Object.entries(s).forEach(([o,n])=>{let i=c.of({results:e,schema:n,key:o,parentKey:n.enum?"":o}).resolve().getSchemaType();return n.enum||(e[o]=i),i}),this.resolvedDefinitions=e,this};toDeclarations=()=>Object.keys(this.resolvedDefinitions).sort().map(e=>{if(e.includes(f))return F(this.resolvedDefinitions,e);if(this.resolvedDefinitions[e]==="object"||(0,me.isEmpty)(this.resolvedDefinitions[e]))return`export interface ${u(e)} {[key:string]:any}`;let t=E(this.resolvedDefinitions[e]);if(t)return`export interface ${u(e)} ${t}`}).filter(e=>!!e)};var v=P(require("path"),1);var T=require("moderndash");var A=class{constructor(e){this.paths=e}resolvedPaths=[];extraDefinitions={};contentType={};static of(e){return new A(e)}resolve=()=>(this.resolvedPaths=Object.entries(this.paths).reduce((e,[t,s])=>[...e,...this.resolvePath(s,t)],[]),this);toRequest=()=>{let e=this.resolvedPaths.sort(H("operationId")),t=[],s=e.map(i=>{let m=a(i,"THeader"),g=a(i.cookieParams,"[0]"),p=a(i,"requestBody"),R=(0,T.camelCase)(u(p||g)),O=this.toHookParams(a(i,"queryParams")),x=pe(!(0,T.isEmpty)(R),this.contentType,i.operationId,m),[S,de]=ie(i.TReqBody,i.TReqQuery,i.operationId);return t.push([S,de]),i.method==="get"?`export const ${L(i.operationId)} = (${ae(i)}) => ${oe(i.TResp)}({ url: \`${i.url}\`, method: "${i.method}",${x}${_(x)} ${O?`params: ${O},`:""}...axiosConfig}, SWRConfig);`:`export const ${L(i.operationId)} = (${ce(i,S)}) => ${ne(i.TResp,S)}({ url: \`${i.url}\`, method: "${i.method}",${x}${_(x)} mutationConfig, axiosConfig});`}),o=Object.keys(this.extraDefinitions).map(i=>F(this.extraDefinitions,i)),n=t.map(([i,m])=>{if(i)return Object.keys(m).forEach(g=>{(0,T.isEmpty)(m[g])&&delete m[g]}),`export interface ${i} ${re(m)}`}).filter(Boolean);return[...s,...n,...o]};toHookParams=(e=[])=>(0,T.isEmpty)(e)?void 0:`{ ${e.join(`, `)} }`;resolvePath(e,t){let s=J(e,X);return Object.keys(s).map(o=>({url:this.getRequestURL(t),method:o,...this.resolveOperation(s[o])}))}getRequestURL=e=>e.split(k).map(t=>this.isPathParam(t)?`$${t}`:t).join(k);isPathParam=e=>e.startsWith("{");resolveOperation=e=>{e.operationId||Z(`your request does not have an operation id, generated request method will not has uniq name! `);let t=this.pickParams(e.parameters),s=t("header"),o={pathParams:t("path"),queryParams:t("query"),cookieParams:t("cookie")};return{operationId:e.operationId,TResp:this.getResponseTypes(e.responses),TReqQuery:this.getQueryParamsTypes(o.queryParams),TReqPath:this.getPathParamsTypes(o.pathParams),TReqCookie:this.getCookieParamsTypes(o.cookieParams),TReqBody:this.getRequestBodyTypes(e.operationId,a(e,"requestBody")),THeader:this.getPathParamsTypes(s),...this.getParamsNames(o),...this.getRequestBodyName(a(e,"requestBody"),e.operationId)}};getParamsNames=e=>{let t=s=>(0,T.isEmpty)(s)?[]:s?.map(o=>o.name);return{pathParams:t(e.pathParams),queryParams:t(e.queryParams),cookieParams:t(e.cookieParams)}};getPathParamsTypes=e=>e?.reduce((t,s)=>{let o=a(s,"schema");return z(o)?{...t,[`${s.name}${s.required?"":"?"}`]:o.type==="integer"?"number":o.type}:{...t}},{})??{};getQueryParamsTypes=e=>e?.reduce((t,s)=>({...t,[`${s.name}${s.required?"":"?"}`]:c.of({results:this.extraDefinitions,schema:s.schema,key:s.name,parentKey:s.name}).resolve().getSchemaType()}),{})??{};getCookieParamsTypes=e=>e?.reduce((t,s)=>({...t,[`${s.name}${s.required?"":"?"}`]:c.of({results:this.extraDefinitions,schema:s.schema,key:s.name,parentKey:s.name}).resolve().getSchemaType()}),{})??{};getResponseTypes=e=>c.of({results:this.extraDefinitions,schema:a(e,"200.content.application/json.schema")||a(e,"200.content.*/*.schema")||a(e,"201.content.application/json.schema")||a(e,"201.content.*/*.schema")||a(e,"default.content.application/json.schema")||a(e,"default.content.application/json; charset=UTF-8.schema")}).resolve().getSchemaType();pickParams=e=>t=>e?.filter(s=>s.in===t);getContentType(e,t){t&&Object.assign(this.contentType,{[t]:e})}getRequestBodyTypes(e,t){if(I(t)){let s=a(t,"content",{});return Object.entries(s).reduce((o,[n,i])=>(this.getContentType(n,e),{...o,[`${e}Request`]:c.of({results:this.extraDefinitions,schema:i.schema,key:`${e}Request`,parentKey:`${e}Request`}).resolve().getSchemaType()}),{})}return{[`${e}Request`]:c.of({results:this.extraDefinitions,schema:t,key:`${e}Request`,parentKey:`${e}Request`}).resolve().getSchemaType()}}getRequestBodyName(e,t){if(e)return{requestBody:`${t}Request`}}};var ye=P(require("axios"),1);var G=require("commander");var ue=`// you can use this file as your request handler directly, // or you can use your own request handler file, just need to align hook name and interface import useSWR, { SWRResponse } from "swr"; import { SWRConfiguration } from "swr/_internal"; import { AxiosError, AxiosRequestConfig, AxiosResponse } from "axios"; import { client } from "./client"; export interface Return<Data, Error> extends Pick<SWRResponse<AxiosResponse<Data>, AxiosError<Error>>, "isValidating" | "error" | "mutate" | "isLoading"> { data: Data | undefined; response: AxiosResponse<Data> | undefined; } export interface SWRConfig<Data = unknown, Error = unknown> extends Omit<SWRConfiguration<AxiosResponse<Data>, AxiosError<Error>>, "onSuccess"> { onSuccess?: (response: AxiosResponse<Data>, key: string) => void; shouldFetch?: boolean; } export const generateSwrConfigWithShouldFetchProperty = <Data, Error>( SWRConfig?: SWRConfig<Data, Error>, ): SWRConfig<Data, Error> => SWRConfig ? !SWRConfig.shouldFetch ? SWRConfig : { ...SWRConfig, shouldFetch: true, } : { shouldFetch: true }; export const useGetRequest = <Data = unknown, Error = unknown>( axiosConfig: AxiosRequestConfig, SWRConfig?: SWRConfig<Data, Error>, ): Return<Data, Error> => { const swrConfig = generateSwrConfigWithShouldFetchProperty(SWRConfig); const shouldFetch = swrConfig.shouldFetch; delete swrConfig.shouldFetch; const { data: response, error, isValidating, mutate, isLoading, } = useSWR<AxiosResponse<Data>, AxiosError<Error>>( // eslint-disable-next-line @typescript-eslint/no-non-null-assertion () => (shouldFetch ? axiosConfig.url! : null), () => client(axiosConfig), swrConfig, ); return { data: response && response.data, response, error, isValidating, isLoading, mutate }; };`;var fe=`import useSWRMutation, { SWRMutationConfiguration } from "swr/mutation"; import { AxiosError, AxiosRequestConfig, AxiosResponse, RawAxiosRequestHeaders } from "axios"; import { client } from "src/request/client"; export type SWRMutationConfig<Request = any, Response = any, Error = any> = SWRMutationConfiguration< AxiosResponse<Response>, AxiosError<Error>, Request, string >; export const useMutationRequest = < Request extends { body?: any; query?: any } | undefined, Response = any, Error = any, >({ url, method, headers, mutationConfig, axiosConfig, }: { url: string; method: string; headers: RawAxiosRequestHeaders; mutationConfig?: SWRMutationConfiguration<AxiosResponse<Response>, AxiosError<Error>, Request, string>; axiosConfig?: AxiosRequestConfig; }) => { const { trigger, data, isMutating, error, reset } = useSWRMutation< AxiosResponse<Response>, AxiosError<Error>, // assume all key is url, so it will be string type string, Request >( url, (url: string, options: { arg: Request }) => client.request({ url, method, headers, data: options.arg?.body, params: options.arg?.query, ...axiosConfig }), mutationConfig, ); return { trigger, data, isMutating, error, reset }; };`;var he=`import axios, { AxiosInstance } from "axios"; export const API_DEFAULT_TIMEOUT = 30 * 1000; export const client: AxiosInstance = axios.create({ baseURL: "/api", timeout: API_DEFAULT_TIMEOUT, });`;G.program.option("-a, --authorization <value>","authorization header value").parse(process.argv);var ge=v.default.resolve("ts-codegen.config.json"),qe=async()=>d.default.existsSync(ge)?await import(ge,{assert:{type:"json"}}).then(r=>r.default):{output:".output",fileHeaders:[],clients:[]};qe().then(({output:r=".output",fileHeaders:e,timeout:t,data:s,clients:o,fileName:n,needRequestHook:i,needClient:m})=>{let g=p=>{if(typeof p=="string"){$(j.INVALID_JSON_FILE_ERROR);return}d.default.existsSync(r)||d.default.mkdirSync(r);let R=(e?e.join(` `):"")+` `+Y+[...A.of(p.paths).resolve().toRequest(),...C.of(p.components).scanDefinitions().toDeclarations()].join(` `);d.default.writeFileSync(v.default.resolve(r,`./${n||"request"}.ts`),N(R),"utf-8")};if((s||[]).map(p=>{if(!p.endsWith("json")&&!p.endsWith("yml")&&!p.endsWith("yaml")){$(j.INVALID_FILE_FORMAT);return}console.log(b.READING);let R=d.default.readFileSync(p,"utf8"),O=p.endsWith("json")?se(R):le.load(R);O&&(console.log(b.GENERATING+` `),g(O),W(b.SUCCESSFUL+` `))}),o){let p=G.program.opts(),R=ye.default.create({timeout:t||10*1e3,headers:p.authorization?{Authorization:p.authorization}:void 0});o.map((O,x)=>{console.log(b.GETTING_FROM_REMOTE(x)),R.get(O).then(S=>{console.log(b.GENERATING+` `),g(S.data),W(b.SUCCESSFUL+` `)}).catch(S=>{$(`${S.code}: ${j.FETCH_CLIENT_FAILED_ERROR}`)})})}i&&(d.default.writeFileSync(v.default.resolve(r,"./useGetRequest.ts"),N(ue),"utf-8"),d.default.writeFileSync(v.default.resolve(r,"./useMutationRequest.ts"),N(fe),"utf-8")),m&&d.default.writeFileSync(v.default.resolve(r,"./client.ts"),N(he),"utf-8")});