@accelbyte/codegen 1.0.0-alpha.1 → 1.0.0-alpha.12
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/LICENSE +19 -0
- package/PATCHING.md +137 -0
- package/README.md +27 -131
- package/dist/accelbyte-codegen.js +354 -239
- package/dist/accelbyte-codegen.js.map +1 -1
- package/dist/accelbyte-codegen.mjs +321 -198
- package/dist/accelbyte-codegen.mjs.map +1 -1
- package/package.json +8 -6
- package/CHANGELOG.md +0 -40
|
@@ -78,15 +78,15 @@ const generateImports = (body, importStatements) => {
|
|
|
78
78
|
${importStatements.sort().join("\n")}`;
|
|
79
79
|
};
|
|
80
80
|
const templateClass = (className, body, importStatements) => `/**
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
* DON'T EDIT THIS FILE, it is AUTO GENERATED
|
|
82
|
+
*/
|
|
83
|
+
${generateImports(body, importStatements)}
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
export class ${className} {
|
|
86
|
+
// @ts-ignore
|
|
87
|
+
constructor(private axiosInstance: AxiosInstance, private namespace: string, private cache = false) {}
|
|
88
88
|
${body}
|
|
89
|
-
|
|
89
|
+
}
|
|
90
90
|
`;
|
|
91
91
|
|
|
92
92
|
const templateJsdocFile = (apiName, body) => `
|
|
@@ -98,44 +98,34 @@ ${body}
|
|
|
98
98
|
`.replace(/, \)/g, ")").trim();
|
|
99
99
|
|
|
100
100
|
class ParserUtils {
|
|
101
|
-
static parseQueryParamAttributeDefault = (
|
|
102
|
-
const attrName = name.slice(name.lastIndexOf(".") + 1);
|
|
101
|
+
static parseQueryParamAttributeDefault = (definition) => {
|
|
102
|
+
const attrName = definition.name.slice(definition.name.lastIndexOf(".") + 1);
|
|
103
103
|
const defaultValue = definition.type === "string" ? `'${definition.default}'` : definition.default;
|
|
104
104
|
return `${attrName}: ${defaultValue}`;
|
|
105
105
|
};
|
|
106
|
-
static parseType = (
|
|
107
|
-
if (type === "integer")
|
|
106
|
+
static parseType = (pathParam) => {
|
|
107
|
+
if (pathParam.type === "int" || pathParam.type === "integer" || pathParam?.schema?.type === "integer")
|
|
108
108
|
return "number";
|
|
109
|
-
if (type === "array")
|
|
110
|
-
return "any[]
|
|
111
|
-
|
|
109
|
+
if (pathParam.type === "array")
|
|
110
|
+
return `${pathParam.items.type ?? "any"}[]`;
|
|
111
|
+
if (pathParam?.schema?.type === "array")
|
|
112
|
+
return `${pathParam.schema.items.type ?? "any"}[]`;
|
|
113
|
+
if (pathParam?.schema?.type)
|
|
114
|
+
return pathParam.schema.type;
|
|
115
|
+
return pathParam.type;
|
|
112
116
|
};
|
|
113
117
|
static parseQueryParamsType = (queryParams) => {
|
|
114
|
-
return queryParams.map((
|
|
118
|
+
return queryParams.map((queryParam) => ParserUtils.parseAttributeType(queryParam)).join(",");
|
|
115
119
|
};
|
|
116
120
|
static isAnyQueryParamRequired = (queryParams) => {
|
|
117
|
-
queryParams.
|
|
118
|
-
if (p.required) {
|
|
119
|
-
return true;
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
return false;
|
|
121
|
+
return queryParams.some((queryParam) => queryParam.required);
|
|
123
122
|
};
|
|
124
123
|
static parseQueryParamsDefault = (queryParams) => {
|
|
125
|
-
const result = queryParams.filter((
|
|
124
|
+
const result = queryParams.filter((queryParam) => !!queryParam.default && !queryParam.required).map(ParserUtils.parseQueryParamAttributeDefault).join(",");
|
|
126
125
|
return result ? `${result},` : "";
|
|
127
126
|
};
|
|
128
127
|
static parseBodyParamsImports = (bodyParams) => {
|
|
129
|
-
|
|
130
|
-
if (p?.schema?.$ref)
|
|
131
|
-
return ParserUtils.parseRefImport(p.schema.$ref, p);
|
|
132
|
-
if (p?.schema?.items?.$ref)
|
|
133
|
-
return ParserUtils.parseRefImport(p.schema.items.$ref, p);
|
|
134
|
-
if (p?.$ref)
|
|
135
|
-
return ParserUtils.parseRefImport(p.$ref, p);
|
|
136
|
-
return null;
|
|
137
|
-
}).filter((p) => !!p);
|
|
138
|
-
return ret;
|
|
128
|
+
return bodyParams.map(ParserUtils.parseRefImport).filter(Boolean);
|
|
139
129
|
};
|
|
140
130
|
static parseImportDir = ($ref) => {
|
|
141
131
|
let ref = $ref.replace(".", "/");
|
|
@@ -148,7 +138,11 @@ class ParserUtils {
|
|
|
148
138
|
return ref.slice(0, ref.lastIndexOf("/")).replace("#", ".");
|
|
149
139
|
}
|
|
150
140
|
};
|
|
151
|
-
static parseRefImport = (
|
|
141
|
+
static parseRefImport = (bodyParam) => {
|
|
142
|
+
const $ref = bodyParam?.schema?.$ref || bodyParam?.schema?.items?.$ref;
|
|
143
|
+
if (!$ref) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
152
146
|
const type = ParserUtils.parseRefType($ref);
|
|
153
147
|
return `import { ${type} } from './definitions/${type}'`;
|
|
154
148
|
};
|
|
@@ -158,60 +152,72 @@ class ParserUtils {
|
|
|
158
152
|
ref = ref.slice(0, -1);
|
|
159
153
|
}
|
|
160
154
|
const val = ref.slice(ref.lastIndexOf("/") + 1);
|
|
161
|
-
return _.upperFirst(_.camelCase(val));
|
|
155
|
+
return _.upperFirst(_.camelCase(val)).replace(/( \w)/g, (group) => group.replace(" ", "").toUpperCase());
|
|
162
156
|
};
|
|
163
|
-
static parseAttributeType = (
|
|
157
|
+
static parseAttributeType = (definition) => {
|
|
164
158
|
const required = definition.required ? "" : "?";
|
|
165
|
-
const attrName = name.slice(name.lastIndexOf(".") + 1);
|
|
166
|
-
if (definition.
|
|
167
|
-
const enums = definition.
|
|
159
|
+
const attrName = definition.name.slice(definition.name.lastIndexOf(".") + 1);
|
|
160
|
+
if (definition.enum) {
|
|
161
|
+
const enums = definition.enum.map((enm) => definition.type === "string" ? `'${enm}'` : enm).join(" | ");
|
|
168
162
|
return `${attrName}${required}: ${enums}`;
|
|
169
163
|
}
|
|
170
|
-
if (definition.type && definition
|
|
164
|
+
if (definition.type && ParserUtils.parseType(definition) === "number") {
|
|
165
|
+
return `${attrName}${required}: number`;
|
|
166
|
+
}
|
|
167
|
+
if (definition?.schema?.type && ParserUtils.parseType(definition) === "number") {
|
|
171
168
|
return `${attrName}${required}: number`;
|
|
172
169
|
}
|
|
173
170
|
if (definition.type && definition.type === "array") {
|
|
174
171
|
return `${attrName}${required}: ${definition.items.type ?? "any"}[]`;
|
|
175
172
|
}
|
|
173
|
+
if (definition?.schema?.type && definition.schema.type === "array") {
|
|
174
|
+
return `${attrName}${required}: ${definition.schema.items.type ?? "any"}[]`;
|
|
175
|
+
}
|
|
176
176
|
if (definition.type && definition.type) {
|
|
177
177
|
return `${attrName}${required}: ${definition.type} | null`;
|
|
178
178
|
}
|
|
179
|
+
if (definition?.schema?.type && definition.schema.type) {
|
|
180
|
+
return `${attrName}${required}: ${definition.schema.type} | null`;
|
|
181
|
+
}
|
|
179
182
|
return `${attrName}${required}: any`;
|
|
180
183
|
};
|
|
181
184
|
static parseBodyParamsType = (bodyParams) => {
|
|
182
|
-
const [
|
|
183
|
-
if (!
|
|
185
|
+
const [bodyParam] = bodyParams;
|
|
186
|
+
if (!bodyParam)
|
|
184
187
|
return null;
|
|
185
|
-
if (bodyParams.length > 0 &&
|
|
186
|
-
let retBodyParams = `{${bodyParams.map((
|
|
188
|
+
if (bodyParams.length > 0 && bodyParam?.name !== "body" && !bodyParam?.schema) {
|
|
189
|
+
let retBodyParams = `{${bodyParams.map((bodyParam2) => ParserUtils.parseAttributeType(bodyParam2)).join(",")}}`;
|
|
187
190
|
retBodyParams = retBodyParams.replace("file?: file", "file?: File");
|
|
188
191
|
return retBodyParams;
|
|
189
192
|
}
|
|
190
|
-
if (
|
|
191
|
-
return `${
|
|
193
|
+
if (bodyParam?.schema?.type === "array" && !bodyParam?.schema?.items?.$ref) {
|
|
194
|
+
return `${bodyParam.schema.items.type ?? "any"}[]`;
|
|
192
195
|
}
|
|
193
|
-
if (
|
|
194
|
-
return `${ParserUtils.parseRefType(
|
|
196
|
+
if (bodyParam?.schema?.type === "array" && bodyParam?.schema?.items?.$ref) {
|
|
197
|
+
return `${ParserUtils.parseRefType(bodyParam.schema.items.$ref)}[]`;
|
|
195
198
|
}
|
|
196
|
-
if (
|
|
197
|
-
return ParserUtils.parseRefType(
|
|
199
|
+
if (bodyParam?.schema.$ref) {
|
|
200
|
+
return ParserUtils.parseRefType(bodyParam.schema.$ref);
|
|
198
201
|
}
|
|
199
|
-
if (
|
|
202
|
+
if (bodyParam?.schema?.additionalProperties?.type === "object") {
|
|
200
203
|
return "any";
|
|
201
204
|
}
|
|
202
205
|
return null;
|
|
203
206
|
};
|
|
204
|
-
static get2xxResponse(methodEntity
|
|
207
|
+
static get2xxResponse(methodEntity) {
|
|
205
208
|
const keys = Object.keys(methodEntity);
|
|
206
209
|
let responseClass = null;
|
|
207
210
|
keys.forEach((key) => {
|
|
208
211
|
if (String(key).startsWith("2")) {
|
|
209
212
|
const sch = methodEntity[key].schema;
|
|
213
|
+
const schV3 = methodEntity[key].content && methodEntity[key].content["application/json"].schema;
|
|
210
214
|
if (sch?.$ref) {
|
|
211
215
|
responseClass = ParserUtils.parseRefType(sch.$ref);
|
|
212
216
|
} else if (sch?.type === "array" && sch.items?.$ref) {
|
|
213
217
|
responseClass = ParserUtils.parseRefType(sch.items.$ref);
|
|
214
218
|
responseClass = `${responseClass}Array`;
|
|
219
|
+
} else if (schV3?.$ref) {
|
|
220
|
+
responseClass = ParserUtils.parseRefType(schV3.$ref);
|
|
215
221
|
} else ;
|
|
216
222
|
}
|
|
217
223
|
});
|
|
@@ -226,24 +232,23 @@ class ParserUtils {
|
|
|
226
232
|
}
|
|
227
233
|
return contentTypes.includes("application/x-www-form-urlencoded");
|
|
228
234
|
}
|
|
229
|
-
static
|
|
230
|
-
if (!
|
|
235
|
+
static filterPathParams(parameters) {
|
|
236
|
+
if (!parameters) {
|
|
231
237
|
return [];
|
|
232
238
|
}
|
|
233
|
-
|
|
234
|
-
for (const p of parametersArray) {
|
|
235
|
-
if (p.in === "path") {
|
|
236
|
-
res.push(p);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
return res;
|
|
239
|
+
return parameters.filter((parameter) => parameter.in === "path");
|
|
240
240
|
}
|
|
241
|
-
static generateClassMethod(
|
|
241
|
+
static generateClassMethod({
|
|
242
|
+
path: path2,
|
|
243
|
+
endpoint,
|
|
244
|
+
httpMethod,
|
|
245
|
+
className
|
|
246
|
+
}) {
|
|
242
247
|
let replacedIdsPath = path2;
|
|
243
|
-
if (
|
|
244
|
-
for (const
|
|
245
|
-
if (
|
|
246
|
-
replacedIdsPath = replacedIdsPath.replace("{" +
|
|
248
|
+
if (endpoint.parameters) {
|
|
249
|
+
for (const parameter of endpoint.parameters) {
|
|
250
|
+
if (parameter.in === "path") {
|
|
251
|
+
replacedIdsPath = replacedIdsPath.replace("{" + parameter.name + "}", "By" + ParserUtils.toTitleCaseWord(parameter.name));
|
|
247
252
|
replacedIdsPath = replacedIdsPath.replace("/iam", "");
|
|
248
253
|
replacedIdsPath = replacedIdsPath.replace("/odin-config", "");
|
|
249
254
|
}
|
|
@@ -251,8 +256,8 @@ class ParserUtils {
|
|
|
251
256
|
}
|
|
252
257
|
let classMethod = httpMethod + "/" + replacedIdsPath;
|
|
253
258
|
classMethod = _.camelCase(classMethod);
|
|
254
|
-
classMethod = classMethod.replace("PublicNamespacesByNamespace", "");
|
|
255
|
-
classMethod = classMethod.replace("AdminNamespacesByNamespace", "
|
|
259
|
+
classMethod = classMethod.replace("PublicNamespacesByNamespace", "Ns");
|
|
260
|
+
classMethod = classMethod.replace("AdminNamespacesByNamespace", "AdminNs");
|
|
256
261
|
const searchWord = "NamespacesByNamespace";
|
|
257
262
|
const nsExistInsideMethod = classMethod.indexOf(searchWord) > 0 && classMethod.indexOf(searchWord) + searchWord.length < classMethod.length;
|
|
258
263
|
const excludedClasses = ["Policies"];
|
|
@@ -261,24 +266,17 @@ class ParserUtils {
|
|
|
261
266
|
}
|
|
262
267
|
return classMethod;
|
|
263
268
|
}
|
|
264
|
-
static
|
|
265
|
-
if (
|
|
266
|
-
return
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
return parametersArray.filter((p) => p.in === "body" || p.in === "formData");
|
|
269
|
+
static filterBodyParams(parameters) {
|
|
270
|
+
if (Array.isArray(parameters) && parameters.length > 0) {
|
|
271
|
+
return parameters.filter((parameter) => parameter.in === "body" || parameter.in === "formData");
|
|
272
|
+
}
|
|
273
|
+
return [];
|
|
270
274
|
}
|
|
271
|
-
static
|
|
272
|
-
if (!
|
|
275
|
+
static filterQueryParameters(parameters) {
|
|
276
|
+
if (!parameters) {
|
|
273
277
|
return [];
|
|
274
278
|
}
|
|
275
|
-
|
|
276
|
-
for (const p of parametersArray) {
|
|
277
|
-
if (p.in === "query") {
|
|
278
|
-
res.push(p);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
return res;
|
|
279
|
+
return parameters.filter((parameter) => parameter.in === "query");
|
|
282
280
|
}
|
|
283
281
|
static mkdirIfNotExist(dirToCreate) {
|
|
284
282
|
if (!fs__default.existsSync(dirToCreate)) {
|
|
@@ -334,16 +332,32 @@ class ParserUtils {
|
|
|
334
332
|
}
|
|
335
333
|
const swaggerContent = JSON.parse(fs__default.readFileSync(swaggerFilePath, "utf8"));
|
|
336
334
|
const swaggerPatchFileContent = JSON.parse(fs__default.readFileSync(possibleSwaggerPatchFilePath, "utf8"));
|
|
335
|
+
for (const patchEntry of swaggerPatchFileContent) {
|
|
336
|
+
const segments = patchEntry.path.split("/").filter(Boolean);
|
|
337
|
+
let currentNode = swaggerContent;
|
|
338
|
+
let aggregatedPath = "";
|
|
339
|
+
for (let i = 0; i < segments.length; i++) {
|
|
340
|
+
const segment = segments[i];
|
|
341
|
+
aggregatedPath += `/${segment}`;
|
|
342
|
+
const effectiveSegment = segment.replace(/(~1)/g, "/").replace(/(~0)/g, "~");
|
|
343
|
+
if (!currentNode[effectiveSegment]) {
|
|
344
|
+
if (i + 1 === segments.length && patchEntry.op === "add") ; else {
|
|
345
|
+
throw new Error([
|
|
346
|
+
`JSON patch error: operation "${patchEntry.op}" on path "${aggregatedPath}" fails because the path doesn't exist in ${swaggerFilePath}. This may be caused by:
|
|
347
|
+
`,
|
|
348
|
+
"1. The related service has patched the service, so patch is no longer needed.",
|
|
349
|
+
"2. There is a breaking change on the service that causes the path to change.\n",
|
|
350
|
+
`In any case, revisit this file: "${possibleSwaggerPatchFilePath}", then try again.
|
|
351
|
+
`
|
|
352
|
+
].join("\n"));
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
currentNode = currentNode[effectiveSegment];
|
|
356
|
+
}
|
|
357
|
+
}
|
|
337
358
|
const { newDocument } = applyPatch(swaggerContent, swaggerPatchFileContent);
|
|
338
359
|
fs__default.writeFileSync(swaggerPatchedFilePath, JSON.stringify(newDocument, null, 2));
|
|
339
360
|
}
|
|
340
|
-
static mapKeys(map_) {
|
|
341
|
-
const methods_ = [];
|
|
342
|
-
for (const m in map_) {
|
|
343
|
-
methods_.push(m);
|
|
344
|
-
}
|
|
345
|
-
return methods_;
|
|
346
|
-
}
|
|
347
361
|
static getRelativePathToWebSdkSrcFolder(srcFolder, targetSrcFolder) {
|
|
348
362
|
const replaced = srcFolder.replace(/\\/g, "/");
|
|
349
363
|
return replaced.replace(/\\/g, "/").replace(targetSrcFolder, "./");
|
|
@@ -359,7 +373,104 @@ ${content}`;
|
|
|
359
373
|
};
|
|
360
374
|
}
|
|
361
375
|
|
|
362
|
-
const
|
|
376
|
+
const Schema = z.object({
|
|
377
|
+
$ref: z.string().nullish(),
|
|
378
|
+
type: z.union([z.literal("array"), z.literal("object"), z.literal("file"), z.literal("string"), z.literal("boolean"), z.literal("integer")]).nullish(),
|
|
379
|
+
items: z.object({
|
|
380
|
+
$ref: z.string().nullish(),
|
|
381
|
+
type: z.string().nullish()
|
|
382
|
+
}).nullish(),
|
|
383
|
+
properties: z.union([z.array(z.string()).nullish(), z.record(z.object({ type: z.string() })).nullish()]),
|
|
384
|
+
description: z.string().nullish(),
|
|
385
|
+
additionalProperties: z.object({
|
|
386
|
+
type: z.string().nullish()
|
|
387
|
+
}).nullish()
|
|
388
|
+
});
|
|
389
|
+
const Definition = z.object({
|
|
390
|
+
required: z.array(z.string()).nullish(),
|
|
391
|
+
properties: z.record(z.object({
|
|
392
|
+
type: z.string()
|
|
393
|
+
})).nullish()
|
|
394
|
+
});
|
|
395
|
+
const Definitions = z.record(Definition);
|
|
396
|
+
const EndpointParametersType = z.enum(["apiKey", "boolean", "int", "integer", "number", "string", "array", "file"]);
|
|
397
|
+
const EndpointParametersIn = z.enum(["body", "formData", "header", "path", "query"]);
|
|
398
|
+
const EndpointParameters = z.object({
|
|
399
|
+
type: EndpointParametersType.nullish(),
|
|
400
|
+
description: z.string().nullish(),
|
|
401
|
+
name: z.string(),
|
|
402
|
+
in: EndpointParametersIn,
|
|
403
|
+
required: z.boolean().nullish(),
|
|
404
|
+
schema: Schema.nullish(),
|
|
405
|
+
default: z.union([z.boolean(), z.string(), z.number()]).nullish(),
|
|
406
|
+
enum: z.array(z.union([z.boolean(), z.string(), z.number()])).nullish(),
|
|
407
|
+
items: z.object({
|
|
408
|
+
type: z.string()
|
|
409
|
+
}).nullish()
|
|
410
|
+
});
|
|
411
|
+
const Endpoint = z.object({
|
|
412
|
+
description: z.string().nullish(),
|
|
413
|
+
consumes: z.array(z.string()).nullish(),
|
|
414
|
+
produces: z.array(z.string()).nullish(),
|
|
415
|
+
tags: z.array(z.string()).nullish(),
|
|
416
|
+
summary: z.string().nullish(),
|
|
417
|
+
operationId: z.string(),
|
|
418
|
+
deprecated: z.boolean().nullish(),
|
|
419
|
+
responses: z.record(z.object({
|
|
420
|
+
description: z.string().nullish(),
|
|
421
|
+
schema: Schema.nullish(),
|
|
422
|
+
content: z.object({
|
|
423
|
+
"application/json": z.object({
|
|
424
|
+
schema: Schema.nullish()
|
|
425
|
+
})
|
|
426
|
+
}).nullish()
|
|
427
|
+
})),
|
|
428
|
+
parameters: z.array(EndpointParameters).nullish(),
|
|
429
|
+
requestBody: z.object({
|
|
430
|
+
required: z.boolean(),
|
|
431
|
+
content: z.object({
|
|
432
|
+
"application/json": z.object({
|
|
433
|
+
schema: Schema.nullish()
|
|
434
|
+
})
|
|
435
|
+
}).nullish()
|
|
436
|
+
}).nullish()
|
|
437
|
+
});
|
|
438
|
+
const Operation = z.object({
|
|
439
|
+
get: Endpoint.nullish(),
|
|
440
|
+
post: Endpoint.nullish(),
|
|
441
|
+
patch: Endpoint.nullish(),
|
|
442
|
+
delete: Endpoint.nullish(),
|
|
443
|
+
put: Endpoint.nullish()
|
|
444
|
+
});
|
|
445
|
+
const Paths = z.record(Operation);
|
|
446
|
+
z.object({
|
|
447
|
+
paths: Paths,
|
|
448
|
+
definitions: Definitions,
|
|
449
|
+
basePath: z.string(),
|
|
450
|
+
info: z.object({
|
|
451
|
+
description: z.string(),
|
|
452
|
+
title: z.string(),
|
|
453
|
+
contact: z.object({
|
|
454
|
+
name: z.string(),
|
|
455
|
+
url: z.string(),
|
|
456
|
+
email: z.string()
|
|
457
|
+
}),
|
|
458
|
+
version: z.string()
|
|
459
|
+
}),
|
|
460
|
+
schemes: z.array(z.string()).nullish(),
|
|
461
|
+
components: z.object({
|
|
462
|
+
schemas: Definitions
|
|
463
|
+
}).nullish()
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
const templateJsdocMethod = ({
|
|
467
|
+
classMethod,
|
|
468
|
+
httpMethod,
|
|
469
|
+
path,
|
|
470
|
+
pathParams,
|
|
471
|
+
bodyParams,
|
|
472
|
+
queryParams
|
|
473
|
+
}) => {
|
|
363
474
|
let jsdoc = "";
|
|
364
475
|
let methodSignature = "";
|
|
365
476
|
let newPath = path;
|
|
@@ -396,21 +507,31 @@ const templateJsdocMethod = (classMethod, httpMethod, path, pathParams, bodyPara
|
|
|
396
507
|
`;
|
|
397
508
|
};
|
|
398
509
|
|
|
399
|
-
const templateMethod = (
|
|
510
|
+
const templateMethod = ({
|
|
511
|
+
classMethod,
|
|
512
|
+
description,
|
|
513
|
+
httpMethod,
|
|
514
|
+
path,
|
|
515
|
+
pathParams,
|
|
516
|
+
bodyParams,
|
|
517
|
+
queryParams,
|
|
518
|
+
isFormUrlEncoded,
|
|
519
|
+
responseClass
|
|
520
|
+
}) => {
|
|
400
521
|
let methodSignature = "";
|
|
401
522
|
let newPath = `'${path}'`;
|
|
402
523
|
let dependencies = [];
|
|
403
|
-
for (const
|
|
404
|
-
const type = ParserUtils.parseType(
|
|
405
|
-
if (
|
|
406
|
-
methodSignature +=
|
|
524
|
+
for (const pathParam of pathParams) {
|
|
525
|
+
const type = ParserUtils.parseType(pathParam);
|
|
526
|
+
if (pathParam.name !== "namespace") {
|
|
527
|
+
methodSignature += pathParam.name + `:${type}, `;
|
|
407
528
|
}
|
|
408
|
-
const pName =
|
|
409
|
-
if (path.match(`{${
|
|
529
|
+
const pName = pathParam.name === "namespace" ? "this.namespace" : pathParam.name;
|
|
530
|
+
if (path.match(`{${pathParam.name}}`)) {
|
|
410
531
|
if (type === "string") {
|
|
411
|
-
newPath = `${newPath}.replace('{${
|
|
532
|
+
newPath = `${newPath}.replace('{${pathParam.name}}', ${pName})`;
|
|
412
533
|
} else {
|
|
413
|
-
newPath = `${newPath}.replace('{${
|
|
534
|
+
newPath = `${newPath}.replace('{${pathParam.name}}', String(${pName}))`;
|
|
414
535
|
}
|
|
415
536
|
}
|
|
416
537
|
}
|
|
@@ -420,8 +541,8 @@ const templateMethod = (classMethod, description, httpMethod, path, pathParams,
|
|
|
420
541
|
dependencies = ParserUtils.parseBodyParamsImports(bodyParams);
|
|
421
542
|
methodSignature += dataType ? `data: ${dataType},` : "";
|
|
422
543
|
}
|
|
423
|
-
ParserUtils.isAnyQueryParamRequired(queryParams);
|
|
424
|
-
const queryParamsType = queryParams.length ? `queryParams${"?"}: {${ParserUtils.parseQueryParamsType(queryParams)}}` : "";
|
|
544
|
+
const isAnyRequired = ParserUtils.isAnyQueryParamRequired(queryParams);
|
|
545
|
+
const queryParamsType = queryParams.length ? `queryParams${isAnyRequired ? "" : "?"}: {${ParserUtils.parseQueryParamsType(queryParams)}}` : "";
|
|
425
546
|
const queryParamsDefault = queryParams.length ? `const params = {${ParserUtils.parseQueryParamsDefault(queryParams)} ...queryParams} as SDKRequestConfig` : "const params = {} as SDKRequestConfig";
|
|
426
547
|
const isPostPutPatch = ["post", "put", "patch"].includes(httpMethod);
|
|
427
548
|
const isDelete = ["delete"].includes(httpMethod);
|
|
@@ -446,74 +567,30 @@ const templateMethod = (classMethod, description, httpMethod, path, pathParams,
|
|
|
446
567
|
const parameters = (queryParamsType ? `${methodSignature} ${queryParamsType}` : methodSignature).replace(/,\s*$/, "");
|
|
447
568
|
let methodImpl = "";
|
|
448
569
|
const isCacheFetch = ["get"].includes(httpMethod) && resolvedResponseClass !== "unknown";
|
|
449
|
-
const isCacheFetchUnknown = ["get"].includes(httpMethod) && resolvedResponseClass === "unknown";
|
|
450
570
|
const cachedFetchMethod = classMethod.replace("get", "fetch");
|
|
451
571
|
const deprecateTag = isCacheFetch ? `/**
|
|
452
572
|
* @deprecated Use "${cachedFetchMethod}()" instead.
|
|
453
573
|
*/` : "";
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
574
|
+
const isGuardInvoked = ["get", "post", "put", "patch", "delete"].includes(httpMethod);
|
|
575
|
+
const methodName = httpMethod === "get" ? cachedFetchMethod : ["post", "put", "patch", "delete"].includes(httpMethod) ? classMethod : "";
|
|
576
|
+
const methodGenerics = resolvedResponseClass !== "unknown" ? `<T = ${resolvedResponseClass}>` : "";
|
|
577
|
+
const responseType = resolvedResponseClass !== "unknown" ? `T` : "unknown";
|
|
578
|
+
const responseSyncType = httpMethod === "get" ? "IResponseWithSync" : ["post", "put", "patch", "delete"].includes(httpMethod) ? "IResponse" : "";
|
|
579
|
+
methodImpl = `${descriptionText}
|
|
580
|
+
${methodName}${methodGenerics}(${parameters}): Promise<${responseSyncType}<${responseType}>> {
|
|
458
581
|
${queryParamsDefault}
|
|
459
582
|
const url = ${newPath} ${formPayloadString} ${isFileUpload ? "\n// TODO file upload not implemented" : ""}
|
|
460
583
|
const resultPromise = this.axiosInstance.${httpMethod}(url, ${dataPayload})
|
|
461
|
-
|
|
462
|
-
const res = () => Validate.responseType(() => resultPromise, ${resolvedResponseClassValidated})
|
|
463
584
|
|
|
464
|
-
|
|
465
|
-
return SdkCache.withoutCache(res)
|
|
466
|
-
}
|
|
467
|
-
const key = url + CodeGenUtil.hashCode(JSON.stringify({ params }))
|
|
468
|
-
return SdkCache.withCache(key, res)
|
|
469
|
-
}
|
|
470
|
-
`;
|
|
471
|
-
isGuardInvoked = true;
|
|
472
|
-
}
|
|
473
|
-
if (isCacheFetchUnknown) {
|
|
474
|
-
methodImpl = `${descriptionText}
|
|
475
|
-
${cachedFetchMethod}(${parameters}): Promise<IResponseWithSync<unknown>> {
|
|
476
|
-
${queryParamsDefault}
|
|
477
|
-
const url = ${newPath} ${formPayloadString} ${isFileUpload ? "\n// TODO file upload not implemented" : ""}
|
|
478
|
-
const resultPromise = this.axiosInstance.${httpMethod}(url, ${dataPayload})
|
|
479
|
-
|
|
480
|
-
const res = () => Validate.responseType(() => resultPromise, z.unknown())
|
|
585
|
+
${httpMethod === "get" ? ` const res = () => Validate.responseType(() => resultPromise, ${resolvedResponseClassValidated})
|
|
481
586
|
|
|
482
587
|
if (!this.cache) {
|
|
483
588
|
return SdkCache.withoutCache(res)
|
|
484
589
|
}
|
|
485
|
-
const
|
|
486
|
-
return SdkCache.withCache(
|
|
487
|
-
}
|
|
488
|
-
`;
|
|
489
|
-
isGuardInvoked = true;
|
|
490
|
-
}
|
|
491
|
-
const withTypeGuard = ["post", "put", "patch", "delete"].includes(httpMethod) && resolvedResponseClass !== "unknown";
|
|
492
|
-
if (withTypeGuard) {
|
|
493
|
-
methodImpl = `${descriptionText}
|
|
494
|
-
${classMethod}<T = ${resolvedResponseClass}>(${parameters}): Promise<IResponse<T>> {
|
|
495
|
-
${queryParamsDefault}
|
|
496
|
-
const url = ${newPath} ${formPayloadString} ${isFileUpload ? "\n// TODO file upload not implemented" : ""}
|
|
497
|
-
const resultPromise = this.axiosInstance.${httpMethod}(url, ${dataPayload})
|
|
498
|
-
|
|
499
|
-
return Validate.responseType(() => resultPromise, ${resolvedResponseClassValidated})
|
|
500
|
-
}
|
|
501
|
-
`;
|
|
502
|
-
isGuardInvoked = true;
|
|
503
|
-
}
|
|
504
|
-
const withTypeGuardUnknown = ["post", "put", "patch", "delete"].includes(httpMethod) && resolvedResponseClass === "unknown";
|
|
505
|
-
if (withTypeGuardUnknown) {
|
|
506
|
-
methodImpl = `${descriptionText}
|
|
507
|
-
${classMethod}(${parameters}): Promise<IResponse<unknown>> {
|
|
508
|
-
${queryParamsDefault}
|
|
509
|
-
const url = ${newPath} ${formPayloadString} ${isFileUpload ? "\n// TODO file upload not implemented" : ""}
|
|
510
|
-
const resultPromise = this.axiosInstance.${httpMethod}(url, ${dataPayload})
|
|
511
|
-
|
|
512
|
-
return Validate.responseType(() => resultPromise, z.unknown())
|
|
590
|
+
const cacheKey = url + CodeGenUtil.hashCode(JSON.stringify({ params }))
|
|
591
|
+
return SdkCache.withCache(cacheKey, res)` : ""}${["post", "put", "patch", "delete"].includes(httpMethod) ? ` return Validate.responseType(() => resultPromise, ${resolvedResponseClassValidated})` : ""}
|
|
513
592
|
}
|
|
514
593
|
`;
|
|
515
|
-
isGuardInvoked = true;
|
|
516
|
-
}
|
|
517
594
|
if (!isGuardInvoked) {
|
|
518
595
|
methodImpl = `${descriptionText}
|
|
519
596
|
${deprecateTag}
|
|
@@ -531,41 +608,41 @@ class TemplateZod {
|
|
|
531
608
|
duplicates;
|
|
532
609
|
duplicateFound = false;
|
|
533
610
|
importClasses = /* @__PURE__ */ new Set();
|
|
534
|
-
render = (
|
|
611
|
+
render = (fileName, definition, duplicates) => {
|
|
535
612
|
this.duplicates = duplicates;
|
|
536
613
|
const content = this.parseToZodSchema(definition, definition.required || []);
|
|
537
|
-
const containsRecursiveType = this.importClasses.has(
|
|
614
|
+
const containsRecursiveType = this.importClasses.has(fileName);
|
|
538
615
|
if (containsRecursiveType) {
|
|
539
|
-
this.importClasses.delete(
|
|
616
|
+
this.importClasses.delete(fileName);
|
|
540
617
|
}
|
|
541
618
|
let imports = "";
|
|
542
619
|
for (const cl of Array.from(this.importClasses).sort()) {
|
|
543
|
-
imports += `
|
|
620
|
+
imports += `import { ${cl} } from './${cl}'
|
|
544
621
|
`;
|
|
545
622
|
}
|
|
546
623
|
let exportedVariableString;
|
|
547
624
|
let exportedTypeString;
|
|
548
625
|
if (containsRecursiveType) {
|
|
549
626
|
exportedVariableString = `
|
|
550
|
-
|
|
627
|
+
export const ${fileName}: z.ZodType<${fileName}> = z.lazy(() =>
|
|
551
628
|
${content.schemaString}
|
|
552
629
|
)
|
|
553
630
|
`;
|
|
554
631
|
exportedTypeString = `
|
|
555
|
-
|
|
632
|
+
export interface ${fileName} {
|
|
556
633
|
${content.typeString}
|
|
557
|
-
|
|
558
|
-
|
|
634
|
+
}
|
|
635
|
+
`;
|
|
559
636
|
} else {
|
|
560
|
-
exportedVariableString = `export const ${
|
|
561
|
-
exportedTypeString = `export
|
|
637
|
+
exportedVariableString = `export const ${fileName} = ${content.schemaString}`;
|
|
638
|
+
exportedTypeString = `export interface ${fileName} extends z.TypeOf<typeof ${fileName}> {}`;
|
|
562
639
|
}
|
|
563
640
|
const template = `import { z } from 'zod'
|
|
564
|
-
|
|
641
|
+
${imports}
|
|
565
642
|
|
|
566
|
-
|
|
643
|
+
${exportedVariableString}
|
|
567
644
|
|
|
568
|
-
|
|
645
|
+
${exportedTypeString}
|
|
569
646
|
`;
|
|
570
647
|
return { buffer: template, duplicateFound: this.duplicateFound };
|
|
571
648
|
};
|
|
@@ -573,13 +650,17 @@ class TemplateZod {
|
|
|
573
650
|
if (definition.additionalProperties) {
|
|
574
651
|
return this.parseToZodAttribute("", definition, []);
|
|
575
652
|
}
|
|
576
|
-
|
|
653
|
+
let properties;
|
|
654
|
+
if (definition.properties) {
|
|
655
|
+
properties = Object.entries(definition.properties);
|
|
656
|
+
} else if (definition.items?.properties) {
|
|
657
|
+
properties = Object.entries(definition.items.properties);
|
|
658
|
+
} else {
|
|
577
659
|
return {
|
|
578
660
|
schemaString: "z.any()",
|
|
579
661
|
typeString: "any"
|
|
580
662
|
};
|
|
581
663
|
}
|
|
582
|
-
const properties = Object.entries(definition.properties);
|
|
583
664
|
const schemaFields = [];
|
|
584
665
|
const typeFields = [];
|
|
585
666
|
for (const property of properties) {
|
|
@@ -588,6 +669,12 @@ class TemplateZod {
|
|
|
588
669
|
schemaFields.push(result.schemaString);
|
|
589
670
|
typeFields.push(result.typeString);
|
|
590
671
|
}
|
|
672
|
+
if (definition?.type === "array") {
|
|
673
|
+
return {
|
|
674
|
+
schemaString: `z.array(z.object({${schemaFields.join(",")}}))`,
|
|
675
|
+
typeString: typeFields.join(";")
|
|
676
|
+
};
|
|
677
|
+
}
|
|
591
678
|
return {
|
|
592
679
|
schemaString: `z.object({${schemaFields.join(",")}})`,
|
|
593
680
|
typeString: typeFields.join(";")
|
|
@@ -629,7 +716,8 @@ class TemplateZod {
|
|
|
629
716
|
};
|
|
630
717
|
}
|
|
631
718
|
if (type === "array") {
|
|
632
|
-
const
|
|
719
|
+
const items = definition.items;
|
|
720
|
+
const ref2 = items?.$ref;
|
|
633
721
|
let model2;
|
|
634
722
|
if (ref2) {
|
|
635
723
|
const refType = ParserUtils.parseRefType(ref2);
|
|
@@ -638,9 +726,13 @@ class TemplateZod {
|
|
|
638
726
|
schemaString: refType,
|
|
639
727
|
typeString: refType
|
|
640
728
|
};
|
|
641
|
-
} else {
|
|
642
|
-
const items = definition.items;
|
|
729
|
+
} else if (items) {
|
|
643
730
|
model2 = this.parseEnumItems(items);
|
|
731
|
+
} else {
|
|
732
|
+
return {
|
|
733
|
+
schemaString: `${schemaAttribute} z.array(z.any())${schemaRequired}`,
|
|
734
|
+
typeString: `${typeAttribute} any[]${typeNullishability}`
|
|
735
|
+
};
|
|
644
736
|
}
|
|
645
737
|
return {
|
|
646
738
|
schemaString: `${schemaAttribute} z.array(${model2.schemaString})${schemaRequired}`,
|
|
@@ -707,11 +799,11 @@ class TemplateZodArray {
|
|
|
707
799
|
render = (name) => {
|
|
708
800
|
const cls = name.replace("Array", "");
|
|
709
801
|
const template = `import { z } from 'zod'
|
|
710
|
-
|
|
802
|
+
import { ${cls} } from './${cls}'
|
|
711
803
|
|
|
712
|
-
|
|
804
|
+
export const ${name} = z.array(${cls})
|
|
713
805
|
|
|
714
|
-
|
|
806
|
+
export interface ${name} extends z.TypeOf<typeof ${name}> {}
|
|
715
807
|
`;
|
|
716
808
|
return template;
|
|
717
809
|
};
|
|
@@ -750,7 +842,7 @@ class CodeGenerator {
|
|
|
750
842
|
static getPatchedDir = () => path__default.join(CliParser.getSwaggersOutputPath(), "patched");
|
|
751
843
|
static getGeneratedPublicFolder = () => `${CliParser.getOutputPath()}/generated-public`;
|
|
752
844
|
static getGeneratedAdminFolder = () => `${CliParser.getOutputPath()}/generated-admin`;
|
|
753
|
-
static iterateApi = (api) => {
|
|
845
|
+
static iterateApi = async (api) => {
|
|
754
846
|
const apiBufferByTag = {};
|
|
755
847
|
const jsDocApiBufferByTag = {};
|
|
756
848
|
const dependenciesByTag = {};
|
|
@@ -763,14 +855,20 @@ class CodeGenerator {
|
|
|
763
855
|
} else if (!CliParser.isAdmin() && isAdminEndpoint) {
|
|
764
856
|
continue;
|
|
765
857
|
}
|
|
766
|
-
const
|
|
767
|
-
const
|
|
768
|
-
for (const httpMethod of
|
|
769
|
-
const
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
858
|
+
const operation = api.paths[path2];
|
|
859
|
+
const httpMethods = Object.keys(operation);
|
|
860
|
+
for (const httpMethod of httpMethods) {
|
|
861
|
+
const endpoint = await Endpoint.parseAsync(operation[httpMethod]).catch((error) => {
|
|
862
|
+
console.error(JSON.stringify({ path: path2, httpMethod }, null, 2));
|
|
863
|
+
throw error;
|
|
864
|
+
});
|
|
865
|
+
if (!endpoint.tags) {
|
|
866
|
+
continue;
|
|
867
|
+
}
|
|
868
|
+
const [tag] = endpoint.tags;
|
|
869
|
+
const description = endpoint.description;
|
|
870
|
+
const isDeprecated = endpoint.deprecated;
|
|
871
|
+
const responseClass = ParserUtils.get2xxResponse(endpoint.responses);
|
|
774
872
|
const className = _.upperFirst(_.camelCase(tag));
|
|
775
873
|
classImports[className] = classImports[className] ? classImports[className] : {};
|
|
776
874
|
if (!isDeprecated) {
|
|
@@ -781,15 +879,39 @@ class CodeGenerator {
|
|
|
781
879
|
if (responseClass && responseClass.endsWith("Array")) {
|
|
782
880
|
arrayDefinitions.push(responseClass);
|
|
783
881
|
}
|
|
784
|
-
const isFormUrlEncoded = ParserUtils.isFormUrlEncoded(httpMethod,
|
|
785
|
-
const queryParams = ParserUtils.
|
|
786
|
-
const pathParams = ParserUtils.
|
|
787
|
-
|
|
788
|
-
const classMethod = ParserUtils.generateClassMethod(
|
|
789
|
-
|
|
790
|
-
|
|
882
|
+
const isFormUrlEncoded = ParserUtils.isFormUrlEncoded(httpMethod, endpoint.consumes);
|
|
883
|
+
const queryParams = ParserUtils.filterQueryParameters(endpoint.parameters);
|
|
884
|
+
const pathParams = ParserUtils.filterPathParams(endpoint.parameters);
|
|
885
|
+
let bodyParams = ParserUtils.filterBodyParams(endpoint.parameters);
|
|
886
|
+
const classMethod = ParserUtils.generateClassMethod({
|
|
887
|
+
path: path2,
|
|
888
|
+
endpoint,
|
|
889
|
+
httpMethod,
|
|
890
|
+
className
|
|
891
|
+
});
|
|
892
|
+
if (endpoint.requestBody) {
|
|
893
|
+
bodyParams = [
|
|
894
|
+
{
|
|
895
|
+
name: "body",
|
|
896
|
+
in: "body",
|
|
897
|
+
schema: endpoint.requestBody.content["application/json"].schema
|
|
898
|
+
}
|
|
899
|
+
];
|
|
900
|
+
}
|
|
901
|
+
const pathWithBase = `${api.basePath ?? ""}${path2}`;
|
|
902
|
+
const [generatedMethodString, importStatements] = templateMethod({
|
|
903
|
+
classMethod,
|
|
904
|
+
description,
|
|
905
|
+
httpMethod,
|
|
906
|
+
path: pathWithBase,
|
|
907
|
+
pathParams,
|
|
908
|
+
bodyParams,
|
|
909
|
+
queryParams,
|
|
910
|
+
isFormUrlEncoded,
|
|
911
|
+
responseClass
|
|
912
|
+
});
|
|
791
913
|
apiBufferByTag[tag] = (apiBufferByTag[tag] || "") + generatedMethodString;
|
|
792
|
-
jsDocApiBufferByTag[tag] = (jsDocApiBufferByTag[tag] || "") + templateJsdocMethod(classMethod, httpMethod, path2, pathParams, bodyParams, queryParams);
|
|
914
|
+
jsDocApiBufferByTag[tag] = (jsDocApiBufferByTag[tag] || "") + templateJsdocMethod({ classMethod, httpMethod, path: path2, pathParams, bodyParams, queryParams });
|
|
793
915
|
dependenciesByTag[tag] = dependenciesByTag[tag] ? [.../* @__PURE__ */ new Set([...importStatements, ...dependenciesByTag[tag]])] : [...new Set(importStatements)];
|
|
794
916
|
}
|
|
795
917
|
}
|
|
@@ -815,7 +937,7 @@ class CodeGenerator {
|
|
|
815
937
|
ParserUtils.mkdirIfNotExist(DIST_DIR);
|
|
816
938
|
ParserUtils.mkdirIfNotExist(DIST_DOCS_DIR);
|
|
817
939
|
ParserUtils.mkdirIfNotExist(DIST_DEFINITION_DIR);
|
|
818
|
-
const { apiBufferByTag, dependenciesByTag, classImports, arrayDefinitions } = CodeGenerator.iterateApi(api);
|
|
940
|
+
const { apiBufferByTag, dependenciesByTag, classImports, arrayDefinitions } = await CodeGenerator.iterateApi(api);
|
|
819
941
|
const targetSrcFolder = `${CliParser.getOutputPath()}/`;
|
|
820
942
|
for (const tag in apiBufferByTag) {
|
|
821
943
|
const className = _.upperFirst(_.camelCase(tag));
|
|
@@ -826,8 +948,9 @@ class CodeGenerator {
|
|
|
826
948
|
indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path__default.join(DIST_DIR, `${classGenName}`), targetSrcFolder));
|
|
827
949
|
}
|
|
828
950
|
const duplicates = /* @__PURE__ */ new Map();
|
|
829
|
-
|
|
830
|
-
|
|
951
|
+
const definitions = api?.components?.schemas || api.definitions;
|
|
952
|
+
for (const ref in definitions) {
|
|
953
|
+
const definition = definitions[ref];
|
|
831
954
|
let fileName = ParserUtils.parseRefType(ref);
|
|
832
955
|
const fileExist = fs__default.existsSync(path__default.join(DIST_DEFINITION_DIR, `${fileName}.ts`));
|
|
833
956
|
if (fileExist) {
|
|
@@ -838,8 +961,8 @@ class CodeGenerator {
|
|
|
838
961
|
ParserUtils.writeDefinitionFile(DIST_DEFINITION_DIR, fileName, buffer);
|
|
839
962
|
indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path__default.join(DIST_DEFINITION_DIR, fileName), targetSrcFolder));
|
|
840
963
|
}
|
|
841
|
-
for (const ref in
|
|
842
|
-
const definition =
|
|
964
|
+
for (const ref in definitions) {
|
|
965
|
+
const definition = definitions[ref];
|
|
843
966
|
const fileName = ParserUtils.parseRefType(ref);
|
|
844
967
|
const { buffer, duplicateFound } = new TemplateZod().render(fileName, definition, duplicates);
|
|
845
968
|
if (duplicateFound) {
|