zenko 0.1.9 → 0.1.10-beta.2

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
- // src/utils/topological-sort.ts
1
+ // ../zenko-core/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
- // src/utils/property-name.ts
50
+ // ../zenko-core/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,7 @@ function formatPropertyName(name) {
127
127
  return isValidJSIdentifier(name) ? name : `"${name}"`;
128
128
  }
129
129
 
130
- // src/utils/string-utils.ts
130
+ // ../zenko-core/src/utils/string-utils.ts
131
131
  function toCamelCase(str) {
132
132
  return str.replace(/-([a-zA-Z])/g, (_, letter) => letter.toUpperCase()).replace(/-+$/, "");
133
133
  }
@@ -135,7 +135,7 @@ function capitalize(str) {
135
135
  return str.charAt(0).toUpperCase() + str.slice(1);
136
136
  }
137
137
 
138
- // src/utils/http-status.ts
138
+ // ../zenko-core/src/utils/http-status.ts
139
139
  var statusNameMap = {
140
140
  "400": "badRequest",
141
141
  "401": "unauthorized",
@@ -201,7 +201,7 @@ function isErrorStatus(status) {
201
201
  return code >= 400;
202
202
  }
203
203
 
204
- // src/utils/tree-shaking.ts
204
+ // ../zenko-core/src/utils/tree-shaking.ts
205
205
  function analyzeZenkoUsage(operations) {
206
206
  const usage = {
207
207
  usesHeaderFn: false,
@@ -241,7 +241,7 @@ function hasAnyErrors(errors) {
241
241
  return Boolean(errors && Object.keys(errors).length > 0);
242
242
  }
243
243
 
244
- // src/utils/collect-inline-types.ts
244
+ // ../zenko-core/src/utils/collect-inline-types.ts
245
245
  function collectInlineRequestTypes(operations, spec) {
246
246
  const requestTypesToGenerate = /* @__PURE__ */ new Map();
247
247
  const operationLookup = /* @__PURE__ */ new Map();
@@ -318,8 +318,186 @@ function collectInlineResponseTypes(operations, spec) {
318
318
  }
319
319
  return responseTypesToGenerate;
320
320
  }
321
+ function collectInlineErrorTypes(operations, spec) {
322
+ const errorTypesToGenerate = /* @__PURE__ */ new Map();
323
+ const operationLookup = /* @__PURE__ */ new Map();
324
+ for (const [, pathItem] of Object.entries(spec.paths || {})) {
325
+ for (const [, operation] of Object.entries(pathItem)) {
326
+ const op = operation;
327
+ if (op.operationId) {
328
+ operationLookup.set(op.operationId, op);
329
+ }
330
+ }
331
+ }
332
+ for (const [, pathItem] of Object.entries(spec.webhooks || {})) {
333
+ for (const [, operation] of Object.entries(pathItem)) {
334
+ const op = operation;
335
+ if (op.operationId) {
336
+ operationLookup.set(op.operationId, op);
337
+ }
338
+ }
339
+ }
340
+ for (const op of operations) {
341
+ const operation = operationLookup.get(op.operationId);
342
+ if (!operation) continue;
343
+ const responses = operation.responses || {};
344
+ for (const [statusCode, response] of Object.entries(responses)) {
345
+ if (isErrorStatus(statusCode) && response.content) {
346
+ const content = response.content;
347
+ const jsonContent = content["application/json"];
348
+ if (jsonContent && jsonContent.schema) {
349
+ const schema = jsonContent.schema;
350
+ const identifier = mapStatusToIdentifier(statusCode);
351
+ const typeName = `${capitalize(toCamelCase(op.operationId))}${capitalize(identifier)}`;
352
+ if (!schema.$ref || schema.allOf || schema.oneOf || schema.anyOf) {
353
+ errorTypesToGenerate.set(typeName, schema);
354
+ }
355
+ }
356
+ }
357
+ }
358
+ }
359
+ return errorTypesToGenerate;
360
+ }
361
+
362
+ // ../zenko-core/src/utils/collect-referenced-schemas.ts
363
+ function findContentType(content) {
364
+ const contentTypes = Object.keys(content);
365
+ if (contentTypes.includes("application/json")) {
366
+ return "application/json";
367
+ }
368
+ const CONTENT_TYPE_MAP2 = {
369
+ "application/json": "unknown",
370
+ "text/csv": "string",
371
+ "text/plain": "string",
372
+ "application/octet-stream": "unknown",
373
+ "application/pdf": "unknown"
374
+ };
375
+ for (const contentType of contentTypes) {
376
+ if (contentType in CONTENT_TYPE_MAP2) {
377
+ return contentType;
378
+ }
379
+ }
380
+ return contentTypes[0] || "";
381
+ }
382
+ function resolveParameter(parameter, spec) {
383
+ if (!parameter) return void 0;
384
+ if (parameter.$ref) {
385
+ const refName = extractRefName(parameter.$ref);
386
+ const resolved = spec.components?.parameters?.[refName];
387
+ if (!resolved) return void 0;
388
+ const { $ref, ...overrides } = parameter;
389
+ return {
390
+ ...resolved,
391
+ ...overrides
392
+ };
393
+ }
394
+ return parameter;
395
+ }
396
+ function collectReferencedSchemas(operations, spec) {
397
+ const referenced = /* @__PURE__ */ new Set();
398
+ const operationLookup = /* @__PURE__ */ new Map();
399
+ for (const [, pathItem] of Object.entries(spec.paths || {})) {
400
+ for (const [, operation] of Object.entries(pathItem)) {
401
+ const op = operation;
402
+ if (op.operationId) {
403
+ operationLookup.set(op.operationId, op);
404
+ }
405
+ }
406
+ }
407
+ for (const [, pathItem] of Object.entries(spec.webhooks || {})) {
408
+ for (const [, operation] of Object.entries(pathItem)) {
409
+ const op = operation;
410
+ if (op.operationId) {
411
+ operationLookup.set(op.operationId, op);
412
+ }
413
+ }
414
+ }
415
+ for (const op of operations) {
416
+ const rawOperation = operationLookup.get(op.operationId);
417
+ if (!rawOperation) continue;
418
+ const requestBody = rawOperation.requestBody?.content?.["application/json"]?.schema;
419
+ if (requestBody?.$ref) {
420
+ const refName = extractRefName(requestBody.$ref);
421
+ referenced.add(refName);
422
+ } else if (requestBody) {
423
+ const deps = extractDependencies(requestBody);
424
+ for (const dep of deps) {
425
+ if (spec.components?.schemas?.[dep]) {
426
+ referenced.add(dep);
427
+ }
428
+ }
429
+ }
430
+ const responses = rawOperation.responses || {};
431
+ for (const [, response] of Object.entries(responses)) {
432
+ const content = response?.content;
433
+ if (!content) continue;
434
+ const contentType = findContentType(content);
435
+ const responseSchema = content[contentType]?.schema;
436
+ if (responseSchema?.$ref) {
437
+ const refName = extractRefName(responseSchema.$ref);
438
+ referenced.add(refName);
439
+ } else if (responseSchema) {
440
+ const deps = extractDependencies(responseSchema);
441
+ for (const dep of deps) {
442
+ if (spec.components?.schemas?.[dep]) {
443
+ referenced.add(dep);
444
+ }
445
+ }
446
+ }
447
+ }
448
+ for (const param of op.queryParams) {
449
+ if (param.schema?.$ref) {
450
+ const refName = extractRefName(param.schema.$ref);
451
+ referenced.add(refName);
452
+ }
453
+ if (param.schema?.items?.$ref) {
454
+ const refName = extractRefName(param.schema.items.$ref);
455
+ referenced.add(refName);
456
+ }
457
+ }
458
+ for (const header of op.requestHeaders || []) {
459
+ if (header.schema?.$ref) {
460
+ const refName = extractRefName(header.schema.$ref);
461
+ referenced.add(refName);
462
+ }
463
+ if (header.schema?.items?.$ref) {
464
+ const refName = extractRefName(header.schema.items.$ref);
465
+ referenced.add(refName);
466
+ }
467
+ }
468
+ const parameters = rawOperation.parameters || [];
469
+ for (const param of parameters) {
470
+ const resolvedParam = resolveParameter(param, spec);
471
+ if (resolvedParam?.schema?.$ref) {
472
+ const refName = extractRefName(resolvedParam.schema.$ref);
473
+ referenced.add(refName);
474
+ }
475
+ if (resolvedParam?.schema?.items?.$ref) {
476
+ const refName = extractRefName(resolvedParam.schema.items.$ref);
477
+ referenced.add(refName);
478
+ }
479
+ }
480
+ }
481
+ const visited = /* @__PURE__ */ new Set();
482
+ const toVisit = Array.from(referenced);
483
+ while (toVisit.length > 0) {
484
+ const schemaName = toVisit.pop();
485
+ if (visited.has(schemaName)) continue;
486
+ visited.add(schemaName);
487
+ const schema = spec.components?.schemas?.[schemaName];
488
+ if (!schema) continue;
489
+ const dependencies = extractDependencies(schema);
490
+ for (const dep of dependencies) {
491
+ if (spec.components?.schemas?.[dep] && !visited.has(dep)) {
492
+ referenced.add(dep);
493
+ toVisit.push(dep);
494
+ }
495
+ }
496
+ }
497
+ return referenced;
498
+ }
321
499
 
322
- // src/utils/generate-helper-file.ts
500
+ // ../zenko-core/src/utils/generate-helper-file.ts
323
501
  function generateHelperFile() {
324
502
  const output = [];
325
503
  output.push("// Generated helper types for Zenko");
@@ -361,11 +539,11 @@ function generateHelperFile() {
361
539
  return output.join("\n");
362
540
  }
363
541
 
364
- // src/zenko.ts
542
+ // ../zenko-core/src/zenko.ts
365
543
  function generateWithMetadata(spec, options = {}) {
366
544
  const output = [];
367
545
  const generatedTypes = /* @__PURE__ */ new Set();
368
- const { strictDates = false, strictNumeric = false } = options;
546
+ const { strictDates = false, strictNumeric = false, operationIds } = options;
369
547
  const typesConfig = normalizeTypesConfig(options.types);
370
548
  const schemaOptions = {
371
549
  strictDates,
@@ -379,13 +557,26 @@ function generateWithMetadata(spec, options = {}) {
379
557
  nameMap.set(name, toCamelCase(name));
380
558
  }
381
559
  }
382
- const operations = parseOperations(spec, nameMap);
560
+ let operations = parseOperations(spec, nameMap);
561
+ if (operationIds && operationIds.length > 0) {
562
+ const selectedIds = new Set(operationIds);
563
+ operations = operations.filter((op) => selectedIds.has(op.operationId));
564
+ }
383
565
  appendHelperTypesImport(output, typesConfig, operations);
384
566
  output.push("");
385
567
  if (spec.components?.schemas) {
386
568
  output.push("// Generated Zod Schemas");
387
569
  output.push("");
388
- const sortedSchemas = topologicalSort(spec.components.schemas);
570
+ let schemasToGenerate;
571
+ if (operationIds && operationIds.length > 0) {
572
+ const referencedSchemas = collectReferencedSchemas(operations, spec);
573
+ schemasToGenerate = Array.from(referencedSchemas);
574
+ } else {
575
+ schemasToGenerate = Object.keys(spec.components.schemas);
576
+ }
577
+ const sortedSchemas = topologicalSort(spec.components.schemas).filter(
578
+ (name) => schemasToGenerate.includes(name)
579
+ );
389
580
  for (const name of sortedSchemas) {
390
581
  const schema = spec.components.schemas[name];
391
582
  const sanitizedName = nameMap.get(name);
@@ -574,6 +765,9 @@ function generateWithMetadata(spec, options = {}) {
574
765
  }
575
766
  return result;
576
767
  }
768
+ function generateFromDocument(spec, options = {}) {
769
+ return generateWithMetadata(spec, options);
770
+ }
577
771
  function generateRequestTypes(output, operations, spec, nameMap, schemaOptions) {
578
772
  const requestTypesToGenerate = collectInlineRequestTypes(operations, spec);
579
773
  if (requestTypesToGenerate.size > 0) {
@@ -596,7 +790,8 @@ function generateRequestTypes(output, operations, spec, nameMap, schemaOptions)
596
790
  }
597
791
  function generateResponseTypes(output, operations, spec, nameMap, schemaOptions) {
598
792
  const responseTypesToGenerate = collectInlineResponseTypes(operations, spec);
599
- if (responseTypesToGenerate.size > 0) {
793
+ const errorTypesToGenerate = collectInlineErrorTypes(operations, spec);
794
+ if (responseTypesToGenerate.size > 0 || errorTypesToGenerate.size > 0) {
600
795
  output.push("// Generated Response Types");
601
796
  output.push("");
602
797
  for (const [typeName, schema] of responseTypesToGenerate) {
@@ -612,10 +807,23 @@ function generateResponseTypes(output, operations, spec, nameMap, schemaOptions)
612
807
  output.push(`export type ${typeName} = z.infer<typeof ${typeName}>;`);
613
808
  output.push("");
614
809
  }
810
+ for (const [typeName, schema] of errorTypesToGenerate) {
811
+ const generatedSchema = generateZodSchema(
812
+ typeName,
813
+ schema,
814
+ /* @__PURE__ */ new Set(),
815
+ schemaOptions,
816
+ nameMap
817
+ );
818
+ output.push(generatedSchema);
819
+ output.push("");
820
+ output.push(`export type ${typeName} = z.infer<typeof ${typeName}>;`);
821
+ output.push("");
822
+ }
615
823
  }
616
824
  }
617
825
  function generate(spec, options = {}) {
618
- return generateWithMetadata(spec, options).output;
826
+ return generateFromDocument(spec, options).output;
619
827
  }
620
828
  function appendOperationField(buffer, key, value) {
621
829
  if (!value) return;
@@ -656,7 +864,7 @@ var CONTENT_TYPE_MAP = {
656
864
  "application/octet-stream": "unknown",
657
865
  "application/pdf": "unknown"
658
866
  };
659
- function findContentType(content) {
867
+ function findContentType2(content) {
660
868
  const contentTypes = Object.keys(content);
661
869
  if (contentTypes.includes("application/json")) {
662
870
  return "application/json";
@@ -907,7 +1115,7 @@ function collectParameters(pathItem, operation, spec) {
907
1115
  const addParameters = (params) => {
908
1116
  if (!Array.isArray(params)) return;
909
1117
  for (const param of params) {
910
- const resolved = resolveParameter(param, spec);
1118
+ const resolved = resolveParameter2(param, spec);
911
1119
  if (!resolved) continue;
912
1120
  const key = `${resolved.in}:${resolved.name}`;
913
1121
  parametersMap.set(key, resolved);
@@ -917,7 +1125,7 @@ function collectParameters(pathItem, operation, spec) {
917
1125
  addParameters(operation.parameters);
918
1126
  return Array.from(parametersMap.values());
919
1127
  }
920
- function resolveParameter(parameter, spec) {
1128
+ function resolveParameter2(parameter, spec) {
921
1129
  if (!parameter) return void 0;
922
1130
  if (parameter.$ref) {
923
1131
  const refName = extractRefName(parameter.$ref);
@@ -972,7 +1180,7 @@ function getResponseTypes(operation, operationId, nameMap) {
972
1180
  }
973
1181
  continue;
974
1182
  }
975
- const contentType = findContentType(content);
1183
+ const contentType = findContentType2(content);
976
1184
  const resolvedSchema = content[contentType]?.schema;
977
1185
  if (!resolvedSchema) {
978
1186
  const inferredType = inferResponseType(contentType, statusCode);
@@ -1344,6 +1552,8 @@ function applyNumericBounds(schema, builder) {
1344
1552
  return builder;
1345
1553
  }
1346
1554
  export {
1347
- generate
1555
+ generate,
1556
+ generateFromDocument,
1557
+ generateWithMetadata
1348
1558
  };
1349
1559
  //# sourceMappingURL=index.mjs.map