zenko 0.1.6-beta.1 → 0.1.7-beta.1

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/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- // ../zenko-core/src/utils/topological-sort.ts
1
+ // src/utils/topological-sort.ts
2
2
  function topologicalSort(schemas) {
3
3
  const visited = /* @__PURE__ */ new Set();
4
4
  const visiting = /* @__PURE__ */ new Set();
@@ -47,7 +47,7 @@ function extractRefName(ref) {
47
47
  return ref.split("/").pop() || "Unknown";
48
48
  }
49
49
 
50
- // ../zenko-core/src/utils/property-name.ts
50
+ // src/utils/property-name.ts
51
51
  function isValidJSIdentifier(name) {
52
52
  if (!name) return false;
53
53
  const firstChar = name.at(0);
@@ -127,7 +127,15 @@ function formatPropertyName(name) {
127
127
  return isValidJSIdentifier(name) ? name : `"${name}"`;
128
128
  }
129
129
 
130
- // ../zenko-core/src/utils/http-status.ts
130
+ // src/utils/string-utils.ts
131
+ function toCamelCase(str) {
132
+ return str.replace(/-([a-zA-Z])/g, (_, letter) => letter.toUpperCase()).replace(/-+$/, "");
133
+ }
134
+ function capitalize(str) {
135
+ return str.charAt(0).toUpperCase() + str.slice(1);
136
+ }
137
+
138
+ // src/utils/http-status.ts
131
139
  var statusNameMap = {
132
140
  "400": "badRequest",
133
141
  "401": "unauthorized",
@@ -186,14 +194,6 @@ function mapStatusToIdentifier(status) {
186
194
  if (!candidate) return "unknownError";
187
195
  return /^[a-zA-Z_$]/.test(candidate) ? candidate : `status${candidate.charAt(0).toUpperCase()}${candidate.slice(1)}`;
188
196
  }
189
- function getStatusCategory(status) {
190
- if (status === "default") return "default";
191
- const code = Number(status);
192
- if (!Number.isInteger(code)) return "unknown";
193
- if (code >= 400 && code <= 499) return "client";
194
- if (code >= 500 && code <= 599) return "server";
195
- return "unknown";
196
- }
197
197
  function isErrorStatus(status) {
198
198
  if (status === "default") return true;
199
199
  const code = Number(status);
@@ -201,7 +201,170 @@ function isErrorStatus(status) {
201
201
  return code >= 400;
202
202
  }
203
203
 
204
- // ../zenko-core/src/zenko.ts
204
+ // src/utils/tree-shaking.ts
205
+ function analyzeZenkoUsage(operations) {
206
+ const usage = {
207
+ usesHeaderFn: false,
208
+ usesOperationDefinition: false,
209
+ usesOperationErrors: false
210
+ };
211
+ if (operations.length > 0) {
212
+ usage.usesOperationDefinition = true;
213
+ }
214
+ for (const op of operations) {
215
+ if (op.requestHeaders && op.requestHeaders.length > 0) {
216
+ usage.usesHeaderFn = true;
217
+ }
218
+ if (op.errors && hasAnyErrors(op.errors)) {
219
+ usage.usesOperationErrors = true;
220
+ }
221
+ }
222
+ if (operations.length > 0 && !usage.usesOperationErrors) {
223
+ const hasDefaultErrors = operations.some(
224
+ (op) => !op.errors || !hasAnyErrors(op.errors)
225
+ );
226
+ if (hasDefaultErrors) {
227
+ usage.usesOperationErrors = true;
228
+ }
229
+ }
230
+ return usage;
231
+ }
232
+ function generateZenkoImport(usage, mode, helpersOutput) {
233
+ const types = [];
234
+ if (usage.usesHeaderFn) types.push("HeaderFn");
235
+ if (usage.usesOperationDefinition) types.push("OperationDefinition");
236
+ if (usage.usesOperationErrors) types.push("OperationErrors");
237
+ if (types.length === 0) {
238
+ return "";
239
+ }
240
+ const importSource = mode === "package" ? '"zenko"' : `"${helpersOutput}"`;
241
+ return `import type { ${types.join(", ")} } from ${importSource};`;
242
+ }
243
+ function hasAnyErrors(errors) {
244
+ return Boolean(errors && Object.keys(errors).length > 0);
245
+ }
246
+
247
+ // src/utils/collect-inline-types.ts
248
+ function collectInlineRequestTypes(operations, spec) {
249
+ const requestTypesToGenerate = /* @__PURE__ */ new Map();
250
+ const operationLookup = /* @__PURE__ */ new Map();
251
+ for (const [, pathItem] of Object.entries(spec.paths || {})) {
252
+ for (const [, operation] of Object.entries(pathItem)) {
253
+ const op = operation;
254
+ if (op.operationId) {
255
+ operationLookup.set(op.operationId, op);
256
+ }
257
+ }
258
+ }
259
+ for (const [, pathItem] of Object.entries(spec.webhooks || {})) {
260
+ for (const [, operation] of Object.entries(pathItem)) {
261
+ const op = operation;
262
+ if (op.operationId) {
263
+ operationLookup.set(op.operationId, op);
264
+ }
265
+ }
266
+ }
267
+ for (const op of operations) {
268
+ const operation = operationLookup.get(op.operationId);
269
+ if (!operation) continue;
270
+ const requestBody = operation.requestBody;
271
+ if (requestBody && requestBody.content) {
272
+ const content = requestBody.content;
273
+ const jsonContent = content["application/json"];
274
+ if (jsonContent && jsonContent.schema) {
275
+ const schema = jsonContent.schema;
276
+ const typeName = `${capitalize(toCamelCase(op.operationId))}Request`;
277
+ if (!schema.$ref || schema.allOf || schema.oneOf || schema.anyOf) {
278
+ requestTypesToGenerate.set(typeName, schema);
279
+ }
280
+ }
281
+ }
282
+ }
283
+ return requestTypesToGenerate;
284
+ }
285
+ function collectInlineResponseTypes(operations, spec) {
286
+ const responseTypesToGenerate = /* @__PURE__ */ new Map();
287
+ const operationLookup = /* @__PURE__ */ new Map();
288
+ for (const [, pathItem] of Object.entries(spec.paths || {})) {
289
+ for (const [, operation] of Object.entries(pathItem)) {
290
+ const op = operation;
291
+ if (op.operationId) {
292
+ operationLookup.set(op.operationId, op);
293
+ }
294
+ }
295
+ }
296
+ for (const [, pathItem] of Object.entries(spec.webhooks || {})) {
297
+ for (const [, operation] of Object.entries(pathItem)) {
298
+ const op = operation;
299
+ if (op.operationId) {
300
+ operationLookup.set(op.operationId, op);
301
+ }
302
+ }
303
+ }
304
+ for (const op of operations) {
305
+ const operation = operationLookup.get(op.operationId);
306
+ if (!operation) continue;
307
+ const responses = operation.responses || {};
308
+ for (const [statusCode, response] of Object.entries(responses)) {
309
+ if (/^2\d\d$/.test(statusCode) && response.content) {
310
+ const content = response.content;
311
+ const jsonContent = content["application/json"];
312
+ if (jsonContent && jsonContent.schema) {
313
+ const schema = jsonContent.schema;
314
+ const typeName = `${capitalize(toCamelCase(op.operationId))}Response`;
315
+ if (!schema.$ref || schema.allOf || schema.oneOf || schema.anyOf) {
316
+ responseTypesToGenerate.set(typeName, schema);
317
+ }
318
+ }
319
+ }
320
+ }
321
+ }
322
+ return responseTypesToGenerate;
323
+ }
324
+
325
+ // src/utils/generate-helper-file.ts
326
+ function generateHelperFile() {
327
+ const output = [];
328
+ output.push("// Generated helper types for Zenko");
329
+ output.push(
330
+ "// This file provides type definitions for operation objects and path functions"
331
+ );
332
+ output.push("");
333
+ output.push(
334
+ "export type PathFn<TArgs extends unknown[] = []> = (...args: TArgs) => string"
335
+ );
336
+ output.push("");
337
+ output.push(
338
+ 'export type RequestMethod = "get" | "put" | "post" | "delete" | "options" | "head" | "patch" | "trace"'
339
+ );
340
+ output.push("");
341
+ output.push(
342
+ "export type HeaderFn<TArgs extends unknown[] = [], TResult = Record<string, unknown> | Record<string, never>> = (...args: TArgs) => TResult"
343
+ );
344
+ output.push("");
345
+ output.push(
346
+ "export type AnyHeaderFn = HeaderFn<any, unknown> | (() => unknown)"
347
+ );
348
+ output.push("");
349
+ output.push(
350
+ "export type OperationErrors<TError = unknown> = TError extends Record<string, unknown> ? TError : Record<string, TError>;"
351
+ );
352
+ output.push("");
353
+ output.push(
354
+ "export type OperationDefinition<TMethod extends RequestMethod, TPath extends (...args: any[]) => string, TRequest = undefined, TResponse = undefined, THeaders extends AnyHeaderFn | undefined = undefined, TErrors extends OperationErrors | undefined = undefined> = {"
355
+ );
356
+ output.push(" method: TMethod");
357
+ output.push(" path: TPath");
358
+ output.push(" request?: TRequest");
359
+ output.push(" response?: TResponse");
360
+ output.push(" headers?: THeaders");
361
+ output.push(" errors?: TErrors");
362
+ output.push("}");
363
+ output.push("");
364
+ return output.join("\n");
365
+ }
366
+
367
+ // src/zenko.ts
205
368
  function generateWithMetadata(spec, options = {}) {
206
369
  const output = [];
207
370
  const generatedTypes = /* @__PURE__ */ new Set();
@@ -212,7 +375,14 @@ function generateWithMetadata(spec, options = {}) {
212
375
  strictNumeric
213
376
  };
214
377
  output.push('import { z } from "zod";');
215
- appendHelperTypesImport(output, typesConfig);
378
+ const nameMap = /* @__PURE__ */ new Map();
379
+ if (spec.components?.schemas) {
380
+ for (const name of Object.keys(spec.components.schemas)) {
381
+ nameMap.set(name, toCamelCase(name));
382
+ }
383
+ }
384
+ const operations = parseOperations(spec, nameMap);
385
+ appendHelperTypesImport(output, typesConfig, operations);
216
386
  output.push("");
217
387
  if (spec.components?.schemas) {
218
388
  output.push("// Generated Zod Schemas");
@@ -220,15 +390,23 @@ function generateWithMetadata(spec, options = {}) {
220
390
  const sortedSchemas = topologicalSort(spec.components.schemas);
221
391
  for (const name of sortedSchemas) {
222
392
  const schema = spec.components.schemas[name];
393
+ const sanitizedName = nameMap.get(name);
223
394
  output.push(
224
- generateZodSchema(name, schema, generatedTypes, schemaOptions)
395
+ generateZodSchema(
396
+ sanitizedName,
397
+ schema,
398
+ generatedTypes,
399
+ schemaOptions,
400
+ nameMap
401
+ )
225
402
  );
226
403
  output.push("");
227
- output.push(`export type ${name} = z.infer<typeof ${name}>;`);
404
+ output.push(
405
+ `export type ${sanitizedName} = z.infer<typeof ${sanitizedName}>;`
406
+ );
228
407
  output.push("");
229
408
  }
230
409
  }
231
- const operations = parseOperations(spec);
232
410
  output.push("// Path Functions");
233
411
  output.push("export const paths = {");
234
412
  for (const op of operations) {
@@ -242,24 +420,37 @@ function generateWithMetadata(spec, options = {}) {
242
420
  );
243
421
  continue;
244
422
  }
245
- const allParamNames = [
246
- ...pathParamNames,
247
- ...op.queryParams.map((p) => p.name)
248
- ];
249
- const signaturePieces = [];
423
+ const alias = (n) => {
424
+ if (isValidJSIdentifier(n)) return n;
425
+ let aliased = toCamelCase(n);
426
+ if (!isValidJSIdentifier(aliased)) {
427
+ aliased = `_${aliased}`;
428
+ }
429
+ return aliased;
430
+ };
431
+ const destructPieces = [];
432
+ const typePieces = [];
250
433
  for (const param of op.pathParams) {
251
- signaturePieces.push(`${param.name}: string`);
434
+ destructPieces.push(
435
+ isValidJSIdentifier(param.name) ? param.name : `${formatPropertyName(param.name)}: ${alias(param.name)}`
436
+ );
437
+ typePieces.push(`${formatPropertyName(param.name)}: string`);
252
438
  }
253
439
  for (const param of op.queryParams) {
254
- signaturePieces.push(
255
- `${param.name}${param.required ? "" : "?"}: ${mapQueryType(param)}`
440
+ destructPieces.push(
441
+ isValidJSIdentifier(param.name) ? param.name : `${formatPropertyName(param.name)}: ${alias(param.name)}`
442
+ );
443
+ typePieces.push(
444
+ `${formatPropertyName(param.name)}${param.required ? "" : "?"}: ${mapQueryType(param)}`
256
445
  );
257
446
  }
258
- const signatureParams = signaturePieces.join(", ");
259
447
  const needsDefaultObject = !hasPathParams && hasQueryParams && op.queryParams.every((param) => !param.required);
260
- const signatureArgs = allParamNames.length ? `{ ${allParamNames.join(", ")} }` : "{}";
261
- const signature = `${signatureArgs}: { ${signatureParams} }${needsDefaultObject ? " = {}" : ""}`;
262
- const pathWithParams = op.path.replace(/{([^}]+)}/g, "${$1}");
448
+ const signatureArgs = destructPieces.length ? `{ ${destructPieces.join(", ")} }` : "{}";
449
+ const signature = `${signatureArgs}: { ${typePieces.join(", ")} }${needsDefaultObject ? " = {}" : ""}`;
450
+ const pathWithParams = op.path.replace(
451
+ /{([^}]+)}/g,
452
+ (_m, n) => `\${${alias(n)}}`
453
+ );
263
454
  if (!hasQueryParams) {
264
455
  output.push(
265
456
  ` ${formatPropertyName(camelCaseOperationId)}: (${signature}) => \`${pathWithParams}\`,`
@@ -271,8 +462,7 @@ function generateWithMetadata(spec, options = {}) {
271
462
  );
272
463
  output.push(" const params = new URLSearchParams()");
273
464
  for (const param of op.queryParams) {
274
- const propertyKey = formatPropertyName(param.name);
275
- const accessor = isValidJSIdentifier(param.name) ? param.name : propertyKey;
465
+ const accessor = isValidJSIdentifier(param.name) ? param.name : alias(toCamelCase(param.name));
276
466
  const schema = param.schema ?? {};
277
467
  if (schema?.type === "array") {
278
468
  const itemValueExpression = convertQueryParamValue(
@@ -354,10 +544,14 @@ function generateWithMetadata(spec, options = {}) {
354
544
  }
355
545
  output.push("} as const;");
356
546
  output.push("");
547
+ generateRequestTypes(output, operations, spec, nameMap, schemaOptions);
548
+ generateResponseTypes(output, operations, spec, nameMap, schemaOptions);
549
+ generateOperationTypes(output, operations, typesConfig);
357
550
  output.push("// Operation Objects");
358
551
  for (const op of operations) {
359
552
  const camelCaseOperationId = toCamelCase(op.operationId);
360
- output.push(`export const ${camelCaseOperationId} = {`);
553
+ const typeAnnotation = typesConfig.emit ? `: ${capitalize(camelCaseOperationId)}Operation` : "";
554
+ output.push(`export const ${camelCaseOperationId}${typeAnnotation} = {`);
361
555
  output.push(` method: "${op.method}",`);
362
556
  output.push(` path: paths.${camelCaseOperationId},`);
363
557
  appendOperationField(output, "request", op.requestType);
@@ -365,18 +559,12 @@ function generateWithMetadata(spec, options = {}) {
365
559
  if (op.requestHeaders && op.requestHeaders.length > 0) {
366
560
  output.push(` headers: headers.${camelCaseOperationId},`);
367
561
  }
368
- if (op.errors && hasAnyErrors(op.errors)) {
369
- output.push(" errors: {");
370
- appendErrorGroup(output, "clientErrors", op.errors.clientErrors);
371
- appendErrorGroup(output, "serverErrors", op.errors.serverErrors);
372
- appendErrorGroup(output, "defaultErrors", op.errors.defaultErrors);
373
- appendErrorGroup(output, "otherErrors", op.errors.otherErrors);
374
- output.push(" },");
562
+ if (op.errors && hasAnyErrors2(op.errors)) {
563
+ appendErrorGroup(output, "errors", op.errors);
375
564
  }
376
565
  output.push("} as const;");
377
566
  output.push("");
378
567
  }
379
- generateOperationTypes(output, operations, typesConfig);
380
568
  const result = {
381
569
  output: output.join("\n")
382
570
  };
@@ -388,6 +576,46 @@ function generateWithMetadata(spec, options = {}) {
388
576
  }
389
577
  return result;
390
578
  }
579
+ function generateRequestTypes(output, operations, spec, nameMap, schemaOptions) {
580
+ const requestTypesToGenerate = collectInlineRequestTypes(operations, spec);
581
+ if (requestTypesToGenerate.size > 0) {
582
+ output.push("// Generated Request Types");
583
+ output.push("");
584
+ for (const [typeName, schema] of requestTypesToGenerate) {
585
+ const generatedSchema = generateZodSchema(
586
+ typeName,
587
+ schema,
588
+ /* @__PURE__ */ new Set(),
589
+ schemaOptions,
590
+ nameMap
591
+ );
592
+ output.push(generatedSchema);
593
+ output.push("");
594
+ output.push(`export type ${typeName} = z.infer<typeof ${typeName}>;`);
595
+ output.push("");
596
+ }
597
+ }
598
+ }
599
+ function generateResponseTypes(output, operations, spec, nameMap, schemaOptions) {
600
+ const responseTypesToGenerate = collectInlineResponseTypes(operations, spec);
601
+ if (responseTypesToGenerate.size > 0) {
602
+ output.push("// Generated Response Types");
603
+ output.push("");
604
+ for (const [typeName, schema] of responseTypesToGenerate) {
605
+ const generatedSchema = generateZodSchema(
606
+ typeName,
607
+ schema,
608
+ /* @__PURE__ */ new Set(),
609
+ schemaOptions,
610
+ nameMap
611
+ );
612
+ output.push(generatedSchema);
613
+ output.push("");
614
+ output.push(`export type ${typeName} = z.infer<typeof ${typeName}>;`);
615
+ output.push("");
616
+ }
617
+ }
618
+ }
391
619
  function generate(spec, options = {}) {
392
620
  return generateWithMetadata(spec, options).output;
393
621
  }
@@ -403,13 +631,8 @@ function appendErrorGroup(buffer, label, errors) {
403
631
  }
404
632
  buffer.push(" },");
405
633
  }
406
- function hasAnyErrors(group) {
407
- return [
408
- group.clientErrors,
409
- group.serverErrors,
410
- group.defaultErrors,
411
- group.otherErrors
412
- ].some((bucket) => bucket && Object.keys(bucket).length > 0);
634
+ function hasAnyErrors2(group) {
635
+ return Boolean(group && Object.keys(group).length > 0);
413
636
  }
414
637
  function isRequestMethod(method) {
415
638
  switch (method) {
@@ -456,33 +679,70 @@ function inferResponseType(contentType, statusCode) {
456
679
  }
457
680
  return "unknown";
458
681
  }
459
- function parseOperations(spec) {
682
+ function parseOperations(spec, nameMap) {
460
683
  const operations = [];
461
- for (const [path, pathItem] of Object.entries(spec.paths)) {
462
- for (const [method, operation] of Object.entries(pathItem)) {
463
- const normalizedMethod = method.toLowerCase();
464
- if (!isRequestMethod(normalizedMethod)) continue;
465
- if (!operation.operationId) continue;
466
- const pathParams = extractPathParams(path);
467
- const requestType = getRequestType(operation);
468
- const { successResponse, errors } = getResponseTypes(
469
- operation,
470
- operation.operationId
471
- );
472
- const resolvedParameters = collectParameters(pathItem, operation, spec);
473
- const requestHeaders = getRequestHeaders(resolvedParameters);
474
- const queryParams = getQueryParams(resolvedParameters);
475
- operations.push({
476
- operationId: operation.operationId,
477
- path,
478
- method: normalizedMethod,
479
- pathParams,
480
- queryParams,
481
- requestType,
482
- responseType: successResponse,
483
- requestHeaders,
484
- errors
485
- });
684
+ if (spec.paths) {
685
+ for (const [path, pathItem] of Object.entries(spec.paths)) {
686
+ for (const [method, operation] of Object.entries(pathItem)) {
687
+ const normalizedMethod = method.toLowerCase();
688
+ if (!isRequestMethod(normalizedMethod)) continue;
689
+ if (!operation.operationId) continue;
690
+ const pathParams = extractPathParams(path);
691
+ const requestType = getRequestType(operation);
692
+ const { successResponse, errors } = getResponseTypes(
693
+ operation,
694
+ operation.operationId,
695
+ nameMap
696
+ );
697
+ const resolvedParameters = collectParameters(pathItem, operation, spec);
698
+ const requestHeaders = getRequestHeaders(resolvedParameters);
699
+ const queryParams = getQueryParams(resolvedParameters);
700
+ operations.push({
701
+ operationId: operation.operationId,
702
+ path,
703
+ method: normalizedMethod,
704
+ pathParams,
705
+ queryParams,
706
+ requestType,
707
+ responseType: successResponse,
708
+ requestHeaders,
709
+ errors
710
+ });
711
+ }
712
+ }
713
+ }
714
+ if (spec.webhooks) {
715
+ for (const [webhookName, webhookItem] of Object.entries(spec.webhooks)) {
716
+ for (const [method, operation] of Object.entries(webhookItem)) {
717
+ const normalizedMethod = method.toLowerCase();
718
+ if (!isRequestMethod(normalizedMethod)) continue;
719
+ if (!operation.operationId) continue;
720
+ const path = webhookName;
721
+ const pathParams = extractPathParams(path);
722
+ const requestType = getRequestType(operation);
723
+ const { successResponse, errors } = getResponseTypes(
724
+ operation,
725
+ operation.operationId
726
+ );
727
+ const resolvedParameters = collectParameters(
728
+ webhookItem,
729
+ operation,
730
+ spec
731
+ );
732
+ const requestHeaders = getRequestHeaders(resolvedParameters);
733
+ const queryParams = getQueryParams(resolvedParameters);
734
+ operations.push({
735
+ operationId: operation.operationId,
736
+ path,
737
+ method: normalizedMethod,
738
+ pathParams,
739
+ queryParams,
740
+ requestType,
741
+ responseType: successResponse,
742
+ requestHeaders,
743
+ errors
744
+ });
745
+ }
486
746
  }
487
747
  }
488
748
  return operations;
@@ -491,21 +751,42 @@ function normalizeTypesConfig(config) {
491
751
  return {
492
752
  emit: config?.emit ?? true,
493
753
  helpers: config?.helpers ?? "package",
494
- helpersOutput: config?.helpersOutput ?? "./zenko-types"
754
+ helpersOutput: config?.helpersOutput ?? "./zenko-types",
755
+ treeShake: config?.treeShake ?? true
495
756
  };
496
757
  }
497
- function appendHelperTypesImport(buffer, config) {
758
+ function appendHelperTypesImport(buffer, config, operations) {
498
759
  if (!config.emit) return;
499
760
  switch (config.helpers) {
500
761
  case "package":
501
- buffer.push(
502
- 'import type { PathFn, HeaderFn, OperationDefinition, OperationErrors } from "zenko";'
503
- );
762
+ if (config.treeShake) {
763
+ const usage = analyzeZenkoUsage(operations);
764
+ const importStatement = generateZenkoImport(usage, "package");
765
+ if (importStatement) {
766
+ buffer.push(importStatement);
767
+ }
768
+ } else {
769
+ buffer.push(
770
+ 'import type { PathFn, HeaderFn, OperationDefinition, OperationErrors } from "zenko";'
771
+ );
772
+ }
504
773
  return;
505
774
  case "file":
506
- buffer.push(
507
- `import type { PathFn, HeaderFn, OperationDefinition, OperationErrors } from "${config.helpersOutput}";`
508
- );
775
+ if (config.treeShake) {
776
+ const usage = analyzeZenkoUsage(operations);
777
+ const importStatement = generateZenkoImport(
778
+ usage,
779
+ "file",
780
+ config.helpersOutput
781
+ );
782
+ if (importStatement) {
783
+ buffer.push(importStatement);
784
+ }
785
+ } else {
786
+ buffer.push(
787
+ `import type { PathFn, HeaderFn, OperationDefinition, OperationErrors } from "${config.helpersOutput}";`
788
+ );
789
+ }
509
790
  return;
510
791
  case "inline":
511
792
  buffer.push(
@@ -521,24 +802,19 @@ function appendHelperTypesImport(buffer, config) {
521
802
  "type AnyHeaderFn = HeaderFn<any, unknown> | (() => unknown);"
522
803
  );
523
804
  buffer.push(
524
- "type OperationErrors<TClient = unknown, TServer = unknown, TDefault = unknown, TOther = unknown> = {"
805
+ "type OperationErrors<TError = unknown> = TError extends Record<string, unknown> ? TError : Record<string, TError>;"
525
806
  );
526
- buffer.push(" clientErrors?: TClient;");
527
- buffer.push(" serverErrors?: TServer;");
528
- buffer.push(" defaultErrors?: TDefault;");
529
- buffer.push(" otherErrors?: TOther;");
530
- buffer.push("};");
531
807
  buffer.push(
532
808
  "type OperationDefinition<TMethod extends RequestMethod, TPath extends (...args: any[]) => string, TRequest = undefined, TResponse = undefined, THeaders extends AnyHeaderFn | undefined = undefined, TErrors extends OperationErrors | undefined = undefined> = {"
533
809
  );
534
- buffer.push(" method: TMethod;");
535
- buffer.push(" path: TPath;");
536
- buffer.push(" request?: TRequest;");
537
- buffer.push(" response?: TResponse;");
538
- buffer.push(" headers?: THeaders;");
539
- buffer.push(" errors?: TErrors;");
540
- buffer.push("};");
541
- return;
810
+ buffer.push(" method: TMethod");
811
+ buffer.push(" path: TPath");
812
+ buffer.push(" request?: TRequest");
813
+ buffer.push(" response?: TResponse");
814
+ buffer.push(" headers?: THeaders");
815
+ buffer.push(" errors?: TErrors");
816
+ buffer.push("}");
817
+ buffer.push("");
542
818
  }
543
819
  }
544
820
  function generateOperationTypes(buffer, operations, config) {
@@ -566,14 +842,11 @@ function generateOperationTypes(buffer, operations, config) {
566
842
  }
567
843
  }
568
844
  function buildOperationErrorsType(errors) {
569
- if (!errors || !hasAnyErrors(errors)) {
845
+ if (!errors || !hasAnyErrors2(errors)) {
570
846
  return "OperationErrors";
571
847
  }
572
- const client = buildErrorBucket(errors.clientErrors);
573
- const server = buildErrorBucket(errors.serverErrors);
574
- const fallback = buildErrorBucket(errors.defaultErrors);
575
- const other = buildErrorBucket(errors.otherErrors);
576
- return `OperationErrors<${client}, ${server}, ${fallback}, ${other}>`;
848
+ const errorBucket = buildErrorBucket(errors);
849
+ return `OperationErrors<${errorBucket}>`;
577
850
  }
578
851
  function buildErrorBucket(bucket) {
579
852
  if (!bucket || Object.keys(bucket).length === 0) {
@@ -680,10 +953,10 @@ function getRequestType(operation) {
680
953
  if (requestBody.$ref) {
681
954
  return extractRefName(requestBody.$ref);
682
955
  }
683
- const typeName = `${capitalize(operation.operationId)}Request`;
956
+ const typeName = `${capitalize(toCamelCase(operation.operationId))}Request`;
684
957
  return typeName;
685
958
  }
686
- function getResponseTypes(operation, operationId) {
959
+ function getResponseTypes(operation, operationId, nameMap) {
687
960
  const responses = operation.responses ?? {};
688
961
  const successCodes = /* @__PURE__ */ new Map();
689
962
  const errorEntries = [];
@@ -724,11 +997,15 @@ function getResponseTypes(operation, operationId) {
724
997
  successCodes.set(statusCode, resolvedSchema);
725
998
  }
726
999
  }
727
- const successResponse = selectSuccessResponse(successCodes, operationId);
728
- const errors = buildErrorGroups(errorEntries, operationId);
1000
+ const successResponse = selectSuccessResponse(
1001
+ successCodes,
1002
+ operationId,
1003
+ nameMap
1004
+ );
1005
+ const errors = buildErrorGroups(errorEntries, operationId, nameMap);
729
1006
  return { successResponse, errors };
730
1007
  }
731
- function selectSuccessResponse(responses, operationId) {
1008
+ function selectSuccessResponse(responses, operationId, nameMap) {
732
1009
  if (responses.size === 0) return void 0;
733
1010
  const preferredOrder = ["200", "201", "204"];
734
1011
  for (const code of preferredOrder) {
@@ -739,61 +1016,51 @@ function selectSuccessResponse(responses, operationId) {
739
1016
  }
740
1017
  return resolveResponseType(
741
1018
  schema,
742
- `${capitalize(operationId)}Response${code}`
1019
+ `${capitalize(toCamelCase(operationId))}Response`,
1020
+ nameMap
743
1021
  );
744
1022
  }
745
1023
  }
746
- const [firstCode, firstSchema] = responses.entries().next().value ?? [];
1024
+ const [, firstSchema] = responses.entries().next().value ?? [];
747
1025
  if (!firstSchema) return void 0;
748
1026
  if (typeof firstSchema === "string") {
749
1027
  return firstSchema;
750
1028
  }
751
1029
  return resolveResponseType(
752
1030
  firstSchema,
753
- `${capitalize(operationId)}Response${firstCode ?? "Default"}`
1031
+ `${capitalize(toCamelCase(operationId))}Response`,
1032
+ nameMap
754
1033
  );
755
1034
  }
756
- function buildErrorGroups(errors = [], operationId) {
1035
+ function buildErrorGroups(errors = [], operationId, nameMap) {
757
1036
  if (!errors.length) return void 0;
758
1037
  const group = {};
759
1038
  for (const { code, schema } of errors) {
760
- const category = getStatusCategory(code);
761
1039
  const identifier = mapStatusToIdentifier(code);
762
1040
  const typeName = resolveResponseType(
763
1041
  schema,
764
- `${capitalize(operationId)}${capitalize(identifier)}`
1042
+ `${capitalize(toCamelCase(operationId))}${capitalize(identifier)}`,
1043
+ nameMap
765
1044
  );
766
- switch (category) {
767
- case "client":
768
- group.clientErrors ??= {};
769
- group.clientErrors[identifier] = typeName;
770
- break;
771
- case "server":
772
- group.serverErrors ??= {};
773
- group.serverErrors[identifier] = typeName;
774
- break;
775
- case "default":
776
- group.defaultErrors ??= {};
777
- group.defaultErrors[identifier] = typeName;
778
- break;
779
- default:
780
- group.otherErrors ??= {};
781
- group.otherErrors[identifier] = typeName;
782
- break;
783
- }
1045
+ group[identifier] = typeName;
784
1046
  }
785
1047
  return group;
786
1048
  }
787
- function resolveResponseType(schema, fallbackName) {
1049
+ function resolveResponseType(schema, fallbackName, nameMap) {
788
1050
  if (typeof schema === "string") {
789
1051
  return schema;
790
1052
  }
791
1053
  if (schema.$ref) {
792
- return extractRefName(schema.$ref);
1054
+ const refName = extractRefName(schema.$ref);
1055
+ return nameMap?.get(refName) || refName;
793
1056
  }
794
1057
  if (schema.type === "array" && schema.items?.$ref) {
795
1058
  const itemRef = extractRefName(schema.items.$ref);
796
- return `z.array(${itemRef})`;
1059
+ const sanitizedItemRef = nameMap?.get(itemRef) || itemRef;
1060
+ return `z.array(${sanitizedItemRef})`;
1061
+ }
1062
+ if (schema.allOf && Array.isArray(schema.allOf)) {
1063
+ return fallbackName;
797
1064
  }
798
1065
  return fallbackName;
799
1066
  }
@@ -876,19 +1143,30 @@ function convertQueryParamValue(schema, accessor) {
876
1143
  return `String(${accessor})`;
877
1144
  }
878
1145
  }
879
- function generateZodSchema(name, schema, generatedTypes, options) {
1146
+ function generateZodSchema(name, schema, generatedTypes, options, nameMap) {
880
1147
  if (generatedTypes.has(name)) return "";
881
1148
  generatedTypes.add(name);
882
1149
  if (schema.enum) {
883
1150
  const enumValues = schema.enum.map((v) => `"${v}"`).join(", ");
884
1151
  return `export const ${name} = z.enum([${enumValues}]);`;
885
1152
  }
1153
+ if (schema.allOf && Array.isArray(schema.allOf)) {
1154
+ const allOfParts = schema.allOf.map(
1155
+ (part) => getZodTypeFromSchema(part, options, nameMap)
1156
+ );
1157
+ if (allOfParts.length === 0) return `export const ${name} = z.object({});`;
1158
+ if (allOfParts.length === 1)
1159
+ return `export const ${name} = ${allOfParts[0]};`;
1160
+ const first = allOfParts[0];
1161
+ const rest = allOfParts.slice(1).map((part) => `.and(${part})`).join("");
1162
+ return `export const ${name} = ${first}${rest};`;
1163
+ }
886
1164
  if (schema.type === "object" || schema.properties) {
887
- return `export const ${name} = ${buildZodObject(schema, options)};`;
1165
+ return `export const ${name} = ${buildZodObject(schema, options, nameMap)};`;
888
1166
  }
889
1167
  if (schema.type === "array") {
890
1168
  const itemSchema = schema.items ?? { type: "unknown" };
891
- const itemType = getZodTypeFromSchema(itemSchema, options);
1169
+ const itemType = getZodTypeFromSchema(itemSchema, options, nameMap);
892
1170
  const builder = applyStrictArrayBounds(
893
1171
  schema,
894
1172
  `z.array(${itemType})`,
@@ -897,18 +1175,29 @@ function generateZodSchema(name, schema, generatedTypes, options) {
897
1175
  );
898
1176
  return `export const ${name} = ${builder};`;
899
1177
  }
900
- return `export const ${name} = ${getZodTypeFromSchema(schema, options)};`;
1178
+ return `export const ${name} = ${getZodTypeFromSchema(schema, options, nameMap)};`;
901
1179
  }
902
- function getZodTypeFromSchema(schema, options) {
1180
+ function getZodTypeFromSchema(schema, options, nameMap) {
903
1181
  if (schema.$ref) {
904
- return extractRefName(schema.$ref);
1182
+ const refName = extractRefName(schema.$ref);
1183
+ return nameMap?.get(refName) || refName;
905
1184
  }
906
1185
  if (schema.enum) {
907
1186
  const enumValues = schema.enum.map((v) => `"${v}"`).join(", ");
908
1187
  return `z.enum([${enumValues}])`;
909
1188
  }
910
- if (schema.type === "object" || schema.properties) {
911
- return buildZodObject(schema, options);
1189
+ if (schema.allOf && Array.isArray(schema.allOf)) {
1190
+ const allOfParts = schema.allOf.map(
1191
+ (part) => getZodTypeFromSchema(part, options, nameMap)
1192
+ );
1193
+ if (allOfParts.length === 0) return "z.object({})";
1194
+ if (allOfParts.length === 1) return allOfParts[0];
1195
+ const first = allOfParts[0];
1196
+ const rest = allOfParts.slice(1).map((part) => `.and(${part})`).join("");
1197
+ return `${first}${rest}`;
1198
+ }
1199
+ if (schema.type === "object" || schema.properties || schema.allOf || schema.oneOf || schema.anyOf) {
1200
+ return buildZodObject(schema, options, nameMap);
912
1201
  }
913
1202
  switch (schema.type) {
914
1203
  case "string":
@@ -918,7 +1207,8 @@ function getZodTypeFromSchema(schema, options) {
918
1207
  case "array":
919
1208
  return `z.array(${getZodTypeFromSchema(
920
1209
  schema.items ?? { type: "unknown" },
921
- options
1210
+ options,
1211
+ nameMap
922
1212
  )})`;
923
1213
  case "null":
924
1214
  return "z.null()";
@@ -930,13 +1220,13 @@ function getZodTypeFromSchema(schema, options) {
930
1220
  return "z.unknown()";
931
1221
  }
932
1222
  }
933
- function buildZodObject(schema, options) {
1223
+ function buildZodObject(schema, options, nameMap) {
934
1224
  const properties = [];
935
1225
  for (const [propName, propSchema] of Object.entries(
936
1226
  schema.properties || {}
937
1227
  )) {
938
1228
  const isRequired = schema.required?.includes(propName) ?? false;
939
- const zodType = getZodTypeFromSchema(propSchema, options);
1229
+ const zodType = getZodTypeFromSchema(propSchema, options, nameMap);
940
1230
  const finalType = isRequired ? zodType : `${zodType}.optional()`;
941
1231
  properties.push(` ${formatPropertyName(propName)}: ${finalType},`);
942
1232
  }
@@ -1044,60 +1334,7 @@ function applyNumericBounds(schema, builder) {
1044
1334
  }
1045
1335
  return builder;
1046
1336
  }
1047
- function generateHelperFile() {
1048
- const output = [];
1049
- output.push("// Generated helper types for Zenko");
1050
- output.push(
1051
- "// This file provides type definitions for operation objects and path functions"
1052
- );
1053
- output.push("");
1054
- output.push(
1055
- "export type PathFn<TArgs extends unknown[] = []> = (...args: TArgs) => string"
1056
- );
1057
- output.push("");
1058
- output.push(
1059
- 'export type RequestMethod = "get" | "put" | "post" | "delete" | "options" | "head" | "patch" | "trace"'
1060
- );
1061
- output.push("");
1062
- output.push(
1063
- "export type HeaderFn<TArgs extends unknown[] = [], TResult = Record<string, unknown> | Record<string, never>> = (...args: TArgs) => TResult"
1064
- );
1065
- output.push("");
1066
- output.push(
1067
- "export type AnyHeaderFn = HeaderFn<any, unknown> | (() => unknown)"
1068
- );
1069
- output.push("");
1070
- output.push(
1071
- "export type OperationErrors<TClient = unknown, TServer = unknown, TDefault = unknown, TOther = unknown> = {"
1072
- );
1073
- output.push(" clientErrors?: TClient");
1074
- output.push(" serverErrors?: TServer");
1075
- output.push(" defaultErrors?: TDefault");
1076
- output.push(" otherErrors?: TOther");
1077
- output.push("}");
1078
- output.push("");
1079
- output.push(
1080
- "export type OperationDefinition<TMethod extends RequestMethod, TPath extends (...args: any[]) => string, TRequest = undefined, TResponse = undefined, THeaders extends AnyHeaderFn | undefined = undefined, TErrors extends OperationErrors | undefined = undefined> = {"
1081
- );
1082
- output.push(" method: TMethod");
1083
- output.push(" path: TPath");
1084
- output.push(" request?: TRequest");
1085
- output.push(" response?: TResponse");
1086
- output.push(" headers?: THeaders");
1087
- output.push(" errors?: TErrors");
1088
- output.push("}");
1089
- output.push("");
1090
- return output.join("\n");
1091
- }
1092
- function toCamelCase(str) {
1093
- return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
1094
- }
1095
- function capitalize(str) {
1096
- return str.charAt(0).toUpperCase() + str.slice(1);
1097
- }
1098
1337
  export {
1099
- generate,
1100
- generateHelperFile,
1101
- generateWithMetadata
1338
+ generate
1102
1339
  };
1103
1340
  //# sourceMappingURL=index.mjs.map