@accelbyte/codegen 4.0.1 → 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.
@@ -23,8 +23,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
23
  ));
24
24
 
25
25
  // src/cli.ts
26
+ var import_path5 = __toESM(require("path"));
26
27
  var import_yargs = __toESM(require("yargs"));
27
- var import_path4 = __toESM(require("path"));
28
28
 
29
29
  // src/CliParser.ts
30
30
  var import_fs = __toESM(require("fs"));
@@ -77,6 +77,12 @@ var CliParser = class _CliParser {
77
77
  static isGenerateSnippetOnly = () => {
78
78
  return _CliParser.instance().argv.snippetOnly;
79
79
  };
80
+ static getWebSocketSchemaPath = () => {
81
+ return _CliParser.instance().argv.webSocketSchema;
82
+ };
83
+ static isGenerateWebSocket = () => {
84
+ return !!_CliParser.getWebSocketSchemaPath();
85
+ };
80
86
  };
81
87
 
82
88
  // src/CodeGenerator.ts
@@ -323,15 +329,15 @@ export enum Key_${classNameWithoutApi} {
323
329
  `;
324
330
  };
325
331
  function filterUsedImports(importArr, body) {
326
- return importArr.filter((path7) => {
327
- const start = path7.indexOf("{") + 1;
328
- const end = path7.indexOf("}");
332
+ return importArr.filter((path8) => {
333
+ const start = path8.indexOf("{") + 1;
334
+ const end = path8.indexOf("}");
329
335
  if (start > 0 && end > start) {
330
- const importName = path7.slice(start, end).trim();
336
+ const importName = path8.slice(start, end).trim();
331
337
  return body.includes(importName);
332
338
  }
333
339
  return false;
334
- }).map((path7) => path7).join("\n") + "\n";
340
+ }).map((path8) => path8).join("\n") + "\n";
335
341
  }
336
342
 
337
343
  // src/ParserUtils.ts
@@ -348,8 +354,8 @@ var REMOVED_KEYWORDS = [
348
354
  "/{namespace}/"
349
355
  ];
350
356
  var ParserUtils = class _ParserUtils {
351
- static getVersionSuffixFromPath(path7) {
352
- const version2_3_4_etc = path7.match(/\/v([2-9]|[1-9]\d+)\/+/);
357
+ static getVersionSuffixFromPath(path8) {
358
+ const version2_3_4_etc = path8.match(/\/v([2-9]|[1-9]\d+)\/+/);
353
359
  const methodSuffix = version2_3_4_etc ? `_v${version2_3_4_etc[1]}` : "";
354
360
  return methodSuffix;
355
361
  }
@@ -544,14 +550,14 @@ var ParserUtils = class _ParserUtils {
544
550
  * to this
545
551
  * `createGenerateByRequestIdByUserId`
546
552
  */
547
- static generateNaturalLangMethod = ({ servicePrefix, path: path7, httpMethod, isForm, existingMethods, permissionType }) => {
548
- let path_ = path7;
553
+ static generateNaturalLangMethod = ({ servicePrefix, path: path8, httpMethod, isForm, existingMethods, permissionType }) => {
554
+ let path_ = path8;
549
555
  path_ = path_.replace(`/${servicePrefix}/`, "/");
550
556
  REMOVED_KEYWORDS.forEach((prefix) => {
551
557
  path_ = path_.replace(prefix, "/");
552
558
  });
553
559
  path_ = path_.substring(1);
554
- const isPlural = httpMethod === "get" && !(path7.slice(-1) === "}");
560
+ const isPlural = httpMethod === "get" && !(path8.slice(-1) === "}");
555
561
  if (!isPlural) {
556
562
  path_ = _ParserUtils.replaceAll(path_, "ies/", "y/");
557
563
  path_ = _ParserUtils.replaceAll(path_, "s/", "/");
@@ -594,9 +600,9 @@ var ParserUtils = class _ParserUtils {
594
600
  const genPath = import_lodash.default.upperFirst(lastWords) + "/" + listBeforeLastWords.join("/") + listByParams.reverse().join("/");
595
601
  let generatedMethod = import_lodash.default.camelCase(mappedMethod(httpMethod, isForm, permissionType) + genPath);
596
602
  generatedMethod = _ParserUtils.replaceAll(generatedMethod, "Byword", "_By");
597
- const testedGeneratedMethod = generatedMethod + _ParserUtils.getVersionSuffixFromPath(path7);
598
- generatedMethod = resolveConflicts({ path: path7, generatedMethod, testedGeneratedMethod, existingMethods });
599
- generatedMethod = generatedMethod + _ParserUtils.getVersionSuffixFromPath(path7);
603
+ const testedGeneratedMethod = generatedMethod + _ParserUtils.getVersionSuffixFromPath(path8);
604
+ generatedMethod = resolveConflicts({ path: path8, generatedMethod, testedGeneratedMethod, existingMethods });
605
+ generatedMethod = generatedMethod + _ParserUtils.getVersionSuffixFromPath(path8);
600
606
  return generatedMethod;
601
607
  };
602
608
  static filterBodyParams(parameters) {
@@ -751,8 +757,8 @@ var ParserUtils = class _ParserUtils {
751
757
  */
752
758
  ${content}`;
753
759
  };
754
- static sortPathParamsByPath = (pathParams, path7) => {
755
- const params = path7.match(/{\w*}/g) || [];
760
+ static sortPathParamsByPath = (pathParams, path8) => {
761
+ const params = path8.match(/{\w*}/g) || [];
756
762
  const cleanParams = params.map((param) => param.replace("{", "").replace("}", ""));
757
763
  return pathParams.sort((a, b) => cleanParams.indexOf(a.name) - cleanParams.indexOf(b.name));
758
764
  };
@@ -776,30 +782,30 @@ var mappedMethod = (httpMethod, isForm, permissionType) => {
776
782
  return "delete";
777
783
  }
778
784
  };
779
- var resolveConflicts = ({ path: path7, generatedMethod, testedGeneratedMethod, existingMethods }) => {
785
+ var resolveConflicts = ({ path: path8, generatedMethod, testedGeneratedMethod, existingMethods }) => {
780
786
  let _testedGenMethod = testedGeneratedMethod;
781
787
  try {
782
- testConflict(path7, _testedGenMethod, existingMethods);
788
+ testConflict(path8, _testedGenMethod, existingMethods);
783
789
  } catch (e) {
784
- if (path7.indexOf("/namespaces/") >= 0) {
790
+ if (path8.indexOf("/namespaces/") >= 0) {
785
791
  generatedMethod += "_ByNS";
786
792
  _testedGenMethod += "_ByNS";
787
793
  }
788
794
  }
789
795
  try {
790
- testConflict(path7, _testedGenMethod, existingMethods);
796
+ testConflict(path8, _testedGenMethod, existingMethods);
791
797
  } catch (e) {
792
- if (path7.indexOf("/admin/") >= 0) {
798
+ if (path8.indexOf("/admin/") >= 0) {
793
799
  generatedMethod += "_admin";
794
800
  _testedGenMethod += "_admin";
795
801
  }
796
802
  }
797
- testConflict(path7, _testedGenMethod, existingMethods);
803
+ testConflict(path8, _testedGenMethod, existingMethods);
798
804
  return generatedMethod;
799
805
  };
800
- var testConflict = (path7, generatedMethod, existingMethods) => {
806
+ var testConflict = (path8, generatedMethod, existingMethods) => {
801
807
  if (existingMethods[generatedMethod]) {
802
- const conflictingMethod = { path: path7, generatedMethod };
808
+ const conflictingMethod = { path: path8, generatedMethod };
803
809
  throw Error(
804
810
  `Duplicate method conflict in ${JSON.stringify(conflictingMethod)},
805
811
  existingMethods: ${JSON.stringify(existingMethods, null, 2)}`
@@ -916,7 +922,7 @@ var OpenApiSpec = import_zod2.z.object({
916
922
  var templateApiMethod = ({
917
923
  classMethod,
918
924
  httpMethod,
919
- path: path7,
925
+ path: path8,
920
926
  pathParams,
921
927
  bodyParams,
922
928
  responseClasses,
@@ -925,12 +931,12 @@ var templateApiMethod = ({
925
931
  methodParamsNoTypes,
926
932
  xSecurity
927
933
  }) => {
928
- let newPath = `'${path7}'`;
934
+ let newPath = `'${path8}'`;
929
935
  let snippetMethod = "";
930
936
  for (const pathParam of pathParams) {
931
937
  const type = ParserUtils.parseType(pathParam);
932
938
  const pName = pathParam.name === "namespace" ? "this.namespace" : pathParam.name;
933
- if (path7.match(`{${pathParam.name}}`)) {
939
+ if (path8.match(`{${pathParam.name}}`)) {
934
940
  if (type === "string") {
935
941
  newPath = `${newPath}.replace('{${pathParam.name}}', ${pName})`;
936
942
  } else {
@@ -938,9 +944,9 @@ var templateApiMethod = ({
938
944
  }
939
945
  }
940
946
  }
941
- const snippetShellArgs = ["--location --request", `${httpMethod} '__DOMAIN__${path7}'`, "--header 'accept: application/json'"];
947
+ const snippetShellArgs = ["--location --request", `${httpMethod} '__DOMAIN__${path8}'`, "--header 'accept: application/json'"];
942
948
  const snippetApiArgs = [];
943
- if (xSecurity !== void 0 || path7.includes("/admin")) {
949
+ if (xSecurity !== void 0 || path8.includes("/admin")) {
944
950
  snippetShellArgs.push("--header 'Authorization: Bearer {access_token}'");
945
951
  snippetApiArgs.push("{ axiosConfig: { request: { headers: { Authorization: 'Bearer {access_token}' } } } }".trim());
946
952
  }
@@ -978,7 +984,7 @@ var templateMethod = ({
978
984
  classMethod,
979
985
  description,
980
986
  httpMethod,
981
- path: path7,
987
+ path: path8,
982
988
  pathParams,
983
989
  bodyParams,
984
990
  queryParams,
@@ -988,9 +994,9 @@ var templateMethod = ({
988
994
  }) => {
989
995
  let methodParams = "";
990
996
  let methodParamsNoTypes = "";
991
- let newPath = `'${path7}'`;
997
+ let newPath = `'${path8}'`;
992
998
  let importStatements = [];
993
- const sortedPathParams = ParserUtils.sortPathParamsByPath(pathParams, path7);
999
+ const sortedPathParams = ParserUtils.sortPathParamsByPath(pathParams, path8);
994
1000
  for (const pathParam of sortedPathParams) {
995
1001
  const type = ParserUtils.parseType(pathParam);
996
1002
  if (pathParam.name !== "namespace") {
@@ -998,7 +1004,7 @@ var templateMethod = ({
998
1004
  methodParamsNoTypes += pathParam.name + ", ";
999
1005
  }
1000
1006
  const pName = pathParam.name === "namespace" ? "this.namespace" : pathParam.name;
1001
- if (path7.match(`{${pathParam.name}}`)) {
1007
+ if (path8.match(`{${pathParam.name}}`)) {
1002
1008
  if (type === "string") {
1003
1009
  newPath = `${newPath}.replace('{${pathParam.name}}', ${pName})`;
1004
1010
  } else {
@@ -1063,7 +1069,7 @@ var POST_FETCH_INCLUDES_PATH = ["/table-query/"];
1063
1069
  var templateQueryMethod = ({
1064
1070
  classMethod,
1065
1071
  httpMethod,
1066
- path: path7,
1072
+ path: path8,
1067
1073
  pathParams,
1068
1074
  responseClasses,
1069
1075
  methodParams,
@@ -1071,14 +1077,14 @@ var templateQueryMethod = ({
1071
1077
  description,
1072
1078
  deprecated
1073
1079
  }) => {
1074
- const isPostFetch = httpMethod === "post" && (POST_FETCH_INCLUDES_PATH.some((p) => path7.includes(p)) || path7.endsWith("/list"));
1080
+ const isPostFetch = httpMethod === "post" && (POST_FETCH_INCLUDES_PATH.some((p) => path8.includes(p)) || path8.endsWith("/list"));
1075
1081
  const isFetch = classMethod.startsWith("fetch");
1076
1082
  const isGet = httpMethod === "get" || isPostFetch || isFetch;
1077
1083
  const queryMethod = isGet ? "useQuery" : "useMutation";
1078
1084
  let mParams = "";
1079
1085
  let mParamsNoTypes = "";
1080
- let newPath = `'${path7}'`;
1081
- const sortedPathParams = ParserUtils.sortPathParamsByPath(pathParams, path7);
1086
+ let newPath = `'${path8}'`;
1087
+ const sortedPathParams = ParserUtils.sortPathParamsByPath(pathParams, path8);
1082
1088
  for (const pathParam of sortedPathParams) {
1083
1089
  const type = ParserUtils.parseType(pathParam);
1084
1090
  if (pathParam.name !== "namespace") {
@@ -1086,7 +1092,7 @@ var templateQueryMethod = ({
1086
1092
  mParamsNoTypes += pathParam.name + ", ";
1087
1093
  }
1088
1094
  const pName = pathParam.name === "namespace" ? "this.namespace" : pathParam.name;
1089
- if (path7.match(`{${pathParam.name}}`)) {
1095
+ if (path8.match(`{${pathParam.name}}`)) {
1090
1096
  if (type === "string") {
1091
1097
  newPath = `${newPath}.replace('{${pathParam.name}}', ${pName})`;
1092
1098
  } else {
@@ -1225,7 +1231,7 @@ import { ${serviceNameTitle} } from '@accelbyte/sdk-${serviceNameTitle.toLowerCa
1225
1231
 
1226
1232
  const sdk = AccelByte.SDK({
1227
1233
  coreConfig: {
1228
- baseURL: 'https://demo.accelbyte.io',
1234
+ baseURL: '__DOMAIN__',
1229
1235
  clientId: '77f88506b6174c3ea4d925f5b4096ce8',
1230
1236
  namespace: 'accelbyte',
1231
1237
  redirectURI: 'http://localhost:3030'
@@ -1255,7 +1261,7 @@ var normalizeMethodSnippet = (methodInput, splitWord) => {
1255
1261
  };
1256
1262
 
1257
1263
  // src/helpers/SwaggerReaderHelpers.ts
1258
- var GIT_URL = "https://github.com/AccelByte/accelbyte-web-sdk/blob/main/packages";
1264
+ var GIT_URL = "https://github.com/AccelByte/accelbyte-typescript-sdk/blob/main/packages";
1259
1265
  var SwaggerReaderHelpers = class _SwaggerReaderHelpers {
1260
1266
  static getServicePrefix = (servicePaths) => servicePaths[servicePaths.length - 1].split("/")[1];
1261
1267
  static parseAllEndpoints = async ({
@@ -1302,11 +1308,11 @@ var SwaggerReaderHelpers = class _SwaggerReaderHelpers {
1302
1308
  admin: {},
1303
1309
  public: {}
1304
1310
  };
1305
- for (const [path7, operation] of sortedPathsByLength) {
1306
- if (path7.indexOf("/healthz") >= 0) {
1311
+ for (const [path8, operation] of sortedPathsByLength) {
1312
+ if (path8.indexOf("/healthz") >= 0) {
1307
1313
  continue;
1308
1314
  }
1309
- const isAdminEndpoint = path7.indexOf("/admin/") > -1;
1315
+ const isAdminEndpoint = path8.indexOf("/admin/") > -1;
1310
1316
  const picked = isAdminEndpoint ? result.admin : result.public;
1311
1317
  const {
1312
1318
  arrayDefinitions,
@@ -1324,25 +1330,25 @@ var SwaggerReaderHelpers = class _SwaggerReaderHelpers {
1324
1330
  const httpMethods = Object.keys(operation);
1325
1331
  for (const httpMethod of httpMethods) {
1326
1332
  const endpoint = await Endpoint.parseAsync(operation[httpMethod]).catch((error) => {
1327
- console.error(JSON.stringify({ path: path7, httpMethod }, null, 2));
1333
+ console.error(JSON.stringify({ path: path8, httpMethod }, null, 2));
1328
1334
  throw error;
1329
1335
  });
1330
1336
  if (!endpoint.tags) continue;
1331
1337
  const [tag] = endpoint.tags;
1332
- const pathWithBase = `${api.basePath ?? ""}${path7}`;
1338
+ const pathWithBase = `${api.basePath ?? ""}${path8}`;
1333
1339
  const permissionType = getPermissionType(getPermission(endpoint));
1334
1340
  tagToClassMethodsMapByType[tag] = tagToClassMethodsMapByType[tag] ? tagToClassMethodsMapByType[tag] : {};
1335
1341
  const isForm = endpoint.consumes && endpoint.consumes[0] === "application/x-www-form-urlencoded";
1336
1342
  const classMethod = ParserUtils.generateNaturalLangMethod({
1337
1343
  servicePrefix,
1338
- path: path7,
1344
+ path: path8,
1339
1345
  httpMethod,
1340
1346
  isForm,
1341
1347
  existingMethods: tagToClassMethodsMapByType[tag],
1342
1348
  permissionType
1343
1349
  });
1344
- tagToClassMethodsMapByType[tag][classMethod] = `${path7} ${httpMethod}`;
1345
- generatedMethods[`${path7} ${httpMethod}`] = `${classMethod}`;
1350
+ tagToClassMethodsMapByType[tag][classMethod] = `${path8} ${httpMethod}`;
1351
+ generatedMethods[`${path8} ${httpMethod}`] = `${classMethod}`;
1346
1352
  if (!snippetMap[pathWithBase]) {
1347
1353
  snippetMap[pathWithBase] = {};
1348
1354
  }
@@ -1441,7 +1447,7 @@ var SwaggerReaderHelpers = class _SwaggerReaderHelpers {
1441
1447
  };
1442
1448
 
1443
1449
  // src/templates/template-api-index.ts
1444
- var templateApiIndex = (serviceNameTitle, apiList) => {
1450
+ var templateApiIndex = (serviceNameTitle, apiList, isGenerateWebSocket = false) => {
1445
1451
  let imports = "";
1446
1452
  let returnStatement = "";
1447
1453
  for (const cl of apiList) {
@@ -1450,6 +1456,12 @@ var templateApiIndex = (serviceNameTitle, apiList) => {
1450
1456
  import { ${cl} } from './${dir}/${cl}.js'`;
1451
1457
  returnStatement += `
1452
1458
  ${cl}, `;
1459
+ }
1460
+ if (isGenerateWebSocket) {
1461
+ imports += `
1462
+ import { WebSocketClass } from './generated-websocket/WebSocketClass.js'`;
1463
+ returnStatement += `
1464
+ WebSocket: WebSocketClass, `;
1453
1465
  }
1454
1466
  return `/**
1455
1467
  * AUTO GENERATED
@@ -1755,7 +1767,9 @@ var CodeGenerator = class _CodeGenerator {
1755
1767
  const queryImportsSet = /* @__PURE__ */ new Set();
1756
1768
  const apiInfo = { ...api.info, "x-version": api["x-version"]?.version };
1757
1769
  console.log("----------\nGenerating API:", { title: apiInfo.title, version: apiInfo.version });
1758
- ParserUtils.writeXVersion(_CodeGenerator.srcFolder(), api["x-version"], api.info);
1770
+ if (!CliParser.isGenerateSnippetOnly()) {
1771
+ ParserUtils.writeXVersion(_CodeGenerator.srcFolder(), api["x-version"], api.info);
1772
+ }
1759
1773
  const parsedInformation = await SwaggerReaderHelpers.parseAllEndpoints({ api, sdkName, serviceName });
1760
1774
  if (CliParser.getSnippetOutputPath()) {
1761
1775
  try {
@@ -1870,7 +1884,8 @@ var CodeGenerator = class _CodeGenerator {
1870
1884
  };
1871
1885
  generatePublicOrAdmin(true);
1872
1886
  generatePublicOrAdmin(false);
1873
- const apiIndexBuff = templateApiIndex(serviceNameTitle, mainApiList);
1887
+ const isGenerateWebSocket = CliParser.isGenerateWebSocket();
1888
+ const apiIndexBuff = templateApiIndex(serviceNameTitle, mainApiList, isGenerateWebSocket);
1874
1889
  ParserUtils.writeApiMainFile(_CodeGenerator.srcFolder(), serviceNameTitle, apiIndexBuff);
1875
1890
  console.log("\nCOMPLETED\n----------\n\n");
1876
1891
  return { indexImports: indexImportsSet, queryImports: queryImportsSet };
@@ -1941,25 +1956,373 @@ var SwaggerDownloader = class _SwaggerDownloader {
1941
1956
  };
1942
1957
  };
1943
1958
 
1959
+ // src/WebsocketGenerator.ts
1960
+ var import_fs5 = __toESM(require("fs"));
1961
+ var import_path4 = __toESM(require("path"));
1962
+
1963
+ // src/templates/template-ws-class.ts
1964
+ var definitionToFunctionName = (type) => {
1965
+ if (type.endsWith("Request")) {
1966
+ return "send" + capitalize(type.slice(0, type.length - 7));
1967
+ }
1968
+ return type;
1969
+ };
1970
+ var renderSendFunction = (name, definition) => {
1971
+ const functionName = definitionToFunctionName(name);
1972
+ return `const ${functionName} = (data: Omit<Definitions.${capitalize(name)}, 'type'>) => {
1973
+ send({ type: '${name}', ...data })
1974
+ }`;
1975
+ };
1976
+ var templateWebsocketClass = (name, path8, definitions) => {
1977
+ const requestDefinitions = Object.keys(definitions).filter((key) => {
1978
+ const val = definitions[key];
1979
+ return val["x-type"] == "request";
1980
+ }).map((key) => [key, definitions[key]]);
1981
+ return `/* eslint-disable camelcase */
1982
+ /* eslint-disable no-inner-declarations */
1983
+ // @ts-ignore -> ts-expect-error TS6133
1984
+ import { AccelByteSDK, RefreshToken, SdkSetConfigParam } from '@accelbyte/sdk'
1985
+ import * as Definitions from './WebSocketDefinitions'
1986
+
1987
+ const messageParser = (data: string) => {
1988
+ const toVal = (str?: string) => {
1989
+ if (str) {
1990
+ if (str.startsWith('[') && str.endsWith(']')) {
1991
+ return str
1992
+ .slice(1, str.length - 1)
1993
+ .split(',')
1994
+ .filter(v => v !== '')
1995
+ }
1996
+ }
1997
+ return str
1998
+ }
1999
+
2000
+ const entries = data.split('\\n')
2001
+ .filter(line => line !== '')
2002
+ .map(line => {
2003
+ const [key, valStr] = line.split(': ')
2004
+ return [key, toVal(valStr)]
2005
+ })
2006
+
2007
+ return Object.fromEntries(entries)
2008
+ }
2009
+
2010
+ const messageSerializer = (data: Record<string, any>) => {
2011
+ return Object.keys(data)
2012
+ .map(key => {
2013
+ const toStr = (val: any) => {
2014
+ // array
2015
+ if (Array.isArray(val)) {
2016
+ return \`[\${String(val)}]\`
2017
+ }
2018
+ // null, undefined
2019
+ if (!val) {
2020
+ return ''
2021
+ }
2022
+ return String(val)
2023
+ }
2024
+ const val = data[key]
2025
+ const valStr = toStr(val)
2026
+
2027
+ return \`\${key}: \${valStr}\`
2028
+ })
2029
+ .join('\\n')
2030
+ }
2031
+
2032
+ export function WebSocketClass(sdk: AccelByteSDK, args?: SdkSetConfigParam) {
2033
+ const sdkAssembly = sdk.assembly()
2034
+ const baseURL = (args?.coreConfig?.baseURL ?? sdkAssembly.coreConfig.baseURL).replace('http', 'ws')
2035
+ const path = '${path8}'
2036
+ const url = baseURL + path
2037
+ let ws: WebSocket | null = null
2038
+ let isDisconnectManually = false
2039
+ const allowReconnect = sdkAssembly.webSocketConfig.allowReconnect ?? true
2040
+ const maxReconnectAttempts = sdkAssembly.webSocketConfig.maxReconnectAttempts ?? 0
2041
+ let reconnectAttempts = maxReconnectAttempts
2042
+
2043
+ const connect = () => {
2044
+ const token = sdk.getToken()
2045
+
2046
+ if (!token.accessToken) {
2047
+ console.warn('No access token, please login first')
2048
+ return
2049
+ }
2050
+
2051
+ if (!ws) {
2052
+ ws = new WebSocket(url, token.accessToken)
2053
+ }
2054
+ }
2055
+
2056
+ const refreshToken = async () => {
2057
+ const { refreshToken } = sdk.getToken()
2058
+ if (refreshToken) {
2059
+ const refresh = new RefreshToken({
2060
+ config: {
2061
+ axiosConfig: sdkAssembly.axiosConfig.request,
2062
+ clientId: sdkAssembly.coreConfig.clientId,
2063
+ refreshToken
2064
+ }
2065
+ })
2066
+ const result = await refresh.runWithLock()
2067
+ if (result) {
2068
+ sdk.setToken({
2069
+ accessToken: result.access_token,
2070
+ refreshToken: result.refresh_token
2071
+ })
2072
+ return true
2073
+ }
2074
+ }
2075
+ return false
2076
+ }
2077
+
2078
+ const handleReconnect = async (ev: CloseEvent) => {
2079
+ if (!allowReconnect || isDisconnectManually || !sdk.getToken().accessToken) return
2080
+ // token revoked
2081
+ if (ev.code === 4020) {
2082
+ await refreshToken()
2083
+ reconnectAttempts--
2084
+ connect()
2085
+ } else if (ev.code >= 1001 && ev.code <= 2999) {
2086
+ // Only reconnect if codes in range 1001-2999
2087
+ if (!ws || ws.readyState !== ws.OPEN) return
2088
+
2089
+ if (maxReconnectAttempts === 0) {
2090
+ setTimeout(() => {
2091
+ connect()
2092
+ }, 1000)
2093
+ } else if (reconnectAttempts !== 0) {
2094
+ setTimeout(() => {
2095
+ reconnectAttempts--
2096
+ connect()
2097
+ }, 1000)
2098
+ }
2099
+ }
2100
+ }
2101
+
2102
+ const disconnect = (code?: number, reason?: string) => {
2103
+ if (ws) {
2104
+ ws.close(code, reason)
2105
+ isDisconnectManually = true
2106
+ ws = null
2107
+ }
2108
+ }
2109
+
2110
+ const send = (message: Definitions.WebSocketRequest) => {
2111
+ if (ws) {
2112
+ ws.send(messageSerializer(message))
2113
+ }
2114
+ }
2115
+
2116
+ const sendRaw = (rawMessage: string) => {
2117
+ if (ws) {
2118
+ ws.send(rawMessage)
2119
+ }
2120
+ }
2121
+
2122
+ const onOpen = (cb: () => any) => {
2123
+ if (ws) {
2124
+ function listener(this: WebSocket, _ev: Event) {
2125
+ isDisconnectManually = false
2126
+ reconnectAttempts = maxReconnectAttempts
2127
+ cb()
2128
+ }
2129
+ ws.addEventListener('open', listener)
2130
+ return {
2131
+ removeEventListener: () => ws?.removeEventListener('open', listener)
2132
+ }
2133
+ }
2134
+ return {}
2135
+ }
2136
+
2137
+ const onClose = (cb: (ev: CloseEvent) => any) => {
2138
+ if (ws) {
2139
+ function listener(this: WebSocket, ev: CloseEvent) {
2140
+ handleReconnect(ev)
2141
+ cb(ev)
2142
+ }
2143
+ ws.addEventListener('close', listener)
2144
+ return {
2145
+ removeEventListener: () => ws?.removeEventListener('close', listener)
2146
+ }
2147
+ }
2148
+ return {}
2149
+ }
2150
+
2151
+ const onMessage = (cb: (message: Definitions.WebSocketResponseOrNotification | string) => any, raw: boolean = false) => {
2152
+ if (ws) {
2153
+ function listener(this: WebSocket, ev: MessageEvent<any>) {
2154
+ if (raw) {
2155
+ cb(ev.data)
2156
+ } else {
2157
+ const result = Definitions.WebSocketResponseOrNotification.parse(messageParser(ev.data))
2158
+ cb(result)
2159
+ }
2160
+ }
2161
+ ws.addEventListener('message', listener)
2162
+ return {
2163
+ removeEventListener: () => ws?.removeEventListener('message', listener)
2164
+ }
2165
+ }
2166
+ return {}
2167
+ }
2168
+
2169
+ const onError = (cb: (err: any) => any) => {
2170
+ if (ws) {
2171
+ function listener(this: WebSocket, err: any) {
2172
+ cb(err)
2173
+ }
2174
+ ws.addEventListener('error', listener)
2175
+ return {
2176
+ removeEventListener: () => ws?.removeEventListener('error', listener)
2177
+ }
2178
+ }
2179
+ return {}
2180
+ }
2181
+
2182
+ ${requestDefinitions.map(([name2, definition]) => renderSendFunction(name2, definition)).join(`
2183
+
2184
+ `)}
2185
+
2186
+ return {
2187
+ instance: ws,
2188
+ connect,
2189
+ disconnect,
2190
+ send,
2191
+ sendRaw,
2192
+ onOpen,
2193
+ onClose,
2194
+ onMessage,
2195
+ onError,
2196
+ ${requestDefinitions.map(([name2, _2]) => definitionToFunctionName(name2)).join(",\n ")}
2197
+ }
2198
+ }
2199
+
2200
+ `;
2201
+ };
2202
+
2203
+ // src/templates/template-ws-defintions.ts
2204
+ var renderZod = (property) => {
2205
+ switch (property.type) {
2206
+ case "string":
2207
+ return `z.coerce.string()`;
2208
+ case "integer":
2209
+ return `z.coerce.number()`;
2210
+ case "boolean":
2211
+ return `z.boolean()`;
2212
+ case "array":
2213
+ return `z.array(${renderZod(property.items)})`;
2214
+ default:
2215
+ return `z.any()`;
2216
+ }
2217
+ };
2218
+ var renderProperty = (name, type, property, required) => {
2219
+ const isRequired = required && required.includes(name);
2220
+ return `${name}: ${renderZod(property)}${isRequired || type != "request" ? "" : ".optional()"}`;
2221
+ };
2222
+ var renderDefinition = (name, definition) => {
2223
+ const capitalizedName = capitalize(name);
2224
+ if (definition.properties) {
2225
+ const properties = Object.entries(definition.properties);
2226
+ return `export const ${capitalizedName} = z.object({
2227
+ type: z.literal("${name}"),
2228
+ ${properties.map(([name2, property]) => renderProperty(name2, definition["x-type"], property, definition.required)).join(",\n ")}
2229
+ })
2230
+
2231
+ export type ${capitalizedName} = z.infer<typeof ${capitalizedName}>
2232
+ `;
2233
+ }
2234
+ return "";
2235
+ };
2236
+ var renderAllDefinitions = (definitions) => {
2237
+ if (definitions) {
2238
+ const definitionEntries = Object.entries(definitions);
2239
+ return definitionEntries.map(([name, definition]) => renderDefinition(name, definition)).join("\n\n");
2240
+ }
2241
+ return "";
2242
+ };
2243
+ var renderUnion = (type, definitions) => {
2244
+ if (definitions) {
2245
+ let capitalizedType = "";
2246
+ if (typeof type === "string") {
2247
+ capitalizedType = capitalize(type);
2248
+ } else {
2249
+ capitalizedType = type.map((t) => capitalize(t)).join("Or");
2250
+ }
2251
+ const filteredDefinitions = Object.entries(definitions).filter(([_2, def]) => {
2252
+ if (typeof type === "string") {
2253
+ return def["x-type"] === type;
2254
+ } else {
2255
+ return type.includes(def["x-type"]);
2256
+ }
2257
+ }).map(([name, _2]) => capitalize(name));
2258
+ return `export const WebSocket${capitalizedType} = z.discriminatedUnion("type", [
2259
+ ${filteredDefinitions.join(",\n ")}
2260
+ ])
2261
+
2262
+ export type WebSocket${capitalizedType} = z.infer<typeof WebSocket${capitalizedType}>`;
2263
+ }
2264
+ return "";
2265
+ };
2266
+ var templateWebsocketDefinitions = (definitions) => {
2267
+ return `/**
2268
+ * AUTO GENERATED
2269
+ */
2270
+
2271
+ import { z } from 'zod'
2272
+
2273
+ ${renderAllDefinitions(definitions)}
2274
+
2275
+ ${renderUnion("request", definitions)}
2276
+
2277
+ ${renderUnion(["response", "notification"], definitions)}
2278
+ `;
2279
+ };
2280
+
2281
+ // src/WebsocketGenerator.ts
2282
+ var WebsocketGenerator = class {
2283
+ static srcFolder = () => CliParser.getOutputPath();
2284
+ static outputFolder = () => import_path4.default.join(this.srcFolder(), "generated-websocket");
2285
+ static schemaContent = () => {
2286
+ const fileContent = JSON.parse(import_fs5.default.readFileSync(CliParser.getWebSocketSchemaPath(), "utf8"));
2287
+ return fileContent;
2288
+ };
2289
+ static prepareDirs = () => {
2290
+ ParserUtils.mkdirIfNotExist(this.outputFolder());
2291
+ };
2292
+ static main = () => {
2293
+ const { name, path: wsPath, definitions } = this.schemaContent();
2294
+ const templateDefinitions = templateWebsocketDefinitions(definitions);
2295
+ this.prepareDirs();
2296
+ const filePath = import_path4.default.join(this.outputFolder(), "WebSocketDefinitions.ts");
2297
+ import_fs5.default.writeFileSync(filePath, templateDefinitions, "utf8");
2298
+ const templateClass2 = templateWebsocketClass(name, wsPath, definitions);
2299
+ const filePathClass = import_path4.default.join(this.outputFolder(), "WebSocketClass.ts");
2300
+ import_fs5.default.writeFileSync(filePathClass, templateClass2, "utf8");
2301
+ };
2302
+ };
2303
+
1944
2304
  // src/cli.ts
1945
2305
  var generateSdk = async () => {
1946
2306
  const arrayOfSets = await Promise.all(CliParser.getConfigFile().map((config) => CodeGenerator.main(config)));
1947
2307
  if (CliParser.isGenerateSnippetOnly()) {
1948
2308
  return;
1949
2309
  }
2310
+ if (CliParser.isGenerateWebSocket()) {
2311
+ WebsocketGenerator.main();
2312
+ }
1950
2313
  const indexImportsSet = /* @__PURE__ */ new Set();
1951
2314
  const queryImportsSet = /* @__PURE__ */ new Set();
1952
2315
  const filenamesSet = /* @__PURE__ */ new Set();
1953
2316
  for (const set of arrayOfSets) {
1954
2317
  set.indexImports.forEach((value) => {
1955
- const fileName = import_path4.default.basename(value);
2318
+ const fileName = import_path5.default.basename(value);
1956
2319
  if (!filenamesSet.has(fileName)) {
1957
2320
  indexImportsSet.add(value);
1958
2321
  filenamesSet.add(fileName);
1959
2322
  }
1960
2323
  });
1961
2324
  set.queryImports.forEach((value) => {
1962
- const fileName = import_path4.default.basename(value);
2325
+ const fileName = import_path5.default.basename(value);
1963
2326
  if (!filenamesSet.has(fileName)) {
1964
2327
  queryImportsSet.add(value);
1965
2328
  }
@@ -1980,30 +2343,39 @@ import_yargs.default.command("download-swaggers", "Download swaggers JSON files"
1980
2343
  CliParser.createInstance(yargs2);
1981
2344
  SwaggerDownloader.main();
1982
2345
  }).command("generate-code", "Generate code based on downloaded swagger files", async (yargs2) => {
1983
- yargs2.check(({ output }) => {
1984
- if (!output?.trim()) {
2346
+ yargs2.check(({ output, snippetOnly, snippetOutput }) => {
2347
+ if (!output?.trim() && !snippetOnly) {
1985
2348
  throw new Error("output is required for generate-code");
1986
2349
  }
2350
+ if (snippetOnly && !snippetOutput) {
2351
+ throw new Error("snippetOutput is required when generating snippets.");
2352
+ }
1987
2353
  return true;
1988
2354
  });
1989
2355
  CliParser.createInstance(yargs2);
1990
2356
  await generateSdk();
1991
2357
  }).option("config", {
1992
- description: "Config file providing backend services URL.",
2358
+ description: "Path to the config file with backend service URLs.",
1993
2359
  type: "string",
1994
2360
  demandOption: true
1995
2361
  }).option("swaggersOutput", {
1996
- description: "Output path for downloaded swaggers JSON files.",
2362
+ description: "Directory to save the downloaded Swagger JSON files.",
1997
2363
  type: "string",
1998
2364
  demandOption: true
1999
2365
  }).option("output", {
2000
- description: "Output path for generated code. Required for generate-code",
2366
+ description: "Directory for the generated code. Required when using the generate-code command.",
2001
2367
  type: "string"
2002
2368
  }).option("skipReactQuery", {
2003
- description: "Skip generating react query",
2369
+ description: "Disable React Query code generation.",
2004
2370
  type: "boolean"
2005
2371
  }).option("snippetOnly", {
2006
- description: "Only generate snippet",
2372
+ description: "Generate only code snippets.",
2007
2373
  type: "boolean"
2374
+ }).option("snippetOutput", {
2375
+ description: "Directory for the generated code snippets. Required when generating snippets.",
2376
+ type: "string"
2377
+ }).option("webSocketSchema", {
2378
+ description: "Path to the WebSocket schema file (schema.json). If provided, WebSocket methods will be generated based on the schema.",
2379
+ type: "string"
2008
2380
  }).demandCommand(1).help().argv;
2009
2381
  //# sourceMappingURL=accelbyte-codegen.js.map