@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.
- package/README.md +4 -4
- package/dist/app/generateApp.js +2 -2
- package/dist/gateway/generators.d.ts +3 -2
- package/dist/gateway/generators.d.ts.map +1 -1
- package/dist/gateway/generators.js +51 -9
- package/dist/openapi/generateOpenAPI.d.ts.map +1 -1
- package/dist/openapi/generateOpenAPI.js +4 -1
- package/dist/runtime/jsonArray.d.ts +24 -0
- package/dist/runtime/jsonArray.d.ts.map +1 -0
- package/dist/runtime/jsonArray.js +52 -0
- package/dist/test/generators.d.ts.map +1 -1
- package/dist/test/generators.js +25 -3
- package/docs/README.md +2 -2
- package/docs/api-reference.md +3 -1
- package/docs/architecture.md +1 -1
- package/docs/cli-reference.md +1 -1
- package/docs/concepts.md +2 -2
- package/docs/configuration.md +1 -0
- package/docs/decisions/002-streamable-responses.md +32 -10
- package/docs/gateway-guide.md +5 -10
- package/docs/generated-code.md +1 -1
- package/docs/migration-playbook.md +1 -1
- package/docs/migration.md +1 -1
- package/docs/output-anatomy.md +26 -4
- package/docs/production.md +2 -2
- package/docs/releases/v0.28.0.md +32 -0
- package/docs/releases/v0.29.0.md +32 -0
- package/docs/roadmap/README.md +31 -18
- package/docs/roadmap/v1.0-capability-conformance-framework.md +219 -0
- package/docs/roadmap/v1.0-contract-audit.md +14 -13
- package/docs/roadmap/v1.0-json-array-streaming.md +21 -19
- package/docs/roadmap/v1.0-openapi-fastify-compatibility.md +15 -13
- package/docs/roadmap/v1.0-release-candidate-gates.md +2 -0
- package/docs/roadmap/v1.0-wsdl-coverage-matrix.md +15 -13
- package/docs/start-here.md +4 -2
- package/docs/supported-patterns.md +1 -1
- package/docs/testing.md +1 -1
- package/docs/troubleshooting.md +1 -1
- package/package.json +5 -5
- package/src/runtime/jsonArray.ts +55 -0
|
@@ -1,45 +1,47 @@
|
|
|
1
1
|
# Version 1.0 OpenAPI Fastify Compatibility
|
|
2
2
|
|
|
3
|
-
|
|
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
|
|
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
|
|
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
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
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
|
|
27
|
-
- Do not
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
32
|
-
|
|
33
|
-
| `xs:choice` union mode
|
|
34
|
-
| `xs:union`
|
|
35
|
-
| Abstract types
|
|
36
|
-
| Substitution groups
|
|
37
|
-
| Multi-binding WSDLs
|
|
38
|
-
| External `PolicyReference` | partial or diagnostic
|
|
39
|
-
| Deep composition
|
|
40
|
-
| `xs:anyAttribute`
|
|
41
|
-
| MTOM/XOP attachments
|
|
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
|
|
package/docs/start-here.md
CHANGED
|
@@ -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
|
|
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>`
|
|
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({
|
package/docs/troubleshooting.md
CHANGED
|
@@ -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
|
-
|
|
|
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.
|
|
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.
|
|
93
|
+
"@types/node": "^25.9.3",
|
|
94
94
|
"@types/yargs": "^17.0.35",
|
|
95
95
|
"fastify": "^5.8.5",
|
|
96
|
-
"fastify-plugin": "^
|
|
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.
|
|
100
|
+
"vitest": "^4.1.9"
|
|
101
101
|
},
|
|
102
102
|
"dependencies": {
|
|
103
103
|
"@apidevtools/swagger-parser": "^12.1.0",
|
|
104
|
-
"fast-xml-parser": "^5.
|
|
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
|
+
}
|