@cerios/openapi-to-zod 1.0.0 → 1.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/dist/cli.mjs CHANGED
@@ -5136,8 +5136,20 @@ var init_batch_executor = __esm({
5136
5136
  });
5137
5137
 
5138
5138
  // src/utils/name-utils.ts
5139
+ function sanitizeIdentifier(str) {
5140
+ return str.replace(/[^a-zA-Z0-9._\-\s]+/g, "_");
5141
+ }
5139
5142
  function toCamelCase(str, options) {
5140
- let name = str.charAt(0).toLowerCase() + str.slice(1);
5143
+ const sanitized = sanitizeIdentifier(str);
5144
+ const words = sanitized.split(/[.\-_\s]+/).filter((word) => word.length > 0);
5145
+ let name;
5146
+ if (words.length === 0) {
5147
+ name = str.charAt(0).toLowerCase() + str.slice(1);
5148
+ } else if (words.length === 1) {
5149
+ name = words[0].charAt(0).toLowerCase() + words[0].slice(1);
5150
+ } else {
5151
+ name = words[0].charAt(0).toLowerCase() + words[0].slice(1) + words.slice(1).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
5152
+ }
5141
5153
  if (options == null ? void 0 : options.prefix) {
5142
5154
  const prefix = options.prefix.toLowerCase();
5143
5155
  name = prefix + name.charAt(0).toUpperCase() + name.slice(1);
@@ -5150,12 +5162,23 @@ function toCamelCase(str, options) {
5150
5162
  }
5151
5163
  function toPascalCase(str) {
5152
5164
  const stringValue = String(str);
5153
- let result = stringValue.replace(/[^a-zA-Z0-9_]+/g, "_").split(/[-_]+/).filter((word) => word.length > 0).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join("");
5165
+ const isAlreadyValidCase = /^[a-zA-Z][a-zA-Z0-9]*$/.test(stringValue);
5166
+ if (isAlreadyValidCase) {
5167
+ return stringValue.charAt(0).toUpperCase() + stringValue.slice(1);
5168
+ }
5169
+ const sanitized = sanitizeIdentifier(stringValue);
5170
+ const words = sanitized.split(/[.\-_\s]+/).filter((word) => word.length > 0);
5171
+ let result;
5172
+ if (words.length === 0) {
5173
+ result = "Value";
5174
+ } else {
5175
+ result = words.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
5176
+ }
5154
5177
  if (/^\d/.test(result)) {
5155
5178
  result = `N${result}`;
5156
5179
  }
5157
5180
  if (!result || /^_+$/.test(result)) {
5158
- result = "Value";
5181
+ return "Value";
5159
5182
  }
5160
5183
  return result;
5161
5184
  }
@@ -5173,9 +5196,10 @@ var init_name_utils = __esm({
5173
5196
  // src/generators/enum-generator.ts
5174
5197
  function generateEnum(name, values, options) {
5175
5198
  const schemaName = `${toCamelCase(name, options)}Schema`;
5199
+ const typeName = toPascalCase(name);
5176
5200
  const enumValues = values.map((v) => `"${v}"`).join(", ");
5177
5201
  const schemaCode = `export const ${schemaName} = z.enum([${enumValues}]);`;
5178
- const typeCode = `export type ${name} = z.infer<typeof ${schemaName}>;`;
5202
+ const typeCode = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
5179
5203
  return { schemaCode, typeCode };
5180
5204
  }
5181
5205
  var init_enum_generator = __esm({
@@ -5335,6 +5359,82 @@ var init_lru_cache = __esm({
5335
5359
  }
5336
5360
  });
5337
5361
 
5362
+ // src/utils/pattern-utils.ts
5363
+ function isRegexPattern(pattern) {
5364
+ if (pattern.startsWith("^") || pattern.endsWith("$")) {
5365
+ return true;
5366
+ }
5367
+ if (/\\[dDwWsS]/.test(pattern)) {
5368
+ return true;
5369
+ }
5370
+ if (/\.\*|\.\+/.test(pattern)) {
5371
+ return true;
5372
+ }
5373
+ if (/[[\]()]/.test(pattern)) {
5374
+ return true;
5375
+ }
5376
+ if (/[^/][+?*]\{/.test(pattern)) {
5377
+ return true;
5378
+ }
5379
+ return false;
5380
+ }
5381
+ function patternToRegex(pattern) {
5382
+ if (pattern instanceof RegExp) {
5383
+ return pattern;
5384
+ }
5385
+ if (isRegexPattern(pattern)) {
5386
+ try {
5387
+ return new RegExp(pattern);
5388
+ } catch (error) {
5389
+ console.warn(`\u26A0\uFE0F Invalid regex pattern "${pattern}": ${error instanceof Error ? error.message : String(error)}`);
5390
+ return null;
5391
+ }
5392
+ }
5393
+ return null;
5394
+ }
5395
+ function stripPrefix(input, pattern, ensureLeadingChar) {
5396
+ if (!pattern) {
5397
+ return input;
5398
+ }
5399
+ const regex = patternToRegex(pattern);
5400
+ if (regex) {
5401
+ const match = input.match(regex);
5402
+ if (match && match.index === 0) {
5403
+ const stripped = input.substring(match[0].length);
5404
+ if (ensureLeadingChar) {
5405
+ if (stripped === "") {
5406
+ return ensureLeadingChar;
5407
+ }
5408
+ if (!stripped.startsWith(ensureLeadingChar)) {
5409
+ return `${ensureLeadingChar}${stripped}`;
5410
+ }
5411
+ }
5412
+ return stripped;
5413
+ }
5414
+ } else {
5415
+ const stringPattern = pattern;
5416
+ if (input.startsWith(stringPattern)) {
5417
+ const stripped = input.substring(stringPattern.length);
5418
+ if (ensureLeadingChar) {
5419
+ if (stripped === "") {
5420
+ return ensureLeadingChar;
5421
+ }
5422
+ if (!stripped.startsWith(ensureLeadingChar)) {
5423
+ return `${ensureLeadingChar}${stripped}`;
5424
+ }
5425
+ }
5426
+ return stripped;
5427
+ }
5428
+ }
5429
+ return input;
5430
+ }
5431
+ var init_pattern_utils = __esm({
5432
+ "src/utils/pattern-utils.ts"() {
5433
+ "use strict";
5434
+ init_esm_shims();
5435
+ }
5436
+ });
5437
+
5338
5438
  // src/validators/array-validator.ts
5339
5439
  function generateArrayValidation(schema, context) {
5340
5440
  var _a;
@@ -6006,6 +6106,7 @@ var init_property_generator = __esm({
6006
6106
  init_esm_shims();
6007
6107
  init_lru_cache();
6008
6108
  init_name_utils();
6109
+ init_pattern_utils();
6009
6110
  init_string_utils();
6010
6111
  init_array_validator();
6011
6112
  init_composition_validator();
@@ -6248,8 +6349,9 @@ var init_property_generator = __esm({
6248
6349
  }
6249
6350
  (_a = this.context.schemaDependencies.get(currentSchema)) == null ? void 0 : _a.add(refName);
6250
6351
  }
6251
- const schemaName = `${toCamelCase(resolvedRefName, this.context.namingOptions)}Schema`;
6252
- if (currentSchema && this.isCircularThroughAlias(currentSchema, refName)) {
6352
+ const strippedRefName = stripPrefix(resolvedRefName, this.context.stripSchemaPrefix);
6353
+ const schemaName = `${toCamelCase(strippedRefName, this.context.namingOptions)}Schema`;
6354
+ if (currentSchema && (refName === currentSchema || this.isCircularThroughAlias(currentSchema, refName))) {
6253
6355
  const lazySchema = `z.lazy((): z.ZodTypeAny => ${schemaName})`;
6254
6356
  return wrapNullable(lazySchema, nullable);
6255
6357
  }
@@ -6551,6 +6653,7 @@ var init_openapi_generator = __esm({
6551
6653
  init_property_generator();
6552
6654
  init_name_utils();
6553
6655
  init_operation_filters();
6656
+ init_pattern_utils();
6554
6657
  init_string_validator();
6555
6658
  OpenApiGenerator = class {
6556
6659
  constructor(options) {
@@ -6573,6 +6676,7 @@ var init_openapi_generator = __esm({
6573
6676
  schemaType: options.schemaType || "all",
6574
6677
  prefix: options.prefix,
6575
6678
  suffix: options.suffix,
6679
+ stripSchemaPrefix: options.stripSchemaPrefix,
6576
6680
  showStats: (_c = options.showStats) != null ? _c : true,
6577
6681
  request: options.request,
6578
6682
  response: options.response,
@@ -6649,7 +6753,8 @@ var init_openapi_generator = __esm({
6649
6753
  namingOptions: {
6650
6754
  prefix: this.options.prefix,
6651
6755
  suffix: this.options.suffix
6652
- }
6756
+ },
6757
+ stripSchemaPrefix: this.options.stripSchemaPrefix
6653
6758
  });
6654
6759
  }
6655
6760
  /**
@@ -6683,9 +6788,11 @@ var init_openapi_generator = __esm({
6683
6788
  const typeCode = this.types.get(name);
6684
6789
  if (schemaCode) {
6685
6790
  output.push(schemaCode);
6686
- if (!schemaCode.includes(`export type ${name}`)) {
6687
- const schemaName = `${toCamelCase(name, { prefix: this.options.prefix, suffix: this.options.suffix })}Schema`;
6688
- output.push(`export type ${name} = z.infer<typeof ${schemaName}>;`);
6791
+ const strippedName = stripPrefix(name, this.options.stripSchemaPrefix);
6792
+ const typeName = toPascalCase(strippedName);
6793
+ if (!schemaCode.includes(`export type ${typeName}`)) {
6794
+ const schemaName = `${toCamelCase(strippedName, { prefix: this.options.prefix, suffix: this.options.suffix })}Schema`;
6795
+ output.push(`export type ${typeName} = z.infer<typeof ${schemaName}>;`);
6689
6796
  }
6690
6797
  output.push("");
6691
6798
  } else if (typeCode) {
@@ -7001,7 +7108,8 @@ var init_openapi_generator = __esm({
7001
7108
  const resolvedOptions = context === "response" ? this.responseOptions : this.requestOptions;
7002
7109
  if (schema.enum) {
7003
7110
  const jsdoc2 = generateJSDoc(schema, name, { includeDescriptions: resolvedOptions.includeDescriptions });
7004
- const { schemaCode, typeCode } = generateEnum(name, schema.enum, {
7111
+ const strippedName2 = stripPrefix(name, this.options.stripSchemaPrefix);
7112
+ const { schemaCode, typeCode } = generateEnum(strippedName2, schema.enum, {
7005
7113
  prefix: this.options.prefix,
7006
7114
  suffix: this.options.suffix
7007
7115
  });
@@ -7010,7 +7118,8 @@ ${typeCode}`;
7010
7118
  this.schemas.set(name, enumSchemaCode);
7011
7119
  return;
7012
7120
  }
7013
- const schemaName = `${toCamelCase(name, { prefix: this.options.prefix, suffix: this.options.suffix })}Schema`;
7121
+ const strippedName = stripPrefix(name, this.options.stripSchemaPrefix);
7122
+ const schemaName = `${toCamelCase(strippedName, { prefix: this.options.prefix, suffix: this.options.suffix })}Schema`;
7014
7123
  const jsdoc = generateJSDoc(schema, name, { includeDescriptions: resolvedOptions.includeDescriptions });
7015
7124
  if (schema.allOf && schema.allOf.length === 1 && schema.allOf[0].$ref) {
7016
7125
  const refName = resolveRef(schema.allOf[0].$ref);
@@ -7026,7 +7135,8 @@ ${typeCode}`;
7026
7135
  namingOptions: {
7027
7136
  prefix: this.options.prefix,
7028
7137
  suffix: this.options.suffix
7029
- }
7138
+ },
7139
+ stripSchemaPrefix: this.options.stripSchemaPrefix
7030
7140
  });
7031
7141
  const isAlias = !!(schema.$ref && !schema.properties && !schema.allOf && !schema.oneOf && !schema.anyOf);
7032
7142
  const zodSchema = this.propertyGenerator.generatePropertySchema(schema, name, isAlias);
@@ -7228,7 +7338,8 @@ ${propsCode}
7228
7338
  generateQueryParamType(schema, param) {
7229
7339
  if (schema.$ref) {
7230
7340
  const refName = resolveRef(schema.$ref);
7231
- const schemaName = toCamelCase(refName, { prefix: this.options.prefix, suffix: this.options.suffix });
7341
+ const strippedRefName = stripPrefix(refName, this.options.stripSchemaPrefix);
7342
+ const schemaName = toCamelCase(strippedRefName, { prefix: this.options.prefix, suffix: this.options.suffix });
7232
7343
  return `${schemaName}Schema`;
7233
7344
  }
7234
7345
  if (schema.enum) {
@@ -7485,7 +7596,7 @@ async function loadConfig(configPath) {
7485
7596
  }
7486
7597
  if (!result || !result.config) {
7487
7598
  throw new Error(
7488
- configPath ? `Config file not found at: ${configPath}` : "No config file found. Searched for: openapi-to-zod.config.ts, openapi-to-zod.config.json, package.json (openapi-to-zod key)"
7599
+ configPath ? `Config file not found at: ${configPath}` : "No config file found. Searched for: openapi-to-zod.config.ts, openapi-to-zod.config.json, package.json (openapi-to-zod key)\nRun 'openapi-to-zod init' to create a new config file."
7489
7600
  );
7490
7601
  }
7491
7602
  try {
@@ -7537,6 +7648,7 @@ var init_config_loader = __esm({
7537
7648
  schemaType: z2.enum(["all", "request", "response"]).optional(),
7538
7649
  prefix: z2.string().optional(),
7539
7650
  suffix: z2.string().optional(),
7651
+ stripSchemaPrefix: z2.string().optional(),
7540
7652
  showStats: z2.boolean().optional(),
7541
7653
  request: RequestResponseOptionsSchema.optional(),
7542
7654
  response: RequestResponseOptionsSchema.optional(),
@@ -7553,6 +7665,7 @@ var init_config_loader = __esm({
7553
7665
  schemaType: z2.enum(["all", "request", "response"]).optional(),
7554
7666
  prefix: z2.string().optional(),
7555
7667
  suffix: z2.string().optional(),
7668
+ stripSchemaPrefix: z2.string().optional(),
7556
7669
  showStats: z2.boolean().optional(),
7557
7670
  request: RequestResponseOptionsSchema.optional(),
7558
7671
  response: RequestResponseOptionsSchema.optional(),
@@ -7652,14 +7765,7 @@ Examples:
7652
7765
  }
7653
7766
  async function executeConfigMode(options) {
7654
7767
  var _a, _b;
7655
- let config;
7656
- try {
7657
- config = await loadConfig(options.config);
7658
- } catch {
7659
- throw new CliOptionsError("No config file found. Run 'openapi-to-zod init' to create one.", {
7660
- configPath: options.config
7661
- });
7662
- }
7768
+ const config = await loadConfig(options.config);
7663
7769
  const specs = mergeConfigWithDefaults(config);
7664
7770
  const executionMode = config.executionMode || "parallel";
7665
7771
  const batchSize = (_b = (_a = specs[0]) == null ? void 0 : _a.batchSize) != null ? _b : 10;