swaggie 1.9.0 → 2.0.0
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/README.md +117 -31
- package/dist/browser.js +24 -5
- package/dist/cli.js +54 -7
- package/dist/gen/genMocks.js +453 -0
- package/dist/gen/genOperations.js +112 -20
- package/dist/gen/genTypes.js +6 -5
- package/dist/gen/header.js +0 -1
- package/dist/gen/index.js +14 -1
- package/dist/generated/bundledTemplates.js +17 -19
- package/dist/index.js +17 -1
- package/dist/swagger/operations.js +16 -7
- package/dist/swagger/typesExtractor.js +12 -11
- package/dist/types.d.ts +55 -5
- package/dist/utils/documentLoader.js +1 -3
- package/dist/utils/fileUtils.js +22 -0
- package/dist/utils/refResolver.js +9 -21
- package/dist/utils/templateEngine.js +18 -0
- package/dist/utils/templateManager.js +123 -14
- package/dist/utils/templateValidator.js +127 -0
- package/dist/utils/utils.js +19 -13
- package/package.json +5 -4
- package/templates/axios/operation.ejs +25 -21
- package/templates/fetch/operation.ejs +4 -0
- package/templates/ng1/operation.ejs +11 -3
- package/templates/ng2/baseClient.ejs +9 -49
- package/templates/ng2/client.ejs +3 -7
- package/templates/ng2/operation.ejs +34 -17
- package/templates/swr/baseClient.ejs +7 -0
- package/templates/swr/client.ejs +63 -0
- package/templates/swr/swrMutationOperation.ejs +32 -0
- package/templates/swr/swrOperation.ejs +18 -0
- package/templates/tsq/baseClient.ejs +1 -0
- package/templates/tsq/client.ejs +67 -0
- package/templates/tsq/mutationOperation.ejs +31 -0
- package/templates/tsq/queryOperation.ejs +19 -0
- package/templates/xior/operation.ejs +25 -21
- package/templates/swr-axios/barrel.ejs +0 -58
- package/templates/swr-axios/baseClient.ejs +0 -20
- package/templates/swr-axios/client.ejs +0 -21
- package/templates/swr-axios/operation.ejs +0 -40
- package/templates/swr-axios/swrOperation.ejs +0 -50
- package/templates/tsq-xior/barrel.ejs +0 -0
- package/templates/tsq-xior/baseClient.ejs +0 -14
- package/templates/tsq-xior/client.ejs +0 -22
- package/templates/tsq-xior/operation.ejs +0 -40
- package/templates/tsq-xior/queryOperation.ejs +0 -30
package/dist/gen/genTypes.js
CHANGED
|
@@ -204,8 +204,9 @@ function generateItemsType(schema, options) {
|
|
|
204
204
|
function renderExtendedEnumType(name, def) {
|
|
205
205
|
const isString = def.type === 'string';
|
|
206
206
|
let res = `export enum ${name} {\n`;
|
|
207
|
-
const
|
|
208
|
-
const
|
|
207
|
+
const defAny = def ;
|
|
208
|
+
const enumNames = _nullishCoalesce(_nullishCoalesce(defAny['x-enumNames'], () => ( defAny['x-enum-varnames'])), () => ( []));
|
|
209
|
+
const enumValues = (_nullishCoalesce(def.enum, () => ( []))).map((el) => (isString ? `"${el}"` : el));
|
|
209
210
|
|
|
210
211
|
for (let index = 0; index < enumNames.length; index++) {
|
|
211
212
|
res += ` ${_utils.escapePropName.call(void 0, enumNames[index])} = ${enumValues[index]},\n`;
|
|
@@ -221,7 +222,7 @@ function renderEnumType(name, def, options) {
|
|
|
221
222
|
return renderStringEnumDeclaration(name, def, options);
|
|
222
223
|
}
|
|
223
224
|
|
|
224
|
-
const values = def.enum.map((v) => (typeof v === 'number' ? v : `"${v}"`)).join(' | ');
|
|
225
|
+
const values = (_nullishCoalesce(def.enum, () => ( []))).map((v) => (typeof v === 'number' ? v : `"${v}"`)).join(' | ');
|
|
225
226
|
return `export type ${name} = ${values};\n`;
|
|
226
227
|
}
|
|
227
228
|
|
|
@@ -272,7 +273,7 @@ function toPascalCase(value) {
|
|
|
272
273
|
*/
|
|
273
274
|
function renderOpenApi31Enum(name, def) {
|
|
274
275
|
let res = `export enum ${name} {\n`;
|
|
275
|
-
for (const v of def.oneOf) {
|
|
276
|
+
for (const v of _nullishCoalesce(def.oneOf, () => ( []))) {
|
|
276
277
|
if ('const' in v) {
|
|
277
278
|
res += ` ${_utils.escapePropName.call(void 0, v.title)} = ${
|
|
278
279
|
typeof v.const === 'string' ? `"${v.const}"` : v.const
|
|
@@ -383,7 +384,7 @@ function getMergedCompositeObjects(schema) {
|
|
|
383
384
|
}
|
|
384
385
|
|
|
385
386
|
function isObject(item) {
|
|
386
|
-
return item && typeof item === 'object' && !Array.isArray(item);
|
|
387
|
+
return !!item && typeof item === 'object' && !Array.isArray(item);
|
|
387
388
|
}
|
|
388
389
|
function deepMerge(target, ...sources) {
|
|
389
390
|
if (!sources.length) return target;
|
package/dist/gen/header.js
CHANGED
package/dist/gen/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _createNamedExportFrom(obj, localName, importedName) { Object.defineProperty(exports, localName, {enumerable: true, configurable: true, get: () => obj[importedName]}); }
|
|
2
2
|
|
|
3
3
|
var _genOperations = require('./genOperations'); var _genOperations2 = _interopRequireDefault(_genOperations);
|
|
4
|
+
var _genMocks = require('./genMocks'); var _genMocks2 = _interopRequireDefault(_genMocks);
|
|
4
5
|
var _genTypes = require('./genTypes'); var _genTypes2 = _interopRequireDefault(_genTypes);
|
|
5
6
|
var _header = require('./header'); _createNamedExportFrom(_header, 'FILE_HEADER', 'FILE_HEADER');
|
|
6
7
|
var _utils = require('../utils');
|
|
@@ -23,7 +24,19 @@ var _utils = require('../utils');
|
|
|
23
24
|
|
|
24
25
|
if (options.out) {
|
|
25
26
|
const destFile = _utils.prepareOutputFilename.call(void 0, options.out);
|
|
26
|
-
|
|
27
|
+
if (destFile) {
|
|
28
|
+
await _utils.saveFile.call(void 0, destFile, fileContents);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (options.mocks && options.testingFramework && options.out) {
|
|
33
|
+
const resolvedMocksPath = _utils.prepareOutputFilename.call(void 0, options.mocks);
|
|
34
|
+
const resolvedOutPath = _utils.prepareOutputFilename.call(void 0, options.out);
|
|
35
|
+
if (resolvedMocksPath && resolvedOutPath) {
|
|
36
|
+
const relativeApiImport = _utils.deriveRelativeImport.call(void 0, resolvedMocksPath, resolvedOutPath);
|
|
37
|
+
const mockContents = _genMocks2.default.call(void 0, spec, options, relativeApiImport);
|
|
38
|
+
await _utils.saveFile.call(void 0, resolvedMocksPath, mockContents);
|
|
39
|
+
}
|
|
27
40
|
}
|
|
28
41
|
|
|
29
42
|
return fileContents;
|
|
@@ -6,45 +6,43 @@
|
|
|
6
6
|
"barrel.ejs": "\n/**\n * Serializes a params object into a query string that is compatible with different REST APIs.\n * Implementation from: https://github.com/suhaotian/xior/blob/main/src/utils.ts\n * Kudos to @suhaotian for the original implementation\n */\nfunction encodeParams<T = any>(\n params: T,\n parentKey: string | null = null,\n options?: {\n allowDots?: boolean;\n serializeDate?: (value: Date) => string;\n arrayFormat?: 'indices' | 'repeat' | 'brackets';\n }\n): string {\n if (params === undefined || params === null) return '';\n const encodedParams: string[] = [];\n const paramsIsArray = Array.isArray(params);\n const { arrayFormat, allowDots, serializeDate } = options || {};\n\n const getKey = (key: string) => {\n if (allowDots && !paramsIsArray) return `.${key}`;\n if (paramsIsArray) {\n if (arrayFormat === 'brackets') {\n return '[]';\n }\n if (arrayFormat === 'repeat') {\n return '';\n }\n }\n return `[${key}]`;\n };\n\n for (const key in params) {\n if (Object.prototype.hasOwnProperty.call(params, key)) {\n let value = (params as any)[key];\n if (value !== undefined) {\n const encodedKey = parentKey ? `${parentKey}${getKey(key)}` : (key as string);\n\n // biome-ignore lint/suspicious/noGlobalIsNan: <explanation>\n if (!isNaN(value) && value instanceof Date) {\n value = serializeDate ? serializeDate(value) : value.toISOString();\n }\n if (typeof value === 'object') {\n // If the value is an object or array, recursively encode its contents\n const result = encodeParams(value, encodedKey, options);\n if (result !== '') encodedParams.push(result);\n } else {\n // Otherwise, encode the key-value pair\n encodedParams.push(`${encodeURIComponent(encodedKey)}=${encodeURIComponent(value)}`);\n }\n }\n }\n }\n\n return encodedParams.join('&');\n}\n\n",
|
|
7
7
|
"baseClient.ejs": "import Axios, { type AxiosPromise, type AxiosRequestConfig } from \"axios\";\n\nexport const axios = Axios.create({\n baseURL: '<%= it.baseUrl || '' %>',\n paramsSerializer: (params: any) =>\n encodeParams(params, null, {\n allowDots: <%= it.allowDots %>,\n arrayFormat: '<%= it.arrayFormat %>',\n }),\n});\n\n",
|
|
8
8
|
"client.ejs": "export const <%= it.camelCaseName %>Client = {\n <% it.operations.forEach((operation) => { %>\n<%~ include('operation.ejs', operation); %>\n\n<% }); %>\n};\n\n",
|
|
9
|
-
"operation.ejs": "<%~ it.jsDocs %>\n\n <%= it.name %>(<% it.parameters.forEach((parameter) => { %>\n<%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,\n <% }); %>\n$config?: AxiosRequestConfig\n ): AxiosPromise<<%~ it.returnType %>> {\n const url = `<%= it.url %>`;\n\n return axios.request<<%~ it.returnType %>>({\n url: url,\n method: '<%= it.method %>',\n<% if(it.body) {
|
|
9
|
+
"operation.ejs": "<%~ it.jsDocs %>\n\n <%= it.name %>(<% it.parameters.forEach((parameter) => { %>\n<%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,\n <% }); %>\n$config?: AxiosRequestConfig\n ): AxiosPromise<<%~ it.returnType %>> {\n const url = `<%= it.url %>`;\n\n return axios.request<<%~ it.returnType %>>({\n url: url,\n method: '<%= it.method %>',\n<% if(it.body) { -%>\n<% if(it.body.contentType === 'urlencoded') { -%>\n data: new URLSearchParams(<%= it.body.name %> as any),\n<% } else { -%>\n data: <%= it.body.name %>,\n<% } -%>\n<% } -%>\n<% if(it.query && it.query.length > 0) { -%>\n params: {\n<% it.query.forEach((parameter) => { -%>\n<% if (it.queryParamObject) { -%>\n '<%= parameter.originalName %>': <%= it.queryParamObject.name %>?.<%= parameter.name %>,\n<% } else { -%>\n '<%= parameter.originalName %>': <%= parameter.name %>,\n<% } -%>\n<% }); -%>\n },\n<% } -%>\n<% if(it.headers && it.headers.length > 0) { -%>\n headers: {\n<% it.headers.forEach((parameter) => { -%>\n<% if (parameter.value) { -%>\n '<%= parameter.originalName %>': '<%= parameter.value %>',\n<% } else { -%>\n '<%= parameter.originalName %>': <%= parameter.name %>,\n<% } -%>\n<% }); -%>\n },\n<% } -%>\n ...$config,\n });\n },\n"
|
|
10
10
|
},
|
|
11
11
|
"fetch": {
|
|
12
12
|
"barrel.ejs": "\n/**\n * Serializes a params object into a query string that is compatible with different REST APIs.\n * Implementation from: https://github.com/suhaotian/xior/blob/main/src/utils.ts\n * Kudos to @suhaotian for the original implementation\n */\nfunction encodeParams<T = any>(\n params: T,\n parentKey: string | null = null,\n options?: {\n allowDots?: boolean;\n serializeDate?: (value: Date) => string;\n arrayFormat?: 'indices' | 'repeat' | 'brackets';\n }\n): string {\n if (params === undefined || params === null) return '';\n const encodedParams: string[] = [];\n const paramsIsArray = Array.isArray(params);\n const { arrayFormat, allowDots, serializeDate } = options || {};\n\n const getKey = (key: string) => {\n if (allowDots && !paramsIsArray) return `.${key}`;\n if (paramsIsArray) {\n if (arrayFormat === 'brackets') {\n return '[]';\n }\n if (arrayFormat === 'repeat') {\n return '';\n }\n }\n return `[${key}]`;\n };\n\n for (const key in params) {\n if (Object.prototype.hasOwnProperty.call(params, key)) {\n let value = (params as any)[key];\n if (value !== undefined) {\n const encodedKey = parentKey ? `${parentKey}${getKey(key)}` : (key as string);\n\n // biome-ignore lint/suspicious/noGlobalIsNan: <explanation>\n if (!isNaN(value) && value instanceof Date) {\n value = serializeDate ? serializeDate(value) : value.toISOString();\n }\n if (typeof value === 'object') {\n // If the value is an object or array, recursively encode its contents\n const result = encodeParams(value, encodedKey, options);\n if (result !== '') encodedParams.push(result);\n } else {\n // Otherwise, encode the key-value pair\n encodedParams.push(`${encodeURIComponent(encodedKey)}=${encodeURIComponent(value)}`);\n }\n }\n }\n }\n\n return encodedParams.join('&');\n}\n\n",
|
|
13
13
|
"baseClient.ejs": "export const defaults = {\n baseUrl: '<%= it.baseUrl || '' %>',\n paramsSerializer: (params: any) =>\n encodeParams(params, null, {\n allowDots: <%= it.allowDots %>,\n arrayFormat: '<%= it.arrayFormat %>',\n }),\n};\n\n",
|
|
14
14
|
"client.ejs": "export const <%= it.camelCaseName %>Client = {\n <% it.operations.forEach((operation) => { %>\n<%~ include('operation.ejs', operation); %>\n\n<% }); %>\n};\n",
|
|
15
|
-
"operation.ejs": "<%~ it.jsDocs %>\n\n <%= it.name %>(<% it.parameters.forEach((parameter) => { %>\n<%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,\n <% }); %>\n$config?: RequestInit\n ): Promise<<%~ it.returnType %>> {\n const url = `${defaults.baseUrl}<%= it.url %>?<%\n if(it.query && it.query.length > 0) { %>${defaults.paramsSerializer({<%\n it.query.forEach((parameter) => { %>\n'<%= parameter.originalName %>': <%= parameter.name %>,\n <% }); %>})}<% } %>`;\n\n<% if(it.headers && it.headers.length > 0) { %>\n const { headers: $configHeaders, ...$configRest } = $config ?? {};\n const headers = new Headers({\n<% it.headers.forEach((parameter) => { %>\n<% if (parameter.value) { %>\n '<%= parameter.originalName %>': '<%= parameter.value %>',\n<% } else { %>\n '<%= parameter.originalName %>': <%= parameter.name %> ?? '',\n<% } %>\n<% }); %>\n });\n if ($configHeaders) {\n new Headers($configHeaders).forEach((value, key) => headers.set(key, value));\n }\n\n return fetch(url, {\n method: '<%= it.method %>',\n<% if(it.body) { %>\n<% if(it.body.contentType === 'json') { %>\n body: JSON.stringify(<%= it.body.name %>),\n<% } else if(it.body.contentType === 'urlencoded') { %>\n body: new URLSearchParams(<%= it.body.name %> as any),\n<% } else { %>\n body: <%= it.body.name %>,\n<% } %>\n<% } %>\n headers,\n ...$configRest,\n })\n<% } else { %>\n return fetch(url, {\n method: '<%= it.method %>',\n<% if(it.body) { %>\n<% if(it.body.contentType === 'json') { %>\n body: JSON.stringify(<%= it.body.name %>),\n<% } else if(it.body.contentType === 'urlencoded') { %>\n body: new URLSearchParams(<%= it.body.name %> as any),\n<% } else { %>\n body: <%= it.body.name %>,\n<% } %>\n<% } %>\n ...$config,\n })\n<% } %>\n<% if(it.responseContentType === 'binary') { %>\n .then((response) => response.blob() as Promise<<%~ it.returnType %>>);\n<% } else if(it.responseContentType === 'text') { %>\n .then((response) => response.text() as Promise<<%~ it.returnType %>>);\n<% } else { %>\n .then((response) => response.json() as Promise<<%~ it.returnType %>>);\n<% } %>\n },\n"
|
|
15
|
+
"operation.ejs": "<%~ it.jsDocs %>\n\n <%= it.name %>(<% it.parameters.forEach((parameter) => { %>\n<%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,\n <% }); %>\n$config?: RequestInit\n ): Promise<<%~ it.returnType %>> {\n const url = `${defaults.baseUrl}<%= it.url %>?<%\n if(it.query && it.query.length > 0) { %>${defaults.paramsSerializer({<%\n it.query.forEach((parameter) => { %>\n<% if (it.queryParamObject) { %>\n'<%= parameter.originalName %>': <%= it.queryParamObject.name %>?.<%= parameter.name %>,\n<% } else { %>\n'<%= parameter.originalName %>': <%= parameter.name %>,\n<% } %>\n <% }); %>})}<% } %>`;\n\n<% if(it.headers && it.headers.length > 0) { %>\n const { headers: $configHeaders, ...$configRest } = $config ?? {};\n const headers = new Headers({\n<% it.headers.forEach((parameter) => { %>\n<% if (parameter.value) { %>\n '<%= parameter.originalName %>': '<%= parameter.value %>',\n<% } else { %>\n '<%= parameter.originalName %>': <%= parameter.name %> ?? '',\n<% } %>\n<% }); %>\n });\n if ($configHeaders) {\n new Headers($configHeaders).forEach((value, key) => headers.set(key, value));\n }\n\n return fetch(url, {\n method: '<%= it.method %>',\n<% if(it.body) { %>\n<% if(it.body.contentType === 'json') { %>\n body: JSON.stringify(<%= it.body.name %>),\n<% } else if(it.body.contentType === 'urlencoded') { %>\n body: new URLSearchParams(<%= it.body.name %> as any),\n<% } else { %>\n body: <%= it.body.name %>,\n<% } %>\n<% } %>\n headers,\n ...$configRest,\n })\n<% } else { %>\n return fetch(url, {\n method: '<%= it.method %>',\n<% if(it.body) { %>\n<% if(it.body.contentType === 'json') { %>\n body: JSON.stringify(<%= it.body.name %>),\n<% } else if(it.body.contentType === 'urlencoded') { %>\n body: new URLSearchParams(<%= it.body.name %> as any),\n<% } else { %>\n body: <%= it.body.name %>,\n<% } %>\n<% } %>\n ...$config,\n })\n<% } %>\n<% if(it.responseContentType === 'binary') { %>\n .then((response) => response.blob() as Promise<<%~ it.returnType %>>);\n<% } else if(it.responseContentType === 'text') { %>\n .then((response) => response.text() as Promise<<%~ it.returnType %>>);\n<% } else { %>\n .then((response) => response.json() as Promise<<%~ it.returnType %>>);\n<% } %>\n },\n"
|
|
16
16
|
},
|
|
17
17
|
"ng1": {
|
|
18
18
|
"barrel.ejs": "export class ApiServices {\n public static bootstrap(moduleName: string, baseUrl: string) {\n angular\n .module(moduleName)\n .constant('Api<%= it.servicePrefix -%>BaseUrl', baseUrl)\n<% it.clients.forEach((client) => { %>\n .service('<%= client.fileName %>Service', <%= client.fileName %>Service)\n<% }); %>;\n }\n}\n\nfunction serializeQueryParam(obj: any, property: string): string {\n if (obj === null || obj === undefined || obj === '') {\n return '';\n } else if (obj instanceof Date) {\n return property + '=' + encodeURIComponent(obj.toJSON());\n } else if (Array.isArray(obj)) {\n return Object.values(obj)\n .map(value => `${property}[]=${value}`)\n .join('&');\n } else if (typeof obj !== 'object') {\n return property + '=' + encodeURIComponent(obj);\n } else if (typeof obj === 'object') {\n return Object.keys(obj)\n .filter(key => !!serializeQueryParam(obj[key], property + '.' + key))\n .reduce(\n (a: any, b) =>\n a.push(serializeQueryParam(obj[b], property + '.' + b)) && a,\n []\n )\n .join('&');\n } else {\n return '';\n }\n}\n",
|
|
19
19
|
"baseClient.ejs": "import type { IHttpService, IRequestShortcutConfig, IPromise } from 'angular';\n\nabstract class BaseService {\n constructor(protected readonly $http: IHttpService, public baseUrl: string) { }\n\n protected $get<T>(\n url: string,\n config?: IRequestShortcutConfig\n ): IPromise<T> {\n return this.$http.get(this.baseUrl + url, config).then((response: any) => {\n return this.processSingle<T>(response);\n });\n }\n\n protected $getAll<T>(\n url: string,\n config?: IRequestShortcutConfig\n ): IPromise<T[]> {\n return this.$http.get(this.baseUrl + url, config).then((response: any) => {\n return this.processMany<T>(response);\n });\n }\n\n protected $delete<T>(\n url: string,\n config?: IRequestShortcutConfig\n ): IPromise<any> {\n return this.$http\n .delete(this.baseUrl + url, config)\n .then((response: any) => {\n return this.processSingle<T>(response);\n });\n }\n\n protected $head<T>(\n url: string,\n config?: IRequestShortcutConfig\n ): IPromise<any> {\n return this.$http.head(this.baseUrl + url, config).then((response: any) => {\n return this.processSingle<T>(response);\n });\n }\n\n protected $jsonp<T>(\n url: string,\n config?: IRequestShortcutConfig\n ): IPromise<any> {\n return this.$http\n .jsonp(this.baseUrl + url, config)\n .then((response: any) => {\n return this.processSingle<T>(response);\n });\n }\n\n protected $post<T>(\n url: string,\n data: any,\n config?: IRequestShortcutConfig\n ): IPromise<any> {\n return this.$http\n .post(this.baseUrl + url, data, config)\n .then((response: any) => {\n return this.processSingle<T>(response);\n });\n }\n\n protected $put<T>(\n url: string,\n data: any,\n config?: IRequestShortcutConfig\n ): IPromise<any> {\n return this.$http\n .put(this.baseUrl + url, data, config)\n .then((response: any) => {\n return this.processSingle<T>(response);\n });\n }\n\n protected $patch<T>(\n url: string,\n data: any,\n config?: IRequestShortcutConfig\n ): IPromise<any> {\n return this.$http\n .patch(this.baseUrl + url, data, config)\n .then((response: any) => {\n return this.processSingle<T>(response);\n });\n }\n\n protected processSingle<T>(response: any): T {\n var data = response.data;\n var status = response.status;\n\n if (status >= 200 && status <= 299) {\n return data;\n } else {\n throw 'error_no_callback_for_the_received_http_status';\n }\n }\n\n protected processMany<T>(response: any): T[] {\n var data = response.data;\n var status = response.status;\n\n if (status >= 200 && status <= 299) {\n return data;\n } else {\n throw 'error_no_callback_for_the_received_http_status';\n }\n }\n}\n\n",
|
|
20
20
|
"client.ejs": "export class <%= it.clientName -%>Service extends BaseService {\n /* @ngInject */\n constructor($http: IHttpService, Api<%= it.servicePrefix -%>BaseUrl: string) {\n super($http, Api<%= it.servicePrefix -%>BaseUrl);\n }\n\n <% it.operations.forEach((operation) => { %>\n<%~ include('operation.ejs', operation); %>\n\n<% }); %>\n}\n\n",
|
|
21
|
-
"operation.ejs": "<%~ it.jsDocs %>\n\n <%= it.name %>(<% it.parameters.forEach((parameter) => { %>\n<%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,\n <% }); %>\n config?: IRequestShortcutConfig\n ): IPromise<<%~ it.returnType %>> {\n let url = `<%= it.url %>?`;\n<% if(it.query && it.query.length > 0) { %>\n <% it.query.forEach((parameter) => { %>\n if (<%= parameter.name %> !== undefined) {\n <% if(!!parameter.original && parameter.original.type === 'array') { %>\n <%= parameter.name %>.forEach(item => { url += serializeQueryParam(item, '<%= parameter.originalName %>') + \"&\"; });\n <% } else {%>\n url += serializeQueryParam(<%= parameter.name %>, '<%= parameter.originalName %>') + \"&\";\n <% } %>\n }\n <% }); %>\n<% } %>\n\n return this.$<%= it.method.toLowerCase() %>(\n url,\n<% if(['POST', 'PUT', 'PATCH'].includes(it.method)) { %>\n <% if(it.body) { %>\n <%= it.body.contentType === 'urlencoded' ? 'new URLSearchParams(' + it.body.name + ' as any)' : it.body.name %>,\n <% } else { %>\n null,\n <% } %>\n<% } %>\n config\n );\n }\n"
|
|
21
|
+
"operation.ejs": "<%~ it.jsDocs %>\n\n <%= it.name %>(<% it.parameters.forEach((parameter) => { %>\n<%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,\n <% }); %>\n config?: IRequestShortcutConfig\n ): IPromise<<%~ it.returnType %>> {\n let url = `<%= it.url %>?`;\n<% if(it.query && it.query.length > 0) { %>\n <% it.query.forEach((parameter) => { %>\n if (<%= it.queryParamObject ? `${it.queryParamObject.name}?.${parameter.name}` : parameter.name %> !== undefined) {\n <% if(!!parameter.original && parameter.original.type === 'array') { %>\n <%= it.queryParamObject ? `${it.queryParamObject.name}.${parameter.name}` : parameter.name %>.forEach(item => { url += serializeQueryParam(item, '<%= parameter.originalName %>') + \"&\"; });\n <% } else {%>\n url += serializeQueryParam(<%= it.queryParamObject ? `${it.queryParamObject.name}.${parameter.name}` : parameter.name %>, '<%= parameter.originalName %>') + \"&\";\n <% } %>\n }\n <% }); %>\n<% } %>\n\n<% if(it.headers && it.headers.length > 0) { it.headers.forEach((parameter) => { %>\n<% if (parameter.value) { %>\n config = { ...config, headers: { ...config?.headers, '<%= parameter.originalName %>': '<%= parameter.value %>' } };\n<% } else { %>\n if (<%= parameter.name %>) {\n config = { ...config, headers: { ...config?.headers, '<%= parameter.originalName %>': <%= parameter.name %> } };\n }\n<% } %><% }); } %>\n return this.$<%= it.method.toLowerCase() %>(\n url,\n<% if(['POST', 'PUT', 'PATCH'].includes(it.method)) { %>\n <% if(it.body) { %>\n <%= it.body.contentType === 'urlencoded' ? 'new URLSearchParams(' + it.body.name + ' as any)' : it.body.name %>,\n <% } else { %>\n null,\n <% } %>\n<% } %>\n config\n );\n }\n"
|
|
22
22
|
},
|
|
23
23
|
"ng2": {
|
|
24
24
|
"barrel.ejs": "\n/**\n * Serializes a params object into a query string that is compatible with different REST APIs.\n * Implementation from: https://github.com/suhaotian/xior/blob/main/src/utils.ts\n * Kudos to @suhaotian for the original implementation\n */\nfunction encodeParams<T = any>(\n params: T,\n parentKey: string | null = null,\n options?: {\n allowDots?: boolean;\n serializeDate?: (value: Date) => string;\n arrayFormat?: 'indices' | 'repeat' | 'brackets';\n }\n): string {\n if (params === undefined || params === null) return '';\n const encodedParams: string[] = [];\n const paramsIsArray = Array.isArray(params);\n const { arrayFormat, allowDots, serializeDate } = options || {};\n\n const getKey = (key: string) => {\n if (allowDots && !paramsIsArray) return `.${key}`;\n if (paramsIsArray) {\n if (arrayFormat === 'brackets') {\n return '[]';\n }\n if (arrayFormat === 'repeat') {\n return '';\n }\n }\n return `[${key}]`;\n };\n\n for (const key in params) {\n if (Object.prototype.hasOwnProperty.call(params, key)) {\n let value = (params as any)[key];\n if (value !== undefined) {\n const encodedKey = parentKey ? `${parentKey}${getKey(key)}` : (key as string);\n\n // biome-ignore lint/suspicious/noGlobalIsNan: <explanation>\n if (!isNaN(value) && value instanceof Date) {\n value = serializeDate ? serializeDate(value) : value.toISOString();\n }\n if (typeof value === 'object') {\n // If the value is an object or array, recursively encode its contents\n const result = encodeParams(value, encodedKey, options);\n if (result !== '') encodedParams.push(result);\n } else {\n // Otherwise, encode the key-value pair\n encodedParams.push(`${encodeURIComponent(encodedKey)}=${encodeURIComponent(value)}`);\n }\n }\n }\n }\n\n return encodedParams.join('&');\n}\n\n",
|
|
25
|
-
"baseClient.ejs": "import type { Observable } from \"rxjs\";\nimport { Injectable,
|
|
26
|
-
"client.ejs": "@Injectable({\n providedIn: 'root'\n})\nexport class <%= it.clientName -%>Service
|
|
27
|
-
"operation.ejs": "<%~ it.jsDocs %>\n\n <%= it.name %>(\n <% it.parameters.forEach((parameter) => { %>\n<%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,\n <% }); %>\nconfig?:
|
|
25
|
+
"baseClient.ejs": "import type { Observable } from \"rxjs\";\nimport { Injectable, InjectionToken, inject } from \"@angular/core\";\nimport { HttpClient, type HttpContext, type HttpHeaders, type HttpParams } from \"@angular/common/http\";\n\nexport const <%= (it.servicePrefix || 'API').toUpperCase() -%>_BASE_URL = new InjectionToken<string>(\"<%= (it.servicePrefix || 'API').toUpperCase() -%>_BASE_URL\");\n\nexport interface HttpConfig {\n headers?: HttpHeaders | Record<string, string | string[]>;\n context?: HttpContext;\n params?: HttpParams | Record<string, string | number | boolean | (string | number | boolean)[]>;\n reportProgress?: boolean;\n withCredentials?: boolean;\n transferCache?: boolean | { includeHeaders?: string[] };\n}\n\nfunction paramsSerializer(params: any) {\n return encodeParams(params, null, {\n allowDots: <%= it.allowDots %>,\n arrayFormat: '<%= it.arrayFormat %>',\n });\n}\n\n",
|
|
26
|
+
"client.ejs": "@Injectable({\n providedIn: 'root'\n})\nexport class <%= it.clientName.charAt(0).toUpperCase() + it.clientName.slice(1) -%>Service {\n private http = inject(HttpClient);\n private baseUrl = inject(<%= (it.servicePrefix || 'API').toUpperCase() -%>_BASE_URL, { optional: true }) ?? '';\n\n <% it.operations.forEach((operation) => { %>\n<%~ include('operation.ejs', operation); %>\n\n<% }); %>\n}\n\n",
|
|
27
|
+
"operation.ejs": "<%~ it.jsDocs %>\n\n <%= it.name %>(\n <% it.parameters.forEach((parameter) => { %>\n<%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,\n <% }); %>\nconfig?: HttpConfig\n ): Observable<<%~ it.returnType %>> {\n<% if(it.query && it.query.length > 0) { -%>\n const params = paramsSerializer({\n<% it.query.forEach((parameter) => { -%>\n<% if (it.queryParamObject) { -%>\n '<%= parameter.originalName %>': <%= it.queryParamObject.name %>?.<%= parameter.name %>,\n<% } else { -%>\n '<%= parameter.originalName %>': <%= parameter.name %>,\n<% } -%>\n<% }); -%>\n });\n const url = `<%= it.url %>${params ? '?' + params : ''}`;\n<% } else { -%>\n const url = `<%= it.url %>`;\n<% } -%>\n<% if(it.headers && it.headers.length > 0) { it.headers.forEach((parameter) => { -%>\n<% if (parameter.value) { -%>\n config = { ...config, headers: { ...config?.headers, '<%= parameter.originalName %>': '<%= parameter.value %>' } };\n<% } else { -%>\n if (<%= parameter.name %>) {\n config = { ...config, headers: { ...config?.headers, '<%= parameter.originalName %>': <%= parameter.name %> } };\n }\n<% } -%>\n<% }); } -%>\n<% if(it.method === 'GET') { -%>\n return this.http.get<<%~ it.returnType %>>(this.baseUrl + url, config);\n<% } else if(it.method === 'DELETE') { -%>\n return this.http.delete<<%~ it.returnType %>>(this.baseUrl + url, config);\n<% } else if(['POST', 'PUT', 'PATCH'].includes(it.method)) {\n const bodyArg = it.body\n ? (it.body.contentType === 'urlencoded' ? 'new URLSearchParams(' + it.body.name + ' as any)' : it.body.name)\n : 'null';\n-%>\n return this.http.<%= it.method.toLowerCase() %><%~ '<' + it.returnType + '>' %>(this.baseUrl + url, <%~ bodyArg %>, config);\n<% } %>\n }\n"
|
|
28
28
|
},
|
|
29
|
-
"swr
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"swrOperation.ejs": "<%~ it.jsDocs %>\n\nexport function <%= it.swrOpName %>(<% it.parameters.forEach((parameter) => { %>\n <%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,\n <% }); %>\n $config?: SwrConfig\n ) {\n const url = `<%= it.url %>`;\n const { axios: $axiosConf, key, ...config } = $config || {};\n\n const cacheUrl = `${url}?<%\n if(it.query && it.query.length > 0) { %>${encodeParams({<%\n it.query.forEach((parameter) => { %>\n'<%= parameter.originalName %>': <%= parameter.name %>,\n <% }); %>})}<% } %>`;\n\nconst { data, error, mutate } = useSWR<<%~ it.returnType %>>(\n key ?? cacheUrl,\n () => axios.request({\n url: url,\n method: '<%= it.method %>',\n<% if(it.query && it.query.length > 0) { %>\n params: {\n <% it.query.forEach((parameter) => { %>\n '<%= parameter.originalName %>': <%= parameter.name %>,\n <% }); %>\n},\n<% } %>\n<% if(it.headers && it.headers.length > 0) { %>\n headers: {\n <% it.headers.forEach((parameter) => { %>\n <% if (parameter.value) { %>\n '<%= parameter.originalName %>': '<%= parameter.value %>',\n <% } else { %>\n '<%= parameter.originalName %>': <%= parameter.name %>,\n <% } %>\n <% }); %>\n },\n<% } %>\n ...$axiosConf})\n .then((resp) => resp.data),\n config);\n\n return {\n data,\n isLoading: !error && !data,\n error: error,\n mutate,\n };\n}\n"
|
|
29
|
+
"swr": {
|
|
30
|
+
"baseClient.ejs": "import useSWR, { type SWRConfiguration, type Key } from 'swr';\nimport useSWRMutation, { type SWRMutationConfiguration } from 'swr/mutation';\n\ninterface SwrConfig extends SWRConfiguration {\n /* Custom key for SWR. You don't have to worry about this as by default it's the URL. You can use standard SWR Key here if you need more flexibility. */\n key?: Key;\n}\n",
|
|
31
|
+
"client.ejs": "export const <%= it.camelCaseName -%>Client = {\n <% it.operations.forEach((operation) => { %>\n<%~ include('operation.ejs', operation); %>\n\n <% }); %>\n};\n\n<%\nvar getOperations = it.operations.filter((o) => o.method === 'GET');\nvar mutationOperations = it.operations.filter((o) => o.method !== 'GET');\n\nfunction toOpName(name) {\n var n = name.toLowerCase().startsWith('get') ? name.substring(3) : name;\n return n.charAt(0).toUpperCase() + n.slice(1);\n}\n\nfunction safeOperation(operation, clientName) {\n var safeParams = operation.parameters.map(function(p) {\n return p.name === clientName ? Object.assign({}, p, { name: '_' + p.name }) : p;\n });\n return Object.assign({}, operation, { parameters: safeParams });\n}\n%>\n\nexport const <%= it.camelCaseName %> = {\n queries: {\n<% getOperations.forEach((operation) => {\n var opName = toOpName(operation.name);\n var swrOperation = Object.assign({\n swrOpName: 'use' + opName,\n clientName: it.camelCaseName,\n httpConfigType: it.httpConfigType,\n }, safeOperation(operation, it.camelCaseName));\n%>\n<%~ include('swrOperation.ejs', swrOperation); %>\n\n<% }); %>\n },\n\n mutations: {\n<% mutationOperations.forEach((operation) => {\n var opName = operation.name.charAt(0).toUpperCase() + operation.name.slice(1);\n var swrMutationOperation = Object.assign({\n mutOpName: 'use' + opName,\n clientName: it.camelCaseName,\n httpConfigType: it.httpConfigType,\n }, safeOperation(operation, it.camelCaseName));\n%>\n<%~ include('swrMutationOperation.ejs', swrMutationOperation); %>\n\n<% }); %>\n },\n\n queryKeys: {\n<% getOperations.forEach((operation) => {\n var opName = toOpName(operation.name);\n var keyName = opName.charAt(0).toLowerCase() + opName.slice(1);\n var safeOp = safeOperation(operation, it.camelCaseName);\n%>\n <%= keyName %>: (<% safeOp.parameters.forEach((parameter) => { %><%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %><%= parameter.optional ? (parameter.skippable ? ' | null' : ' | null | undefined') : '' %>, <% }); %>) => `<%= operation.url %><% if(safeOp.query && safeOp.query.length > 0) { %>?${encodeParams({<% safeOp.query.forEach((parameter) => { %>'<%= parameter.originalName %>': <%= safeOp.queryParamObject ? `${safeOp.queryParamObject.name}?.${parameter.name}` : parameter.name %>, <% }); %>})}<% } %>`,\n<% }); %>\n },\n};\n",
|
|
32
|
+
"swrMutationOperation.ejs": "<%\nvar hasParams = it.parameters.length > 0;\n\nvar variablesType;\nif (!hasParams) {\n variablesType = 'void';\n} else {\n var parts = it.parameters.map(function(p) {\n return p.name + (p.skippable ? '?' : '') + ': ' + p.type + (p.optional ? ' | null' : '');\n });\n variablesType = '{ ' + parts.join('; ') + ' }';\n}\n\nvar callArgs = it.parameters.map(function(p) { return 'arg.' + p.name; });\n\n// Stable SWR key: replace all ${...} path expressions with *\nvar swrKey = it.url.replace(/\\$\\{(?:[^{}]|\\{[^{}]*\\})*\\}/g, '*');\n\nvar docs = it.jsDocs ? it.jsDocs.replace(/^/gm, ' ') + '\\n' : '';\n%>\n<%~ docs %>\n <%= it.mutOpName %>(\n $config?: SWRMutationConfiguration<<%~ it.returnType %>, Error, string, <%~ variablesType %>>,\n $httpConfig?: <%= it.httpConfigType %>\n ) {\n return useSWRMutation<<%~ it.returnType %>, Error, string, <%~ variablesType %>>(\n '<%= swrKey %>',\n (_key: string, { arg }<%= hasParams ? ': { arg: ' + variablesType + ' }' : '' %>) =>\n <%= it.clientName %>Client.<%= it.name %>(<%= callArgs.join(', ') %><%= callArgs.length > 0 ? ', ' : '' %>$httpConfig).then((resp) => resp.data),\n $config\n );\n },\n",
|
|
33
|
+
"swrOperation.ejs": "<% var docs = it.jsDocs ? it.jsDocs.replace(/^/gm, ' ') + '\\n' : ''; %>\n<%~ docs %>\n <%= it.swrOpName %>(\n<% it.parameters.forEach((parameter) => { %> <%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %><%= parameter.optional ? (parameter.skippable ? ' | null' : ' | null | undefined') : '' %>,\n<% }); %> $config?: Omit<SwrConfig, 'key'> & { key?: Key },\n $httpConfig?: <%= it.httpConfigType %>\n ) {\n const { key, ...config } = $config || {};\n const cacheUrl = key ?? <%= it.clientName %>.queryKeys.<%= it.swrOpName.charAt(3).toLowerCase() + it.swrOpName.slice(4) %>(<% it.parameters.forEach((parameter) => { %><%= parameter.name %>, <% }); %>);\n\n const { data, error, isLoading, mutate } = useSWR<<%~ it.returnType %>>(\n cacheUrl,\n () => <%= it.clientName %>Client.<%= it.name %>(<% it.parameters.forEach((parameter) => { %><%= parameter.name %>, <% }); %>$httpConfig).then((resp) => resp.data),\n config\n );\n\n return { data, isLoading, error, mutate };\n },\n"
|
|
35
34
|
},
|
|
36
|
-
"tsq
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"queryOperation.ejs": "<%\nif (it.jsDocs) {\n const additionalParams = ` * @param $config (optional) Additional configuration for TanStack Query\n * @param $httpConfig (optional) Additional configuration for xior request (actually executes the request)`;\n\n // Replace the closing */ with newline + additional params + closing */\n const modifiedDocs = it.jsDocs.replace(/(\\s*)\\*\\/\\s*$/, `\\n${additionalParams}\\n */`);\n-%>\n<%~ modifiedDocs %>\n<% } else { -%>\n<%~ it.jsDocs %>\n<% } %>\n\nexport function <%= it.rqOpName %><TData = <%~ it.returnType %>, TError = Error>(<% it.parameters.forEach((parameter) => { %>\n <%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,\n <% }); %>\n$config?: Omit<\n UseQueryOptions<<%~ it.returnType %>, TError, TData>,\n 'queryKey' | 'queryFn'\n>,\n $httpConfig?: XiorRequestConfig\n ) {\n return useQuery<<%~ it.returnType %>, TError, TData>({\n queryKey: ['<%= it.clientName %>', '<%= it.opKey %>', <% it.parameters.forEach((parameter) => { %><%= parameter.name %>, <% }); %>],\n queryFn: () => <%= it.clientName %>Client.<%= it.name %>(<% it.parameters.forEach((parameter) => { %>\n<%= parameter.name %>, <% }); %>$httpConfig).then(res => res.data),\n ...$config\n });\n}\n<%= it.rqOpName %>.queryKeys = ['<%= it.clientName %>', '<%= it.opKey %>'];\n"
|
|
35
|
+
"tsq": {
|
|
36
|
+
"baseClient.ejs": "import { type UseQueryOptions, type UseMutationOptions, useQuery, useMutation } from '@tanstack/react-query';\n",
|
|
37
|
+
"client.ejs": "export const <%= it.camelCaseName %>Client = {\n <% it.operations.forEach((operation) => { %>\n<%~ include('operation.ejs', operation); %>\n\n<% }); %>\n};\n\n<%\nvar getOperations = it.operations.filter((o) => o.method === 'GET');\nvar mutationOperations = it.operations.filter((o) => o.method !== 'GET');\n\n// Helper: strip leading \"get\" and capitalise\nfunction toOpName(name) {\n var n = name.toLowerCase().startsWith('get') ? name.substring(3) : name;\n return n.charAt(0).toUpperCase() + n.slice(1);\n}\n\n// Returns a deep copy of operation with any parameter whose name collides with\n// the group object name (clientName) renamed to _<name> to avoid TS shadowing.\nfunction safeOperation(operation, clientName) {\n var safeParams = operation.parameters.map(function(p) {\n return p.name === clientName ? Object.assign({}, p, { name: '_' + p.name }) : p;\n });\n return Object.assign({}, operation, { parameters: safeParams });\n}\n%>\n\nexport const <%= it.camelCaseName %> = {\n queries: {\n<% getOperations.forEach((operation) => {\n var opName = toOpName(operation.name);\n var queryOperation = Object.assign({\n rqOpName: 'use' + opName,\n opKey: it.camelCaseName + opName,\n clientName: it.camelCaseName,\n httpConfigType: it.httpConfigType,\n }, safeOperation(operation, it.camelCaseName));\n%>\n<%~ include('queryOperation.ejs', queryOperation); %>\n\n<% }); %>\n },\n\n mutations: {\n<% mutationOperations.forEach((operation) => {\n var opName = operation.name.charAt(0).toUpperCase() + operation.name.slice(1);\n var mutationOperation = Object.assign({\n mutOpName: 'use' + opName,\n clientName: it.camelCaseName,\n httpConfigType: it.httpConfigType,\n }, safeOperation(operation, it.camelCaseName));\n%>\n<%~ include('mutationOperation.ejs', mutationOperation); %>\n\n<% }); %>\n },\n\n queryKeys: {\n<% getOperations.forEach((operation) => {\n var opName = toOpName(operation.name);\n var keyName = opName.charAt(0).toLowerCase() + opName.slice(1);\n var safeOp = safeOperation(operation, it.camelCaseName);\n%>\n <%= keyName %>: (<% safeOp.parameters.forEach((parameter) => { %><%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %><%= parameter.optional ? (parameter.skippable ? ' | null' : ' | null | undefined') : '' %>, <% }); %>) => ['<%= it.camelCaseName %>', '<%= it.camelCaseName + opName %>'<% safeOp.parameters.forEach((parameter) => { %>, <%= parameter.name %><% }); %>] as const,\n<% }); %>\n },\n};\n",
|
|
38
|
+
"mutationOperation.ejs": "<%\nvar hasParams = it.parameters.length > 0;\n\nvar variablesType;\nif (!hasParams) {\n variablesType = 'void';\n} else {\n var parts = it.parameters.map(function(p) {\n return p.name + (p.skippable ? '?' : '') + ': ' + p.type + (p.optional ? ' | null' : '');\n });\n variablesType = '{ ' + parts.join('; ') + ' }';\n}\n\nvar callArgs = it.parameters.map(function(p) { return 'vars.' + p.name; });\n\nvar baseAdditionalParams = ' * @param $config (optional) Additional configuration for TanStack Query\\n * @param $httpConfig (optional) Additional HTTP client configuration (passed to the underlying ' + it.httpConfigType + ')';\nvar rawDocs = it.jsDocs\n ? it.jsDocs.replace(/(\\s*)\\*\\/\\s*$/, '\\n' + baseAdditionalParams + '\\n */')\n : '';\nvar docs = rawDocs ? rawDocs.replace(/^/gm, ' ') + '\\n' : '';\n%>\n<%~ docs %>\n <%= it.mutOpName %><TData = <%~ it.returnType %>, TError = Error>(\n $config?: UseMutationOptions<<%~ it.returnType %>, TError, <%~ variablesType %>>,\n $httpConfig?: <%= it.httpConfigType %>\n ) {\n return useMutation<<%~ it.returnType %>, TError, <%~ variablesType %>>({\n mutationFn: (<%= hasParams ? 'vars' : '' %>) => <%= it.clientName %>Client.<%= it.name %>(<%= callArgs.join(', ') %><%= callArgs.length > 0 ? ', ' : '' %>$httpConfig).then(res => res.data),\n ...$config\n });\n },\n",
|
|
39
|
+
"queryOperation.ejs": "<%\nvar baseAdditionalParams = ' * @param $config (optional) Additional configuration for TanStack Query\\n * @param $httpConfig (optional) Additional HTTP client configuration (passed to the underlying ' + it.httpConfigType + ')';\nvar rawDocs = it.jsDocs\n ? it.jsDocs.replace(/(\\s*)\\*\\/\\s*$/, '\\n' + baseAdditionalParams + '\\n */')\n : '';\nvar docs = rawDocs ? rawDocs.replace(/^/gm, ' ') + '\\n' : '';\n%>\n<%~ docs %>\n <%= it.rqOpName %><TData = <%~ it.returnType %>, TError = Error>(\n<% it.parameters.forEach((parameter) => { %> <%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %><%= parameter.optional ? (parameter.skippable ? ' | null' : ' | null | undefined') : '' %>,\n<% }); %> $config?: Omit<UseQueryOptions<<%~ it.returnType %>, TError, TData>, 'queryKey' | 'queryFn'>,\n $httpConfig?: <%= it.httpConfigType %>\n ) {\n return useQuery<<%~ it.returnType %>, TError, TData>({\n queryKey: <%= it.clientName %>.queryKeys.<%= it.rqOpName.charAt(3).toLowerCase() + it.rqOpName.slice(4) %>(<% it.parameters.forEach((parameter) => { %><%= parameter.name %>, <% }); %>),\n queryFn: () => <%= it.clientName %>Client.<%= it.name %>(<% it.parameters.forEach((parameter) => { %><%= parameter.name %>, <% }); %>$httpConfig).then(res => res.data),\n ...$config\n });\n },\n"
|
|
42
40
|
},
|
|
43
41
|
"xior": {
|
|
44
42
|
"barrel.ejs": "",
|
|
45
43
|
"baseClient.ejs": "import xior, { type XiorResponse, type XiorRequestConfig, encodeParams } from \"xior\";\n\nexport const http = xior.create({\n baseURL: '<%= it.baseUrl || '' %>',\n paramsSerializer: (params: any) =>\n encodeParams(params, true, null, {\n allowDots: <%= it.allowDots %>,\n arrayFormat: '<%= it.arrayFormat %>',\n }),\n});\n\n",
|
|
46
44
|
"client.ejs": "export const <%= it.camelCaseName %>Client = {\n <% it.operations.forEach((operation) => { %>\n<%~ include('operation.ejs', operation); %>\n\n<% }); %>\n};\n\n",
|
|
47
|
-
"operation.ejs": "<%~ it.jsDocs %>\n\n <%= it.name %>(<% it.parameters.forEach((parameter) => { %>\n<%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,\n <% }); %>\n$config?: XiorRequestConfig\n ): Promise<XiorResponse<<%~ it.returnType %>>> {\n const url = `<%= it.url %>`;\n\n return http.request<<%~ it.returnType %>>({\n url: url,\n method: '<%= it.method %>',\n<% if(it.body) {
|
|
45
|
+
"operation.ejs": "<%~ it.jsDocs %>\n\n <%= it.name %>(<% it.parameters.forEach((parameter) => { %>\n<%= parameter.name %><%= parameter.skippable ? '?' : '' %>: <%~ parameter.type %> <%= parameter.optional ? (parameter.skippable ? '| null' : '| null | undefined') : '' %>,\n <% }); %>\n$config?: XiorRequestConfig\n ): Promise<XiorResponse<<%~ it.returnType %>>> {\n const url = `<%= it.url %>`;\n\n return http.request<<%~ it.returnType %>>({\n url: url,\n method: '<%= it.method %>',\n<% if(it.body) { -%>\n<% if(it.body.contentType === 'urlencoded') { -%>\n data: new URLSearchParams(<%= it.body.name %> as any),\n<% } else { -%>\n data: <%= it.body.name %>,\n<% } -%>\n<% } -%>\n<% if(it.query && it.query.length > 0) { -%>\n params: {\n<% it.query.forEach((parameter) => { -%>\n<% if (it.queryParamObject) { -%>\n '<%= parameter.originalName %>': <%= it.queryParamObject.name %>?.<%= parameter.name %>,\n<% } else { -%>\n '<%= parameter.originalName %>': <%= parameter.name %>,\n<% } -%>\n<% }); -%>\n },\n<% } -%>\n<% if(it.headers && it.headers.length > 0) { -%>\n headers: {\n<% it.headers.forEach((parameter) => { -%>\n<% if (parameter.value) { -%>\n '<%= parameter.originalName %>': '<%= parameter.value %>',\n<% } else { -%>\n '<%= parameter.originalName %>': <%= parameter.name %>,\n<% } -%>\n<% }); -%>\n },\n<% } -%>\n ...$config,\n });\n },\n"
|
|
48
46
|
}
|
|
49
47
|
} ; exports.BUNDLED_TEMPLATES = BUNDLED_TEMPLATES;
|
|
50
48
|
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
var _gen = require('./gen'); var _gen2 = _interopRequireDefault(_gen);
|
|
5
5
|
|
|
6
6
|
var _utils = require('./utils');
|
|
7
|
+
var _templateValidator = require('./utils/templateValidator');
|
|
7
8
|
var _swagger = require('./swagger');
|
|
8
9
|
|
|
9
10
|
/**
|
|
@@ -31,10 +32,19 @@ function verifyOptions(options) {
|
|
|
31
32
|
if (!!options.config === !!options.src) {
|
|
32
33
|
throw new Error('You need to provide either --config or --src parameters');
|
|
33
34
|
}
|
|
35
|
+
if (!!options.mocks !== !!options.testingFramework) {
|
|
36
|
+
throw new Error('--mocks and --testingFramework must be used together');
|
|
37
|
+
}
|
|
38
|
+
if (options.mocks && !options.out) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
'--mocks requires --out to be set, since the mock file needs to import the generated client'
|
|
41
|
+
);
|
|
42
|
+
}
|
|
34
43
|
}
|
|
35
44
|
|
|
36
45
|
function gen(spec, options) {
|
|
37
46
|
if (options.generationMode === 'full') {
|
|
47
|
+
_templateValidator.validateTemplate.call(void 0, options.template);
|
|
38
48
|
_utils.loadAllTemplateFiles.call(void 0, options.template);
|
|
39
49
|
}
|
|
40
50
|
|
|
@@ -83,6 +93,7 @@ function readFile(filePath) {
|
|
|
83
93
|
const {
|
|
84
94
|
allowDots,
|
|
85
95
|
arrayFormat,
|
|
96
|
+
queryParamsAsObject,
|
|
86
97
|
mode,
|
|
87
98
|
schemaStyle,
|
|
88
99
|
enumStyle,
|
|
@@ -90,6 +101,8 @@ function readFile(filePath) {
|
|
|
90
101
|
nullables,
|
|
91
102
|
template,
|
|
92
103
|
queryParamsSerialization = {},
|
|
104
|
+
mocks,
|
|
105
|
+
testingFramework,
|
|
93
106
|
...rest
|
|
94
107
|
} = cliOpts;
|
|
95
108
|
const mergedQueryParamsSerialization = {
|
|
@@ -99,11 +112,12 @@ function readFile(filePath) {
|
|
|
99
112
|
),
|
|
100
113
|
...(allowDots !== undefined ? { allowDots } : {}),
|
|
101
114
|
...(arrayFormat !== undefined ? { arrayFormat } : {}),
|
|
115
|
+
...(queryParamsAsObject !== undefined ? { queryParamsAsObject } : {}),
|
|
102
116
|
};
|
|
103
117
|
|
|
104
118
|
return {
|
|
105
119
|
...rest,
|
|
106
|
-
template: _nullishCoalesce(template, () => ( _swagger.APP_DEFAULTS.template)),
|
|
120
|
+
template: _templateValidator.normalizeTemplate.call(void 0, _nullishCoalesce(template, () => ( _swagger.APP_DEFAULTS.template))),
|
|
107
121
|
servicePrefix: _nullishCoalesce(rest.servicePrefix, () => ( _swagger.APP_DEFAULTS.servicePrefix)),
|
|
108
122
|
nullableStrategy: _nullishCoalesce(_nullishCoalesce(nullables, () => ( rest.nullableStrategy)), () => ( _swagger.APP_DEFAULTS.nullableStrategy)),
|
|
109
123
|
generationMode: _nullishCoalesce(_nullishCoalesce(mode, () => ( rest.generationMode)), () => ( _swagger.APP_DEFAULTS.generationMode)),
|
|
@@ -113,6 +127,8 @@ function readFile(filePath) {
|
|
|
113
127
|
_nullishCoalesce(_nullishCoalesce(enumStyle, () => ( rest.enumDeclarationStyle)), () => ( _swagger.APP_DEFAULTS.enumDeclarationStyle)),
|
|
114
128
|
enumNamesStyle: normalizeEnumNamesStyle(enumNamesStyle),
|
|
115
129
|
queryParamsSerialization: mergedQueryParamsSerialization,
|
|
130
|
+
...(mocks !== undefined ? { mocks } : {}),
|
|
131
|
+
...(testingFramework !== undefined ? { testingFramework } : {}),
|
|
116
132
|
};
|
|
117
133
|
} exports.prepareAppOptions = prepareAppOptions;
|
|
118
134
|
|
|
@@ -53,11 +53,15 @@ function inheritPathParams(op, inheritableParams) {
|
|
|
53
53
|
return;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
if (!op.parameters) {
|
|
57
|
+
op.parameters = [];
|
|
58
|
+
}
|
|
59
|
+
|
|
56
60
|
for (const pathParam of inheritableParams) {
|
|
57
61
|
// If the operation doesn't have a parameter with the same name and in, then add it
|
|
58
62
|
if (
|
|
59
63
|
!op.parameters.some(
|
|
60
|
-
(p) => p.name === pathParam.name && p.in === pathParam.in
|
|
64
|
+
(p) => !('$ref' in p) && (p ).name === pathParam.name && (p ).in === pathParam.in
|
|
61
65
|
)
|
|
62
66
|
) {
|
|
63
67
|
op.parameters.push(Object.assign({}, pathParam));
|
|
@@ -70,9 +74,10 @@ function getPathOperation(
|
|
|
70
74
|
pathInfo,
|
|
71
75
|
spec
|
|
72
76
|
) {
|
|
77
|
+
const pathOp = pathInfo[method];
|
|
73
78
|
const op = Object.assign(
|
|
74
|
-
{ method, path: pathInfo.path, parameters: [], group: getOperationGroupName(
|
|
75
|
-
|
|
79
|
+
{ method, path: pathInfo.path, parameters: [], group: getOperationGroupName(pathOp) },
|
|
80
|
+
pathOp
|
|
76
81
|
);
|
|
77
82
|
|
|
78
83
|
// if there's no explicit operationId given, create one based on the method and path
|
|
@@ -83,13 +88,13 @@ function getPathOperation(
|
|
|
83
88
|
.replace(/[\/}\-]/g, '');
|
|
84
89
|
}
|
|
85
90
|
|
|
86
|
-
const pathLevelParams = _nullishCoalesce(spec.paths[pathInfo.path].parameters, () => ( []));
|
|
91
|
+
const pathLevelParams = _nullishCoalesce(_optionalChain([spec, 'access', _2 => _2.paths, 'optionalAccess', _3 => _3[pathInfo.path], 'optionalAccess', _4 => _4.parameters]), () => ( []));
|
|
87
92
|
|
|
88
93
|
// Replace the path level parameters references with the actual parameters
|
|
89
|
-
replaceReferencedParams(pathLevelParams, _nullishCoalesce(_optionalChain([spec, 'access',
|
|
94
|
+
replaceReferencedParams(pathLevelParams, _nullishCoalesce(_optionalChain([spec, 'access', _5 => _5.components, 'optionalAccess', _6 => _6.parameters]), () => ( {})));
|
|
90
95
|
|
|
91
96
|
// Replace the operation parameters references with the actual parameters
|
|
92
|
-
replaceReferencedParams(op.parameters, _nullishCoalesce(_optionalChain([spec, 'access',
|
|
97
|
+
replaceReferencedParams(op.parameters, _nullishCoalesce(_optionalChain([spec, 'access', _7 => _7.components, 'optionalAccess', _8 => _8.parameters]), () => ( {})));
|
|
93
98
|
|
|
94
99
|
// At this stage path level parameters are already replaced with the actual parameters
|
|
95
100
|
inheritPathParams(op, pathLevelParams );
|
|
@@ -103,7 +108,7 @@ function getPathOperation(
|
|
|
103
108
|
* Removes invalid characters and ensures the name doesn't start with a number.
|
|
104
109
|
*/
|
|
105
110
|
function getOperationGroupName(op) {
|
|
106
|
-
let name = _optionalChain([op, 'access',
|
|
111
|
+
let name = _optionalChain([op, 'access', _9 => _9.tags, 'optionalAccess', _10 => _10.length]) ? op.tags[0] : 'default';
|
|
107
112
|
name = name.replace(/[^$_a-z0-9]+/gi, '');
|
|
108
113
|
return name.replace(/^[0-9]+/m, '');
|
|
109
114
|
}
|
|
@@ -117,6 +122,10 @@ function replaceReferencedParams(
|
|
|
117
122
|
parameters,
|
|
118
123
|
componentParams
|
|
119
124
|
) {
|
|
125
|
+
if (!parameters || !componentParams) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
120
129
|
for (let index = 0; index < parameters.length; index++) {
|
|
121
130
|
const param = parameters[index];
|
|
122
131
|
|
|
@@ -25,7 +25,7 @@ var _utils = require('../utils/utils');
|
|
|
25
25
|
return unknownType;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
return getTypeFromSchemaResolved(param.schema, options, `${context}.schema`);
|
|
28
|
+
return getTypeFromSchemaResolved(param.schema , options, `${context}.schema`);
|
|
29
29
|
} exports.getParameterType = getParameterType;
|
|
30
30
|
|
|
31
31
|
/**
|
|
@@ -172,7 +172,7 @@ function getTypeFromSchemaInternal(
|
|
|
172
172
|
return getTypeFromObject(schema, options, undefined, context);
|
|
173
173
|
}
|
|
174
174
|
if ('enum' in schema) {
|
|
175
|
-
return `${schema.enum.map((v) => JSON.stringify(v)).join(' | ')}`;
|
|
175
|
+
return `${(_nullishCoalesce(schema.enum, () => ( []))).map((v) => JSON.stringify(v)).join(' | ')}`;
|
|
176
176
|
}
|
|
177
177
|
if (schema.type === 'integer' || schema.type === 'number') {
|
|
178
178
|
return 'number';
|
|
@@ -368,25 +368,26 @@ function isRequiredOnlyCompositeBranch(schema) {
|
|
|
368
368
|
* It is used only for `allOf` property, as it enforces extending types.
|
|
369
369
|
*/
|
|
370
370
|
function getRefCompositeTypes(schema) {
|
|
371
|
-
return schema.allOf
|
|
371
|
+
return (_nullishCoalesce(schema.allOf, () => ( [])))
|
|
372
372
|
.filter((v) => '$ref' in v)
|
|
373
373
|
.map((s) => getSafeIdentifier(s.$ref.split('/').pop()));
|
|
374
374
|
} exports.getRefCompositeTypes = getRefCompositeTypes;
|
|
375
375
|
|
|
376
376
|
/** Default values applied to every field of AppOptions that has a default. */
|
|
377
377
|
const APP_DEFAULTS = {
|
|
378
|
-
template: 'axios',
|
|
378
|
+
template: 'axios' ,
|
|
379
379
|
servicePrefix: '',
|
|
380
|
-
nullableStrategy: 'ignore',
|
|
381
|
-
generationMode: 'full',
|
|
382
|
-
schemaDeclarationStyle: 'interface',
|
|
383
|
-
enumDeclarationStyle: 'union',
|
|
384
|
-
enumNamesStyle: 'original',
|
|
380
|
+
nullableStrategy: 'ignore' ,
|
|
381
|
+
generationMode: 'full' ,
|
|
382
|
+
schemaDeclarationStyle: 'interface' ,
|
|
383
|
+
enumDeclarationStyle: 'union' ,
|
|
384
|
+
enumNamesStyle: 'original' ,
|
|
385
385
|
queryParamsSerialization: {
|
|
386
386
|
allowDots: true,
|
|
387
|
-
arrayFormat: 'repeat',
|
|
387
|
+
arrayFormat: 'repeat' ,
|
|
388
|
+
queryParamsAsObject: false ,
|
|
388
389
|
},
|
|
389
|
-
}; exports.APP_DEFAULTS = APP_DEFAULTS;
|
|
390
|
+
} ; exports.APP_DEFAULTS = APP_DEFAULTS;
|
|
390
391
|
|
|
391
392
|
/**
|
|
392
393
|
* Fills in all AppOptions defaults for a partial ClientOptions object.
|
package/dist/types.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { OpenAPIV3 as OA3 } from 'openapi-types';
|
|
|
2
2
|
interface QueryParamsSerializationOptions {
|
|
3
3
|
allowDots?: boolean;
|
|
4
4
|
arrayFormat?: ArrayFormat;
|
|
5
|
+
queryParamsAsObject?: boolean | number;
|
|
5
6
|
}
|
|
6
7
|
export interface ClientOptions {
|
|
7
8
|
/**
|
|
@@ -11,8 +12,14 @@ export interface ClientOptions {
|
|
|
11
12
|
src: string | object;
|
|
12
13
|
/** Path to the file which will contain generated TypeScript code */
|
|
13
14
|
out?: string;
|
|
14
|
-
/**
|
|
15
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Template to be used for code generation.
|
|
17
|
+
* Can be a single L1 template name (e.g. "axios"), a single L2 template name
|
|
18
|
+
* (e.g. "swr" — defaults to "fetch" as the L1), or a 2-element tuple of
|
|
19
|
+
* [L2, L1] (e.g. ["swr", "axios"]).
|
|
20
|
+
* Custom filesystem paths are also accepted in any position.
|
|
21
|
+
*/
|
|
22
|
+
template: TemplateInput;
|
|
16
23
|
baseUrl?: string;
|
|
17
24
|
preferAny?: boolean;
|
|
18
25
|
/** Skip deprecated operations. When enabled, deprecated operations will be skipped from the generated code */
|
|
@@ -42,6 +49,26 @@ export interface ClientOptions {
|
|
|
42
49
|
* - `'PascalCase'` — convert values to PascalCase (e.g. `OrgName = "org name"`)
|
|
43
50
|
*/
|
|
44
51
|
enumNamesStyle?: EnumNamesStyle;
|
|
52
|
+
/**
|
|
53
|
+
* Prepends `'use client';` as the very first line of the generated file.
|
|
54
|
+
* Required for Next.js App Router when using SWR or TanStack Query hooks,
|
|
55
|
+
* which can only run in Client Components.
|
|
56
|
+
* Has no effect and should not be used with non-RSC environments.
|
|
57
|
+
*/
|
|
58
|
+
useClient?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Output path for the generated mock/stub file. Requires `testingFramework`
|
|
61
|
+
* and `out` to also be set. When provided, a companion mock file is generated
|
|
62
|
+
* alongside the main client, exporting typed spy stubs for every operation.
|
|
63
|
+
*/
|
|
64
|
+
mocks?: string;
|
|
65
|
+
/**
|
|
66
|
+
* The test framework to use for generated mock stubs.
|
|
67
|
+
* - `'vitest'` — uses `vi.fn()` from `vitest`
|
|
68
|
+
* - `'jest'` — uses `jest.fn()` from `@jest/globals`
|
|
69
|
+
* Requires `mocks` and `out` to also be set.
|
|
70
|
+
*/
|
|
71
|
+
testingFramework?: TestingFramework;
|
|
45
72
|
/** Offers ability to adjust the OpenAPI spec before it is processed */
|
|
46
73
|
modifiers?: {
|
|
47
74
|
/** Global-level modifiers for parameter with a given name */
|
|
@@ -53,18 +80,37 @@ export interface ClientOptions {
|
|
|
53
80
|
export interface CliOptions extends Omit<FullAppOptions, 'enumNamesStyle'> {
|
|
54
81
|
allowDots?: boolean;
|
|
55
82
|
arrayFormat?: ArrayFormat;
|
|
83
|
+
queryParamsAsObject?: boolean | number;
|
|
56
84
|
mode?: GenerationMode;
|
|
57
85
|
schemaStyle?: SchemaDeclarationStyle;
|
|
58
86
|
enumStyle?: EnumDeclarationStyle;
|
|
59
87
|
/** Accepts 'original', 'PascalCase', or 'pascal' (normalized to 'PascalCase') */
|
|
60
88
|
enumNamesStyle?: string;
|
|
61
89
|
nullables?: NullableStrategy;
|
|
90
|
+
mocks?: string;
|
|
91
|
+
testingFramework?: TestingFramework;
|
|
62
92
|
}
|
|
63
93
|
export interface FullAppOptions extends ClientOptions {
|
|
64
94
|
/** Path to the configuration file that contains actual config to be used */
|
|
65
95
|
config?: string;
|
|
66
96
|
}
|
|
67
|
-
|
|
97
|
+
/** HTTP client templates (standalone, no reactive layer) */
|
|
98
|
+
export type L1Template = 'axios' | 'fetch' | 'xior' | 'ng1' | 'ng2';
|
|
99
|
+
/** Reactive query layer templates (must be composed with an L1 template) */
|
|
100
|
+
export type L2Template = 'swr' | 'tsq';
|
|
101
|
+
/** Any named built-in template */
|
|
102
|
+
export type Template = L1Template | L2Template;
|
|
103
|
+
/**
|
|
104
|
+
* What the user may supply as a `template` value:
|
|
105
|
+
* - a single template name or custom path string
|
|
106
|
+
* - a [L2, L1] pair (names or custom paths)
|
|
107
|
+
*/
|
|
108
|
+
export type TemplateInput = Template | string | [string, string];
|
|
109
|
+
/**
|
|
110
|
+
* After normalization inside prepareAppOptions the template is always
|
|
111
|
+
* either a single L1 string or a resolved [L2, L1] pair.
|
|
112
|
+
*/
|
|
113
|
+
export type ResolvedTemplate = L1Template | string | [string, string];
|
|
68
114
|
export type HttpMethod = 'get' | 'put' | 'post' | 'delete' | 'options' | 'head' | 'patch';
|
|
69
115
|
export type DateSupport = 'string' | 'Date';
|
|
70
116
|
export type ArrayFormat = 'indices' | 'repeat' | 'brackets';
|
|
@@ -73,13 +119,14 @@ export type GenerationMode = 'full' | 'schemas';
|
|
|
73
119
|
export type SchemaDeclarationStyle = 'interface' | 'type';
|
|
74
120
|
export type EnumDeclarationStyle = 'union' | 'enum';
|
|
75
121
|
export type EnumNamesStyle = 'original' | 'PascalCase';
|
|
122
|
+
export type TestingFramework = 'vitest' | 'jest';
|
|
76
123
|
/**
|
|
77
124
|
* Internal options type used throughout the app after `prepareAppOptions` has run.
|
|
78
125
|
* All fields that have defaults are required here so the rest of the codebase never
|
|
79
126
|
* needs to perform its own `?? fallback` logic.
|
|
80
127
|
*/
|
|
81
128
|
export interface AppOptions extends ClientOptions {
|
|
82
|
-
template:
|
|
129
|
+
template: ResolvedTemplate;
|
|
83
130
|
servicePrefix: string;
|
|
84
131
|
nullableStrategy: NullableStrategy;
|
|
85
132
|
generationMode: GenerationMode;
|
|
@@ -89,7 +136,10 @@ export interface AppOptions extends ClientOptions {
|
|
|
89
136
|
queryParamsSerialization: {
|
|
90
137
|
allowDots: boolean;
|
|
91
138
|
arrayFormat: ArrayFormat;
|
|
139
|
+
queryParamsAsObject: boolean | number;
|
|
92
140
|
};
|
|
141
|
+
mocks?: string;
|
|
142
|
+
testingFramework?: TestingFramework;
|
|
93
143
|
}
|
|
94
144
|
/**
|
|
95
145
|
* Local type that represent Operation as understood by Swaggie
|
|
@@ -97,6 +147,6 @@ export interface AppOptions extends ClientOptions {
|
|
|
97
147
|
export interface ApiOperation extends OA3.OperationObject {
|
|
98
148
|
method: HttpMethod;
|
|
99
149
|
path: string;
|
|
100
|
-
group: string;
|
|
150
|
+
group: string | null;
|
|
101
151
|
}
|
|
102
152
|
export {};
|
|
@@ -35,9 +35,7 @@ async function loadFromUrl(url) {
|
|
|
35
35
|
|
|
36
36
|
async function readLocalFile(filePath) {
|
|
37
37
|
const contents = await new Promise((res, rej) =>
|
|
38
|
-
_nodefs2.default.readFile(filePath, 'utf8', (err, loadedContents) =>
|
|
39
|
-
err ? rej(err) : res(loadedContents)
|
|
40
|
-
)
|
|
38
|
+
_nodefs2.default.readFile(filePath, 'utf8', (err, loadedContents) => (err ? rej(err) : res(loadedContents)))
|
|
41
39
|
);
|
|
42
40
|
const spec = parseFileContents(contents , filePath) ;
|
|
43
41
|
|