@kubb/ast 5.0.0-beta.29 → 5.0.0-beta.30
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.cjs +256 -211
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1041 -837
- package/dist/index.js +251 -212
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/dialect.ts +64 -0
- package/src/dispatch.ts +53 -0
- package/src/factory.ts +93 -6
- package/src/guards.ts +15 -0
- package/src/index.ts +6 -1
- package/src/nodes/base.ts +2 -0
- package/src/nodes/content.ts +37 -0
- package/src/nodes/index.ts +6 -2
- package/src/nodes/operation.ts +98 -62
- package/src/nodes/response.ts +2 -16
- package/src/types.ts +6 -0
- package/src/utils.ts +13 -6
- package/src/visitor.ts +140 -174
package/dist/index.cjs
CHANGED
|
@@ -224,6 +224,60 @@ const mediaTypes = {
|
|
|
224
224
|
videoMp4: "video/mp4"
|
|
225
225
|
};
|
|
226
226
|
//#endregion
|
|
227
|
+
//#region src/dialect.ts
|
|
228
|
+
/**
|
|
229
|
+
* Identity helper that types a {@link SchemaDialect} for an adapter. Like
|
|
230
|
+
* `defineParser`, it adds no runtime behavior — it pins the dialect's type for
|
|
231
|
+
* inference and gives adapter authors a discoverable anchor.
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```ts
|
|
235
|
+
* export const oasDialect = defineSchemaDialect({
|
|
236
|
+
* name: 'oas',
|
|
237
|
+
* isNullable,
|
|
238
|
+
* isReference,
|
|
239
|
+
* isDiscriminator,
|
|
240
|
+
* isBinary: (schema) => schema.type === 'string' && schema.contentMediaType === 'application/octet-stream',
|
|
241
|
+
* resolveRef,
|
|
242
|
+
* })
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
function defineSchemaDialect(dialect) {
|
|
246
|
+
return dialect;
|
|
247
|
+
}
|
|
248
|
+
//#endregion
|
|
249
|
+
//#region src/dispatch.ts
|
|
250
|
+
/**
|
|
251
|
+
* Walks an ordered list of {@link DispatchRule}s and returns the first node produced.
|
|
252
|
+
*
|
|
253
|
+
* This is the shared backbone for spec adapters (OpenAPI today, AsyncAPI and others later).
|
|
254
|
+
* The contract an adapter follows is intentionally minimal:
|
|
255
|
+
*
|
|
256
|
+
* context → [rule.match → rule.convert] → node
|
|
257
|
+
*
|
|
258
|
+
* An adapter derives a context from a source spec node, then declares an ordered table of
|
|
259
|
+
* rules mapping spec shapes onto Kubb AST nodes. To add support for a new spec, write a new
|
|
260
|
+
* context type and a new rules table — the traversal here is reused unchanged.
|
|
261
|
+
*
|
|
262
|
+
* Order is significant: earlier rules win, so list higher-precedence or more specific shapes
|
|
263
|
+
* first (e.g. composition keywords before plain `type`). A rule whose `match` returns `true`
|
|
264
|
+
* may still `convert` to `null` to defer to later rules. When no rule produces a node this
|
|
265
|
+
* returns `null`, leaving the caller to apply its own fallback.
|
|
266
|
+
*
|
|
267
|
+
* @example
|
|
268
|
+
* ```ts
|
|
269
|
+
* const node = dispatch(schemaRules, schemaContext) ?? createSchema({ type: fallbackType })
|
|
270
|
+
* ```
|
|
271
|
+
*/
|
|
272
|
+
function dispatch(rules, context) {
|
|
273
|
+
for (const rule of rules) {
|
|
274
|
+
if (!rule.match(context)) continue;
|
|
275
|
+
const node = rule.convert(context);
|
|
276
|
+
if (node !== null && node !== void 0) return node;
|
|
277
|
+
}
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
//#endregion
|
|
227
281
|
//#region ../../internals/utils/src/casing.ts
|
|
228
282
|
/**
|
|
229
283
|
* Shared implementation for camelCase and PascalCase conversion.
|
|
@@ -498,6 +552,19 @@ const isOutputNode = isKind("Output");
|
|
|
498
552
|
*/
|
|
499
553
|
const isOperationNode = isKind("Operation");
|
|
500
554
|
/**
|
|
555
|
+
* Narrows an `OperationNode` to an `HttpOperationNode`, guaranteeing `method` and `path`.
|
|
556
|
+
*
|
|
557
|
+
* @example
|
|
558
|
+
* ```ts
|
|
559
|
+
* if (isHttpOperationNode(node)) {
|
|
560
|
+
* console.log(node.method, node.path)
|
|
561
|
+
* }
|
|
562
|
+
* ```
|
|
563
|
+
*/
|
|
564
|
+
function isHttpOperationNode(node) {
|
|
565
|
+
return node.protocol === "http" || node.method !== void 0 && node.path !== void 0;
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
501
568
|
* Returns `true` when the input is a `SchemaNode`.
|
|
502
569
|
*
|
|
503
570
|
* @example
|
|
@@ -560,58 +627,84 @@ function createLimit(concurrency) {
|
|
|
560
627
|
});
|
|
561
628
|
};
|
|
562
629
|
}
|
|
630
|
+
const visitorKeysByKind = {
|
|
631
|
+
Input: ["schemas", "operations"],
|
|
632
|
+
Operation: [
|
|
633
|
+
"parameters",
|
|
634
|
+
"requestBody",
|
|
635
|
+
"responses"
|
|
636
|
+
],
|
|
637
|
+
RequestBody: ["content"],
|
|
638
|
+
Content: ["schema"],
|
|
639
|
+
Response: ["content"],
|
|
640
|
+
Schema: [
|
|
641
|
+
"properties",
|
|
642
|
+
"items",
|
|
643
|
+
"members",
|
|
644
|
+
"additionalProperties"
|
|
645
|
+
],
|
|
646
|
+
Property: ["schema"],
|
|
647
|
+
Parameter: ["schema"]
|
|
648
|
+
};
|
|
563
649
|
/**
|
|
564
|
-
* Returns
|
|
650
|
+
* Returns `true` when `value` is an AST node (an object carrying a `kind`).
|
|
651
|
+
*/
|
|
652
|
+
function isNode(value) {
|
|
653
|
+
return typeof value === "object" && value !== null && "kind" in value;
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Returns the immediate traversable children of `node` based on {@link VISITOR_KEYS}.
|
|
565
657
|
*
|
|
566
|
-
*
|
|
567
|
-
* `additionalProperties`) are only included
|
|
568
|
-
* when `recurse` is `true`; shallow mode skips them.
|
|
658
|
+
* `Schema` children are only included when `recurse` is `true`; shallow mode skips them.
|
|
569
659
|
*
|
|
570
660
|
* @example
|
|
571
661
|
* ```ts
|
|
572
662
|
* const children = getChildren(operationNode, true)
|
|
573
|
-
* // returns parameters,
|
|
663
|
+
* // returns parameters, the request body, and responses
|
|
574
664
|
* ```
|
|
575
665
|
*/
|
|
576
666
|
function* getChildren(node, recurse) {
|
|
577
|
-
if (node.kind === "
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
if (
|
|
586
|
-
for (const c of node.requestBody.content) if (c.schema) yield c.schema;
|
|
587
|
-
}
|
|
588
|
-
yield* node.responses;
|
|
589
|
-
return;
|
|
590
|
-
}
|
|
591
|
-
if (node.kind === "Schema") {
|
|
592
|
-
if (!recurse) return;
|
|
593
|
-
if ("properties" in node && node.properties.length > 0) yield* node.properties;
|
|
594
|
-
if ("items" in node && node.items) yield* node.items;
|
|
595
|
-
if ("members" in node && node.members) yield* node.members;
|
|
596
|
-
if ("additionalProperties" in node && node.additionalProperties && node.additionalProperties !== true) yield node.additionalProperties;
|
|
597
|
-
return;
|
|
598
|
-
}
|
|
599
|
-
if (node.kind === "Property") {
|
|
600
|
-
yield node.schema;
|
|
601
|
-
return;
|
|
602
|
-
}
|
|
603
|
-
if (node.kind === "Parameter") {
|
|
604
|
-
yield node.schema;
|
|
605
|
-
return;
|
|
606
|
-
}
|
|
607
|
-
if (node.kind === "Response") {
|
|
608
|
-
if (node.content) {
|
|
609
|
-
for (const c of node.content) if (c.schema) yield c.schema;
|
|
610
|
-
}
|
|
611
|
-
return;
|
|
667
|
+
if (node.kind === "Schema" && !recurse) return;
|
|
668
|
+
const keys = visitorKeysByKind[node.kind];
|
|
669
|
+
if (!keys) return;
|
|
670
|
+
const record = node;
|
|
671
|
+
for (const key of keys) {
|
|
672
|
+
const value = record[key];
|
|
673
|
+
if (Array.isArray(value)) {
|
|
674
|
+
for (const item of value) if (isNode(item)) yield item;
|
|
675
|
+
} else if (isNode(value)) yield value;
|
|
612
676
|
}
|
|
613
677
|
}
|
|
614
678
|
/**
|
|
679
|
+
* Maps a node `kind` to the matching visitor callback name. Only the seven
|
|
680
|
+
* traversable node kinds have an entry; every other kind resolves to
|
|
681
|
+
* `undefined` and is skipped.
|
|
682
|
+
*/
|
|
683
|
+
const VISITOR_KEY_BY_KIND = {
|
|
684
|
+
Input: "input",
|
|
685
|
+
Output: "output",
|
|
686
|
+
Operation: "operation",
|
|
687
|
+
Schema: "schema",
|
|
688
|
+
Property: "property",
|
|
689
|
+
Parameter: "parameter",
|
|
690
|
+
Response: "response"
|
|
691
|
+
};
|
|
692
|
+
/**
|
|
693
|
+
* Invokes the visitor callback that matches `node.kind`, passing the traversal
|
|
694
|
+
* context. Returns the callback's result (a replacement node, a collected
|
|
695
|
+
* value, or `undefined` when no callback is registered for the kind).
|
|
696
|
+
*
|
|
697
|
+
* Shared by `walk`, `transform`, and `collectLazy` so node-kind dispatch lives
|
|
698
|
+
* in one place. `TResult` is the caller's expected return: the same node type
|
|
699
|
+
* for `transform`, the collected value type for `collectLazy`, ignored for `walk`.
|
|
700
|
+
*/
|
|
701
|
+
function applyVisitor(node, visitor, parent) {
|
|
702
|
+
const key = VISITOR_KEY_BY_KIND[node.kind];
|
|
703
|
+
if (!key) return void 0;
|
|
704
|
+
const fn = visitor[key];
|
|
705
|
+
return fn?.(node, { parent });
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
615
708
|
* Async depth-first traversal for side effects. Visitor return values are
|
|
616
709
|
* ignored. Use `transform` when you want to rewrite nodes.
|
|
617
710
|
*
|
|
@@ -637,122 +730,63 @@ async function walk(node, options) {
|
|
|
637
730
|
return _walk(node, options, (options.depth ?? visitorDepths.deep) === visitorDepths.deep, createLimit(options.concurrency ?? 30), void 0);
|
|
638
731
|
}
|
|
639
732
|
async function _walk(node, visitor, recurse, limit, parent) {
|
|
640
|
-
|
|
641
|
-
case "Input":
|
|
642
|
-
await limit(() => visitor.input?.(node, { parent }));
|
|
643
|
-
break;
|
|
644
|
-
case "Output":
|
|
645
|
-
await limit(() => visitor.output?.(node, { parent }));
|
|
646
|
-
break;
|
|
647
|
-
case "Operation":
|
|
648
|
-
await limit(() => visitor.operation?.(node, { parent }));
|
|
649
|
-
break;
|
|
650
|
-
case "Schema":
|
|
651
|
-
await limit(() => visitor.schema?.(node, { parent }));
|
|
652
|
-
break;
|
|
653
|
-
case "Property":
|
|
654
|
-
await limit(() => visitor.property?.(node, { parent }));
|
|
655
|
-
break;
|
|
656
|
-
case "Parameter":
|
|
657
|
-
await limit(() => visitor.parameter?.(node, { parent }));
|
|
658
|
-
break;
|
|
659
|
-
case "Response":
|
|
660
|
-
await limit(() => visitor.response?.(node, { parent }));
|
|
661
|
-
break;
|
|
662
|
-
}
|
|
733
|
+
await limit(() => applyVisitor(node, visitor, parent));
|
|
663
734
|
const children = getChildren(node, recurse);
|
|
664
735
|
for (const child of children) await _walk(child, visitor, recurse, limit, node);
|
|
665
736
|
}
|
|
666
737
|
function transform(node, options) {
|
|
667
738
|
const { depth, parent, ...visitor } = options;
|
|
668
739
|
const recurse = (depth ?? visitorDepths.deep) === visitorDepths.deep;
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
}
|
|
714
|
-
return {
|
|
715
|
-
...schema,
|
|
716
|
-
..."properties" in schema && recurse ? { properties: schema.properties.map((p) => transform(p, childOptions)) } : {},
|
|
717
|
-
..."items" in schema && recurse ? { items: schema.items?.map((i) => transform(i, childOptions)) } : {},
|
|
718
|
-
..."members" in schema && recurse ? { members: schema.members?.map((m) => transform(m, childOptions)) } : {},
|
|
719
|
-
..."additionalProperties" in schema && recurse && schema.additionalProperties && schema.additionalProperties !== true ? { additionalProperties: transform(schema.additionalProperties, childOptions) } : {}
|
|
720
|
-
};
|
|
721
|
-
}
|
|
722
|
-
if (node.kind === "Property") {
|
|
723
|
-
const prop = visitor.property?.(node, { parent }) ?? node;
|
|
724
|
-
return createProperty({
|
|
725
|
-
...prop,
|
|
726
|
-
schema: transform(prop.schema, {
|
|
727
|
-
...options,
|
|
728
|
-
parent: prop
|
|
729
|
-
})
|
|
730
|
-
});
|
|
731
|
-
}
|
|
732
|
-
if (node.kind === "Parameter") {
|
|
733
|
-
const param = visitor.parameter?.(node, { parent }) ?? node;
|
|
734
|
-
return createParameter({
|
|
735
|
-
...param,
|
|
736
|
-
schema: transform(param.schema, {
|
|
737
|
-
...options,
|
|
738
|
-
parent: param
|
|
739
|
-
})
|
|
740
|
-
});
|
|
741
|
-
}
|
|
742
|
-
if (node.kind === "Response") {
|
|
743
|
-
const response = visitor.response?.(node, { parent }) ?? node;
|
|
744
|
-
return {
|
|
745
|
-
...response,
|
|
746
|
-
content: response.content?.map((entry) => ({
|
|
747
|
-
...entry,
|
|
748
|
-
schema: entry.schema ? transform(entry.schema, {
|
|
749
|
-
...options,
|
|
750
|
-
parent: response
|
|
751
|
-
}) : entry.schema
|
|
752
|
-
}))
|
|
753
|
-
};
|
|
740
|
+
const rebuilt = transformChildren(applyVisitor(node, visitor, parent) ?? node, options, recurse);
|
|
741
|
+
if (rebuilt === node) return node;
|
|
742
|
+
const finalize = nodeFinalizers[rebuilt.kind];
|
|
743
|
+
return finalize ? finalize(rebuilt) : rebuilt;
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Per-kind builders rerun after children are rebuilt. `Property`/`Parameter`
|
|
747
|
+
* resync schema optionality against their `required` flag once the schema may
|
|
748
|
+
* have changed.
|
|
749
|
+
*/
|
|
750
|
+
const nodeFinalizers = {
|
|
751
|
+
Property: (node) => createProperty(node),
|
|
752
|
+
Parameter: (node) => createParameter(node)
|
|
753
|
+
};
|
|
754
|
+
/**
|
|
755
|
+
* Immutably rebuilds a node's children using {@link VISITOR_KEYS}, transforming
|
|
756
|
+
* each child node and leaving non-node values (e.g. `additionalProperties: true`) intact.
|
|
757
|
+
* `Schema` children are skipped in shallow mode.
|
|
758
|
+
*/
|
|
759
|
+
function transformChildren(node, options, recurse) {
|
|
760
|
+
if (node.kind === "Schema" && !recurse) return node;
|
|
761
|
+
const keys = visitorKeysByKind[node.kind];
|
|
762
|
+
if (!keys) return node;
|
|
763
|
+
const record = node;
|
|
764
|
+
const childOptions = {
|
|
765
|
+
...options,
|
|
766
|
+
parent: node
|
|
767
|
+
};
|
|
768
|
+
let updates;
|
|
769
|
+
for (const key of keys) {
|
|
770
|
+
if (!(key in record)) continue;
|
|
771
|
+
const value = record[key];
|
|
772
|
+
if (Array.isArray(value)) {
|
|
773
|
+
let changed = false;
|
|
774
|
+
const mapped = value.map((item) => {
|
|
775
|
+
if (!isNode(item)) return item;
|
|
776
|
+
const next = transform(item, childOptions);
|
|
777
|
+
if (next !== item) changed = true;
|
|
778
|
+
return next;
|
|
779
|
+
});
|
|
780
|
+
if (changed) (updates ??= {})[key] = mapped;
|
|
781
|
+
} else if (isNode(value)) {
|
|
782
|
+
const next = transform(value, childOptions);
|
|
783
|
+
if (next !== value) (updates ??= {})[key] = next;
|
|
784
|
+
}
|
|
754
785
|
}
|
|
755
|
-
return
|
|
786
|
+
return updates ? {
|
|
787
|
+
...node,
|
|
788
|
+
...updates
|
|
789
|
+
} : node;
|
|
756
790
|
}
|
|
757
791
|
/**
|
|
758
792
|
* Lazy depth-first collection pass. Yields every non-null value returned by
|
|
@@ -773,30 +807,7 @@ function transform(node, options) {
|
|
|
773
807
|
function* collectLazy(node, options) {
|
|
774
808
|
const { depth, parent, ...visitor } = options;
|
|
775
809
|
const recurse = (depth ?? visitorDepths.deep) === visitorDepths.deep;
|
|
776
|
-
|
|
777
|
-
switch (node.kind) {
|
|
778
|
-
case "Input":
|
|
779
|
-
v = visitor.input?.(node, { parent });
|
|
780
|
-
break;
|
|
781
|
-
case "Output":
|
|
782
|
-
v = visitor.output?.(node, { parent });
|
|
783
|
-
break;
|
|
784
|
-
case "Operation":
|
|
785
|
-
v = visitor.operation?.(node, { parent });
|
|
786
|
-
break;
|
|
787
|
-
case "Schema":
|
|
788
|
-
v = visitor.schema?.(node, { parent });
|
|
789
|
-
break;
|
|
790
|
-
case "Property":
|
|
791
|
-
v = visitor.property?.(node, { parent });
|
|
792
|
-
break;
|
|
793
|
-
case "Parameter":
|
|
794
|
-
v = visitor.parameter?.(node, { parent });
|
|
795
|
-
break;
|
|
796
|
-
case "Response":
|
|
797
|
-
v = visitor.response?.(node, { parent });
|
|
798
|
-
break;
|
|
799
|
-
}
|
|
810
|
+
const v = applyVisitor(node, visitor, parent);
|
|
800
811
|
if (v != null) yield v;
|
|
801
812
|
for (const child of getChildren(node, recurse)) yield* collectLazy(child, {
|
|
802
813
|
...options,
|
|
@@ -1158,6 +1169,16 @@ function combineSources(sources) {
|
|
|
1158
1169
|
return [...seen.values()];
|
|
1159
1170
|
}
|
|
1160
1171
|
/**
|
|
1172
|
+
* Merges `incoming` names into `existing`, preserving order and dropping duplicates.
|
|
1173
|
+
*
|
|
1174
|
+
* Shared by `combineExports` and `combineImports` for the same-path name-merge case.
|
|
1175
|
+
*/
|
|
1176
|
+
function mergeNameArrays(existing, incoming) {
|
|
1177
|
+
const merged = new Set(existing);
|
|
1178
|
+
for (const name of incoming) merged.add(name);
|
|
1179
|
+
return [...merged];
|
|
1180
|
+
}
|
|
1181
|
+
/**
|
|
1161
1182
|
* Deduplicates and merges `ExportNode` objects by path and type.
|
|
1162
1183
|
*
|
|
1163
1184
|
* Named exports with the same path and `isTypeOnly` flag have their names merged into a single export.
|
|
@@ -1178,11 +1199,8 @@ function combineExports(exports) {
|
|
|
1178
1199
|
if (!name.length) continue;
|
|
1179
1200
|
const key = pathTypeKey(path, isTypeOnly);
|
|
1180
1201
|
const existing = namedByPath.get(key);
|
|
1181
|
-
if (existing && Array.isArray(existing.name))
|
|
1182
|
-
|
|
1183
|
-
for (const n of name) merged.add(n);
|
|
1184
|
-
existing.name = [...merged];
|
|
1185
|
-
} else {
|
|
1202
|
+
if (existing && Array.isArray(existing.name)) existing.name = mergeNameArrays(existing.name, name);
|
|
1203
|
+
else {
|
|
1186
1204
|
const newItem = {
|
|
1187
1205
|
...curr,
|
|
1188
1206
|
name: [...new Set(name)]
|
|
@@ -1240,11 +1258,8 @@ function combineImports(imports, exports, source) {
|
|
|
1240
1258
|
if (!name.length) continue;
|
|
1241
1259
|
const key = pathTypeKey(path, isTypeOnly);
|
|
1242
1260
|
const existing = namedByPath.get(key);
|
|
1243
|
-
if (existing && Array.isArray(existing.name))
|
|
1244
|
-
|
|
1245
|
-
for (const n of name) merged.add(n);
|
|
1246
|
-
existing.name = [...merged];
|
|
1247
|
-
} else {
|
|
1261
|
+
if (existing && Array.isArray(existing.name)) existing.name = mergeNameArrays(existing.name, name);
|
|
1262
|
+
else {
|
|
1248
1263
|
const newItem = {
|
|
1249
1264
|
...curr,
|
|
1250
1265
|
name
|
|
@@ -1463,6 +1478,29 @@ function syncOptionality(schema, required) {
|
|
|
1463
1478
|
};
|
|
1464
1479
|
}
|
|
1465
1480
|
/**
|
|
1481
|
+
* Identity-preserving node update: returns `node` unchanged when every field in
|
|
1482
|
+
* `changes` already equals (by reference) the current value, otherwise a new node
|
|
1483
|
+
* with the changes applied.
|
|
1484
|
+
*
|
|
1485
|
+
* Mirrors the TypeScript compiler's `factory.updateX` contract — pair it with the
|
|
1486
|
+
* structural sharing in {@link transform} so a no-op rewrite doesn't allocate and
|
|
1487
|
+
* downstream passes can detect "nothing changed" by identity. Comparison is
|
|
1488
|
+
* shallow: a structurally-equal but newly-allocated array/object counts as a change.
|
|
1489
|
+
*
|
|
1490
|
+
* @example
|
|
1491
|
+
* ```ts
|
|
1492
|
+
* update(node, { name: node.name }) // -> same `node` reference
|
|
1493
|
+
* update(node, { name: 'renamed' }) // -> new node, `name` replaced
|
|
1494
|
+
* ```
|
|
1495
|
+
*/
|
|
1496
|
+
function update(node, changes) {
|
|
1497
|
+
for (const key in changes) if (changes[key] !== node[key]) return {
|
|
1498
|
+
...node,
|
|
1499
|
+
...changes
|
|
1500
|
+
};
|
|
1501
|
+
return node;
|
|
1502
|
+
}
|
|
1503
|
+
/**
|
|
1466
1504
|
* Creates an `InputNode` with stable defaults for `schemas` and `operations`.
|
|
1467
1505
|
*
|
|
1468
1506
|
* @example
|
|
@@ -1527,35 +1565,35 @@ function createOutput(overrides = {}) {
|
|
|
1527
1565
|
};
|
|
1528
1566
|
}
|
|
1529
1567
|
/**
|
|
1530
|
-
* Creates
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
*
|
|
1540
|
-
* ```
|
|
1541
|
-
*
|
|
1542
|
-
* @example
|
|
1543
|
-
* ```ts
|
|
1544
|
-
* const operation = createOperation({
|
|
1545
|
-
* operationId: 'findPets',
|
|
1546
|
-
* method: 'GET',
|
|
1547
|
-
* path: '/pet/findByStatus',
|
|
1548
|
-
* tags: ['pet'],
|
|
1549
|
-
* })
|
|
1550
|
-
* ```
|
|
1568
|
+
* Creates a `ContentNode` for a single request-body or response content type.
|
|
1569
|
+
*/
|
|
1570
|
+
function createContent(props) {
|
|
1571
|
+
return {
|
|
1572
|
+
...props,
|
|
1573
|
+
kind: "Content"
|
|
1574
|
+
};
|
|
1575
|
+
}
|
|
1576
|
+
/**
|
|
1577
|
+
* Creates a `RequestBodyNode`, normalizing each content entry into a `ContentNode`.
|
|
1551
1578
|
*/
|
|
1579
|
+
function createRequestBody(props) {
|
|
1580
|
+
return {
|
|
1581
|
+
...props,
|
|
1582
|
+
kind: "RequestBody",
|
|
1583
|
+
content: props.content?.map(createContent)
|
|
1584
|
+
};
|
|
1585
|
+
}
|
|
1552
1586
|
function createOperation(props) {
|
|
1587
|
+
const { requestBody, ...rest } = props;
|
|
1588
|
+
const isHttp = rest.method !== void 0 && rest.path !== void 0;
|
|
1553
1589
|
return {
|
|
1554
1590
|
tags: [],
|
|
1555
1591
|
parameters: [],
|
|
1556
1592
|
responses: [],
|
|
1557
|
-
...
|
|
1558
|
-
|
|
1593
|
+
...rest,
|
|
1594
|
+
...isHttp ? { protocol: "http" } : {},
|
|
1595
|
+
kind: "Operation",
|
|
1596
|
+
requestBody: requestBody ? createRequestBody(requestBody) : void 0
|
|
1559
1597
|
};
|
|
1560
1598
|
}
|
|
1561
1599
|
/**
|
|
@@ -1683,14 +1721,15 @@ function createParameter(props) {
|
|
|
1683
1721
|
*/
|
|
1684
1722
|
function createResponse(props) {
|
|
1685
1723
|
const { schema, mediaType, keysToOmit, content, ...rest } = props;
|
|
1724
|
+
const entries = content ?? (schema ? [{
|
|
1725
|
+
contentType: mediaType ?? "application/json",
|
|
1726
|
+
schema,
|
|
1727
|
+
keysToOmit: keysToOmit ?? null
|
|
1728
|
+
}] : void 0);
|
|
1686
1729
|
return {
|
|
1687
1730
|
...rest,
|
|
1688
1731
|
kind: "Response",
|
|
1689
|
-
content:
|
|
1690
|
-
contentType: mediaType ?? "application/json",
|
|
1691
|
-
schema,
|
|
1692
|
-
keysToOmit: keysToOmit ?? null
|
|
1693
|
-
}] : void 0)
|
|
1732
|
+
content: entries?.map(createContent)
|
|
1694
1733
|
};
|
|
1695
1734
|
}
|
|
1696
1735
|
/**
|
|
@@ -2326,6 +2365,7 @@ exports.containsCircularRef = containsCircularRef;
|
|
|
2326
2365
|
exports.createArrowFunction = createArrowFunction;
|
|
2327
2366
|
exports.createBreak = createBreak;
|
|
2328
2367
|
exports.createConst = createConst;
|
|
2368
|
+
exports.createContent = createContent;
|
|
2329
2369
|
exports.createDiscriminantNode = createDiscriminantNode;
|
|
2330
2370
|
exports.createExport = createExport;
|
|
2331
2371
|
exports.createFile = createFile;
|
|
@@ -2343,6 +2383,7 @@ exports.createParameterGroup = createParameterGroup;
|
|
|
2343
2383
|
exports.createParamsType = createParamsType;
|
|
2344
2384
|
exports.createPrinterFactory = createPrinterFactory;
|
|
2345
2385
|
exports.createProperty = createProperty;
|
|
2386
|
+
exports.createRequestBody = createRequestBody;
|
|
2346
2387
|
exports.createResponse = createResponse;
|
|
2347
2388
|
exports.createSchema = createSchema;
|
|
2348
2389
|
exports.createSource = createSource;
|
|
@@ -2350,12 +2391,15 @@ exports.createStreamInput = createStreamInput;
|
|
|
2350
2391
|
exports.createText = createText;
|
|
2351
2392
|
exports.createType = createType;
|
|
2352
2393
|
exports.definePrinter = definePrinter;
|
|
2394
|
+
exports.defineSchemaDialect = defineSchemaDialect;
|
|
2395
|
+
exports.dispatch = dispatch;
|
|
2353
2396
|
exports.enumPropName = enumPropName;
|
|
2354
2397
|
exports.extractRefName = extractRefName;
|
|
2355
2398
|
exports.extractStringsFromNodes = extractStringsFromNodes;
|
|
2356
2399
|
exports.findCircularSchemas = findCircularSchemas;
|
|
2357
2400
|
exports.findDiscriminator = findDiscriminator;
|
|
2358
2401
|
exports.httpMethods = httpMethods;
|
|
2402
|
+
exports.isHttpOperationNode = isHttpOperationNode;
|
|
2359
2403
|
exports.isInputNode = isInputNode;
|
|
2360
2404
|
exports.isOperationNode = isOperationNode;
|
|
2361
2405
|
exports.isOutputNode = isOutputNode;
|
|
@@ -2375,6 +2419,7 @@ exports.simplifyUnion = simplifyUnion;
|
|
|
2375
2419
|
exports.syncOptionality = syncOptionality;
|
|
2376
2420
|
exports.syncSchemaRef = syncSchemaRef;
|
|
2377
2421
|
exports.transform = transform;
|
|
2422
|
+
exports.update = update;
|
|
2378
2423
|
exports.walk = walk;
|
|
2379
2424
|
|
|
2380
2425
|
//# sourceMappingURL=index.cjs.map
|