@techspokes/typescript-wsdl-client 1.1.8 → 1.3.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 +22 -3
- package/dist/checkedPlanning.js +27 -4
- package/dist/cli.js +17 -1
- package/dist/client/checkedDirectRuntime.d.ts +11 -1
- package/dist/client/checkedDirectRuntime.js +19 -2
- package/dist/client/directClientRuntime.d.ts +18 -1
- package/dist/client/directClientRuntime.js +15 -3
- package/dist/client/directClientVersion.d.ts +2 -0
- package/dist/client/directClientVersion.js +2 -0
- package/dist/client/generateClient.js +72 -16
- package/dist/client/generateDirectClient.js +14 -9
- package/dist/client/generateOperations.js +30 -11
- package/dist/client/generateUtils.js +5 -1
- package/dist/compiler/canonicalGraph.d.ts +4 -15
- package/dist/compiler/canonicalGraph.js +1 -8
- package/dist/compiler/componentRecordProjection.d.ts +3 -0
- package/dist/compiler/componentRecordProjection.js +10 -0
- package/dist/compiler/declarationIdentity.d.ts +22 -0
- package/dist/compiler/declarationIdentity.js +9 -0
- package/dist/compiler/directCodec.d.ts +22 -2
- package/dist/compiler/directCodec.js +40 -7
- package/dist/compiler/directOperation.d.ts +28 -5
- package/dist/compiler/directOperation.js +84 -14
- package/dist/compiler/directSoap.d.ts +40 -10
- package/dist/compiler/directSoap.js +151 -18
- package/dist/compiler/directSoapSource.js +3 -2
- package/dist/compiler/directSourceCapsule.js +69 -4
- package/dist/compiler/directStructure.js +6 -2
- package/dist/compiler/directStructurePlan.d.ts +10 -1
- package/dist/compiler/directStructurePlan.js +27 -7
- package/dist/compiler/directValues.d.ts +15 -3
- package/dist/compiler/directValues.js +20 -4
- package/dist/compiler/legacyDeclarations.d.ts +26 -0
- package/dist/compiler/legacyDeclarations.js +144 -0
- package/dist/compiler/projectionScalar.d.ts +18 -1
- package/dist/compiler/projectionScalar.js +47 -13
- package/dist/compiler/rpcStringValues.d.ts +30 -0
- package/dist/compiler/rpcStringValues.js +196 -0
- package/dist/compiler/rpcTypedValues.d.ts +48 -0
- package/dist/compiler/rpcTypedValues.js +190 -0
- package/dist/compiler/schemaCompiler.js +44 -109
- package/dist/compiler/semanticCatalog.d.ts +2 -2
- package/dist/compiler/soapHeaders.d.ts +10 -4
- package/dist/compiler/soapHeaders.js +28 -9
- package/dist/gateway/generateCheckedGateway.js +26 -6
- package/dist/gateway/generateComposedGateway.d.ts +16 -0
- package/dist/gateway/generateComposedGateway.js +65 -0
- package/dist/gateway/generateGateway.js +1 -0
- package/dist/gateway/generators.js +19 -4
- package/dist/gateway/helpers.d.ts +1 -0
- package/dist/gateway/helpers.js +15 -0
- package/dist/generation/componentShape.js +25 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +3 -1
- package/dist/loader/orderedSyntax.d.ts +4 -0
- package/dist/loader/orderedSyntax.js +18 -4
- package/dist/multiServicePipeline.d.ts +41 -0
- package/dist/multiServicePipeline.js +287 -0
- package/dist/openapi/composeOpenAPI.d.ts +29 -0
- package/dist/openapi/composeOpenAPI.js +322 -0
- package/dist/pipeline.d.ts +1 -1
- package/dist/pipeline.js +2 -0
- package/docs/agent-skill.md +10 -1
- package/docs/api-reference.md +127 -9
- package/docs/checked-gateway.md +10 -0
- package/docs/checked-generation.md +11 -5
- package/docs/cli-reference.md +25 -5
- package/docs/concepts.md +4 -5
- package/docs/configuration.md +10 -3
- package/docs/corpus.md +1 -1
- package/docs/gateway-guide.md +104 -27
- package/docs/generated-code.md +12 -6
- package/docs/migration-playbook.md +4 -0
- package/docs/migration.md +134 -6
- package/docs/output-anatomy.md +20 -17
- package/docs/production.md +7 -5
- package/docs/start-here.md +12 -2
- package/docs/supported-patterns.md +23 -0
- package/docs/testing.md +2 -0
- package/docs/troubleshooting.md +3 -1
- package/llms.txt +9 -1
- package/package.json +2 -2
- package/src/runtime/clientStreamMethods.tpl.txt +156 -148
- package/src/runtime/operationsStreamHelper.tpl.txt +6 -6
- package/src/runtime/streamXml.ts +48 -20
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
# Try opt-in checked generation
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Opt-in checked generation supports qualified SOAP 1.1 and SOAP 1.2 document/literal contracts and the bounded SOAP 1.1 RPC/encoded string profile. Choose `pipeline --model checked-components-v1`; omitting `--model` keeps legacy generation. SOAP 1.2 execution is available starting with 1.3.0; see the [binding and artifact contract](checked-gateway.md#component-service-generation). See the root [README](../README.md).
|
|
4
4
|
|
|
5
5
|
This is a bounded preview, not general WSDL/XSD or production-provider qualification. It adds source-backed request, response, fault and artifact checks for the supported fragment. Generation exposes legacy and components only; the shipped v1.1.5 direct runtime remains a compatibility binding for existing clients. See the [checked gateway reference](checked-gateway.md).
|
|
6
6
|
|
|
7
7
|
## Install and try the bundled contract
|
|
8
8
|
|
|
9
|
+
The examples target 1.3.0. Before that version is published, install a locally packed 1.3.0 tarball instead of requesting an unpublished registry version. After publication, use the explicit registry version below. Earlier releases retain their own documented contracts.
|
|
10
|
+
|
|
9
11
|
Use Node.js 24 or newer. Run these commands in a new trial directory:
|
|
10
12
|
|
|
11
13
|
```powershell
|
|
12
14
|
npm init -y
|
|
13
|
-
npm install --save-dev @techspokes/typescript-wsdl-client@1.
|
|
15
|
+
npm install --save-dev @techspokes/typescript-wsdl-client@1.3.0
|
|
14
16
|
npm install soap
|
|
15
17
|
npx wsdl-tsc pipeline --model checked-components-v1 --wsdl-source node_modules/@techspokes/typescript-wsdl-client/docs/examples/checked-forecast.wsdl --client-dir .generated/forecast/client --openapi-file .generated/forecast/openapi.json --gateway-dir .generated/forecast/gateway --gateway-version-prefix v1 --gateway-service-name forecast --init-app --app-dir .generated/forecast --test-dir .generated/forecast/test --checked-report .generated/forecast-plan.json
|
|
16
18
|
```
|
|
@@ -69,7 +71,7 @@ Read the planning report before editing anything. Unsupported source, mapping, b
|
|
|
69
71
|
|
|
70
72
|
Checked planning refusals show the construct or source location, the reason and the next action, then exit nonzero without generating artifacts or invoking SOAP. Save the unchanged structured report with `--checked-report`; set the `DEBUG` environment variable to `wsdl-tsc` when you need the raw error, stack and report details.
|
|
71
73
|
|
|
72
|
-
For a locationless import, `--checked-draft` can write `service-resolution.json` containing a `REQUIRED_SCHEMA_LOCATION` placeholder. Replace that value with the actual permitted schema location, then rerun with `--checked-config service-resolution.json`.
|
|
74
|
+
For a locationless import whose referenced components are unavailable, `--checked-draft` can write `service-resolution.json` containing a `REQUIRED_SCHEMA_LOCATION` placeholder. Replace that value with the actual permitted schema location, then rerun with `--checked-config service-resolution.json`. Unused locationless imports need no fabricated schema; native qualification and reference resolution remain mandatory.
|
|
73
75
|
|
|
74
76
|
Multiple service/port/binding candidates require an explicit choice. Partial configuration and operation subsets are supported; see [selection and recovery details](checked-gateway.md#planning-and-missing-schema-recovery). Reports and drafts are preserved by default; use `--force-checked-files` deliberately to replace them on a later run.
|
|
75
77
|
|
|
@@ -133,7 +135,9 @@ The older `assessSchemaSource` API and `assess` command retain the narrow `check
|
|
|
133
135
|
|
|
134
136
|
The qualified component fragment includes imported schemas, nested/repeated and inherited records, attributes, simple content, ordered values and supported scalar restrictions. [Keyed mixed/namespace/open values](checked-gateway.md#mixed-namespaced-and-open-values) additionally preserve source-permitted wildcard data with native strict/lax/skip checks. Escapia qualification retains 15 Main operations and two Content operations against owned services. Content uses explicit companion configuration with scoped validation and buffered delivery; it is not automatic companion discovery or checked streaming.
|
|
135
137
|
|
|
136
|
-
|
|
138
|
+
The [bounded SOAP 1.1 RPC/encoded profile](supported-patterns.md#checked-soap-11-rpc-string-profile) supports typed scalar parts, native restrictions, one flat required Boolean record and one opaque string result. [NOAA qualification](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/docs/noaa-ndfd-qualification.md) covers all 12 operations against an owned server; ten live operations succeeded and two GML operations returned non-SOAP failures. There is no parsed DWML/GML or geographic correctness claim.
|
|
139
|
+
|
|
140
|
+
General XSD, general RPC encoding, broader authentication/security, arbitrary wildcard conversion and checked incremental streaming remain outside this preview. SOAP 1.2 document/literal uses the separately versioned binding described in the [checked gateway reference](checked-gateway.md#component-service-generation); live-provider acceptance is separate from owned-server protocol evidence. OpenAPI describes the JSON shape but does not express every native scalar/order/wildcard rule. Required declarations and strict wildcard failures cannot become successful unchecked replies.
|
|
137
141
|
|
|
138
142
|
[#409](https://github.com/TechSpokes/typescript-wsdl-client/issues/409) supplies the bounded mixed/namespace/open mapping and its schema/serialization slice of [#410](https://github.com/TechSpokes/typescript-wsdl-client/issues/410). Representative unrelated contract qualification remains under [#397](https://github.com/TechSpokes/typescript-wsdl-client/issues/397); broader HTTP translation, source, scalar, group/naming, security and streaming work retains its existing owners. Legacy defaults and full-profile activation remain unchanged. See the [roadmap](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/ROADMAP.md) for direction and [development checkpoint](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/research/docs/content-model-development-checkpoint.md) for detailed evidence.
|
|
139
143
|
|
|
@@ -158,4 +162,6 @@ With generated defaults, omitted restrictions retain the generated choices; expl
|
|
|
158
162
|
|
|
159
163
|
Consumer-owned server/config/test files are preserved unless their existing `--force-init` or `--force-test` option is selected. Review customizations before deliberately refreshing older host scaffolds. Existing v1.1.5-issued direct clients continue using `checkedDirectRuntimeV1` unchanged; new generation uses components.
|
|
160
164
|
|
|
161
|
-
Legacy users need no model change.
|
|
165
|
+
Legacy users need no model change. Follow the [1.1.x-to-1.2.0 migration guide](migration.md#from-11x-to-120) for affected generated names, stream values, buffered conversion fixes and rollback. The preview reached npm in 1.1.8; the earlier 1.1.6/1.1.7 candidates were unpublished.
|
|
166
|
+
|
|
167
|
+
Checked hosts import `@techspokes/typescript-wsdl-client` at runtime. Retain it in production dependencies as emitted by the checked app manifest; do not omit it from a deployment that installs only production dependencies. Refresh separately maintained consumer package/lockfiles deliberately, and preserve adopted app/test customizations when regenerating.
|
package/docs/cli-reference.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# CLI Reference
|
|
2
2
|
|
|
3
|
+
Commands and configuration for generation and assessment. See the root [README](../README.md).
|
|
4
|
+
|
|
3
5
|
Generation offers legacy, the default, and opt-in `pipeline --model checked-components-v1`. Start with [Try Opt-in Checked Generation](checked-generation.md); the [checked gateway reference](checked-gateway.md) covers exact configuration and v1.1.5 runtime compatibility. Checked generation emits source-backed contracts rather than a legacy catalog and refuses unsupported compiler/streaming controls.
|
|
4
6
|
|
|
5
7
|
The `wsdl-tsc` tool generates TypeScript SOAP clients, OpenAPI specifications, and Fastify gateways from WSDL files.
|
|
@@ -44,6 +46,18 @@ Checked modes require all three explicit outputs: `--client-dir`, `--openapi-fil
|
|
|
44
46
|
|
|
45
47
|
Run the complete generation pipeline in one pass: WSDL parsing, TypeScript client, OpenAPI spec, Fastify gateway, and optional app. This is the recommended command for most use cases.
|
|
46
48
|
|
|
49
|
+
### Multi-service configuration
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npx wsdl-tsc pipeline --services-config ./services.json
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`--services-config` selects native legacy composition and is exclusive with the single-source pipeline flags below. The JSON file contains `services: [{key, generation}]`, aggregate `openapi: {outFile}` and aggregate `gateway: {outDir}` settings. Each `generation` uses the programmatic `PipelineOptions` field names, including explicit `wsdl`, `catalogOut`, `clientOutDir`, `openapi.outFile`, `openapi.basePath`, `gateway.outDir`, `gateway.serviceSlug` and `gateway.versionSlug`.
|
|
56
|
+
|
|
57
|
+
Paths resolve relative to the configuration file. Service keys, normalized gateway service slugs, route prefixes and generated ownership paths must remain distinct; source WSDLs must stay outside generated outputs. The aggregate OpenAPI file must be JSON, and its generated discovery route defaults to `/openapi.json`; set aggregate `gateway.openapiPath` to `false` to disable it.
|
|
58
|
+
|
|
59
|
+
Keep compiler options, `streamConfigFile` or parsed `streamConfig`, and OpenAPI/gateway options inside the owning service entry. Runtime credentials and client sources belong to the generated `createClients` options, separate from generation configuration. Aggregate app/test scaffolding and checked composition are not supported in this mode; see the [complete configuration and runtime example](gateway-guide.md#multi-service-setup).
|
|
60
|
+
|
|
47
61
|
### Usage
|
|
48
62
|
|
|
49
63
|
```bash
|
|
@@ -56,11 +70,11 @@ npx wsdl-tsc pipeline \
|
|
|
56
70
|
[options]
|
|
57
71
|
```
|
|
58
72
|
|
|
59
|
-
### Required Flags
|
|
73
|
+
### Required Single-Source Flags
|
|
60
74
|
|
|
61
75
|
| Flag | Description |
|
|
62
76
|
|------|-------------|
|
|
63
|
-
| `--wsdl-source` |
|
|
77
|
+
| `--wsdl-source` | Required WSDL path or URL; `--catalog-file` selects the catalog output |
|
|
64
78
|
|
|
65
79
|
At least one of `--client-dir`, `--openapi-file`, or `--gateway-dir` must be provided.
|
|
66
80
|
|
|
@@ -162,7 +176,9 @@ Legacy tests need consumer test/runtime dependencies and use their emitted Vites
|
|
|
162
176
|
|
|
163
177
|
| Flag | Default | Description |
|
|
164
178
|
|------|---------|-------------|
|
|
165
|
-
| `--stream-config` | (none) | Path to a JSON stream-configuration file
|
|
179
|
+
| `--stream-config` | (none) | Path to a JSON stream-configuration file; selects operations for mapped record streaming |
|
|
180
|
+
|
|
181
|
+
Configured client methods return records through `AsyncIterable<RecordType>`; gateway routes serve NDJSON or JSON-array items, and OpenAPI carries `x-wsdl-tsc-stream` record metadata. Unselected operations retain the buffered API, while generated mapper/metadata output can still change across versions. See [1.2.0 migration](migration.md#from-11x-to-120) before regenerating.
|
|
166
182
|
|
|
167
183
|
`--stream-config` is accepted on the `compile`, `client`, and `pipeline` commands. It is not accepted on `openapi`, `gateway`, or `app` because those consume a pre-compiled `catalog.json` that already carries the normalized stream metadata.
|
|
168
184
|
|
|
@@ -281,7 +297,7 @@ npx wsdl-tsc client --catalog-file <path> --client-dir <path> [options]
|
|
|
281
297
|
|
|
282
298
|
| Flag | Description |
|
|
283
299
|
|------|-------------|
|
|
284
|
-
| `--wsdl-source` |
|
|
300
|
+
| `--wsdl-source` or `--catalog-file` | WSDL source or precompiled catalog input |
|
|
285
301
|
| `--client-dir` | Output directory for generated files |
|
|
286
302
|
|
|
287
303
|
Provide either `--wsdl-source` (compile from WSDL) or `--catalog-file` (use pre-compiled catalog). When using `--wsdl-source`, the catalog is auto-generated in the client directory unless overridden with `--catalog-file`.
|
|
@@ -360,7 +376,7 @@ These flags are mutually exclusive.
|
|
|
360
376
|
|
|
361
377
|
### Response Envelope
|
|
362
378
|
|
|
363
|
-
|
|
379
|
+
Buffered legacy success responses use the standard envelope. Legacy streams emit NDJSON or a JSON array directly; checked component routes use checked values/faults. Errors after stream commitment truncate output.
|
|
364
380
|
|
|
365
381
|
Base structure:
|
|
366
382
|
|
|
@@ -467,6 +483,8 @@ Format: `urn:services:{serviceSlug}:{versionSlug}:schemas:{models|operations}:{s
|
|
|
467
483
|
|
|
468
484
|
### Contract Assumptions
|
|
469
485
|
|
|
486
|
+
These assumptions apply to buffered legacy gateway inputs. Stream response bodies and checked component schemas follow their separate contracts.
|
|
487
|
+
|
|
470
488
|
- All request/response bodies must use `$ref` to `components.schemas`
|
|
471
489
|
- Every operation must have a default response with `application/json`
|
|
472
490
|
- All referenced schemas must exist in `components.schemas`
|
|
@@ -587,6 +605,8 @@ npx wsdl-tsc compile --wsdl-source <file|url> --catalog-file <path> [options]
|
|
|
587
605
|
|
|
588
606
|
### Compiler Flags
|
|
589
607
|
|
|
608
|
+
The shared [client/compiler flag table](#client-flags) documents import extensions, naming, scalar policies, unresolved references and optionality. `compile --help` lists the complete current surface, including stream configuration.
|
|
609
|
+
|
|
590
610
|
| Flag | Default | Description |
|
|
591
611
|
|------|---------|-------------|
|
|
592
612
|
| `--client-choice-mode` | `all-optional` | Controls `xs:choice` modeling |
|
package/docs/concepts.md
CHANGED
|
@@ -312,8 +312,7 @@ OpenAPI uses operation docs for both `description` and default `summary` values.
|
|
|
312
312
|
|
|
313
313
|
## Response Envelope
|
|
314
314
|
|
|
315
|
-
|
|
316
|
-
always-on since v0.7.1.
|
|
315
|
+
Buffered legacy gateway responses use this envelope. Stream success bodies deliver records directly, and checked components use their separate value/fault contract.
|
|
317
316
|
|
|
318
317
|
### Success Response
|
|
319
318
|
|
|
@@ -367,7 +366,7 @@ details:
|
|
|
367
366
|
|
|
368
367
|
### Streaming Bypass
|
|
369
368
|
|
|
370
|
-
|
|
369
|
+
Legacy stream operations bypass the success envelope. OpenAPI declares the configured media type, and the gateway writes NDJSON lines or one JSON array. Errors handled before response commitment can use the normal error envelope; after commitment, failures truncate output. See [streaming handlers](gateway-guide.md#streaming-handlers).
|
|
371
370
|
|
|
372
371
|
### Envelope Naming
|
|
373
372
|
|
|
@@ -497,13 +496,13 @@ The generator produces two response execution models. Buffered is the default an
|
|
|
497
496
|
|
|
498
497
|
### Execution Model Contrast
|
|
499
498
|
|
|
500
|
-
Buffered operations call `node-soap`, wait for the full response to materialize, and return `{ response, headers, responseRaw, requestRaw }`. Streaming operations
|
|
499
|
+
Buffered operations call `node-soap`, wait for the full response to materialize, and return `{ response, headers, responseRaw, requestRaw }`. Streaming operations use node-soap's WSDL serializer and public HTTP `requestStream` transport, returning `StreamOperationResponse<RecordType>` with `records: AsyncIterable<RecordType>`. The SAX parser walks `recordPath`; each completed record passes through `fromSoapResult` to produce the generated DTO, including flat attributes and typed `$value` content.
|
|
501
500
|
|
|
502
501
|
The catalog is the source of truth for stream metadata. Each opted-in operation carries an `OperationStreamMetadata` entry, and downstream emitters (client, OpenAPI, gateway, tests) all read from the catalog. OpenAPI carries a derived view via the `x-wsdl-tsc-stream` extension.
|
|
503
502
|
|
|
504
503
|
### Terminal-Error Policy
|
|
505
504
|
|
|
506
|
-
|
|
505
|
+
Failures before response commitment can use the normal gateway error handler. After commitment, failures truncate output; an incomplete HTTP response or JSON document is a failed stream. See the [Production Guide](production.md#terminal-error-policy).
|
|
507
506
|
|
|
508
507
|
## Companion Catalogs and Shape Resolution
|
|
509
508
|
|
package/docs/configuration.md
CHANGED
|
@@ -102,8 +102,7 @@ Per-operation overrides for method, summary, description, and deprecation.
|
|
|
102
102
|
## Stream Configuration
|
|
103
103
|
|
|
104
104
|
The `--stream-config <file>` flag (available on `compile`, `client`, `pipeline`)
|
|
105
|
-
opts selected WSDL operations into streaming.
|
|
106
|
-
operations not listed in the file.
|
|
105
|
+
opts selected WSDL operations into streaming. Unlisted operations retain their buffered API selection; 1.2.0 can still change generated mapper and metadata output.
|
|
107
106
|
|
|
108
107
|
```json
|
|
109
108
|
{
|
|
@@ -140,7 +139,15 @@ operations not listed in the file.
|
|
|
140
139
|
See [ADR-002](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/docs/decisions/002-streamable-responses.md) for rationale and the
|
|
141
140
|
terminal-error policy.
|
|
142
141
|
|
|
143
|
-
##
|
|
142
|
+
## Multi-service configuration
|
|
143
|
+
|
|
144
|
+
Use `pipeline --services-config services.json` exclusively, without single-source CLI flags. Each `services[].generation` uses programmatic `PipelineOptions` names, not CLI flag names. The canonical schema/example and typed runtime registry are in [Multi-Service Setup](gateway-guide.md#multi-service-setup).
|
|
145
|
+
|
|
146
|
+
Paths in the services file resolve relative to that file; companion paths inside `streamConfigFile` resolve relative to the stream file. Programmatic `streamConfig` requires normalized metadata from `parseStreamConfig`, whereas raw JSON uses `recordType` and `shapeCatalog`. Do not interchange those shapes.
|
|
147
|
+
|
|
148
|
+
Use unique lowercase service keys, normalized service slugs, decorators and static base paths, with explicit disjoint output ownership. Aggregate output is JSON only; `gateway.openapiPath` selects discovery or disables it with `false`. Bind runtime WSDL sources and security separately for every client. Checked services and aggregate app/test scaffolding are refused.
|
|
149
|
+
|
|
150
|
+
## Example configuration files
|
|
144
151
|
|
|
145
152
|
Example configuration files are available in the `examples/config/` directory:
|
|
146
153
|
|
package/docs/corpus.md
CHANGED
|
@@ -8,7 +8,7 @@ This table is generated from `test/conformance/readiness-corpus.json`; its sourc
|
|
|
8
8
|
|
|
9
9
|
| Input | Provenance tier | Mode | Expected result | Evidence stages | Executable evidence |
|
|
10
10
|
|---|---|---|---|---|---|
|
|
11
|
-
| [noaa-ndfd](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/test/fixtures/wsdl/real-services/noaa-ndfd/ndfd-xml.wsdl) | real | checked |
|
|
11
|
+
| [noaa-ndfd](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/test/fixtures/wsdl/real-services/noaa-ndfd/ndfd-xml.wsdl) | real | checked | partial | original source decoding and 12-operation inventory, all 12 operations native planning and generation, installed build and every generated HTTP route, owned typed SOAP 1.1 RPC with native restrictions and 73-field Boolean record, exact Latin1 responses and offline provider replay; zero provider calls in tests | [noaa-ndfd-qualification.test.ts](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/test/integration/noaa-ndfd-qualification.test.ts), [checked-gateway-installed.test.ts](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/test/integration/checked-gateway-installed.test.ts) |
|
|
12
12
|
| [weather](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/examples/minimal/weather.wsdl) | synthetic | legacy | supported | generate, typecheck, OpenAPI, gateway mock, installed package | [gateway-routes.test.ts](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/test/integration/gateway-routes.test.ts); `npm run package:smoke` |
|
|
13
13
|
| [checked-forecast](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/test/conformance/fixtures/assessment/forecast.wsdl) | synthetic | checked | supported | generate, install, typecheck, HTTP/SOAP success and faults | [checked-gateway-installed.test.ts](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/test/integration/checked-gateway-installed.test.ts) |
|
|
14
14
|
| [application-groups](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/test/conformance/fixtures/assessment/application-groups.wsdl) | synthetic | checked | supported | generate, native SOAP, OpenAPI, installed HTTP/SOAP variant | [checked-application-groups.test.ts](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/test/integration/checked-application-groups.test.ts), [checked-gateway-installed.test.ts](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/test/integration/checked-gateway-installed.test.ts) |
|
package/docs/gateway-guide.md
CHANGED
|
@@ -201,9 +201,19 @@ export async function registerRoute_v1_weather_getweatherinformation(fastify: Fa
|
|
|
201
201
|
schema: routeSchema,
|
|
202
202
|
handler: async (request, reply) => {
|
|
203
203
|
const client = fastify.weatherClient;
|
|
204
|
-
const
|
|
205
|
-
reply.
|
|
206
|
-
|
|
204
|
+
const controller = new AbortController();
|
|
205
|
+
const disconnected = () => { if (!reply.raw.writableEnded) controller.abort(); };
|
|
206
|
+
request.raw.once("aborted", disconnected);
|
|
207
|
+
reply.raw.once("close", disconnected);
|
|
208
|
+
if (request.raw.aborted || reply.raw.destroyed) controller.abort();
|
|
209
|
+
try {
|
|
210
|
+
const result = await client.GetWeatherInformation(request.body as GetWeatherInformation, {signal: controller.signal});
|
|
211
|
+
reply.type("application/x-ndjson");
|
|
212
|
+
return await reply.send(toNdjson(result.records));
|
|
213
|
+
} finally {
|
|
214
|
+
request.raw.removeListener("aborted", disconnected);
|
|
215
|
+
reply.raw.removeListener("close", disconnected);
|
|
216
|
+
}
|
|
207
217
|
},
|
|
208
218
|
});
|
|
209
219
|
}
|
|
@@ -211,7 +221,25 @@ export async function registerRoute_v1_weather_getweatherinformation(fastify: Fa
|
|
|
211
221
|
|
|
212
222
|
For `format: "json-array"`, the same handler imports `toJsonArray`, sets `reply.type("application/json")`, and sends `reply.send(toJsonArray(result.records))`.
|
|
213
223
|
|
|
214
|
-
The client method returns `StreamOperationResponse<RecordType>` with a `records
|
|
224
|
+
The client method returns `StreamOperationResponse<RecordType>` with a single-pass `records` iterable. Failures before response commitment can use the error envelope; errors after commitment truncate the response. Treat an incomplete HTTP response or JSON array as a failed stream, even if earlier records were valid.
|
|
225
|
+
|
|
226
|
+
Each completed record passes through the legacy client's `fromSoapResult` mapper before delivery. Public DTOs flatten XML attributes, convert boolean/numeric lexical values according to projected types, preserve configured string-first decimal/integer policies, map typed `$value` content, tokenize XML lists and retain repeated-element arrays. Empty complex types without child fields become `{}`; empty primitive strings remain strings. The low-level `streamXml.ts` parser retains lexical values and attribute bags, and checked mapping conventions are unchanged.
|
|
227
|
+
|
|
228
|
+
For buffered responses, node-soap's `null` empty-object recovery requires a declared non-nillable child of a known complex type without child fields. Nullable and unknown values keep their existing behavior; empty containers with declared optional children are outside this bounded recovery.
|
|
229
|
+
|
|
230
|
+
When array-wrapper flattening is enabled, the gateway unwraps each mapped record using the same wrapper convention as buffered routes. Both NDJSON and JSON-array delivery stay incremental. A consumer disconnect aborts the upstream request even before SOAP response headers arrive, and remains connected to cancellation throughout record delivery.
|
|
231
|
+
|
|
232
|
+
### Streaming transport settings
|
|
233
|
+
|
|
234
|
+
Stream calls use `soap.HttpClient.requestStream` or the configured `options.httpClient.requestStream`, with the configured `options.request` adapter. They honor the current `soapClient().setEndpoint(...)`, static SOAP/HTTP headers, and the current security object's `addHeaders`, `addOptions`, `toXML` and `postProcess` hooks. A custom HTTP client must implement `requestStream`.
|
|
235
|
+
|
|
236
|
+
Requests pass through `toSoapArgs` and node-soap's WSDL document serializer, preserving unqualified local children and foreign namespace references. The initialized client's `envelopeKey` also governs SOAP headers and security `postProcess`. Stream calls require a compatible live document/literal binding matching the generated operation name and SOAP action; missing or ambiguous incompatible bindings are refused before I/O.
|
|
237
|
+
|
|
238
|
+
Only clients with stream-configured operations expose constructor `streamRequestOptions`, using node-soap's `IExOptions` HTTP options. Use it for stream-specific HTTP timeouts or an HTTPS agent with trusted CA/client certificates; WSDL-fetch settings remain separate. TLS verification stays enabled by default and uses Node's configured trust; no certificate bypass is added.
|
|
239
|
+
|
|
240
|
+
Generated stream operations also accept `{signal, timeoutMs}` as an optional second argument. `timeoutMs` covers the upstream HTTP request and record consumption, starting after SOAP metadata initialization. Exhaust the records or return their iterator to release the connection; a per-call signal already aborted rejects before metadata initialization. See the [generated stream client API](api-reference.md#generated-stream-client-contract).
|
|
241
|
+
|
|
242
|
+
Streaming supports SOAP 1.1 document/literal requests. SOAP 1.2/custom envelope namespaces, functional SOAP headers, SOAP body attributes, MTOM attachments and NTLM transport are explicitly refused. Other node-soap serializer/security combinations require separate qualification; date mappings remain type-level, and `bigint` values retain normal JSON serialization limitations.
|
|
215
243
|
|
|
216
244
|
## Error Handling
|
|
217
245
|
|
|
@@ -220,12 +248,14 @@ The centralized error handler (runtime.ts) automatically classifies errors:
|
|
|
220
248
|
| Error Type | HTTP Status | Error Code |
|
|
221
249
|
|--------------------|-------------|---------------------|
|
|
222
250
|
| Validation errors | 400 | VALIDATION_ERROR |
|
|
223
|
-
|
|
|
251
|
+
| Buffered node-soap faults | 502 | SOAP_FAULT |
|
|
224
252
|
| Connection refused | 503 | SERVICE_UNAVAILABLE |
|
|
225
253
|
| Timeout | 504 | GATEWAY_TIMEOUT |
|
|
226
254
|
| Other errors | 500 | INTERNAL_ERROR |
|
|
227
255
|
|
|
228
|
-
|
|
256
|
+
Legacy errors handled before response commitment use the standard envelope. After stream output begins, errors truncate the response. Checked component values and faults follow their separate [checked contract](checked-gateway.md).
|
|
257
|
+
|
|
258
|
+
Stream parser faults fail the iterator instead of producing an empty successful result. Before output begins they use the generic error classification; after output begins the response is truncated.
|
|
229
259
|
|
|
230
260
|
## Stub Handler Mode
|
|
231
261
|
|
|
@@ -252,39 +282,86 @@ Example: `urn:services:weather:v1:schemas:models:getcityweatherbyzipresponse`
|
|
|
252
282
|
|
|
253
283
|
## Multi-Service Setup
|
|
254
284
|
|
|
255
|
-
|
|
285
|
+
Native legacy composition generates independent service clients and routers, one aggregate Fastify plugin, and one combined OpenAPI document. Save a configuration such as `services.json` beside your `sources/` directory:
|
|
286
|
+
|
|
287
|
+
```json
|
|
288
|
+
{
|
|
289
|
+
"services": [
|
|
290
|
+
{
|
|
291
|
+
"key": "main",
|
|
292
|
+
"generation": {
|
|
293
|
+
"wsdl": "./sources/main.wsdl",
|
|
294
|
+
"catalogOut": "./.generated/main/client/catalog.json",
|
|
295
|
+
"clientOutDir": "./.generated/main/client",
|
|
296
|
+
"compiler": {"imports": "js"},
|
|
297
|
+
"openapi": {"outFile": "./.generated/main/openapi.json", "basePath": "/main"},
|
|
298
|
+
"gateway": {"outDir": "./.generated/main/gateway", "serviceSlug": "main", "versionSlug": "v1"}
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
"key": "content",
|
|
303
|
+
"generation": {
|
|
304
|
+
"wsdl": "./sources/content.wsdl",
|
|
305
|
+
"catalogOut": "./.generated/content/client/catalog.json",
|
|
306
|
+
"clientOutDir": "./.generated/content/client",
|
|
307
|
+
"compiler": {"imports": "js"},
|
|
308
|
+
"openapi": {"outFile": "./.generated/content/openapi.json", "basePath": "/content"},
|
|
309
|
+
"gateway": {"outDir": "./.generated/content/gateway", "serviceSlug": "content", "versionSlug": "v1"}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
],
|
|
313
|
+
"openapi": {"outFile": "./.generated/aggregate/openapi.json", "title": "Combined SOAP Gateway", "version": "1.0.0"},
|
|
314
|
+
"gateway": {"outDir": "./.generated/aggregate/gateway", "imports": "js"}
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
npx wsdl-tsc pipeline --services-config ./services.json
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
Relative paths resolve against `services.json`; companion paths in `streamConfigFile` resolve against that stream file. Each `generation` uses `PipelineOptions` property names. Every service requires explicit outputs and its own static `basePath`; prefixes are baked into routes once. Keys, normalized service slugs, decorators and prefixes must be unique; output ownership must not overlap across services, and source metadata must remain outside outputs.
|
|
323
|
+
|
|
324
|
+
### Runtime clients
|
|
325
|
+
|
|
326
|
+
The aggregate plugin exports a typed `createClients` helper. Its registry requires exactly the configured keys, and each value is that service client's constructor options:
|
|
256
327
|
|
|
257
328
|
```typescript
|
|
258
329
|
import Fastify from "fastify";
|
|
259
|
-
import
|
|
260
|
-
import
|
|
261
|
-
import { Weather } from "./.generated/weather/client/client.js";
|
|
262
|
-
import { Inventory } from "./.generated/inventory/client/client.js";
|
|
263
|
-
|
|
264
|
-
const app = Fastify({ logger: true });
|
|
330
|
+
import gateway, {createClients} from "./.generated/aggregate/gateway/plugin.js";
|
|
331
|
+
import type {IOptions, ISecurity} from "soap";
|
|
265
332
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
client: new Weather({ source: "https://example.com/weather?wsdl" }),
|
|
270
|
-
prefix: "/api/weather",
|
|
271
|
-
});
|
|
272
|
-
});
|
|
333
|
+
declare const mainEndpoint: string, contentEndpoint: string;
|
|
334
|
+
declare const mainOptions: IOptions, contentOptions: IOptions;
|
|
335
|
+
declare const mainSecurity: ISecurity, contentSecurity: ISecurity;
|
|
273
336
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
prefix: "/api/inventory",
|
|
278
|
-
});
|
|
337
|
+
const clients = createClients({
|
|
338
|
+
main: {source: "./sources/main.wsdl", options: mainOptions, security: mainSecurity},
|
|
339
|
+
content: {source: "./sources/content.wsdl", options: contentOptions, security: contentSecurity},
|
|
279
340
|
});
|
|
341
|
+
(await clients.main.soapClient()).setEndpoint(mainEndpoint);
|
|
342
|
+
(await clients.content.soapClient()).setEndpoint(contentEndpoint);
|
|
280
343
|
|
|
281
|
-
|
|
344
|
+
const app = Fastify({logger: true});
|
|
345
|
+
await app.register(gateway, {clients});
|
|
346
|
+
await app.listen({port: 3000});
|
|
282
347
|
```
|
|
283
348
|
|
|
284
|
-
|
|
349
|
+
Runtime `source` supplies WSDL metadata, while `setEndpoint` selects the SOAP destination. Keep source, credentials, trust, headers, stream settings and cancellation decisions scoped to their client; overlapping SOAP operation names still dispatch through their owning route. Alternatively, provide a `{clients}` registry of preconfigured instances or compatible operations mocks directly.
|
|
350
|
+
|
|
351
|
+
The aggregate serves the combined definition at `/openapi.json`; generation `gateway.openapiPath` can change or disable that route. Do not register the aggregate under a Fastify runtime prefix, including an inherited parent prefix; configure each service's generation-time `openapi.basePath` instead.
|
|
352
|
+
|
|
353
|
+
Components and operation identifiers are qualified by service key, including stream item schema references. Local references and security scheme names are rewritten, and service-local root security/server semantics are preserved at their applicable operations or paths. Composition rejects duplicate final paths, unresolved/relative references and unsupported schema resources or anchors. Compiler settings and optional stream configuration stay inside each `generation`; checked composition and aggregate app/test scaffolding remain deferred.
|
|
354
|
+
|
|
355
|
+
The aggregate specification is JSON only. Aggregate spec/plugin staging protects the previous pair on failure, but earlier service-generated dependencies can already have changed. This is not a whole-directory transaction; regenerate and verify matched artifacts after a failure.
|
|
356
|
+
|
|
357
|
+
Single-source plugins can still be mounted manually in separate Fastify scopes. See [`examples/fastify-gateway`](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/examples/fastify-gateway/README.md) for single-source application wiring and the [composition API](api-reference.md#runmultiservicepipeline) for its supported settings and limits.
|
|
358
|
+
|
|
359
|
+
The credential-free [native composition example](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/examples/native-composition/README.md) uses two committed generic sources, explicit `.generated/` outputs and a compileable typed registry.
|
|
285
360
|
|
|
286
361
|
## Contract Assumptions
|
|
287
362
|
|
|
363
|
+
The following assumptions describe buffered legacy gateway input. Stream responses use format-specific bodies without success envelopes; checked components use their own value/schema contract. Native composition retains those per-service legacy contracts.
|
|
364
|
+
|
|
288
365
|
- All request/response bodies must use $ref to components.schemas
|
|
289
366
|
- Every operation must have a default response with application/json content
|
|
290
367
|
- All referenced schemas must exist in components.schemas
|
package/docs/generated-code.md
CHANGED
|
@@ -4,6 +4,10 @@ Guide to using the TypeScript SOAP clients and types generated by wsdl-tsc.
|
|
|
4
4
|
|
|
5
5
|
See [README](../README.md) for quick start and [Concepts](concepts.md) for type modeling details.
|
|
6
6
|
|
|
7
|
+
## Upgrading generated output
|
|
8
|
+
|
|
9
|
+
Installing a generator version does not itself rewrite these files, but a consumer build/install script may regenerate them. For 1.2.0, review the [migration guide](migration.md#from-11x-to-120) before replacing matched artifacts: affected type names, stream records and corrected scalar/simple-content results can require consumer changes. Preserve adopted app/test scaffolds and keep the generator/runtime versions appropriate to the selected profile.
|
|
10
|
+
|
|
7
11
|
## Installed package definitions
|
|
8
12
|
|
|
9
13
|
The generator package ships TypeScript declarations for its public ESM API. Definition lookup resolves to those packaged `.d.ts` files; original implementation source and declaration maps are not shipped for public API source navigation. Installed package smoke checks this definition resolution using the consumer's TypeScript language service; editor-specific UI behavior is not asserted.
|
|
@@ -140,20 +144,20 @@ const forecast = await client.GetCityForecastByZIP({
|
|
|
140
144
|
ZIP: "10001"
|
|
141
145
|
});
|
|
142
146
|
|
|
143
|
-
console.log(forecast.GetCityForecastByZIPResult
|
|
144
|
-
console.log(forecast.GetCityForecastByZIPResult
|
|
147
|
+
console.log(forecast.response.GetCityForecastByZIPResult?.Success);
|
|
148
|
+
console.log(forecast.response.GetCityForecastByZIPResult?.ForecastResult);
|
|
145
149
|
```
|
|
146
150
|
|
|
147
151
|
Operations without input still require an empty object:
|
|
148
152
|
|
|
149
153
|
```typescript
|
|
150
154
|
const info = await client.GetWeatherInformation({});
|
|
151
|
-
console.log(info.GetWeatherInformationResult
|
|
155
|
+
console.log(info.response.GetWeatherInformationResult?.WeatherDescription);
|
|
152
156
|
```
|
|
153
157
|
|
|
154
158
|
## Calling Stream Operations
|
|
155
159
|
|
|
156
|
-
Operations opted into streaming with `--stream-config`
|
|
160
|
+
Operations opted into streaming with `--stream-config` accept `(args, {signal, timeoutMs}?)` and return `StreamOperationResponse<RecordType>`. The single-pass `records` iterable maps complete records into generated DTOs. Memory depends on record size and transport/parser buffering; there is no constant-memory or byte-cap guarantee.
|
|
157
161
|
|
|
158
162
|
```typescript
|
|
159
163
|
const result = await client.UnitDescriptiveInfoStream({});
|
|
@@ -164,6 +168,8 @@ for await (const record of result.records) {
|
|
|
164
168
|
|
|
165
169
|
Because `records` is single-pass, each response can be iterated once. Headers captured before the first record are available on `result.headers`, and the serialized SOAP envelope that was sent upstream is on `result.requestRaw` when populated.
|
|
166
170
|
|
|
171
|
+
Exhaust or return the iterator, for example by breaking a `for await` loop, to dispose of transport resources. A per-call deadline starts after metadata initialization; an already-aborted signal rejects before it. Stream-enabled constructors accept `streamRequestOptions` for HTTP settings such as a verified HTTPS agent, separately from WSDL loading. See [transport settings and refusals](gateway-guide.md#streaming-transport-settings).
|
|
172
|
+
|
|
167
173
|
Streaming requires the `saxes` runtime dependency. The generated app scaffold pins `saxes ^6.0.0` automatically; consumers that integrate the generated client into their own project must install it explicitly.
|
|
168
174
|
|
|
169
175
|
See [Stream Configuration](configuration.md#stream-configuration) for how to opt specific operations in, and [ADR-002](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/docs/decisions/002-streamable-responses.md) for the rationale and terminal-error policy.
|
|
@@ -214,11 +220,11 @@ Generated gateway test suites use one valid branch in union-mode mocks. They als
|
|
|
214
220
|
All operations and types are fully typed:
|
|
215
221
|
|
|
216
222
|
```typescript
|
|
217
|
-
const result
|
|
223
|
+
const result = await client.GetCityWeatherByZIP({
|
|
218
224
|
ZIP: "10001"
|
|
219
225
|
});
|
|
220
226
|
|
|
221
|
-
result.GetCityWeatherByZIPResult
|
|
227
|
+
result.response.GetCityWeatherByZIPResult?.Temperature;
|
|
222
228
|
```
|
|
223
229
|
|
|
224
230
|
Autocomplete and type checking work across all generated interfaces.
|
|
@@ -4,6 +4,10 @@ A step-by-step guide for modernizing a SOAP API into a typed TypeScript client a
|
|
|
4
4
|
|
|
5
5
|
For CLI flag details, see [CLI Reference](cli-reference.md). For gateway integration, see [Gateway Guide](gateway-guide.md).
|
|
6
6
|
|
|
7
|
+
See the root [README](../README.md) and [1.1.x-to-1.2.0 migration](migration.md#from-11x-to-120) before regenerating. Native legacy composition retains per-client ownership; checked/RPC generation has a separate buffered validation contract.
|
|
8
|
+
|
|
9
|
+
This playbook describes adopting a SOAP-to-REST integration. Updating an existing generated gateway is a separate package-upgrade task: keep its profile first, review matched regenerated artifacts and preserved scaffolds, and use the version migration guide's verification and rollback steps. Adopting checked generation or composition should be a deliberate follow-up rather than an incidental upgrade effect.
|
|
10
|
+
|
|
7
11
|
## Overview
|
|
8
12
|
|
|
9
13
|
The typical migration follows this sequence:
|