@techspokes/typescript-wsdl-client 0.30.1 → 0.31.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/README.md CHANGED
@@ -232,6 +232,7 @@ See [CLI Reference](docs/cli-reference.md) for all flags and examples.
232
232
  | [Programmatic API](docs/api-reference.md) | TypeScript functions for build tools |
233
233
  | [Core Concepts](docs/concepts.md) | Flattening, $value, primitives, determinism |
234
234
  | [Architecture](docs/architecture.md) | Internal pipeline for contributors |
235
+ | [File Naming And Path Organization](docs/file-naming-and-path-organization.md) | Contributor convention for taxonomy paths and fixture retrieval |
235
236
  | [Agent Skill Artifact](docs/agent-skill.md) | Release ZIP for consumer-project AI agents |
236
237
  | [Version 1.0 Roadmap Plan](docs/roadmap/README.md) | Conformance framework, implementation slices, and release gates for 1.0 |
237
238
  | [Streamable Responses (ADR-002)](docs/decisions/002-streamable-responses.md) | Opt-in streaming: client `AsyncIterable`, gateway NDJSON or JSON array, `x-wsdl-tsc-stream` |
@@ -38,6 +38,10 @@ export type CompiledWildcard = {
38
38
  namespace?: string;
39
39
  processContents?: "lax" | "strict" | "skip";
40
40
  };
41
+ export type CompiledAttributeWildcard = {
42
+ namespace?: string;
43
+ processContents?: "lax" | "strict" | "skip";
44
+ };
41
45
  export type CompiledChoiceBranch = {
42
46
  name: string;
43
47
  tsType: string;
@@ -68,6 +72,7 @@ export type CompiledChoiceGroup = {
68
72
  * @property {Array<Object>} [localAttrs] - Attributes added in extension (not inherited)
69
73
  * @property {Array<Object>} [localElems] - Elements added in extension (not inherited)
70
74
  * @property {Array<Object>} [wildcards] - xs:any wildcard particles retained on the type
75
+ * @property {Array<Object>} [attributeWildcards] - xs:anyAttribute wildcards retained on the type
71
76
  */
72
77
  export type CompiledType = {
73
78
  name: string;
@@ -108,6 +113,7 @@ export type CompiledType = {
108
113
  doc?: string;
109
114
  }>;
110
115
  wildcards?: CompiledWildcard[];
116
+ attributeWildcards?: CompiledAttributeWildcard[];
111
117
  choiceGroups?: CompiledChoiceGroup[];
112
118
  localChoiceGroups?: CompiledChoiceGroup[];
113
119
  };
@@ -1 +1 @@
1
- {"version":3,"file":"schemaCompiler.d.ts","sourceRoot":"","sources":["../../src/compiler/schemaCompiler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,yBAAyB,CAAC;AAIzD,OAAO,KAAK,EAAC,uBAAuB,EAAE,YAAY,EAAC,MAAM,yBAAyB,CAAC;AAEnF;;;;;;GAMG;AACH,MAAM,MAAM,KAAK,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAElD;;;;;;;;GAQG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,oBAAoB,EAAE,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,KAAK,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;QAC9B,YAAY,EAAE,MAAM,CAAC;QACrB,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;IACH,KAAK,EAAE,KAAK,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC;QAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,UAAU,CAAC,EAAE,KAAK,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;QAC9B,YAAY,EAAE,MAAM,CAAC;QACrB,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;IAEH,UAAU,CAAC,EAAE,KAAK,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC;QAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;IAGH,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAG/B,YAAY,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACrC,iBAAiB,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC3C,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,KAAK,CAAC;IAChB,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,KAAK,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACpC,QAAQ,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACpC,QAAQ,CAAC,EAAE,sBAAsB,EAAE,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,aAAa,CAAC,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,CAAC,EAAE,uBAAuB,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,eAAe,CAAC;IACzB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,IAAI,EAAE;QACJ,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACnC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QACjD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QAClD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;KAC/C,CAAC;IACF,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,WAAW,CAAC,EAAE,mBAAmB,CAAC;CACnC,CAAC;AAwJF;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,WAAW,EAChB,OAAO,EAAE,eAAe,EACxB,YAAY,CAAC,EAAE,YAAY,GAC1B,eAAe,CAm9BjB"}
1
+ {"version":3,"file":"schemaCompiler.d.ts","sourceRoot":"","sources":["../../src/compiler/schemaCompiler.ts"],"names":[],"mappings":"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"}
@@ -143,6 +143,79 @@ function extractAnnotationDocumentation(node) {
143
143
  .join(" ");
144
144
  return normalizeDocText(merged);
145
145
  }
146
+ function localName(name) {
147
+ return name.includes(":") ? name.split(":").pop() : name;
148
+ }
149
+ function isTruthyXmlBoolean(value) {
150
+ return String(value).trim().toLowerCase() === "true" || String(value).trim() === "1";
151
+ }
152
+ function getAttributeByLocalName(node, name) {
153
+ if (!node || typeof node !== "object") {
154
+ return undefined;
155
+ }
156
+ for (const [key, value] of Object.entries(node)) {
157
+ if (key.startsWith("@_") && localName(key.slice(2)) === name) {
158
+ return value;
159
+ }
160
+ }
161
+ return undefined;
162
+ }
163
+ function hasAttributeByLocalName(node, name) {
164
+ if (Array.isArray(node)) {
165
+ return node.some(child => hasAttributeByLocalName(child, name));
166
+ }
167
+ if (!node || typeof node !== "object") {
168
+ return false;
169
+ }
170
+ if (getAttributeByLocalName(node, name) !== undefined) {
171
+ return true;
172
+ }
173
+ return Object.entries(node)
174
+ .filter(([key]) => !key.startsWith("@_"))
175
+ .some(([, value]) => hasAttributeByLocalName(value, name));
176
+ }
177
+ function rejectUnsupportedSchemaConstructs(cat) {
178
+ for (const schema of cat.schemas) {
179
+ for (const element of getChildrenWithLocalName(schema.xml, "element")) {
180
+ const substitutionGroup = getAttributeByLocalName(element, "substitutionGroup");
181
+ if (substitutionGroup) {
182
+ throw new WsdlCompilationError(`Unsupported XSD substitution group on element "${element["@_name"] ?? "(anonymous)"}".`, {
183
+ element: String(element["@_name"] ?? ""),
184
+ namespace: schema.targetNS,
185
+ file: cat.wsdlUri,
186
+ suggestion: "Substitution groups require polymorphic element expansion. Remove the substitution group or model the accepted concrete element explicitly before generation.",
187
+ });
188
+ }
189
+ }
190
+ for (const complexType of getChildrenWithLocalName(schema.xml, "complexType")) {
191
+ if (isTruthyXmlBoolean(getAttributeByLocalName(complexType, "abstract"))) {
192
+ throw new WsdlCompilationError(`Unsupported abstract complex type "${complexType["@_name"] ?? "(anonymous)"}".`, {
193
+ element: String(complexType["@_name"] ?? ""),
194
+ namespace: schema.targetNS,
195
+ file: cat.wsdlUri,
196
+ suggestion: "Abstract complex types require polymorphic instance handling. Use a concrete type or add support for explicit abstract type diagnostics before generation.",
197
+ });
198
+ }
199
+ }
200
+ for (const element of getChildrenWithLocalName(schema.xml, "element")) {
201
+ if (isTruthyXmlBoolean(getAttributeByLocalName(element, "abstract"))) {
202
+ throw new WsdlCompilationError(`Unsupported abstract element "${element["@_name"] ?? "(anonymous)"}".`, {
203
+ element: String(element["@_name"] ?? ""),
204
+ namespace: schema.targetNS,
205
+ file: cat.wsdlUri,
206
+ suggestion: "Abstract elements require substitution or polymorphic element handling. Use a concrete element before generation.",
207
+ });
208
+ }
209
+ }
210
+ if (hasAttributeByLocalName(schema.xml, "expectedContentTypes")) {
211
+ throw new WsdlCompilationError("Unsupported MTOM/XOP or XML MIME attachment metadata.", {
212
+ namespace: schema.targetNS,
213
+ file: cat.wsdlUri,
214
+ suggestion: "Attachment payloads require MIME or binary transport semantics that are outside the typed SOAP-to-REST generation contract.",
215
+ });
216
+ }
217
+ }
218
+ }
146
219
  /**
147
220
  * Compile a WSDL catalog into an internal representation (CompiledCatalog).
148
221
  * Steps:
@@ -154,6 +227,7 @@ function extractAnnotationDocumentation(node) {
154
227
  * portType reference, then enumerate operations and their soapAction URIs.
155
228
  */
156
229
  export function compileCatalog(cat, options, streamConfig) {
230
+ rejectUnsupportedSchemaConstructs(cat);
157
231
  // symbol tables discovered across all schemas
158
232
  const complexTypes = new Map();
159
233
  const simpleTypes = new Map();
@@ -213,6 +287,30 @@ export function compileCatalog(cat, options, streamConfig) {
213
287
  }
214
288
  return { tsType: xsdToTsPrimitive(declared, options?.primitive), declared };
215
289
  }
290
+ const union = getFirstWithLocalName(simpleNode, "union");
291
+ if (union) {
292
+ const members = [];
293
+ const memberTypes = String(union["@_memberTypes"] ?? "")
294
+ .split(/\s+/)
295
+ .map(value => value.trim())
296
+ .filter(Boolean);
297
+ for (const memberType of memberTypes) {
298
+ const q = resolveQName(memberType, schemaNS, prefixes);
299
+ members.push(resolveTypeRef(q, schemaNS, prefixes));
300
+ }
301
+ for (const inlineSimple of getChildrenWithLocalName(union, "simpleType")) {
302
+ members.push(compileSimpleTypeNode(inlineSimple, schemaNS, prefixes));
303
+ }
304
+ if (members.length > 0) {
305
+ const tsTypes = Array.from(new Set(members.flatMap(member => member.tsType.split("|").map(part => part.trim()))));
306
+ const declared = members.map(member => member.declared).join(" | ");
307
+ return {
308
+ tsType: tsTypes.join(" | "),
309
+ declared,
310
+ jsdoc: JSON.stringify({ kind: "union", members: members.map(member => member.declared) }),
311
+ };
312
+ }
313
+ }
216
314
  const list = getFirstWithLocalName(simpleNode, "list");
217
315
  if (list?.["@_itemType"]) {
218
316
  const q = resolveQName(list["@_itemType"], schemaNS, prefixes);
@@ -398,6 +496,17 @@ export function compileCatalog(cat, options, streamConfig) {
398
496
  recurse(node);
399
497
  return out;
400
498
  };
499
+ const collectAttributeWildcards = (node) => {
500
+ const out = [];
501
+ for (const a of getChildrenWithLocalName(node, "anyAttribute")) {
502
+ const pc = a["@_processContents"];
503
+ out.push({
504
+ ...(a["@_namespace"] ? { namespace: a["@_namespace"] } : {}),
505
+ ...(pc === "lax" || pc === "strict" || pc === "skip" ? { processContents: pc } : {}),
506
+ });
507
+ }
508
+ return out;
509
+ };
401
510
  const readOccurrence = (node) => {
402
511
  const min = node["@_minOccurs"] ? Number(node["@_minOccurs"]) : 1;
403
512
  const maxAttr = node["@_maxOccurs"];
@@ -542,12 +651,16 @@ export function compileCatalog(cat, options, streamConfig) {
542
651
  const newAttrs = collectAttributes(cnode);
543
652
  const newElems = collectParticles(outName, cnode);
544
653
  const newWildcards = collectWildcards(cnode);
654
+ const newAttributeWildcards = collectAttributeWildcards(cnode);
545
655
  const newChoiceGroups = collectChoiceGroups(outName, cnode);
546
656
  mergeAttrs(present.attrs, newAttrs);
547
657
  mergeElems(present.elems, newElems);
548
658
  if (newWildcards.length > 0) {
549
659
  present.wildcards = [...(present.wildcards ?? []), ...newWildcards];
550
660
  }
661
+ if (newAttributeWildcards.length > 0) {
662
+ present.attributeWildcards = [...(present.attributeWildcards ?? []), ...newAttributeWildcards];
663
+ }
551
664
  const mergedChoiceGroups = mergeChoiceGroups(present.choiceGroups, newChoiceGroups);
552
665
  if (mergedChoiceGroups && mergedChoiceGroups.length > 0) {
553
666
  present.choiceGroups = mergedChoiceGroups;
@@ -562,6 +675,7 @@ export function compileCatalog(cat, options, streamConfig) {
562
675
  // result accumulators
563
676
  const attrs = [];
564
677
  const elems = [];
678
+ const attributeWildcards = [];
565
679
  const choiceGroups = [];
566
680
  // Inheritance: complexContent
567
681
  const complexContent = getFirstWithLocalName(cnode, "complexContent");
@@ -582,6 +696,7 @@ export function compileCatalog(cat, options, streamConfig) {
582
696
  // inherit base members
583
697
  attrs.push(...baseType.attrs);
584
698
  elems.push(...baseType.elems);
699
+ attributeWildcards.push(...(baseType.attributeWildcards ?? []));
585
700
  choiceGroups.push(...(baseType.choiceGroups ?? []));
586
701
  }
587
702
  }
@@ -589,9 +704,11 @@ export function compileCatalog(cat, options, streamConfig) {
589
704
  const locals = collectAttributes(node);
590
705
  const localElems = collectParticles(outName, node);
591
706
  const localWildcards = collectWildcards(node);
707
+ const localAttributeWildcards = collectAttributeWildcards(node);
592
708
  const localChoiceGroups = collectChoiceGroups(outName, node);
593
709
  attrs.push(...locals);
594
710
  elems.push(...localElems);
711
+ attributeWildcards.push(...localAttributeWildcards);
595
712
  choiceGroups.push(...localChoiceGroups);
596
713
  const result = {
597
714
  name: outName,
@@ -603,6 +720,7 @@ export function compileCatalog(cat, options, streamConfig) {
603
720
  localAttrs: locals,
604
721
  localElems,
605
722
  ...(localWildcards.length > 0 ? { wildcards: localWildcards } : {}),
723
+ ...(attributeWildcards.length > 0 ? { attributeWildcards } : {}),
606
724
  ...(choiceGroups.length > 0 ? { choiceGroups } : {}),
607
725
  ...(localChoiceGroups.length > 0 ? { localChoiceGroups } : {}),
608
726
  };
@@ -632,7 +750,15 @@ export function compileCatalog(cat, options, streamConfig) {
632
750
  declaredType: r.declared,
633
751
  }]);
634
752
  mergeAttrs(attrs, collectAttributes(scNode));
635
- const result = { name: outName, ns: schemaNS, attrs, elems, doc: typeDoc };
753
+ const attributeWildcards = collectAttributeWildcards(scNode);
754
+ const result = {
755
+ name: outName,
756
+ ns: schemaNS,
757
+ attrs,
758
+ elems,
759
+ doc: typeDoc,
760
+ ...(attributeWildcards.length > 0 ? { attributeWildcards } : {}),
761
+ };
636
762
  compiledMap.set(key, result);
637
763
  inProgress.delete(rawKey);
638
764
  return result;
@@ -648,6 +774,7 @@ export function compileCatalog(cat, options, streamConfig) {
648
774
  mergeAttrs(attrs, collectAttributes(cnode));
649
775
  mergeElems(elems, collectParticles(outName, cnode));
650
776
  const wildcards = collectWildcards(cnode);
777
+ attributeWildcards.push(...collectAttributeWildcards(cnode));
651
778
  choiceGroups.push(...collectChoiceGroups(outName, cnode));
652
779
  const result = {
653
780
  name: outName,
@@ -656,6 +783,7 @@ export function compileCatalog(cat, options, streamConfig) {
656
783
  elems,
657
784
  doc: typeDoc,
658
785
  ...(wildcards.length > 0 ? { wildcards } : {}),
786
+ ...(attributeWildcards.length > 0 ? { attributeWildcards } : {}),
659
787
  ...(choiceGroups.length > 0 ? { choiceGroups } : {}),
660
788
  };
661
789
  compiledMap.set(key, result);
@@ -251,6 +251,10 @@ function canonicalizeType(t) {
251
251
  namespace: w.namespace ?? null,
252
252
  processContents: w.processContents ?? null,
253
253
  })),
254
+ attributeWildcards: (t.attributeWildcards ?? []).map((w) => ({
255
+ namespace: w.namespace ?? null,
256
+ processContents: w.processContents ?? null,
257
+ })),
254
258
  choiceGroups: (t.choiceGroups ?? []).map((g) => ({
255
259
  name: g.name,
256
260
  min: g.min,
@@ -1 +1 @@
1
- {"version":3,"file":"generateSchemas.d.ts","sourceRoot":"","sources":["../../src/openapi/generateSchemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAgB,eAAe,EAAe,MAAM,+BAA+B,CAAC;AAEhG;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACrC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAkNpD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,sBAAsB,GAAG,iBAAiB,CA2D1G"}
1
+ {"version":3,"file":"generateSchemas.d.ts","sourceRoot":"","sources":["../../src/openapi/generateSchemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAgB,eAAe,EAAe,MAAM,+BAA+B,CAAC;AAEhG;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACrC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAwPpD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,sBAAsB,GAAG,iBAAiB,CA2D1G"}
@@ -8,6 +8,10 @@ function isLiteralUnion(ts) {
8
8
  }
9
9
  return null;
10
10
  }
11
+ function unionParts(ts) {
12
+ const parts = ts.split("|").map(p => p.trim()).filter(Boolean);
13
+ return parts.length > 1 ? parts : null;
14
+ }
11
15
  function primitiveSchema(ts) {
12
16
  switch (ts) {
13
17
  case "string":
@@ -25,6 +29,27 @@ function primitiveSchema(ts) {
25
29
  return { $ref: `#/components/schemas/${ts}` };
26
30
  }
27
31
  }
32
+ function schemaForUnionPart(ts) {
33
+ if (/^".*"$/.test(ts)) {
34
+ return { type: "string", enum: [ts.slice(1, -1)] };
35
+ }
36
+ return primitiveSchema(ts);
37
+ }
38
+ function mixedUnionSchema(ts) {
39
+ const parts = unionParts(ts);
40
+ if (!parts)
41
+ return null;
42
+ const schemas = parts.map(schemaForUnionPart);
43
+ const stringEnums = schemas
44
+ .filter((schema) => schema.type === "string" && Array.isArray(schema.enum))
45
+ .flatMap(schema => schema.enum);
46
+ const rest = schemas.filter(schema => !(schema.type === "string" && Array.isArray(schema.enum)));
47
+ const oneOf = [
48
+ ...(stringEnums.length > 0 ? [{ type: "string", enum: Array.from(new Set(stringEnums)) }] : []),
49
+ ...rest,
50
+ ];
51
+ return { oneOf };
52
+ }
28
53
  function buildAliasSchema(a) {
29
54
  const lit = isLiteralUnion(a.tsType);
30
55
  if (lit) {
@@ -34,6 +59,13 @@ function buildAliasSchema(a) {
34
59
  ...(a.doc ? { description: a.doc } : {}),
35
60
  };
36
61
  }
62
+ const union = mixedUnionSchema(a.tsType);
63
+ if (union) {
64
+ return {
65
+ ...union,
66
+ ...(a.doc ? { description: a.doc } : {}),
67
+ };
68
+ }
37
69
  // If alias wraps primitive
38
70
  if (["string", "number", "boolean", "any"].includes(a.tsType) || a.tsType.endsWith("[]")) {
39
71
  return {
@@ -86,6 +118,10 @@ function buildComplexSchema(t, closed, knownTypeNames, aliasNames, flattenWrappe
86
118
  if (lit) {
87
119
  return { type: "string", enum: lit };
88
120
  }
121
+ const union = mixedUnionSchema(ts);
122
+ if (union) {
123
+ return union;
124
+ }
89
125
  if (ts.endsWith("[]")) {
90
126
  const inner = ts.slice(0, -2);
91
127
  return { type: "array", items: refOrPrimitive(inner) };
package/docs/README.md CHANGED
@@ -28,6 +28,7 @@ Human-maintained reference documents for `@techspokes/typescript-wsdl-client`. T
28
28
  - [api-reference.md](api-reference.md): programmatic TypeScript API
29
29
  - [concepts.md](concepts.md): flattening, `$value`, primitives, determinism
30
30
  - [architecture.md](architecture.md): internal pipeline for contributors
31
+ - [file-naming-and-path-organization.md](file-naming-and-path-organization.md): contributor convention for taxonomy paths and fixture retrieval
31
32
  - [agent-skill.md](agent-skill.md): release ZIP for consumer-project AI agents
32
33
  - [roadmap/README.md](roadmap/README.md): conformance framework, implementation slices, and release gates for 1.0
33
34
  - [decisions/002-streamable-responses.md](decisions/002-streamable-responses.md): opt-in streaming design (client `AsyncIterable`, gateway NDJSON or JSON array, `x-wsdl-tsc-stream` OpenAPI extension); shipped in 0.17.0 and extended in 0.28.0
@@ -38,6 +39,7 @@ Human-maintained reference documents for `@techspokes/typescript-wsdl-client`. T
38
39
  - Each document opens with an H1 title and a one-line description.
39
40
  - Cross-reference related documents and the root README where relevant.
40
41
  - Use fenced code blocks for CLI examples; format flags as inline code (`` `--flag-name` ``).
42
+ - Use `bash` fences for portable command examples; reserve `powershell` fences for Windows-specific commands.
41
43
  - Run `npm run docs:validate` to check local links and TypeScript fenced snippets.
42
44
  - Keep language direct and task-oriented; architecture.md targets contributors, all others target users.
43
45
 
@@ -0,0 +1,207 @@
1
+ # File Naming And Path Organization
2
+
3
+ Contributor guide for naming files and organizing fixture paths. See the root [README.md](../README.md) for the authoritative documentation index.
4
+
5
+ ## Purpose
6
+
7
+ Paths should classify files before a reader opens them. The left side of a path carries the broadest concept; each segment to the right narrows the classification until the filename states the exact artifact purpose.
8
+
9
+ This convention is especially important for conformance fixtures. A maintainer should be able to search or list paths and see which WSDL, XSD, SOAP, policy, and recovery concepts already have evidence.
10
+
11
+ ## Authority Model
12
+
13
+ This convention borrows from resource-oriented API design. REST APIs commonly use noun-based paths, hierarchy through `/`, and readable lowercase path segments.
14
+
15
+ Google AIP-122 describes resource names as slash-separated paths and says collection identifiers are usually plural nouns. Zalando REST guidelines require plural resource names, kebab-case path segments, verb-free URLs, and domain-specific resource names. Microsoft Azure API guidelines prefer kebab-casing for URL path segments. REST URI naming guidance uses nouns for resources, `/` for hierarchy, and hyphens for readability.
16
+
17
+ Filesystem paths are not REST APIs, but the same retrieval model applies: a path is a resource name for a contributor, a terminal command, an IDE index, and an agent.
18
+
19
+ ## Shell Examples
20
+
21
+ Use `bash` fences for portable command examples in repository documentation and GitHub workflow notes. Use `powershell` fences only when the command is intentionally Windows-specific.
22
+
23
+ Prefer `rg` for retrieval examples because agents already use it for fast file and content search. Write path filters so they tolerate `/` and `\` separators when possible.
24
+
25
+ On Windows PowerShell, keep `rg` regex arguments in single quotes when the pattern contains backslashes, brackets, or alternation. The examples in this document were checked in PowerShell with single-quoted regexes. A no-match `rg` filter exits with code `1`; that is expected for negative checks such as confirming `service.wsdl` is absent.
26
+
27
+ ## Progressive Discovery
28
+
29
+ Start broad, then narrow. A path should answer these questions from left to right:
30
+
31
+ 1. What repository area owns this artifact?
32
+ 2. What artifact family is this?
33
+ 3. What standards domain or product domain does it belong to?
34
+ 4. What feature family does it exercise?
35
+ 5. What exact purpose does the file serve?
36
+
37
+ For conformance fixtures, this means the preferred shape is:
38
+
39
+ ```text
40
+ test/conformance/fixtures/<domain>/<feature-family>/<feature-name>.<ext>
41
+ ```
42
+
43
+ Use deeper nesting only when it improves retrieval. Do not create a folder level that only repeats the filename.
44
+
45
+ ## Folder Names
46
+
47
+ Folder names are taxonomy terms. They classify a set of files.
48
+
49
+ - Use lowercase kebab-case.
50
+ - Prefer one noun per segment.
51
+ - Prefer plural nouns when the term is naturally countable.
52
+ - Preserve standards terms when pluralizing them would reduce clarity.
53
+ - Avoid verbs, implementation steps, and filler words.
54
+ - Place the broadest useful classifier on the left.
55
+ - Add a narrower folder only when it groups multiple related files or distinguishes a standards boundary.
56
+
57
+ Acceptable standards-domain folders include `wsdl`, `xsd`, `soap`, `ws-policy`, `ws-security`, `interop`, and `recovery`.
58
+
59
+ Acceptable feature-family folders include `types`, `elements`, `bindings`, `policies`, `attachments`, `wildcards`, `compositors`, `sequences`, and `choices`.
60
+
61
+ ## File Names
62
+
63
+ File names state the exact purpose and content of the artifact. They should remain useful when shown without the full path.
64
+
65
+ - Use lowercase kebab-case.
66
+ - Use general-to-specific segment order.
67
+ - Put the broad feature classifier first.
68
+ - Put variable-like qualifiers at the right side.
69
+ - Keep recognized standards terms when they identify the feature.
70
+ - Avoid filler words such as `service`, `sample`, `fixture`, and `test`.
71
+ - Use the file extension to identify format, not the basename.
72
+
73
+ Good file names classify sorted terminal output:
74
+
75
+ ```text
76
+ attachment-mtom-xop.wsdl
77
+ binding-soap-first-multi.wsdl
78
+ choice-union-simple.wsdl
79
+ element-substitution-group.wsdl
80
+ policy-reference-external.wsdl
81
+ sequence-composition-deep.wsdl
82
+ type-complex-abstract-extension.wsdl
83
+ type-union-simple.wsdl
84
+ wildcard-attribute-any.wsdl
85
+ ```
86
+
87
+ Avoid names that only read naturally in English but group poorly in file listings:
88
+
89
+ ```text
90
+ abstract-complex-type-extension.wsdl
91
+ any-attribute.wsdl
92
+ deep-sequence-composition.wsdl
93
+ mtom-xop-attachment.wsdl
94
+ multi-binding-first-soap.wsdl
95
+ xs-union-simple-type.wsdl
96
+ ```
97
+
98
+ ## Conformance Fixtures
99
+
100
+ Conformance fixtures should be committed XML files, not inline strings in tests. Inline XML is acceptable only for throwaway probes or very small unit tests that do not represent a reusable fixture.
101
+
102
+ The fixture path should support discovery by partial path search. A contributor should be able to search `xsd/wildcards`, `soap/attachments`, or `wsdl/bindings` and see what exists.
103
+
104
+ The registry ID should remain stable for test reporting. The fixture path may use taxonomy folders and a more precise filename when that improves retrieval.
105
+
106
+ ## Multi-file Fixtures
107
+
108
+ Use a folder when a fixture needs a root WSDL plus imported schemas or companion files. Keep the root filename aligned with the feature name.
109
+
110
+ ```text
111
+ test/conformance/fixtures/xsd/wildcards/wildcard-attribute-any.wsdl
112
+ test/conformance/fixtures/xsd/wildcards/wildcard-attribute-any-types.xsd
113
+ test/conformance/fixtures/xsd/wildcards/wildcard-attribute-any-shared.xsd
114
+ ```
115
+
116
+ Use purpose suffixes such as `types`, `messages`, `shared`, `policy`, and `binding` for companion files.
117
+
118
+ ## Retrieval Examples
119
+
120
+ List every conformance fixture path:
121
+
122
+ ```bash
123
+ rg --files test/conformance/fixtures | sort
124
+ ```
125
+
126
+ Find every XSD wildcard fixture:
127
+
128
+ ```bash
129
+ rg --files test/conformance/fixtures | rg '(^|[\\/])xsd[\\/]wildcards[\\/]'
130
+ ```
131
+
132
+ Find whether a SOAP attachment fixture exists:
133
+
134
+ ```bash
135
+ rg --files test/conformance/fixtures | rg '(^|[\\/])attachment-'
136
+ ```
137
+
138
+ Use `rg` when searching by concept inside paths or XML content:
139
+
140
+ ```bash
141
+ rg -n "xs:anyAttribute|wildcard-attribute" test\conformance\fixtures
142
+ ```
143
+
144
+ ## Agent Retrieval Playbook
145
+
146
+ Agents should prefer a small number of focused file-system checks before adding or renaming fixtures. These commands are intentionally simple and use portable `rg` patterns.
147
+
148
+ Check the current taxonomy shape:
149
+
150
+ ```bash
151
+ rg --files test/conformance/fixtures | sort
152
+ ```
153
+
154
+ Check whether a domain branch already exists:
155
+
156
+ ```bash
157
+ rg --files test/conformance/fixtures | rg '(^|[\\/])xsd[\\/]types[\\/]'
158
+ ```
159
+
160
+ Find fixtures by filename classifier:
161
+
162
+ ```bash
163
+ rg --files test/conformance/fixtures | rg '(^|[\\/])type-'
164
+ ```
165
+
166
+ Find fixtures by XML feature content:
167
+
168
+ ```bash
169
+ rg -n "xs:union|xs:anyAttribute|substitutionGroup|PolicyReference" test\conformance\fixtures
170
+ ```
171
+
172
+ Check whether old filler names are still present:
173
+
174
+ ```bash
175
+ rg --files test/conformance/fixtures | rg '(^|[\\/])service\.wsdl'
176
+ ```
177
+
178
+ Find the registry row that owns a fixture path:
179
+
180
+ ```bash
181
+ rg -n "wildcard-attribute-any|type-union-simple|attachment-mtom-xop" test\conformance\registry.ts
182
+ ```
183
+
184
+ Use these commands as discovery checks, not as validation gates. Repository validation still runs through `npm run docs:validate`, `npm run test:conformance`, and `npm test`.
185
+
186
+ ## Candidate Fixture Paths
187
+
188
+ Use these paths as the target direction for the current conformance corpus:
189
+
190
+ ```text
191
+ test/conformance/fixtures/xsd/compositors/choice-union-simple.wsdl
192
+ test/conformance/fixtures/xsd/types/type-union-simple.wsdl
193
+ test/conformance/fixtures/xsd/types/type-complex-abstract-extension.wsdl
194
+ test/conformance/fixtures/xsd/elements/element-substitution-group.wsdl
195
+ test/conformance/fixtures/wsdl/bindings/binding-soap-first-multi.wsdl
196
+ test/conformance/fixtures/ws-policy/references/policy-reference-external.wsdl
197
+ test/conformance/fixtures/xsd/sequences/sequence-composition-deep.wsdl
198
+ test/conformance/fixtures/xsd/wildcards/wildcard-attribute-any.wsdl
199
+ test/conformance/fixtures/soap/attachments/attachment-mtom-xop.wsdl
200
+ ```
201
+
202
+ ## References
203
+
204
+ - [Google AIP-122 Resource Names](https://google.aip.dev/122)
205
+ - [Zalando RESTful API Guidelines](https://opensource.zalando.com/restful-api-guidelines/)
206
+ - [Microsoft Azure API Guidelines](https://github.com/microsoft/api-guidelines/blob/vNext/azure/Guidelines.md)
207
+ - [REST API URI Naming Conventions](https://restfulapi.net/resource-naming/)
@@ -0,0 +1,30 @@
1
+ # TypeScript WSDL Client v0.30.2
2
+
3
+ ## Conformance fixture foundation
4
+
5
+ This patch release adds the first capability conformance fixture corpus, records `xs:anyAttribute` wildcard metadata, and documents a reusable taxonomy for fixture paths and file names.
6
+
7
+ ## What This Improves
8
+
9
+ Maintainers now have a fixture-backed way to classify WSDL and XSD support claims before 1.0. The conformance registry makes supported, partial, diagnostic, unsupported, and research rows explicit, while taxonomy-based fixture paths make it easier to discover existing XML coverage through ordinary file-system search.
10
+
11
+ ## Highlights
12
+
13
+ - Added Phase 1 conformance registry tests and reusable WSDL fixtures.
14
+ - Retained `xs:anyAttribute` declarations as compiled type metadata.
15
+ - Documented taxonomy-based fixture path organization and portable retrieval commands.
16
+
17
+ ## Upgrade Notes
18
+
19
+ No special upgrade steps.
20
+
21
+ ## Validation
22
+
23
+ - Dependency maintenance completed successfully.
24
+ - Documentation validation passed.
25
+ - Test suite passed.
26
+ - Smoke pipeline passed.
27
+
28
+ ## Notes
29
+
30
+ Release tag: `v0.30.2`.
@@ -0,0 +1,33 @@
1
+ # TypeScript WSDL Client v0.30.3
2
+
3
+ ## Fixture-Backed Support Evidence
4
+
5
+ This patch release adds simple `xs:union` support and makes the public support matrix generated from the conformance registry.
6
+
7
+ ## What This Improves
8
+
9
+ Developers using WSDLs with simple `xs:union` aliases now get honest TypeScript union aliases and OpenAPI `oneOf` schemas instead of an under-modeled type. Maintainers also get a generated support matrix that keeps public documentation aligned with fixture-backed conformance rows.
10
+
11
+ The release process guidance now makes the tag gate explicit: development commit titles may use the next patch target, but release tags require package metadata, changelog, release notes, and preflight checks to match first.
12
+
13
+ ## Highlights
14
+
15
+ - Simple `xs:union` aliases now compile to TypeScript unions.
16
+ - Mixed primitive and literal unions now emit OpenAPI `oneOf` schemas.
17
+ - The public capability evidence matrix is generated from the conformance registry.
18
+ - Agent instructions now require release preflight before pushing release tags.
19
+
20
+ ## Upgrade Notes
21
+
22
+ No special upgrade steps.
23
+
24
+ ## Validation
25
+
26
+ - CI passed.
27
+ - NPM package contents were validated.
28
+ - Agent skill artifact was validated and packaged.
29
+ - Release preflight passed against the target tag.
30
+
31
+ ## Notes
32
+
33
+ Release tag: `v0.30.3`.
@@ -0,0 +1,33 @@
1
+ # TypeScript WSDL Client v0.31.0
2
+
3
+ ## Conformance Evidence Moves Downstream
4
+
5
+ This release extends the WSDL capability conformance framework beyond compile-only checks and adds diagnostics for unsupported schema constructs that previously risked silent miscompilation.
6
+
7
+ ## What This Improves
8
+
9
+ Maintainers can now prove supported and partial WSDL capability rows through generated TypeScript clients and validated OpenAPI specs, not only through catalog compilation. This makes the support matrix more trustworthy and gives future gateway-runtime work a stronger base.
10
+
11
+ Unsupported abstract types, substitution groups, and MTOM/XOP-style attachment metadata now fail with structured diagnostics instead of compiling into misleading contracts.
12
+
13
+ ## Highlights
14
+
15
+ - Adds generated client type-check evidence for supported and partial WSDL conformance rows.
16
+ - Adds OpenAPI validation and targeted schema assertions for supported and partial WSDL conformance rows.
17
+ - Rejects abstract complex types, substitution groups, and XML MIME attachment metadata with diagnostics.
18
+ - Updates the roadmap so the next 1.0 slice is gateway runtime conformance evidence.
19
+
20
+ ## Upgrade Notes
21
+
22
+ WSDLs that declare abstract complex types, substitution groups, or XML MIME attachment metadata now fail during compilation with a diagnostic. This is intentional because those constructs require polymorphic or attachment transport semantics that are not part of the current typed SOAP-to-REST contract.
23
+
24
+ ## Validation
25
+
26
+ - CI passed.
27
+ - NPM package contents were validated.
28
+ - Agent skill artifact was validated and packaged.
29
+ - Release preflight passed against the target tag.
30
+
31
+ ## Notes
32
+
33
+ Release tag: `v0.31.0`.
@@ -18,8 +18,8 @@ The plan is optimized for preserving quality. The contract and compatibility bas
18
18
  | OpenAPI compatibility | [OpenAPI Fastify Compatibility](v1.0-openapi-fastify-compatibility.md) | baseline complete | Schema strategy is proven |
19
19
  | Choice union mode | [Choice Union Mode](v1.0-choice-union-mode.md) | complete | Implemented in `0.26.0` |
20
20
  | JSON array streaming | [JSON Array Streaming](v1.0-json-array-streaming.md) | complete | Implemented in `0.28.0` |
21
- | Conformance framework | [Capability Conformance Framework](v1.0-capability-conformance-framework.md) | planned | Pipeline claims are test-backed |
22
- | WSDL coverage matrix | [WSDL Coverage Matrix](v1.0-wsdl-coverage-matrix.md) | remaining | Feature support is test-backed |
21
+ | Conformance framework | [Capability Conformance Framework](v1.0-capability-conformance-framework.md) | phase 2 shipped | Pipeline claims are test-backed |
22
+ | WSDL coverage matrix | [WSDL Coverage Matrix](v1.0-wsdl-coverage-matrix.md) | client and OpenAPI evidence shipped | Feature support is test-backed |
23
23
  | Release candidate | [Release Candidate Gates](v1.0-release-candidate-gates.md) | remaining | 1.0 release is repeatable |
24
24
 
25
25
  ## Execution Order
@@ -42,11 +42,11 @@ JSON array streaming is complete in `0.28.0`. The default `ndjson` format remain
42
42
 
43
43
  ### Slice 5: Capability Conformance Framework
44
44
 
45
- Build the conformance registry, fixture strategy, stage runners, and issue-triage model. This slice turns feature claims into testable pipeline-wide capability cases.
45
+ The registry, fixture strategy, compile runner, client evidence, OpenAPI evidence, documentation drift check, and generated support matrix are shipped. The next work is to extend relevant rows into gateway runtime evidence without expanding public APIs.
46
46
 
47
47
  ### Slice 6: WSDL Coverage Matrix
48
48
 
49
- Build the automated WSDL feature matrix next. The matrix should drive the remaining WSDL support, diagnostic, and deferral decisions.
49
+ The first WSDL matrix rows now exist as conformance registry entries with compile, client, OpenAPI, and documentation evidence. The next work is to prove relevant rows through generated gateway runtime artifacts.
50
50
 
51
51
  ### Slice 7: Release Candidate Gates
52
52
 
@@ -54,9 +54,9 @@ Run the release candidate gates after feature work and documentation have conver
54
54
 
55
55
  ## Remaining Before 1.0
56
56
 
57
- - Build the capability conformance registry and compile-stage runner.
58
- - Build and run the WSDL feature matrix as the first conformance domain.
59
- - Turn unsupported or partial matrix rows into diagnostics, documentation, or scoped fixes.
57
+ - Extend the capability registry beyond OpenAPI evidence into gateway runtime evidence.
58
+ - Add generated gateway checks for supported and partial WSDL rows where HTTP behavior is part of the contract.
59
+ - Turn remaining unsupported, diagnostic, or partial matrix rows into diagnostics, documentation, or scoped fixes.
60
60
  - Confirm `docs/supported-patterns.md` matches the matrix.
61
61
  - Run the release-candidate gates.
62
62
 
@@ -1,9 +1,11 @@
1
1
  # Version 1.0 Capability Conformance Framework
2
2
 
3
- Status: planned before `1.0.0`.
3
+ Status: Phase 2 shipped; gateway runtime evidence remaining before `1.0.0`.
4
4
 
5
5
  Plan for turning SOAP, WSDL, OpenAPI, gateway, app, generated-test, and documentation support claims into fixture-backed conformance evidence.
6
6
 
7
+ Phase 1 shipped a TypeScript registry, reusable WSDL fixtures, compile-stage runner, documentation drift tests, and generated public support matrix. Phase 2 added generated client type-checking, OpenAPI validation, and executable diagnostics for terminal rows. The next slice should extend relevant rows into gateway runtime evidence before adding more feature rows.
8
+
7
9
  See the root [README.md](../../README.md) for project overview and [Version 1.0 Roadmap Plan](README.md) for the complete 1.0 route.
8
10
 
9
11
  ## Goal
@@ -75,6 +77,8 @@ The generated test stage proves `--test-dir` emits tests that compile and pass f
75
77
 
76
78
  The documentation stage proves `docs/supported-patterns.md` agrees with the capability registry. It should prevent docs from claiming support, partial support, or non-support without a matching conformance row.
77
79
 
80
+ The public evidence matrix in `docs/supported-patterns.md` should be generated from registry rows. The rest of the page should remain human-authored so supported-pattern explanations stay useful to readers.
81
+
78
82
  ## Registry Shape
79
83
 
80
84
  The first implementation should use a TypeScript manifest because tests can import it with full type safety. JSON can be added later if external tooling needs a stable data format.
@@ -89,12 +93,173 @@ interface CapabilityCase {
89
93
  featureTags: string[];
90
94
  fixture: string;
91
95
  docsAnchor?: string;
96
+ publicContract: string;
92
97
  stages: CapabilityStages;
93
98
  }
94
99
  ```
95
100
 
96
101
  Stage payloads should stay small and explicit. Avoid a generic assertion language in the first version; use typed expectation objects and small runner helpers instead.
97
102
 
103
+ ## Standards And External Corpus
104
+
105
+ Use WSDL 1.1, SOAP 1.1, XML Schema 1.0, and WS-I Basic Profile as the authority stack for Phase 1 capability expectations.
106
+
107
+ WSDL 1.1 defines the service description model used by this project: `types`, `message`, `portType`, `binding`, `port`, and `service`, plus SOAP 1.1, HTTP, and MIME binding extensions.
108
+
109
+ SOAP 1.1 defines the envelope and processing model that generated clients ultimately target through `node-soap`.
110
+
111
+ XML Schema 1.0 defines the schema constructs compiled into TypeScript and OpenAPI shapes. XML Schema 1.1 test suites are useful as edge-case inspiration, but the project should not imply full XML Schema 1.1 support.
112
+
113
+ WS-I Basic Profile 1.1 and 1.2 define interoperability constraints across SOAP, WSDL, XML Schema, and HTTP. Treat WS-I rules as the best available profile for portable SOAP behavior, not as a complete fixture source.
114
+
115
+ Do not vendor third-party WSDL or XSD corpora wholesale in Phase 1. Prefer minimized synthetic fixtures derived from standard rules and clearly cite the relevant standard or profile section in the registry row.
116
+
117
+ Third-party suites can inform future rows:
118
+
119
+ - W3C WSDL 2.0 Test Suite: useful for conformance-suite structure, but not directly applicable to this WSDL 1.1 generator.
120
+ - W3C XML Schema test suite: useful for XSD edge-case discovery, but it validates schema processors rather than WSDL-to-client generation.
121
+ - WS-I test assertions and analyzer tools: useful for interoperability rule vocabulary, but heavy and not a direct TypeScript generation oracle.
122
+ - Apache Axis or Apache CXF sample WSDL files: useful as real-world smoke candidates when license and fixture scope are clear.
123
+
124
+ ## Public Fixture Corpus Direction
125
+
126
+ The conformance framework should be designed so its fixtures can later seed a standalone public project, tentatively named `wsdl-conformance-fixtures`.
127
+
128
+ The public fixture project would be an experimental, curated corpus of small WSDL and XSD fixtures for SOAP client and code-generation tools. It should not claim to be an official standards suite. It should provide practical, source-backed examples for valid, partial, diagnostic, unsupported, recovery, and real-world-compatible behaviors.
129
+
130
+ The public corpus should preserve clean licensing and clear provenance. Do not copy external corpora wholesale. Prefer original minimized fixtures derived from standards, profiles, and observed real-world patterns.
131
+
132
+ Phase 1 should add metadata that will make extraction possible later without changing every row:
133
+
134
+ - `authority`: the standard, profile, or real-world source category behind the case.
135
+ - `provenance`: a short explanation of whether the fixture is original, minimized from a report, or inspired by a third-party example.
136
+ - `license`: the fixture license or repository default license.
137
+ - `fixtureKind`: one of `standards-valid`, `interop-profile`, `real-world-compatible`, `diagnostic-required`, or `recovery`.
138
+
139
+ Do not publish the standalone fixture project before the internal registry has proven the metadata shape with multiple useful rows. The first public release should happen only after maintainers can explain how another tool would consume the fixtures without depending on this repository's internals.
140
+
141
+ ## Fixture Corpus Goals
142
+
143
+ The internal corpus should serve this repository first. It should make generator behavior explicit, prevent silent miscompilation, and give maintainers a repeatable way to classify WSDL reports.
144
+
145
+ The future public corpus should serve the SOAP tooling community. It should offer small, understandable fixtures that other generators, validators, and migration tools can run against or inspect.
146
+
147
+ The corpus should distinguish standards conformance from product policy. A fixture can be standards-valid while unsupported by this generator, or non-ideal but common enough to justify recovery behavior.
148
+
149
+ The corpus should be useful without a live network. Every fixture should be committed with local relative imports and no dependency on public SOAP endpoints.
150
+
151
+ The corpus should be explainable. Each fixture should say what behavior it exercises, what source justifies the expectation, and which outcomes are acceptable.
152
+
153
+ ## Decision Framework
154
+
155
+ Use this framework before changing a capability from `research` to a final status. The decision should optimize for truthful generation, deterministic output, and maintainable SOAP modernization rather than broad standards completeness.
156
+
157
+ First decide whether the construct is important enough for this project. Favor support when the feature is common in WSDLs, important for enterprise modernization, or already required by existing generated outputs. Favor deferral when the feature is rare, can be worked around, or requires a runtime contract outside the current product surface.
158
+
159
+ Then decide whether the construct can be modeled honestly in `catalog.json`. If the catalog can represent the shape without losing semantics, support or partial support may be appropriate. If the catalog would hide polymorphism, transport behavior, binary parts, external network policy, or runtime ambiguity, prefer a diagnostic or unsupported decision.
160
+
161
+ Then check downstream stages. A `supported` row must work through every relevant stage. A feature that compiles but cannot be represented in generated TypeScript, OpenAPI, gateway runtime, or generated tests should be `partial` unless those stages do not apply.
162
+
163
+ Then check implementation locality. Local schema transforms such as simple aliases, deterministic metadata retention, and documented first-choice behavior are good support candidates. Features that require broad runtime semantics, wire-protocol changes, or public API design should usually become diagnostics or explicit deferrals before 1.0.
164
+
165
+ Use these decisions:
166
+
167
+ - `support`: implement and prove the feature through relevant stages.
168
+ - `partial-support`: implement the honest subset and document the limit.
169
+ - `diagnostic`: reject or warn clearly to avoid silent miscompilation.
170
+ - `defer`: keep a fixture and rationale, but do not claim support yet.
171
+ - `out-of-scope`: document that the feature is intentionally outside the 1.0 product contract.
172
+
173
+ When full support is clearly local, deterministic, and representable, implement it rather than leaving unnecessary diagnostics. When full support would imply semantics the generator cannot preserve, prefer diagnostics over partial, misleading output.
174
+
175
+ ## Phase 1 Decisions
176
+
177
+ Phase 1 shipped in the `0.30.x` line. Keep this section as the historical baseline and as guardrails for future registry changes.
178
+
179
+ Phase 1 is internal test infrastructure. It must not add exports from `src/index.ts`, new public CLI commands, or new consumer-facing APIs.
180
+
181
+ The first registry should live under `test/conformance/registry.ts`. It should export types and data for repository tests only. Public package exports can be reconsidered after the inspector has a stable use case.
182
+
183
+ The first runner should live under `test/conformance/runner.ts`. It should execute compile-stage checks by calling `loadWsdl`, `compileCatalog`, and `resolveCompilerOptions` directly.
184
+
185
+ The first Vitest entry point should be `test/conformance/conformance.test.ts`. Add `npm run test:conformance` and keep it included in `npm test` through Vitest's normal test discovery.
186
+
187
+ Fixtures should live under `test/conformance/fixtures/`. Each fixture should be a committed `.wsdl` or `.xsd` file, use relative files only, and require no network access.
188
+
189
+ Documentation drift checks should start as a lightweight test in `test/conformance/docs.test.ts`. The test should verify that each registry row with a `docsAnchor` points to an existing heading anchor in `docs/supported-patterns.md`.
190
+
191
+ The public evidence matrix should be generated from the registry with `npm run docs:support-matrix`. The check command should fail when the generated table and committed table drift.
192
+
193
+ ## Phase 1 File Map
194
+
195
+ The Phase 1 file map is implemented. Keep these ownership boundaries in place while extending the framework.
196
+
197
+ `test/conformance/types.ts` owns shared registry types. Keep these types out of `src/` until a public API is justified.
198
+
199
+ `test/conformance/registry.ts` owns the initial capability rows. Include new priority features from the WSDL coverage matrix here before changing generator behavior.
200
+
201
+ `test/conformance/runner.ts` owns compile-stage execution helpers. Resolve fixture paths relative to `test/conformance/fixtures/` and create one temporary output directory per case under the OS temp directory.
202
+
203
+ `test/conformance/conformance.test.ts` owns manifest-driven compile tests. Supported and partial rows should compile successfully; diagnostic rows should assert the error shape or explicit warning behavior.
204
+
205
+ `test/conformance/docs.test.ts` owns registry-to-docs alignment. It should validate existing heading anchors and prove that the public evidence matrix matches generated registry output.
206
+
207
+ `test/conformance/fixtures/` contains minimal WSDL fixtures. Keep each fixture synthetic, deterministic, and scoped to one capability.
208
+
209
+ `package.json` exposes `test:conformance` with `vitest run test/conformance`.
210
+
211
+ Modify `docs/supported-patterns.md` only when the registry reveals a real mismatch. Generate only the evidence matrix from the registry in Phase 1; do not rewrite the explanatory sections from registry data.
212
+
213
+ ## Phase 1 Type Contract
214
+
215
+ Use these internal test types as the starting point:
216
+
217
+ ```ts
218
+ export type CapabilityStatus = "supported" | "partial" | "diagnostic" | "unsupported" | "research";
219
+
220
+ export type CompileExpectation =
221
+ | { outcome: "success"; typeNames?: string[]; aliasNames?: string[]; operationNames?: string[]; diagnosticNotes?: string[] }
222
+ | { outcome: "error"; errorClass?: "WsdlCompilationError"; messageIncludes?: string[]; userMessageIncludes?: string[]; context?: Partial<WsdlErrorContext> }
223
+ | { outcome: "research"; reason: string };
224
+
225
+ export interface CapabilityCase {
226
+ id: string;
227
+ title: string;
228
+ status: CapabilityStatus;
229
+ featureTags: string[];
230
+ fixture: string;
231
+ docsAnchor?: string;
232
+ publicContract: string;
233
+ decision: CapabilityDecision;
234
+ decisionReason: string;
235
+ compile: CompileExpectation;
236
+ }
237
+ ```
238
+
239
+ `docsAnchor` values should use the same heading slug rules as the repository docs validator. Phase 1 may point rows to broad section anchors such as `fully-supported`, `partially-supported`, `not-yet-supported`, or `known-edge-cases`. Add feature-level headings to `docs/supported-patterns.md` only when a broad section anchor is too ambiguous for a row.
240
+
241
+ `error` expectations should assert `instanceof WsdlCompilationError` when `errorClass` is `WsdlCompilationError`. `messageIncludes` checks should inspect `error.message`, `userMessageIncludes` checks should inspect `error.toUserMessage()`, and `context` checks should inspect `error.context`.
242
+
243
+ `unsupported` rows should not silently pass. They should either use an `error` compile expectation or remain `research` until a diagnostic exists.
244
+
245
+ `partial` rows should compile successfully only when the limitation is explicitly documented. The row should include a `docsAnchor` and an assertion that proves the supported subset.
246
+
247
+ `research` rows should not pretend to validate support. They should load the fixture only if useful, then state the unresolved decision in the registry.
248
+
249
+ ## Phase 1 Conventions
250
+
251
+ Prefer committed fixture files over inline WSDL strings. Inline WSDL builders are useful for focused unit tests, but conformance cases should be inspectable as standalone artifacts.
252
+
253
+ Use the taxonomy path convention in [File Naming And Path Organization](../file-naming-and-path-organization.md) for reusable fixtures. Put imported schemas beside the root WSDL when a capability needs multiple files.
254
+
255
+ Use a runner-owned temporary directory per capability case. Do not share a module-level temp root across the suite, because conformance failures should leave case-local paths easy to inspect.
256
+
257
+ Assert catalog shape through stable names and metadata. Avoid full catalog snapshots in Phase 1 because the registry should describe capability contracts, not freeze incidental serialization details.
258
+
259
+ Assert diagnostics through `WsdlCompilationError` and catalog `diagnostics.notes`. Do not assert full formatted messages unless the exact text is part of the public contract.
260
+
261
+ Prefer adding feature-level headings in `docs/supported-patterns.md` when a broad section anchor would make the docs check too weak. Keep those headings short and user-facing.
262
+
98
263
  ## Fixture Strategy
99
264
 
100
265
  Fixtures should live under a dedicated conformance fixture directory, separate from the weather smoke fixture. Each fixture should be minimal, synthetic, deterministic, and focused on one capability unless the purpose is to prove a composition case.
@@ -140,7 +305,21 @@ The inspector should not be treated as proof that generation will succeed. It is
140
305
 
141
306
  ## Phase 1: Registry And Compile Matrix
142
307
 
143
- Create the capability registry, fixture directory, and a Vitest runner for compile-stage expectations. Include the existing roadmap priority rows and keep unsupported rows diagnostic or research-only until behavior is proven.
308
+ The capability registry, fixture directory, and Vitest runner for compile-stage expectations are implemented. Keep unsupported rows diagnostic or research-only until behavior is proven.
309
+
310
+ Start with these capability IDs:
311
+
312
+ | ID | Status | Compile expectation |
313
+ |---|---|---|
314
+ | `choice-union-simple` | supported | success |
315
+ | `xs-union-simple-type` | supported | success |
316
+ | `abstract-complex-type` | diagnostic | error or research |
317
+ | `substitution-group-element` | diagnostic | error or research |
318
+ | `multi-binding-first-soap` | partial | success with documented behavior |
319
+ | `external-policy-reference` | partial | success with documented limitation |
320
+ | `deep-composition-sequence` | supported | success |
321
+ | `xs-anyattribute` | partial | success with metadata retention |
322
+ | `mtom-xop-attachment` | unsupported | error or research |
144
323
 
145
324
  Acceptance criteria:
146
325
 
@@ -148,9 +327,14 @@ Acceptance criteria:
148
327
  - Each row has a stable ID, status, fixture, and compile expectation.
149
328
  - `docs/supported-patterns.md` has matching capability IDs or anchors.
150
329
  - The runner works without network access.
330
+ - `npm run test:conformance` passes.
331
+ - `npm test` includes the conformance suite.
332
+ - No Phase 1 change expands the public API.
151
333
 
152
334
  ## Phase 2: Client And OpenAPI Evidence
153
335
 
336
+ Phase 2 is implemented for the current supported and partial WSDL rows. Keep this section as the baseline for future client and OpenAPI evidence.
337
+
154
338
  Extend supported rows to generate clients and OpenAPI specs. Add type-check verification for generated clients and schema assertions for OpenAPI output.
155
339
 
156
340
  Acceptance criteria:
@@ -160,6 +344,22 @@ Acceptance criteria:
160
344
  - Capability-specific schema strategies are asserted where they matter.
161
345
  - Diagnostic rows stop before downstream stages.
162
346
 
347
+ Recommended scope:
348
+
349
+ - Add optional `client` and `openapi` expectation blocks to `CapabilityCase`.
350
+ - Generate artifacts into a temporary directory owned by each capability row.
351
+ - Emit a temporary `tsconfig.json` that includes generated client artifacts and uses repository NodeNext settings.
352
+ - Validate OpenAPI documents through the same validator used by existing OpenAPI tests.
353
+ - Assert public schema contracts for rows that already claim support or partial support.
354
+
355
+ Skeptical review notes:
356
+
357
+ - A `supported` status should not rely on compile-only evidence after this phase.
358
+ - `diagnostic` rows currently using `research` compile expectations need either real diagnostics or clearer deferral language.
359
+ - Whole-file snapshots would make conformance brittle; prefer targeted assertions on generated types, schemas, paths, and operation metadata.
360
+ - The support matrix generator should remain limited to the public evidence table, not the human-authored explanatory sections.
361
+ - Keep the inspector out of this slice unless the stage evidence reveals a stable detection model.
362
+
163
363
  ## Phase 3: Gateway Runtime Evidence
164
364
 
165
365
  Extend relevant rows to generate gateways and test Fastify runtime behavior through `fastify.inject`. Add mock operations clients and request/response fixtures as part of the registry.
@@ -206,8 +406,6 @@ Acceptance criteria:
206
406
 
207
407
  ## Open Decisions
208
408
 
209
- - Decide whether the first registry lives under `test/fixtures` or `test/conformance`.
210
- - Decide whether conformance should be a normal `npm test` suite or a separate script at first.
211
409
  - Decide how much generated output type-checking is acceptable in CI runtime.
212
410
  - Decide which inspector output format becomes public before `1.0.0`.
213
411
  - Decide whether docs should remain manually maintained or eventually generated from the registry.
@@ -1,9 +1,11 @@
1
1
  # Version 1.0 WSDL Coverage Matrix
2
2
 
3
- Status: remaining before `1.0.0`.
3
+ Status: client and OpenAPI evidence shipped; gateway runtime evidence remaining before `1.0.0`.
4
4
 
5
5
  Plan for turning WSDL and XSD support claims into automated, fixture-backed evidence before 1.0. This is the first domain under the [Capability Conformance Framework](v1.0-capability-conformance-framework.md).
6
6
 
7
+ The initial fixture-backed compile matrix shipped in `0.30.2` and `0.30.3`. Client and OpenAPI evidence now prove the current supported and partial rows, and terminal rows have executable diagnostics. The remaining work is to prove generated gateway runtime artifacts and keep public support claims tied to registry rows.
8
+
7
9
  See the root [README.md](../../README.md) for project overview and [Version 1.0 Roadmap Plan](README.md) for the complete 1.0 route.
8
10
 
9
11
  ## Goal
@@ -14,32 +16,44 @@ The project should have an automated WSDL and XSD feature matrix that proves whi
14
16
 
15
17
  Each matrix row should have a minimal fixture, an expected support status, and a test that proves the status. A supported feature must compile and generate aligned client, OpenAPI, and gateway artifacts where applicable. An unsupported feature must fail with a clear diagnostic or be documented as intentionally out of scope.
16
18
 
17
- ## Scope
19
+ ## Shipped Baseline
20
+
21
+ - `test/conformance/fixtures/` contains the first priority WSDL fixture set.
22
+ - `test/conformance/registry.ts` lists priority rows with status, decision, provenance, and public contract text.
23
+ - `test/conformance/conformance.test.ts` runs compile-stage expectations for runnable rows.
24
+ - Supported and partial rows generate client artifacts that type-check.
25
+ - Supported and partial rows generate validated OpenAPI specs with targeted contract assertions.
26
+ - Diagnostic and unsupported rows have executable compiler error expectations.
27
+ - `docs/supported-patterns.md` includes a generated capability evidence matrix.
28
+ - `npm run docs:support-matrix:check` prevents support matrix drift.
29
+
30
+ ## Remaining Scope
18
31
 
19
- - Add a fixture directory for WSDL feature coverage.
20
- - Add a manifest that lists features, status, expected commands, and expected diagnostics.
21
- - Add Vitest coverage that reads the manifest and runs the relevant generation steps.
22
- - Update `docs/supported-patterns.md` from the matrix findings.
23
- - Include priority gaps from the roadmap.
32
+ - Add stage expectations for generated gateway output and runtime behavior.
33
+ - Add generated request and response fixtures where HTTP behavior is part of a capability contract.
34
+ - Keep diagnostics executable as more unsupported rows are added.
35
+ - Keep fixture metadata useful for a future public conformance fixture corpus.
36
+ - Preserve the weather smoke fixture as the canonical end-to-end happy path.
24
37
 
25
38
  ## Out Of Scope
26
39
 
27
40
  - Do not implement every unsupported WSDL feature in this slice.
28
41
  - Do not replace the existing weather fixture for smoke tests.
29
- - Do not make docs generated from the manifest unless that is a deliberate later decision.
42
+ - Do not generate the explanatory supported-pattern sections from the registry.
43
+ - Do not add public CLI commands for the inspector until the registry evidence model stabilizes.
30
44
 
31
45
  ## Priority Feature Rows
32
46
 
33
47
  | Feature | Expected 1.0 Status | Notes |
34
48
  |----------------------------|-------------------------|---------------------------------------|
35
49
  | `xs:choice` union mode | supported | Implemented in `0.26.0` |
36
- | `xs:union` | supported or diagnostic | Decide after fixture work |
50
+ | `xs:union` | supported | Simple unions implemented after fixture work |
37
51
  | Abstract types | diagnostic | Avoid silent concrete treatment |
38
52
  | Substitution groups | diagnostic | Avoid silent omission |
39
53
  | Multi-binding WSDLs | documented behavior | First binding or explicit selection |
40
54
  | External `PolicyReference` | partial or diagnostic | Inline policy already exists |
41
55
  | Deep composition | supported | Prove current recursion behavior |
42
- | `xs:anyAttribute` | diagnostic | Current support is not full |
56
+ | `xs:anyAttribute` | partial | Metadata retained; generated wildcard attributes deferred |
43
57
  | MTOM/XOP attachments | unsupported diagnostic | Keep out of 1.0 scope unless required |
44
58
 
45
59
  ## Manifest Shape
@@ -63,16 +77,20 @@ The manifest should be small and reviewable. A JSON or TypeScript manifest is ac
63
77
 
64
78
  ### Matrix Runner
65
79
 
66
- Create a Vitest suite that reads the manifest and executes the requested commands through programmatic APIs where possible. CLI smoke behavior should remain covered by existing smoke scripts.
80
+ The existing Vitest suite reads the TypeScript registry and runs compile expectations through programmatic APIs. The next runner should generate artifacts into per-case temporary directories and avoid shelling out where direct generator APIs give better diagnostics.
67
81
 
68
82
  ### Supported Feature Tests
69
83
 
70
84
  For supported rows, assert successful compilation, generated TypeScript type-checking, OpenAPI validation, and gateway schema generation when applicable.
71
85
 
86
+ Generated client checks should verify that emitted `client.ts`, `types.ts`, `utils.ts`, and `operations.ts` type-check together. OpenAPI checks should validate the full spec and assert capability-specific schema shapes only where the shape is part of the public contract.
87
+
72
88
  ### Diagnostic Feature Tests
73
89
 
74
90
  For diagnostic rows, assert the exact error class or user-facing message shape. Avoid brittle full-message assertions unless the message is part of the public contract.
75
91
 
92
+ Rows marked `diagnostic` should not remain permanent `research` placeholders. If full diagnostics are not implemented in the next slice, the row should say `defer` or carry a clear unresolved decision rather than implying that diagnostic behavior already exists.
93
+
76
94
  ### Documentation Tests
77
95
 
78
96
  Ensure every documented unsupported or partial feature has a corresponding matrix row. This can be a lightweight consistency test that compares feature IDs with anchors or explicit markers in `docs/supported-patterns.md`.
@@ -80,12 +98,33 @@ Ensure every documented unsupported or partial feature has a corresponding matri
80
98
  ## Acceptance Criteria
81
99
 
82
100
  - The matrix includes every roadmap priority feature.
83
- - Supported rows have passing fixtures.
84
- - Unsupported rows fail with clear diagnostics.
101
+ - Supported rows have compile, client, and OpenAPI evidence when those stages apply.
102
+ - Unsupported or diagnostic rows fail with clear diagnostics, or are explicitly deferred without support claims.
85
103
  - `docs/supported-patterns.md` reflects the matrix.
86
104
  - No known feature silently miscompiles in matrix coverage.
87
105
  - The matrix can run in CI or release preflight without network access.
88
106
 
107
+ ## Next Slice
108
+
109
+ The next slice should implement Phase 3 gateway runtime evidence for the current registry rows before adding more feature rows. This keeps the matrix honest: support claims become pipeline evidence, while diagnostic and unsupported claims remain stopped before downstream generation.
110
+
111
+ Work items:
112
+
113
+ - Add optional `gateway` expectations to the conformance type model.
114
+ - Generate gateway artifacts from each relevant row's OpenAPI document.
115
+ - Type-check generated gateway artifacts with the generated client artifacts.
116
+ - Add mock operations clients and `fastify.inject` assertions where request or response behavior is part of the contract.
117
+ - Leave diagnostic and unsupported rows stopped at compile.
118
+ - Update the generated public support matrix only when a row status or public contract changes.
119
+
120
+ Gotchas:
121
+
122
+ - Do not overclaim `supported` when gateway behavior is relevant but unproven.
123
+ - Do not snapshot whole generated files for conformance rows; assert stable contract surfaces instead.
124
+ - Do not share temporary output directories across rows.
125
+ - Do not let diagnostic or unsupported rows proceed to client, OpenAPI, or gateway generation.
126
+ - Do not add a public inspector command in this slice.
127
+
89
128
  ## Release Implications
90
129
 
91
130
  This slice may reveal features that should be implemented before 1.0. It may also justify explicit post-1.0 deferrals if diagnostics and documentation are strong enough.
@@ -2,6 +2,24 @@
2
2
 
3
3
  This document lists the WSDL and XSD features handled by the generator, along with current limitations. For modeling details, see [Core Concepts](concepts.md).
4
4
 
5
+ ## Capability Evidence Matrix
6
+
7
+ The rows below are backed by committed conformance fixtures under `test/conformance/fixtures/`. Status means the current product contract, not the full standards surface.
8
+
9
+ <!-- support-matrix:start -->
10
+ | Capability ID | Status | Public contract |
11
+ |---|---|---|
12
+ | `choice-union-simple` | supported | `xs:choice` union mode retains choice metadata and drives generated TypeScript/OpenAPI constraints. |
13
+ | `xs-union-simple-type` | supported | Simple `xs:union` aliases compile to TypeScript unions and OpenAPI `oneOf` schemas. |
14
+ | `abstract-complex-type` | diagnostic | Abstract complex types are rejected with a diagnostic instead of being treated as concrete. |
15
+ | `substitution-group-element` | diagnostic | Substitution groups are rejected with a diagnostic instead of being silently omitted. |
16
+ | `multi-binding-first-soap` | partial | Multiple bindings are deterministic: the first SOAP binding is selected and all ports are documented. |
17
+ | `external-policy-reference` | partial | Inline policy hints are detected; external `PolicyReference` documents are not fetched or resolved. |
18
+ | `deep-composition-sequence` | supported | Deep nested sequences compile into deterministic type metadata. |
19
+ | `xs-anyattribute` | partial | `xs:anyAttribute` is retained as catalog metadata, but generated wildcard attributes are not emitted. |
20
+ | `mtom-xop-attachment` | unsupported | MTOM/XOP binary attachment metadata is rejected because attachment transport is outside the 1.0 typed SOAP-to-REST contract. |
21
+ <!-- support-matrix:end -->
22
+
5
23
  ## Fully Supported
6
24
 
7
25
  These patterns are handled end-to-end: WSDL parsing, TypeScript type generation, OpenAPI schema output, and gateway code generation.
@@ -9,6 +27,7 @@ These patterns are handled end-to-end: WSDL parsing, TypeScript type generation,
9
27
  - Complex types with `<xs:sequence>`, `<xs:all>`, and `<xs:choice>` compositors, including recursive nesting
10
28
  - Simple content with attributes using the `$value` pattern to preserve text content alongside attribute properties
11
29
  - Named simple type restrictions and enumerations emitted as TypeScript aliases and OpenAPI scalar schemas
30
+ - Named `xs:union` simple types emitted as TypeScript alias unions and OpenAPI `oneOf` schemas
12
31
  - Type inheritance through `<xs:extension>` and `<xs:restriction>` on both simple and complex content
13
32
  - Nested XSD imports across multiple schema files with relative and absolute URI resolution
14
33
  - Multiple namespaces with deterministic collision resolution via PascalCase uniqueness
@@ -65,15 +84,22 @@ Groups are inlined into the parent type during schema compilation. The group ide
65
84
 
66
85
  List types with an `itemType` attribute are detected and generate array types (`${itemType}[]`). Lists defined with inline simple types are not handled.
67
86
 
87
+ ### xs:union
88
+
89
+ Union types with `memberTypes` or inline simple type members are detected and generate TypeScript alias unions. Mixed primitive and literal unions generate OpenAPI `oneOf` schemas.
90
+
91
+ ### xs:anyAttribute
92
+
93
+ Attribute wildcards are retained as catalog metadata on the enclosing compiled type. They are not emitted as typed attribute properties in generated TypeScript or OpenAPI schemas.
94
+
68
95
  ## Not Yet Supported
69
96
 
70
97
  These features are not currently handled. Contributions are welcome.
71
98
 
72
- - Full `xs:any` serialization and `xs:anyAttribute`: arbitrary wildcard content is not emitted as a typed contract
73
- - `xs:union` types: only union members expressed as restriction enumerations are captured
74
- - Abstract types: treated as regular concrete types without substitution logic
75
- - Substitution groups: not resolved during schema compilation
76
- - MTOM/XOP binary attachments: no support for binary part handling
99
+ - Full `xs:any` serialization: arbitrary wildcard content is not emitted as a typed contract
100
+ - Abstract types: rejected with a diagnostic; no polymorphic instance handling
101
+ - Substitution groups: rejected with a diagnostic; no polymorphic element expansion
102
+ - MTOM/XOP binary attachments: rejected with a diagnostic; no binary part handling
77
103
  - WS-ReliableMessaging, WS-Addressing beyond basic headers
78
104
  - Custom serialization hooks for non-standard XML patterns
79
105
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@techspokes/typescript-wsdl-client",
3
- "version": "0.30.1",
3
+ "version": "0.31.0",
4
4
  "description": "Turn legacy WSDL/SOAP services into typed TypeScript clients, OpenAPI 3.1 specs, and production-ready Fastify REST gateways. Built for enterprise SOAP modernization.",
5
5
  "keywords": [
6
6
  "wsdl",
@@ -70,6 +70,7 @@
70
70
  "test:unit": "vitest run test/unit",
71
71
  "test:snap": "vitest run test/snapshot",
72
72
  "test:integration": "vitest run test/integration",
73
+ "test:conformance": "vitest run test/conformance",
73
74
  "test:watch": "vitest",
74
75
  "prepublishOnly": "npm run clean && npm run build && npm run package:validate",
75
76
  "smoke:reset": "npm run clean:tmp",
@@ -80,7 +81,9 @@
80
81
  "smoke:pipeline": "npm run smoke:reset && tsx src/cli.ts pipeline --wsdl-source examples/minimal/weather.wsdl --client-dir tmp/client --openapi-file tmp/openapi.json --gateway-dir tmp/gateway --gateway-service-name weather --gateway-version-prefix v1 --openapi-format json --init-app && tsc -p tsconfig.smoke.json",
81
82
  "smoke:app": "npm run smoke:reset && tsx src/cli.ts pipeline --wsdl-source examples/minimal/weather.wsdl --client-dir tmp/client --openapi-file tmp/openapi.json --gateway-dir tmp/gateway --gateway-service-name weather --gateway-version-prefix v1 --openapi-format json --openapi-servers https://example.com/api && tsx src/cli.ts app --client-dir tmp/client --gateway-dir tmp/gateway --openapi-file tmp/openapi.json --app-dir tmp/app --port 8080 && tsc -p tsconfig.smoke.json",
82
83
  "maint:deps": "node scripts/maint-deps.mjs",
83
- "docs:validate": "node scripts/validate-docs.mjs",
84
+ "docs:support-matrix": "tsx scripts/generate-support-matrix.ts",
85
+ "docs:support-matrix:check": "tsx scripts/generate-support-matrix.ts --check",
86
+ "docs:validate": "node scripts/validate-docs.mjs && npm run docs:support-matrix:check",
84
87
  "skill:validate": "node scripts/validate-agent-skill.mjs",
85
88
  "skill:package": "node scripts/build-agent-skill.mjs",
86
89
  "package:validate": "node scripts/validate-npm-package.mjs",