@techspokes/typescript-wsdl-client 0.27.0 → 0.29.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.
Files changed (40) hide show
  1. package/README.md +4 -4
  2. package/dist/app/generateApp.js +2 -2
  3. package/dist/gateway/generators.d.ts +3 -2
  4. package/dist/gateway/generators.d.ts.map +1 -1
  5. package/dist/gateway/generators.js +51 -9
  6. package/dist/openapi/generateOpenAPI.d.ts.map +1 -1
  7. package/dist/openapi/generateOpenAPI.js +4 -1
  8. package/dist/runtime/jsonArray.d.ts +24 -0
  9. package/dist/runtime/jsonArray.d.ts.map +1 -0
  10. package/dist/runtime/jsonArray.js +52 -0
  11. package/dist/test/generators.d.ts.map +1 -1
  12. package/dist/test/generators.js +25 -3
  13. package/docs/README.md +2 -2
  14. package/docs/api-reference.md +3 -1
  15. package/docs/architecture.md +1 -1
  16. package/docs/cli-reference.md +1 -1
  17. package/docs/concepts.md +2 -2
  18. package/docs/configuration.md +1 -0
  19. package/docs/decisions/002-streamable-responses.md +32 -10
  20. package/docs/gateway-guide.md +5 -10
  21. package/docs/generated-code.md +1 -1
  22. package/docs/migration-playbook.md +1 -1
  23. package/docs/migration.md +1 -1
  24. package/docs/output-anatomy.md +26 -4
  25. package/docs/production.md +2 -2
  26. package/docs/releases/v0.28.0.md +32 -0
  27. package/docs/releases/v0.29.0.md +32 -0
  28. package/docs/roadmap/README.md +31 -18
  29. package/docs/roadmap/v1.0-capability-conformance-framework.md +219 -0
  30. package/docs/roadmap/v1.0-contract-audit.md +14 -13
  31. package/docs/roadmap/v1.0-json-array-streaming.md +21 -19
  32. package/docs/roadmap/v1.0-openapi-fastify-compatibility.md +15 -13
  33. package/docs/roadmap/v1.0-release-candidate-gates.md +2 -0
  34. package/docs/roadmap/v1.0-wsdl-coverage-matrix.md +15 -13
  35. package/docs/start-here.md +4 -2
  36. package/docs/supported-patterns.md +1 -1
  37. package/docs/testing.md +1 -1
  38. package/docs/troubleshooting.md +1 -1
  39. package/package.json +5 -5
  40. package/src/runtime/jsonArray.ts +55 -0
@@ -1,45 +1,47 @@
1
1
  # Version 1.0 OpenAPI Fastify Compatibility
2
2
 
3
- Plan for proving schema choices against Fastify before changing choice union output or JSON array streaming output.
3
+ Status: compatibility baseline completed for `0.26.0` choice union mode and `0.28.0` JSON array streaming.
4
+
5
+ Plan for preserving Fastify compatibility as schema output evolves toward `1.0.0`.
4
6
 
5
7
  See the root [README.md](../../README.md) for project overview and [Version 1.0 Roadmap Plan](README.md) for the complete 1.0 route.
6
8
 
7
9
  ## Goal
8
10
 
9
- This slice confirms which OpenAPI 3.1 and JSON Schema constructs are safe for generated Fastify gateways. The result should constrain choice union mode, JSON array streaming, and any future schema complexity work.
11
+ This slice confirms which OpenAPI 3.1 and JSON Schema constructs are safe for generated Fastify gateways. The completed findings constrain released choice union mode, released JSON array streaming, and any future schema complexity work.
10
12
 
11
- ## Why This Slice Comes Before Implementation
13
+ ## Why This Slice Remains Active
12
14
 
13
15
  Fastify compatibility is part of the generated gateway contract. A TypeScript type shape can be correct while the generated OpenAPI schema is unusable for Fastify request validation or response serialization.
14
16
 
15
17
  ## Scope
16
18
 
17
- - Test `oneOf`, `anyOf`, and `allOf` request schemas through Fastify validation.
18
- - Test generated response schemas through Fastify serialization where applicable.
19
- - Test route schemas that omit response serialization for streamed responses.
20
- - Verify how schema complexity interacts with the existing response-depth safety limit.
19
+ - Maintain probes for `oneOf`, `anyOf`, and `allOf` request schemas through Fastify validation.
20
+ - Maintain probes for generated response schemas through Fastify serialization where applicable.
21
+ - Maintain probes for streamed routes that omit response serialization schemas.
22
+ - Keep the response-depth safety limit aware of schema composition.
21
23
  - Document the allowed schema strategy for choice union mode.
22
24
  - Document the allowed schema strategy for JSON array streaming.
23
25
 
24
26
  ## Out Of Scope
25
27
 
26
- - Do not implement choice union mode in this slice.
27
- - Do not implement JSON array streaming in this slice.
28
+ - Do not change shipped choice union behavior without new compatibility evidence.
29
+ - Do not change shipped JSON array streaming behavior without new compatibility evidence.
28
30
  - Do not change public WSDL feature coverage in this slice.
29
31
 
30
32
  ## Research Questions
31
33
 
32
34
  ### Choice Request Validation
33
35
 
34
- The research must determine whether `oneOf` with mutually exclusive object branches behaves correctly for request bodies. It must also determine whether additional branch exclusion properties are needed to reject payloads that send more than one choice branch.
36
+ The research determined that `oneOf` with mutually exclusive object branches needs peer exclusion constraints for request bodies. Additional branch exclusion properties are needed to reject payloads that send more than one choice branch.
35
37
 
36
38
  ### Choice Response Serialization
37
39
 
38
- The research must determine whether generated response schemas should use union constructs or stay envelope-based with permissive payload branches. If Fastify serialization becomes fragile, generated route response schemas must stay conservative.
40
+ The research determined that generated response schemas should stay conservative unless a future slice proves a stricter strategy. If Fastify serialization becomes fragile, generated route response schemas must stay conservative.
39
41
 
40
42
  ### JSON Array Streaming Schema
41
43
 
42
- The research must determine how to advertise an incrementally streamed JSON array in OpenAPI while keeping generated Fastify route schemas valid. Stream routes already omit normal response serialization because the response is not a single buffered object.
44
+ The research determined how to advertise an incrementally streamed JSON array in OpenAPI while keeping generated Fastify route schemas valid. Stream routes omit normal response serialization because the response is not a single buffered object.
43
45
 
44
46
  ## Local Fastify Findings
45
47
 
@@ -94,4 +96,4 @@ Use small synthetic schemas for compatibility probes. Do not require WSDL fixtur
94
96
 
95
97
  ## Release Implications
96
98
 
97
- This slice may ship without user-facing generator changes if it only adds tests and docs. If it changes schema generation defaults, it must be paired with snapshot updates and migration notes.
99
+ This slice shipped its released findings through the choice union and JSON array streaming work. Future schema-generation changes must be paired with compatibility probes, snapshot updates, and migration notes when behavior changes.
@@ -1,5 +1,7 @@
1
1
  # Version 1.0 Release Candidate Gates
2
2
 
3
+ Status: remaining final release preparation for `1.0.0`.
4
+
3
5
  Plan for validating that `1.0.0` is repeatable, documented, test-backed, and ready to publish.
4
6
 
5
7
  See the root [README.md](../../README.md) for project overview and [Version 1.0 Roadmap Plan](README.md) for the complete 1.0 route.
@@ -1,12 +1,14 @@
1
1
  # Version 1.0 WSDL Coverage Matrix
2
2
 
3
- Plan for turning WSDL and XSD support claims into automated, fixture-backed evidence before 1.0.
3
+ Status: remaining before `1.0.0`.
4
+
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).
4
6
 
5
7
  See the root [README.md](../../README.md) for project overview and [Version 1.0 Roadmap Plan](README.md) for the complete 1.0 route.
6
8
 
7
9
  ## Goal
8
10
 
9
- The project should have an automated feature matrix that proves which WSDL and XSD patterns are supported, partially supported, or rejected with diagnostics. The matrix should feed `docs/supported-patterns.md` and protect 1.0 from silent miscompilation.
11
+ The project should have an automated WSDL and XSD feature matrix that proves which patterns are supported, partially supported, or rejected with diagnostics. The matrix should feed the conformance registry, align with `docs/supported-patterns.md`, and protect 1.0 from silent miscompilation.
10
12
 
11
13
  ## Design Direction
12
14
 
@@ -28,17 +30,17 @@ Each matrix row should have a minimal fixture, an expected support status, and a
28
30
 
29
31
  ## Priority Feature Rows
30
32
 
31
- | Feature | Expected 1.0 Status | Notes |
32
- |---------|---------------------|-------|
33
- | `xs:choice` union mode | supported | Implemented in `0.26.0` |
34
- | `xs:union` | supported or diagnostic | Decide after fixture work |
35
- | Abstract types | diagnostic | Avoid silent concrete treatment |
36
- | Substitution groups | diagnostic | Avoid silent omission |
37
- | Multi-binding WSDLs | documented behavior | First binding or explicit selection |
38
- | External `PolicyReference` | partial or diagnostic | Inline policy already exists |
39
- | Deep composition | supported | Prove current recursion behavior |
40
- | `xs:anyAttribute` | diagnostic | Current support is not full |
41
- | MTOM/XOP attachments | unsupported diagnostic | Keep out of 1.0 scope unless required |
33
+ | Feature | Expected 1.0 Status | Notes |
34
+ |----------------------------|-------------------------|---------------------------------------|
35
+ | `xs:choice` union mode | supported | Implemented in `0.26.0` |
36
+ | `xs:union` | supported or diagnostic | Decide after fixture work |
37
+ | Abstract types | diagnostic | Avoid silent concrete treatment |
38
+ | Substitution groups | diagnostic | Avoid silent omission |
39
+ | Multi-binding WSDLs | documented behavior | First binding or explicit selection |
40
+ | External `PolicyReference` | partial or diagnostic | Inline policy already exists |
41
+ | Deep composition | supported | Prove current recursion behavior |
42
+ | `xs:anyAttribute` | diagnostic | Current support is not full |
43
+ | MTOM/XOP attachments | unsupported diagnostic | Keep out of 1.0 scope unless required |
42
44
 
43
45
  ## Manifest Shape
44
46
 
@@ -92,7 +92,9 @@ Minimal `stream.config.json`:
92
92
  }
93
93
  ```
94
94
 
95
- Stream operations return `StreamOperationResponse<RecordType>` on the client (`records: AsyncIterable<RecordType>`), emit `application/x-ndjson` on the gateway, and advertise the record schema in OpenAPI via the `x-wsdl-tsc-stream` extension.
95
+ Stream operations return `StreamOperationResponse<RecordType>` on the client (`records: AsyncIterable<RecordType>`), emit `application/x-ndjson` by default on the gateway, and advertise the record schema in OpenAPI via the `x-wsdl-tsc-stream` extension.
96
+
97
+ Set `"format": "json-array"` in the stream config when downstream clients need one `application/json` array document instead of NDJSON lines.
96
98
 
97
99
  Next: [ADR-002: Streamable Responses](decisions/002-streamable-responses.md) for rationale and terminal-error policy, then [Stream Configuration](configuration.md#stream-configuration) for the full file reference.
98
100
 
@@ -118,5 +120,5 @@ For more on scope boundaries, see the "When NOT to Use This" section of the [REA
118
120
  | Plan a full SOAP-to-REST migration | [Migration Playbook](migration-playbook.md) |
119
121
  | Set up testing for generated code | [Testing Guide](testing.md) |
120
122
  | Review all CLI flags | [CLI Reference](cli-reference.md) |
121
- | Opt specific operations into NDJSON streaming | [ADR-002](decisions/002-streamable-responses.md) and [Stream Configuration](configuration.md#stream-configuration) |
123
+ | Opt specific operations into response streaming | [ADR-002](decisions/002-streamable-responses.md) and [Stream Configuration](configuration.md#stream-configuration) |
122
124
  | Install package-specific agent guidance | [Agent Skill Artifact](agent-skill.md) |
@@ -20,7 +20,7 @@ These patterns are handled end-to-end: WSDL parsing, TypeScript type generation,
20
20
  - Circular type references detected and broken with minimal stub types
21
21
  - Multiple WSDL ports and bindings; the first SOAP binding is selected, all ports are documented in service metadata
22
22
  - SOAP 1.1 and SOAP 1.2 binding detection
23
- - Streamable SOAP responses, opt-in per operation via `--stream-config` (ADR-002): client exposes `AsyncIterable<RecordType>`, gateway emits NDJSON with backpressure, OpenAPI advertises the record schema via `x-wsdl-tsc-stream`
23
+ - Streamable SOAP responses, opt-in per operation via `--stream-config` (ADR-002): client exposes `AsyncIterable<RecordType>`, gateway emits NDJSON or JSON array streams with backpressure, OpenAPI advertises the record schema via `x-wsdl-tsc-stream`
24
24
  - `xs:any` wildcard particles retained on compiled types (they used to be dropped silently) — enables honest stream-candidate detection and companion-catalog shape resolution
25
25
 
26
26
  ### Named simple types and same-name elements
package/docs/testing.md CHANGED
@@ -246,7 +246,7 @@ const client = createMockClient({
246
246
 
247
247
  Mock responses use the pre-unwrap SOAP wrapper shape. The generated `unwrapArrayWrappers()` function handles conversion at runtime.
248
248
 
249
- For operations opted in via `--stream-config`, the mock returns `records: AsyncIterable<RecordType>` (via a small `asyncIterableOf` helper) and the generated happy-path test asserts on the NDJSON content-type and parseable record lines. Override a stream op with a multi-record iterable to exercise downstream backpressure:
249
+ For operations opted in via `--stream-config`, the mock returns `records: AsyncIterable<RecordType>` via a small `asyncIterableOf` helper. Generated happy-path tests assert on the configured content type; NDJSON tests parse record lines, and JSON array tests parse the response body once as an array. Override a stream op with a multi-record iterable to exercise downstream backpressure:
250
250
 
251
251
  ```typescript
252
252
  const client = createMockClient({
@@ -20,7 +20,7 @@ See [README](../README.md) for quick start and [CLI Reference](cli-reference.md)
20
20
  | Stream config references unknown operation | Operation name must match the WSDL exactly; check spelling and casing |
21
21
  | Stream record type not found | `recordType` must exist in the main catalog or a companion `shapeCatalog` must supply it; confirm the companion WSDL compiles cleanly in isolation |
22
22
  | Structural collision between main and companion catalog | Two types share a name but differ structurally; rename in the companion source or point `recordType` at a distinct subtree |
23
- | NDJSON response ends abruptly | Mid-stream upstream error per the terminal-error policy; check gateway logs for the classified error |
23
+ | Stream response ends abruptly or JSON array parse fails | Mid-stream upstream error per the terminal-error policy; check gateway logs for the classified error |
24
24
  | Stream recordPath does not match | SAX matching is positional and case-sensitive; verify duplicate local-name segments are spelled exactly |
25
25
  | Stream client throws "stream request failed" | The upstream SOAP endpoint rejected the hand-built envelope; check `requestRaw` on the response and verify SOAP action and namespaces match the WSDL binding |
26
26
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@techspokes/typescript-wsdl-client",
3
- "version": "0.27.0",
3
+ "version": "0.29.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",
@@ -90,18 +90,18 @@
90
90
  },
91
91
  "devDependencies": {
92
92
  "@types/js-yaml": "^4.0.9",
93
- "@types/node": "^25.9.1",
93
+ "@types/node": "^25.9.3",
94
94
  "@types/yargs": "^17.0.35",
95
95
  "fastify": "^5.8.5",
96
- "fastify-plugin": "^5.1.0",
96
+ "fastify-plugin": "^6.0.0",
97
97
  "rimraf": "^6.1.3",
98
98
  "tsx": "^4.22.4",
99
99
  "typescript": "^6.0.3",
100
- "vitest": "^4.1.8"
100
+ "vitest": "^4.1.9"
101
101
  },
102
102
  "dependencies": {
103
103
  "@apidevtools/swagger-parser": "^12.1.0",
104
- "fast-xml-parser": "^5.8.0",
104
+ "fast-xml-parser": "^5.9.0",
105
105
  "js-yaml": "^4.2.0",
106
106
  "saxes": "^6.0.0",
107
107
  "soap": "^1.9.3",
@@ -0,0 +1,55 @@
1
+ /**
2
+ * JSON array adapter for record iterables.
3
+ *
4
+ * Given an `AsyncIterable<T>` (typically the output of `parseRecords`), produce
5
+ * a Node `Readable` that emits a single JSON array document without buffering
6
+ * the full record set.
7
+ *
8
+ * Terminal-error policy: the first record is prefetched before any bytes are
9
+ * pushed. A source error before the first record reaches Fastify before the
10
+ * response starts, so the gateway can return the standard JSON error envelope.
11
+ * Errors after the first record abort the stream and leave a truncated JSON
12
+ * document for clients to treat as a failed stream.
13
+ */
14
+ import {Readable} from "node:stream";
15
+
16
+ /**
17
+ * Wrap an async iterable of records in a Node `Readable` stream that emits a
18
+ * JSON array. Downstream backpressure is honored via `Readable.from`'s default
19
+ * behavior: the iterator's `next()` is not called until the internal buffer has
20
+ * room.
21
+ *
22
+ * Source errors are forwarded to the returned stream's `error` event.
23
+ */
24
+ export function toJsonArray<T>(records: AsyncIterable<T>): Readable {
25
+ return Readable.from(encode(records), {objectMode: false, encoding: "utf-8"});
26
+ }
27
+
28
+ async function* encode<T>(records: AsyncIterable<T>): AsyncIterable<string> {
29
+ const iterator = records[Symbol.asyncIterator]();
30
+ let complete = false;
31
+ try {
32
+ const first = await iterator.next();
33
+ if (first.done) {
34
+ complete = true;
35
+ yield "[]";
36
+ return;
37
+ }
38
+
39
+ yield "[" + JSON.stringify(first.value);
40
+
41
+ while (true) {
42
+ const next = await iterator.next();
43
+ if (next.done) {
44
+ complete = true;
45
+ yield "]";
46
+ return;
47
+ }
48
+ yield "," + JSON.stringify(next.value);
49
+ }
50
+ } finally {
51
+ if (!complete && typeof iterator.return === "function") {
52
+ await iterator.return();
53
+ }
54
+ }
55
+ }