@accelbyte/codegen 2.0.0-beta.1 → 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,15 +149,25 @@ export function ${className}(sdk: AccelbyteSDK, args?: ApiArgs) {
146
149
  `;
147
150
  };
148
151
 
152
+ const VersionBumpType = zod.z.enum(["CUTOFF", "RELEASE", "HOTFIX"]);
149
153
  class VersionHelpers {
150
154
  static getNextVersion = ({
151
155
  codegenVersion,
152
156
  serviceVersion,
153
157
  predefinedMajorVersion,
154
- predefinedMinorVersion,
158
+ versionBumpType,
155
159
  sdkVersion,
156
160
  nextPrereleaseId
157
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
+ }
158
171
  const codegenSemvers = semver.parse(codegenVersion);
159
172
  const serviceSemvers = semver.parse(serviceVersion);
160
173
  const sdkSemvers = semver.parse(sdkVersion);
@@ -167,20 +180,39 @@ class VersionHelpers {
167
180
  if (sdkSemvers === null) {
168
181
  throw new Error(`Invalid sdk version: ${sdkVersion}`);
169
182
  }
170
- const nextMajor = codegenSemvers.minor + predefinedMajorVersion;
171
- const nextMinor = codegenSemvers.minor + predefinedMinorVersion;
172
- const nextPatch = codegenSemvers.patch + serviceSemvers.patch;
173
- const { major: currentMajor, minor: currentMinor, patch: currentPatch } = sdkSemvers;
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
+ }
174
205
  let nextVersion = [
175
206
  codegenSemvers.major + predefinedMajorVersion,
176
207
  nextMinor,
177
208
  nextPatch
178
209
  ].join(".");
179
210
  if (nextPrereleaseId) {
180
- if (nextMinor !== currentMinor || nextPatch !== currentPatch || nextMajor !== currentMajor) {
211
+ if (nextMinor !== currentMinor || nextMajor !== currentMajor) {
181
212
  nextVersion += `-${nextPrereleaseId}.0`;
182
213
  } else {
183
- nextVersion += `-${sdkSemvers.prerelease.join(".")}`;
214
+ if (currentPrerelease.length)
215
+ nextVersion += `-${currentPrerelease.join(".")}`;
184
216
  nextVersion = semver.inc(nextVersion, "prerelease", void 0, nextPrereleaseId);
185
217
  }
186
218
  }
@@ -207,14 +239,14 @@ class ParserUtils {
207
239
  static replaceAll = (string, search, replace) => {
208
240
  return string.split(search).join(replace);
209
241
  };
210
- static generateClassName = (tag) => {
242
+ static generateClassName = (tag, isAdmin) => {
211
243
  const className = _.upperFirst(_.camelCase(tag));
212
- const classGenName = CliParser.isAdmin() ? className + "Admin$" : className + "$";
244
+ const classGenName = isAdmin ? className + "Admin$" : className + "$";
213
245
  return { className, classGenName };
214
246
  };
215
- static generateApiName = (tag) => {
247
+ static generateApiName = (tag, isAdmin) => {
216
248
  const apiName = _.upperFirst(_.camelCase(tag));
217
- const apiGenName = CliParser.isAdmin() ? apiName + "AdminApi" : apiName + "Api";
249
+ const apiGenName = isAdmin ? apiName + "AdminApi" : apiName + "Api";
218
250
  return { apiName, apiGenName };
219
251
  };
220
252
  static parseQueryParamAttributeDefault = (definition) => {
@@ -314,6 +346,12 @@ class ParserUtils {
314
346
  if (definition?.schema?.type && definition.schema.type === "array") {
315
347
  return `${attrName}${required}: ${definition.schema.items.type ?? "any"}[]`;
316
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
+ }
317
355
  if (definition.type && definition.type) {
318
356
  return `${attrName}${required}: ${definition.type} | null`;
319
357
  }
@@ -493,17 +531,16 @@ class ParserUtils {
493
531
  ParserUtils.mkdirIfNotExist(distDir);
494
532
  fs.writeFileSync(path.join(distDir, `all-${isAdminWebSdk ? "admin" : "public"}-imports.ts`), ParserUtils.prependCopyrightHeader(buffer));
495
533
  }
496
- static syncPackageVersion(apiInfo, isAdminWebSdk, prereleaseId) {
497
- if (isAdminWebSdk) {
534
+ static syncPackageVersion(apiInfo, skipVersionSync, prereleaseId) {
535
+ if (skipVersionSync)
498
536
  return;
499
- }
500
537
  const currDir = process.cwd();
501
538
  const { packageJSON, pathToPackageJSON } = ParserUtils.getPackageJSONInfo(currDir);
502
539
  const nextSemver = VersionHelpers.getNextVersion({
503
540
  codegenVersion: codegenPackageJSON.version,
504
541
  serviceVersion: apiInfo["x-version"] || apiInfo.version || UNDEFINED_SWAGGER_SEMVER,
505
- predefinedMajorVersion: packageJSON.predefinedMajorVersion,
506
- predefinedMinorVersion: packageJSON.predefinedMinorVersion,
542
+ predefinedMajorVersion: packageJSON.predefinedMajorVersion || 0,
543
+ versionBumpType: process.env.VERSION_BUMP_TYPE,
507
544
  sdkVersion: packageJSON.version,
508
545
  nextPrereleaseId: prereleaseId
509
546
  });
@@ -587,7 +624,9 @@ class ParserUtils {
587
624
  ${content}`;
588
625
  };
589
626
  static sortPathParamsByPath = (pathParams, path2) => {
590
- return pathParams.sort((a, b) => path2.indexOf(a.name) - path2.indexOf(b.name));
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));
591
630
  };
592
631
  }
593
632
  const mappedMethod = (httpMethod, isForm) => {
@@ -655,205 +694,6 @@ const isSwaggerIntegerType = (type) => {
655
694
  return type === "integer" || type === "int";
656
695
  };
657
696
 
658
- const Schema = zod.z.object({
659
- $ref: zod.z.string().nullish(),
660
- 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(),
661
- items: zod.z.object({
662
- $ref: zod.z.string().nullish(),
663
- type: zod.z.string().nullish()
664
- }).nullish(),
665
- properties: zod.z.union([zod.z.array(zod.z.string()).nullish(), zod.z.record(zod.z.object({ type: zod.z.string() })).nullish()]),
666
- description: zod.z.string().nullish(),
667
- additionalProperties: zod.z.object({
668
- type: zod.z.string().nullish()
669
- }).nullish()
670
- });
671
- const Definition = zod.z.object({
672
- required: zod.z.array(zod.z.string()).nullish(),
673
- properties: zod.z.record(zod.z.object({
674
- type: zod.z.string()
675
- })).nullish()
676
- });
677
- const Definitions = zod.z.record(Definition);
678
- const EndpointParametersType = zod.z.enum(["apiKey", "boolean", "int", "integer", "number", "string", "array", "file"]);
679
- const EndpointParametersIn = zod.z.enum(["body", "formData", "header", "path", "query"]);
680
- const EndpointParameters = zod.z.object({
681
- type: EndpointParametersType.nullish(),
682
- description: zod.z.string().nullish(),
683
- name: zod.z.string(),
684
- in: EndpointParametersIn,
685
- required: zod.z.boolean().nullish(),
686
- schema: Schema.nullish(),
687
- default: zod.z.union([zod.z.boolean(), zod.z.string(), zod.z.number(), zod.z.array(zod.z.any())]).nullish(),
688
- enum: zod.z.array(zod.z.union([zod.z.boolean(), zod.z.string(), zod.z.number()])).nullish(),
689
- items: zod.z.object({
690
- type: zod.z.string(),
691
- enum: zod.z.array(zod.z.any()).nullish()
692
- }).nullish()
693
- });
694
- const Endpoint = zod.z.object({
695
- description: zod.z.string().nullish(),
696
- consumes: zod.z.array(zod.z.string()).nullish(),
697
- produces: zod.z.array(zod.z.string()).nullish(),
698
- tags: zod.z.array(zod.z.string()).nullish(),
699
- summary: zod.z.string().nullish(),
700
- operationId: zod.z.string(),
701
- deprecated: zod.z.boolean().nullish(),
702
- responses: zod.z.record(zod.z.object({
703
- description: zod.z.string().nullish(),
704
- schema: Schema.nullish(),
705
- content: zod.z.object({
706
- "application/json": zod.z.object({
707
- schema: Schema.nullish()
708
- })
709
- }).nullish()
710
- })),
711
- parameters: zod.z.array(EndpointParameters).nullish(),
712
- requestBody: zod.z.object({
713
- required: zod.z.boolean(),
714
- content: zod.z.object({
715
- "application/json": zod.z.object({
716
- schema: Schema.nullish()
717
- })
718
- }).nullish()
719
- }).nullish()
720
- });
721
- const Operation = zod.z.object({
722
- get: Endpoint.nullish(),
723
- post: Endpoint.nullish(),
724
- patch: Endpoint.nullish(),
725
- delete: Endpoint.nullish(),
726
- put: Endpoint.nullish()
727
- });
728
- const Paths = zod.z.record(Operation);
729
- zod.z.object({
730
- paths: Paths,
731
- definitions: Definitions,
732
- basePath: zod.z.string(),
733
- info: zod.z.object({
734
- description: zod.z.string(),
735
- title: zod.z.string(),
736
- contact: zod.z.object({
737
- name: zod.z.string(),
738
- url: zod.z.string(),
739
- email: zod.z.string()
740
- }),
741
- version: zod.z.string()
742
- }),
743
- schemes: zod.z.array(zod.z.string()).nullish(),
744
- components: zod.z.object({
745
- schemas: Definitions
746
- }).nullish()
747
- });
748
-
749
- const templateMethod = ({
750
- classMethod,
751
- description,
752
- httpMethod,
753
- path,
754
- pathParams,
755
- bodyParams,
756
- queryParams,
757
- isFormUrlEncoded,
758
- responseClass
759
- }) => {
760
- let methodParams = "";
761
- let methodParamsNoTypes = "";
762
- let newPath = `'${path}'`;
763
- let importStatements = [];
764
- const sortedPathParams = ParserUtils.sortPathParamsByPath(pathParams, path);
765
- for (const pathParam of sortedPathParams) {
766
- const type = ParserUtils.parseType(pathParam);
767
- if (pathParam.name !== "namespace") {
768
- methodParams += pathParam.name + `:${type}, `;
769
- methodParamsNoTypes += pathParam.name + ", ";
770
- }
771
- const pName = pathParam.name === "namespace" ? "this.namespace" : pathParam.name;
772
- if (path.match(`{${pathParam.name}}`)) {
773
- if (type === "string") {
774
- newPath = `${newPath}.replace('{${pathParam.name}}', ${pName})`;
775
- } else {
776
- newPath = `${newPath}.replace('{${pathParam.name}}', String(${pName}))`;
777
- }
778
- }
779
- }
780
- let dataType = null;
781
- if (httpMethod !== "get") {
782
- dataType = ParserUtils.parseBodyParamsType(bodyParams);
783
- importStatements = ParserUtils.parseBodyParamsImports(bodyParams);
784
- methodParams += dataType ? `data: ${dataType},` : "";
785
- methodParamsNoTypes += dataType ? `data,` : "";
786
- }
787
- const isAnyRequired = ParserUtils.isAnyQueryParamRequired(queryParams);
788
- const queryParamsType = queryParams.length ? `queryParams${isAnyRequired ? "" : "?"}: {${ParserUtils.parseQueryParamsType(queryParams)}}` : "";
789
- const queryParamsDefault = queryParams.length ? `const params = {${ParserUtils.parseQueryParamsDefault(queryParams)} ...queryParams} as SDKRequestConfig` : "const params = {} as SDKRequestConfig";
790
- const isPostPutPatch = ["post", "put", "patch"].includes(httpMethod);
791
- const isDelete = ["delete"].includes(httpMethod);
792
- let dataPayload = "{params}";
793
- const descriptionText = description ? `
794
- /**
795
- * ${description.replace(/\n/g, "\n * ")}
796
- */` : "";
797
- let formPayloadString = "";
798
- if (isFormUrlEncoded) {
799
- formPayloadString = ``;
800
- const params = "{ ...params, headers: { ...params.headers, 'content-type': 'application/x-www-form-urlencoded' } }";
801
- dataPayload = dataType ? `CodeGenUtil.getFormUrlEncodedData(data), ${params}` : `null, ${params}`;
802
- } else if (isPostPutPatch) {
803
- dataPayload = dataType ? `data, {params}` : "null, {params}";
804
- } else if (isDelete) {
805
- dataPayload = dataType ? `{data, params}` : "{params}";
806
- }
807
- const isFileUpload = methodParams.indexOf("data: {file") > -1;
808
- const resolvedResponseClass = responseClass || "unknown";
809
- const resolvedResponseClassValidated = responseClass || "z.unknown()";
810
- methodParams = (queryParamsType ? `${methodParams} ${queryParamsType}` : methodParams).replace(/,\s*$/, "");
811
- methodParamsNoTypes = queryParamsType ? `${methodParamsNoTypes} queryParams` : methodParamsNoTypes;
812
- let methodImpl = "";
813
- const isCacheFetch = ["get"].includes(httpMethod) && resolvedResponseClass !== "unknown";
814
- const cachedFetchMethod = classMethod;
815
- const deprecateTag = isCacheFetch ? `/**
816
- * @deprecated Use "${classMethod}()" instead.
817
- */` : "";
818
- const isGuardInvoked = ["get", "post", "put", "patch", "delete"].includes(httpMethod);
819
- const methodName = httpMethod === "get" ? cachedFetchMethod : ["post", "put", "patch", "delete"].includes(httpMethod) ? classMethod : "";
820
- const responseType = resolvedResponseClass !== "unknown" ? `${resolvedResponseClass}` : "unknown";
821
- const generateMethodName = () => `${methodName}(${methodParams}): Promise<${responseSyncType}<${responseType}>>`;
822
- const responseSyncType = httpMethod === "get" ? "IResponseWithSync" : ["post", "put", "patch", "delete"].includes(httpMethod) ? "IResponse" : "";
823
- methodImpl = `${descriptionText}
824
- ${generateMethodName()} {
825
- ${queryParamsDefault}
826
- const url = ${newPath} ${formPayloadString} ${isFileUpload ? "\n// TODO file upload not implemented" : ""}
827
- const resultPromise = this.axiosInstance.${httpMethod}(url, ${dataPayload})
828
-
829
- ${httpMethod === "get" ? ` const res = () => Validate.responseType(() => resultPromise, ${resolvedResponseClassValidated}, '${resolvedResponseClassValidated}')
830
-
831
- if (!this.cache) {
832
- return SdkCache.withoutCache(res)
833
- }
834
- const cacheKey = url + CodeGenUtil.hashCode(JSON.stringify({ params }))
835
- return SdkCache.withCache(cacheKey, res)` : ""}${["post", "put", "patch", "delete"].includes(httpMethod) ? ` return Validate.responseType(() => resultPromise, ${resolvedResponseClassValidated}, '${resolvedResponseClassValidated}')` : ""}
836
- }
837
- `;
838
- if (!isGuardInvoked) {
839
- methodImpl = `${descriptionText}
840
- ${deprecateTag}
841
- TODO_${classMethod}(${methodParams}): Promise<AxiosResponse<${resolvedResponseClass}>> {
842
- ${queryParamsDefault}
843
- const url = ${newPath} ${formPayloadString} ${isFileUpload ? "\n// TODO file upload not implemented" : ""}
844
- return this.axiosInstance.${httpMethod}(url, ${dataPayload})
845
- }
846
- `;
847
- }
848
- const res = {
849
- methodImpl,
850
- methodParams,
851
- methodParamsNoTypes,
852
- importStatements
853
- };
854
- return res;
855
- };
856
-
857
697
  class TemplateZod {
858
698
  duplicates;
859
699
  duplicateFound = false;
@@ -938,7 +778,13 @@ ${exportedTypeString}
938
778
  const schemaAttribute = name ? `'${name}':` : "";
939
779
  const typeAttribute = name ? `'${name}'${typeRequired}:` : "";
940
780
  const type = definition?.type;
941
- if (type) {
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) {
942
788
  if (type === "object" && definition.additionalProperties) {
943
789
  const zodAttribute = this.parseToZodAttribute("", definition.additionalProperties, [""]);
944
790
  return {
@@ -1014,12 +860,6 @@ ${exportedTypeString}
1014
860
  typeString: `${typeAttribute} ${result.typeString}`
1015
861
  };
1016
862
  }
1017
- } else if (definition.properties) {
1018
- const result = this.parseToZodSchema(definition, requiredAttrs);
1019
- return {
1020
- schemaString: `${schemaAttribute} ${result.schemaString}${schemaRequired}`,
1021
- typeString: `${typeAttribute} ${result.typeString}${typeNullishability}`
1022
- };
1023
863
  }
1024
864
  const ref = definition.$ref;
1025
865
  let model = `z.record(z.any())`;
@@ -1106,6 +946,227 @@ const extractEnumObject = (type, isRequired, enumArr) => {
1106
946
  };
1107
947
  };
1108
948
 
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
+
1109
1170
  const templateApiMethod = ({
1110
1171
  classMethod,
1111
1172
  description,
@@ -1167,28 +1228,6 @@ const templateApiMethod = ({
1167
1228
  return [methodImpl, snippetSdk, snippetShell];
1168
1229
  };
1169
1230
 
1170
- const templateApiIndex = (serviceName, serviceNameTitle, apiList) => {
1171
- let imports = "";
1172
- let returnStatement = "";
1173
- for (const cl of apiList) {
1174
- imports += `
1175
- import { ${cl} } from './${serviceName}/${cl}.js'`;
1176
- returnStatement += `
1177
- ${cl}, `;
1178
- }
1179
- return `/**
1180
- * AUTO GENERATED
1181
- */
1182
- ${imports}
1183
-
1184
- const apis = {
1185
- ${returnStatement}
1186
- }
1187
-
1188
- export const ${ParserUtils.convertDashesToTitleCase(serviceNameTitle)} = apis
1189
- `;
1190
- };
1191
-
1192
1231
  const templateSdkSnippet = (serviceNameTitle, apiName, methodSnippet) => {
1193
1232
  const methodArr = methodSnippet.split("//");
1194
1233
  let normMethod = normalizeMethodSnippet(methodArr[0].trim(), "data:");
@@ -1228,21 +1267,33 @@ const normalizeMethodSnippet = (methodInput, splitWord) => {
1228
1267
  };
1229
1268
 
1230
1269
  const GIT_URL = "https://github.com/AccelByte/accelbyte-web-sdk/blob/main/packages";
1231
- class CodeGenerator {
1232
- static getPatchedDir = () => path.join(CliParser.getSwaggersOutputPath(), "patched");
1233
- static getGeneratedPublicFolder = () => `${CliParser.getOutputPath()}/generated-public`;
1234
- static getGeneratedAdminFolder = () => `${CliParser.getOutputPath()}/generated-admin`;
1235
- static getGeneratedSnippetsFolder = () => `${CliParser.getSnippetOutputPath()}/generated-snippets`;
1270
+ class SwaggerReaderHelpers {
1236
1271
  static getServicePrefix = (servicePaths) => servicePaths[servicePaths.length - 1].split("/")[1];
1237
- static iterateApi = async (api, serviceName) => {
1238
- const apiBufferByTag = {};
1239
- const apiArgumentsByTag = {};
1240
- const classBufferByTag = {};
1241
- const dependenciesByTag = {};
1242
- const classImports = {};
1243
- let arrayDefinitions = [];
1244
- const snippetMap = {};
1245
- const mapClassMethods = {};
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
+ };
1246
1297
  const sortedPathsByLength = new Map(Object.entries(api.paths).sort((a, b) => {
1247
1298
  if (a[0].length === b[0].length) {
1248
1299
  return a[0].localeCompare(b[0]);
@@ -1251,55 +1302,62 @@ class CodeGenerator {
1251
1302
  }
1252
1303
  }));
1253
1304
  const sortedKeys = Array.from(sortedPathsByLength.keys());
1254
- const servicePrefix = CodeGenerator.getServicePrefix(sortedKeys);
1255
- for (const [path2, operation] of sortedPathsByLength) {
1256
- const isAdminEndpoint = path2.indexOf("/admin/") > -1;
1257
- if (CliParser.isAdmin() && !isAdminEndpoint) {
1258
- continue;
1259
- } else if (!CliParser.isAdmin() && isAdminEndpoint) {
1260
- continue;
1261
- } 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) {
1262
1312
  continue;
1263
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;
1264
1326
  const httpMethods = Object.keys(operation);
1265
1327
  for (const httpMethod of httpMethods) {
1266
1328
  const endpoint = await Endpoint.parseAsync(operation[httpMethod]).catch((error) => {
1267
- console.error(JSON.stringify({ path: path2, httpMethod }, null, 2));
1329
+ console.error(JSON.stringify({ path, httpMethod }, null, 2));
1268
1330
  throw error;
1269
1331
  });
1270
- if (!endpoint.tags) {
1271
- continue;
1272
- }
1273
- if (endpoint.deprecated) {
1332
+ if (!endpoint.tags || endpoint.deprecated)
1274
1333
  continue;
1275
- }
1276
1334
  const [tag] = endpoint.tags;
1277
- mapClassMethods[tag] = mapClassMethods[tag] ? mapClassMethods[tag] : {};
1335
+ const pathWithBase = `${api.basePath ?? ""}${path}`;
1336
+ tagToClassMethodsMapByType[tag] = tagToClassMethodsMapByType[tag] ? tagToClassMethodsMapByType[tag] : {};
1278
1337
  const isForm = endpoint.consumes && endpoint.consumes[0] === "application/x-www-form-urlencoded";
1279
1338
  const classMethod = ParserUtils.generateNaturalLangMethod({
1280
1339
  servicePrefix,
1281
- path: path2,
1340
+ path,
1282
1341
  httpMethod,
1283
1342
  isForm,
1284
- existingMethods: mapClassMethods[tag]
1343
+ existingMethods: tagToClassMethodsMapByType[tag]
1285
1344
  });
1286
- mapClassMethods[tag][classMethod] = `${path2} ${httpMethod}`;
1287
- snippetMap[path2] = snippetMap[path2] ? snippetMap[path2] : {};
1288
- let description = endpoint.description;
1289
- description = description || "";
1290
- description = description.replace(/\s+/g, " ");
1345
+ tagToClassMethodsMapByType[tag][classMethod] = `${path} ${httpMethod}`;
1346
+ if (!snippetMap[pathWithBase]) {
1347
+ snippetMap[pathWithBase] = {};
1348
+ }
1349
+ const description = endpoint.description?.replace(/\s+/g, " ") || "";
1291
1350
  const responseClass = ParserUtils.get2xxResponse(endpoint.responses);
1292
- const { className, classGenName } = ParserUtils.generateClassName(tag);
1293
- classImports[className] = classImports[className] ? classImports[className] : {};
1351
+ const { className, classGenName } = ParserUtils.generateClassName(tag, isAdminEndpoint);
1352
+ tagToClassImportsRecord[className] = tagToClassImportsRecord[className] ? tagToClassImportsRecord[className] : {};
1294
1353
  if (responseClass) {
1295
1354
  const importTypeClass = ParserUtils.parseRefType(responseClass);
1296
- classImports[className][importTypeClass] = `import { ${importTypeClass} } from '../definitions/${importTypeClass}.js'`;
1355
+ tagToClassImportsRecord[className][importTypeClass] = `import { ${importTypeClass} } from '../definitions/${importTypeClass}.js'`;
1297
1356
  }
1298
1357
  if (responseClass && responseClass.endsWith("Array")) {
1299
1358
  arrayDefinitions.push(responseClass);
1300
1359
  }
1301
1360
  const queryParams = ParserUtils.filterQueryParameters(endpoint.parameters);
1302
- const pathWithBase = `${api.basePath ?? ""}${path2}`;
1303
1361
  const isFormUrlEncoded = ParserUtils.isFormUrlEncoded(httpMethod, endpoint.consumes);
1304
1362
  const pathParams = ParserUtils.filterPathParams(endpoint.parameters);
1305
1363
  let bodyParams = ParserUtils.filterBodyParams(endpoint.parameters);
@@ -1323,8 +1381,8 @@ class CodeGenerator {
1323
1381
  isFormUrlEncoded,
1324
1382
  responseClass
1325
1383
  });
1326
- classBufferByTag[tag] = (classBufferByTag[tag] || "") + methodImpl;
1327
- const [generatedMethodString1, snippetMethod, snippetShell] = templateApiMethod({
1384
+ tagToEndpointClassesRecord[tag] = (tagToEndpointClassesRecord[tag] || "") + methodImpl;
1385
+ const [generatedMethodString, snippetMethod, snippetShell] = templateApiMethod({
1328
1386
  classMethod,
1329
1387
  description,
1330
1388
  httpMethod,
@@ -1336,32 +1394,37 @@ class CodeGenerator {
1336
1394
  methodParams,
1337
1395
  methodParamsNoTypes
1338
1396
  });
1339
- apiBufferByTag[tag] = (apiBufferByTag[tag] || "") + generatedMethodString1;
1340
- apiArgumentsByTag[tag] = (apiArgumentsByTag[tag] || "") + classMethod + ",";
1341
- dependenciesByTag[tag] = dependenciesByTag[tag] ? [.../* @__PURE__ */ new Set([...importStatements, ...dependenciesByTag[tag]])] : [...new Set(importStatements)];
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)];
1342
1400
  const serviceNameTitle = ParserUtils.convertDashesToTitleCase(serviceName);
1343
- const { apiGenName } = ParserUtils.generateApiName(tag);
1401
+ const { apiGenName } = ParserUtils.generateApiName(tag, isAdminEndpoint);
1344
1402
  const resultSnippet = templateSdkSnippet(serviceNameTitle, apiGenName, snippetMethod);
1345
- snippetMap[path2][httpMethod] = {
1346
- web: resultSnippet,
1347
- webGit: GIT_URL + `/sdk-${serviceName}/src/generated-public/${serviceName}/${apiGenName}.ts`,
1348
- shell: snippetShell
1349
- };
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;
1350
1410
  }
1351
1411
  }
1352
- arrayDefinitions = [...new Set(arrayDefinitions)];
1353
- return {
1354
- apiArgumentsByTag,
1355
- apiBufferByTag,
1356
- classBufferByTag,
1357
- dependenciesByTag,
1358
- classImports,
1359
- arrayDefinitions,
1360
- snippetMap
1361
- };
1412
+ for (const key in result) {
1413
+ result[key].arrayDefinitions = Array.from(new Set(result[key].arrayDefinitions));
1414
+ }
1415
+ return result;
1362
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];
1363
1425
  static main = async (nameArray) => {
1364
1426
  const serviceName = nameArray[0];
1427
+ const sdkName = nameArray[1];
1365
1428
  const swaggerFile = nameArray[2];
1366
1429
  const parser = new SwaggerParser();
1367
1430
  const generatedFolder = CliParser.isAdmin() ? CodeGenerator.getGeneratedAdminFolder() : CodeGenerator.getGeneratedPublicFolder();
@@ -1376,27 +1439,39 @@ class CodeGenerator {
1376
1439
  ParserUtils.mkdirIfNotExist(DIST_DIR);
1377
1440
  ParserUtils.mkdirIfNotExist(DIST_DEFINITION_DIR);
1378
1441
  ParserUtils.mkdirIfNotExist(DIST_ENDPOINTS_DIR);
1379
- ParserUtils.syncPackageVersion(apiInfo, CliParser.isAdmin(), process.env.PRERELEASE_ID);
1380
- const { apiArgumentsByTag, apiBufferByTag, classBufferByTag, dependenciesByTag, classImports, arrayDefinitions, snippetMap } = await CodeGenerator.iterateApi(api, serviceName);
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;
1381
1453
  if (CliParser.getSnippetOutputPath()) {
1382
1454
  try {
1383
- ParserUtils.writeSnippetFile(CodeGenerator.getGeneratedSnippetsFolder(), api.info.title, JSON.stringify(snippetMap, null, 2));
1455
+ ParserUtils.writeSnippetFile(CodeGenerator.getGeneratedSnippetsFolder(), api.info.title, JSON.stringify({
1456
+ ...parsedInformation.public.snippetMap,
1457
+ ...parsedInformation.admin.snippetMap
1458
+ }, null, 2));
1384
1459
  } catch (err) {
1385
1460
  console.log("Generating snippets", err);
1386
1461
  }
1387
1462
  }
1388
1463
  const targetSrcFolder = `${CliParser.getOutputPath()}/`;
1389
1464
  const apiList = [];
1390
- for (const tag in classBufferByTag) {
1391
- const { className, classGenName } = ParserUtils.generateClassName(tag);
1392
- const classBuffer = classBufferByTag[tag];
1393
- const imports = [.../* @__PURE__ */ new Set([...dependenciesByTag[tag], ...Object.values(classImports[className])])];
1394
- const apiImports = [.../* @__PURE__ */ new Set([...dependenciesByTag[tag], ...Object.values(classImports[className])])];
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])])];
1395
1470
  apiImports.push(`import { ${classGenName} } from './endpoints/${classGenName}.js'`);
1396
1471
  ParserUtils.writeClassFile(DIST_ENDPOINTS_DIR, classGenName, classBuffer, imports);
1397
- const apiBuffer = apiBufferByTag[tag];
1398
- const { apiGenName } = ParserUtils.generateApiName(tag);
1399
- ParserUtils.writeApiFile(DIST_DIR, apiGenName, apiBuffer, apiImports, apiArgumentsByTag[tag]);
1472
+ const apiBuffer = tagToSdkClientRecord[tag];
1473
+ const { apiGenName } = ParserUtils.generateApiName(tag, CliParser.isAdmin());
1474
+ ParserUtils.writeApiFile(DIST_DIR, apiGenName, apiBuffer, apiImports, tagToSdkFunctionNamesRecord[tag]);
1400
1475
  apiList.push(apiGenName);
1401
1476
  indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path.join(DIST_ENDPOINTS_DIR, `${classGenName}`), targetSrcFolder));
1402
1477
  indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path.join(DIST_DIR, `${apiGenName}`), targetSrcFolder));