@accelbyte/codegen 1.0.0-beta.7 → 1.0.1-experimental.1
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/dist/accelbyte-codegen.js +344 -89
- package/dist/accelbyte-codegen.js.map +1 -1
- package/dist/accelbyte-codegen.mjs +345 -90
- package/dist/accelbyte-codegen.mjs.map +1 -1
- package/package.json +3 -21
|
@@ -79,18 +79,18 @@ class CliParser {
|
|
|
79
79
|
};
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
const getImportableVarMap = () => ({
|
|
82
|
+
const getImportableVarMap$1 = () => ({
|
|
83
83
|
"@accelbyte/sdk": ["CodeGenUtil", "SdkCache", "IResponse", "IResponseWithSync", "Validate"],
|
|
84
84
|
axios: ["AxiosRequestConfig", "AxiosResponse"],
|
|
85
85
|
zod: ["z"]
|
|
86
86
|
});
|
|
87
|
-
const makeNewImportVarMap = () => ({
|
|
87
|
+
const makeNewImportVarMap$1 = () => ({
|
|
88
88
|
axios: ["AxiosInstance"],
|
|
89
89
|
"@accelbyte/sdk": ["SDKRequestConfig"]
|
|
90
90
|
});
|
|
91
|
-
const generateImports = (body, importStatements) => {
|
|
92
|
-
const usedImportVarMap =
|
|
93
|
-
const importableVarMap =
|
|
91
|
+
const generateImports = (body, importStatements, makeNewImportVarMap2, getImportableVarMap2) => {
|
|
92
|
+
const usedImportVarMap = makeNewImportVarMap2;
|
|
93
|
+
const importableVarMap = getImportableVarMap2;
|
|
94
94
|
for (const [moduleSource, importableVars] of Object.entries(importableVarMap)) {
|
|
95
95
|
for (const importableVar of importableVars) {
|
|
96
96
|
const importVarRegex = new RegExp(`(?<![\\d\\w_])${importableVar}(?![\\d\\w_])`);
|
|
@@ -103,10 +103,11 @@ const generateImports = (body, importStatements) => {
|
|
|
103
103
|
return `${generatedImports}
|
|
104
104
|
${importStatements.sort().join("\n")}`;
|
|
105
105
|
};
|
|
106
|
-
const templateClass = (className, body, importStatements) =>
|
|
107
|
-
|
|
106
|
+
const templateClass = (className, body, importStatements) => {
|
|
107
|
+
return `/**
|
|
108
|
+
* AUTO GENERATED
|
|
108
109
|
*/
|
|
109
|
-
${generateImports(body, importStatements)}
|
|
110
|
+
${generateImports(body, importStatements, makeNewImportVarMap$1(), getImportableVarMap$1())}
|
|
110
111
|
|
|
111
112
|
export class ${className} {
|
|
112
113
|
// @ts-ignore
|
|
@@ -114,15 +115,37 @@ export class ${className} {
|
|
|
114
115
|
${body}
|
|
115
116
|
}
|
|
116
117
|
`;
|
|
118
|
+
};
|
|
117
119
|
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
const getImportableVarMap = () => ({
|
|
121
|
+
"@accelbyte/sdk": ["CodeGenUtil", "SdkCache", "IResponse", "IResponseWithSync", "Validate", "ApiArgs", "Network", "AccelbyteSDK"]
|
|
122
|
+
});
|
|
123
|
+
const makeNewImportVarMap = () => ({
|
|
124
|
+
"@accelbyte/sdk": ["AccelbyteSDK", "ApiArgs", "ApiUtils"]
|
|
125
|
+
});
|
|
126
|
+
const templateApiClass = (className, body, importStatements, returnMethods) => {
|
|
127
|
+
return `/**
|
|
128
|
+
* AUTO GENERATED
|
|
129
|
+
*/
|
|
130
|
+
/* eslint-disable camelcase */
|
|
131
|
+
${generateImports(body, importStatements, makeNewImportVarMap(), getImportableVarMap())}
|
|
122
132
|
|
|
123
|
-
|
|
124
|
-
|
|
133
|
+
export function ${className}(sdk: AccelbyteSDK, args?: ApiArgs) {
|
|
134
|
+
const sdkAssembly = sdk.assembly()
|
|
135
|
+
|
|
136
|
+
const namespace = args?.namespace ? args?.namespace : sdkAssembly.namespace
|
|
137
|
+
const cache = args?.cache ? args?.cache : sdkAssembly.cache
|
|
138
|
+
const requestConfig = ApiUtils.mergedConfigs(sdkAssembly.config, args)
|
|
139
|
+
${body}
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
${returnMethods}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
`;
|
|
146
|
+
};
|
|
125
147
|
|
|
148
|
+
const UNDEFINED_SWAGGER_SEMVER = "0.0.0";
|
|
126
149
|
const REMOVED_KEYWORDS = [
|
|
127
150
|
"/admin/",
|
|
128
151
|
"/public/",
|
|
@@ -136,39 +159,62 @@ const REMOVED_KEYWORDS = [
|
|
|
136
159
|
"/{namespace}/"
|
|
137
160
|
];
|
|
138
161
|
class ParserUtils {
|
|
162
|
+
static replaceAll = (string, search, replace) => {
|
|
163
|
+
return string.split(search).join(replace);
|
|
164
|
+
};
|
|
139
165
|
static generateClassName = (tag) => {
|
|
140
166
|
const className = _.upperFirst(_.camelCase(tag));
|
|
141
167
|
const classGenName = CliParser.isAdmin() ? className + "Admin$" : className + "$";
|
|
142
168
|
return { className, classGenName };
|
|
143
169
|
};
|
|
170
|
+
static generateApiName = (tag) => {
|
|
171
|
+
const apiName = _.upperFirst(_.camelCase(tag));
|
|
172
|
+
const apiGenName = CliParser.isAdmin() ? apiName + "AdminApi" : apiName + "Api";
|
|
173
|
+
return { apiName, apiGenName };
|
|
174
|
+
};
|
|
144
175
|
static parseQueryParamAttributeDefault = (definition) => {
|
|
145
176
|
const attrName = definition.name.slice(definition.name.lastIndexOf(".") + 1);
|
|
146
177
|
const defaultValue = definition.type === "string" ? `'${definition.default}'` : definition.default;
|
|
147
178
|
return `${attrName}: ${defaultValue}`;
|
|
148
179
|
};
|
|
149
180
|
static parseType = (pathParam) => {
|
|
150
|
-
if (pathParam.type
|
|
181
|
+
if (isSwaggerIntegerType(pathParam.type || pathParam?.schema?.type))
|
|
151
182
|
return "number";
|
|
152
|
-
if (pathParam.type === "array")
|
|
183
|
+
if (pathParam.type === "array") {
|
|
184
|
+
if (isSwaggerIntegerType(pathParam.items.type))
|
|
185
|
+
return "number[]";
|
|
153
186
|
return `${pathParam.items.type ?? "any"}[]`;
|
|
154
|
-
|
|
187
|
+
}
|
|
188
|
+
if (pathParam?.schema?.type === "array") {
|
|
189
|
+
if (isSwaggerIntegerType(pathParam.schema.items.type))
|
|
190
|
+
return "number[]";
|
|
155
191
|
return `${pathParam.schema.items.type ?? "any"}[]`;
|
|
192
|
+
}
|
|
156
193
|
if (pathParam?.schema?.type)
|
|
157
194
|
return pathParam.schema.type;
|
|
158
195
|
return pathParam.type;
|
|
159
196
|
};
|
|
160
197
|
static parseQueryParamsType = (queryParams) => {
|
|
161
|
-
return queryParams.map((queryParam) => ParserUtils.parseAttributeType(queryParam)).join(",");
|
|
198
|
+
return queryParams.map((queryParam) => ParserUtils.parseAttributeType(queryParam)).join(", ");
|
|
162
199
|
};
|
|
163
200
|
static isAnyQueryParamRequired = (queryParams) => {
|
|
164
201
|
return queryParams.some((queryParam) => queryParam.required);
|
|
165
202
|
};
|
|
203
|
+
static convertDashesToTitleCase = (str) => {
|
|
204
|
+
const result = str.split("-").map((word, index) => {
|
|
205
|
+
if (index === 0) {
|
|
206
|
+
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
207
|
+
}
|
|
208
|
+
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
|
209
|
+
}).join("");
|
|
210
|
+
return result;
|
|
211
|
+
};
|
|
166
212
|
static parseQueryParamsDefault = (queryParams) => {
|
|
167
213
|
const result = queryParams.filter((queryParam) => !!queryParam.default && !queryParam.required).map(ParserUtils.parseQueryParamAttributeDefault).join(",");
|
|
168
214
|
return result ? `${result},` : "";
|
|
169
215
|
};
|
|
170
216
|
static parseBodyParamsImports = (bodyParams) => {
|
|
171
|
-
return bodyParams.map(ParserUtils.parseRefImport).filter(Boolean);
|
|
217
|
+
return bodyParams.map((bodyParams2) => ParserUtils.parseRefImport(bodyParams2)).filter(Boolean);
|
|
172
218
|
};
|
|
173
219
|
static parseImportDir = ($ref) => {
|
|
174
220
|
let ref = $ref.replace(".", "/");
|
|
@@ -187,7 +233,7 @@ class ParserUtils {
|
|
|
187
233
|
return null;
|
|
188
234
|
}
|
|
189
235
|
const type = ParserUtils.parseRefType($ref);
|
|
190
|
-
return `import { ${type} } from '
|
|
236
|
+
return `import { ${type} } from '../definitions/${type}.js'`;
|
|
191
237
|
};
|
|
192
238
|
static parseRefType = ($ref) => {
|
|
193
239
|
let ref = $ref.replace(".", "/");
|
|
@@ -234,6 +280,8 @@ class ParserUtils {
|
|
|
234
280
|
return retBodyParams;
|
|
235
281
|
}
|
|
236
282
|
if (bodyParam?.schema?.type === "array" && !bodyParam?.schema?.items?.$ref) {
|
|
283
|
+
if (isSwaggerIntegerType(bodyParam.schema.items.type))
|
|
284
|
+
return "number[]";
|
|
237
285
|
return `${bodyParam.schema.items.type ?? "any"}[]`;
|
|
238
286
|
}
|
|
239
287
|
if (bodyParam?.schema?.type === "array" && bodyParam?.schema?.items?.$ref) {
|
|
@@ -290,8 +338,8 @@ class ParserUtils {
|
|
|
290
338
|
path_ = path_.substring(1);
|
|
291
339
|
const isPlural = httpMethod === "get" && !(path2.slice(-1) === "}");
|
|
292
340
|
if (!isPlural) {
|
|
293
|
-
path_ = replaceAll(path_, "ies/", "y/");
|
|
294
|
-
path_ = replaceAll(path_, "s/", "/");
|
|
341
|
+
path_ = ParserUtils.replaceAll(path_, "ies/", "y/");
|
|
342
|
+
path_ = ParserUtils.replaceAll(path_, "s/", "/");
|
|
295
343
|
if (path_.indexOf("status") < 0) {
|
|
296
344
|
path_ = path_.replace(/ies$/, "y");
|
|
297
345
|
path_ = path_.replace(/s$/, "");
|
|
@@ -330,7 +378,7 @@ class ParserUtils {
|
|
|
330
378
|
});
|
|
331
379
|
const genPath = _.upperFirst(lastWords) + "/" + listBeforeLastWords.join("/") + listByParams.reverse().join("/");
|
|
332
380
|
let generatedMethod = _.camelCase(mappedMethod(httpMethod, isForm) + genPath);
|
|
333
|
-
generatedMethod = replaceAll(generatedMethod, "Byword", "_By");
|
|
381
|
+
generatedMethod = ParserUtils.replaceAll(generatedMethod, "Byword", "_By");
|
|
334
382
|
generatedMethod = resolveConflicts(path2, generatedMethod, existingMethods);
|
|
335
383
|
return generatedMethod;
|
|
336
384
|
};
|
|
@@ -355,12 +403,22 @@ class ParserUtils {
|
|
|
355
403
|
const fileContent = templateClass(apiName, apiBuffer, imports);
|
|
356
404
|
fs.writeFileSync(`${distDir}/${apiName}.ts`, ParserUtils.prependCopyrightHeader(fileContent));
|
|
357
405
|
}
|
|
358
|
-
static
|
|
359
|
-
const
|
|
360
|
-
|
|
406
|
+
static writeApiFile(distDir, apiName, apiBuffer, imports, returnMethods) {
|
|
407
|
+
const newImports = [];
|
|
408
|
+
imports.forEach((el, index) => {
|
|
409
|
+
newImports.push(el.replace("../definitions", "./definitions"));
|
|
410
|
+
});
|
|
411
|
+
const fileContent = templateApiClass(apiName, apiBuffer, newImports, returnMethods);
|
|
412
|
+
fs.writeFileSync(`${distDir}/${apiName}.ts`, ParserUtils.prependCopyrightHeader(fileContent));
|
|
413
|
+
}
|
|
414
|
+
static writeApiMainFile(distDir, serviceName, fileContent) {
|
|
415
|
+
fs.writeFileSync(`${distDir}/${serviceName}.ts`, ParserUtils.prependCopyrightHeader(fileContent));
|
|
361
416
|
}
|
|
362
417
|
static writeSnippetFile(distDir, name, docBuffer) {
|
|
363
|
-
|
|
418
|
+
let snippetFileName = ParserUtils.replaceAll(name, " ", "-").toLowerCase();
|
|
419
|
+
snippetFileName = snippetFileName.replace("justice-", "");
|
|
420
|
+
snippetFileName = "snippet-" + snippetFileName + ".json";
|
|
421
|
+
fs.writeFileSync(`${distDir}/${snippetFileName}`, docBuffer);
|
|
364
422
|
}
|
|
365
423
|
static writeDefinitionFile(distDir, name, buffer) {
|
|
366
424
|
ParserUtils.mkdirIfNotExist(distDir);
|
|
@@ -370,15 +428,36 @@ class ParserUtils {
|
|
|
370
428
|
ParserUtils.mkdirIfNotExist(distDir);
|
|
371
429
|
fs.writeFileSync(path.join(distDir, `all-${isAdminWebSdk ? "admin" : "public"}-imports.ts`), ParserUtils.prependCopyrightHeader(buffer));
|
|
372
430
|
}
|
|
373
|
-
static
|
|
374
|
-
const
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
431
|
+
static syncChangelog(packageVersion) {
|
|
432
|
+
const currDir = process.cwd();
|
|
433
|
+
const pathToChangelog = path.join(currDir, "./CHANGELOG.md");
|
|
434
|
+
let fileContent = fs.readFileSync(pathToChangelog, "utf-8");
|
|
435
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
436
|
+
fileContent = "### " + packageVersion + " - " + date + `
|
|
437
|
+
|
|
438
|
+
- code-generated update
|
|
439
|
+
|
|
440
|
+
` + fileContent.trim();
|
|
441
|
+
fs.writeFileSync(pathToChangelog, fileContent, "utf-8");
|
|
442
|
+
}
|
|
443
|
+
static syncPackageVersion(apiInfo, isAdminWebSdk) {
|
|
444
|
+
if (isAdminWebSdk) {
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
const currDir = process.cwd();
|
|
448
|
+
const { packageJSON, pathToPackageJSON } = ParserUtils.getPackageJSONInfo(currDir);
|
|
449
|
+
let swaggerVersion = apiInfo.version ? apiInfo.version : UNDEFINED_SWAGGER_SEMVER;
|
|
450
|
+
swaggerVersion = Number(swaggerVersion.replace(".", "").replace(".", ""));
|
|
451
|
+
swaggerVersion = isNaN(swaggerVersion) ? 0 : swaggerVersion;
|
|
452
|
+
const semver = packageJSON.version.split(".").map((numStr) => Number(numStr));
|
|
453
|
+
const newSemver = [semver[0], swaggerVersion, ++semver[2]];
|
|
454
|
+
packageJSON.version = newSemver[0] + "." + newSemver[1] + "." + newSemver[2];
|
|
455
|
+
fs.writeFileSync(pathToPackageJSON, JSON.stringify(packageJSON, null, 2));
|
|
456
|
+
ParserUtils.syncChangelog(packageJSON.version);
|
|
457
|
+
}
|
|
458
|
+
static getPackageJSONInfo(dir) {
|
|
459
|
+
const pathToPackageJSON = path.join(dir, "./package.json");
|
|
460
|
+
return { packageJSON: JSON.parse(fs.readFileSync(pathToPackageJSON, "utf-8")), pathToPackageJSON };
|
|
382
461
|
}
|
|
383
462
|
static toCamelCase(str) {
|
|
384
463
|
return str.split("/").map(function(word, index) {
|
|
@@ -453,12 +532,9 @@ class ParserUtils {
|
|
|
453
532
|
${content}`;
|
|
454
533
|
};
|
|
455
534
|
}
|
|
456
|
-
const replaceAll = (string, search, replace) => {
|
|
457
|
-
return string.split(search).join(replace);
|
|
458
|
-
};
|
|
459
535
|
const mappedMethod = (httpMethod, isForm) => {
|
|
460
536
|
if (httpMethod === "get") {
|
|
461
|
-
return "
|
|
537
|
+
return "get";
|
|
462
538
|
} else if (httpMethod === "post" && isForm) {
|
|
463
539
|
return "post";
|
|
464
540
|
} else if (httpMethod === "post") {
|
|
@@ -517,6 +593,9 @@ const testConflict = (path2, generatedMethod, existingMethods) => {
|
|
|
517
593
|
existingMethods: ${JSON.stringify(existingMethods, null, 2)}`);
|
|
518
594
|
}
|
|
519
595
|
};
|
|
596
|
+
const isSwaggerIntegerType = (type) => {
|
|
597
|
+
return type === "integer" || type === "int";
|
|
598
|
+
};
|
|
520
599
|
|
|
521
600
|
const Schema = zod.z.object({
|
|
522
601
|
$ref: zod.z.string().nullish(),
|
|
@@ -619,16 +698,15 @@ const templateMethod = ({
|
|
|
619
698
|
isFormUrlEncoded,
|
|
620
699
|
responseClass
|
|
621
700
|
}) => {
|
|
622
|
-
let
|
|
701
|
+
let methodParams = "";
|
|
702
|
+
let methodParamsNoTypes = "";
|
|
623
703
|
let newPath = `'${path}'`;
|
|
624
|
-
let
|
|
625
|
-
let snippetString = "";
|
|
626
|
-
let snippetMethodSignature = "";
|
|
627
|
-
let snippetCurl = "";
|
|
704
|
+
let importStatements = [];
|
|
628
705
|
for (const pathParam of pathParams) {
|
|
629
706
|
const type = ParserUtils.parseType(pathParam);
|
|
630
707
|
if (pathParam.name !== "namespace") {
|
|
631
|
-
|
|
708
|
+
methodParams += pathParam.name + `:${type}, `;
|
|
709
|
+
methodParamsNoTypes += pathParam.name + ", ";
|
|
632
710
|
}
|
|
633
711
|
const pName = pathParam.name === "namespace" ? "this.namespace" : pathParam.name;
|
|
634
712
|
if (path.match(`{${pathParam.name}}`)) {
|
|
@@ -639,20 +717,12 @@ const templateMethod = ({
|
|
|
639
717
|
}
|
|
640
718
|
}
|
|
641
719
|
}
|
|
642
|
-
snippetCurl = `<span class='sn-blue'>curl</span> --location --request <span class='sn-blue'>${httpMethod}</span> '<span class='sn-green'>__DOMAIN__${path}</span>' --header 'accept: application/json'`;
|
|
643
720
|
let dataType = null;
|
|
644
721
|
if (httpMethod !== "get") {
|
|
645
722
|
dataType = ParserUtils.parseBodyParamsType(bodyParams);
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
return ` <span class='sn-purple'>${ob.name}</span>`;
|
|
650
|
-
});
|
|
651
|
-
snippetMethodSignature += snippetParams ? `data: { ${snippetParams} }` : "";
|
|
652
|
-
const curlParams = bodyParams?.map((ob) => {
|
|
653
|
-
return ` <span class='sn-purple'>"${ob.name}": ""</span>`;
|
|
654
|
-
});
|
|
655
|
-
snippetCurl += ` --data-raw { ${curlParams}}`;
|
|
723
|
+
importStatements = ParserUtils.parseBodyParamsImports(bodyParams);
|
|
724
|
+
methodParams += dataType ? `data: ${dataType},` : "";
|
|
725
|
+
methodParamsNoTypes += dataType ? `data,` : "";
|
|
656
726
|
}
|
|
657
727
|
const isAnyRequired = ParserUtils.isAnyQueryParamRequired(queryParams);
|
|
658
728
|
const queryParamsType = queryParams.length ? `queryParams${isAnyRequired ? "" : "?"}: {${ParserUtils.parseQueryParamsType(queryParams)}}` : "";
|
|
@@ -662,7 +732,7 @@ const templateMethod = ({
|
|
|
662
732
|
let dataPayload = "{params}";
|
|
663
733
|
const descriptionText = description ? `
|
|
664
734
|
/**
|
|
665
|
-
* ${
|
|
735
|
+
* ${description.replace(/\n/g, "\n * ")}
|
|
666
736
|
*/` : "";
|
|
667
737
|
let formPayloadString = "";
|
|
668
738
|
if (isFormUrlEncoded) {
|
|
@@ -674,23 +744,21 @@ const templateMethod = ({
|
|
|
674
744
|
} else if (isDelete) {
|
|
675
745
|
dataPayload = dataType ? `{data, params}` : "{params}";
|
|
676
746
|
}
|
|
677
|
-
const isFileUpload =
|
|
747
|
+
const isFileUpload = methodParams.indexOf("data: {file") > -1;
|
|
678
748
|
const resolvedResponseClass = responseClass || "unknown";
|
|
679
749
|
const resolvedResponseClassValidated = responseClass || "z.unknown()";
|
|
680
|
-
|
|
750
|
+
methodParams = (queryParamsType ? `${methodParams} ${queryParamsType}` : methodParams).replace(/,\s*$/, "");
|
|
751
|
+
methodParamsNoTypes = queryParamsType ? `${methodParamsNoTypes} queryParams` : methodParamsNoTypes;
|
|
681
752
|
let methodImpl = "";
|
|
682
753
|
const isCacheFetch = ["get"].includes(httpMethod) && resolvedResponseClass !== "unknown";
|
|
683
|
-
const cachedFetchMethod = classMethod
|
|
754
|
+
const cachedFetchMethod = classMethod;
|
|
684
755
|
const deprecateTag = isCacheFetch ? `/**
|
|
685
|
-
* @deprecated Use "${
|
|
756
|
+
* @deprecated Use "${classMethod}()" instead.
|
|
686
757
|
*/` : "";
|
|
687
758
|
const isGuardInvoked = ["get", "post", "put", "patch", "delete"].includes(httpMethod);
|
|
688
759
|
const methodName = httpMethod === "get" ? cachedFetchMethod : ["post", "put", "patch", "delete"].includes(httpMethod) ? classMethod : "";
|
|
689
|
-
const
|
|
690
|
-
const
|
|
691
|
-
const generateMethodName = () => `${methodName}${methodGenerics}(${parameters}): Promise<${responseSyncType}<${responseType}>>`;
|
|
692
|
-
const generateSnippetMethodName = () => `${methodName}(${snippetMethodSignature})`;
|
|
693
|
-
snippetString += `${generateSnippetMethodName()}`;
|
|
760
|
+
const responseType = resolvedResponseClass !== "unknown" ? `${resolvedResponseClass}` : "unknown";
|
|
761
|
+
const generateMethodName = () => `${methodName}(${methodParams}): Promise<${responseSyncType}<${responseType}>>`;
|
|
694
762
|
const responseSyncType = httpMethod === "get" ? "IResponseWithSync" : ["post", "put", "patch", "delete"].includes(httpMethod) ? "IResponse" : "";
|
|
695
763
|
methodImpl = `${descriptionText}
|
|
696
764
|
${generateMethodName()} {
|
|
@@ -698,26 +766,32 @@ const templateMethod = ({
|
|
|
698
766
|
const url = ${newPath} ${formPayloadString} ${isFileUpload ? "\n// TODO file upload not implemented" : ""}
|
|
699
767
|
const resultPromise = this.axiosInstance.${httpMethod}(url, ${dataPayload})
|
|
700
768
|
|
|
701
|
-
${httpMethod === "get" ? ` const res = () => Validate.responseType(() => resultPromise, ${resolvedResponseClassValidated})
|
|
769
|
+
${httpMethod === "get" ? ` const res = () => Validate.responseType(() => resultPromise, ${resolvedResponseClassValidated}, '${resolvedResponseClassValidated}')
|
|
702
770
|
|
|
703
771
|
if (!this.cache) {
|
|
704
772
|
return SdkCache.withoutCache(res)
|
|
705
773
|
}
|
|
706
774
|
const cacheKey = url + CodeGenUtil.hashCode(JSON.stringify({ params }))
|
|
707
|
-
return SdkCache.withCache(cacheKey, res)` : ""}${["post", "put", "patch", "delete"].includes(httpMethod) ? ` return Validate.responseType(() => resultPromise, ${resolvedResponseClassValidated})` : ""}
|
|
775
|
+
return SdkCache.withCache(cacheKey, res)` : ""}${["post", "put", "patch", "delete"].includes(httpMethod) ? ` return Validate.responseType(() => resultPromise, ${resolvedResponseClassValidated}, '${resolvedResponseClassValidated}')` : ""}
|
|
708
776
|
}
|
|
709
777
|
`;
|
|
710
778
|
if (!isGuardInvoked) {
|
|
711
779
|
methodImpl = `${descriptionText}
|
|
712
780
|
${deprecateTag}
|
|
713
|
-
TODO_${classMethod}
|
|
781
|
+
TODO_${classMethod}(${methodParams}): Promise<AxiosResponse<${resolvedResponseClass}>> {
|
|
714
782
|
${queryParamsDefault}
|
|
715
783
|
const url = ${newPath} ${formPayloadString} ${isFileUpload ? "\n// TODO file upload not implemented" : ""}
|
|
716
784
|
return this.axiosInstance.${httpMethod}(url, ${dataPayload})
|
|
717
785
|
}
|
|
718
786
|
`;
|
|
719
787
|
}
|
|
720
|
-
|
|
788
|
+
const res = {
|
|
789
|
+
methodImpl,
|
|
790
|
+
methodParams,
|
|
791
|
+
methodParamsNoTypes,
|
|
792
|
+
importStatements
|
|
793
|
+
};
|
|
794
|
+
return res;
|
|
721
795
|
};
|
|
722
796
|
|
|
723
797
|
class TemplateZod {
|
|
@@ -733,7 +807,7 @@ class TemplateZod {
|
|
|
733
807
|
}
|
|
734
808
|
let imports = "";
|
|
735
809
|
for (const cl of Array.from(this.importClasses).sort()) {
|
|
736
|
-
imports += `import { ${cl} } from './${cl}'
|
|
810
|
+
imports += `import { ${cl} } from './${cl}.js'
|
|
737
811
|
`;
|
|
738
812
|
}
|
|
739
813
|
let exportedVariableString;
|
|
@@ -933,7 +1007,7 @@ class TemplateZodArray {
|
|
|
933
1007
|
render = (name) => {
|
|
934
1008
|
const cls = name.replace("Array", "");
|
|
935
1009
|
const template = `import { z } from 'zod'
|
|
936
|
-
import { ${cls} } from './${cls}'
|
|
1010
|
+
import { ${cls} } from './${cls}.js'
|
|
937
1011
|
|
|
938
1012
|
export const ${name} = z.array(${cls})
|
|
939
1013
|
|
|
@@ -972,15 +1046,138 @@ const extractEnumObject = (type, isRequired, enumArr) => {
|
|
|
972
1046
|
};
|
|
973
1047
|
};
|
|
974
1048
|
|
|
975
|
-
const
|
|
1049
|
+
const templateApiMethod = ({
|
|
1050
|
+
classMethod,
|
|
1051
|
+
description,
|
|
1052
|
+
httpMethod,
|
|
1053
|
+
path,
|
|
1054
|
+
pathParams,
|
|
1055
|
+
bodyParams,
|
|
1056
|
+
responseClass,
|
|
1057
|
+
classGenName,
|
|
1058
|
+
methodParams,
|
|
1059
|
+
methodParamsNoTypes
|
|
1060
|
+
}) => {
|
|
1061
|
+
let methodSignature = "";
|
|
1062
|
+
let newPath = `'${path}'`;
|
|
1063
|
+
let snippetSdk = "";
|
|
1064
|
+
let snippetShell = "";
|
|
1065
|
+
for (const pathParam of pathParams) {
|
|
1066
|
+
const type = ParserUtils.parseType(pathParam);
|
|
1067
|
+
if (pathParam.name !== "namespace") {
|
|
1068
|
+
methodSignature += pathParam.name + `:${type}, `;
|
|
1069
|
+
}
|
|
1070
|
+
const pName = pathParam.name === "namespace" ? "this.namespace" : pathParam.name;
|
|
1071
|
+
if (path.match(`{${pathParam.name}}`)) {
|
|
1072
|
+
if (type === "string") {
|
|
1073
|
+
newPath = `${newPath}.replace('{${pathParam.name}}', ${pName})`;
|
|
1074
|
+
} else {
|
|
1075
|
+
newPath = `${newPath}.replace('{${pathParam.name}}', String(${pName}))`;
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
snippetShell = `curl --location --request \\
|
|
1080
|
+
${httpMethod} '__DOMAIN__${path}' \\
|
|
1081
|
+
--header 'accept: application/json'`;
|
|
1082
|
+
if (httpMethod !== "get") {
|
|
1083
|
+
const curlParams = bodyParams?.map((ob) => {
|
|
1084
|
+
return ` "${ob.name}": ""`;
|
|
1085
|
+
});
|
|
1086
|
+
snippetShell += ` \\
|
|
1087
|
+
--data-raw '{ ${curlParams}}'`;
|
|
1088
|
+
}
|
|
1089
|
+
const descriptionText = description ? `
|
|
1090
|
+
/**
|
|
1091
|
+
* ${description.replace(/\n/g, "\n * ")}
|
|
1092
|
+
*/` : "";
|
|
1093
|
+
const resolvedResponseClass = responseClass || "unknown";
|
|
1094
|
+
const responseType = resolvedResponseClass !== "unknown" ? `${resolvedResponseClass}` : "unknown";
|
|
1095
|
+
const methodImpl = `
|
|
1096
|
+
${descriptionText}
|
|
1097
|
+
async function ${classMethod}(${methodParams}): Promise<${responseType}> {
|
|
1098
|
+
const $ = new ${classGenName}(Network.create(requestConfig), namespace, cache)
|
|
1099
|
+
const resp = await $.${classMethod}(${methodParamsNoTypes})
|
|
1100
|
+
if (resp.error) throw resp.error
|
|
1101
|
+
return resp.response.data
|
|
1102
|
+
}
|
|
1103
|
+
`;
|
|
1104
|
+
const snippetPromiseString = responseType !== "unknown" ? `Promise<${responseType}>` : "Promise";
|
|
1105
|
+
snippetSdk += `${classMethod}(${methodParams})
|
|
1106
|
+
// return ${snippetPromiseString}`;
|
|
1107
|
+
return [methodImpl, snippetSdk, snippetShell];
|
|
1108
|
+
};
|
|
1109
|
+
|
|
1110
|
+
const templateApiIndex = (serviceName, serviceNameTitle, apiList) => {
|
|
1111
|
+
let imports = "";
|
|
1112
|
+
let returnStatement = "";
|
|
1113
|
+
for (const cl of apiList) {
|
|
1114
|
+
imports += `
|
|
1115
|
+
import { ${cl} } from './${serviceName}/${cl}.js'`;
|
|
1116
|
+
returnStatement += `
|
|
1117
|
+
${cl}, `;
|
|
1118
|
+
}
|
|
1119
|
+
return `/**
|
|
1120
|
+
* AUTO GENERATED
|
|
1121
|
+
*/
|
|
1122
|
+
${imports}
|
|
1123
|
+
|
|
1124
|
+
const apis = {
|
|
1125
|
+
${returnStatement}
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
export const ${ParserUtils.convertDashesToTitleCase(serviceNameTitle)} = apis
|
|
1129
|
+
`;
|
|
1130
|
+
};
|
|
1131
|
+
|
|
1132
|
+
const templateSdkSnippet = (serviceNameTitle, apiName, methodSnippet) => {
|
|
1133
|
+
const methodArr = methodSnippet.split("//");
|
|
1134
|
+
let normMethod = normalizeMethodSnippet(methodArr[0].trim(), "data:");
|
|
1135
|
+
normMethod = normalizeMethodSnippet(normMethod, "queryParams:");
|
|
1136
|
+
normMethod = normalizeMethodSnippet(normMethod, "queryParams?:");
|
|
1137
|
+
normMethod += "\n\n//" + methodArr[1];
|
|
1138
|
+
const sdkSnippet = `import { Accelbyte } from '@accelbyte/sdk'
|
|
1139
|
+
import { ${serviceNameTitle} } from '@accelbyte/sdk-${serviceNameTitle.toLowerCase()}'
|
|
1140
|
+
|
|
1141
|
+
const sdk = Accelbyte.SDK({
|
|
1142
|
+
baseURL: 'https://demo.accelbyte.io',
|
|
1143
|
+
clientId: '77f88506b6174c3ea4d925f5b4096ce8',
|
|
1144
|
+
namespace: 'accelbyte',
|
|
1145
|
+
redirectURI: 'http://localhost:3030'
|
|
1146
|
+
})
|
|
1147
|
+
|
|
1148
|
+
${serviceNameTitle}.${apiName}(sdk)
|
|
1149
|
+
.${normMethod}`;
|
|
1150
|
+
return sdkSnippet;
|
|
1151
|
+
};
|
|
1152
|
+
const normalizeMethodSnippet = (methodInput, splitWord) => {
|
|
1153
|
+
const split1 = methodInput.split(splitWord);
|
|
1154
|
+
if (!split1[1]) {
|
|
1155
|
+
return methodInput;
|
|
1156
|
+
}
|
|
1157
|
+
let split2 = split1[1].trim();
|
|
1158
|
+
split2 = ParserUtils.replaceAll(split2, "{", "");
|
|
1159
|
+
split2 = ParserUtils.replaceAll(split2, "})", "");
|
|
1160
|
+
split2 = split2.split(",");
|
|
1161
|
+
let params = "";
|
|
1162
|
+
split2.forEach((p) => {
|
|
1163
|
+
params += "\n " + ParserUtils.replaceAll(p.trim(), ")", "") + ",";
|
|
1164
|
+
});
|
|
1165
|
+
params = params.slice(0, -1);
|
|
1166
|
+
const result = split1[0] + splitWord + " {" + params + "\n })";
|
|
1167
|
+
return result;
|
|
1168
|
+
};
|
|
1169
|
+
|
|
1170
|
+
const GIT_URL = "https://github.com/AccelByte/accelbyte-web-sdk/blob/main/packages";
|
|
976
1171
|
class CodeGenerator {
|
|
977
1172
|
static getPatchedDir = () => path.join(CliParser.getSwaggersOutputPath(), "patched");
|
|
978
1173
|
static getGeneratedPublicFolder = () => `${CliParser.getOutputPath()}/generated-public`;
|
|
979
1174
|
static getGeneratedAdminFolder = () => `${CliParser.getOutputPath()}/generated-admin`;
|
|
980
1175
|
static getGeneratedSnippetsFolder = () => `${CliParser.getSnippetOutputPath()}/generated-snippets`;
|
|
981
1176
|
static getServicePrefix = (servicePaths) => servicePaths[servicePaths.length - 1].split("/")[1];
|
|
982
|
-
static iterateApi = async (api) => {
|
|
1177
|
+
static iterateApi = async (api, serviceName) => {
|
|
983
1178
|
const apiBufferByTag = {};
|
|
1179
|
+
const apiArgumentsByTag = {};
|
|
1180
|
+
const classBufferByTag = {};
|
|
984
1181
|
const dependenciesByTag = {};
|
|
985
1182
|
const classImports = {};
|
|
986
1183
|
let arrayDefinitions = [];
|
|
@@ -995,7 +1192,6 @@ class CodeGenerator {
|
|
|
995
1192
|
}));
|
|
996
1193
|
const sortedKeys = Array.from(sortedPathsByLength.keys());
|
|
997
1194
|
const servicePrefix = CodeGenerator.getServicePrefix(sortedKeys);
|
|
998
|
-
console.log("ServicePrefix", servicePrefix, ", Paths:", sortedKeys);
|
|
999
1195
|
for (const [path2, operation] of sortedPathsByLength) {
|
|
1000
1196
|
const isAdminEndpoint = path2.indexOf("/admin/") > -1;
|
|
1001
1197
|
if (CliParser.isAdmin() && !isAdminEndpoint) {
|
|
@@ -1027,13 +1223,15 @@ class CodeGenerator {
|
|
|
1027
1223
|
});
|
|
1028
1224
|
mapClassMethods[tag][classMethod] = `${path2} ${httpMethod}`;
|
|
1029
1225
|
snippetMap[path2] = snippetMap[path2] ? snippetMap[path2] : {};
|
|
1030
|
-
|
|
1226
|
+
let description = endpoint.description;
|
|
1227
|
+
description = description || "";
|
|
1228
|
+
description = description.replace(/\s+/g, " ");
|
|
1031
1229
|
const responseClass = ParserUtils.get2xxResponse(endpoint.responses);
|
|
1032
1230
|
const { className, classGenName } = ParserUtils.generateClassName(tag);
|
|
1033
1231
|
classImports[className] = classImports[className] ? classImports[className] : {};
|
|
1034
1232
|
if (responseClass) {
|
|
1035
1233
|
const importTypeClass = ParserUtils.parseRefType(responseClass);
|
|
1036
|
-
classImports[className][importTypeClass] = `import { ${importTypeClass} } from '
|
|
1234
|
+
classImports[className][importTypeClass] = `import { ${importTypeClass} } from '../definitions/${importTypeClass}.js'`;
|
|
1037
1235
|
}
|
|
1038
1236
|
if (responseClass && responseClass.endsWith("Array")) {
|
|
1039
1237
|
arrayDefinitions.push(responseClass);
|
|
@@ -1052,7 +1250,7 @@ class CodeGenerator {
|
|
|
1052
1250
|
}
|
|
1053
1251
|
];
|
|
1054
1252
|
}
|
|
1055
|
-
const
|
|
1253
|
+
const { methodImpl, methodParams, methodParamsNoTypes, importStatements } = templateMethod({
|
|
1056
1254
|
classMethod,
|
|
1057
1255
|
description,
|
|
1058
1256
|
httpMethod,
|
|
@@ -1063,16 +1261,42 @@ class CodeGenerator {
|
|
|
1063
1261
|
isFormUrlEncoded,
|
|
1064
1262
|
responseClass
|
|
1065
1263
|
});
|
|
1066
|
-
|
|
1264
|
+
classBufferByTag[tag] = (classBufferByTag[tag] || "") + methodImpl;
|
|
1265
|
+
const [generatedMethodString1, snippetMethod, snippetShell] = templateApiMethod({
|
|
1266
|
+
classMethod,
|
|
1267
|
+
description,
|
|
1268
|
+
httpMethod,
|
|
1269
|
+
path: pathWithBase,
|
|
1270
|
+
pathParams,
|
|
1271
|
+
bodyParams,
|
|
1272
|
+
responseClass,
|
|
1273
|
+
classGenName,
|
|
1274
|
+
methodParams,
|
|
1275
|
+
methodParamsNoTypes
|
|
1276
|
+
});
|
|
1277
|
+
apiBufferByTag[tag] = (apiBufferByTag[tag] || "") + generatedMethodString1;
|
|
1278
|
+
apiArgumentsByTag[tag] = (apiArgumentsByTag[tag] || "") + classMethod + ",";
|
|
1067
1279
|
dependenciesByTag[tag] = dependenciesByTag[tag] ? [.../* @__PURE__ */ new Set([...importStatements, ...dependenciesByTag[tag]])] : [...new Set(importStatements)];
|
|
1280
|
+
const serviceNameTitle = ParserUtils.convertDashesToTitleCase(serviceName);
|
|
1281
|
+
const { apiGenName } = ParserUtils.generateApiName(tag);
|
|
1282
|
+
const resultSnippet = templateSdkSnippet(serviceNameTitle, apiGenName, snippetMethod);
|
|
1068
1283
|
snippetMap[path2][httpMethod] = {
|
|
1069
|
-
web:
|
|
1070
|
-
|
|
1284
|
+
web: resultSnippet,
|
|
1285
|
+
webGit: GIT_URL + `/sdk-${serviceName}/src/generated-public/${serviceName}/${apiGenName}.ts`,
|
|
1286
|
+
shell: snippetShell
|
|
1071
1287
|
};
|
|
1072
1288
|
}
|
|
1073
1289
|
}
|
|
1074
1290
|
arrayDefinitions = [...new Set(arrayDefinitions)];
|
|
1075
|
-
return {
|
|
1291
|
+
return {
|
|
1292
|
+
apiArgumentsByTag,
|
|
1293
|
+
apiBufferByTag,
|
|
1294
|
+
classBufferByTag,
|
|
1295
|
+
dependenciesByTag,
|
|
1296
|
+
classImports,
|
|
1297
|
+
arrayDefinitions,
|
|
1298
|
+
snippetMap
|
|
1299
|
+
};
|
|
1076
1300
|
};
|
|
1077
1301
|
static main = async (nameArray) => {
|
|
1078
1302
|
const serviceName = nameArray[0];
|
|
@@ -1080,6 +1304,7 @@ class CodeGenerator {
|
|
|
1080
1304
|
const parser = new SwaggerParser();
|
|
1081
1305
|
const generatedFolder = CliParser.isAdmin() ? CodeGenerator.getGeneratedAdminFolder() : CodeGenerator.getGeneratedPublicFolder();
|
|
1082
1306
|
const DIST_DIR = `${generatedFolder}/${serviceName}`;
|
|
1307
|
+
const DIST_ENDPOINTS_DIR = path.join(DIST_DIR, "endpoints");
|
|
1083
1308
|
const DIST_DEFINITION_DIR = path.join(DIST_DIR, "definitions");
|
|
1084
1309
|
const swaggerFilePath = `${CliParser.getSwaggersOutputPath()}/${swaggerFile}`;
|
|
1085
1310
|
const swaggerPatchedFilePath = `${CodeGenerator.getPatchedDir()}/${swaggerFile}`;
|
|
@@ -1090,19 +1315,32 @@ class CodeGenerator {
|
|
|
1090
1315
|
console.log("----------\nGenerating API:", { title: api.info.title, version: api.info.version });
|
|
1091
1316
|
ParserUtils.mkdirIfNotExist(DIST_DIR);
|
|
1092
1317
|
ParserUtils.mkdirIfNotExist(DIST_DEFINITION_DIR);
|
|
1093
|
-
ParserUtils.
|
|
1094
|
-
|
|
1318
|
+
ParserUtils.mkdirIfNotExist(DIST_ENDPOINTS_DIR);
|
|
1319
|
+
ParserUtils.syncPackageVersion(api.info, CliParser.isAdmin());
|
|
1320
|
+
const { apiArgumentsByTag, apiBufferByTag, classBufferByTag, dependenciesByTag, classImports, arrayDefinitions, snippetMap } = await CodeGenerator.iterateApi(api, serviceName);
|
|
1095
1321
|
if (CliParser.getSnippetOutputPath()) {
|
|
1096
1322
|
ParserUtils.writeSnippetFile(CodeGenerator.getGeneratedSnippetsFolder(), api.info.title, JSON.stringify(snippetMap, null, 2));
|
|
1097
1323
|
}
|
|
1098
1324
|
const targetSrcFolder = `${CliParser.getOutputPath()}/`;
|
|
1099
|
-
|
|
1325
|
+
const apiList = [];
|
|
1326
|
+
for (const tag in classBufferByTag) {
|
|
1100
1327
|
const { className, classGenName } = ParserUtils.generateClassName(tag);
|
|
1101
|
-
const
|
|
1328
|
+
const classBuffer = classBufferByTag[tag];
|
|
1102
1329
|
const imports = [.../* @__PURE__ */ new Set([...dependenciesByTag[tag], ...Object.values(classImports[className])])];
|
|
1103
|
-
|
|
1104
|
-
|
|
1330
|
+
const apiImports = [.../* @__PURE__ */ new Set([...dependenciesByTag[tag], ...Object.values(classImports[className])])];
|
|
1331
|
+
apiImports.push(`import { ${classGenName} } from './endpoints/${classGenName}.js'`);
|
|
1332
|
+
ParserUtils.writeClassFile(DIST_ENDPOINTS_DIR, classGenName, classBuffer, imports);
|
|
1333
|
+
const apiBuffer = apiBufferByTag[tag];
|
|
1334
|
+
const { apiGenName } = ParserUtils.generateApiName(tag);
|
|
1335
|
+
ParserUtils.writeApiFile(DIST_DIR, apiGenName, apiBuffer, apiImports, apiArgumentsByTag[tag]);
|
|
1336
|
+
apiList.push(apiGenName);
|
|
1337
|
+
indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path.join(DIST_ENDPOINTS_DIR, `${classGenName}`), targetSrcFolder));
|
|
1338
|
+
indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path.join(DIST_DIR, `${apiGenName}`), targetSrcFolder));
|
|
1105
1339
|
}
|
|
1340
|
+
const serviceNameTitle = ParserUtils.convertDashesToTitleCase(serviceName);
|
|
1341
|
+
const apiIndexBuff = templateApiIndex(serviceName, serviceNameTitle, apiList);
|
|
1342
|
+
ParserUtils.writeApiMainFile(generatedFolder, serviceNameTitle, apiIndexBuff);
|
|
1343
|
+
indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path.join(generatedFolder, serviceNameTitle), targetSrcFolder));
|
|
1106
1344
|
const duplicates = /* @__PURE__ */ new Map();
|
|
1107
1345
|
const definitions = api?.components?.schemas || api.definitions;
|
|
1108
1346
|
for (const ref in definitions) {
|
|
@@ -1147,6 +1385,22 @@ class SwaggerDownloader {
|
|
|
1147
1385
|
fs__namespace.writeFileSync(destFile, "");
|
|
1148
1386
|
return destFile;
|
|
1149
1387
|
};
|
|
1388
|
+
static postSanitizeDownloadedFile = (filePath) => {
|
|
1389
|
+
const searchStr = ["%5B", "%5D", "%20", "%7B", "%7D"];
|
|
1390
|
+
fs__namespace.readFile(filePath, "utf8", (err, data) => {
|
|
1391
|
+
if (err)
|
|
1392
|
+
throw err;
|
|
1393
|
+
let result = data;
|
|
1394
|
+
searchStr.forEach((s) => {
|
|
1395
|
+
result = result.replace(new RegExp(s, "g"), " ");
|
|
1396
|
+
});
|
|
1397
|
+
fs__namespace.writeFile(filePath, result, "utf8", (err2) => {
|
|
1398
|
+
if (err2)
|
|
1399
|
+
throw err2;
|
|
1400
|
+
console.log("File updated successfully.");
|
|
1401
|
+
});
|
|
1402
|
+
});
|
|
1403
|
+
};
|
|
1150
1404
|
static downloadFile = (targetFileName, url) => {
|
|
1151
1405
|
const destFile = SwaggerDownloader.getDestFile(targetFileName);
|
|
1152
1406
|
const file = fs__namespace.createWriteStream(destFile);
|
|
@@ -1154,6 +1408,7 @@ class SwaggerDownloader {
|
|
|
1154
1408
|
response.pipe(file);
|
|
1155
1409
|
file.on("finish", () => {
|
|
1156
1410
|
file.close();
|
|
1411
|
+
SwaggerDownloader.postSanitizeDownloadedFile(destFile);
|
|
1157
1412
|
console.log(`SwaggerDownload ${url} completed`);
|
|
1158
1413
|
});
|
|
1159
1414
|
});
|