@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.
@@ -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((path7) => {
305
- const start = path7.indexOf("{") + 1;
306
- const end = path7.indexOf("}");
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 = path7.slice(start, end).trim();
314
+ const importName = path8.slice(start, end).trim();
309
315
  return body.includes(importName);
310
316
  }
311
317
  return false;
312
- }).map((path7) => path7).join("\n") + "\n";
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(path7) {
330
- const version2_3_4_etc = path7.match(/\/v([2-9]|[1-9]\d+)\/+/);
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: path7, httpMethod, isForm, existingMethods, permissionType }) => {
526
- let path_ = path7;
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" && !(path7.slice(-1) === "}");
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(path7);
576
- generatedMethod = resolveConflicts({ path: path7, generatedMethod, testedGeneratedMethod, existingMethods });
577
- generatedMethod = generatedMethod + _ParserUtils.getVersionSuffixFromPath(path7);
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, path7) => {
733
- const params = path7.match(/{\w*}/g) || [];
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: path7, generatedMethod, testedGeneratedMethod, existingMethods }) => {
763
+ var resolveConflicts = ({ path: path8, generatedMethod, testedGeneratedMethod, existingMethods }) => {
758
764
  let _testedGenMethod = testedGeneratedMethod;
759
765
  try {
760
- testConflict(path7, _testedGenMethod, existingMethods);
766
+ testConflict(path8, _testedGenMethod, existingMethods);
761
767
  } catch (e) {
762
- if (path7.indexOf("/namespaces/") >= 0) {
768
+ if (path8.indexOf("/namespaces/") >= 0) {
763
769
  generatedMethod += "_ByNS";
764
770
  _testedGenMethod += "_ByNS";
765
771
  }
766
772
  }
767
773
  try {
768
- testConflict(path7, _testedGenMethod, existingMethods);
774
+ testConflict(path8, _testedGenMethod, existingMethods);
769
775
  } catch (e) {
770
- if (path7.indexOf("/admin/") >= 0) {
776
+ if (path8.indexOf("/admin/") >= 0) {
771
777
  generatedMethod += "_admin";
772
778
  _testedGenMethod += "_admin";
773
779
  }
774
780
  }
775
- testConflict(path7, _testedGenMethod, existingMethods);
781
+ testConflict(path8, _testedGenMethod, existingMethods);
776
782
  return generatedMethod;
777
783
  };
778
- var testConflict = (path7, generatedMethod, existingMethods) => {
784
+ var testConflict = (path8, generatedMethod, existingMethods) => {
779
785
  if (existingMethods[generatedMethod]) {
780
- const conflictingMethod = { path: path7, generatedMethod };
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: path7,
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 = `'${path7}'`;
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 (path7.match(`{${pathParam.name}}`)) {
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__${path7}'`, "--header 'accept: application/json'"];
925
+ const snippetShellArgs = ["--location --request", `${httpMethod} '__DOMAIN__${path8}'`, "--header 'accept: application/json'"];
920
926
  const snippetApiArgs = [];
921
- if (xSecurity !== void 0 || path7.includes("/admin")) {
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: path7,
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 = `'${path7}'`;
975
+ let newPath = `'${path8}'`;
970
976
  let importStatements = [];
971
- const sortedPathParams = ParserUtils.sortPathParamsByPath(pathParams, path7);
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 (path7.match(`{${pathParam.name}}`)) {
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: path7,
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) => path7.includes(p)) || path7.endsWith("/list"));
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 = `'${path7}'`;
1059
- const sortedPathParams = ParserUtils.sortPathParamsByPath(pathParams, path7);
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 (path7.match(`{${pathParam.name}}`)) {
1073
+ if (path8.match(`{${pathParam.name}}`)) {
1068
1074
  if (type === "string") {
1069
1075
  newPath = `${newPath}.replace('{${pathParam.name}}', ${pName})`;
1070
1076
  } else {
@@ -1203,7 +1209,7 @@ import { ${serviceNameTitle} } from '@accelbyte/sdk-${serviceNameTitle.toLowerCa
1203
1209
 
1204
1210
  const sdk = AccelByte.SDK({
1205
1211
  coreConfig: {
1206
- baseURL: 'https://demo.accelbyte.io',
1212
+ baseURL: '__DOMAIN__',
1207
1213
  clientId: '77f88506b6174c3ea4d925f5b4096ce8',
1208
1214
  namespace: 'accelbyte',
1209
1215
  redirectURI: 'http://localhost:3030'
@@ -1233,7 +1239,7 @@ var normalizeMethodSnippet = (methodInput, splitWord) => {
1233
1239
  };
1234
1240
 
1235
1241
  // src/helpers/SwaggerReaderHelpers.ts
1236
- var GIT_URL = "https://github.com/AccelByte/accelbyte-web-sdk/blob/main/packages";
1242
+ var GIT_URL = "https://github.com/AccelByte/accelbyte-typescript-sdk/blob/main/packages";
1237
1243
  var SwaggerReaderHelpers = class _SwaggerReaderHelpers {
1238
1244
  static getServicePrefix = (servicePaths) => servicePaths[servicePaths.length - 1].split("/")[1];
1239
1245
  static parseAllEndpoints = async ({
@@ -1280,11 +1286,11 @@ var SwaggerReaderHelpers = class _SwaggerReaderHelpers {
1280
1286
  admin: {},
1281
1287
  public: {}
1282
1288
  };
1283
- for (const [path7, operation] of sortedPathsByLength) {
1284
- if (path7.indexOf("/healthz") >= 0) {
1289
+ for (const [path8, operation] of sortedPathsByLength) {
1290
+ if (path8.indexOf("/healthz") >= 0) {
1285
1291
  continue;
1286
1292
  }
1287
- const isAdminEndpoint = path7.indexOf("/admin/") > -1;
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: path7, httpMethod }, null, 2));
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 ?? ""}${path7}`;
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: path7,
1322
+ path: path8,
1317
1323
  httpMethod,
1318
1324
  isForm,
1319
1325
  existingMethods: tagToClassMethodsMapByType[tag],
1320
1326
  permissionType
1321
1327
  });
1322
- tagToClassMethodsMapByType[tag][classMethod] = `${path7} ${httpMethod}`;
1323
- generatedMethods[`${path7} ${httpMethod}`] = `${classMethod}`;
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
@@ -1733,7 +1745,9 @@ var CodeGenerator = class _CodeGenerator {
1733
1745
  const queryImportsSet = /* @__PURE__ */ new Set();
1734
1746
  const apiInfo = { ...api.info, "x-version": api["x-version"]?.version };
1735
1747
  console.log("----------\nGenerating API:", { title: apiInfo.title, version: apiInfo.version });
1736
- ParserUtils.writeXVersion(_CodeGenerator.srcFolder(), api["x-version"], api.info);
1748
+ if (!CliParser.isGenerateSnippetOnly()) {
1749
+ ParserUtils.writeXVersion(_CodeGenerator.srcFolder(), api["x-version"], api.info);
1750
+ }
1737
1751
  const parsedInformation = await SwaggerReaderHelpers.parseAllEndpoints({ api, sdkName, serviceName });
1738
1752
  if (CliParser.getSnippetOutputPath()) {
1739
1753
  try {
@@ -1848,7 +1862,8 @@ var CodeGenerator = class _CodeGenerator {
1848
1862
  };
1849
1863
  generatePublicOrAdmin(true);
1850
1864
  generatePublicOrAdmin(false);
1851
- const apiIndexBuff = templateApiIndex(serviceNameTitle, mainApiList);
1865
+ const isGenerateWebSocket = CliParser.isGenerateWebSocket();
1866
+ const apiIndexBuff = templateApiIndex(serviceNameTitle, mainApiList, isGenerateWebSocket);
1852
1867
  ParserUtils.writeApiMainFile(_CodeGenerator.srcFolder(), serviceNameTitle, apiIndexBuff);
1853
1868
  console.log("\nCOMPLETED\n----------\n\n");
1854
1869
  return { indexImports: indexImportsSet, queryImports: queryImportsSet };
@@ -1919,25 +1934,373 @@ var SwaggerDownloader = class _SwaggerDownloader {
1919
1934
  };
1920
1935
  };
1921
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
+
1922
2282
  // src/cli.ts
1923
2283
  var generateSdk = async () => {
1924
2284
  const arrayOfSets = await Promise.all(CliParser.getConfigFile().map((config) => CodeGenerator.main(config)));
1925
2285
  if (CliParser.isGenerateSnippetOnly()) {
1926
2286
  return;
1927
2287
  }
2288
+ if (CliParser.isGenerateWebSocket()) {
2289
+ WebsocketGenerator.main();
2290
+ }
1928
2291
  const indexImportsSet = /* @__PURE__ */ new Set();
1929
2292
  const queryImportsSet = /* @__PURE__ */ new Set();
1930
2293
  const filenamesSet = /* @__PURE__ */ new Set();
1931
2294
  for (const set of arrayOfSets) {
1932
2295
  set.indexImports.forEach((value) => {
1933
- const fileName = path6.basename(value);
2296
+ const fileName = path7.basename(value);
1934
2297
  if (!filenamesSet.has(fileName)) {
1935
2298
  indexImportsSet.add(value);
1936
2299
  filenamesSet.add(fileName);
1937
2300
  }
1938
2301
  });
1939
2302
  set.queryImports.forEach((value) => {
1940
- const fileName = path6.basename(value);
2303
+ const fileName = path7.basename(value);
1941
2304
  if (!filenamesSet.has(fileName)) {
1942
2305
  queryImportsSet.add(value);
1943
2306
  }
@@ -1958,30 +2321,39 @@ yargs.command("download-swaggers", "Download swaggers JSON files", (yargs2) => {
1958
2321
  CliParser.createInstance(yargs2);
1959
2322
  SwaggerDownloader.main();
1960
2323
  }).command("generate-code", "Generate code based on downloaded swagger files", async (yargs2) => {
1961
- yargs2.check(({ output }) => {
1962
- if (!output?.trim()) {
2324
+ yargs2.check(({ output, snippetOnly, snippetOutput }) => {
2325
+ if (!output?.trim() && !snippetOnly) {
1963
2326
  throw new Error("output is required for generate-code");
1964
2327
  }
2328
+ if (snippetOnly && !snippetOutput) {
2329
+ throw new Error("snippetOutput is required when generating snippets.");
2330
+ }
1965
2331
  return true;
1966
2332
  });
1967
2333
  CliParser.createInstance(yargs2);
1968
2334
  await generateSdk();
1969
2335
  }).option("config", {
1970
- description: "Config file providing backend services URL.",
2336
+ description: "Path to the config file with backend service URLs.",
1971
2337
  type: "string",
1972
2338
  demandOption: true
1973
2339
  }).option("swaggersOutput", {
1974
- description: "Output path for downloaded swaggers JSON files.",
2340
+ description: "Directory to save the downloaded Swagger JSON files.",
1975
2341
  type: "string",
1976
2342
  demandOption: true
1977
2343
  }).option("output", {
1978
- description: "Output path for generated code. Required for generate-code",
2344
+ description: "Directory for the generated code. Required when using the generate-code command.",
1979
2345
  type: "string"
1980
2346
  }).option("skipReactQuery", {
1981
- description: "Skip generating react query",
2347
+ description: "Disable React Query code generation.",
1982
2348
  type: "boolean"
1983
2349
  }).option("snippetOnly", {
1984
- description: "Only generate snippet",
2350
+ description: "Generate only code snippets.",
1985
2351
  type: "boolean"
2352
+ }).option("snippetOutput", {
2353
+ description: "Directory for the generated code snippets. Required when generating snippets.",
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"
1986
2358
  }).demandCommand(1).help().argv;
1987
2359
  //# sourceMappingURL=accelbyte-codegen.mjs.map