@accelbyte/codegen 0.0.0-dev-20260320085237 → 0.0.0-dev-20260406042959

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 CHANGED
@@ -124,14 +124,16 @@ Place an `abcodegen.config.ts` file next to your `swaggers.json` to customize co
124
124
 
125
125
  ```typescript
126
126
  // abcodegen.config.ts
127
+ import { type CodegenConfigOptions } from '@accelbyte/codegen'
128
+
127
129
  export default {
128
130
  // Override the base path prepended to all API routes.
129
131
  // Default: uses basePath from the swagger spec.
130
132
  basePath: '/custom',
131
133
 
132
- // Skip generation of barrel index files (index.ts, all-query-imports.ts).
134
+ // Generate barrel index files (index.ts, all-imports.ts, all-query-imports.ts).
133
135
  // Default: true
134
- unstable_shouldProduceIndexFile: false,
136
+ unstable_shouldProduceIndexFiles: false,
135
137
 
136
138
  // Force specific definitions to emit `z.any()` instead of a full schema.
137
139
  // Keyed by definition file name. Value can be `true` or a function receiving the schema.
@@ -139,7 +141,7 @@ export default {
139
141
  ProtobufAny: true,
140
142
  SomeOther: (schema) => schema.properties?.['@type'] !== undefined
141
143
  }
142
- }
144
+ } satisfies CodegenConfigOptions
143
145
  ```
144
146
 
145
147
  ## Design Decisions
@@ -156,4 +158,10 @@ This triggers `@typescript-eslint/no-empty-object-type`. That rule guards agains
156
158
  files: ['src/generated-definitions/**'],
157
159
  rules: { '@typescript-eslint/no-empty-object-type': 'off' }
158
160
  }
159
- ```
161
+ ```
162
+
163
+ ## Troubleshooting
164
+
165
+ ### Type or lint errors in generated files
166
+
167
+ The generated code aims to use neutral, unopinionated style defaults. However, some generated syntax may conflict with your tsconfig or linter settings. In that case, you can ignore specific lint rules in the codegen folder, or create a `tsconfig.json` inside it to override your top-level configuration.
@@ -0,0 +1,22 @@
1
+ interface CodegenConfigOptions {
2
+ /**
3
+ * Force specific definitions to emit `z.any()` instead of a full schema.
4
+ * Keyed by definition file name. Value can be `true` or a function receiving the schema.
5
+ *
6
+ * @example
7
+ * { ProtobufAny: true, SomeOther: (schema) => schema.properties?.['@type'] !== undefined }
8
+ */
9
+ unstable_overrideAsAny?: Record<string, boolean | ((schema: Record<string, any>) => boolean)>;
10
+ /**
11
+ * Generate barrel index files (index.ts, all-imports.ts, all-query-imports.ts).
12
+ * @default true
13
+ */
14
+ unstable_shouldProduceIndexFiles?: boolean;
15
+ /**
16
+ * Override the base path prepended to all API routes.
17
+ * @default `basePath` from the swagger spec
18
+ */
19
+ basePath?: string;
20
+ }
21
+
22
+ export type { CodegenConfigOptions };
@@ -0,0 +1,22 @@
1
+ interface CodegenConfigOptions {
2
+ /**
3
+ * Force specific definitions to emit `z.any()` instead of a full schema.
4
+ * Keyed by definition file name. Value can be `true` or a function receiving the schema.
5
+ *
6
+ * @example
7
+ * { ProtobufAny: true, SomeOther: (schema) => schema.properties?.['@type'] !== undefined }
8
+ */
9
+ unstable_overrideAsAny?: Record<string, boolean | ((schema: Record<string, any>) => boolean)>;
10
+ /**
11
+ * Generate barrel index files (index.ts, all-imports.ts, all-query-imports.ts).
12
+ * @default true
13
+ */
14
+ unstable_shouldProduceIndexFiles?: boolean;
15
+ /**
16
+ * Override the base path prepended to all API routes.
17
+ * @default `basePath` from the swagger spec
18
+ */
19
+ basePath?: string;
20
+ }
21
+
22
+ export type { CodegenConfigOptions };
@@ -21,8 +21,11 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
21
21
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
22
  mod
23
23
  ));
24
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
24
25
 
25
26
  // src/cli.ts
27
+ var cli_exports = {};
28
+ module.exports = __toCommonJS(cli_exports);
26
29
  var import_path6 = __toESM(require("path"));
27
30
  var import_yargs = __toESM(require("yargs"));
28
31
 
@@ -105,8 +108,8 @@ var CodegenConfig = class _CodegenConfig {
105
108
  const loaded = await import((0, import_url.pathToFileURL)(configPath).href);
106
109
  _CodegenConfig.config = loaded.default ?? loaded ?? {};
107
110
  }
108
- static shouldProduceIndexFile() {
109
- return _CodegenConfig.config.unstable_shouldProduceIndexFile ?? true;
111
+ static shouldProduceIndexFiles() {
112
+ return _CodegenConfig.config.unstable_shouldProduceIndexFiles ?? true;
110
113
  }
111
114
  static getBasePath() {
112
115
  return _CodegenConfig.config.basePath;
@@ -194,7 +197,8 @@ var getResponseType = ({
194
197
  defaultType = "unknown"
195
198
  }) => {
196
199
  const responseClass = responseClasses.length === 1 ? responseClasses?.[0] : "unknown";
197
- const responseType = responseClass !== "unknown" ? responseClasses?.[0] : defaultType;
200
+ const rawResponseType = responseClass !== "unknown" ? responseClasses?.[0] : defaultType;
201
+ const responseType = rawResponseType === "__dictionary__" ? "Record<string, any>" : rawResponseType;
198
202
  return {
199
203
  responseType,
200
204
  responseTypeInAxiosResponse: `Promise<AxiosResponse<${responseType}>>`,
@@ -240,13 +244,28 @@ var generateImports = (body, importStatements, makeNewImportVarMap3, getImportab
240
244
  ${importStatements.sort().join("\n")}`;
241
245
  };
242
246
  var templateClass = (className, body, importStatements) => {
247
+ const attributes = {
248
+ definitions: ["private axiosInstance: AxiosInstance", "private namespace: string", "private useSchemaValidation: boolean"],
249
+ assignments: ["this.axiosInstance = axiosInstance", "this.namespace = namespace", "this.useSchemaValidation = useSchemaValidation"]
250
+ };
251
+ let namespaceConstructor = "namespace";
252
+ if (!body.includes(".replace('{namespace}', this.namespace)")) {
253
+ namespaceConstructor = "_namespace";
254
+ attributes.definitions.splice(1, 1);
255
+ attributes.assignments.splice(1, 1);
256
+ }
243
257
  return `/**
244
258
  * AUTO GENERATED
245
259
  */
246
260
  ${generateImports(body, importStatements, makeNewImportVarMap(), getImportableVarMap(), CLASS_TYPE_ONLY_VARS)}
247
261
 
248
262
  export class ${className} {
249
- constructor(private axiosInstance: AxiosInstance, private namespace: string, private useSchemaValidation = true) {}
263
+ ${attributes.definitions.join("\n")}
264
+
265
+ constructor(axiosInstance: AxiosInstance, ${namespaceConstructor}: string, useSchemaValidation = true) {
266
+ ${attributes.assignments.join("\n")}
267
+ }
268
+
250
269
  ${body}
251
270
  }
252
271
  `;
@@ -499,13 +518,14 @@ var ParserUtils = class _ParserUtils {
499
518
  };
500
519
  static parseRefImport = (bodyParam) => {
501
520
  const $ref = bodyParam?.schema?.$ref || bodyParam?.schema?.items?.$ref;
502
- if (!$ref) {
521
+ if (!$ref || $ref.endsWith("__dictionary__")) {
503
522
  return null;
504
523
  }
505
524
  const type = _ParserUtils.parseRefType($ref);
506
525
  return `import { ${type} } from '../../generated-definitions/${type}.js'`;
507
526
  };
508
527
  static parseRefType = ($ref) => {
528
+ if ($ref.endsWith("__dictionary__")) return "__dictionary__";
509
529
  let ref = $ref.replace(".", "/");
510
530
  if (ref[ref.length - 1] === "." || ref[ref.length - 1] === "/") {
511
531
  ref = ref.slice(0, -1);
@@ -703,6 +723,7 @@ var ParserUtils = class _ParserUtils {
703
723
  return queryFileName;
704
724
  }
705
725
  static writeXVersion(distDir, xversionJson, apiInfo) {
726
+ import_fs4.default.mkdirSync(distDir, { recursive: true });
706
727
  if (xversionJson) {
707
728
  console.log("x-version:", xversionJson);
708
729
  import_fs4.default.writeFileSync(`${distDir}/version.json`, JSON.stringify(xversionJson, null, 2));
@@ -1077,6 +1098,7 @@ var templateMethod = ({
1077
1098
  let dataType = null;
1078
1099
  if (httpMethod !== "get") {
1079
1100
  dataType = ParserUtils.parseBodyParamsType(bodyParams);
1101
+ if (dataType === "__dictionary__") dataType = "Record<string, any>";
1080
1102
  importStatements = ParserUtils.parseBodyParamsImports(bodyParams);
1081
1103
  methodParams += dataType ? `data: ${dataType},` : "";
1082
1104
  methodParamsNoTypes += dataType ? `data,` : "";
@@ -1100,7 +1122,7 @@ var templateMethod = ({
1100
1122
  }
1101
1123
  const isFileUpload = methodParams.indexOf("data: {file") > -1;
1102
1124
  const { responseType, responseTypeInResponse } = getResponseType({ responseClasses });
1103
- const resolvedResponseClassValidated = responseType !== "unknown" ? `${responseType}` : "z.unknown()";
1125
+ const resolvedResponseClassValidated = responseClasses.length === 1 && responseClasses[0] === "__dictionary__" ? "z.record(z.string(), z.any())" : responseType !== "unknown" ? `${responseType}` : "z.unknown()";
1104
1126
  methodParams = (queryParamsType ? `${methodParams} ${queryParamsType}` : methodParams).replace(/,\s*$/, "");
1105
1127
  methodParamsNoTypes = queryParamsType ? `${methodParamsNoTypes} queryParams` : methodParamsNoTypes;
1106
1128
  const isGuardInvoked = ["get", "post", "put", "patch", "delete"].includes(httpMethod);
@@ -1444,7 +1466,7 @@ var SwaggerReaderHelpers = class _SwaggerReaderHelpers {
1444
1466
  const responseClass = responseClasses.length > 1 ? null : responseClasses?.[0];
1445
1467
  const { className, classGenName } = ParserUtils.generateClassName(tag, isAdminEndpoint);
1446
1468
  tagToClassImportsRecord[className] = tagToClassImportsRecord[className] ? tagToClassImportsRecord[className] : {};
1447
- if (responseClass) {
1469
+ if (responseClass && responseClass !== "__dictionary__") {
1448
1470
  tagToClassImportsRecord[className][responseClass] = `import { ${responseClass} } from '../../generated-definitions/${responseClass}.js'`;
1449
1471
  }
1450
1472
  if (responseClass && responseClass.endsWith("Array")) {
@@ -1692,7 +1714,14 @@ ${exportedTypeString}
1692
1714
  };
1693
1715
  } else if (type) {
1694
1716
  if (type === "object" && definition.additionalProperties) {
1695
- const zodAttribute = this.parseToZodAttribute("", definition.additionalProperties, [""]);
1717
+ const additionalProps = definition.additionalProperties;
1718
+ if (Object.keys(additionalProps).length === 0) {
1719
+ return {
1720
+ schemaString: `${schemaAttribute} z.record(z.any())${schemaRequired}`,
1721
+ typeString: `${typeAttribute} Record<string, any>${typeNullishability}`
1722
+ };
1723
+ }
1724
+ const zodAttribute = this.parseToZodAttribute("", additionalProps, [""]);
1696
1725
  return {
1697
1726
  schemaString: `${schemaAttribute} z.record(${zodAttribute.schemaString})${schemaRequired}`,
1698
1727
  typeString: `${typeAttribute} Record<string, ${zodAttribute.typeString}>${typeNullishability}`
@@ -1963,7 +1992,7 @@ var CodeGenerator = class _CodeGenerator {
1963
1992
  );
1964
1993
  }
1965
1994
  mainApiList.push(...apiList);
1966
- if (CodegenConfig.shouldProduceIndexFile()) {
1995
+ if (CodegenConfig.shouldProduceIndexFiles()) {
1967
1996
  indexImportsSet.add(
1968
1997
  ParserUtils.getRelativePathToWebSdkSrcFolder(import_path4.default.join(_CodeGenerator.srcFolder(), serviceNameTitle), targetSrcFolder)
1969
1998
  );
@@ -1973,6 +2002,7 @@ var CodeGenerator = class _CodeGenerator {
1973
2002
  const duplicates = /* @__PURE__ */ new Map();
1974
2003
  const definitions = api2?.components?.schemas || api2.definitions;
1975
2004
  for (const ref in definitions) {
2005
+ if (ref === "__dictionary__") continue;
1976
2006
  const definition = definitions[ref];
1977
2007
  const fileName = ParserUtils.parseRefType(ref);
1978
2008
  const fileExist = import_fs5.default.existsSync(import_path4.default.join(DIST_DEFINITION_DIR, `${fileName}.ts`));
@@ -1997,7 +2027,7 @@ var CodeGenerator = class _CodeGenerator {
1997
2027
  };
1998
2028
  generatePublicOrAdmin(true);
1999
2029
  generatePublicOrAdmin(false);
2000
- if (CodegenConfig.shouldProduceIndexFile()) {
2030
+ if (CodegenConfig.shouldProduceIndexFiles()) {
2001
2031
  const isGenerateWebSocket = CliParser.isGenerateWebSocket();
2002
2032
  const apiIndexBuff = templateApiIndex(serviceNameTitle, mainApiList, isGenerateWebSocket);
2003
2033
  ParserUtils.writeApiMainFile(_CodeGenerator.srcFolder(), serviceNameTitle, apiIndexBuff);
@@ -2028,6 +2058,7 @@ var SwaggerDownloader = class _SwaggerDownloader {
2028
2058
  fs6.readFile(filePath, "utf8", (err, data) => {
2029
2059
  if (err) throw err;
2030
2060
  let result = data;
2061
+ result = result.replace(new RegExp("map%5Bstring%5Dinterface%20%7B%7D", "g"), "__dictionary__").replace(new RegExp("map\\[string\\]interface \\{\\}", "g"), "__dictionary__").replace(new RegExp("map\\[string\\]any", "g"), "__dictionary__");
2031
2062
  searchStr.forEach((s) => {
2032
2063
  result = result.replace(new RegExp(s, "g"), " ");
2033
2064
  });
@@ -2425,6 +2456,9 @@ var generateSdk = async () => {
2425
2456
  if (CliParser.isGenerateWebSocket()) {
2426
2457
  WebsocketGenerator.main();
2427
2458
  }
2459
+ if (!CodegenConfig.shouldProduceIndexFiles()) {
2460
+ return;
2461
+ }
2428
2462
  const indexImportsSet = /* @__PURE__ */ new Set();
2429
2463
  const queryImportsSet = /* @__PURE__ */ new Set();
2430
2464
  const filenamesSet = /* @__PURE__ */ new Set();