@accelbyte/codegen 2.0.0-beta.5 → 2.0.0-beta.6
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 +333 -299
- package/dist/accelbyte-codegen.js.map +1 -1
- package/dist/accelbyte-codegen.mjs +333 -299
- package/dist/accelbyte-codegen.mjs.map +1 -1
- package/package.json +1 -21
- package/scripts/generate-test-resources.mjs +105 -0
|
@@ -215,14 +215,14 @@ class ParserUtils {
|
|
|
215
215
|
static replaceAll = (string, search, replace) => {
|
|
216
216
|
return string.split(search).join(replace);
|
|
217
217
|
};
|
|
218
|
-
static generateClassName = (tag) => {
|
|
218
|
+
static generateClassName = (tag, isAdmin) => {
|
|
219
219
|
const className = _.upperFirst(_.camelCase(tag));
|
|
220
|
-
const classGenName =
|
|
220
|
+
const classGenName = isAdmin ? className + "Admin$" : className + "$";
|
|
221
221
|
return { className, classGenName };
|
|
222
222
|
};
|
|
223
|
-
static generateApiName = (tag) => {
|
|
223
|
+
static generateApiName = (tag, isAdmin) => {
|
|
224
224
|
const apiName = _.upperFirst(_.camelCase(tag));
|
|
225
|
-
const apiGenName =
|
|
225
|
+
const apiGenName = isAdmin ? apiName + "AdminApi" : apiName + "Api";
|
|
226
226
|
return { apiName, apiGenName };
|
|
227
227
|
};
|
|
228
228
|
static parseQueryParamAttributeDefault = (definition) => {
|
|
@@ -594,9 +594,7 @@ class ParserUtils {
|
|
|
594
594
|
${content}`;
|
|
595
595
|
};
|
|
596
596
|
static sortPathParamsByPath = (pathParams, path2) => {
|
|
597
|
-
|
|
598
|
-
const cleanParams = params.map((param) => param.replace("{", "").replace("}", ""));
|
|
599
|
-
return pathParams.sort((a, b) => cleanParams.indexOf(a.name) - cleanParams.indexOf(b.name));
|
|
597
|
+
return pathParams.sort((a, b) => path2.indexOf(a.name) - path2.indexOf(b.name));
|
|
600
598
|
};
|
|
601
599
|
}
|
|
602
600
|
const mappedMethod = (httpMethod, isForm) => {
|
|
@@ -664,205 +662,6 @@ const isSwaggerIntegerType = (type) => {
|
|
|
664
662
|
return type === "integer" || type === "int";
|
|
665
663
|
};
|
|
666
664
|
|
|
667
|
-
const Schema = z.object({
|
|
668
|
-
$ref: z.string().nullish(),
|
|
669
|
-
type: z.union([z.literal("array"), z.literal("object"), z.literal("file"), z.literal("string"), z.literal("boolean"), z.literal("integer")]).nullish(),
|
|
670
|
-
items: z.object({
|
|
671
|
-
$ref: z.string().nullish(),
|
|
672
|
-
type: z.string().nullish()
|
|
673
|
-
}).nullish(),
|
|
674
|
-
properties: z.union([z.array(z.string()).nullish(), z.record(z.object({ type: z.string() })).nullish()]),
|
|
675
|
-
description: z.string().nullish(),
|
|
676
|
-
additionalProperties: z.object({
|
|
677
|
-
type: z.string().nullish()
|
|
678
|
-
}).nullish()
|
|
679
|
-
});
|
|
680
|
-
const Definition = z.object({
|
|
681
|
-
required: z.array(z.string()).nullish(),
|
|
682
|
-
properties: z.record(z.object({
|
|
683
|
-
type: z.string()
|
|
684
|
-
})).nullish()
|
|
685
|
-
});
|
|
686
|
-
const Definitions = z.record(Definition);
|
|
687
|
-
const EndpointParametersType = z.enum(["apiKey", "boolean", "int", "integer", "number", "string", "array", "file"]);
|
|
688
|
-
const EndpointParametersIn = z.enum(["body", "formData", "header", "path", "query"]);
|
|
689
|
-
const EndpointParameters = z.object({
|
|
690
|
-
type: EndpointParametersType.nullish(),
|
|
691
|
-
description: z.string().nullish(),
|
|
692
|
-
name: z.string(),
|
|
693
|
-
in: EndpointParametersIn,
|
|
694
|
-
required: z.boolean().nullish(),
|
|
695
|
-
schema: Schema.nullish(),
|
|
696
|
-
default: z.union([z.boolean(), z.string(), z.number(), z.array(z.any())]).nullish(),
|
|
697
|
-
enum: z.array(z.union([z.boolean(), z.string(), z.number()])).nullish(),
|
|
698
|
-
items: z.object({
|
|
699
|
-
type: z.string(),
|
|
700
|
-
enum: z.array(z.any()).nullish()
|
|
701
|
-
}).nullish()
|
|
702
|
-
});
|
|
703
|
-
const Endpoint = z.object({
|
|
704
|
-
description: z.string().nullish(),
|
|
705
|
-
consumes: z.array(z.string()).nullish(),
|
|
706
|
-
produces: z.array(z.string()).nullish(),
|
|
707
|
-
tags: z.array(z.string()).nullish(),
|
|
708
|
-
summary: z.string().nullish(),
|
|
709
|
-
operationId: z.string(),
|
|
710
|
-
deprecated: z.boolean().nullish(),
|
|
711
|
-
responses: z.record(z.object({
|
|
712
|
-
description: z.string().nullish(),
|
|
713
|
-
schema: Schema.nullish(),
|
|
714
|
-
content: z.object({
|
|
715
|
-
"application/json": z.object({
|
|
716
|
-
schema: Schema.nullish()
|
|
717
|
-
})
|
|
718
|
-
}).nullish()
|
|
719
|
-
})),
|
|
720
|
-
parameters: z.array(EndpointParameters).nullish(),
|
|
721
|
-
requestBody: z.object({
|
|
722
|
-
required: z.boolean(),
|
|
723
|
-
content: z.object({
|
|
724
|
-
"application/json": z.object({
|
|
725
|
-
schema: Schema.nullish()
|
|
726
|
-
})
|
|
727
|
-
}).nullish()
|
|
728
|
-
}).nullish()
|
|
729
|
-
});
|
|
730
|
-
const Operation = z.object({
|
|
731
|
-
get: Endpoint.nullish(),
|
|
732
|
-
post: Endpoint.nullish(),
|
|
733
|
-
patch: Endpoint.nullish(),
|
|
734
|
-
delete: Endpoint.nullish(),
|
|
735
|
-
put: Endpoint.nullish()
|
|
736
|
-
});
|
|
737
|
-
const Paths = z.record(Operation);
|
|
738
|
-
z.object({
|
|
739
|
-
paths: Paths,
|
|
740
|
-
definitions: Definitions,
|
|
741
|
-
basePath: z.string(),
|
|
742
|
-
info: z.object({
|
|
743
|
-
description: z.string(),
|
|
744
|
-
title: z.string(),
|
|
745
|
-
contact: z.object({
|
|
746
|
-
name: z.string(),
|
|
747
|
-
url: z.string(),
|
|
748
|
-
email: z.string()
|
|
749
|
-
}),
|
|
750
|
-
version: z.string()
|
|
751
|
-
}),
|
|
752
|
-
schemes: z.array(z.string()).nullish(),
|
|
753
|
-
components: z.object({
|
|
754
|
-
schemas: Definitions
|
|
755
|
-
}).nullish()
|
|
756
|
-
});
|
|
757
|
-
|
|
758
|
-
const templateMethod = ({
|
|
759
|
-
classMethod,
|
|
760
|
-
description,
|
|
761
|
-
httpMethod,
|
|
762
|
-
path,
|
|
763
|
-
pathParams,
|
|
764
|
-
bodyParams,
|
|
765
|
-
queryParams,
|
|
766
|
-
isFormUrlEncoded,
|
|
767
|
-
responseClass
|
|
768
|
-
}) => {
|
|
769
|
-
let methodParams = "";
|
|
770
|
-
let methodParamsNoTypes = "";
|
|
771
|
-
let newPath = `'${path}'`;
|
|
772
|
-
let importStatements = [];
|
|
773
|
-
const sortedPathParams = ParserUtils.sortPathParamsByPath(pathParams, path);
|
|
774
|
-
for (const pathParam of sortedPathParams) {
|
|
775
|
-
const type = ParserUtils.parseType(pathParam);
|
|
776
|
-
if (pathParam.name !== "namespace") {
|
|
777
|
-
methodParams += pathParam.name + `:${type}, `;
|
|
778
|
-
methodParamsNoTypes += pathParam.name + ", ";
|
|
779
|
-
}
|
|
780
|
-
const pName = pathParam.name === "namespace" ? "this.namespace" : pathParam.name;
|
|
781
|
-
if (path.match(`{${pathParam.name}}`)) {
|
|
782
|
-
if (type === "string") {
|
|
783
|
-
newPath = `${newPath}.replace('{${pathParam.name}}', ${pName})`;
|
|
784
|
-
} else {
|
|
785
|
-
newPath = `${newPath}.replace('{${pathParam.name}}', String(${pName}))`;
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
}
|
|
789
|
-
let dataType = null;
|
|
790
|
-
if (httpMethod !== "get") {
|
|
791
|
-
dataType = ParserUtils.parseBodyParamsType(bodyParams);
|
|
792
|
-
importStatements = ParserUtils.parseBodyParamsImports(bodyParams);
|
|
793
|
-
methodParams += dataType ? `data: ${dataType},` : "";
|
|
794
|
-
methodParamsNoTypes += dataType ? `data,` : "";
|
|
795
|
-
}
|
|
796
|
-
const isAnyRequired = ParserUtils.isAnyQueryParamRequired(queryParams);
|
|
797
|
-
const queryParamsType = queryParams.length ? `queryParams${isAnyRequired ? "" : "?"}: {${ParserUtils.parseQueryParamsType(queryParams)}}` : "";
|
|
798
|
-
const queryParamsDefault = queryParams.length ? `const params = {${ParserUtils.parseQueryParamsDefault(queryParams)} ...queryParams} as SDKRequestConfig` : "const params = {} as SDKRequestConfig";
|
|
799
|
-
const isPostPutPatch = ["post", "put", "patch"].includes(httpMethod);
|
|
800
|
-
const isDelete = ["delete"].includes(httpMethod);
|
|
801
|
-
let dataPayload = "{params}";
|
|
802
|
-
const descriptionText = description ? `
|
|
803
|
-
/**
|
|
804
|
-
* ${description.replace(/\n/g, "\n * ")}
|
|
805
|
-
*/` : "";
|
|
806
|
-
let formPayloadString = "";
|
|
807
|
-
if (isFormUrlEncoded) {
|
|
808
|
-
formPayloadString = ``;
|
|
809
|
-
const params = "{ ...params, headers: { ...params.headers, 'content-type': 'application/x-www-form-urlencoded' } }";
|
|
810
|
-
dataPayload = dataType ? `CodeGenUtil.getFormUrlEncodedData(data), ${params}` : `null, ${params}`;
|
|
811
|
-
} else if (isPostPutPatch) {
|
|
812
|
-
dataPayload = dataType ? `data, {params}` : "null, {params}";
|
|
813
|
-
} else if (isDelete) {
|
|
814
|
-
dataPayload = dataType ? `{data, params}` : "{params}";
|
|
815
|
-
}
|
|
816
|
-
const isFileUpload = methodParams.indexOf("data: {file") > -1;
|
|
817
|
-
const resolvedResponseClass = responseClass || "unknown";
|
|
818
|
-
const resolvedResponseClassValidated = responseClass || "z.unknown()";
|
|
819
|
-
methodParams = (queryParamsType ? `${methodParams} ${queryParamsType}` : methodParams).replace(/,\s*$/, "");
|
|
820
|
-
methodParamsNoTypes = queryParamsType ? `${methodParamsNoTypes} queryParams` : methodParamsNoTypes;
|
|
821
|
-
let methodImpl = "";
|
|
822
|
-
const isCacheFetch = ["get"].includes(httpMethod) && resolvedResponseClass !== "unknown";
|
|
823
|
-
const cachedFetchMethod = classMethod;
|
|
824
|
-
const deprecateTag = isCacheFetch ? `/**
|
|
825
|
-
* @deprecated Use "${classMethod}()" instead.
|
|
826
|
-
*/` : "";
|
|
827
|
-
const isGuardInvoked = ["get", "post", "put", "patch", "delete"].includes(httpMethod);
|
|
828
|
-
const methodName = httpMethod === "get" ? cachedFetchMethod : ["post", "put", "patch", "delete"].includes(httpMethod) ? classMethod : "";
|
|
829
|
-
const responseType = resolvedResponseClass !== "unknown" ? `${resolvedResponseClass}` : "unknown";
|
|
830
|
-
const generateMethodName = () => `${methodName}(${methodParams}): Promise<${responseSyncType}<${responseType}>>`;
|
|
831
|
-
const responseSyncType = httpMethod === "get" ? "IResponseWithSync" : ["post", "put", "patch", "delete"].includes(httpMethod) ? "IResponse" : "";
|
|
832
|
-
methodImpl = `${descriptionText}
|
|
833
|
-
${generateMethodName()} {
|
|
834
|
-
${queryParamsDefault}
|
|
835
|
-
const url = ${newPath} ${formPayloadString} ${isFileUpload ? "\n// TODO file upload not implemented" : ""}
|
|
836
|
-
const resultPromise = this.axiosInstance.${httpMethod}(url, ${dataPayload})
|
|
837
|
-
|
|
838
|
-
${httpMethod === "get" ? ` const res = () => Validate.responseType(() => resultPromise, ${resolvedResponseClassValidated}, '${resolvedResponseClassValidated}')
|
|
839
|
-
|
|
840
|
-
if (!this.cache) {
|
|
841
|
-
return SdkCache.withoutCache(res)
|
|
842
|
-
}
|
|
843
|
-
const cacheKey = url + CodeGenUtil.hashCode(JSON.stringify({ params }))
|
|
844
|
-
return SdkCache.withCache(cacheKey, res)` : ""}${["post", "put", "patch", "delete"].includes(httpMethod) ? ` return Validate.responseType(() => resultPromise, ${resolvedResponseClassValidated}, '${resolvedResponseClassValidated}')` : ""}
|
|
845
|
-
}
|
|
846
|
-
`;
|
|
847
|
-
if (!isGuardInvoked) {
|
|
848
|
-
methodImpl = `${descriptionText}
|
|
849
|
-
${deprecateTag}
|
|
850
|
-
TODO_${classMethod}(${methodParams}): Promise<AxiosResponse<${resolvedResponseClass}>> {
|
|
851
|
-
${queryParamsDefault}
|
|
852
|
-
const url = ${newPath} ${formPayloadString} ${isFileUpload ? "\n// TODO file upload not implemented" : ""}
|
|
853
|
-
return this.axiosInstance.${httpMethod}(url, ${dataPayload})
|
|
854
|
-
}
|
|
855
|
-
`;
|
|
856
|
-
}
|
|
857
|
-
const res = {
|
|
858
|
-
methodImpl,
|
|
859
|
-
methodParams,
|
|
860
|
-
methodParamsNoTypes,
|
|
861
|
-
importStatements
|
|
862
|
-
};
|
|
863
|
-
return res;
|
|
864
|
-
};
|
|
865
|
-
|
|
866
665
|
class TemplateZod {
|
|
867
666
|
duplicates;
|
|
868
667
|
duplicateFound = false;
|
|
@@ -1115,6 +914,227 @@ const extractEnumObject = (type, isRequired, enumArr) => {
|
|
|
1115
914
|
};
|
|
1116
915
|
};
|
|
1117
916
|
|
|
917
|
+
const templateApiIndex = (serviceName, serviceNameTitle, apiList) => {
|
|
918
|
+
let imports = "";
|
|
919
|
+
let returnStatement = "";
|
|
920
|
+
for (const cl of apiList) {
|
|
921
|
+
imports += `
|
|
922
|
+
import { ${cl} } from './${serviceName}/${cl}.js'`;
|
|
923
|
+
returnStatement += `
|
|
924
|
+
${cl}, `;
|
|
925
|
+
}
|
|
926
|
+
return `/**
|
|
927
|
+
* AUTO GENERATED
|
|
928
|
+
*/
|
|
929
|
+
${imports}
|
|
930
|
+
|
|
931
|
+
const apis = {
|
|
932
|
+
${returnStatement}
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
export const ${ParserUtils.convertDashesToTitleCase(serviceNameTitle)} = apis
|
|
936
|
+
`;
|
|
937
|
+
};
|
|
938
|
+
|
|
939
|
+
const Schema = z.object({
|
|
940
|
+
$ref: z.string().nullish(),
|
|
941
|
+
type: z.union([z.literal("array"), z.literal("object"), z.literal("file"), z.literal("string"), z.literal("boolean"), z.literal("integer")]).nullish(),
|
|
942
|
+
items: z.object({
|
|
943
|
+
$ref: z.string().nullish(),
|
|
944
|
+
type: z.string().nullish()
|
|
945
|
+
}).nullish(),
|
|
946
|
+
properties: z.union([z.array(z.string()).nullish(), z.record(z.object({ type: z.string() })).nullish()]),
|
|
947
|
+
description: z.string().nullish(),
|
|
948
|
+
additionalProperties: z.object({
|
|
949
|
+
type: z.string().nullish()
|
|
950
|
+
}).nullish()
|
|
951
|
+
});
|
|
952
|
+
const Definition = z.object({
|
|
953
|
+
required: z.array(z.string()).nullish(),
|
|
954
|
+
properties: z.record(z.object({
|
|
955
|
+
type: z.string()
|
|
956
|
+
})).nullish()
|
|
957
|
+
});
|
|
958
|
+
const Definitions = z.record(Definition);
|
|
959
|
+
const EndpointParametersType = z.enum(["apiKey", "boolean", "int", "integer", "number", "string", "array", "file"]);
|
|
960
|
+
const EndpointParametersIn = z.enum(["body", "formData", "header", "path", "query"]);
|
|
961
|
+
const EndpointParameters = z.object({
|
|
962
|
+
type: EndpointParametersType.nullish(),
|
|
963
|
+
description: z.string().nullish(),
|
|
964
|
+
name: z.string(),
|
|
965
|
+
in: EndpointParametersIn,
|
|
966
|
+
required: z.boolean().nullish(),
|
|
967
|
+
schema: Schema.nullish(),
|
|
968
|
+
default: z.union([z.boolean(), z.string(), z.number(), z.array(z.any())]).nullish(),
|
|
969
|
+
enum: z.array(z.union([z.boolean(), z.string(), z.number()])).nullish(),
|
|
970
|
+
items: z.object({
|
|
971
|
+
type: z.string(),
|
|
972
|
+
enum: z.array(z.any()).nullish()
|
|
973
|
+
}).nullish()
|
|
974
|
+
});
|
|
975
|
+
const Endpoint = z.object({
|
|
976
|
+
description: z.string().nullish(),
|
|
977
|
+
consumes: z.array(z.string()).nullish(),
|
|
978
|
+
produces: z.array(z.string()).nullish(),
|
|
979
|
+
tags: z.array(z.string()).nullish(),
|
|
980
|
+
summary: z.string().nullish(),
|
|
981
|
+
operationId: z.string(),
|
|
982
|
+
deprecated: z.boolean().nullish(),
|
|
983
|
+
responses: z.record(z.object({
|
|
984
|
+
description: z.string().nullish(),
|
|
985
|
+
schema: Schema.nullish(),
|
|
986
|
+
content: z.object({
|
|
987
|
+
"application/json": z.object({
|
|
988
|
+
schema: Schema.nullish()
|
|
989
|
+
})
|
|
990
|
+
}).nullish()
|
|
991
|
+
})),
|
|
992
|
+
parameters: z.array(EndpointParameters).nullish(),
|
|
993
|
+
requestBody: z.object({
|
|
994
|
+
required: z.boolean(),
|
|
995
|
+
content: z.object({
|
|
996
|
+
"application/json": z.object({
|
|
997
|
+
schema: Schema.nullish()
|
|
998
|
+
})
|
|
999
|
+
}).nullish()
|
|
1000
|
+
}).nullish()
|
|
1001
|
+
});
|
|
1002
|
+
const Operation = z.object({
|
|
1003
|
+
get: Endpoint.nullish(),
|
|
1004
|
+
post: Endpoint.nullish(),
|
|
1005
|
+
patch: Endpoint.nullish(),
|
|
1006
|
+
delete: Endpoint.nullish(),
|
|
1007
|
+
put: Endpoint.nullish()
|
|
1008
|
+
});
|
|
1009
|
+
const Paths = z.record(Operation);
|
|
1010
|
+
z.object({
|
|
1011
|
+
paths: Paths,
|
|
1012
|
+
definitions: Definitions,
|
|
1013
|
+
basePath: z.string(),
|
|
1014
|
+
info: z.object({
|
|
1015
|
+
description: z.string(),
|
|
1016
|
+
title: z.string(),
|
|
1017
|
+
contact: z.object({
|
|
1018
|
+
name: z.string(),
|
|
1019
|
+
url: z.string(),
|
|
1020
|
+
email: z.string()
|
|
1021
|
+
}),
|
|
1022
|
+
version: z.string()
|
|
1023
|
+
}),
|
|
1024
|
+
schemes: z.array(z.string()).nullish(),
|
|
1025
|
+
components: z.object({
|
|
1026
|
+
schemas: Definitions
|
|
1027
|
+
}).nullish()
|
|
1028
|
+
});
|
|
1029
|
+
|
|
1030
|
+
const templateMethod = ({
|
|
1031
|
+
classMethod,
|
|
1032
|
+
description,
|
|
1033
|
+
httpMethod,
|
|
1034
|
+
path,
|
|
1035
|
+
pathParams,
|
|
1036
|
+
bodyParams,
|
|
1037
|
+
queryParams,
|
|
1038
|
+
isFormUrlEncoded,
|
|
1039
|
+
responseClass
|
|
1040
|
+
}) => {
|
|
1041
|
+
let methodParams = "";
|
|
1042
|
+
let methodParamsNoTypes = "";
|
|
1043
|
+
let newPath = `'${path}'`;
|
|
1044
|
+
let importStatements = [];
|
|
1045
|
+
const sortedPathParams = ParserUtils.sortPathParamsByPath(pathParams, path);
|
|
1046
|
+
for (const pathParam of sortedPathParams) {
|
|
1047
|
+
const type = ParserUtils.parseType(pathParam);
|
|
1048
|
+
if (pathParam.name !== "namespace") {
|
|
1049
|
+
methodParams += pathParam.name + `:${type}, `;
|
|
1050
|
+
methodParamsNoTypes += pathParam.name + ", ";
|
|
1051
|
+
}
|
|
1052
|
+
const pName = pathParam.name === "namespace" ? "this.namespace" : pathParam.name;
|
|
1053
|
+
if (path.match(`{${pathParam.name}}`)) {
|
|
1054
|
+
if (type === "string") {
|
|
1055
|
+
newPath = `${newPath}.replace('{${pathParam.name}}', ${pName})`;
|
|
1056
|
+
} else {
|
|
1057
|
+
newPath = `${newPath}.replace('{${pathParam.name}}', String(${pName}))`;
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
let dataType = null;
|
|
1062
|
+
if (httpMethod !== "get") {
|
|
1063
|
+
dataType = ParserUtils.parseBodyParamsType(bodyParams);
|
|
1064
|
+
importStatements = ParserUtils.parseBodyParamsImports(bodyParams);
|
|
1065
|
+
methodParams += dataType ? `data: ${dataType},` : "";
|
|
1066
|
+
methodParamsNoTypes += dataType ? `data,` : "";
|
|
1067
|
+
}
|
|
1068
|
+
const isAnyRequired = ParserUtils.isAnyQueryParamRequired(queryParams);
|
|
1069
|
+
const queryParamsType = queryParams.length ? `queryParams${isAnyRequired ? "" : "?"}: {${ParserUtils.parseQueryParamsType(queryParams)}}` : "";
|
|
1070
|
+
const queryParamsDefault = queryParams.length ? `const params = {${ParserUtils.parseQueryParamsDefault(queryParams)} ...queryParams} as SDKRequestConfig` : "const params = {} as SDKRequestConfig";
|
|
1071
|
+
const isPostPutPatch = ["post", "put", "patch"].includes(httpMethod);
|
|
1072
|
+
const isDelete = ["delete"].includes(httpMethod);
|
|
1073
|
+
let dataPayload = "{params}";
|
|
1074
|
+
const descriptionText = description ? `
|
|
1075
|
+
/**
|
|
1076
|
+
* ${description.replace(/\n/g, "\n * ")}
|
|
1077
|
+
*/` : "";
|
|
1078
|
+
let formPayloadString = "";
|
|
1079
|
+
if (isFormUrlEncoded) {
|
|
1080
|
+
formPayloadString = ``;
|
|
1081
|
+
const params = "{ ...params, headers: { ...params.headers, 'content-type': 'application/x-www-form-urlencoded' } }";
|
|
1082
|
+
dataPayload = dataType ? `CodeGenUtil.getFormUrlEncodedData(data), ${params}` : `null, ${params}`;
|
|
1083
|
+
} else if (isPostPutPatch) {
|
|
1084
|
+
dataPayload = dataType ? `data, {params}` : "null, {params}";
|
|
1085
|
+
} else if (isDelete) {
|
|
1086
|
+
dataPayload = dataType ? `{data, params}` : "{params}";
|
|
1087
|
+
}
|
|
1088
|
+
const isFileUpload = methodParams.indexOf("data: {file") > -1;
|
|
1089
|
+
const resolvedResponseClass = responseClass || "unknown";
|
|
1090
|
+
const resolvedResponseClassValidated = responseClass || "z.unknown()";
|
|
1091
|
+
methodParams = (queryParamsType ? `${methodParams} ${queryParamsType}` : methodParams).replace(/,\s*$/, "");
|
|
1092
|
+
methodParamsNoTypes = queryParamsType ? `${methodParamsNoTypes} queryParams` : methodParamsNoTypes;
|
|
1093
|
+
let methodImpl = "";
|
|
1094
|
+
const isCacheFetch = ["get"].includes(httpMethod) && resolvedResponseClass !== "unknown";
|
|
1095
|
+
const cachedFetchMethod = classMethod;
|
|
1096
|
+
const deprecateTag = isCacheFetch ? `/**
|
|
1097
|
+
* @deprecated Use "${classMethod}()" instead.
|
|
1098
|
+
*/` : "";
|
|
1099
|
+
const isGuardInvoked = ["get", "post", "put", "patch", "delete"].includes(httpMethod);
|
|
1100
|
+
const methodName = httpMethod === "get" ? cachedFetchMethod : ["post", "put", "patch", "delete"].includes(httpMethod) ? classMethod : "";
|
|
1101
|
+
const responseType = resolvedResponseClass !== "unknown" ? `${resolvedResponseClass}` : "unknown";
|
|
1102
|
+
const generateMethodName = () => `${methodName}(${methodParams}): Promise<${responseSyncType}<${responseType}>>`;
|
|
1103
|
+
const responseSyncType = httpMethod === "get" ? "IResponseWithSync" : ["post", "put", "patch", "delete"].includes(httpMethod) ? "IResponse" : "";
|
|
1104
|
+
methodImpl = `${descriptionText}
|
|
1105
|
+
${generateMethodName()} {
|
|
1106
|
+
${queryParamsDefault}
|
|
1107
|
+
const url = ${newPath} ${formPayloadString} ${isFileUpload ? "\n// TODO file upload not implemented" : ""}
|
|
1108
|
+
const resultPromise = this.axiosInstance.${httpMethod}(url, ${dataPayload})
|
|
1109
|
+
|
|
1110
|
+
${httpMethod === "get" ? ` const res = () => Validate.responseType(() => resultPromise, ${resolvedResponseClassValidated}, '${resolvedResponseClassValidated}')
|
|
1111
|
+
|
|
1112
|
+
if (!this.cache) {
|
|
1113
|
+
return SdkCache.withoutCache(res)
|
|
1114
|
+
}
|
|
1115
|
+
const cacheKey = url + CodeGenUtil.hashCode(JSON.stringify({ params }))
|
|
1116
|
+
return SdkCache.withCache(cacheKey, res)` : ""}${["post", "put", "patch", "delete"].includes(httpMethod) ? ` return Validate.responseType(() => resultPromise, ${resolvedResponseClassValidated}, '${resolvedResponseClassValidated}')` : ""}
|
|
1117
|
+
}
|
|
1118
|
+
`;
|
|
1119
|
+
if (!isGuardInvoked) {
|
|
1120
|
+
methodImpl = `${descriptionText}
|
|
1121
|
+
${deprecateTag}
|
|
1122
|
+
TODO_${classMethod}(${methodParams}): Promise<AxiosResponse<${resolvedResponseClass}>> {
|
|
1123
|
+
${queryParamsDefault}
|
|
1124
|
+
const url = ${newPath} ${formPayloadString} ${isFileUpload ? "\n// TODO file upload not implemented" : ""}
|
|
1125
|
+
return this.axiosInstance.${httpMethod}(url, ${dataPayload})
|
|
1126
|
+
}
|
|
1127
|
+
`;
|
|
1128
|
+
}
|
|
1129
|
+
const res = {
|
|
1130
|
+
methodImpl,
|
|
1131
|
+
methodParams,
|
|
1132
|
+
methodParamsNoTypes,
|
|
1133
|
+
importStatements
|
|
1134
|
+
};
|
|
1135
|
+
return res;
|
|
1136
|
+
};
|
|
1137
|
+
|
|
1118
1138
|
const templateApiMethod = ({
|
|
1119
1139
|
classMethod,
|
|
1120
1140
|
description,
|
|
@@ -1176,28 +1196,6 @@ const templateApiMethod = ({
|
|
|
1176
1196
|
return [methodImpl, snippetSdk, snippetShell];
|
|
1177
1197
|
};
|
|
1178
1198
|
|
|
1179
|
-
const templateApiIndex = (serviceName, serviceNameTitle, apiList) => {
|
|
1180
|
-
let imports = "";
|
|
1181
|
-
let returnStatement = "";
|
|
1182
|
-
for (const cl of apiList) {
|
|
1183
|
-
imports += `
|
|
1184
|
-
import { ${cl} } from './${serviceName}/${cl}.js'`;
|
|
1185
|
-
returnStatement += `
|
|
1186
|
-
${cl}, `;
|
|
1187
|
-
}
|
|
1188
|
-
return `/**
|
|
1189
|
-
* AUTO GENERATED
|
|
1190
|
-
*/
|
|
1191
|
-
${imports}
|
|
1192
|
-
|
|
1193
|
-
const apis = {
|
|
1194
|
-
${returnStatement}
|
|
1195
|
-
}
|
|
1196
|
-
|
|
1197
|
-
export const ${ParserUtils.convertDashesToTitleCase(serviceNameTitle)} = apis
|
|
1198
|
-
`;
|
|
1199
|
-
};
|
|
1200
|
-
|
|
1201
1199
|
const templateSdkSnippet = (serviceNameTitle, apiName, methodSnippet) => {
|
|
1202
1200
|
const methodArr = methodSnippet.split("//");
|
|
1203
1201
|
let normMethod = normalizeMethodSnippet(methodArr[0].trim(), "data:");
|
|
@@ -1237,21 +1235,33 @@ const normalizeMethodSnippet = (methodInput, splitWord) => {
|
|
|
1237
1235
|
};
|
|
1238
1236
|
|
|
1239
1237
|
const GIT_URL = "https://github.com/AccelByte/accelbyte-web-sdk/blob/main/packages";
|
|
1240
|
-
class
|
|
1241
|
-
static getPatchedDir = () => path__default.join(CliParser.getSwaggersOutputPath(), "patched");
|
|
1242
|
-
static getGeneratedPublicFolder = () => `${CliParser.getOutputPath()}/generated-public`;
|
|
1243
|
-
static getGeneratedAdminFolder = () => `${CliParser.getOutputPath()}/generated-admin`;
|
|
1244
|
-
static getGeneratedSnippetsFolder = () => `${CliParser.getSnippetOutputPath()}/generated-snippets`;
|
|
1238
|
+
class SwaggerReaderHelpers {
|
|
1245
1239
|
static getServicePrefix = (servicePaths) => servicePaths[servicePaths.length - 1].split("/")[1];
|
|
1246
|
-
static
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
const
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1240
|
+
static parseAllEndpoints = async ({
|
|
1241
|
+
api,
|
|
1242
|
+
sdkName,
|
|
1243
|
+
serviceName
|
|
1244
|
+
}) => {
|
|
1245
|
+
const result = {
|
|
1246
|
+
admin: {
|
|
1247
|
+
arrayDefinitions: [],
|
|
1248
|
+
snippetMap: {},
|
|
1249
|
+
tagToClassImportsRecord: {},
|
|
1250
|
+
tagToEndpointClassesRecord: {},
|
|
1251
|
+
tagToSdkClientRecord: {},
|
|
1252
|
+
tagToSdkFunctionNamesRecord: {},
|
|
1253
|
+
tagToSdkImportsRecord: {}
|
|
1254
|
+
},
|
|
1255
|
+
public: {
|
|
1256
|
+
arrayDefinitions: [],
|
|
1257
|
+
snippetMap: {},
|
|
1258
|
+
tagToClassImportsRecord: {},
|
|
1259
|
+
tagToEndpointClassesRecord: {},
|
|
1260
|
+
tagToSdkClientRecord: {},
|
|
1261
|
+
tagToSdkFunctionNamesRecord: {},
|
|
1262
|
+
tagToSdkImportsRecord: {}
|
|
1263
|
+
}
|
|
1264
|
+
};
|
|
1255
1265
|
const sortedPathsByLength = new Map(Object.entries(api.paths).sort((a, b) => {
|
|
1256
1266
|
if (a[0].length === b[0].length) {
|
|
1257
1267
|
return a[0].localeCompare(b[0]);
|
|
@@ -1260,50 +1270,57 @@ class CodeGenerator {
|
|
|
1260
1270
|
}
|
|
1261
1271
|
}));
|
|
1262
1272
|
const sortedKeys = Array.from(sortedPathsByLength.keys());
|
|
1263
|
-
const servicePrefix =
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
} else if (path2.indexOf("/healthz") >= 0) {
|
|
1273
|
+
const servicePrefix = SwaggerReaderHelpers.getServicePrefix(sortedKeys);
|
|
1274
|
+
const tagToClassMethodsMap = {
|
|
1275
|
+
admin: {},
|
|
1276
|
+
public: {}
|
|
1277
|
+
};
|
|
1278
|
+
for (const [path, operation] of sortedPathsByLength) {
|
|
1279
|
+
if (path.indexOf("/healthz") >= 0) {
|
|
1271
1280
|
continue;
|
|
1272
1281
|
}
|
|
1282
|
+
const isAdminEndpoint = path.indexOf("/admin/") > -1;
|
|
1283
|
+
const picked = isAdminEndpoint ? result.admin : result.public;
|
|
1284
|
+
const {
|
|
1285
|
+
arrayDefinitions,
|
|
1286
|
+
snippetMap,
|
|
1287
|
+
tagToClassImportsRecord,
|
|
1288
|
+
tagToEndpointClassesRecord,
|
|
1289
|
+
tagToSdkClientRecord,
|
|
1290
|
+
tagToSdkFunctionNamesRecord,
|
|
1291
|
+
tagToSdkImportsRecord
|
|
1292
|
+
} = picked;
|
|
1293
|
+
const tagToClassMethodsMapByType = isAdminEndpoint ? tagToClassMethodsMap.admin : tagToClassMethodsMap.public;
|
|
1273
1294
|
const httpMethods = Object.keys(operation);
|
|
1274
1295
|
for (const httpMethod of httpMethods) {
|
|
1275
1296
|
const endpoint = await Endpoint.parseAsync(operation[httpMethod]).catch((error) => {
|
|
1276
|
-
console.error(JSON.stringify({ path
|
|
1297
|
+
console.error(JSON.stringify({ path, httpMethod }, null, 2));
|
|
1277
1298
|
throw error;
|
|
1278
1299
|
});
|
|
1279
|
-
if (!endpoint.tags)
|
|
1280
|
-
continue;
|
|
1281
|
-
}
|
|
1282
|
-
if (endpoint.deprecated) {
|
|
1300
|
+
if (!endpoint.tags || endpoint.deprecated)
|
|
1283
1301
|
continue;
|
|
1284
|
-
}
|
|
1285
1302
|
const [tag] = endpoint.tags;
|
|
1286
|
-
const pathWithBase = `${api.basePath ?? ""}${
|
|
1287
|
-
|
|
1303
|
+
const pathWithBase = `${api.basePath ?? ""}${path}`;
|
|
1304
|
+
tagToClassMethodsMapByType[tag] = tagToClassMethodsMapByType[tag] ? tagToClassMethodsMapByType[tag] : {};
|
|
1288
1305
|
const isForm = endpoint.consumes && endpoint.consumes[0] === "application/x-www-form-urlencoded";
|
|
1289
1306
|
const classMethod = ParserUtils.generateNaturalLangMethod({
|
|
1290
1307
|
servicePrefix,
|
|
1291
|
-
path
|
|
1308
|
+
path,
|
|
1292
1309
|
httpMethod,
|
|
1293
1310
|
isForm,
|
|
1294
|
-
existingMethods:
|
|
1311
|
+
existingMethods: tagToClassMethodsMapByType[tag]
|
|
1295
1312
|
});
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
description = description
|
|
1313
|
+
tagToClassMethodsMapByType[tag][classMethod] = `${path} ${httpMethod}`;
|
|
1314
|
+
if (!snippetMap[pathWithBase]) {
|
|
1315
|
+
snippetMap[pathWithBase] = {};
|
|
1316
|
+
}
|
|
1317
|
+
const description = endpoint.description?.replace(/\s+/g, " ") || "";
|
|
1301
1318
|
const responseClass = ParserUtils.get2xxResponse(endpoint.responses);
|
|
1302
|
-
const { className, classGenName } = ParserUtils.generateClassName(tag);
|
|
1303
|
-
|
|
1319
|
+
const { className, classGenName } = ParserUtils.generateClassName(tag, isAdminEndpoint);
|
|
1320
|
+
tagToClassImportsRecord[className] = tagToClassImportsRecord[className] ? tagToClassImportsRecord[className] : {};
|
|
1304
1321
|
if (responseClass) {
|
|
1305
1322
|
const importTypeClass = ParserUtils.parseRefType(responseClass);
|
|
1306
|
-
|
|
1323
|
+
tagToClassImportsRecord[className][importTypeClass] = `import { ${importTypeClass} } from '../definitions/${importTypeClass}.js'`;
|
|
1307
1324
|
}
|
|
1308
1325
|
if (responseClass && responseClass.endsWith("Array")) {
|
|
1309
1326
|
arrayDefinitions.push(responseClass);
|
|
@@ -1332,8 +1349,8 @@ class CodeGenerator {
|
|
|
1332
1349
|
isFormUrlEncoded,
|
|
1333
1350
|
responseClass
|
|
1334
1351
|
});
|
|
1335
|
-
|
|
1336
|
-
const [
|
|
1352
|
+
tagToEndpointClassesRecord[tag] = (tagToEndpointClassesRecord[tag] || "") + methodImpl;
|
|
1353
|
+
const [generatedMethodString, snippetMethod, snippetShell] = templateApiMethod({
|
|
1337
1354
|
classMethod,
|
|
1338
1355
|
description,
|
|
1339
1356
|
httpMethod,
|
|
@@ -1345,32 +1362,37 @@ class CodeGenerator {
|
|
|
1345
1362
|
methodParams,
|
|
1346
1363
|
methodParamsNoTypes
|
|
1347
1364
|
});
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1365
|
+
tagToSdkClientRecord[tag] = (tagToSdkClientRecord[tag] || "") + generatedMethodString;
|
|
1366
|
+
tagToSdkFunctionNamesRecord[tag] = (tagToSdkFunctionNamesRecord[tag] || "") + classMethod + ",";
|
|
1367
|
+
tagToSdkImportsRecord[tag] = tagToSdkImportsRecord[tag] ? [.../* @__PURE__ */ new Set([...importStatements, ...tagToSdkImportsRecord[tag]])] : [...new Set(importStatements)];
|
|
1351
1368
|
const serviceNameTitle = ParserUtils.convertDashesToTitleCase(serviceName);
|
|
1352
|
-
const { apiGenName } = ParserUtils.generateApiName(tag);
|
|
1369
|
+
const { apiGenName } = ParserUtils.generateApiName(tag, isAdminEndpoint);
|
|
1353
1370
|
const resultSnippet = templateSdkSnippet(serviceNameTitle, apiGenName, snippetMethod);
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1371
|
+
const currentSnippetMap = {};
|
|
1372
|
+
snippetMap[pathWithBase][httpMethod] = currentSnippetMap;
|
|
1373
|
+
if (!isAdminEndpoint) {
|
|
1374
|
+
currentSnippetMap.web = !isAdminEndpoint ? resultSnippet : "";
|
|
1375
|
+
currentSnippetMap.webGit = !isAdminEndpoint ? GIT_URL + `/sdk-${sdkName}/src/generated-public/${serviceName}/${apiGenName}.ts` : "";
|
|
1376
|
+
}
|
|
1377
|
+
currentSnippetMap.shell = snippetShell;
|
|
1359
1378
|
}
|
|
1360
1379
|
}
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
classBufferByTag,
|
|
1366
|
-
dependenciesByTag,
|
|
1367
|
-
classImports,
|
|
1368
|
-
arrayDefinitions,
|
|
1369
|
-
snippetMap
|
|
1370
|
-
};
|
|
1380
|
+
for (const key in result) {
|
|
1381
|
+
result[key].arrayDefinitions = Array.from(new Set(result[key].arrayDefinitions));
|
|
1382
|
+
}
|
|
1383
|
+
return result;
|
|
1371
1384
|
};
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
class CodeGenerator {
|
|
1388
|
+
static getPatchedDir = () => path__default.join(CliParser.getSwaggersOutputPath(), "patched");
|
|
1389
|
+
static getGeneratedPublicFolder = () => `${CliParser.getOutputPath()}/generated-public`;
|
|
1390
|
+
static getGeneratedAdminFolder = () => `${CliParser.getOutputPath()}/generated-admin`;
|
|
1391
|
+
static getGeneratedSnippetsFolder = () => `${CliParser.getSnippetOutputPath()}/generated-snippets`;
|
|
1392
|
+
static getServicePrefix = (servicePaths) => servicePaths[servicePaths.length - 1].split("/")[1];
|
|
1372
1393
|
static main = async (nameArray) => {
|
|
1373
1394
|
const serviceName = nameArray[0];
|
|
1395
|
+
const sdkName = nameArray[1];
|
|
1374
1396
|
const swaggerFile = nameArray[2];
|
|
1375
1397
|
const parser = new SwaggerParser();
|
|
1376
1398
|
const generatedFolder = CliParser.isAdmin() ? CodeGenerator.getGeneratedAdminFolder() : CodeGenerator.getGeneratedPublicFolder();
|
|
@@ -1386,26 +1408,38 @@ class CodeGenerator {
|
|
|
1386
1408
|
ParserUtils.mkdirIfNotExist(DIST_DEFINITION_DIR);
|
|
1387
1409
|
ParserUtils.mkdirIfNotExist(DIST_ENDPOINTS_DIR);
|
|
1388
1410
|
ParserUtils.syncPackageVersion(apiInfo, CliParser.skipVersionSync(), process.env.PRERELEASE_ID);
|
|
1389
|
-
const
|
|
1411
|
+
const parsedInformation = await SwaggerReaderHelpers.parseAllEndpoints({ api, sdkName, serviceName });
|
|
1412
|
+
const parsedInformationByType = CliParser.isAdmin() ? parsedInformation.admin : parsedInformation.public;
|
|
1413
|
+
const {
|
|
1414
|
+
arrayDefinitions,
|
|
1415
|
+
tagToClassImportsRecord,
|
|
1416
|
+
tagToEndpointClassesRecord,
|
|
1417
|
+
tagToSdkClientRecord,
|
|
1418
|
+
tagToSdkFunctionNamesRecord,
|
|
1419
|
+
tagToSdkImportsRecord
|
|
1420
|
+
} = parsedInformationByType;
|
|
1390
1421
|
if (CliParser.getSnippetOutputPath()) {
|
|
1391
1422
|
try {
|
|
1392
|
-
ParserUtils.writeSnippetFile(CodeGenerator.getGeneratedSnippetsFolder(), api.info.title, JSON.stringify(
|
|
1423
|
+
ParserUtils.writeSnippetFile(CodeGenerator.getGeneratedSnippetsFolder(), api.info.title, JSON.stringify({
|
|
1424
|
+
...parsedInformation.public.snippetMap,
|
|
1425
|
+
...parsedInformation.admin.snippetMap
|
|
1426
|
+
}, null, 2));
|
|
1393
1427
|
} catch (err) {
|
|
1394
1428
|
console.log("Generating snippets", err);
|
|
1395
1429
|
}
|
|
1396
1430
|
}
|
|
1397
1431
|
const targetSrcFolder = `${CliParser.getOutputPath()}/`;
|
|
1398
1432
|
const apiList = [];
|
|
1399
|
-
for (const tag in
|
|
1400
|
-
const { className, classGenName } = ParserUtils.generateClassName(tag);
|
|
1401
|
-
const classBuffer =
|
|
1402
|
-
const imports = [.../* @__PURE__ */ new Set([...
|
|
1403
|
-
const apiImports = [.../* @__PURE__ */ new Set([...
|
|
1433
|
+
for (const tag in tagToEndpointClassesRecord) {
|
|
1434
|
+
const { className, classGenName } = ParserUtils.generateClassName(tag, CliParser.isAdmin());
|
|
1435
|
+
const classBuffer = tagToEndpointClassesRecord[tag];
|
|
1436
|
+
const imports = [.../* @__PURE__ */ new Set([...tagToSdkImportsRecord[tag], ...Object.values(tagToClassImportsRecord[className])])];
|
|
1437
|
+
const apiImports = [.../* @__PURE__ */ new Set([...tagToSdkImportsRecord[tag], ...Object.values(tagToClassImportsRecord[className])])];
|
|
1404
1438
|
apiImports.push(`import { ${classGenName} } from './endpoints/${classGenName}.js'`);
|
|
1405
1439
|
ParserUtils.writeClassFile(DIST_ENDPOINTS_DIR, classGenName, classBuffer, imports);
|
|
1406
|
-
const apiBuffer =
|
|
1407
|
-
const { apiGenName } = ParserUtils.generateApiName(tag);
|
|
1408
|
-
ParserUtils.writeApiFile(DIST_DIR, apiGenName, apiBuffer, apiImports,
|
|
1440
|
+
const apiBuffer = tagToSdkClientRecord[tag];
|
|
1441
|
+
const { apiGenName } = ParserUtils.generateApiName(tag, CliParser.isAdmin());
|
|
1442
|
+
ParserUtils.writeApiFile(DIST_DIR, apiGenName, apiBuffer, apiImports, tagToSdkFunctionNamesRecord[tag]);
|
|
1409
1443
|
apiList.push(apiGenName);
|
|
1410
1444
|
indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path__default.join(DIST_ENDPOINTS_DIR, `${classGenName}`), targetSrcFolder));
|
|
1411
1445
|
indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path__default.join(DIST_DIR, `${apiGenName}`), targetSrcFolder));
|