@accelbyte/codegen 1.0.5 → 2.0.0-beta.10
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.
|
@@ -78,6 +78,9 @@ class CliParser {
|
|
|
78
78
|
static getSnippetOutputPath = () => {
|
|
79
79
|
return CliParser.instance().argv.snippetOutput;
|
|
80
80
|
};
|
|
81
|
+
static skipVersionSync = () => {
|
|
82
|
+
return CliParser.instance().argv.skipVersionSync;
|
|
83
|
+
};
|
|
81
84
|
}
|
|
82
85
|
|
|
83
86
|
const getImportableVarMap$1 = () => ({
|
|
@@ -146,6 +149,79 @@ export function ${className}(sdk: AccelbyteSDK, args?: ApiArgs) {
|
|
|
146
149
|
`;
|
|
147
150
|
};
|
|
148
151
|
|
|
152
|
+
const VersionBumpType = zod.z.enum(["CUTOFF", "RELEASE", "HOTFIX"]);
|
|
153
|
+
class VersionHelpers {
|
|
154
|
+
static getNextVersion = ({
|
|
155
|
+
codegenVersion,
|
|
156
|
+
serviceVersion,
|
|
157
|
+
predefinedMajorVersion,
|
|
158
|
+
versionBumpType,
|
|
159
|
+
sdkVersion,
|
|
160
|
+
nextPrereleaseId
|
|
161
|
+
}) => {
|
|
162
|
+
if (versionBumpType !== void 0) {
|
|
163
|
+
const parsed = VersionBumpType.safeParse(versionBumpType);
|
|
164
|
+
if (!parsed.success) {
|
|
165
|
+
throw new Error(`Invalid process.env.VERSION_BUMP_TYPE: ${versionBumpType}`);
|
|
166
|
+
}
|
|
167
|
+
if ((parsed.data === "HOTFIX" || parsed.data === "RELEASE") && nextPrereleaseId) {
|
|
168
|
+
throw new Error(`process.env.PRERELEASE_ID should be empty when process.env.VERSION_BUMP_TYPE is "HOTFIX" or "PRELEASE".`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const codegenSemvers = semver.parse(codegenVersion);
|
|
172
|
+
const serviceSemvers = semver.parse(serviceVersion);
|
|
173
|
+
const sdkSemvers = semver.parse(sdkVersion);
|
|
174
|
+
if (codegenSemvers === null) {
|
|
175
|
+
throw new Error(`Invalid codegen version: ${codegenVersion}`);
|
|
176
|
+
}
|
|
177
|
+
if (serviceSemvers === null) {
|
|
178
|
+
throw new Error(`Invalid service version: ${serviceVersion}`);
|
|
179
|
+
}
|
|
180
|
+
if (sdkSemvers === null) {
|
|
181
|
+
throw new Error(`Invalid sdk version: ${sdkVersion}`);
|
|
182
|
+
}
|
|
183
|
+
const { major: currentMajor, minor: currentMinor, patch: currentPatch, prerelease: currentPrerelease } = sdkSemvers;
|
|
184
|
+
const nextMajor = codegenSemvers.major + predefinedMajorVersion;
|
|
185
|
+
const shouldResetVersion = nextMajor !== currentMajor;
|
|
186
|
+
let nextMinor = currentMinor;
|
|
187
|
+
let nextPatch = currentPatch;
|
|
188
|
+
switch (versionBumpType) {
|
|
189
|
+
case VersionBumpType.Enum.CUTOFF: {
|
|
190
|
+
nextMinor++;
|
|
191
|
+
nextPatch = 0;
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
case VersionBumpType.Enum.RELEASE:
|
|
195
|
+
break;
|
|
196
|
+
case VersionBumpType.Enum.HOTFIX: {
|
|
197
|
+
nextPatch++;
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (shouldResetVersion) {
|
|
202
|
+
nextMinor = 0;
|
|
203
|
+
nextPatch = 0;
|
|
204
|
+
}
|
|
205
|
+
let nextVersion = [
|
|
206
|
+
codegenSemvers.major + predefinedMajorVersion,
|
|
207
|
+
nextMinor,
|
|
208
|
+
nextPatch
|
|
209
|
+
].join(".");
|
|
210
|
+
if (nextPrereleaseId) {
|
|
211
|
+
if (nextMinor !== currentMinor || nextMajor !== currentMajor) {
|
|
212
|
+
nextVersion += `-${nextPrereleaseId}.0`;
|
|
213
|
+
} else {
|
|
214
|
+
if (currentPrerelease.length)
|
|
215
|
+
nextVersion += `-${currentPrerelease.join(".")}`;
|
|
216
|
+
nextVersion = semver.inc(nextVersion, "prerelease", void 0, nextPrereleaseId);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return nextVersion;
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const codegenPackageJsonPath = path.join(__dirname, "../package.json");
|
|
224
|
+
const codegenPackageJSON = JSON.parse(fs.readFileSync(codegenPackageJsonPath, "utf-8"));
|
|
149
225
|
const UNDEFINED_SWAGGER_SEMVER = "0.0.0";
|
|
150
226
|
const REMOVED_KEYWORDS = [
|
|
151
227
|
"/admin/",
|
|
@@ -163,14 +239,14 @@ class ParserUtils {
|
|
|
163
239
|
static replaceAll = (string, search, replace) => {
|
|
164
240
|
return string.split(search).join(replace);
|
|
165
241
|
};
|
|
166
|
-
static generateClassName = (tag) => {
|
|
242
|
+
static generateClassName = (tag, isAdmin) => {
|
|
167
243
|
const className = _.upperFirst(_.camelCase(tag));
|
|
168
|
-
const classGenName =
|
|
244
|
+
const classGenName = isAdmin ? className + "Admin$" : className + "$";
|
|
169
245
|
return { className, classGenName };
|
|
170
246
|
};
|
|
171
|
-
static generateApiName = (tag) => {
|
|
247
|
+
static generateApiName = (tag, isAdmin) => {
|
|
172
248
|
const apiName = _.upperFirst(_.camelCase(tag));
|
|
173
|
-
const apiGenName =
|
|
249
|
+
const apiGenName = isAdmin ? apiName + "AdminApi" : apiName + "Api";
|
|
174
250
|
return { apiName, apiGenName };
|
|
175
251
|
};
|
|
176
252
|
static parseQueryParamAttributeDefault = (definition) => {
|
|
@@ -270,6 +346,12 @@ class ParserUtils {
|
|
|
270
346
|
if (definition?.schema?.type && definition.schema.type === "array") {
|
|
271
347
|
return `${attrName}${required}: ${definition.schema.items.type ?? "any"}[]`;
|
|
272
348
|
}
|
|
349
|
+
if (definition.type && definition.type === "file") {
|
|
350
|
+
return `${attrName}${required}: File`;
|
|
351
|
+
}
|
|
352
|
+
if (definition?.schema?.type && definition.schema.type === "file") {
|
|
353
|
+
return `${attrName}${required}: File`;
|
|
354
|
+
}
|
|
273
355
|
if (definition.type && definition.type) {
|
|
274
356
|
return `${attrName}${required}: ${definition.type} | null`;
|
|
275
357
|
}
|
|
@@ -449,42 +531,21 @@ class ParserUtils {
|
|
|
449
531
|
ParserUtils.mkdirIfNotExist(distDir);
|
|
450
532
|
fs.writeFileSync(path.join(distDir, `all-${isAdminWebSdk ? "admin" : "public"}-imports.ts`), ParserUtils.prependCopyrightHeader(buffer));
|
|
451
533
|
}
|
|
452
|
-
static
|
|
453
|
-
|
|
454
|
-
const pathToChangelog = path.join(currDir, "./CHANGELOG.md");
|
|
455
|
-
let fileContent = fs.readFileSync(pathToChangelog, "utf-8");
|
|
456
|
-
const date = new Date().toISOString().slice(0, 10);
|
|
457
|
-
fileContent = "### " + packageVersion + " - " + date + `
|
|
458
|
-
|
|
459
|
-
- code-generated update
|
|
460
|
-
|
|
461
|
-
` + fileContent.trim();
|
|
462
|
-
fs.writeFileSync(pathToChangelog, fileContent, "utf-8");
|
|
463
|
-
}
|
|
464
|
-
static syncPackageVersion(apiInfo, isAdminWebSdk, prereleaseId) {
|
|
465
|
-
if (isAdminWebSdk) {
|
|
534
|
+
static syncPackageVersion(apiInfo, skipVersionSync, prereleaseId) {
|
|
535
|
+
if (skipVersionSync)
|
|
466
536
|
return;
|
|
467
|
-
}
|
|
468
537
|
const currDir = process.cwd();
|
|
469
538
|
const { packageJSON, pathToPackageJSON } = ParserUtils.getPackageJSONInfo(currDir);
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
nextSemver += `-${id}.${rest.join(".")}`;
|
|
479
|
-
}
|
|
480
|
-
if (!prereleaseId) {
|
|
481
|
-
nextSemver = semver.inc(nextSemver, "patch");
|
|
482
|
-
} else {
|
|
483
|
-
nextSemver = semver.inc(nextSemver, "prerelease", void 0, prereleaseId);
|
|
484
|
-
}
|
|
539
|
+
const nextSemver = VersionHelpers.getNextVersion({
|
|
540
|
+
codegenVersion: codegenPackageJSON.version,
|
|
541
|
+
serviceVersion: apiInfo["x-version"] || apiInfo.version || UNDEFINED_SWAGGER_SEMVER,
|
|
542
|
+
predefinedMajorVersion: packageJSON.predefinedMajorVersion || 0,
|
|
543
|
+
versionBumpType: process.env.VERSION_BUMP_TYPE,
|
|
544
|
+
sdkVersion: packageJSON.version,
|
|
545
|
+
nextPrereleaseId: prereleaseId
|
|
546
|
+
});
|
|
485
547
|
packageJSON.version = nextSemver;
|
|
486
548
|
fs.writeFileSync(pathToPackageJSON, JSON.stringify(packageJSON, null, 2));
|
|
487
|
-
ParserUtils.syncChangelog(packageJSON.version);
|
|
488
549
|
}
|
|
489
550
|
static getPackageJSONInfo(dir) {
|
|
490
551
|
const pathToPackageJSON = path.join(dir, "./package.json");
|
|
@@ -563,7 +624,9 @@ class ParserUtils {
|
|
|
563
624
|
${content}`;
|
|
564
625
|
};
|
|
565
626
|
static sortPathParamsByPath = (pathParams, path2) => {
|
|
566
|
-
|
|
627
|
+
const params = path2.match(/{\w*}/g) || [];
|
|
628
|
+
const cleanParams = params.map((param) => param.replace("{", "").replace("}", ""));
|
|
629
|
+
return pathParams.sort((a, b) => cleanParams.indexOf(a.name) - cleanParams.indexOf(b.name));
|
|
567
630
|
};
|
|
568
631
|
}
|
|
569
632
|
const mappedMethod = (httpMethod, isForm) => {
|
|
@@ -631,205 +694,6 @@ const isSwaggerIntegerType = (type) => {
|
|
|
631
694
|
return type === "integer" || type === "int";
|
|
632
695
|
};
|
|
633
696
|
|
|
634
|
-
const Schema = zod.z.object({
|
|
635
|
-
$ref: zod.z.string().nullish(),
|
|
636
|
-
type: zod.z.union([zod.z.literal("array"), zod.z.literal("object"), zod.z.literal("file"), zod.z.literal("string"), zod.z.literal("boolean"), zod.z.literal("integer")]).nullish(),
|
|
637
|
-
items: zod.z.object({
|
|
638
|
-
$ref: zod.z.string().nullish(),
|
|
639
|
-
type: zod.z.string().nullish()
|
|
640
|
-
}).nullish(),
|
|
641
|
-
properties: zod.z.union([zod.z.array(zod.z.string()).nullish(), zod.z.record(zod.z.object({ type: zod.z.string() })).nullish()]),
|
|
642
|
-
description: zod.z.string().nullish(),
|
|
643
|
-
additionalProperties: zod.z.object({
|
|
644
|
-
type: zod.z.string().nullish()
|
|
645
|
-
}).nullish()
|
|
646
|
-
});
|
|
647
|
-
const Definition = zod.z.object({
|
|
648
|
-
required: zod.z.array(zod.z.string()).nullish(),
|
|
649
|
-
properties: zod.z.record(zod.z.object({
|
|
650
|
-
type: zod.z.string()
|
|
651
|
-
})).nullish()
|
|
652
|
-
});
|
|
653
|
-
const Definitions = zod.z.record(Definition);
|
|
654
|
-
const EndpointParametersType = zod.z.enum(["apiKey", "boolean", "int", "integer", "number", "string", "array", "file"]);
|
|
655
|
-
const EndpointParametersIn = zod.z.enum(["body", "formData", "header", "path", "query"]);
|
|
656
|
-
const EndpointParameters = zod.z.object({
|
|
657
|
-
type: EndpointParametersType.nullish(),
|
|
658
|
-
description: zod.z.string().nullish(),
|
|
659
|
-
name: zod.z.string(),
|
|
660
|
-
in: EndpointParametersIn,
|
|
661
|
-
required: zod.z.boolean().nullish(),
|
|
662
|
-
schema: Schema.nullish(),
|
|
663
|
-
default: zod.z.union([zod.z.boolean(), zod.z.string(), zod.z.number(), zod.z.array(zod.z.any())]).nullish(),
|
|
664
|
-
enum: zod.z.array(zod.z.union([zod.z.boolean(), zod.z.string(), zod.z.number()])).nullish(),
|
|
665
|
-
items: zod.z.object({
|
|
666
|
-
type: zod.z.string(),
|
|
667
|
-
enum: zod.z.array(zod.z.any()).nullish()
|
|
668
|
-
}).nullish()
|
|
669
|
-
});
|
|
670
|
-
const Endpoint = zod.z.object({
|
|
671
|
-
description: zod.z.string().nullish(),
|
|
672
|
-
consumes: zod.z.array(zod.z.string()).nullish(),
|
|
673
|
-
produces: zod.z.array(zod.z.string()).nullish(),
|
|
674
|
-
tags: zod.z.array(zod.z.string()).nullish(),
|
|
675
|
-
summary: zod.z.string().nullish(),
|
|
676
|
-
operationId: zod.z.string(),
|
|
677
|
-
deprecated: zod.z.boolean().nullish(),
|
|
678
|
-
responses: zod.z.record(zod.z.object({
|
|
679
|
-
description: zod.z.string().nullish(),
|
|
680
|
-
schema: Schema.nullish(),
|
|
681
|
-
content: zod.z.object({
|
|
682
|
-
"application/json": zod.z.object({
|
|
683
|
-
schema: Schema.nullish()
|
|
684
|
-
})
|
|
685
|
-
}).nullish()
|
|
686
|
-
})),
|
|
687
|
-
parameters: zod.z.array(EndpointParameters).nullish(),
|
|
688
|
-
requestBody: zod.z.object({
|
|
689
|
-
required: zod.z.boolean(),
|
|
690
|
-
content: zod.z.object({
|
|
691
|
-
"application/json": zod.z.object({
|
|
692
|
-
schema: Schema.nullish()
|
|
693
|
-
})
|
|
694
|
-
}).nullish()
|
|
695
|
-
}).nullish()
|
|
696
|
-
});
|
|
697
|
-
const Operation = zod.z.object({
|
|
698
|
-
get: Endpoint.nullish(),
|
|
699
|
-
post: Endpoint.nullish(),
|
|
700
|
-
patch: Endpoint.nullish(),
|
|
701
|
-
delete: Endpoint.nullish(),
|
|
702
|
-
put: Endpoint.nullish()
|
|
703
|
-
});
|
|
704
|
-
const Paths = zod.z.record(Operation);
|
|
705
|
-
zod.z.object({
|
|
706
|
-
paths: Paths,
|
|
707
|
-
definitions: Definitions,
|
|
708
|
-
basePath: zod.z.string(),
|
|
709
|
-
info: zod.z.object({
|
|
710
|
-
description: zod.z.string(),
|
|
711
|
-
title: zod.z.string(),
|
|
712
|
-
contact: zod.z.object({
|
|
713
|
-
name: zod.z.string(),
|
|
714
|
-
url: zod.z.string(),
|
|
715
|
-
email: zod.z.string()
|
|
716
|
-
}),
|
|
717
|
-
version: zod.z.string()
|
|
718
|
-
}),
|
|
719
|
-
schemes: zod.z.array(zod.z.string()).nullish(),
|
|
720
|
-
components: zod.z.object({
|
|
721
|
-
schemas: Definitions
|
|
722
|
-
}).nullish()
|
|
723
|
-
});
|
|
724
|
-
|
|
725
|
-
const templateMethod = ({
|
|
726
|
-
classMethod,
|
|
727
|
-
description,
|
|
728
|
-
httpMethod,
|
|
729
|
-
path,
|
|
730
|
-
pathParams,
|
|
731
|
-
bodyParams,
|
|
732
|
-
queryParams,
|
|
733
|
-
isFormUrlEncoded,
|
|
734
|
-
responseClass
|
|
735
|
-
}) => {
|
|
736
|
-
let methodParams = "";
|
|
737
|
-
let methodParamsNoTypes = "";
|
|
738
|
-
let newPath = `'${path}'`;
|
|
739
|
-
let importStatements = [];
|
|
740
|
-
const sortedPathParams = ParserUtils.sortPathParamsByPath(pathParams, path);
|
|
741
|
-
for (const pathParam of sortedPathParams) {
|
|
742
|
-
const type = ParserUtils.parseType(pathParam);
|
|
743
|
-
if (pathParam.name !== "namespace") {
|
|
744
|
-
methodParams += pathParam.name + `:${type}, `;
|
|
745
|
-
methodParamsNoTypes += pathParam.name + ", ";
|
|
746
|
-
}
|
|
747
|
-
const pName = pathParam.name === "namespace" ? "this.namespace" : pathParam.name;
|
|
748
|
-
if (path.match(`{${pathParam.name}}`)) {
|
|
749
|
-
if (type === "string") {
|
|
750
|
-
newPath = `${newPath}.replace('{${pathParam.name}}', ${pName})`;
|
|
751
|
-
} else {
|
|
752
|
-
newPath = `${newPath}.replace('{${pathParam.name}}', String(${pName}))`;
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
let dataType = null;
|
|
757
|
-
if (httpMethod !== "get") {
|
|
758
|
-
dataType = ParserUtils.parseBodyParamsType(bodyParams);
|
|
759
|
-
importStatements = ParserUtils.parseBodyParamsImports(bodyParams);
|
|
760
|
-
methodParams += dataType ? `data: ${dataType},` : "";
|
|
761
|
-
methodParamsNoTypes += dataType ? `data,` : "";
|
|
762
|
-
}
|
|
763
|
-
const isAnyRequired = ParserUtils.isAnyQueryParamRequired(queryParams);
|
|
764
|
-
const queryParamsType = queryParams.length ? `queryParams${isAnyRequired ? "" : "?"}: {${ParserUtils.parseQueryParamsType(queryParams)}}` : "";
|
|
765
|
-
const queryParamsDefault = queryParams.length ? `const params = {${ParserUtils.parseQueryParamsDefault(queryParams)} ...queryParams} as SDKRequestConfig` : "const params = {} as SDKRequestConfig";
|
|
766
|
-
const isPostPutPatch = ["post", "put", "patch"].includes(httpMethod);
|
|
767
|
-
const isDelete = ["delete"].includes(httpMethod);
|
|
768
|
-
let dataPayload = "{params}";
|
|
769
|
-
const descriptionText = description ? `
|
|
770
|
-
/**
|
|
771
|
-
* ${description.replace(/\n/g, "\n * ")}
|
|
772
|
-
*/` : "";
|
|
773
|
-
let formPayloadString = "";
|
|
774
|
-
if (isFormUrlEncoded) {
|
|
775
|
-
formPayloadString = ``;
|
|
776
|
-
const params = "{ ...params, headers: { ...params.headers, 'content-type': 'application/x-www-form-urlencoded' } }";
|
|
777
|
-
dataPayload = dataType ? `CodeGenUtil.getFormUrlEncodedData(data), ${params}` : `null, ${params}`;
|
|
778
|
-
} else if (isPostPutPatch) {
|
|
779
|
-
dataPayload = dataType ? `data, {params}` : "null, {params}";
|
|
780
|
-
} else if (isDelete) {
|
|
781
|
-
dataPayload = dataType ? `{data, params}` : "{params}";
|
|
782
|
-
}
|
|
783
|
-
const isFileUpload = methodParams.indexOf("data: {file") > -1;
|
|
784
|
-
const resolvedResponseClass = responseClass || "unknown";
|
|
785
|
-
const resolvedResponseClassValidated = responseClass || "z.unknown()";
|
|
786
|
-
methodParams = (queryParamsType ? `${methodParams} ${queryParamsType}` : methodParams).replace(/,\s*$/, "");
|
|
787
|
-
methodParamsNoTypes = queryParamsType ? `${methodParamsNoTypes} queryParams` : methodParamsNoTypes;
|
|
788
|
-
let methodImpl = "";
|
|
789
|
-
const isCacheFetch = ["get"].includes(httpMethod) && resolvedResponseClass !== "unknown";
|
|
790
|
-
const cachedFetchMethod = classMethod;
|
|
791
|
-
const deprecateTag = isCacheFetch ? `/**
|
|
792
|
-
* @deprecated Use "${classMethod}()" instead.
|
|
793
|
-
*/` : "";
|
|
794
|
-
const isGuardInvoked = ["get", "post", "put", "patch", "delete"].includes(httpMethod);
|
|
795
|
-
const methodName = httpMethod === "get" ? cachedFetchMethod : ["post", "put", "patch", "delete"].includes(httpMethod) ? classMethod : "";
|
|
796
|
-
const responseType = resolvedResponseClass !== "unknown" ? `${resolvedResponseClass}` : "unknown";
|
|
797
|
-
const generateMethodName = () => `${methodName}(${methodParams}): Promise<${responseSyncType}<${responseType}>>`;
|
|
798
|
-
const responseSyncType = httpMethod === "get" ? "IResponseWithSync" : ["post", "put", "patch", "delete"].includes(httpMethod) ? "IResponse" : "";
|
|
799
|
-
methodImpl = `${descriptionText}
|
|
800
|
-
${generateMethodName()} {
|
|
801
|
-
${queryParamsDefault}
|
|
802
|
-
const url = ${newPath} ${formPayloadString} ${isFileUpload ? "\n// TODO file upload not implemented" : ""}
|
|
803
|
-
const resultPromise = this.axiosInstance.${httpMethod}(url, ${dataPayload})
|
|
804
|
-
|
|
805
|
-
${httpMethod === "get" ? ` const res = () => Validate.responseType(() => resultPromise, ${resolvedResponseClassValidated}, '${resolvedResponseClassValidated}')
|
|
806
|
-
|
|
807
|
-
if (!this.cache) {
|
|
808
|
-
return SdkCache.withoutCache(res)
|
|
809
|
-
}
|
|
810
|
-
const cacheKey = url + CodeGenUtil.hashCode(JSON.stringify({ params }))
|
|
811
|
-
return SdkCache.withCache(cacheKey, res)` : ""}${["post", "put", "patch", "delete"].includes(httpMethod) ? ` return Validate.responseType(() => resultPromise, ${resolvedResponseClassValidated}, '${resolvedResponseClassValidated}')` : ""}
|
|
812
|
-
}
|
|
813
|
-
`;
|
|
814
|
-
if (!isGuardInvoked) {
|
|
815
|
-
methodImpl = `${descriptionText}
|
|
816
|
-
${deprecateTag}
|
|
817
|
-
TODO_${classMethod}(${methodParams}): Promise<AxiosResponse<${resolvedResponseClass}>> {
|
|
818
|
-
${queryParamsDefault}
|
|
819
|
-
const url = ${newPath} ${formPayloadString} ${isFileUpload ? "\n// TODO file upload not implemented" : ""}
|
|
820
|
-
return this.axiosInstance.${httpMethod}(url, ${dataPayload})
|
|
821
|
-
}
|
|
822
|
-
`;
|
|
823
|
-
}
|
|
824
|
-
const res = {
|
|
825
|
-
methodImpl,
|
|
826
|
-
methodParams,
|
|
827
|
-
methodParamsNoTypes,
|
|
828
|
-
importStatements
|
|
829
|
-
};
|
|
830
|
-
return res;
|
|
831
|
-
};
|
|
832
|
-
|
|
833
697
|
class TemplateZod {
|
|
834
698
|
duplicates;
|
|
835
699
|
duplicateFound = false;
|
|
@@ -914,7 +778,13 @@ ${exportedTypeString}
|
|
|
914
778
|
const schemaAttribute = name ? `'${name}':` : "";
|
|
915
779
|
const typeAttribute = name ? `'${name}'${typeRequired}:` : "";
|
|
916
780
|
const type = definition?.type;
|
|
917
|
-
if (
|
|
781
|
+
if (definition.properties) {
|
|
782
|
+
const result = this.parseToZodSchema(definition, requiredAttrs);
|
|
783
|
+
return {
|
|
784
|
+
schemaString: `${schemaAttribute} ${result.schemaString}${schemaRequired}`,
|
|
785
|
+
typeString: `${typeAttribute} ${result.typeString}${typeNullishability}`
|
|
786
|
+
};
|
|
787
|
+
} else if (type) {
|
|
918
788
|
if (type === "object" && definition.additionalProperties) {
|
|
919
789
|
const zodAttribute = this.parseToZodAttribute("", definition.additionalProperties, [""]);
|
|
920
790
|
return {
|
|
@@ -990,12 +860,6 @@ ${exportedTypeString}
|
|
|
990
860
|
typeString: `${typeAttribute} ${result.typeString}`
|
|
991
861
|
};
|
|
992
862
|
}
|
|
993
|
-
} else if (definition.properties) {
|
|
994
|
-
const result = this.parseToZodSchema(definition, requiredAttrs);
|
|
995
|
-
return {
|
|
996
|
-
schemaString: `${schemaAttribute} ${result.schemaString}${schemaRequired}`,
|
|
997
|
-
typeString: `${typeAttribute} ${result.typeString}${typeNullishability}`
|
|
998
|
-
};
|
|
999
863
|
}
|
|
1000
864
|
const ref = definition.$ref;
|
|
1001
865
|
let model = `z.record(z.any())`;
|
|
@@ -1082,29 +946,250 @@ const extractEnumObject = (type, isRequired, enumArr) => {
|
|
|
1082
946
|
};
|
|
1083
947
|
};
|
|
1084
948
|
|
|
1085
|
-
const
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
949
|
+
const templateApiIndex = (serviceName, serviceNameTitle, apiList) => {
|
|
950
|
+
let imports = "";
|
|
951
|
+
let returnStatement = "";
|
|
952
|
+
for (const cl of apiList) {
|
|
953
|
+
imports += `
|
|
954
|
+
import { ${cl} } from './${serviceName}/${cl}.js'`;
|
|
955
|
+
returnStatement += `
|
|
956
|
+
${cl}, `;
|
|
957
|
+
}
|
|
958
|
+
return `/**
|
|
959
|
+
* AUTO GENERATED
|
|
960
|
+
*/
|
|
961
|
+
${imports}
|
|
962
|
+
|
|
963
|
+
const apis = {
|
|
964
|
+
${returnStatement}
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
export const ${ParserUtils.convertDashesToTitleCase(serviceNameTitle)} = apis
|
|
968
|
+
`;
|
|
969
|
+
};
|
|
970
|
+
|
|
971
|
+
const Schema = zod.z.object({
|
|
972
|
+
$ref: zod.z.string().nullish(),
|
|
973
|
+
type: zod.z.union([zod.z.literal("array"), zod.z.literal("object"), zod.z.literal("file"), zod.z.literal("string"), zod.z.literal("boolean"), zod.z.literal("integer")]).nullish(),
|
|
974
|
+
items: zod.z.object({
|
|
975
|
+
$ref: zod.z.string().nullish(),
|
|
976
|
+
type: zod.z.string().nullish()
|
|
977
|
+
}).nullish(),
|
|
978
|
+
properties: zod.z.union([zod.z.array(zod.z.string()).nullish(), zod.z.record(zod.z.object({ type: zod.z.string() })).nullish()]),
|
|
979
|
+
description: zod.z.string().nullish(),
|
|
980
|
+
additionalProperties: zod.z.object({
|
|
981
|
+
type: zod.z.string().nullish()
|
|
982
|
+
}).nullish()
|
|
983
|
+
});
|
|
984
|
+
const Definition = zod.z.object({
|
|
985
|
+
required: zod.z.array(zod.z.string()).nullish(),
|
|
986
|
+
properties: zod.z.record(zod.z.object({
|
|
987
|
+
type: zod.z.string()
|
|
988
|
+
})).nullish()
|
|
989
|
+
});
|
|
990
|
+
const Definitions = zod.z.record(Definition);
|
|
991
|
+
const EndpointParametersType = zod.z.enum(["apiKey", "boolean", "int", "integer", "number", "string", "array", "file"]);
|
|
992
|
+
const EndpointParametersIn = zod.z.enum(["body", "formData", "header", "path", "query"]);
|
|
993
|
+
const EndpointParameters = zod.z.object({
|
|
994
|
+
type: EndpointParametersType.nullish(),
|
|
995
|
+
description: zod.z.string().nullish(),
|
|
996
|
+
name: zod.z.string(),
|
|
997
|
+
in: EndpointParametersIn,
|
|
998
|
+
required: zod.z.boolean().nullish(),
|
|
999
|
+
schema: Schema.nullish(),
|
|
1000
|
+
default: zod.z.union([zod.z.boolean(), zod.z.string(), zod.z.number(), zod.z.array(zod.z.any())]).nullish(),
|
|
1001
|
+
enum: zod.z.array(zod.z.union([zod.z.boolean(), zod.z.string(), zod.z.number()])).nullish(),
|
|
1002
|
+
items: zod.z.object({
|
|
1003
|
+
type: zod.z.string(),
|
|
1004
|
+
enum: zod.z.array(zod.z.any()).nullish()
|
|
1005
|
+
}).nullish()
|
|
1006
|
+
});
|
|
1007
|
+
const Endpoint = zod.z.object({
|
|
1008
|
+
description: zod.z.string().nullish(),
|
|
1009
|
+
consumes: zod.z.array(zod.z.string()).nullish(),
|
|
1010
|
+
produces: zod.z.array(zod.z.string()).nullish(),
|
|
1011
|
+
tags: zod.z.array(zod.z.string()).nullish(),
|
|
1012
|
+
summary: zod.z.string().nullish(),
|
|
1013
|
+
operationId: zod.z.string(),
|
|
1014
|
+
deprecated: zod.z.boolean().nullish(),
|
|
1015
|
+
responses: zod.z.record(zod.z.object({
|
|
1016
|
+
description: zod.z.string().nullish(),
|
|
1017
|
+
schema: Schema.nullish(),
|
|
1018
|
+
content: zod.z.object({
|
|
1019
|
+
"application/json": zod.z.object({
|
|
1020
|
+
schema: Schema.nullish()
|
|
1021
|
+
})
|
|
1022
|
+
}).nullish()
|
|
1023
|
+
})),
|
|
1024
|
+
parameters: zod.z.array(EndpointParameters).nullish(),
|
|
1025
|
+
requestBody: zod.z.object({
|
|
1026
|
+
required: zod.z.boolean(),
|
|
1027
|
+
content: zod.z.object({
|
|
1028
|
+
"application/json": zod.z.object({
|
|
1029
|
+
schema: Schema.nullish()
|
|
1030
|
+
})
|
|
1031
|
+
}).nullish()
|
|
1032
|
+
}).nullish()
|
|
1033
|
+
});
|
|
1034
|
+
const Operation = zod.z.object({
|
|
1035
|
+
get: Endpoint.nullish(),
|
|
1036
|
+
post: Endpoint.nullish(),
|
|
1037
|
+
patch: Endpoint.nullish(),
|
|
1038
|
+
delete: Endpoint.nullish(),
|
|
1039
|
+
put: Endpoint.nullish()
|
|
1040
|
+
});
|
|
1041
|
+
const Paths = zod.z.record(Operation);
|
|
1042
|
+
zod.z.object({
|
|
1043
|
+
paths: Paths,
|
|
1044
|
+
definitions: Definitions,
|
|
1045
|
+
basePath: zod.z.string(),
|
|
1046
|
+
info: zod.z.object({
|
|
1047
|
+
description: zod.z.string(),
|
|
1048
|
+
title: zod.z.string(),
|
|
1049
|
+
contact: zod.z.object({
|
|
1050
|
+
name: zod.z.string(),
|
|
1051
|
+
url: zod.z.string(),
|
|
1052
|
+
email: zod.z.string()
|
|
1053
|
+
}),
|
|
1054
|
+
version: zod.z.string()
|
|
1055
|
+
}),
|
|
1056
|
+
schemes: zod.z.array(zod.z.string()).nullish(),
|
|
1057
|
+
components: zod.z.object({
|
|
1058
|
+
schemas: Definitions
|
|
1059
|
+
}).nullish()
|
|
1060
|
+
});
|
|
1061
|
+
|
|
1062
|
+
const templateMethod = ({
|
|
1063
|
+
classMethod,
|
|
1064
|
+
description,
|
|
1065
|
+
httpMethod,
|
|
1066
|
+
path,
|
|
1067
|
+
pathParams,
|
|
1068
|
+
bodyParams,
|
|
1069
|
+
queryParams,
|
|
1070
|
+
isFormUrlEncoded,
|
|
1071
|
+
responseClass
|
|
1072
|
+
}) => {
|
|
1073
|
+
let methodParams = "";
|
|
1074
|
+
let methodParamsNoTypes = "";
|
|
1075
|
+
let newPath = `'${path}'`;
|
|
1076
|
+
let importStatements = [];
|
|
1077
|
+
const sortedPathParams = ParserUtils.sortPathParamsByPath(pathParams, path);
|
|
1078
|
+
for (const pathParam of sortedPathParams) {
|
|
1079
|
+
const type = ParserUtils.parseType(pathParam);
|
|
1080
|
+
if (pathParam.name !== "namespace") {
|
|
1081
|
+
methodParams += pathParam.name + `:${type}, `;
|
|
1082
|
+
methodParamsNoTypes += pathParam.name + ", ";
|
|
1083
|
+
}
|
|
1084
|
+
const pName = pathParam.name === "namespace" ? "this.namespace" : pathParam.name;
|
|
1085
|
+
if (path.match(`{${pathParam.name}}`)) {
|
|
1086
|
+
if (type === "string") {
|
|
1087
|
+
newPath = `${newPath}.replace('{${pathParam.name}}', ${pName})`;
|
|
1088
|
+
} else {
|
|
1089
|
+
newPath = `${newPath}.replace('{${pathParam.name}}', String(${pName}))`;
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
let dataType = null;
|
|
1094
|
+
if (httpMethod !== "get") {
|
|
1095
|
+
dataType = ParserUtils.parseBodyParamsType(bodyParams);
|
|
1096
|
+
importStatements = ParserUtils.parseBodyParamsImports(bodyParams);
|
|
1097
|
+
methodParams += dataType ? `data: ${dataType},` : "";
|
|
1098
|
+
methodParamsNoTypes += dataType ? `data,` : "";
|
|
1099
|
+
}
|
|
1100
|
+
const isAnyRequired = ParserUtils.isAnyQueryParamRequired(queryParams);
|
|
1101
|
+
const queryParamsType = queryParams.length ? `queryParams${isAnyRequired ? "" : "?"}: {${ParserUtils.parseQueryParamsType(queryParams)}}` : "";
|
|
1102
|
+
const queryParamsDefault = queryParams.length ? `const params = {${ParserUtils.parseQueryParamsDefault(queryParams)} ...queryParams} as SDKRequestConfig` : "const params = {} as SDKRequestConfig";
|
|
1103
|
+
const isPostPutPatch = ["post", "put", "patch"].includes(httpMethod);
|
|
1104
|
+
const isDelete = ["delete"].includes(httpMethod);
|
|
1105
|
+
let dataPayload = "{params}";
|
|
1106
|
+
const descriptionText = description ? `
|
|
1107
|
+
/**
|
|
1108
|
+
* ${description.replace(/\n/g, "\n * ")}
|
|
1109
|
+
*/` : "";
|
|
1110
|
+
let formPayloadString = "";
|
|
1111
|
+
if (isFormUrlEncoded) {
|
|
1112
|
+
formPayloadString = ``;
|
|
1113
|
+
const params = "{ ...params, headers: { ...params.headers, 'content-type': 'application/x-www-form-urlencoded' } }";
|
|
1114
|
+
dataPayload = dataType ? `CodeGenUtil.getFormUrlEncodedData(data), ${params}` : `null, ${params}`;
|
|
1115
|
+
} else if (isPostPutPatch) {
|
|
1116
|
+
dataPayload = dataType ? `data, {params}` : "null, {params}";
|
|
1117
|
+
} else if (isDelete) {
|
|
1118
|
+
dataPayload = dataType ? `{data, params}` : "{params}";
|
|
1119
|
+
}
|
|
1120
|
+
const isFileUpload = methodParams.indexOf("data: {file") > -1;
|
|
1121
|
+
const resolvedResponseClass = responseClass || "unknown";
|
|
1122
|
+
const resolvedResponseClassValidated = responseClass || "z.unknown()";
|
|
1123
|
+
methodParams = (queryParamsType ? `${methodParams} ${queryParamsType}` : methodParams).replace(/,\s*$/, "");
|
|
1124
|
+
methodParamsNoTypes = queryParamsType ? `${methodParamsNoTypes} queryParams` : methodParamsNoTypes;
|
|
1125
|
+
let methodImpl = "";
|
|
1126
|
+
const isCacheFetch = ["get"].includes(httpMethod) && resolvedResponseClass !== "unknown";
|
|
1127
|
+
const cachedFetchMethod = classMethod;
|
|
1128
|
+
const deprecateTag = isCacheFetch ? `/**
|
|
1129
|
+
* @deprecated Use "${classMethod}()" instead.
|
|
1130
|
+
*/` : "";
|
|
1131
|
+
const isGuardInvoked = ["get", "post", "put", "patch", "delete"].includes(httpMethod);
|
|
1132
|
+
const methodName = httpMethod === "get" ? cachedFetchMethod : ["post", "put", "patch", "delete"].includes(httpMethod) ? classMethod : "";
|
|
1133
|
+
const responseType = resolvedResponseClass !== "unknown" ? `${resolvedResponseClass}` : "unknown";
|
|
1134
|
+
const generateMethodName = () => `${methodName}(${methodParams}): Promise<${responseSyncType}<${responseType}>>`;
|
|
1135
|
+
const responseSyncType = httpMethod === "get" ? "IResponseWithSync" : ["post", "put", "patch", "delete"].includes(httpMethod) ? "IResponse" : "";
|
|
1136
|
+
methodImpl = `${descriptionText}
|
|
1137
|
+
${generateMethodName()} {
|
|
1138
|
+
${queryParamsDefault}
|
|
1139
|
+
const url = ${newPath} ${formPayloadString} ${isFileUpload ? "\n// TODO file upload not implemented" : ""}
|
|
1140
|
+
const resultPromise = this.axiosInstance.${httpMethod}(url, ${dataPayload})
|
|
1141
|
+
|
|
1142
|
+
${httpMethod === "get" ? ` const res = () => Validate.responseType(() => resultPromise, ${resolvedResponseClassValidated}, '${resolvedResponseClassValidated}')
|
|
1143
|
+
|
|
1144
|
+
if (!this.cache) {
|
|
1145
|
+
return SdkCache.withoutCache(res)
|
|
1146
|
+
}
|
|
1147
|
+
const cacheKey = url + CodeGenUtil.hashCode(JSON.stringify({ params }))
|
|
1148
|
+
return SdkCache.withCache(cacheKey, res)` : ""}${["post", "put", "patch", "delete"].includes(httpMethod) ? ` return Validate.responseType(() => resultPromise, ${resolvedResponseClassValidated}, '${resolvedResponseClassValidated}')` : ""}
|
|
1149
|
+
}
|
|
1150
|
+
`;
|
|
1151
|
+
if (!isGuardInvoked) {
|
|
1152
|
+
methodImpl = `${descriptionText}
|
|
1153
|
+
${deprecateTag}
|
|
1154
|
+
TODO_${classMethod}(${methodParams}): Promise<AxiosResponse<${resolvedResponseClass}>> {
|
|
1155
|
+
${queryParamsDefault}
|
|
1156
|
+
const url = ${newPath} ${formPayloadString} ${isFileUpload ? "\n// TODO file upload not implemented" : ""}
|
|
1157
|
+
return this.axiosInstance.${httpMethod}(url, ${dataPayload})
|
|
1158
|
+
}
|
|
1159
|
+
`;
|
|
1160
|
+
}
|
|
1161
|
+
const res = {
|
|
1162
|
+
methodImpl,
|
|
1163
|
+
methodParams,
|
|
1164
|
+
methodParamsNoTypes,
|
|
1165
|
+
importStatements
|
|
1166
|
+
};
|
|
1167
|
+
return res;
|
|
1168
|
+
};
|
|
1169
|
+
|
|
1170
|
+
const templateApiMethod = ({
|
|
1171
|
+
classMethod,
|
|
1172
|
+
description,
|
|
1173
|
+
httpMethod,
|
|
1174
|
+
path,
|
|
1175
|
+
pathParams,
|
|
1176
|
+
bodyParams,
|
|
1177
|
+
responseClass,
|
|
1178
|
+
classGenName,
|
|
1179
|
+
methodParams,
|
|
1180
|
+
methodParamsNoTypes
|
|
1181
|
+
}) => {
|
|
1182
|
+
let methodSignature = "";
|
|
1183
|
+
let newPath = `'${path}'`;
|
|
1184
|
+
let snippetSdk = "";
|
|
1185
|
+
let snippetShell = "";
|
|
1186
|
+
for (const pathParam of pathParams) {
|
|
1187
|
+
const type = ParserUtils.parseType(pathParam);
|
|
1188
|
+
if (pathParam.name !== "namespace") {
|
|
1189
|
+
methodSignature += pathParam.name + `:${type}, `;
|
|
1190
|
+
}
|
|
1191
|
+
const pName = pathParam.name === "namespace" ? "this.namespace" : pathParam.name;
|
|
1192
|
+
if (path.match(`{${pathParam.name}}`)) {
|
|
1108
1193
|
if (type === "string") {
|
|
1109
1194
|
newPath = `${newPath}.replace('{${pathParam.name}}', ${pName})`;
|
|
1110
1195
|
} else {
|
|
@@ -1143,28 +1228,6 @@ const templateApiMethod = ({
|
|
|
1143
1228
|
return [methodImpl, snippetSdk, snippetShell];
|
|
1144
1229
|
};
|
|
1145
1230
|
|
|
1146
|
-
const templateApiIndex = (serviceName, serviceNameTitle, apiList) => {
|
|
1147
|
-
let imports = "";
|
|
1148
|
-
let returnStatement = "";
|
|
1149
|
-
for (const cl of apiList) {
|
|
1150
|
-
imports += `
|
|
1151
|
-
import { ${cl} } from './${serviceName}/${cl}.js'`;
|
|
1152
|
-
returnStatement += `
|
|
1153
|
-
${cl}, `;
|
|
1154
|
-
}
|
|
1155
|
-
return `/**
|
|
1156
|
-
* AUTO GENERATED
|
|
1157
|
-
*/
|
|
1158
|
-
${imports}
|
|
1159
|
-
|
|
1160
|
-
const apis = {
|
|
1161
|
-
${returnStatement}
|
|
1162
|
-
}
|
|
1163
|
-
|
|
1164
|
-
export const ${ParserUtils.convertDashesToTitleCase(serviceNameTitle)} = apis
|
|
1165
|
-
`;
|
|
1166
|
-
};
|
|
1167
|
-
|
|
1168
1231
|
const templateSdkSnippet = (serviceNameTitle, apiName, methodSnippet) => {
|
|
1169
1232
|
const methodArr = methodSnippet.split("//");
|
|
1170
1233
|
let normMethod = normalizeMethodSnippet(methodArr[0].trim(), "data:");
|
|
@@ -1204,21 +1267,33 @@ const normalizeMethodSnippet = (methodInput, splitWord) => {
|
|
|
1204
1267
|
};
|
|
1205
1268
|
|
|
1206
1269
|
const GIT_URL = "https://github.com/AccelByte/accelbyte-web-sdk/blob/main/packages";
|
|
1207
|
-
class
|
|
1208
|
-
static getPatchedDir = () => path.join(CliParser.getSwaggersOutputPath(), "patched");
|
|
1209
|
-
static getGeneratedPublicFolder = () => `${CliParser.getOutputPath()}/generated-public`;
|
|
1210
|
-
static getGeneratedAdminFolder = () => `${CliParser.getOutputPath()}/generated-admin`;
|
|
1211
|
-
static getGeneratedSnippetsFolder = () => `${CliParser.getSnippetOutputPath()}/generated-snippets`;
|
|
1270
|
+
class SwaggerReaderHelpers {
|
|
1212
1271
|
static getServicePrefix = (servicePaths) => servicePaths[servicePaths.length - 1].split("/")[1];
|
|
1213
|
-
static
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
const
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1272
|
+
static parseAllEndpoints = async ({
|
|
1273
|
+
api,
|
|
1274
|
+
sdkName,
|
|
1275
|
+
serviceName
|
|
1276
|
+
}) => {
|
|
1277
|
+
const result = {
|
|
1278
|
+
admin: {
|
|
1279
|
+
arrayDefinitions: [],
|
|
1280
|
+
snippetMap: {},
|
|
1281
|
+
tagToClassImportsRecord: {},
|
|
1282
|
+
tagToEndpointClassesRecord: {},
|
|
1283
|
+
tagToSdkClientRecord: {},
|
|
1284
|
+
tagToSdkFunctionNamesRecord: {},
|
|
1285
|
+
tagToSdkImportsRecord: {}
|
|
1286
|
+
},
|
|
1287
|
+
public: {
|
|
1288
|
+
arrayDefinitions: [],
|
|
1289
|
+
snippetMap: {},
|
|
1290
|
+
tagToClassImportsRecord: {},
|
|
1291
|
+
tagToEndpointClassesRecord: {},
|
|
1292
|
+
tagToSdkClientRecord: {},
|
|
1293
|
+
tagToSdkFunctionNamesRecord: {},
|
|
1294
|
+
tagToSdkImportsRecord: {}
|
|
1295
|
+
}
|
|
1296
|
+
};
|
|
1222
1297
|
const sortedPathsByLength = new Map(Object.entries(api.paths).sort((a, b) => {
|
|
1223
1298
|
if (a[0].length === b[0].length) {
|
|
1224
1299
|
return a[0].localeCompare(b[0]);
|
|
@@ -1227,55 +1302,62 @@ class CodeGenerator {
|
|
|
1227
1302
|
}
|
|
1228
1303
|
}));
|
|
1229
1304
|
const sortedKeys = Array.from(sortedPathsByLength.keys());
|
|
1230
|
-
const servicePrefix =
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
} else if (path2.indexOf("/healthz") >= 0) {
|
|
1305
|
+
const servicePrefix = SwaggerReaderHelpers.getServicePrefix(sortedKeys);
|
|
1306
|
+
const tagToClassMethodsMap = {
|
|
1307
|
+
admin: {},
|
|
1308
|
+
public: {}
|
|
1309
|
+
};
|
|
1310
|
+
for (const [path, operation] of sortedPathsByLength) {
|
|
1311
|
+
if (path.indexOf("/healthz") >= 0) {
|
|
1238
1312
|
continue;
|
|
1239
1313
|
}
|
|
1314
|
+
const isAdminEndpoint = path.indexOf("/admin/") > -1;
|
|
1315
|
+
const picked = isAdminEndpoint ? result.admin : result.public;
|
|
1316
|
+
const {
|
|
1317
|
+
arrayDefinitions,
|
|
1318
|
+
snippetMap,
|
|
1319
|
+
tagToClassImportsRecord,
|
|
1320
|
+
tagToEndpointClassesRecord,
|
|
1321
|
+
tagToSdkClientRecord,
|
|
1322
|
+
tagToSdkFunctionNamesRecord,
|
|
1323
|
+
tagToSdkImportsRecord
|
|
1324
|
+
} = picked;
|
|
1325
|
+
const tagToClassMethodsMapByType = isAdminEndpoint ? tagToClassMethodsMap.admin : tagToClassMethodsMap.public;
|
|
1240
1326
|
const httpMethods = Object.keys(operation);
|
|
1241
1327
|
for (const httpMethod of httpMethods) {
|
|
1242
1328
|
const endpoint = await Endpoint.parseAsync(operation[httpMethod]).catch((error) => {
|
|
1243
|
-
console.error(JSON.stringify({ path
|
|
1329
|
+
console.error(JSON.stringify({ path, httpMethod }, null, 2));
|
|
1244
1330
|
throw error;
|
|
1245
1331
|
});
|
|
1246
|
-
if (!endpoint.tags)
|
|
1332
|
+
if (!endpoint.tags || endpoint.deprecated)
|
|
1247
1333
|
continue;
|
|
1248
|
-
}
|
|
1249
|
-
if (endpoint.deprecated) {
|
|
1250
|
-
continue;
|
|
1251
|
-
}
|
|
1252
1334
|
const [tag] = endpoint.tags;
|
|
1253
|
-
|
|
1335
|
+
const pathWithBase = `${api.basePath ?? ""}${path}`;
|
|
1336
|
+
tagToClassMethodsMapByType[tag] = tagToClassMethodsMapByType[tag] ? tagToClassMethodsMapByType[tag] : {};
|
|
1254
1337
|
const isForm = endpoint.consumes && endpoint.consumes[0] === "application/x-www-form-urlencoded";
|
|
1255
1338
|
const classMethod = ParserUtils.generateNaturalLangMethod({
|
|
1256
1339
|
servicePrefix,
|
|
1257
|
-
path
|
|
1340
|
+
path,
|
|
1258
1341
|
httpMethod,
|
|
1259
1342
|
isForm,
|
|
1260
|
-
existingMethods:
|
|
1343
|
+
existingMethods: tagToClassMethodsMapByType[tag]
|
|
1261
1344
|
});
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
description = description
|
|
1345
|
+
tagToClassMethodsMapByType[tag][classMethod] = `${path} ${httpMethod}`;
|
|
1346
|
+
if (!snippetMap[pathWithBase]) {
|
|
1347
|
+
snippetMap[pathWithBase] = {};
|
|
1348
|
+
}
|
|
1349
|
+
const description = endpoint.description?.replace(/\s+/g, " ") || "";
|
|
1267
1350
|
const responseClass = ParserUtils.get2xxResponse(endpoint.responses);
|
|
1268
|
-
const { className, classGenName } = ParserUtils.generateClassName(tag);
|
|
1269
|
-
|
|
1351
|
+
const { className, classGenName } = ParserUtils.generateClassName(tag, isAdminEndpoint);
|
|
1352
|
+
tagToClassImportsRecord[className] = tagToClassImportsRecord[className] ? tagToClassImportsRecord[className] : {};
|
|
1270
1353
|
if (responseClass) {
|
|
1271
1354
|
const importTypeClass = ParserUtils.parseRefType(responseClass);
|
|
1272
|
-
|
|
1355
|
+
tagToClassImportsRecord[className][importTypeClass] = `import { ${importTypeClass} } from '../definitions/${importTypeClass}.js'`;
|
|
1273
1356
|
}
|
|
1274
1357
|
if (responseClass && responseClass.endsWith("Array")) {
|
|
1275
1358
|
arrayDefinitions.push(responseClass);
|
|
1276
1359
|
}
|
|
1277
1360
|
const queryParams = ParserUtils.filterQueryParameters(endpoint.parameters);
|
|
1278
|
-
const pathWithBase = `${api.basePath ?? ""}${path2}`;
|
|
1279
1361
|
const isFormUrlEncoded = ParserUtils.isFormUrlEncoded(httpMethod, endpoint.consumes);
|
|
1280
1362
|
const pathParams = ParserUtils.filterPathParams(endpoint.parameters);
|
|
1281
1363
|
let bodyParams = ParserUtils.filterBodyParams(endpoint.parameters);
|
|
@@ -1299,8 +1381,8 @@ class CodeGenerator {
|
|
|
1299
1381
|
isFormUrlEncoded,
|
|
1300
1382
|
responseClass
|
|
1301
1383
|
});
|
|
1302
|
-
|
|
1303
|
-
const [
|
|
1384
|
+
tagToEndpointClassesRecord[tag] = (tagToEndpointClassesRecord[tag] || "") + methodImpl;
|
|
1385
|
+
const [generatedMethodString, snippetMethod, snippetShell] = templateApiMethod({
|
|
1304
1386
|
classMethod,
|
|
1305
1387
|
description,
|
|
1306
1388
|
httpMethod,
|
|
@@ -1312,32 +1394,37 @@ class CodeGenerator {
|
|
|
1312
1394
|
methodParams,
|
|
1313
1395
|
methodParamsNoTypes
|
|
1314
1396
|
});
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1397
|
+
tagToSdkClientRecord[tag] = (tagToSdkClientRecord[tag] || "") + generatedMethodString;
|
|
1398
|
+
tagToSdkFunctionNamesRecord[tag] = (tagToSdkFunctionNamesRecord[tag] || "") + classMethod + ",";
|
|
1399
|
+
tagToSdkImportsRecord[tag] = tagToSdkImportsRecord[tag] ? [.../* @__PURE__ */ new Set([...importStatements, ...tagToSdkImportsRecord[tag]])] : [...new Set(importStatements)];
|
|
1318
1400
|
const serviceNameTitle = ParserUtils.convertDashesToTitleCase(serviceName);
|
|
1319
|
-
const { apiGenName } = ParserUtils.generateApiName(tag);
|
|
1401
|
+
const { apiGenName } = ParserUtils.generateApiName(tag, isAdminEndpoint);
|
|
1320
1402
|
const resultSnippet = templateSdkSnippet(serviceNameTitle, apiGenName, snippetMethod);
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1403
|
+
const currentSnippetMap = {};
|
|
1404
|
+
snippetMap[pathWithBase][httpMethod] = currentSnippetMap;
|
|
1405
|
+
if (!isAdminEndpoint) {
|
|
1406
|
+
currentSnippetMap.web = !isAdminEndpoint ? resultSnippet : "";
|
|
1407
|
+
currentSnippetMap.webGit = !isAdminEndpoint ? GIT_URL + `/sdk-${sdkName}/src/generated-public/${serviceName}/${apiGenName}.ts` : "";
|
|
1408
|
+
}
|
|
1409
|
+
currentSnippetMap.shell = snippetShell;
|
|
1326
1410
|
}
|
|
1327
1411
|
}
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
classBufferByTag,
|
|
1333
|
-
dependenciesByTag,
|
|
1334
|
-
classImports,
|
|
1335
|
-
arrayDefinitions,
|
|
1336
|
-
snippetMap
|
|
1337
|
-
};
|
|
1412
|
+
for (const key in result) {
|
|
1413
|
+
result[key].arrayDefinitions = Array.from(new Set(result[key].arrayDefinitions));
|
|
1414
|
+
}
|
|
1415
|
+
return result;
|
|
1338
1416
|
};
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1419
|
+
class CodeGenerator {
|
|
1420
|
+
static getPatchedDir = () => path.join(CliParser.getSwaggersOutputPath(), "patched");
|
|
1421
|
+
static getGeneratedPublicFolder = () => `${CliParser.getOutputPath()}/generated-public`;
|
|
1422
|
+
static getGeneratedAdminFolder = () => `${CliParser.getOutputPath()}/generated-admin`;
|
|
1423
|
+
static getGeneratedSnippetsFolder = () => `${CliParser.getSnippetOutputPath()}/generated-snippets`;
|
|
1424
|
+
static getServicePrefix = (servicePaths) => servicePaths[servicePaths.length - 1].split("/")[1];
|
|
1339
1425
|
static main = async (nameArray) => {
|
|
1340
1426
|
const serviceName = nameArray[0];
|
|
1427
|
+
const sdkName = nameArray[1];
|
|
1341
1428
|
const swaggerFile = nameArray[2];
|
|
1342
1429
|
const parser = new SwaggerParser();
|
|
1343
1430
|
const generatedFolder = CliParser.isAdmin() ? CodeGenerator.getGeneratedAdminFolder() : CodeGenerator.getGeneratedPublicFolder();
|
|
@@ -1347,31 +1434,44 @@ class CodeGenerator {
|
|
|
1347
1434
|
const swaggerFilePath = `${CliParser.getSwaggersOutputPath()}/${swaggerFile}`;
|
|
1348
1435
|
const api = await parser.parse(swaggerFilePath);
|
|
1349
1436
|
const indexImportsSet = /* @__PURE__ */ new Set();
|
|
1350
|
-
|
|
1437
|
+
const apiInfo = { ...api.info, "x-version": api["x-version"]?.version };
|
|
1438
|
+
console.log("----------\nGenerating API:", { title: apiInfo.title, version: apiInfo.version });
|
|
1351
1439
|
ParserUtils.mkdirIfNotExist(DIST_DIR);
|
|
1352
1440
|
ParserUtils.mkdirIfNotExist(DIST_DEFINITION_DIR);
|
|
1353
1441
|
ParserUtils.mkdirIfNotExist(DIST_ENDPOINTS_DIR);
|
|
1354
|
-
ParserUtils.syncPackageVersion(
|
|
1355
|
-
const
|
|
1442
|
+
ParserUtils.syncPackageVersion(apiInfo, CliParser.skipVersionSync(), process.env.PRERELEASE_ID);
|
|
1443
|
+
const parsedInformation = await SwaggerReaderHelpers.parseAllEndpoints({ api, sdkName, serviceName });
|
|
1444
|
+
const parsedInformationByType = CliParser.isAdmin() ? parsedInformation.admin : parsedInformation.public;
|
|
1445
|
+
const {
|
|
1446
|
+
arrayDefinitions,
|
|
1447
|
+
tagToClassImportsRecord,
|
|
1448
|
+
tagToEndpointClassesRecord,
|
|
1449
|
+
tagToSdkClientRecord,
|
|
1450
|
+
tagToSdkFunctionNamesRecord,
|
|
1451
|
+
tagToSdkImportsRecord
|
|
1452
|
+
} = parsedInformationByType;
|
|
1356
1453
|
if (CliParser.getSnippetOutputPath()) {
|
|
1357
1454
|
try {
|
|
1358
|
-
ParserUtils.writeSnippetFile(CodeGenerator.getGeneratedSnippetsFolder(), api.info.title, JSON.stringify(
|
|
1455
|
+
ParserUtils.writeSnippetFile(CodeGenerator.getGeneratedSnippetsFolder(), api.info.title, JSON.stringify({
|
|
1456
|
+
...parsedInformation.public.snippetMap,
|
|
1457
|
+
...parsedInformation.admin.snippetMap
|
|
1458
|
+
}, null, 2));
|
|
1359
1459
|
} catch (err) {
|
|
1360
1460
|
console.log("Generating snippets", err);
|
|
1361
1461
|
}
|
|
1362
1462
|
}
|
|
1363
1463
|
const targetSrcFolder = `${CliParser.getOutputPath()}/`;
|
|
1364
1464
|
const apiList = [];
|
|
1365
|
-
for (const tag in
|
|
1366
|
-
const { className, classGenName } = ParserUtils.generateClassName(tag);
|
|
1367
|
-
const classBuffer =
|
|
1368
|
-
const imports = [.../* @__PURE__ */ new Set([...
|
|
1369
|
-
const apiImports = [.../* @__PURE__ */ new Set([...
|
|
1465
|
+
for (const tag in tagToEndpointClassesRecord) {
|
|
1466
|
+
const { className, classGenName } = ParserUtils.generateClassName(tag, CliParser.isAdmin());
|
|
1467
|
+
const classBuffer = tagToEndpointClassesRecord[tag];
|
|
1468
|
+
const imports = [.../* @__PURE__ */ new Set([...tagToSdkImportsRecord[tag], ...Object.values(tagToClassImportsRecord[className])])];
|
|
1469
|
+
const apiImports = [.../* @__PURE__ */ new Set([...tagToSdkImportsRecord[tag], ...Object.values(tagToClassImportsRecord[className])])];
|
|
1370
1470
|
apiImports.push(`import { ${classGenName} } from './endpoints/${classGenName}.js'`);
|
|
1371
1471
|
ParserUtils.writeClassFile(DIST_ENDPOINTS_DIR, classGenName, classBuffer, imports);
|
|
1372
|
-
const apiBuffer =
|
|
1373
|
-
const { apiGenName } = ParserUtils.generateApiName(tag);
|
|
1374
|
-
ParserUtils.writeApiFile(DIST_DIR, apiGenName, apiBuffer, apiImports,
|
|
1472
|
+
const apiBuffer = tagToSdkClientRecord[tag];
|
|
1473
|
+
const { apiGenName } = ParserUtils.generateApiName(tag, CliParser.isAdmin());
|
|
1474
|
+
ParserUtils.writeApiFile(DIST_DIR, apiGenName, apiBuffer, apiImports, tagToSdkFunctionNamesRecord[tag]);
|
|
1375
1475
|
apiList.push(apiGenName);
|
|
1376
1476
|
indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path.join(DIST_ENDPOINTS_DIR, `${classGenName}`), targetSrcFolder));
|
|
1377
1477
|
indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path.join(DIST_DIR, `${apiGenName}`), targetSrcFolder));
|
|
@@ -1441,33 +1541,36 @@ class SwaggerDownloader {
|
|
|
1441
1541
|
});
|
|
1442
1542
|
});
|
|
1443
1543
|
};
|
|
1444
|
-
static downloadFile = (targetFileName, url) => {
|
|
1544
|
+
static downloadFile = async (targetFileName, url) => {
|
|
1445
1545
|
const destFile = SwaggerDownloader.getDestFile(targetFileName);
|
|
1446
1546
|
let data = "";
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
data
|
|
1547
|
+
return new Promise((resolve) => {
|
|
1548
|
+
const request = https__namespace.get(url, function(response) {
|
|
1549
|
+
response.on("data", (chunk) => {
|
|
1550
|
+
data += chunk;
|
|
1551
|
+
});
|
|
1552
|
+
response.on("end", () => {
|
|
1553
|
+
if (response.statusCode !== 200) {
|
|
1554
|
+
console.log(`SwaggerDownload error with status code: ${response.statusCode}`);
|
|
1555
|
+
} else {
|
|
1556
|
+
fs__namespace.writeFileSync(destFile, JSON.stringify(JSON.parse(data), null, 2), "utf-8");
|
|
1557
|
+
SwaggerDownloader.postSanitizeDownloadedFile(destFile);
|
|
1558
|
+
console.log(`SwaggerDownload ${url} completed with status code: ${response.statusCode}`);
|
|
1559
|
+
}
|
|
1560
|
+
resolve(void 0);
|
|
1561
|
+
});
|
|
1450
1562
|
});
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
console.log(`SwaggerDownload error with status code: ${response.statusCode}`);
|
|
1454
|
-
} else {
|
|
1455
|
-
fs__namespace.writeFileSync(destFile, JSON.stringify(JSON.parse(data), null, 2), "utf-8");
|
|
1456
|
-
SwaggerDownloader.postSanitizeDownloadedFile(destFile);
|
|
1457
|
-
console.log(`SwaggerDownload ${url} completed with status code: ${response.statusCode}`);
|
|
1458
|
-
}
|
|
1563
|
+
request.on("error", (err) => {
|
|
1564
|
+
console.log(`SwaggerDownloader failed for "${targetFileName}" and "${url}"`, err);
|
|
1459
1565
|
});
|
|
1460
1566
|
});
|
|
1461
|
-
request.on("error", (err) => {
|
|
1462
|
-
console.log(`SwaggerDownloader failed for "${targetFileName}" and "${url}"`, err);
|
|
1463
|
-
});
|
|
1464
1567
|
};
|
|
1465
|
-
static main = () => {
|
|
1568
|
+
static main = async () => {
|
|
1466
1569
|
const swaggers = CliParser.getConfigFile();
|
|
1467
1570
|
for (const ref in swaggers) {
|
|
1468
1571
|
const targetFileName = swaggers[ref][2];
|
|
1469
1572
|
const url = swaggers[ref][3];
|
|
1470
|
-
SwaggerDownloader.downloadFile(targetFileName, url);
|
|
1573
|
+
await SwaggerDownloader.downloadFile(targetFileName, url);
|
|
1471
1574
|
}
|
|
1472
1575
|
};
|
|
1473
1576
|
}
|