@accelbyte/codegen 2.0.0-beta.4 → 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 +332 -296
- package/dist/accelbyte-codegen.js.map +1 -1
- package/dist/accelbyte-codegen.mjs +332 -296
- 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) => {
|
|
@@ -662,205 +662,6 @@ const isSwaggerIntegerType = (type) => {
|
|
|
662
662
|
return type === "integer" || type === "int";
|
|
663
663
|
};
|
|
664
664
|
|
|
665
|
-
const Schema = z.object({
|
|
666
|
-
$ref: z.string().nullish(),
|
|
667
|
-
type: z.union([z.literal("array"), z.literal("object"), z.literal("file"), z.literal("string"), z.literal("boolean"), z.literal("integer")]).nullish(),
|
|
668
|
-
items: z.object({
|
|
669
|
-
$ref: z.string().nullish(),
|
|
670
|
-
type: z.string().nullish()
|
|
671
|
-
}).nullish(),
|
|
672
|
-
properties: z.union([z.array(z.string()).nullish(), z.record(z.object({ type: z.string() })).nullish()]),
|
|
673
|
-
description: z.string().nullish(),
|
|
674
|
-
additionalProperties: z.object({
|
|
675
|
-
type: z.string().nullish()
|
|
676
|
-
}).nullish()
|
|
677
|
-
});
|
|
678
|
-
const Definition = z.object({
|
|
679
|
-
required: z.array(z.string()).nullish(),
|
|
680
|
-
properties: z.record(z.object({
|
|
681
|
-
type: z.string()
|
|
682
|
-
})).nullish()
|
|
683
|
-
});
|
|
684
|
-
const Definitions = z.record(Definition);
|
|
685
|
-
const EndpointParametersType = z.enum(["apiKey", "boolean", "int", "integer", "number", "string", "array", "file"]);
|
|
686
|
-
const EndpointParametersIn = z.enum(["body", "formData", "header", "path", "query"]);
|
|
687
|
-
const EndpointParameters = z.object({
|
|
688
|
-
type: EndpointParametersType.nullish(),
|
|
689
|
-
description: z.string().nullish(),
|
|
690
|
-
name: z.string(),
|
|
691
|
-
in: EndpointParametersIn,
|
|
692
|
-
required: z.boolean().nullish(),
|
|
693
|
-
schema: Schema.nullish(),
|
|
694
|
-
default: z.union([z.boolean(), z.string(), z.number(), z.array(z.any())]).nullish(),
|
|
695
|
-
enum: z.array(z.union([z.boolean(), z.string(), z.number()])).nullish(),
|
|
696
|
-
items: z.object({
|
|
697
|
-
type: z.string(),
|
|
698
|
-
enum: z.array(z.any()).nullish()
|
|
699
|
-
}).nullish()
|
|
700
|
-
});
|
|
701
|
-
const Endpoint = z.object({
|
|
702
|
-
description: z.string().nullish(),
|
|
703
|
-
consumes: z.array(z.string()).nullish(),
|
|
704
|
-
produces: z.array(z.string()).nullish(),
|
|
705
|
-
tags: z.array(z.string()).nullish(),
|
|
706
|
-
summary: z.string().nullish(),
|
|
707
|
-
operationId: z.string(),
|
|
708
|
-
deprecated: z.boolean().nullish(),
|
|
709
|
-
responses: z.record(z.object({
|
|
710
|
-
description: z.string().nullish(),
|
|
711
|
-
schema: Schema.nullish(),
|
|
712
|
-
content: z.object({
|
|
713
|
-
"application/json": z.object({
|
|
714
|
-
schema: Schema.nullish()
|
|
715
|
-
})
|
|
716
|
-
}).nullish()
|
|
717
|
-
})),
|
|
718
|
-
parameters: z.array(EndpointParameters).nullish(),
|
|
719
|
-
requestBody: z.object({
|
|
720
|
-
required: z.boolean(),
|
|
721
|
-
content: z.object({
|
|
722
|
-
"application/json": z.object({
|
|
723
|
-
schema: Schema.nullish()
|
|
724
|
-
})
|
|
725
|
-
}).nullish()
|
|
726
|
-
}).nullish()
|
|
727
|
-
});
|
|
728
|
-
const Operation = z.object({
|
|
729
|
-
get: Endpoint.nullish(),
|
|
730
|
-
post: Endpoint.nullish(),
|
|
731
|
-
patch: Endpoint.nullish(),
|
|
732
|
-
delete: Endpoint.nullish(),
|
|
733
|
-
put: Endpoint.nullish()
|
|
734
|
-
});
|
|
735
|
-
const Paths = z.record(Operation);
|
|
736
|
-
z.object({
|
|
737
|
-
paths: Paths,
|
|
738
|
-
definitions: Definitions,
|
|
739
|
-
basePath: z.string(),
|
|
740
|
-
info: z.object({
|
|
741
|
-
description: z.string(),
|
|
742
|
-
title: z.string(),
|
|
743
|
-
contact: z.object({
|
|
744
|
-
name: z.string(),
|
|
745
|
-
url: z.string(),
|
|
746
|
-
email: z.string()
|
|
747
|
-
}),
|
|
748
|
-
version: z.string()
|
|
749
|
-
}),
|
|
750
|
-
schemes: z.array(z.string()).nullish(),
|
|
751
|
-
components: z.object({
|
|
752
|
-
schemas: Definitions
|
|
753
|
-
}).nullish()
|
|
754
|
-
});
|
|
755
|
-
|
|
756
|
-
const templateMethod = ({
|
|
757
|
-
classMethod,
|
|
758
|
-
description,
|
|
759
|
-
httpMethod,
|
|
760
|
-
path,
|
|
761
|
-
pathParams,
|
|
762
|
-
bodyParams,
|
|
763
|
-
queryParams,
|
|
764
|
-
isFormUrlEncoded,
|
|
765
|
-
responseClass
|
|
766
|
-
}) => {
|
|
767
|
-
let methodParams = "";
|
|
768
|
-
let methodParamsNoTypes = "";
|
|
769
|
-
let newPath = `'${path}'`;
|
|
770
|
-
let importStatements = [];
|
|
771
|
-
const sortedPathParams = ParserUtils.sortPathParamsByPath(pathParams, path);
|
|
772
|
-
for (const pathParam of sortedPathParams) {
|
|
773
|
-
const type = ParserUtils.parseType(pathParam);
|
|
774
|
-
if (pathParam.name !== "namespace") {
|
|
775
|
-
methodParams += pathParam.name + `:${type}, `;
|
|
776
|
-
methodParamsNoTypes += pathParam.name + ", ";
|
|
777
|
-
}
|
|
778
|
-
const pName = pathParam.name === "namespace" ? "this.namespace" : pathParam.name;
|
|
779
|
-
if (path.match(`{${pathParam.name}}`)) {
|
|
780
|
-
if (type === "string") {
|
|
781
|
-
newPath = `${newPath}.replace('{${pathParam.name}}', ${pName})`;
|
|
782
|
-
} else {
|
|
783
|
-
newPath = `${newPath}.replace('{${pathParam.name}}', String(${pName}))`;
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
let dataType = null;
|
|
788
|
-
if (httpMethod !== "get") {
|
|
789
|
-
dataType = ParserUtils.parseBodyParamsType(bodyParams);
|
|
790
|
-
importStatements = ParserUtils.parseBodyParamsImports(bodyParams);
|
|
791
|
-
methodParams += dataType ? `data: ${dataType},` : "";
|
|
792
|
-
methodParamsNoTypes += dataType ? `data,` : "";
|
|
793
|
-
}
|
|
794
|
-
const isAnyRequired = ParserUtils.isAnyQueryParamRequired(queryParams);
|
|
795
|
-
const queryParamsType = queryParams.length ? `queryParams${isAnyRequired ? "" : "?"}: {${ParserUtils.parseQueryParamsType(queryParams)}}` : "";
|
|
796
|
-
const queryParamsDefault = queryParams.length ? `const params = {${ParserUtils.parseQueryParamsDefault(queryParams)} ...queryParams} as SDKRequestConfig` : "const params = {} as SDKRequestConfig";
|
|
797
|
-
const isPostPutPatch = ["post", "put", "patch"].includes(httpMethod);
|
|
798
|
-
const isDelete = ["delete"].includes(httpMethod);
|
|
799
|
-
let dataPayload = "{params}";
|
|
800
|
-
const descriptionText = description ? `
|
|
801
|
-
/**
|
|
802
|
-
* ${description.replace(/\n/g, "\n * ")}
|
|
803
|
-
*/` : "";
|
|
804
|
-
let formPayloadString = "";
|
|
805
|
-
if (isFormUrlEncoded) {
|
|
806
|
-
formPayloadString = ``;
|
|
807
|
-
const params = "{ ...params, headers: { ...params.headers, 'content-type': 'application/x-www-form-urlencoded' } }";
|
|
808
|
-
dataPayload = dataType ? `CodeGenUtil.getFormUrlEncodedData(data), ${params}` : `null, ${params}`;
|
|
809
|
-
} else if (isPostPutPatch) {
|
|
810
|
-
dataPayload = dataType ? `data, {params}` : "null, {params}";
|
|
811
|
-
} else if (isDelete) {
|
|
812
|
-
dataPayload = dataType ? `{data, params}` : "{params}";
|
|
813
|
-
}
|
|
814
|
-
const isFileUpload = methodParams.indexOf("data: {file") > -1;
|
|
815
|
-
const resolvedResponseClass = responseClass || "unknown";
|
|
816
|
-
const resolvedResponseClassValidated = responseClass || "z.unknown()";
|
|
817
|
-
methodParams = (queryParamsType ? `${methodParams} ${queryParamsType}` : methodParams).replace(/,\s*$/, "");
|
|
818
|
-
methodParamsNoTypes = queryParamsType ? `${methodParamsNoTypes} queryParams` : methodParamsNoTypes;
|
|
819
|
-
let methodImpl = "";
|
|
820
|
-
const isCacheFetch = ["get"].includes(httpMethod) && resolvedResponseClass !== "unknown";
|
|
821
|
-
const cachedFetchMethod = classMethod;
|
|
822
|
-
const deprecateTag = isCacheFetch ? `/**
|
|
823
|
-
* @deprecated Use "${classMethod}()" instead.
|
|
824
|
-
*/` : "";
|
|
825
|
-
const isGuardInvoked = ["get", "post", "put", "patch", "delete"].includes(httpMethod);
|
|
826
|
-
const methodName = httpMethod === "get" ? cachedFetchMethod : ["post", "put", "patch", "delete"].includes(httpMethod) ? classMethod : "";
|
|
827
|
-
const responseType = resolvedResponseClass !== "unknown" ? `${resolvedResponseClass}` : "unknown";
|
|
828
|
-
const generateMethodName = () => `${methodName}(${methodParams}): Promise<${responseSyncType}<${responseType}>>`;
|
|
829
|
-
const responseSyncType = httpMethod === "get" ? "IResponseWithSync" : ["post", "put", "patch", "delete"].includes(httpMethod) ? "IResponse" : "";
|
|
830
|
-
methodImpl = `${descriptionText}
|
|
831
|
-
${generateMethodName()} {
|
|
832
|
-
${queryParamsDefault}
|
|
833
|
-
const url = ${newPath} ${formPayloadString} ${isFileUpload ? "\n// TODO file upload not implemented" : ""}
|
|
834
|
-
const resultPromise = this.axiosInstance.${httpMethod}(url, ${dataPayload})
|
|
835
|
-
|
|
836
|
-
${httpMethod === "get" ? ` const res = () => Validate.responseType(() => resultPromise, ${resolvedResponseClassValidated}, '${resolvedResponseClassValidated}')
|
|
837
|
-
|
|
838
|
-
if (!this.cache) {
|
|
839
|
-
return SdkCache.withoutCache(res)
|
|
840
|
-
}
|
|
841
|
-
const cacheKey = url + CodeGenUtil.hashCode(JSON.stringify({ params }))
|
|
842
|
-
return SdkCache.withCache(cacheKey, res)` : ""}${["post", "put", "patch", "delete"].includes(httpMethod) ? ` return Validate.responseType(() => resultPromise, ${resolvedResponseClassValidated}, '${resolvedResponseClassValidated}')` : ""}
|
|
843
|
-
}
|
|
844
|
-
`;
|
|
845
|
-
if (!isGuardInvoked) {
|
|
846
|
-
methodImpl = `${descriptionText}
|
|
847
|
-
${deprecateTag}
|
|
848
|
-
TODO_${classMethod}(${methodParams}): Promise<AxiosResponse<${resolvedResponseClass}>> {
|
|
849
|
-
${queryParamsDefault}
|
|
850
|
-
const url = ${newPath} ${formPayloadString} ${isFileUpload ? "\n// TODO file upload not implemented" : ""}
|
|
851
|
-
return this.axiosInstance.${httpMethod}(url, ${dataPayload})
|
|
852
|
-
}
|
|
853
|
-
`;
|
|
854
|
-
}
|
|
855
|
-
const res = {
|
|
856
|
-
methodImpl,
|
|
857
|
-
methodParams,
|
|
858
|
-
methodParamsNoTypes,
|
|
859
|
-
importStatements
|
|
860
|
-
};
|
|
861
|
-
return res;
|
|
862
|
-
};
|
|
863
|
-
|
|
864
665
|
class TemplateZod {
|
|
865
666
|
duplicates;
|
|
866
667
|
duplicateFound = false;
|
|
@@ -1113,6 +914,227 @@ const extractEnumObject = (type, isRequired, enumArr) => {
|
|
|
1113
914
|
};
|
|
1114
915
|
};
|
|
1115
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
|
+
|
|
1116
1138
|
const templateApiMethod = ({
|
|
1117
1139
|
classMethod,
|
|
1118
1140
|
description,
|
|
@@ -1174,28 +1196,6 @@ const templateApiMethod = ({
|
|
|
1174
1196
|
return [methodImpl, snippetSdk, snippetShell];
|
|
1175
1197
|
};
|
|
1176
1198
|
|
|
1177
|
-
const templateApiIndex = (serviceName, serviceNameTitle, apiList) => {
|
|
1178
|
-
let imports = "";
|
|
1179
|
-
let returnStatement = "";
|
|
1180
|
-
for (const cl of apiList) {
|
|
1181
|
-
imports += `
|
|
1182
|
-
import { ${cl} } from './${serviceName}/${cl}.js'`;
|
|
1183
|
-
returnStatement += `
|
|
1184
|
-
${cl}, `;
|
|
1185
|
-
}
|
|
1186
|
-
return `/**
|
|
1187
|
-
* AUTO GENERATED
|
|
1188
|
-
*/
|
|
1189
|
-
${imports}
|
|
1190
|
-
|
|
1191
|
-
const apis = {
|
|
1192
|
-
${returnStatement}
|
|
1193
|
-
}
|
|
1194
|
-
|
|
1195
|
-
export const ${ParserUtils.convertDashesToTitleCase(serviceNameTitle)} = apis
|
|
1196
|
-
`;
|
|
1197
|
-
};
|
|
1198
|
-
|
|
1199
1199
|
const templateSdkSnippet = (serviceNameTitle, apiName, methodSnippet) => {
|
|
1200
1200
|
const methodArr = methodSnippet.split("//");
|
|
1201
1201
|
let normMethod = normalizeMethodSnippet(methodArr[0].trim(), "data:");
|
|
@@ -1235,21 +1235,33 @@ const normalizeMethodSnippet = (methodInput, splitWord) => {
|
|
|
1235
1235
|
};
|
|
1236
1236
|
|
|
1237
1237
|
const GIT_URL = "https://github.com/AccelByte/accelbyte-web-sdk/blob/main/packages";
|
|
1238
|
-
class
|
|
1239
|
-
static getPatchedDir = () => path__default.join(CliParser.getSwaggersOutputPath(), "patched");
|
|
1240
|
-
static getGeneratedPublicFolder = () => `${CliParser.getOutputPath()}/generated-public`;
|
|
1241
|
-
static getGeneratedAdminFolder = () => `${CliParser.getOutputPath()}/generated-admin`;
|
|
1242
|
-
static getGeneratedSnippetsFolder = () => `${CliParser.getSnippetOutputPath()}/generated-snippets`;
|
|
1238
|
+
class SwaggerReaderHelpers {
|
|
1243
1239
|
static getServicePrefix = (servicePaths) => servicePaths[servicePaths.length - 1].split("/")[1];
|
|
1244
|
-
static
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
const
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
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
|
+
};
|
|
1253
1265
|
const sortedPathsByLength = new Map(Object.entries(api.paths).sort((a, b) => {
|
|
1254
1266
|
if (a[0].length === b[0].length) {
|
|
1255
1267
|
return a[0].localeCompare(b[0]);
|
|
@@ -1258,55 +1270,62 @@ class CodeGenerator {
|
|
|
1258
1270
|
}
|
|
1259
1271
|
}));
|
|
1260
1272
|
const sortedKeys = Array.from(sortedPathsByLength.keys());
|
|
1261
|
-
const servicePrefix =
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
} 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) {
|
|
1269
1280
|
continue;
|
|
1270
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;
|
|
1271
1294
|
const httpMethods = Object.keys(operation);
|
|
1272
1295
|
for (const httpMethod of httpMethods) {
|
|
1273
1296
|
const endpoint = await Endpoint.parseAsync(operation[httpMethod]).catch((error) => {
|
|
1274
|
-
console.error(JSON.stringify({ path
|
|
1297
|
+
console.error(JSON.stringify({ path, httpMethod }, null, 2));
|
|
1275
1298
|
throw error;
|
|
1276
1299
|
});
|
|
1277
|
-
if (!endpoint.tags)
|
|
1278
|
-
continue;
|
|
1279
|
-
}
|
|
1280
|
-
if (endpoint.deprecated) {
|
|
1300
|
+
if (!endpoint.tags || endpoint.deprecated)
|
|
1281
1301
|
continue;
|
|
1282
|
-
}
|
|
1283
1302
|
const [tag] = endpoint.tags;
|
|
1284
|
-
|
|
1303
|
+
const pathWithBase = `${api.basePath ?? ""}${path}`;
|
|
1304
|
+
tagToClassMethodsMapByType[tag] = tagToClassMethodsMapByType[tag] ? tagToClassMethodsMapByType[tag] : {};
|
|
1285
1305
|
const isForm = endpoint.consumes && endpoint.consumes[0] === "application/x-www-form-urlencoded";
|
|
1286
1306
|
const classMethod = ParserUtils.generateNaturalLangMethod({
|
|
1287
1307
|
servicePrefix,
|
|
1288
|
-
path
|
|
1308
|
+
path,
|
|
1289
1309
|
httpMethod,
|
|
1290
1310
|
isForm,
|
|
1291
|
-
existingMethods:
|
|
1311
|
+
existingMethods: tagToClassMethodsMapByType[tag]
|
|
1292
1312
|
});
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
description = description
|
|
1313
|
+
tagToClassMethodsMapByType[tag][classMethod] = `${path} ${httpMethod}`;
|
|
1314
|
+
if (!snippetMap[pathWithBase]) {
|
|
1315
|
+
snippetMap[pathWithBase] = {};
|
|
1316
|
+
}
|
|
1317
|
+
const description = endpoint.description?.replace(/\s+/g, " ") || "";
|
|
1298
1318
|
const responseClass = ParserUtils.get2xxResponse(endpoint.responses);
|
|
1299
|
-
const { className, classGenName } = ParserUtils.generateClassName(tag);
|
|
1300
|
-
|
|
1319
|
+
const { className, classGenName } = ParserUtils.generateClassName(tag, isAdminEndpoint);
|
|
1320
|
+
tagToClassImportsRecord[className] = tagToClassImportsRecord[className] ? tagToClassImportsRecord[className] : {};
|
|
1301
1321
|
if (responseClass) {
|
|
1302
1322
|
const importTypeClass = ParserUtils.parseRefType(responseClass);
|
|
1303
|
-
|
|
1323
|
+
tagToClassImportsRecord[className][importTypeClass] = `import { ${importTypeClass} } from '../definitions/${importTypeClass}.js'`;
|
|
1304
1324
|
}
|
|
1305
1325
|
if (responseClass && responseClass.endsWith("Array")) {
|
|
1306
1326
|
arrayDefinitions.push(responseClass);
|
|
1307
1327
|
}
|
|
1308
1328
|
const queryParams = ParserUtils.filterQueryParameters(endpoint.parameters);
|
|
1309
|
-
const pathWithBase = `${api.basePath ?? ""}${path2}`;
|
|
1310
1329
|
const isFormUrlEncoded = ParserUtils.isFormUrlEncoded(httpMethod, endpoint.consumes);
|
|
1311
1330
|
const pathParams = ParserUtils.filterPathParams(endpoint.parameters);
|
|
1312
1331
|
let bodyParams = ParserUtils.filterBodyParams(endpoint.parameters);
|
|
@@ -1330,8 +1349,8 @@ class CodeGenerator {
|
|
|
1330
1349
|
isFormUrlEncoded,
|
|
1331
1350
|
responseClass
|
|
1332
1351
|
});
|
|
1333
|
-
|
|
1334
|
-
const [
|
|
1352
|
+
tagToEndpointClassesRecord[tag] = (tagToEndpointClassesRecord[tag] || "") + methodImpl;
|
|
1353
|
+
const [generatedMethodString, snippetMethod, snippetShell] = templateApiMethod({
|
|
1335
1354
|
classMethod,
|
|
1336
1355
|
description,
|
|
1337
1356
|
httpMethod,
|
|
@@ -1343,32 +1362,37 @@ class CodeGenerator {
|
|
|
1343
1362
|
methodParams,
|
|
1344
1363
|
methodParamsNoTypes
|
|
1345
1364
|
});
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
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)];
|
|
1349
1368
|
const serviceNameTitle = ParserUtils.convertDashesToTitleCase(serviceName);
|
|
1350
|
-
const { apiGenName } = ParserUtils.generateApiName(tag);
|
|
1369
|
+
const { apiGenName } = ParserUtils.generateApiName(tag, isAdminEndpoint);
|
|
1351
1370
|
const resultSnippet = templateSdkSnippet(serviceNameTitle, apiGenName, snippetMethod);
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
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;
|
|
1357
1378
|
}
|
|
1358
1379
|
}
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
classBufferByTag,
|
|
1364
|
-
dependenciesByTag,
|
|
1365
|
-
classImports,
|
|
1366
|
-
arrayDefinitions,
|
|
1367
|
-
snippetMap
|
|
1368
|
-
};
|
|
1380
|
+
for (const key in result) {
|
|
1381
|
+
result[key].arrayDefinitions = Array.from(new Set(result[key].arrayDefinitions));
|
|
1382
|
+
}
|
|
1383
|
+
return result;
|
|
1369
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];
|
|
1370
1393
|
static main = async (nameArray) => {
|
|
1371
1394
|
const serviceName = nameArray[0];
|
|
1395
|
+
const sdkName = nameArray[1];
|
|
1372
1396
|
const swaggerFile = nameArray[2];
|
|
1373
1397
|
const parser = new SwaggerParser();
|
|
1374
1398
|
const generatedFolder = CliParser.isAdmin() ? CodeGenerator.getGeneratedAdminFolder() : CodeGenerator.getGeneratedPublicFolder();
|
|
@@ -1384,26 +1408,38 @@ class CodeGenerator {
|
|
|
1384
1408
|
ParserUtils.mkdirIfNotExist(DIST_DEFINITION_DIR);
|
|
1385
1409
|
ParserUtils.mkdirIfNotExist(DIST_ENDPOINTS_DIR);
|
|
1386
1410
|
ParserUtils.syncPackageVersion(apiInfo, CliParser.skipVersionSync(), process.env.PRERELEASE_ID);
|
|
1387
|
-
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;
|
|
1388
1421
|
if (CliParser.getSnippetOutputPath()) {
|
|
1389
1422
|
try {
|
|
1390
|
-
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));
|
|
1391
1427
|
} catch (err) {
|
|
1392
1428
|
console.log("Generating snippets", err);
|
|
1393
1429
|
}
|
|
1394
1430
|
}
|
|
1395
1431
|
const targetSrcFolder = `${CliParser.getOutputPath()}/`;
|
|
1396
1432
|
const apiList = [];
|
|
1397
|
-
for (const tag in
|
|
1398
|
-
const { className, classGenName } = ParserUtils.generateClassName(tag);
|
|
1399
|
-
const classBuffer =
|
|
1400
|
-
const imports = [.../* @__PURE__ */ new Set([...
|
|
1401
|
-
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])])];
|
|
1402
1438
|
apiImports.push(`import { ${classGenName} } from './endpoints/${classGenName}.js'`);
|
|
1403
1439
|
ParserUtils.writeClassFile(DIST_ENDPOINTS_DIR, classGenName, classBuffer, imports);
|
|
1404
|
-
const apiBuffer =
|
|
1405
|
-
const { apiGenName } = ParserUtils.generateApiName(tag);
|
|
1406
|
-
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]);
|
|
1407
1443
|
apiList.push(apiGenName);
|
|
1408
1444
|
indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path__default.join(DIST_ENDPOINTS_DIR, `${classGenName}`), targetSrcFolder));
|
|
1409
1445
|
indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path__default.join(DIST_DIR, `${apiGenName}`), targetSrcFolder));
|