@accelbyte/codegen 4.0.2 → 4.1.0
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/README.md +10 -8
- package/dist/accelbyte-codegen.js +414 -50
- package/dist/accelbyte-codegen.js.map +1 -1
- package/dist/accelbyte-codegen.mjs +414 -50
- package/dist/accelbyte-codegen.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
+
import path7 from "path";
|
|
4
5
|
import yargs from "yargs";
|
|
5
|
-
import path6 from "path";
|
|
6
6
|
|
|
7
7
|
// src/CliParser.ts
|
|
8
8
|
import fs from "fs";
|
|
@@ -55,6 +55,12 @@ var CliParser = class _CliParser {
|
|
|
55
55
|
static isGenerateSnippetOnly = () => {
|
|
56
56
|
return _CliParser.instance().argv.snippetOnly;
|
|
57
57
|
};
|
|
58
|
+
static getWebSocketSchemaPath = () => {
|
|
59
|
+
return _CliParser.instance().argv.webSocketSchema;
|
|
60
|
+
};
|
|
61
|
+
static isGenerateWebSocket = () => {
|
|
62
|
+
return !!_CliParser.getWebSocketSchemaPath();
|
|
63
|
+
};
|
|
58
64
|
};
|
|
59
65
|
|
|
60
66
|
// src/CodeGenerator.ts
|
|
@@ -301,15 +307,15 @@ export enum Key_${classNameWithoutApi} {
|
|
|
301
307
|
`;
|
|
302
308
|
};
|
|
303
309
|
function filterUsedImports(importArr, body) {
|
|
304
|
-
return importArr.filter((
|
|
305
|
-
const start =
|
|
306
|
-
const end =
|
|
310
|
+
return importArr.filter((path8) => {
|
|
311
|
+
const start = path8.indexOf("{") + 1;
|
|
312
|
+
const end = path8.indexOf("}");
|
|
307
313
|
if (start > 0 && end > start) {
|
|
308
|
-
const importName =
|
|
314
|
+
const importName = path8.slice(start, end).trim();
|
|
309
315
|
return body.includes(importName);
|
|
310
316
|
}
|
|
311
317
|
return false;
|
|
312
|
-
}).map((
|
|
318
|
+
}).map((path8) => path8).join("\n") + "\n";
|
|
313
319
|
}
|
|
314
320
|
|
|
315
321
|
// src/ParserUtils.ts
|
|
@@ -326,8 +332,8 @@ var REMOVED_KEYWORDS = [
|
|
|
326
332
|
"/{namespace}/"
|
|
327
333
|
];
|
|
328
334
|
var ParserUtils = class _ParserUtils {
|
|
329
|
-
static getVersionSuffixFromPath(
|
|
330
|
-
const version2_3_4_etc =
|
|
335
|
+
static getVersionSuffixFromPath(path8) {
|
|
336
|
+
const version2_3_4_etc = path8.match(/\/v([2-9]|[1-9]\d+)\/+/);
|
|
331
337
|
const methodSuffix = version2_3_4_etc ? `_v${version2_3_4_etc[1]}` : "";
|
|
332
338
|
return methodSuffix;
|
|
333
339
|
}
|
|
@@ -522,14 +528,14 @@ var ParserUtils = class _ParserUtils {
|
|
|
522
528
|
* to this
|
|
523
529
|
* `createGenerateByRequestIdByUserId`
|
|
524
530
|
*/
|
|
525
|
-
static generateNaturalLangMethod = ({ servicePrefix, path:
|
|
526
|
-
let path_ =
|
|
531
|
+
static generateNaturalLangMethod = ({ servicePrefix, path: path8, httpMethod, isForm, existingMethods, permissionType }) => {
|
|
532
|
+
let path_ = path8;
|
|
527
533
|
path_ = path_.replace(`/${servicePrefix}/`, "/");
|
|
528
534
|
REMOVED_KEYWORDS.forEach((prefix) => {
|
|
529
535
|
path_ = path_.replace(prefix, "/");
|
|
530
536
|
});
|
|
531
537
|
path_ = path_.substring(1);
|
|
532
|
-
const isPlural = httpMethod === "get" && !(
|
|
538
|
+
const isPlural = httpMethod === "get" && !(path8.slice(-1) === "}");
|
|
533
539
|
if (!isPlural) {
|
|
534
540
|
path_ = _ParserUtils.replaceAll(path_, "ies/", "y/");
|
|
535
541
|
path_ = _ParserUtils.replaceAll(path_, "s/", "/");
|
|
@@ -572,9 +578,9 @@ var ParserUtils = class _ParserUtils {
|
|
|
572
578
|
const genPath = _.upperFirst(lastWords) + "/" + listBeforeLastWords.join("/") + listByParams.reverse().join("/");
|
|
573
579
|
let generatedMethod = _.camelCase(mappedMethod(httpMethod, isForm, permissionType) + genPath);
|
|
574
580
|
generatedMethod = _ParserUtils.replaceAll(generatedMethod, "Byword", "_By");
|
|
575
|
-
const testedGeneratedMethod = generatedMethod + _ParserUtils.getVersionSuffixFromPath(
|
|
576
|
-
generatedMethod = resolveConflicts({ path:
|
|
577
|
-
generatedMethod = generatedMethod + _ParserUtils.getVersionSuffixFromPath(
|
|
581
|
+
const testedGeneratedMethod = generatedMethod + _ParserUtils.getVersionSuffixFromPath(path8);
|
|
582
|
+
generatedMethod = resolveConflicts({ path: path8, generatedMethod, testedGeneratedMethod, existingMethods });
|
|
583
|
+
generatedMethod = generatedMethod + _ParserUtils.getVersionSuffixFromPath(path8);
|
|
578
584
|
return generatedMethod;
|
|
579
585
|
};
|
|
580
586
|
static filterBodyParams(parameters) {
|
|
@@ -729,8 +735,8 @@ var ParserUtils = class _ParserUtils {
|
|
|
729
735
|
*/
|
|
730
736
|
${content}`;
|
|
731
737
|
};
|
|
732
|
-
static sortPathParamsByPath = (pathParams,
|
|
733
|
-
const params =
|
|
738
|
+
static sortPathParamsByPath = (pathParams, path8) => {
|
|
739
|
+
const params = path8.match(/{\w*}/g) || [];
|
|
734
740
|
const cleanParams = params.map((param) => param.replace("{", "").replace("}", ""));
|
|
735
741
|
return pathParams.sort((a, b) => cleanParams.indexOf(a.name) - cleanParams.indexOf(b.name));
|
|
736
742
|
};
|
|
@@ -754,30 +760,30 @@ var mappedMethod = (httpMethod, isForm, permissionType) => {
|
|
|
754
760
|
return "delete";
|
|
755
761
|
}
|
|
756
762
|
};
|
|
757
|
-
var resolveConflicts = ({ path:
|
|
763
|
+
var resolveConflicts = ({ path: path8, generatedMethod, testedGeneratedMethod, existingMethods }) => {
|
|
758
764
|
let _testedGenMethod = testedGeneratedMethod;
|
|
759
765
|
try {
|
|
760
|
-
testConflict(
|
|
766
|
+
testConflict(path8, _testedGenMethod, existingMethods);
|
|
761
767
|
} catch (e) {
|
|
762
|
-
if (
|
|
768
|
+
if (path8.indexOf("/namespaces/") >= 0) {
|
|
763
769
|
generatedMethod += "_ByNS";
|
|
764
770
|
_testedGenMethod += "_ByNS";
|
|
765
771
|
}
|
|
766
772
|
}
|
|
767
773
|
try {
|
|
768
|
-
testConflict(
|
|
774
|
+
testConflict(path8, _testedGenMethod, existingMethods);
|
|
769
775
|
} catch (e) {
|
|
770
|
-
if (
|
|
776
|
+
if (path8.indexOf("/admin/") >= 0) {
|
|
771
777
|
generatedMethod += "_admin";
|
|
772
778
|
_testedGenMethod += "_admin";
|
|
773
779
|
}
|
|
774
780
|
}
|
|
775
|
-
testConflict(
|
|
781
|
+
testConflict(path8, _testedGenMethod, existingMethods);
|
|
776
782
|
return generatedMethod;
|
|
777
783
|
};
|
|
778
|
-
var testConflict = (
|
|
784
|
+
var testConflict = (path8, generatedMethod, existingMethods) => {
|
|
779
785
|
if (existingMethods[generatedMethod]) {
|
|
780
|
-
const conflictingMethod = { path:
|
|
786
|
+
const conflictingMethod = { path: path8, generatedMethod };
|
|
781
787
|
throw Error(
|
|
782
788
|
`Duplicate method conflict in ${JSON.stringify(conflictingMethod)},
|
|
783
789
|
existingMethods: ${JSON.stringify(existingMethods, null, 2)}`
|
|
@@ -894,7 +900,7 @@ var OpenApiSpec = z2.object({
|
|
|
894
900
|
var templateApiMethod = ({
|
|
895
901
|
classMethod,
|
|
896
902
|
httpMethod,
|
|
897
|
-
path:
|
|
903
|
+
path: path8,
|
|
898
904
|
pathParams,
|
|
899
905
|
bodyParams,
|
|
900
906
|
responseClasses,
|
|
@@ -903,12 +909,12 @@ var templateApiMethod = ({
|
|
|
903
909
|
methodParamsNoTypes,
|
|
904
910
|
xSecurity
|
|
905
911
|
}) => {
|
|
906
|
-
let newPath = `'${
|
|
912
|
+
let newPath = `'${path8}'`;
|
|
907
913
|
let snippetMethod = "";
|
|
908
914
|
for (const pathParam of pathParams) {
|
|
909
915
|
const type = ParserUtils.parseType(pathParam);
|
|
910
916
|
const pName = pathParam.name === "namespace" ? "this.namespace" : pathParam.name;
|
|
911
|
-
if (
|
|
917
|
+
if (path8.match(`{${pathParam.name}}`)) {
|
|
912
918
|
if (type === "string") {
|
|
913
919
|
newPath = `${newPath}.replace('{${pathParam.name}}', ${pName})`;
|
|
914
920
|
} else {
|
|
@@ -916,9 +922,9 @@ var templateApiMethod = ({
|
|
|
916
922
|
}
|
|
917
923
|
}
|
|
918
924
|
}
|
|
919
|
-
const snippetShellArgs = ["--location --request", `${httpMethod} '__DOMAIN__${
|
|
925
|
+
const snippetShellArgs = ["--location --request", `${httpMethod} '__DOMAIN__${path8}'`, "--header 'accept: application/json'"];
|
|
920
926
|
const snippetApiArgs = [];
|
|
921
|
-
if (xSecurity !== void 0 ||
|
|
927
|
+
if (xSecurity !== void 0 || path8.includes("/admin")) {
|
|
922
928
|
snippetShellArgs.push("--header 'Authorization: Bearer {access_token}'");
|
|
923
929
|
snippetApiArgs.push("{ axiosConfig: { request: { headers: { Authorization: 'Bearer {access_token}' } } } }".trim());
|
|
924
930
|
}
|
|
@@ -956,7 +962,7 @@ var templateMethod = ({
|
|
|
956
962
|
classMethod,
|
|
957
963
|
description,
|
|
958
964
|
httpMethod,
|
|
959
|
-
path:
|
|
965
|
+
path: path8,
|
|
960
966
|
pathParams,
|
|
961
967
|
bodyParams,
|
|
962
968
|
queryParams,
|
|
@@ -966,9 +972,9 @@ var templateMethod = ({
|
|
|
966
972
|
}) => {
|
|
967
973
|
let methodParams = "";
|
|
968
974
|
let methodParamsNoTypes = "";
|
|
969
|
-
let newPath = `'${
|
|
975
|
+
let newPath = `'${path8}'`;
|
|
970
976
|
let importStatements = [];
|
|
971
|
-
const sortedPathParams = ParserUtils.sortPathParamsByPath(pathParams,
|
|
977
|
+
const sortedPathParams = ParserUtils.sortPathParamsByPath(pathParams, path8);
|
|
972
978
|
for (const pathParam of sortedPathParams) {
|
|
973
979
|
const type = ParserUtils.parseType(pathParam);
|
|
974
980
|
if (pathParam.name !== "namespace") {
|
|
@@ -976,7 +982,7 @@ var templateMethod = ({
|
|
|
976
982
|
methodParamsNoTypes += pathParam.name + ", ";
|
|
977
983
|
}
|
|
978
984
|
const pName = pathParam.name === "namespace" ? "this.namespace" : pathParam.name;
|
|
979
|
-
if (
|
|
985
|
+
if (path8.match(`{${pathParam.name}}`)) {
|
|
980
986
|
if (type === "string") {
|
|
981
987
|
newPath = `${newPath}.replace('{${pathParam.name}}', ${pName})`;
|
|
982
988
|
} else {
|
|
@@ -1041,7 +1047,7 @@ var POST_FETCH_INCLUDES_PATH = ["/table-query/"];
|
|
|
1041
1047
|
var templateQueryMethod = ({
|
|
1042
1048
|
classMethod,
|
|
1043
1049
|
httpMethod,
|
|
1044
|
-
path:
|
|
1050
|
+
path: path8,
|
|
1045
1051
|
pathParams,
|
|
1046
1052
|
responseClasses,
|
|
1047
1053
|
methodParams,
|
|
@@ -1049,14 +1055,14 @@ var templateQueryMethod = ({
|
|
|
1049
1055
|
description,
|
|
1050
1056
|
deprecated
|
|
1051
1057
|
}) => {
|
|
1052
|
-
const isPostFetch = httpMethod === "post" && (POST_FETCH_INCLUDES_PATH.some((p) =>
|
|
1058
|
+
const isPostFetch = httpMethod === "post" && (POST_FETCH_INCLUDES_PATH.some((p) => path8.includes(p)) || path8.endsWith("/list"));
|
|
1053
1059
|
const isFetch = classMethod.startsWith("fetch");
|
|
1054
1060
|
const isGet = httpMethod === "get" || isPostFetch || isFetch;
|
|
1055
1061
|
const queryMethod = isGet ? "useQuery" : "useMutation";
|
|
1056
1062
|
let mParams = "";
|
|
1057
1063
|
let mParamsNoTypes = "";
|
|
1058
|
-
let newPath = `'${
|
|
1059
|
-
const sortedPathParams = ParserUtils.sortPathParamsByPath(pathParams,
|
|
1064
|
+
let newPath = `'${path8}'`;
|
|
1065
|
+
const sortedPathParams = ParserUtils.sortPathParamsByPath(pathParams, path8);
|
|
1060
1066
|
for (const pathParam of sortedPathParams) {
|
|
1061
1067
|
const type = ParserUtils.parseType(pathParam);
|
|
1062
1068
|
if (pathParam.name !== "namespace") {
|
|
@@ -1064,7 +1070,7 @@ var templateQueryMethod = ({
|
|
|
1064
1070
|
mParamsNoTypes += pathParam.name + ", ";
|
|
1065
1071
|
}
|
|
1066
1072
|
const pName = pathParam.name === "namespace" ? "this.namespace" : pathParam.name;
|
|
1067
|
-
if (
|
|
1073
|
+
if (path8.match(`{${pathParam.name}}`)) {
|
|
1068
1074
|
if (type === "string") {
|
|
1069
1075
|
newPath = `${newPath}.replace('{${pathParam.name}}', ${pName})`;
|
|
1070
1076
|
} else {
|
|
@@ -1280,11 +1286,11 @@ var SwaggerReaderHelpers = class _SwaggerReaderHelpers {
|
|
|
1280
1286
|
admin: {},
|
|
1281
1287
|
public: {}
|
|
1282
1288
|
};
|
|
1283
|
-
for (const [
|
|
1284
|
-
if (
|
|
1289
|
+
for (const [path8, operation] of sortedPathsByLength) {
|
|
1290
|
+
if (path8.indexOf("/healthz") >= 0) {
|
|
1285
1291
|
continue;
|
|
1286
1292
|
}
|
|
1287
|
-
const isAdminEndpoint =
|
|
1293
|
+
const isAdminEndpoint = path8.indexOf("/admin/") > -1;
|
|
1288
1294
|
const picked = isAdminEndpoint ? result.admin : result.public;
|
|
1289
1295
|
const {
|
|
1290
1296
|
arrayDefinitions,
|
|
@@ -1302,25 +1308,25 @@ var SwaggerReaderHelpers = class _SwaggerReaderHelpers {
|
|
|
1302
1308
|
const httpMethods = Object.keys(operation);
|
|
1303
1309
|
for (const httpMethod of httpMethods) {
|
|
1304
1310
|
const endpoint = await Endpoint.parseAsync(operation[httpMethod]).catch((error) => {
|
|
1305
|
-
console.error(JSON.stringify({ path:
|
|
1311
|
+
console.error(JSON.stringify({ path: path8, httpMethod }, null, 2));
|
|
1306
1312
|
throw error;
|
|
1307
1313
|
});
|
|
1308
1314
|
if (!endpoint.tags) continue;
|
|
1309
1315
|
const [tag] = endpoint.tags;
|
|
1310
|
-
const pathWithBase = `${api.basePath ?? ""}${
|
|
1316
|
+
const pathWithBase = `${api.basePath ?? ""}${path8}`;
|
|
1311
1317
|
const permissionType = getPermissionType(getPermission(endpoint));
|
|
1312
1318
|
tagToClassMethodsMapByType[tag] = tagToClassMethodsMapByType[tag] ? tagToClassMethodsMapByType[tag] : {};
|
|
1313
1319
|
const isForm = endpoint.consumes && endpoint.consumes[0] === "application/x-www-form-urlencoded";
|
|
1314
1320
|
const classMethod = ParserUtils.generateNaturalLangMethod({
|
|
1315
1321
|
servicePrefix,
|
|
1316
|
-
path:
|
|
1322
|
+
path: path8,
|
|
1317
1323
|
httpMethod,
|
|
1318
1324
|
isForm,
|
|
1319
1325
|
existingMethods: tagToClassMethodsMapByType[tag],
|
|
1320
1326
|
permissionType
|
|
1321
1327
|
});
|
|
1322
|
-
tagToClassMethodsMapByType[tag][classMethod] = `${
|
|
1323
|
-
generatedMethods[`${
|
|
1328
|
+
tagToClassMethodsMapByType[tag][classMethod] = `${path8} ${httpMethod}`;
|
|
1329
|
+
generatedMethods[`${path8} ${httpMethod}`] = `${classMethod}`;
|
|
1324
1330
|
if (!snippetMap[pathWithBase]) {
|
|
1325
1331
|
snippetMap[pathWithBase] = {};
|
|
1326
1332
|
}
|
|
@@ -1419,7 +1425,7 @@ var SwaggerReaderHelpers = class _SwaggerReaderHelpers {
|
|
|
1419
1425
|
};
|
|
1420
1426
|
|
|
1421
1427
|
// src/templates/template-api-index.ts
|
|
1422
|
-
var templateApiIndex = (serviceNameTitle, apiList) => {
|
|
1428
|
+
var templateApiIndex = (serviceNameTitle, apiList, isGenerateWebSocket = false) => {
|
|
1423
1429
|
let imports = "";
|
|
1424
1430
|
let returnStatement = "";
|
|
1425
1431
|
for (const cl of apiList) {
|
|
@@ -1428,6 +1434,12 @@ var templateApiIndex = (serviceNameTitle, apiList) => {
|
|
|
1428
1434
|
import { ${cl} } from './${dir}/${cl}.js'`;
|
|
1429
1435
|
returnStatement += `
|
|
1430
1436
|
${cl}, `;
|
|
1437
|
+
}
|
|
1438
|
+
if (isGenerateWebSocket) {
|
|
1439
|
+
imports += `
|
|
1440
|
+
import { WebSocketClass } from './generated-websocket/WebSocketClass.js'`;
|
|
1441
|
+
returnStatement += `
|
|
1442
|
+
WebSocket: WebSocketClass, `;
|
|
1431
1443
|
}
|
|
1432
1444
|
return `/**
|
|
1433
1445
|
* AUTO GENERATED
|
|
@@ -1850,7 +1862,8 @@ var CodeGenerator = class _CodeGenerator {
|
|
|
1850
1862
|
};
|
|
1851
1863
|
generatePublicOrAdmin(true);
|
|
1852
1864
|
generatePublicOrAdmin(false);
|
|
1853
|
-
const
|
|
1865
|
+
const isGenerateWebSocket = CliParser.isGenerateWebSocket();
|
|
1866
|
+
const apiIndexBuff = templateApiIndex(serviceNameTitle, mainApiList, isGenerateWebSocket);
|
|
1854
1867
|
ParserUtils.writeApiMainFile(_CodeGenerator.srcFolder(), serviceNameTitle, apiIndexBuff);
|
|
1855
1868
|
console.log("\nCOMPLETED\n----------\n\n");
|
|
1856
1869
|
return { indexImports: indexImportsSet, queryImports: queryImportsSet };
|
|
@@ -1921,25 +1934,373 @@ var SwaggerDownloader = class _SwaggerDownloader {
|
|
|
1921
1934
|
};
|
|
1922
1935
|
};
|
|
1923
1936
|
|
|
1937
|
+
// src/WebsocketGenerator.ts
|
|
1938
|
+
import fs6 from "fs";
|
|
1939
|
+
import path6 from "path";
|
|
1940
|
+
|
|
1941
|
+
// src/templates/template-ws-class.ts
|
|
1942
|
+
var definitionToFunctionName = (type) => {
|
|
1943
|
+
if (type.endsWith("Request")) {
|
|
1944
|
+
return "send" + capitalize(type.slice(0, type.length - 7));
|
|
1945
|
+
}
|
|
1946
|
+
return type;
|
|
1947
|
+
};
|
|
1948
|
+
var renderSendFunction = (name, definition) => {
|
|
1949
|
+
const functionName = definitionToFunctionName(name);
|
|
1950
|
+
return `const ${functionName} = (data: Omit<Definitions.${capitalize(name)}, 'type'>) => {
|
|
1951
|
+
send({ type: '${name}', ...data })
|
|
1952
|
+
}`;
|
|
1953
|
+
};
|
|
1954
|
+
var templateWebsocketClass = (name, path8, definitions) => {
|
|
1955
|
+
const requestDefinitions = Object.keys(definitions).filter((key) => {
|
|
1956
|
+
const val = definitions[key];
|
|
1957
|
+
return val["x-type"] == "request";
|
|
1958
|
+
}).map((key) => [key, definitions[key]]);
|
|
1959
|
+
return `/* eslint-disable camelcase */
|
|
1960
|
+
/* eslint-disable no-inner-declarations */
|
|
1961
|
+
// @ts-ignore -> ts-expect-error TS6133
|
|
1962
|
+
import { AccelByteSDK, RefreshToken, SdkSetConfigParam } from '@accelbyte/sdk'
|
|
1963
|
+
import * as Definitions from './WebSocketDefinitions'
|
|
1964
|
+
|
|
1965
|
+
const messageParser = (data: string) => {
|
|
1966
|
+
const toVal = (str?: string) => {
|
|
1967
|
+
if (str) {
|
|
1968
|
+
if (str.startsWith('[') && str.endsWith(']')) {
|
|
1969
|
+
return str
|
|
1970
|
+
.slice(1, str.length - 1)
|
|
1971
|
+
.split(',')
|
|
1972
|
+
.filter(v => v !== '')
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
return str
|
|
1976
|
+
}
|
|
1977
|
+
|
|
1978
|
+
const entries = data.split('\\n')
|
|
1979
|
+
.filter(line => line !== '')
|
|
1980
|
+
.map(line => {
|
|
1981
|
+
const [key, valStr] = line.split(': ')
|
|
1982
|
+
return [key, toVal(valStr)]
|
|
1983
|
+
})
|
|
1984
|
+
|
|
1985
|
+
return Object.fromEntries(entries)
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
const messageSerializer = (data: Record<string, any>) => {
|
|
1989
|
+
return Object.keys(data)
|
|
1990
|
+
.map(key => {
|
|
1991
|
+
const toStr = (val: any) => {
|
|
1992
|
+
// array
|
|
1993
|
+
if (Array.isArray(val)) {
|
|
1994
|
+
return \`[\${String(val)}]\`
|
|
1995
|
+
}
|
|
1996
|
+
// null, undefined
|
|
1997
|
+
if (!val) {
|
|
1998
|
+
return ''
|
|
1999
|
+
}
|
|
2000
|
+
return String(val)
|
|
2001
|
+
}
|
|
2002
|
+
const val = data[key]
|
|
2003
|
+
const valStr = toStr(val)
|
|
2004
|
+
|
|
2005
|
+
return \`\${key}: \${valStr}\`
|
|
2006
|
+
})
|
|
2007
|
+
.join('\\n')
|
|
2008
|
+
}
|
|
2009
|
+
|
|
2010
|
+
export function WebSocketClass(sdk: AccelByteSDK, args?: SdkSetConfigParam) {
|
|
2011
|
+
const sdkAssembly = sdk.assembly()
|
|
2012
|
+
const baseURL = (args?.coreConfig?.baseURL ?? sdkAssembly.coreConfig.baseURL).replace('http', 'ws')
|
|
2013
|
+
const path = '${path8}'
|
|
2014
|
+
const url = baseURL + path
|
|
2015
|
+
let ws: WebSocket | null = null
|
|
2016
|
+
let isDisconnectManually = false
|
|
2017
|
+
const allowReconnect = sdkAssembly.webSocketConfig.allowReconnect ?? true
|
|
2018
|
+
const maxReconnectAttempts = sdkAssembly.webSocketConfig.maxReconnectAttempts ?? 0
|
|
2019
|
+
let reconnectAttempts = maxReconnectAttempts
|
|
2020
|
+
|
|
2021
|
+
const connect = () => {
|
|
2022
|
+
const token = sdk.getToken()
|
|
2023
|
+
|
|
2024
|
+
if (!token.accessToken) {
|
|
2025
|
+
console.warn('No access token, please login first')
|
|
2026
|
+
return
|
|
2027
|
+
}
|
|
2028
|
+
|
|
2029
|
+
if (!ws) {
|
|
2030
|
+
ws = new WebSocket(url, token.accessToken)
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
const refreshToken = async () => {
|
|
2035
|
+
const { refreshToken } = sdk.getToken()
|
|
2036
|
+
if (refreshToken) {
|
|
2037
|
+
const refresh = new RefreshToken({
|
|
2038
|
+
config: {
|
|
2039
|
+
axiosConfig: sdkAssembly.axiosConfig.request,
|
|
2040
|
+
clientId: sdkAssembly.coreConfig.clientId,
|
|
2041
|
+
refreshToken
|
|
2042
|
+
}
|
|
2043
|
+
})
|
|
2044
|
+
const result = await refresh.runWithLock()
|
|
2045
|
+
if (result) {
|
|
2046
|
+
sdk.setToken({
|
|
2047
|
+
accessToken: result.access_token,
|
|
2048
|
+
refreshToken: result.refresh_token
|
|
2049
|
+
})
|
|
2050
|
+
return true
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2053
|
+
return false
|
|
2054
|
+
}
|
|
2055
|
+
|
|
2056
|
+
const handleReconnect = async (ev: CloseEvent) => {
|
|
2057
|
+
if (!allowReconnect || isDisconnectManually || !sdk.getToken().accessToken) return
|
|
2058
|
+
// token revoked
|
|
2059
|
+
if (ev.code === 4020) {
|
|
2060
|
+
await refreshToken()
|
|
2061
|
+
reconnectAttempts--
|
|
2062
|
+
connect()
|
|
2063
|
+
} else if (ev.code >= 1001 && ev.code <= 2999) {
|
|
2064
|
+
// Only reconnect if codes in range 1001-2999
|
|
2065
|
+
if (!ws || ws.readyState !== ws.OPEN) return
|
|
2066
|
+
|
|
2067
|
+
if (maxReconnectAttempts === 0) {
|
|
2068
|
+
setTimeout(() => {
|
|
2069
|
+
connect()
|
|
2070
|
+
}, 1000)
|
|
2071
|
+
} else if (reconnectAttempts !== 0) {
|
|
2072
|
+
setTimeout(() => {
|
|
2073
|
+
reconnectAttempts--
|
|
2074
|
+
connect()
|
|
2075
|
+
}, 1000)
|
|
2076
|
+
}
|
|
2077
|
+
}
|
|
2078
|
+
}
|
|
2079
|
+
|
|
2080
|
+
const disconnect = (code?: number, reason?: string) => {
|
|
2081
|
+
if (ws) {
|
|
2082
|
+
ws.close(code, reason)
|
|
2083
|
+
isDisconnectManually = true
|
|
2084
|
+
ws = null
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
|
|
2088
|
+
const send = (message: Definitions.WebSocketRequest) => {
|
|
2089
|
+
if (ws) {
|
|
2090
|
+
ws.send(messageSerializer(message))
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
|
|
2094
|
+
const sendRaw = (rawMessage: string) => {
|
|
2095
|
+
if (ws) {
|
|
2096
|
+
ws.send(rawMessage)
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2100
|
+
const onOpen = (cb: () => any) => {
|
|
2101
|
+
if (ws) {
|
|
2102
|
+
function listener(this: WebSocket, _ev: Event) {
|
|
2103
|
+
isDisconnectManually = false
|
|
2104
|
+
reconnectAttempts = maxReconnectAttempts
|
|
2105
|
+
cb()
|
|
2106
|
+
}
|
|
2107
|
+
ws.addEventListener('open', listener)
|
|
2108
|
+
return {
|
|
2109
|
+
removeEventListener: () => ws?.removeEventListener('open', listener)
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
return {}
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
const onClose = (cb: (ev: CloseEvent) => any) => {
|
|
2116
|
+
if (ws) {
|
|
2117
|
+
function listener(this: WebSocket, ev: CloseEvent) {
|
|
2118
|
+
handleReconnect(ev)
|
|
2119
|
+
cb(ev)
|
|
2120
|
+
}
|
|
2121
|
+
ws.addEventListener('close', listener)
|
|
2122
|
+
return {
|
|
2123
|
+
removeEventListener: () => ws?.removeEventListener('close', listener)
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
return {}
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2129
|
+
const onMessage = (cb: (message: Definitions.WebSocketResponseOrNotification | string) => any, raw: boolean = false) => {
|
|
2130
|
+
if (ws) {
|
|
2131
|
+
function listener(this: WebSocket, ev: MessageEvent<any>) {
|
|
2132
|
+
if (raw) {
|
|
2133
|
+
cb(ev.data)
|
|
2134
|
+
} else {
|
|
2135
|
+
const result = Definitions.WebSocketResponseOrNotification.parse(messageParser(ev.data))
|
|
2136
|
+
cb(result)
|
|
2137
|
+
}
|
|
2138
|
+
}
|
|
2139
|
+
ws.addEventListener('message', listener)
|
|
2140
|
+
return {
|
|
2141
|
+
removeEventListener: () => ws?.removeEventListener('message', listener)
|
|
2142
|
+
}
|
|
2143
|
+
}
|
|
2144
|
+
return {}
|
|
2145
|
+
}
|
|
2146
|
+
|
|
2147
|
+
const onError = (cb: (err: any) => any) => {
|
|
2148
|
+
if (ws) {
|
|
2149
|
+
function listener(this: WebSocket, err: any) {
|
|
2150
|
+
cb(err)
|
|
2151
|
+
}
|
|
2152
|
+
ws.addEventListener('error', listener)
|
|
2153
|
+
return {
|
|
2154
|
+
removeEventListener: () => ws?.removeEventListener('error', listener)
|
|
2155
|
+
}
|
|
2156
|
+
}
|
|
2157
|
+
return {}
|
|
2158
|
+
}
|
|
2159
|
+
|
|
2160
|
+
${requestDefinitions.map(([name2, definition]) => renderSendFunction(name2, definition)).join(`
|
|
2161
|
+
|
|
2162
|
+
`)}
|
|
2163
|
+
|
|
2164
|
+
return {
|
|
2165
|
+
instance: ws,
|
|
2166
|
+
connect,
|
|
2167
|
+
disconnect,
|
|
2168
|
+
send,
|
|
2169
|
+
sendRaw,
|
|
2170
|
+
onOpen,
|
|
2171
|
+
onClose,
|
|
2172
|
+
onMessage,
|
|
2173
|
+
onError,
|
|
2174
|
+
${requestDefinitions.map(([name2, _2]) => definitionToFunctionName(name2)).join(",\n ")}
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2177
|
+
|
|
2178
|
+
`;
|
|
2179
|
+
};
|
|
2180
|
+
|
|
2181
|
+
// src/templates/template-ws-defintions.ts
|
|
2182
|
+
var renderZod = (property) => {
|
|
2183
|
+
switch (property.type) {
|
|
2184
|
+
case "string":
|
|
2185
|
+
return `z.coerce.string()`;
|
|
2186
|
+
case "integer":
|
|
2187
|
+
return `z.coerce.number()`;
|
|
2188
|
+
case "boolean":
|
|
2189
|
+
return `z.boolean()`;
|
|
2190
|
+
case "array":
|
|
2191
|
+
return `z.array(${renderZod(property.items)})`;
|
|
2192
|
+
default:
|
|
2193
|
+
return `z.any()`;
|
|
2194
|
+
}
|
|
2195
|
+
};
|
|
2196
|
+
var renderProperty = (name, type, property, required) => {
|
|
2197
|
+
const isRequired = required && required.includes(name);
|
|
2198
|
+
return `${name}: ${renderZod(property)}${isRequired || type != "request" ? "" : ".optional()"}`;
|
|
2199
|
+
};
|
|
2200
|
+
var renderDefinition = (name, definition) => {
|
|
2201
|
+
const capitalizedName = capitalize(name);
|
|
2202
|
+
if (definition.properties) {
|
|
2203
|
+
const properties = Object.entries(definition.properties);
|
|
2204
|
+
return `export const ${capitalizedName} = z.object({
|
|
2205
|
+
type: z.literal("${name}"),
|
|
2206
|
+
${properties.map(([name2, property]) => renderProperty(name2, definition["x-type"], property, definition.required)).join(",\n ")}
|
|
2207
|
+
})
|
|
2208
|
+
|
|
2209
|
+
export type ${capitalizedName} = z.infer<typeof ${capitalizedName}>
|
|
2210
|
+
`;
|
|
2211
|
+
}
|
|
2212
|
+
return "";
|
|
2213
|
+
};
|
|
2214
|
+
var renderAllDefinitions = (definitions) => {
|
|
2215
|
+
if (definitions) {
|
|
2216
|
+
const definitionEntries = Object.entries(definitions);
|
|
2217
|
+
return definitionEntries.map(([name, definition]) => renderDefinition(name, definition)).join("\n\n");
|
|
2218
|
+
}
|
|
2219
|
+
return "";
|
|
2220
|
+
};
|
|
2221
|
+
var renderUnion = (type, definitions) => {
|
|
2222
|
+
if (definitions) {
|
|
2223
|
+
let capitalizedType = "";
|
|
2224
|
+
if (typeof type === "string") {
|
|
2225
|
+
capitalizedType = capitalize(type);
|
|
2226
|
+
} else {
|
|
2227
|
+
capitalizedType = type.map((t) => capitalize(t)).join("Or");
|
|
2228
|
+
}
|
|
2229
|
+
const filteredDefinitions = Object.entries(definitions).filter(([_2, def]) => {
|
|
2230
|
+
if (typeof type === "string") {
|
|
2231
|
+
return def["x-type"] === type;
|
|
2232
|
+
} else {
|
|
2233
|
+
return type.includes(def["x-type"]);
|
|
2234
|
+
}
|
|
2235
|
+
}).map(([name, _2]) => capitalize(name));
|
|
2236
|
+
return `export const WebSocket${capitalizedType} = z.discriminatedUnion("type", [
|
|
2237
|
+
${filteredDefinitions.join(",\n ")}
|
|
2238
|
+
])
|
|
2239
|
+
|
|
2240
|
+
export type WebSocket${capitalizedType} = z.infer<typeof WebSocket${capitalizedType}>`;
|
|
2241
|
+
}
|
|
2242
|
+
return "";
|
|
2243
|
+
};
|
|
2244
|
+
var templateWebsocketDefinitions = (definitions) => {
|
|
2245
|
+
return `/**
|
|
2246
|
+
* AUTO GENERATED
|
|
2247
|
+
*/
|
|
2248
|
+
|
|
2249
|
+
import { z } from 'zod'
|
|
2250
|
+
|
|
2251
|
+
${renderAllDefinitions(definitions)}
|
|
2252
|
+
|
|
2253
|
+
${renderUnion("request", definitions)}
|
|
2254
|
+
|
|
2255
|
+
${renderUnion(["response", "notification"], definitions)}
|
|
2256
|
+
`;
|
|
2257
|
+
};
|
|
2258
|
+
|
|
2259
|
+
// src/WebsocketGenerator.ts
|
|
2260
|
+
var WebsocketGenerator = class {
|
|
2261
|
+
static srcFolder = () => CliParser.getOutputPath();
|
|
2262
|
+
static outputFolder = () => path6.join(this.srcFolder(), "generated-websocket");
|
|
2263
|
+
static schemaContent = () => {
|
|
2264
|
+
const fileContent = JSON.parse(fs6.readFileSync(CliParser.getWebSocketSchemaPath(), "utf8"));
|
|
2265
|
+
return fileContent;
|
|
2266
|
+
};
|
|
2267
|
+
static prepareDirs = () => {
|
|
2268
|
+
ParserUtils.mkdirIfNotExist(this.outputFolder());
|
|
2269
|
+
};
|
|
2270
|
+
static main = () => {
|
|
2271
|
+
const { name, path: wsPath, definitions } = this.schemaContent();
|
|
2272
|
+
const templateDefinitions = templateWebsocketDefinitions(definitions);
|
|
2273
|
+
this.prepareDirs();
|
|
2274
|
+
const filePath = path6.join(this.outputFolder(), "WebSocketDefinitions.ts");
|
|
2275
|
+
fs6.writeFileSync(filePath, templateDefinitions, "utf8");
|
|
2276
|
+
const templateClass2 = templateWebsocketClass(name, wsPath, definitions);
|
|
2277
|
+
const filePathClass = path6.join(this.outputFolder(), "WebSocketClass.ts");
|
|
2278
|
+
fs6.writeFileSync(filePathClass, templateClass2, "utf8");
|
|
2279
|
+
};
|
|
2280
|
+
};
|
|
2281
|
+
|
|
1924
2282
|
// src/cli.ts
|
|
1925
2283
|
var generateSdk = async () => {
|
|
1926
2284
|
const arrayOfSets = await Promise.all(CliParser.getConfigFile().map((config) => CodeGenerator.main(config)));
|
|
1927
2285
|
if (CliParser.isGenerateSnippetOnly()) {
|
|
1928
2286
|
return;
|
|
1929
2287
|
}
|
|
2288
|
+
if (CliParser.isGenerateWebSocket()) {
|
|
2289
|
+
WebsocketGenerator.main();
|
|
2290
|
+
}
|
|
1930
2291
|
const indexImportsSet = /* @__PURE__ */ new Set();
|
|
1931
2292
|
const queryImportsSet = /* @__PURE__ */ new Set();
|
|
1932
2293
|
const filenamesSet = /* @__PURE__ */ new Set();
|
|
1933
2294
|
for (const set of arrayOfSets) {
|
|
1934
2295
|
set.indexImports.forEach((value) => {
|
|
1935
|
-
const fileName =
|
|
2296
|
+
const fileName = path7.basename(value);
|
|
1936
2297
|
if (!filenamesSet.has(fileName)) {
|
|
1937
2298
|
indexImportsSet.add(value);
|
|
1938
2299
|
filenamesSet.add(fileName);
|
|
1939
2300
|
}
|
|
1940
2301
|
});
|
|
1941
2302
|
set.queryImports.forEach((value) => {
|
|
1942
|
-
const fileName =
|
|
2303
|
+
const fileName = path7.basename(value);
|
|
1943
2304
|
if (!filenamesSet.has(fileName)) {
|
|
1944
2305
|
queryImportsSet.add(value);
|
|
1945
2306
|
}
|
|
@@ -1991,5 +2352,8 @@ yargs.command("download-swaggers", "Download swaggers JSON files", (yargs2) => {
|
|
|
1991
2352
|
}).option("snippetOutput", {
|
|
1992
2353
|
description: "Directory for the generated code snippets. Required when generating snippets.",
|
|
1993
2354
|
type: "string"
|
|
2355
|
+
}).option("webSocketSchema", {
|
|
2356
|
+
description: "Path to the WebSocket schema file (schema.json). If provided, WebSocket methods will be generated based on the schema.",
|
|
2357
|
+
type: "string"
|
|
1994
2358
|
}).demandCommand(1).help().argv;
|
|
1995
2359
|
//# sourceMappingURL=accelbyte-codegen.mjs.map
|