@techspokes/typescript-wsdl-client 0.7.14 → 0.8.14

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 (60) hide show
  1. package/README.md +1504 -263
  2. package/dist/cli.js +423 -270
  3. package/dist/{emit/clientEmitter.d.ts → client/generateClient.d.ts} +2 -2
  4. package/dist/client/generateClient.d.ts.map +1 -0
  5. package/dist/{emit/clientEmitter.js → client/generateClient.js} +5 -5
  6. package/dist/{emit/typesEmitter.d.ts → client/generateTypes.d.ts} +4 -4
  7. package/dist/client/generateTypes.d.ts.map +1 -0
  8. package/dist/{emit/typesEmitter.js → client/generateTypes.js} +6 -6
  9. package/dist/{emit/utilsEmitter.d.ts → client/generateUtils.d.ts} +4 -4
  10. package/dist/client/generateUtils.d.ts.map +1 -0
  11. package/dist/{emit/utilsEmitter.js → client/generateUtils.js} +7 -7
  12. package/dist/{emit/catalogEmitter.d.ts → compiler/generateCatalog.d.ts} +4 -4
  13. package/dist/compiler/generateCatalog.d.ts.map +1 -0
  14. package/dist/{emit/catalogEmitter.js → compiler/generateCatalog.js} +5 -5
  15. package/dist/compiler/schemaCompiler.d.ts +1 -1
  16. package/dist/compiler/schemaCompiler.js +1 -1
  17. package/dist/config.d.ts +13 -0
  18. package/dist/config.d.ts.map +1 -1
  19. package/dist/config.js +17 -0
  20. package/dist/gateway/generateGateway.d.ts +73 -0
  21. package/dist/gateway/generateGateway.d.ts.map +1 -0
  22. package/dist/gateway/generateGateway.js +135 -0
  23. package/dist/gateway/generators.d.ts +90 -0
  24. package/dist/gateway/generators.d.ts.map +1 -0
  25. package/dist/gateway/generators.js +270 -0
  26. package/dist/gateway/helpers.d.ts +115 -0
  27. package/dist/gateway/helpers.d.ts.map +1 -0
  28. package/dist/gateway/helpers.js +224 -0
  29. package/dist/index.d.ts +1 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +18 -18
  32. package/dist/loader/wsdlLoader.d.ts.map +1 -1
  33. package/dist/loader/wsdlLoader.js +1 -3
  34. package/dist/openapi/generateOpenAPI.d.ts +25 -1
  35. package/dist/openapi/generateOpenAPI.d.ts.map +1 -1
  36. package/dist/openapi/generateOpenAPI.js +28 -27
  37. package/dist/openapi/{buildPaths.d.ts → generatePaths.d.ts} +6 -6
  38. package/dist/openapi/generatePaths.d.ts.map +1 -0
  39. package/dist/openapi/{buildPaths.js → generatePaths.js} +1 -1
  40. package/dist/openapi/{buildSchemas.d.ts → generateSchemas.d.ts} +10 -10
  41. package/dist/openapi/generateSchemas.d.ts.map +1 -0
  42. package/dist/openapi/{buildSchemas.js → generateSchemas.js} +5 -5
  43. package/dist/openapi/security.d.ts.map +1 -1
  44. package/dist/openapi/security.js +2 -1
  45. package/dist/pipeline.d.ts +21 -7
  46. package/dist/pipeline.d.ts.map +1 -1
  47. package/dist/pipeline.js +66 -32
  48. package/dist/util/builder.d.ts +25 -0
  49. package/dist/util/builder.d.ts.map +1 -0
  50. package/dist/util/builder.js +52 -0
  51. package/dist/util/cli.d.ts +106 -0
  52. package/dist/util/cli.d.ts.map +1 -0
  53. package/dist/util/cli.js +164 -0
  54. package/package.json +11 -8
  55. package/dist/emit/catalogEmitter.d.ts.map +0 -1
  56. package/dist/emit/clientEmitter.d.ts.map +0 -1
  57. package/dist/emit/typesEmitter.d.ts.map +0 -1
  58. package/dist/emit/utilsEmitter.d.ts.map +0 -1
  59. package/dist/openapi/buildPaths.d.ts.map +0 -1
  60. package/dist/openapi/buildSchemas.d.ts.map +0 -1
package/README.md CHANGED
@@ -9,354 +9,1595 @@
9
9
  [![TechSpokes Org](https://img.shields.io/badge/org-techspokes-181717?logo=github)](https://github.com/techspokes)
10
10
  [![Sponsor](https://img.shields.io/badge/sponsor-GitHub-blue?logo=github-sponsors)](https://github.com/sponsors/TechSpokes)
11
11
 
12
- > **Mission**: Turn complex WSDL/XSD definitions into ergonomic, stable, typesafe TypeScript SOAP clients with an optional OpenAPI 3.1 bridgeso you can integrate legacy enterprise services confidently.
12
+ > **Mission**: Transform complex WSDL/XSD definitions into ergonomic, type-safe TypeScript SOAP clients with optional OpenAPI 3.1 specs and Fastify REST gateway scaffolding enabling confident integration with legacy enterprise services.
13
13
 
14
14
  ---
15
+
16
+ ## Table of Contents
17
+
18
+ - [1. Why This Project](#1-why-this-project-what-sets-it-apart)
19
+ - [2. Installation](#2-installation)
20
+ - [3. Quick Start](#3-quick-start)
21
+ - [4. Commands Overview](#4-commands-overview)
22
+ - [5. Command: `compile`](#5-command-compile)
23
+ - [6. Command: `client`](#6-command-client)
24
+ - [7. Command: `openapi`](#7-command-openapi)
25
+ - [8. Command: `gateway`](#8-command-gateway)
26
+ - [9. Command: `pipeline`](#9-command-pipeline)
27
+ - [10. Working With Generated Clients](#10-working-with-generated-clients)
28
+ - [11. OpenAPI Configuration](#11-openapi-configuration)
29
+ - [12. Programmatic API](#12-programmatic-api)
30
+ - [13. Advanced Topics](#13-advanced-topics)
31
+ - [14. Troubleshooting](#14-troubleshooting)
32
+ - [15. Contributing](#15-contributing)
33
+ - [16. License](#16-license)
34
+ - [17. Sponsors](#17-sponsors)
35
+
36
+ ---
37
+
15
38
  ## 1. Why This Project (What Sets It Apart)
16
- Most generators stop at loosely typed stubs or leak XML complexity into your application layer. This tool focuses on **correct flattening and determinism**:
17
-
18
- | Core Differentiator | What You Get |
19
- |----------------------------------|------------------------------------------------------------------------------------------------------|
20
- | Attribute + Element Flattening | Attributes and child elements appear as peer properties (no nested wrapper noise). |
21
- | `$value` Text Content Convention | Simple text & mixed content always represented as a `$value` property (collision-safe & documented). |
22
- | Inheritance Resolution | `complexContent` and `simpleContent` extensions are merged or extended consistently. |
23
- | Choice Strategy | Predictable `all-optional` modeling today (future advanced discriminators planned). |
24
- | WS‑Policy Security Hints | Inline scan of policies surfaces required auth hints (e.g. `usernameToken`, `https`). |
25
- | Deterministic Output | Sorted declarations and stable alias resolution for diff‑friendly regeneration. |
26
- | Primitive Mapping Controls | Explicit flags for long / big integer / decimal / temporal families (string‑first safety). |
27
- | Catalog Introspection | One JSON artifact (`catalog.json`) to drive further tooling (including OpenAPI). |
28
- | OpenAPI 3.1 Bridge | Mirrors the exact TypeScript model — no divergence between runtime and spec. |
29
- | Multi‑format Output | `--format json\|yaml\|both` with always‑on validation (unless disabled). |
30
- | One‑Shot Pipeline | Single pass (parse → TS → OpenAPI) for CI & automation. |
31
39
 
32
- **Vendor**: [TechSpokes](https://www.techspokes.com) · **Maintainer**: Serge Liatko ([@sergeliatko](https://github.com/sergeliatko))
40
+ Most WSDL generators produce loosely typed stubs or expose raw XML complexity to your application layer. This tool delivers **correct flattening, determinism, and multiple integration paths**:
33
41
 
42
+ | Core Differentiator | What You Get |
43
+ |--------------------------------------|------------------------------------------------------------------------------------------------------|
44
+ | **Attribute + Element Flattening** | Attributes and child elements appear as peer properties (no nested wrapper noise). |
45
+ | **`$value` Text Content Convention** | Simple text & mixed content always represented as a `$value` property (collision-safe & documented). |
46
+ | **Inheritance Resolution** | `complexContent` and `simpleContent` extensions are merged or extended consistently. |
47
+ | **Choice Strategy** | Predictable `all-optional` modeling today (future advanced discriminators planned). |
48
+ | **WS-Policy Security Hints** | Inline scan of policies surfaces required auth hints (e.g. `usernameToken`, `https`). |
49
+ | **Deterministic Output** | Sorted declarations and stable alias resolution for diff-friendly regeneration. |
50
+ | **Primitive Mapping Controls** | Explicit flags for long / big integer / decimal / temporal families (string-first safety). |
51
+ | **Catalog Introspection** | One JSON artifact (`catalog.json`) to drive further tooling (including OpenAPI & gateway). |
52
+ | **OpenAPI 3.1 Bridge** | Mirrors the exact TypeScript model with no divergence between runtime and spec. |
53
+ | **Standard Response Envelope** | Always-on, debuggable envelope structure (status, message, data, error) for REST gateways. |
54
+ | **Fastify Gateway Scaffolding** | Route and schema generation with JSON Schema validation (handler implementation in progress). |
55
+ | **Multi-format Output** | `--openapi-format json\|yaml\|both` with always-on validation (unless disabled). |
56
+ | **One-Shot Pipeline** | Single pass (parse to TS to OpenAPI to Gateway) for CI & automation. |
57
+
58
+ **Vendor**: [TechSpokes](https://www.techspokes.com) · **Maintainer**: Serge Liatko ([@sergeliatko](https://github.com/sergeliatko))
34
59
 
35
60
  ---
61
+
36
62
  ## 2. Installation
63
+
37
64
  ```bash
38
- npm i -D @techspokes/typescript-wsdl-client
39
- npm i soap # runtime dependency for actual SOAP calls
65
+ npm install --save-dev @techspokes/typescript-wsdl-client
66
+ npm install soap # Runtime dependency for SOAP calls
40
67
  ```
41
68
 
69
+ **Requirements**:
70
+ - Node.js 20.0.0 or later
71
+ - `soap` package (runtime dependency for generated clients)
72
+
42
73
  ---
43
- ## 3. Typical Repository Layout
44
- You usually want generated SOAP clients under a namespaced integration folder. Examples:
74
+
75
+ ## 3. Quick Start
76
+
77
+ ### Generate TypeScript SOAP Client
78
+
79
+ ```bash
80
+ npx wsdl-tsc client --wsdl-source ./wsdl/Weather.wsdl --client-dir ./src/services/weather
81
+ ```
82
+
83
+ **Try with included example:**
84
+
85
+ ```bash
86
+ npx wsdl-tsc client --wsdl-source examples/minimal/weather.wsdl --client-dir ./tmp/weather
45
87
  ```
46
- src/
47
- services/
48
- third-party/
49
- weather/
50
- client.ts
51
- types.ts
52
- utils.ts
53
- catalog.json
54
- openapi.json
88
+
89
+ ### Generate Everything (Pipeline)
90
+
91
+ ```bash
92
+ npx wsdl-tsc pipeline \
93
+ --wsdl-source examples/minimal/weather.wsdl \
94
+ --client-dir ./tmp/client \
95
+ --openapi-file ./tmp/openapi.json \
96
+ --gateway-dir ./tmp/gateway \
97
+ --gateway-service-name weather \
98
+ --gateway-version-prefix v1
55
99
  ```
56
- Pick a structure that communicates ownership and stability. Regenerate into the same folder for clean diffs.
100
+
101
+ **Output**: Generates client files in `tmp/client/`, OpenAPI spec at `tmp/openapi.json`, gateway code in `tmp/gateway/`, and catalog at `tmp/client/catalog.json`.
57
102
 
58
103
  ---
59
- ## 4. Primary Usage: Generate a TypeScript SOAP Client
60
- The **SOAP client generation** is the core of this project and the most common use case.
61
104
 
62
- ### 4.1 Quick Start
105
+ ## 4. Commands Overview
106
+
107
+ The tool provides **five commands** for different integration scenarios:
108
+
109
+ | Command | Purpose | Typical Use Case |
110
+ |--------------|----------------------------------------------------------------|-----------------------------------------------------|
111
+ | `compile` | Parse WSDL and emit `catalog.json` only | Debugging, inspection, or multi-stage builds |
112
+ | `client` | Generate TypeScript SOAP client from WSDL or catalog | Standard SOAP integration (most common) |
113
+ | `openapi` | Generate OpenAPI 3.1 spec from WSDL or catalog | Documentation, REST proxies, API gateways |
114
+ | `gateway` | Generate Fastify gateway scaffolding from OpenAPI spec | REST gateway foundation (handler stubs) |
115
+ | `pipeline` | Run full pipeline: client + OpenAPI + gateway in one pass | CI/CD automation, complete stack generation |
116
+
117
+ ---
118
+
119
+ ## 5. Command: `compile`
120
+
121
+ **Purpose**: Parse WSDL and generate only the intermediate `catalog.json` representation without TypeScript client code.
122
+
123
+ **When to use**:
124
+ - Multi-stage builds where you want to cache the parsed WSDL
125
+ - Debugging or inspecting the compiled schema structure
126
+ - Sharing a compiled catalog across multiple generation targets
127
+
128
+ ### Usage
129
+
63
130
  ```bash
64
- npx wsdl-tsc --wsdl ./wsdl/Weather.wsdl --out ./src/services/third-party/weather
131
+ npx wsdl-tsc compile --wsdl-source <file|url> --catalog-file <path> [options]
65
132
  ```
66
133
 
67
- **Try with included example:**
134
+ ### Required Flags
135
+
136
+ | Flag | Description |
137
+ |---------------------|------------------------------------------|
138
+ | `--wsdl-source` | Path or URL to the WSDL file |
139
+ | `--catalog-file` | Output path for `catalog.json` |
140
+
141
+ ### Optional Flags
142
+
143
+ | Flag | Default | Description |
144
+ |------------------------------------|----------------|--------------------------------------------------------------|
145
+ | `--import-extensions` | `js` | Import specifier style: `js`, `ts`, or `bare` |
146
+ | `--client-attributes-key` | `$attributes` | Attribute bag key for runtime mapper |
147
+ | `--client-class-name` | (derived) | Override generated client class name |
148
+ | `--client-int64-as` | `string` | Map 64-bit integers: `string`, `number`, or `bigint` |
149
+ | `--client-bigint-as` | `string` | Map arbitrary-size integers: `string` or `number` |
150
+ | `--client-decimal-as` | `string` | Map `xs:decimal`: `string` or `number` |
151
+ | `--client-date-as` | `string` | Map date/time types: `string` or `Date` |
152
+ | `--client-choice-mode` | `all-optional` | Choice element strategy: `all-optional` or `union` |
153
+ | `--client-fail-on-unresolved` | `false` | Fail build on unresolved type references |
154
+ | `--client-nillable-as-optional` | `false` | Treat nillable elements as optional properties |
155
+
156
+ ### Examples
157
+
158
+ #### Basic Compilation
159
+
68
160
  ```bash
69
- npx wsdl-tsc --wsdl examples/minimal/weather.wsdl --out ./tmp/weather
70
- ```
71
-
72
- Imports afterward:
73
- ```ts
74
- import { Weather } from "../services/third-party/weather/client.js";
75
- ```
76
-
77
- ### 4.2 What Gets Generated
78
- | File | Purpose |
79
- |----------------|-------------------------------------------------------------------------|
80
- | `client.ts` | Strongly typed wrapper with one method per operation. |
81
- | `types.ts` | Flattened interfaces & literal/enum aliases. |
82
- | `utils.ts` | Metadata (attribute vs element, occurrence, nillable). |
83
- | `catalog.json` | (If `--catalog`) compiled representation for debugging / OpenAPI reuse. |
84
-
85
- ### 4.3 Key Modeling Rules Recap
86
- - **Attributes & elements** → peer properties.
87
- - **Text content** → `$value`.
88
- - **Required attributes**: `use!=optional`; elements `min>=1`.
89
- - **Multiplicity**: `max>1` or `unbounded` → arrays.
90
- - **Nillable**: `nillable="true"` preserved (optionally modelled optional with `--nillable-as-optional`).
91
- - **Inheritance**: extensions merged or emitted as extends; simpleContent base collapsed logically.
92
-
93
- ### 4.4 CLI Flags (SOAP Client)
94
- | Flag | Default | Description |
95
- |--------------------------|----------------|---------------------------------------------------|
96
- | `--wsdl` | (required) | Local path or URL to WSDL. |
97
- | `--out` | (required) | Output directory. |
98
- | `--imports` | `js` | Intra‑generated import style: `js`, `ts`, `bare`. |
99
- | `--catalog` | `false` | Emit `catalog.json`. |
100
- | `--client-name` | derived | Override exported class name. |
101
- | `--attributes-key` | `$attributes` | Attribute bag key. |
102
- | `--choice` | `all-optional` | Current choice strategy. |
103
- | `--nillable-as-optional` | `false` | Treat nillable elements as optional props. |
104
- | `--fail-on-unresolved` | `true` | Fail build on unresolved references. |
105
- | `--int64-as` | `string` | Map 64‑bit integer types. |
106
- | `--bigint-as` | `string` | Map arbitrary-size integer family. |
107
- | `--decimal-as` | `string` | Map `xs:decimal`. |
108
- | `--date-as` | `string` | Map date/time/duration primitives. |
109
-
110
- ### 4.5 Example With Safer Numeric Decisions
111
- ```bash
112
- npx wsdl-tsc \
113
- --wsdl https://example.com/Hotel.wsdl \
114
- --out ./src/integrations/soap/hotel \
115
- --int64-as number \
116
- --decimal-as string \
117
- --date-as string \
118
- --catalog
119
- ```
120
-
121
- ### 4.6 Programmatic Generation (TypeScript Only)
122
- ```ts
123
- import { compileWsdlToProject } from "@techspokes/typescript-wsdl-client";
124
- await compileWsdlToProject({
125
- wsdl: "./wsdl/Hotel.wsdl",
126
- outDir: "./src/integrations/soap/hotel"
127
- });
161
+ npx wsdl-tsc compile \
162
+ --wsdl-source examples/minimal/weather.wsdl \
163
+ --catalog-file tmp/catalog.json
164
+ ```
165
+
166
+ #### With Custom Output Path
167
+
168
+ ```bash
169
+ npx wsdl-tsc compile \
170
+ --wsdl-source https://example.com/Hotel.wsdl \
171
+ --catalog-file ./build/hotel-catalog.json \
172
+ --client-int64-as number \
173
+ --client-decimal-as string
128
174
  ```
129
175
 
176
+ #### For Debugging
177
+
178
+ ```bash
179
+ # Compile to inspect types and operations
180
+ npx wsdl-tsc compile \
181
+ --wsdl-source ./wsdl/ComplexService.wsdl \
182
+ --catalog-file ./debug/catalog.json \
183
+ --client-fail-on-unresolved false
184
+ ```
185
+
186
+ ### Output
187
+
188
+ - `catalog.json` - Compiled schema representation including types, operations, and metadata
189
+
190
+ ### Catalog Structure
191
+
192
+ The catalog.json file contains the compiled WSDL representation:
193
+
194
+ ```json
195
+ {
196
+ "wsdlUri": "path/to/service.wsdl",
197
+ "targetNamespace": "http://example.com/service",
198
+ "serviceName": "WeatherService",
199
+ "types": [
200
+ {
201
+ "name": "GetWeatherRequest",
202
+ "properties": []
203
+ }
204
+ ],
205
+ "operations": [
206
+ {
207
+ "name": "GetWeather",
208
+ "input": "GetWeatherRequest",
209
+ "output": "GetWeatherResponse"
210
+ }
211
+ ],
212
+ "options": {
213
+ "imports": "js",
214
+ "catalog": true
215
+ }
216
+ }
217
+ ```
218
+
219
+ **Key sections**:
220
+ - `types` - All compiled type definitions with properties and inheritance
221
+ - `operations` - SOAP operations with input/output type references
222
+ - `options` - Compiler options used during generation
223
+
224
+ This catalog can be reused with the `client` and `openapi` commands via `--catalog-file`.
225
+
226
+ ### Catalog File Organization
227
+
228
+ **Default behavior**: Catalog files are **co-located** with their primary output files for better organization and discoverability.
229
+
230
+ **Catalog Location by Command**:
231
+ - `compile`: Always requires explicit `--catalog-file` (no default)
232
+ - `client`: Defaults to `{client-dir}/catalog.json`
233
+ - `openapi`: Defaults to `{openapi-file-dir}/catalog.json`
234
+ - `pipeline`: Intelligent cascade - first available: `{client-dir}` > `{openapi-dir}` > `{gateway-dir}` > `tmp/`
235
+
236
+ **Common patterns**:
237
+
238
+ 1. **Co-located with client** (recommended for most projects):
239
+ ```bash
240
+ npx wsdl-tsc client --wsdl-source service.wsdl --client-dir src/services/weather
241
+ ```
242
+
243
+ Creates `src/services/weather/catalog.json` automatically.
244
+
245
+ Result:
246
+ ```
247
+ src/services/weather/
248
+ ├── client.ts
249
+ ├── types.ts
250
+ ├── utils.ts
251
+ └── catalog.json
252
+ ```
253
+
254
+ 2. **Pipeline with multiple outputs** (catalog in client directory):
255
+ ```bash
256
+ npx wsdl-tsc pipeline --wsdl-source service.wsdl --client-dir src/client --openapi-file docs/api.json
257
+ ```
258
+
259
+ Creates `src/client/catalog.json` (co-located with client).
260
+
261
+ 3. **Shared catalog for multiple commands** (custom location):
262
+ ```bash
263
+ npx wsdl-tsc compile --wsdl-source service.wsdl --catalog-file build/shared-catalog.json
264
+ npx wsdl-tsc client --catalog-file build/shared-catalog.json --client-dir src/client
265
+ npx wsdl-tsc openapi --catalog-file build/shared-catalog.json --openapi-file docs/api.json
266
+ ```
267
+
130
268
  ---
131
- ## 5. Generating an OpenAPI 3.1 Definition (as a standalone run)
132
- If you already have generated your SOAP client and just want an HTTP-friendly spec for proxies / gateways / docs:
133
- ```bash
134
- npx wsdl-tsc openapi --wsdl ./wsdl/Hotel.wsdl --out ./openapi/hotel --format both
135
- ```
136
- Or reuse a previously generated catalog:
137
- ```bash
138
- npx wsdl-tsc openapi --catalog ./src/integrations/soap/hotel/catalog.json --out ./openapi/hotel
139
- ```
140
-
141
- ### 5.1 Formats & Validation
142
- | Flag | Purpose |
143
- |----------------------------|------------------------------------------------------------|
144
- | `--format` | Output format: `json`, `yaml`, `both`. Default: `json`. |
145
- | `--yaml` | (Deprecated) alias for `--format yaml` when format absent. |
146
- | `--validate/--no-validate` | Validation (on by default). |
147
- | `--out` | Base path or explicit file (extension optional). |
148
-
149
- ### 5.2 Core Schema Parity
150
- The OpenAPI schemas reproduce the **exact** flattening & naming used in `types.ts` — crucial for avoiding drift between SOAP and REST surfaces.
151
-
152
- ### 5.3 Additional Flags (Selected)
153
- | Flag | Description |
154
- |------------------------|------------------------------------------------------------------------------------------|
155
- | `--openapi-out` | Output base or file for OpenAPI (if omitted chooses `openapi.json`). |
156
- | `--basePath` | Prefix for REST path segments (e.g. `/v1/booking`). |
157
- | `--pathStyle` | Control operation name → path transformation: `kebab`, `asis`, `lower`. Default: `kebab` |
158
- | `--method` | Default HTTP method (per‑op override via `--ops`). Default: `post`. |
159
- | `--tag-style` | Tag inference: `default`, `service`, `first`. Default: `default`. |
160
- | `--security` | Path to `security.json` (schemes + headers + overrides). |
161
- | `--tags` | Path to `tags.json` (explicit operation → tag map). |
162
- | `--ops` | Path to `ops.json` (method/summary/description/deprecated). |
163
- | `--closedSchemas` | Apply `additionalProperties:false` globally. Default: `false`. |
164
- | `--pruneUnusedSchemas` | Emit only reachable schemas. Default: `false`. |
165
- | `--servers` | Comma‑separated server base URLs for the spec. Default: `/`. |
166
-
167
- Deterministic ordering: all path keys, HTTP methods, component schema names, securitySchemes, parameters, component section keys, and operation tag arrays are alphabetically sorted for diff‑friendly output. The generator also omits a custom `jsonSchemaDialect` declaration to maximize IDE/tool compatibility (JetBrains warning avoidance) unless a future flag introduces non‑default dialect selection.
168
-
169
- ### 5.4 Programmatic OpenAPI Generation
170
- ```ts
171
- import { generateOpenAPI } from "@techspokes/typescript-wsdl-client";
172
- const { jsonPath, yamlPath } = await generateOpenAPI({
173
- wsdl: "./wsdl/Hotel.wsdl",
174
- outFile: "./openapi/hotel",
175
- format: "both",
176
- servers: ["https://api.example.com/v1"] // optional; defaults to ["/"] when omitted
177
- });
269
+
270
+ ## 6. Command: `client`
271
+
272
+ **Purpose**: Generate strongly-typed TypeScript SOAP client code from WSDL or a pre-compiled catalog.
273
+
274
+ **When to use**:
275
+ - Standard SOAP integration (most common use case)
276
+ - When you need TypeScript types and client methods for SOAP operations
277
+ - When building applications that consume SOAP services
278
+
279
+ ### Usage
280
+
281
+ ```bash
282
+ npx wsdl-tsc client --wsdl-source <file|url> --client-dir <path> [options]
283
+ # OR
284
+ npx wsdl-tsc client --catalog-file <path> --client-dir <path> [options]
178
285
  ```
179
286
 
180
- ### 5.5 Standard Response Envelope (Always On Since 0.7.1)
181
- To provide a consistent, debuggable, gateway‑friendly REST surface over SOAP operations, all responses are wrapped in a **standard envelope**. You can customize naming, but disabling the envelope is no longer supported.
287
+ ### Required Flags
182
288
 
183
- #### Collision Avoidance
184
- If the base name you are concatenating already ends with the leading token of the namespace (first CamelCase word), an underscore is inserted to avoid unreadable duplicates. Examples (default `ResponseEnvelope`):
185
- - Payload type `WeatherResponse` `WeatherResponse_ResponseEnvelope` (instead of `WeatherResponseResponseEnvelope`).
186
- - Service `Booking` + default envelope `BookingResponseEnvelope` (no underscore since `Booking` does not end with `Response`).
187
- The same rule applies to the error namespace (e.g. `StatusErrorObject`, `StatusError_ErrorObject`). This keeps the intent obvious and signals to developers they might want to pick a shorter custom namespace.
289
+ | Flag | Description |
290
+ |------------------|-------------------------------------------------|
291
+ | `--wsdl-source` | Path or URL to WSDL file (see note below) |
292
+ | `--client-dir` | Output directory for generated TypeScript files |
293
+
294
+ ### Optional Input Flags
295
+
296
+ | Flag | Default | Description |
297
+ |------------------|-----------------------------|----------------------------------------------------------------------|
298
+ | `--catalog-file` | `{client-dir}/catalog.json` | Path to pre-compiled `catalog.json` (when not using `--wsdl-source`) |
299
+
300
+ **Note**: Provide **either** `--wsdl-source` (to compile from WSDL) **or** `--catalog-file` (to use pre-compiled catalog). When using `--wsdl-source`, the catalog is automatically generated in the client directory unless you override with `--catalog-file`.
301
+
302
+ ### Generated Files
303
+
304
+ | File | Purpose |
305
+ |----------------|------------------------------------------------------------------------------|
306
+ | `client.ts` | Strongly-typed SOAP client wrapper with one method per operation |
307
+ | `types.ts` | Flattened TypeScript interfaces, type aliases, and enums |
308
+ | `utils.ts` | Runtime metadata for JSON to SOAP conversion (attribute mapping, occurrence) |
309
+ | `catalog.json` | (When using `--wsdl-source`) Generated in client directory by default |
310
+
311
+ ### Optional Flags
312
+
313
+ All flags from `compile` command, plus:
314
+
315
+ | Flag | Default | Description |
316
+ |---------------------------------|----------------|-------------------------------------|
317
+ | `--import-extensions` | `js` | Import style: `js`, `ts`, or `bare` |
318
+ | `--client-attributes-key` | `$attributes` | Attribute bag key |
319
+ | `--client-class-name` | (derived) | Override client class name |
320
+ | `--client-int64-as` | `string` | Map 64-bit integers |
321
+ | `--client-bigint-as` | `string` | Map arbitrary-size integers |
322
+ | `--client-decimal-as` | `string` | Map `xs:decimal` |
323
+ | `--client-date-as` | `string` | Map date/time types |
324
+ | `--client-choice-mode` | `all-optional` | Choice element strategy |
325
+ | `--client-fail-on-unresolved` | `false` | Fail on unresolved references |
326
+ | `--client-nillable-as-optional` | `false` | Treat nillable as optional |
327
+
328
+ ### Examples
329
+
330
+ #### Basic Generation (Default Catalog Location)
331
+
332
+ ```bash
333
+ npx wsdl-tsc client \
334
+ --wsdl-source examples/minimal/weather.wsdl \
335
+ --client-dir tmp/client
336
+ ```
337
+
338
+ **Output**: Generates client files and catalog at `tmp/client/catalog.json`.
339
+
340
+ #### With Custom Catalog Path
341
+
342
+ ```bash
343
+ npx wsdl-tsc client \
344
+ --wsdl-source examples/minimal/weather.wsdl \
345
+ --client-dir tmp/client \
346
+ --catalog-file build/shared-catalog.json
347
+ ```
348
+
349
+ #### With Custom Numeric Mappings
350
+
351
+ ```bash
352
+ npx wsdl-tsc client \
353
+ --wsdl-source https://example.com/Hotel.wsdl \
354
+ --client-dir ./src/integrations/soap/hotel \
355
+ --client-int64-as number \
356
+ --client-decimal-as string \
357
+ --client-date-as string
358
+ ```
359
+
360
+ **Output**: Catalog generated at `./src/integrations/soap/hotel/catalog.json`.
361
+
362
+ #### From Pre-compiled Catalog
363
+
364
+ ```bash
365
+ # First compile the catalog
366
+ npx wsdl-tsc compile --wsdl-source https://example.com/Hotel.wsdl --catalog-file build/hotel-catalog.json
367
+
368
+ # Then generate client from catalog
369
+ npx wsdl-tsc client \
370
+ --catalog-file build/hotel-catalog.json \
371
+ --client-dir ./src/services/hotel
372
+ ```
373
+
374
+ ### Key Modeling Rules
375
+
376
+ - **Attributes & elements** become peer properties (flattened)
377
+ - **Text content** becomes `$value` property
378
+ - **Required attributes**: `use!="optional"`; elements `minOccurs>=1`
379
+ - **Multiplicity**: `maxOccurs>1` or `unbounded` become arrays
380
+ - **Nillable**: `nillable="true"` preserved (optionally model as optional with `--client-nillable-as-optional`)
381
+ - **Inheritance**: extensions merged or emitted as `extends`; simpleContent base collapsed logically
382
+
383
+ ---
384
+
385
+ ## 7. Command: `openapi`
386
+
387
+ **Purpose**: Generate OpenAPI 3.1 specification from WSDL or a pre-compiled catalog, mirroring the exact TypeScript type structure.
388
+
389
+ **When to use**:
390
+ - Creating REST API documentation for SOAP services
391
+ - Building API gateways or proxies
392
+ - Enabling REST-style access to SOAP operations
393
+ - Generating client SDKs in other languages
394
+
395
+ ### Usage
396
+
397
+ ```bash
398
+ npx wsdl-tsc openapi --wsdl-source <file|url> --openapi-file <path> [options]
399
+ # OR
400
+ npx wsdl-tsc openapi --catalog-file <path> --openapi-file <path> [options]
401
+ ```
402
+
403
+ ### Required Flags
404
+
405
+ | Flag | Description |
406
+ |---------------------|----------------------------------------------------|
407
+ | `--openapi-file` | Output path for OpenAPI specification |
408
+
409
+ ### Input Source Flags (Mutually Exclusive)
410
+
411
+ | Flag | Default | Description |
412
+ |---------------------|--------------------------------------|----------------------------------------------------|
413
+ | `--wsdl-source` | (none) | Path or URL to WSDL file |
414
+ | `--catalog-file` | `{openapi-file-dir}/catalog.json` | Path to pre-compiled `catalog.json` |
188
415
 
189
- Core properties (always present in the base envelope):
416
+ **Note**: Provide **either** `--wsdl-source` **or** `--catalog-file`. When neither is provided, defaults to reading from the OpenAPI output directory. When using `--wsdl-source`, the catalog is automatically written to the OpenAPI output directory unless overridden.
190
417
 
191
- | Field | Type | Purpose |
192
- |-----------|----------------------|-------------------------------------------------------------------|
193
- | `status` | string | High‑level machine status (e.g. `SUCCESS`, `FAILURE`, `PENDING`). |
194
- | `message` | string \| null | Diagnostic / log message (not for end‑user UI). |
195
- | `data` | any \| null | Operation payload (per‑operation extension specializes this). |
196
- | `error` | Error object \| null | Populated on failures; null on success. |
418
+ ### Core Optional Flags
197
419
 
198
- Error object schema fields:
420
+ | Flag | Default | Description |
421
+ |-------------------------------|-----------|----------------------------------------------------------|
422
+ | `--openapi-format` | `json` | Output format: `json`, `yaml`, or `both` |
423
+ | `--openapi-title` | (derived) | API title in `info` section |
424
+ | `--openapi-version` | `0.0.0` | API version in `info.version` |
425
+ | `--openapi-description` | (empty) | API description in `info` section |
426
+ | `--openapi-servers` | `/` | Comma-separated server URLs |
427
+ | `--openapi-base-path` | (empty) | Base path prefix (e.g., `/v1/soap`) |
428
+ | `--openapi-validate` | `true` | Validate spec with `swagger-parser` |
199
429
 
200
- | Field | Type | Notes |
201
- |-----------|----------------|------------------------------------------------------------|
202
- | `code` | string | Stable machine error code. |
203
- | `message` | string | Brief description. |
204
- | `details` | object \| null | Arbitrary extra info (trace IDs, validation detail, etc.). |
430
+ ### Path & Schema Customization
431
+
432
+ | Flag | Default | Description |
433
+ |----------------------------------|-----------|--------------------------------------------------|
434
+ | `--openapi-path-style` | `kebab` | Path transformation: `kebab`, `asis`, or `lower` |
435
+ | `--openapi-method` | `post` | Default HTTP method for operations |
436
+ | `--openapi-tag-style` | `default` | Tag inference: `default`, `service`, or `first` |
437
+ | `--openapi-closed-schemas` | `false` | Add `additionalProperties: false` to all schemas |
438
+ | `--openapi-prune-unused-schemas` | `false` | Emit only schemas referenced by operations |
439
+
440
+ ### Response Envelope Customization
441
+
442
+ | Flag | Default | Description |
443
+ |--------------------------------|--------------------|---------------------------------------------|
444
+ | `--openapi-envelope-namespace` | `ResponseEnvelope` | Override envelope component name suffix |
445
+ | `--openapi-error-namespace` | `ErrorObject` | Override error object component name suffix |
446
+
447
+ ### Configuration Files
448
+
449
+ | Flag | Description |
450
+ |-----------------------------------|-------------------------------------------------------|
451
+ | `--openapi-security-config-file` | Path to `security.json` (schemes, headers, overrides) |
452
+ | `--openapi-tags-file` | Path to `tags.json` (explicit operation → tag map) |
453
+ | `--openapi-ops-file` | Path to `ops.json` (per-operation overrides) |
454
+
455
+ ### Examples
456
+
457
+ #### Basic JSON Output
458
+
459
+ ```bash
460
+ npx wsdl-tsc openapi \
461
+ --wsdl-source examples/minimal/weather.wsdl \
462
+ --openapi-file ./docs/weather-api.json
463
+ ```
464
+
465
+ #### Multi-Format with Validation
466
+
467
+ ```bash
468
+ npx wsdl-tsc openapi \
469
+ --wsdl-source https://example.com/Hotel.wsdl \
470
+ --openapi-file ./docs/hotel-api \
471
+ --openapi-format both \
472
+ --openapi-servers https://api.example.com/v1,https://api-staging.example.com/v1 \
473
+ --openapi-base-path /soap
474
+ ```
475
+
476
+ #### From Pre-compiled Catalog
477
+
478
+ ```bash
479
+ npx wsdl-tsc openapi \
480
+ --catalog-file ./artifacts/hotel-catalog.json \
481
+ --openapi-file ./docs/hotel-api.json \
482
+ --openapi-format json
483
+ ```
484
+
485
+ #### With Custom Configuration
486
+
487
+ ```bash
488
+ npx wsdl-tsc openapi \
489
+ --wsdl-source ./wsdl/Booking.wsdl \
490
+ --openapi-file ./docs/booking-api.yaml \
491
+ --openapi-format yaml \
492
+ --openapi-title "Hotel Booking API" \
493
+ --openapi-version "1.2.0" \
494
+ --openapi-description "REST API for hotel booking SOAP service" \
495
+ --openapi-security-config-file ./config/security.json \
496
+ --openapi-tags-file ./config/tags.json \
497
+ --openapi-path-style kebab \
498
+ --openapi-method post \
499
+ --openapi-tag-style service
500
+ ```
501
+
502
+ ### Standard Response Envelope
503
+
504
+ All responses are wrapped in a **standard envelope** for consistency and debuggability (always-on since 0.7.1):
505
+
506
+ #### Base Envelope Structure
507
+
508
+ ```typescript
509
+ {
510
+ status: string; // e.g., "SUCCESS", "FAILURE", "PENDING"
511
+ message: string | null; // diagnostic message (not for end-user UI)
512
+ data: T | null; // operation payload (typed per operation)
513
+ error: ErrorObject | null; // populated on failures
514
+ }
515
+ ```
516
+
517
+ #### Error Object Structure
518
+
519
+ ```typescript
520
+ {
521
+ code: string; // stable machine error code
522
+ message: string; // brief description
523
+ details: object | null; // arbitrary extra info
524
+ }
525
+ ```
205
526
 
206
527
  #### Naming Rules
207
- * Base envelope component: `${serviceName}ResponseEnvelope` (override with `--envelope-namespace`).
208
- * Error object component: `${serviceName}ErrorObject` (override with `--error-namespace`).
209
- * Per operation extension: `<PayloadType|OperationName><EnvelopeNamespace>` (alphabetically sorted for stable diffs) which refines `data` to that operation's output type.
210
- * When you pass an explicit namespace flag its value is used verbatim (no service name prefix).
211
528
 
212
- #### CLI Flags
213
- | Flag | Description |
214
- |-------------------------------|------------------------------------------------|
215
- | `--envelope-namespace <Name>` | Override base envelope component name segment. |
216
- | `--error-namespace <Name>` | Override error object component name segment. |
529
+ - **Base envelope**: `${serviceName}ResponseEnvelope` (override with `--openapi-envelope-namespace`)
530
+ - **Error object**: `${serviceName}ErrorObject` (override with `--openapi-error-namespace`)
531
+ - **Per-operation extension**: `<PayloadType|OperationName><EnvelopeNamespace>` (refines `data` field)
532
+
533
+ #### Collision Avoidance
534
+
535
+ If the payload type already ends with the namespace prefix, an underscore is inserted:
536
+
537
+ - Payload `WeatherResponse` + default `ResponseEnvelope` → `WeatherResponse_ResponseEnvelope`
538
+ - Payload `Booking` + default `ResponseEnvelope` → `BookingResponseEnvelope`
217
539
 
218
540
  #### Example
541
+
219
542
  ```bash
220
543
  npx wsdl-tsc openapi \
221
- --wsdl ./wsdl/Hotel.wsdl \
222
- --out ./openapi/hotel \
223
- --format json \
224
- --envelope-namespace ApiEnvelope \
225
- --error-namespace ApiError
544
+ --wsdl-source ./wsdl/Hotel.wsdl \
545
+ --openapi-file ./docs/hotel-api.json \
546
+ --openapi-envelope-namespace ApiEnvelope \
547
+ --openapi-error-namespace ApiError
226
548
  ```
227
- Yields components in order:
549
+
550
+ Produces components:
228
551
  1. `HotelApiEnvelope` (base)
229
- 2. `<Payload…>ApiEnvelope` extension schemas (A→Z)
552
+ 2. `<Payload>ApiEnvelope` extension schemas (alphabetically sorted)
230
553
  3. `HotelApiError` (error object)
231
- 4. Remaining domain schemas.
554
+ 4. Domain schemas
555
+
556
+ ### Tag Inference Strategies
557
+
558
+ | Strategy | Behavior |
559
+ |-----------|------------------------------------------------------------------------------------|
560
+ | `default` | Single tag = service name (fallback `SOAP`) |
561
+ | `service` | Always service name (even if operation prefix differs) |
562
+ | `first` | First lexical segment of CamelCase operation (e.g., `GetCityWeatherByZIP` → `Get`) |
563
+
564
+ Use `--openapi-tags-file` for explicit mapping when heuristics are insufficient.
565
+
566
+ ### Output Determinism
567
+
568
+ All generated OpenAPI specs have **deterministic ordering**:
569
+ - Path keys (alphabetically sorted)
570
+ - HTTP methods within paths (alphabetically sorted)
571
+ - Component schema names (alphabetically sorted)
572
+ - Security schemes (alphabetically sorted)
573
+ - Parameters (alphabetically sorted)
574
+ - Operation tag arrays (alphabetically sorted)
575
+
576
+ This ensures diff-friendly output for version control.
232
577
 
233
578
  ---
234
- ## 6. One‑Shot Pipeline (SOAP Client + OpenAPI Together)
235
- Ideal for CI: single WSDL parse → TS artifacts + catalog + OpenAPI (validated).
579
+
580
+ ## 8. Command: `gateway`
581
+
582
+ **Purpose**: Generate Fastify gateway scaffolding (routes and schemas) from an OpenAPI 3.1 specification. This provides the foundation for building a REST API layer over your SOAP client.
583
+
584
+ > **Current Status (v0.8.0)**: The gateway generator produces basic scaffolding including route registration, JSON Schema validation setup, and handler stubs. Full code generation with complete handler implementations is planned for future releases. You will need to implement the business logic that calls your SOAP client and transforms responses.
585
+
586
+ **When to use**:
587
+ - Building a REST API gateway for legacy SOAP services
588
+ - Creating a modern HTTP/JSON interface for SOAP operations
589
+ - Setting up request/response validation with JSON Schema
590
+ - Establishing Fastify routing structure for SOAP operations
591
+
592
+ **What it generates**:
593
+ - Fastify route registration files
594
+ - JSON Schema models with URN-based IDs
595
+ - Operation schemas (request/response validation)
596
+ - Schema and route registration modules
597
+ - Handler stubs (require manual implementation)
598
+ - Full handler implementations (coming in future versions)
599
+
600
+ ### Usage
601
+
236
602
  ```bash
237
- npx wsdl-tsc pipeline --wsdl ./wsdl/Hotel.wsdl --out ./src/integrations/soap/hotel --format both
603
+ npx wsdl-tsc gateway \
604
+ --openapi-file <path> \
605
+ --client-dir <path> \
606
+ --gateway-dir <path> \
607
+ --gateway-service-name <slug> \
608
+ --gateway-version-prefix <slug> \
609
+ [options]
238
610
  ```
239
611
 
240
- | Pipeline Flag | Default | Notes |
241
- |----------------------------|----------|---------------------------------------|
242
- | All SOAP flags | — | Same semantics as base generation. |
243
- | All OpenAPI flags | — | Same semantics as standalone openapi. |
244
- | `--openapi-out` | derived | Override OpenAPI base file. |
245
- | `--format` | json | Multi-format control. |
246
- | `--validate/--no-validate` | validate | Spec validation toggle. |
247
- | `--tag-style` | default | Tag inference. |
612
+ ### Required Flags
248
613
 
249
- Programmatic single pass:
250
- ```ts
251
- import { runGenerationPipeline } from "@techspokes/typescript-wsdl-client";
252
- await runGenerationPipeline({
253
- wsdl: "./wsdl/Hotel.wsdl",
254
- outDir: "./src/integrations/soap/hotel",
255
- openapi: { format: "both", tagStyle: "service" }
614
+ | Flag | Description |
615
+ |----------------------------|--------------------------------------------------------------------------|
616
+ | `--openapi-file` | Path to OpenAPI 3.1 JSON or YAML file |
617
+ | `--client-dir` | Path to client directory (where `client.ts` is located) |
618
+ | `--gateway-dir` | Output directory for generated gateway code |
619
+ | `--gateway-service-name` | Service identifier for URN generation (e.g., `weather`, `booking`) |
620
+ | `--gateway-version-prefix` | Version prefix for URN generation (e.g., `v1`, `v2`, `urn:1.0.2:schema`) |
621
+
622
+ ### Optional Flags
623
+
624
+ | Flag | Default | Description |
625
+ |----------------------------------|---------------------------------------------------|------------------------------------------|
626
+ | `--import-extensions` | `js` | Import style: `js`, `ts`, or `bare` |
627
+ | `--gateway-default-status-codes` | `200,400,401,403,404,409,422,429,500,502,503,504` | Comma-separated status codes to backfill |
628
+
629
+ ### Generated Output Structure
630
+
631
+ ```
632
+ {gateway-dir}/
633
+ ├── schemas/
634
+ │ ├── models/ # JSON Schema components with URN IDs
635
+ │ │ ├── <schema1>.json
636
+ │ │ ├── <schema2>.json
637
+ │ │ └── ...
638
+ │ └── operations/ # Fastify operation schemas
639
+ │ ├── <operation1>.json
640
+ │ ├── <operation2>.json
641
+ │ └── ...
642
+ ├── routes/ # Individual route registration files
643
+ │ ├── <route1>.ts
644
+ │ ├── <route2>.ts
645
+ │ └── ...
646
+ ├── schemas.ts # Schema registration module
647
+ └── routes.ts # Route aggregator module
648
+ ```
649
+
650
+ ### URN-Based Schema IDs
651
+
652
+ All generated JSON Schemas use deterministic URN identifiers:
653
+
654
+ ```
655
+ urn:services:{serviceSlug}:{versionSlug}:schemas:{models|operations}:{schemaSlug}
656
+ ```
657
+
658
+ **Example**: `urn:services:weather:v1:schemas:models:getcityweatherbyzipresponse`
659
+
660
+ ### Contract Assumptions
661
+
662
+ The gateway generator enforces strict OpenAPI contract validation:
663
+
664
+ - All request/response bodies must use `$ref` to `components.schemas` (no inline schemas)
665
+ - Every operation must have a default response with `application/json` content
666
+ - All schemas referenced by operations must exist in `components.schemas`
667
+
668
+ ### Examples
669
+
670
+ #### Basic Gateway Generation
671
+
672
+ ```bash
673
+ npx wsdl-tsc gateway \
674
+ --openapi-file ./docs/weather-api.json \
675
+ --client-dir ./src/services/weather \
676
+ --gateway-dir ./src/gateway/weather \
677
+ --gateway-service-name weather \
678
+ --gateway-version-prefix v1
679
+ ```
680
+
681
+ #### With Custom Status Codes
682
+
683
+ ```bash
684
+ npx wsdl-tsc gateway \
685
+ --openapi-file ./docs/hotel-api.json \
686
+ --client-dir ./src/services/hotel \
687
+ --gateway-dir ./src/gateway/hotel \
688
+ --gateway-service-name hotel \
689
+ --gateway-version-prefix v2 \
690
+ --gateway-default-status-codes 200,400,401,404,500
691
+ ```
692
+
693
+ #### From YAML OpenAPI
694
+
695
+ ```bash
696
+ npx wsdl-tsc gateway \
697
+ --openapi-file ./docs/booking-api.yaml \
698
+ --client-dir ./src/services/booking \
699
+ --gateway-dir ./src/gateway/booking \
700
+ --gateway-service-name booking \
701
+ --gateway-version-prefix v1
702
+ ```
703
+
704
+ ### Integration Pattern
705
+
706
+ The generated gateway scaffolding provides the foundation for your Fastify application:
707
+
708
+ ```typescript
709
+ import Fastify from 'fastify';
710
+ import { registerSchemas } from './gateway/schemas.js';
711
+ import { registerRoutes } from './gateway/routes.js';
712
+
713
+ const app = Fastify({ logger: true });
714
+
715
+ // Register JSON Schemas (validation setup)
716
+ await registerSchemas(app);
717
+
718
+ // Register routes (with handler stubs)
719
+ await registerRoutes(app, {
720
+ prefix: '/api/v1',
721
+ // Pass any route-level options
722
+ });
723
+
724
+ await app.listen({ port: 3000 });
725
+ ```
726
+
727
+ > **Note**: The registered routes contain handler stubs that throw "Not implemented" errors. You must implement the handler logic in each route file before the gateway becomes functional.
728
+
729
+ ### Handler Implementation
730
+
731
+ > ** Manual Implementation Required**: Currently, the gateway generator produces handler stubs that you must implement. Future versions will include full code generation for handler logic.
732
+
733
+ Each generated route file contains handler stubs that you need to implement:
734
+
735
+ ```typescript
736
+ // Example: routes/get-weather.ts
737
+ export async function handler(request, reply) {
738
+ // TODO: Implement handler logic
739
+ // 1. Extract validated input from request.body
740
+ // 2. Call SOAP client
741
+ // 3. Transform response
742
+ // 4. Return standard envelope
743
+
744
+ throw new Error('Not implemented');
745
+ }
746
+ ```
747
+
748
+ **Current workflow**:
749
+ 1. Generate gateway scaffolding with `wsdl-tsc gateway`
750
+ 2. Implement handler functions manually in each route file
751
+ 3. Import and call your SOAP client
752
+ 4. Transform SOAP responses to match OpenAPI schemas
753
+ 5. Return responses in the standard envelope format
754
+
755
+ **Future enhancement**: Automated handler generation will include SOAP client calls, response transformation, error handling, and envelope wrapping.
756
+
757
+ ---
758
+
759
+ ## 9. Command: `pipeline`
760
+
761
+ **Purpose**: Run the complete generation pipeline in a single pass: WSDL parsing → TypeScript client → OpenAPI spec → Fastify gateway.
762
+
763
+ **When to use**:
764
+ - CI/CD automation
765
+ - Complete stack generation
766
+ - Ensuring all artifacts are generated from the same WSDL parse
767
+ - One-command development workflows
768
+
769
+ ### Usage
770
+
771
+ ```bash
772
+ npx wsdl-tsc pipeline \
773
+ --wsdl-source <file|url> \
774
+ [--catalog-file <path>] \
775
+ [--client-dir <path>] \
776
+ [--openapi-file <path>] \
777
+ [--gateway-dir <path>] \
778
+ [options]
779
+ ```
780
+
781
+ ### Required Flags
782
+
783
+ | Flag | Description |
784
+ |---------------------|----------------------------------------------------------------------|
785
+ | `--wsdl-source` | Path or URL to WSDL file |
786
+
787
+ ### Output Flags
788
+
789
+ | Flag | Default | Description |
790
+ |---------------------|---------------------------------------------|---------------------------------------------------|
791
+ | `--catalog-file` | Co-located with first output (see below) | Output path for `catalog.json` (always generated) |
792
+
793
+ **Catalog Default Location**: The catalog is automatically placed alongside the first available output:
794
+ - With `--client-dir`: `{client-dir}/catalog.json`
795
+ - With `--openapi-file` only: `{openapi-file-dir}/catalog.json`
796
+ - With `--gateway-dir` only: `{gateway-dir}/catalog.json`
797
+
798
+ **Note**: At least one of `--client-dir`, `--openapi-file`, or `--gateway-dir` must be provided.
799
+
800
+ ### Generation Control Flags
801
+
802
+ | Flag | Description |
803
+ |-------------------------|------------------------------------------------|
804
+ | `--client-dir` | Generate TypeScript client in this directory |
805
+ | `--openapi-file` | Generate OpenAPI spec at this path |
806
+ | `--gateway-dir` | Generate Fastify gateway in this directory |
807
+
808
+ ### Optional Flags
809
+
810
+ All flags from `client`, `openapi`, and `gateway` commands are supported. Key flags:
811
+
812
+ #### Client Flags
813
+ - `--import-extensions` (default: `js`)
814
+ - `--client-attributes-key` (default: `$attributes`)
815
+ - `--client-class-name`
816
+ - `--client-int64-as` (default: `string`)
817
+ - `--client-bigint-as` (default: `string`)
818
+ - `--client-decimal-as` (default: `string`)
819
+ - `--client-date-as` (default: `string`)
820
+ - `--client-choice-mode` (default: `all-optional`)
821
+ - `--client-fail-on-unresolved` (default: `false`)
822
+ - `--client-nillable-as-optional` (default: `false`)
823
+
824
+ #### OpenAPI Flags
825
+ - `--openapi-format` (default: `json`)
826
+ - `--openapi-title`
827
+ - `--openapi-version` (default: `0.0.0`)
828
+ - `--openapi-description`
829
+ - `--openapi-servers` (default: `/`)
830
+ - `--openapi-base-path`
831
+ - `--openapi-path-style` (default: `kebab`)
832
+ - `--openapi-method` (default: `post`)
833
+ - `--openapi-tag-style` (default: `default`)
834
+ - `--openapi-closed-schemas` (default: `false`)
835
+ - `--openapi-prune-unused-schemas` (default: `false`)
836
+ - `--openapi-envelope-namespace` (default: `ResponseEnvelope`)
837
+ - `--openapi-error-namespace` (default: `ErrorObject`)
838
+ - `--openapi-validate` (default: `true`)
839
+ - `--openapi-security-config-file`
840
+ - `--openapi-tags-file`
841
+ - `--openapi-ops-file`
842
+
843
+ #### Gateway Flags
844
+ - `--gateway-service-name` (required if `--gateway-dir` provided)
845
+ - `--gateway-version-prefix` (required if `--gateway-dir` provided)
846
+ - `--gateway-default-status-codes`
847
+
848
+ ### Examples
849
+
850
+ #### Complete Stack Generation (Using Default Catalog Location)
851
+
852
+ ```bash
853
+ npx wsdl-tsc pipeline \
854
+ --wsdl-source examples/minimal/weather.wsdl \
855
+ --client-dir tmp/client \
856
+ --openapi-file tmp/openapi.json \
857
+ --gateway-dir tmp/gateway \
858
+ --gateway-service-name weather \
859
+ --gateway-version-prefix v1
860
+ ```
861
+
862
+ **Output**: Catalog at `tmp/client/catalog.json`.
863
+
864
+ #### Client + OpenAPI Only
865
+
866
+ ```bash
867
+ npx wsdl-tsc pipeline \
868
+ --wsdl-source https://example.com/Hotel.wsdl \
869
+ --client-dir ./build/client \
870
+ --openapi-file ./docs/hotel-api.json \
871
+ --openapi-format both
872
+ ```
873
+
874
+ **Output**: Catalog at `./build/client/catalog.json`.
875
+
876
+ #### OpenAPI + Gateway Only
877
+
878
+ ```bash
879
+ npx wsdl-tsc pipeline \
880
+ --wsdl-source ./wsdl/Booking.wsdl \
881
+ --openapi-file ./docs/booking-api.json \
882
+ --gateway-dir ./build/gateway \
883
+ --gateway-service-name booking \
884
+ --gateway-version-prefix v1
885
+ ```
886
+
887
+ **Output**: Catalog at `./docs/catalog.json`.
888
+
889
+ #### With Custom Catalog Path
890
+
891
+ ```bash
892
+ npx wsdl-tsc pipeline \
893
+ --wsdl-source ./wsdl/Booking.wsdl \
894
+ --catalog-file ./build/shared/catalog.json \
895
+ --client-dir ./build/client \
896
+ --openapi-file ./docs/booking-api.json \
897
+ --gateway-dir ./build/gateway \
898
+ --gateway-service-name booking \
899
+ --gateway-version-prefix v1
900
+ ```
901
+
902
+ #### With Full Configuration
903
+
904
+ ```bash
905
+ npx wsdl-tsc pipeline \
906
+ --wsdl-source ./wsdl/Booking.wsdl \
907
+ --client-dir ./build/client \
908
+ --openapi-file ./docs/booking-api \
909
+ --gateway-dir ./build/gateway \
910
+ --openapi-format both \
911
+ --openapi-servers https://api.example.com/v1 \
912
+ --openapi-base-path /booking \
913
+ --openapi-security-config-file ./config/security.json \
914
+ --gateway-service-name booking \
915
+ --gateway-version-prefix v1 \
916
+ --client-int64-as number \
917
+ --client-decimal-as string
918
+ ```
919
+
920
+ **Output**: Catalog at `./build/client/catalog.json`.
921
+
922
+ ### Pipeline Workflow
923
+
924
+ The pipeline command executes these steps in order:
925
+
926
+ 1. **Parse WSDL** → Load and validate WSDL document
927
+ 2. **Compile Catalog** → Generate intermediate representation
928
+ 3. **Emit Catalog** → Write `catalog.json` (always)
929
+ 4. **Generate Client** → Emit TypeScript client files (if `--client-dir`)
930
+ 5. **Generate OpenAPI** → Create OpenAPI spec (if `--openapi-file`)
931
+ 6. **Generate Gateway** → Create Fastify gateway code (if `--gateway-dir`)
932
+
933
+ All steps share the same parsed WSDL and compiled catalog, ensuring consistency.
934
+
935
+ ---
936
+
937
+ ## 10. Working With Generated Clients
938
+
939
+ ### Client Construction
940
+
941
+ ```typescript
942
+ import soap from "soap";
943
+ import { Weather } from "./src/services/weather/client.js";
944
+
945
+ const client = new Weather({
946
+ source: "https://example.com/WeatherService?wsdl",
947
+ security: new soap.WSSecurity("username", "password")
948
+ });
949
+ ```
950
+
951
+ ### Calling Operations
952
+
953
+ ```typescript
954
+ // Operation with input
955
+ const forecast = await client.GetCityForecastByZIP({
956
+ ZIP: "10001"
256
957
  });
958
+
959
+ console.log(forecast.GetCityForecastByZIPResult.Success);
960
+ console.log(forecast.GetCityForecastByZIPResult.ForecastResult);
961
+
962
+ // Operation without input
963
+ const info = await client.GetWeatherInformation({});
964
+ console.log(info.GetWeatherInformationResult.WeatherDescriptions);
965
+ ```
966
+
967
+ ### Attributes & Text Content
968
+
969
+ When an element has both attributes and text content, use the `$value` convention:
970
+
971
+ ```typescript
972
+ const price = {
973
+ currencyCode: "USD", // attribute
974
+ $value: "123.45" // text content
975
+ };
976
+ ```
977
+
978
+ ### Working With Arrays
979
+
980
+ Repeated elements are automatically typed as arrays:
981
+
982
+ ```typescript
983
+ interface ForecastReturn {
984
+ Forecast: Forecast[]; // maxOccurs > 1
985
+ }
986
+ ```
987
+
988
+ ### Type Safety
989
+
990
+ All operations and types are fully typed:
991
+
992
+ ```typescript
993
+ // TypeScript knows the exact shape
994
+ const result: GetCityWeatherByZIPResponse = await client.GetCityWeatherByZIP({
995
+ ZIP: "10001"
996
+ });
997
+
998
+ // Autocomplete and type checking work
999
+ result.GetCityWeatherByZIPResult.Temperature; // number | string (depends on mapping)
257
1000
  ```
258
1001
 
259
1002
  ---
260
- ## 7. Security Configuration (OpenAPI)
261
- `security.json` example:
1003
+
1004
+ ## 11. OpenAPI Configuration
1005
+
1006
+ ### Security Configuration (`security.json`)
1007
+
1008
+ Define security schemes, headers, and per-operation overrides:
1009
+
262
1010
  ```json
263
1011
  {
264
1012
  "global": {
265
1013
  "scheme": "bearer",
266
1014
  "bearer": { "bearerFormat": "JWT" },
267
- "headers": [ { "name": "X-Correlation-Id", "required": false, "schema": { "type": "string" } } ]
1015
+ "headers": [
1016
+ {
1017
+ "name": "X-Correlation-Id",
1018
+ "required": false,
1019
+ "schema": { "type": "string" }
1020
+ }
1021
+ ]
268
1022
  },
269
1023
  "overrides": {
270
1024
  "CancelBooking": { "scheme": "apiKey" }
271
1025
  }
272
1026
  }
273
1027
  ```
274
- Supported `scheme`: `none|basic|bearer|apiKey|oauth2`.
275
1028
 
276
- ---
277
- ## 8. Tag Inference Strategies
278
- | Strategy | Behavior |
279
- |-----------|------------------------------------------------------------------------------------|
280
- | `default` | Single tag = service name (fallback `SOAP`). |
281
- | `service` | Always service name (even if operation prefix differs). |
282
- | `first` | First lexical segment of CamelCase operation (e.g. `GetCityWeatherByZIP` → `Get`). |
1029
+ **Supported schemes**: `none`, `basic`, `bearer`, `apiKey`, `oauth2`
1030
+
1031
+ ### Tags Configuration (`tags.json`)
283
1032
 
284
- Provide `tags.json` for explicit mapping when heuristics are insufficient.
1033
+ Explicit operation tag mapping:
1034
+
1035
+ ```json
1036
+ {
1037
+ "GetCityWeatherByZIP": ["Weather", "Forecast"],
1038
+ "GetWeatherInformation": ["Weather", "Info"],
1039
+ "CancelBooking": ["Booking", "Cancellation"]
1040
+ }
1041
+ ```
1042
+
1043
+ ### Operations Configuration (`ops.json`)
1044
+
1045
+ Per-operation overrides for method, summary, description, and deprecation:
1046
+
1047
+ ```json
1048
+ {
1049
+ "GetCityWeatherByZIP": {
1050
+ "method": "get",
1051
+ "summary": "Get weather forecast by ZIP code",
1052
+ "description": "Returns a detailed weather forecast for the specified US ZIP code",
1053
+ "deprecated": false
1054
+ },
1055
+ "LegacyOperation": {
1056
+ "deprecated": true
1057
+ }
1058
+ }
1059
+ ```
285
1060
 
286
1061
  ---
287
- ## 9. Working With the Generated Client
288
- ### 9.1 SOAP Client Construction
289
- ```ts
290
- import soap from "soap";
291
- import { Hotel } from "./src/integrations/soap/hotel/client.js";
292
1062
 
293
- const hotel = new Hotel({
294
- source: "https://example.com/HotelService?wsdl",
295
- security: new soap.WSSecurity("user", "pass")
1063
+ ## 12. Programmatic API
1064
+
1065
+ All CLI commands are available as TypeScript functions for programmatic usage.
1066
+
1067
+ ### `compileWsdlToProject`
1068
+
1069
+ Generate TypeScript SOAP client from WSDL.
1070
+
1071
+ ```typescript
1072
+ import { compileWsdlToProject } from "@techspokes/typescript-wsdl-client";
1073
+
1074
+ await compileWsdlToProject({
1075
+ wsdl: "./wsdl/Hotel.wsdl",
1076
+ outDir: "./src/services/hotel",
1077
+ options: {
1078
+ imports: "js",
1079
+ catalog: true,
1080
+ primitive: {
1081
+ int64As: "number",
1082
+ bigIntegerAs: "string",
1083
+ decimalAs: "string",
1084
+ dateAs: "string"
1085
+ },
1086
+ choice: "all-optional",
1087
+ clientName: "HotelClient",
1088
+ nillableAsOptional: false
1089
+ }
296
1090
  });
1091
+ ```
1092
+
1093
+ **Type Signature**:
1094
+
1095
+ ```typescript
1096
+ // noinspection JSAnnotator
1097
+ function compileWsdlToProject(input: {
1098
+ wsdl: string;
1099
+ outDir: string;
1100
+ options?: Partial<CompilerOptions>;
1101
+ }): Promise<void>;
1102
+ ```
1103
+
1104
+ **Options** (`CompilerOptions`):
1105
+
1106
+ ```typescript
1107
+ interface CompilerOptions {
1108
+ wsdl: string;
1109
+ out: string;
1110
+ imports: "js" | "ts" | "bare";
1111
+ catalog: boolean;
1112
+ primitive: PrimitiveOptions;
1113
+ choice?: "all-optional" | "union";
1114
+ failOnUnresolved?: boolean;
1115
+ attributesKey?: string;
1116
+ clientName?: string;
1117
+ nillableAsOptional?: boolean;
1118
+ }
297
1119
 
298
- const res = await hotel.GetReservation({
299
- GetReservationRQ: { ReservationId: "ABC123" }
1120
+ interface PrimitiveOptions {
1121
+ int64As?: "string" | "number" | "bigint";
1122
+ bigIntegerAs?: "string" | "number";
1123
+ decimalAs?: "string" | "number";
1124
+ dateAs?: "string" | "Date";
1125
+ }
1126
+ ```
1127
+
1128
+ ### `generateOpenAPI`
1129
+
1130
+ Generate OpenAPI 3.1 specification from WSDL or catalog.
1131
+
1132
+ ```typescript
1133
+ import { generateOpenAPI } from "@techspokes/typescript-wsdl-client";
1134
+
1135
+ const { doc, jsonPath, yamlPath } = await generateOpenAPI({
1136
+ wsdl: "./wsdl/Hotel.wsdl",
1137
+ outFile: "./docs/hotel-api",
1138
+ format: "both",
1139
+ title: "Hotel Booking API",
1140
+ version: "1.0.0",
1141
+ servers: ["https://api.example.com/v1"],
1142
+ basePath: "/booking",
1143
+ pathStyle: "kebab",
1144
+ tagStyle: "service",
1145
+ validate: true
300
1146
  });
301
1147
  ```
302
- ### 9.2 Attributes & Text Values
303
- If an element has text content and attributes, you pass both:
304
- ```ts
305
- const Price = {
306
- currencyCode: "USD",
307
- $value: "123.45"
308
- };
1148
+
1149
+ **Type Signature**:
1150
+
1151
+ ```typescript
1152
+ // noinspection JSAnnotator
1153
+ function generateOpenAPI(opts: GenerateOpenAPIOptions): Promise<{
1154
+ doc: any;
1155
+ jsonPath?: string;
1156
+ yamlPath?: string;
1157
+ }>;
1158
+ ```
1159
+
1160
+ **Options** (`GenerateOpenAPIOptions`):
1161
+
1162
+ ```typescript
1163
+ interface GenerateOpenAPIOptions {
1164
+ // Input sources (mutually exclusive)
1165
+ wsdl?: string;
1166
+ catalogFile?: string;
1167
+ compiledCatalog?: CompiledCatalog;
1168
+
1169
+ // Output
1170
+ outFile?: string;
1171
+ format?: "json" | "yaml" | "both";
1172
+
1173
+ // Metadata
1174
+ title?: string;
1175
+ version?: string;
1176
+ description?: string;
1177
+ servers?: string[];
1178
+
1179
+ // Path configuration
1180
+ basePath?: string;
1181
+ pathStyle?: "kebab" | "asis" | "lower";
1182
+ defaultMethod?: string;
1183
+
1184
+ // Schema configuration
1185
+ closedSchemas?: boolean;
1186
+ pruneUnusedSchemas?: boolean;
1187
+
1188
+ // Tag configuration
1189
+ tagStyle?: "default" | "first" | "service";
1190
+ tagsFile?: string;
1191
+
1192
+ // Security & operations
1193
+ securityConfigFile?: string;
1194
+ opsFile?: string;
1195
+
1196
+ // Envelope customization
1197
+ envelopeNamespace?: string;
1198
+ errorNamespace?: string;
1199
+
1200
+ // Validation
1201
+ validate?: boolean;
1202
+ skipValidate?: boolean;
1203
+
1204
+ // Deprecated
1205
+ asYaml?: boolean;
1206
+ }
1207
+ ```
1208
+
1209
+ ### `generateGateway`
1210
+
1211
+ Generate Fastify gateway code from OpenAPI specification.
1212
+
1213
+ ```typescript
1214
+ import { generateGateway } from "@techspokes/typescript-wsdl-client";
1215
+
1216
+ await generateGateway({
1217
+ openapiFile: "./docs/hotel-api.json",
1218
+ outDir: "./src/gateway/hotel",
1219
+ clientDir: "./src/services/hotel",
1220
+ versionSlug: "v1",
1221
+ serviceSlug: "hotel",
1222
+ defaultResponseStatusCodes: [200, 400, 401, 403, 404, 409, 422, 429, 500, 502, 503, 504],
1223
+ imports: "js"
1224
+ });
1225
+ ```
1226
+
1227
+ **Type Signature**:
1228
+
1229
+ ```typescript
1230
+ // noinspection JSAnnotator
1231
+ function generateGateway(opts: GenerateGatewayOptions): Promise<void>;
1232
+ ```
1233
+
1234
+ **Options** (`GenerateGatewayOptions`):
1235
+
1236
+ ```typescript
1237
+ interface GenerateGatewayOptions {
1238
+ // Input sources (mutually exclusive)
1239
+ openapiFile?: string;
1240
+ openapiDocument?: any;
1241
+
1242
+ // Output
1243
+ outDir: string;
1244
+
1245
+ // Client integration
1246
+ clientDir?: string;
1247
+
1248
+ // URN configuration
1249
+ versionSlug?: string;
1250
+ serviceSlug?: string;
1251
+
1252
+ // Schema configuration
1253
+ defaultResponseStatusCodes?: number[];
1254
+
1255
+ // Import style
1256
+ imports?: "js" | "ts" | "bare";
1257
+ }
1258
+ ```
1259
+
1260
+ ### `runGenerationPipeline`
1261
+
1262
+ Run complete pipeline: client + OpenAPI + gateway in one pass.
1263
+
1264
+ ```typescript
1265
+ import { runGenerationPipeline } from "@techspokes/typescript-wsdl-client";
1266
+
1267
+ const { compiled, openapiDoc } = await runGenerationPipeline({
1268
+ wsdl: "./wsdl/Hotel.wsdl",
1269
+ catalogOut: "./build/hotel-catalog.json",
1270
+ clientOutDir: "./src/services/hotel",
1271
+ compiler: {
1272
+ imports: "js",
1273
+ primitive: {
1274
+ int64As: "number",
1275
+ decimalAs: "string"
1276
+ }
1277
+ },
1278
+ openapi: {
1279
+ outFile: "./docs/hotel-api.json",
1280
+ format: "both",
1281
+ servers: ["https://api.example.com/v1"],
1282
+ tagStyle: "service"
1283
+ },
1284
+ gateway: {
1285
+ outDir: "./src/gateway/hotel",
1286
+ versionSlug: "v1",
1287
+ serviceSlug: "hotel"
1288
+ }
1289
+ });
1290
+ ```
1291
+
1292
+ **Type Signature**:
1293
+
1294
+ ```typescript
1295
+ // noinspection JSAnnotator
1296
+ function runGenerationPipeline(opts: PipelineOptions): Promise<{
1297
+ compiled: CompiledCatalog;
1298
+ openapiDoc?: any;
1299
+ }>;
1300
+ ```
1301
+
1302
+ **Options** (`PipelineOptions`):
1303
+
1304
+ ```typescript
1305
+ interface PipelineOptions {
1306
+ // Input
1307
+ wsdl: string;
1308
+
1309
+ // Catalog (always generated)
1310
+ catalogOut: string;
1311
+
1312
+ // Client generation (optional)
1313
+ clientOutDir?: string;
1314
+ compiler?: Partial<CompilerOptions>;
1315
+
1316
+ // OpenAPI generation (optional)
1317
+ openapi?: Omit<GenerateOpenAPIOptions, "wsdl" | "catalogFile" | "compiledCatalog"> & {
1318
+ outFile?: string;
1319
+ };
1320
+
1321
+ // Gateway generation (optional, requires openapi)
1322
+ gateway?: Omit<GenerateGatewayOptions, "openapiFile" | "openapiDocument"> & {
1323
+ outDir?: string;
1324
+ };
1325
+ }
309
1326
  ```
310
1327
 
311
1328
  ---
312
- ## 10. Advanced Topics
313
- | Topic | Notes |
314
- |------------------------------|-------------------------------------------------------------------------------------|
315
- | Primitive mapping philosophy | Defaults prefer string to avoid precision loss. |
316
- | Choice flattening | Represented as optional union of fields – simpler consumption. |
317
- | Array wrappers | Single repeated child w/out attributes collapses to an array schema in OpenAPI. |
318
- | Validation | Uses `@apidevtools/swagger-parser`; disable with `--no-validate`. |
319
- | Future | Discriminated unions for choices, richer policy extraction, snapshot OpenAPI tests. |
1329
+
1330
+ ## 13. Advanced Topics
1331
+
1332
+ ### Primitive Mapping Philosophy
1333
+
1334
+ **Default: String-first safety** Prevents precision loss and parsing errors at the cost of convenience.
1335
+
1336
+ | XSD Type | Default | Alternatives | Recommendation |
1337
+ |---------------|----------|--------------------|-------------------------------------------------|
1338
+ | `xs:long` | `string` | `number`, `bigint` | Use `number` if values fit safely in JS range |
1339
+ | `xs:integer` | `string` | `number` | Use `string` for arbitrary-size integers |
1340
+ | `xs:decimal` | `string` | `number` | Use `string` for precise decimal representation |
1341
+ | `xs:dateTime` | `string` | `Date` | Use `Date` if runtime parsing is acceptable |
1342
+
1343
+ ### Choice Element Handling
1344
+
1345
+ **Current strategy**: `all-optional` — All choice branches are emitted as optional properties.
1346
+
1347
+ ```typescript
1348
+ // WSDL: <xs:choice>
1349
+ interface MyType {
1350
+ optionA?: string;
1351
+ optionB?: number;
1352
+ }
1353
+ ```
1354
+
1355
+ **Future**: Discriminated unions for type-safe choice validation.
1356
+
1357
+ ### Array Wrapper Flattening
1358
+
1359
+ Single repeated child without attributes collapses to array schema in OpenAPI:
1360
+
1361
+ ```xml
1362
+ <xs:complexType name="ArrayOfForecast">
1363
+ <xs:sequence>
1364
+ <xs:element name="Forecast" type="tns:Forecast" maxOccurs="unbounded"/>
1365
+ </xs:sequence>
1366
+ </xs:complexType>
1367
+ ```
1368
+
1369
+ **OpenAPI Schema**:
1370
+
1371
+ ```json
1372
+ {
1373
+ "ArrayOfForecast": {
1374
+ "type": "array",
1375
+ "items": { "$ref": "#/components/schemas/Forecast" }
1376
+ }
1377
+ }
1378
+ ```
1379
+
1380
+ ### Inheritance Flattening
1381
+
1382
+ **Extension (`xs:extension`)**:
1383
+ - Base properties merged into derived type
1384
+ - TypeScript: `extends` when possible
1385
+
1386
+ **Restriction (`xs:restriction`)**:
1387
+ - Treated as base type with constraints
1388
+
1389
+ **SimpleContent**:
1390
+ - Base value collapsed into `$value` property
1391
+ - Attributes remain as peer properties
1392
+
1393
+ ### Validation
1394
+
1395
+ OpenAPI validation uses `@apidevtools/swagger-parser`:
1396
+ - Validates schema structure
1397
+ - Resolves all `$ref` references
1398
+ - Catches missing schemas
1399
+ - Detects circular dependencies
1400
+
1401
+ Disable with `--openapi-validate false` or `validate: false` in API.
320
1402
 
321
1403
  ---
322
- ## 11. Troubleshooting
323
- | Symptom | Resolution |
324
- |---------------------------|--------------------------------------------------------------------------|
325
- | WSDL fetch fails | Curl the URL, check TLS/proxy, retry with local copy. |
326
- | Unresolved types | Re-run with `--fail-on-unresolved=false` to inspect partial graph. |
327
- | Missing schema in OpenAPI | Ensure the global element exists (catalog shows compiled symbols). |
328
- | Wrong array modeling | Check `maxOccurs` in WSDL; tool only arrays when `max>1` or `unbounded`. |
329
- | Auth errors at runtime | Provide a proper `soap.ISecurity` instance (`WSSecurity`, etc.). |
330
- | Date/time confusion | Use `--date-as Date` for runtime Date objects. |
331
-
332
- Enable SOAP wire logging:
1404
+
1405
+ ## 14. Troubleshooting
1406
+
1407
+ ### Common Issues
1408
+
1409
+ | Symptom | Resolution |
1410
+ |-----------------------------------|---------------------------------------------------------------------------------------------------------------------------|
1411
+ | **WSDL fetch fails** | Curl the URL, check TLS/proxy settings, retry with local copy |
1412
+ | **Unresolved type references** | Re-run with `--client-fail-on-unresolved=false` to inspect partial graph |
1413
+ | **Missing schema in OpenAPI** | Ensure the global element exists (catalog shows compiled symbols) |
1414
+ | **Wrong array modeling** | Check `maxOccurs` in WSDL; tool only arrays when `maxOccurs>1` or `unbounded` |
1415
+ | **Authentication errors** | Provide proper `soap.ISecurity` instance (`WSSecurity`, `BasicAuthSecurity`) |
1416
+ | **Date/time confusion** | Use `--client-date-as Date` for runtime Date objects |
1417
+ | **TypeScript compilation errors** | Check `--import-extensions` matches your tsconfig `moduleResolution` |
1418
+ | **Gateway validation failures** | Ensure OpenAPI has valid `$ref` paths and all schemas in `components.schemas` |
1419
+ | **Catalog file not found** | Catalog defaults to output directory (e.g., `{client-dir}/catalog.json`); use `--catalog-file` to specify custom location |
1420
+
1421
+ ### Enable SOAP Wire Logging
1422
+
1423
+ Debug SOAP requests/responses:
1424
+
333
1425
  ```bash
334
1426
  NODE_DEBUG=soap node app.js
335
1427
  ```
336
1428
 
1429
+ ### Verify Installation
1430
+
1431
+ ```bash
1432
+ npx wsdl-tsc --help
1433
+ npm run smoke:compile # Test catalog generation
1434
+ npm run smoke:client # Test client generation
1435
+ npm run smoke:openapi # Test OpenAPI generation
1436
+ npm run smoke:gateway # Test gateway generation
1437
+ npm run smoke:pipeline # Test complete pipeline
1438
+ ```
1439
+
1440
+ ### TypeScript Configuration
1441
+
1442
+ Ensure your `tsconfig.json` is compatible:
1443
+
1444
+ ```json
1445
+ {
1446
+ "compilerOptions": {
1447
+ "target": "ES2022",
1448
+ "module": "NodeNext",
1449
+ "moduleResolution": "NodeNext",
1450
+ "strict": true,
1451
+ "esModuleInterop": true,
1452
+ "skipLibCheck": true
1453
+ }
1454
+ }
1455
+ ```
1456
+
1457
+ ### Catalog Inspection
1458
+
1459
+ Examine the compiled catalog to understand type resolution:
1460
+
1461
+ ```bash
1462
+ # Compile to specific location
1463
+ npx wsdl-tsc compile \
1464
+ --wsdl-source ./wsdl/Hotel.wsdl \
1465
+ --catalog-file build/hotel-catalog.json
1466
+
1467
+ # Inspect types, operations, and metadata
1468
+ cat build/hotel-catalog.json | jq '.types'
1469
+ cat build/hotel-catalog.json | jq '.operations'
1470
+ ```
1471
+
1472
+ Or inspect catalog from client generation:
1473
+
1474
+ ```bash
1475
+ npx wsdl-tsc client \
1476
+ --wsdl-source ./wsdl/Hotel.wsdl \
1477
+ --client-dir ./src/services/hotel
1478
+
1479
+ cat ./src/services/hotel/catalog.json | jq '.types'
1480
+ ```
1481
+
1482
+ The catalog is automatically placed at `./src/services/hotel/catalog.json`.
1483
+
337
1484
  ---
338
- ## 12. Programmatic Reference (Summary)
339
- | Function | Purpose |
340
- |-------------------------|-----------------------------------------------------|
341
- | `compileWsdlToProject` | WSDL TS artifacts. |
342
- | `generateOpenAPI` | WSDL or catalog → OpenAPI (`json`, `yaml`, `both`). |
343
- | `runGenerationPipeline` | One pass: compile + TS emit + OpenAPI. |
1485
+
1486
+ ## 15. Contributing
1487
+
1488
+ We welcome contributions! Here's how to get started:
1489
+
1490
+ ### Development Setup
1491
+
1492
+ ```bash
1493
+ # Clone repository
1494
+ git clone https://github.com/techspokes/typescript-wsdl-client.git
1495
+ cd typescript-wsdl-client
1496
+
1497
+ # Install dependencies
1498
+ npm install
1499
+
1500
+ # Build
1501
+ npm run build
1502
+
1503
+ # Type check
1504
+ npm run typecheck
1505
+
1506
+ # Run smoke tests
1507
+ npm run smoke:compile
1508
+ npm run smoke:client
1509
+ npm run smoke:openapi
1510
+ npm run smoke:gateway
1511
+ npm run smoke:pipeline
1512
+
1513
+ # Run full CI suite
1514
+ npm run ci
1515
+ ```
1516
+
1517
+ ### Making Changes
1518
+
1519
+ 1. **Fork & branch** — Create a feature branch from `main`
1520
+ 2. **Make changes** — Implement your feature or fix
1521
+ 3. **Test** — Run smoke tests and verify functionality
1522
+ 4. **Update CHANGELOG** — Add entry under `## [Unreleased]` section
1523
+ 5. **Commit** — Use conventional commit format: `feat:`, `fix:`, `docs:`, etc.
1524
+ 6. **Submit PR** — Create pull request with clear description
1525
+
1526
+ ### Commit Message Format
1527
+
1528
+ ```
1529
+ Version: <version> <type>(<optional-scope>): <imperative summary>
1530
+
1531
+ [optional body with details, rationale, breaking changes]
1532
+
1533
+ [optional footer with refs: Closes #123]
1534
+ ```
1535
+
1536
+ **Types**: `feat`, `fix`, `docs`, `refactor`, `test`, `chore`
1537
+
1538
+ **Example**:
1539
+ ```
1540
+ Version: 0.8.0 feat(gateway): add support for YAML OpenAPI input
1541
+
1542
+ Gateway command now accepts both JSON and YAML OpenAPI files,
1543
+ determined by file extension (.json, .yaml, .yml).
1544
+
1545
+ Closes #456
1546
+ ```
1547
+
1548
+ ### Guidelines
1549
+
1550
+ - Follow existing code style and conventions
1551
+ - Keep PRs focused and scoped
1552
+ - Update documentation for user-visible changes
1553
+ - Add tests where applicable
1554
+ - Ensure CI passes
1555
+
1556
+ See also: [CONTRIBUTING.md](CONTRIBUTING.md), [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)
344
1557
 
345
1558
  ---
346
- ## 13. Contributing
347
- 1. Fork & branch.
348
- 2. `npm i && npm run build`.
349
- 3. Use `npm run smoke:gen`, `npm run smoke:pipeline`.
350
- - Pipeline smoke validates envelope, ordering & validation.
351
- 4. Add a bullet under **Unreleased** in `CHANGELOG.md`.
352
1559
 
353
- See also: `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`.
1560
+ ## 16. License
1561
+
1562
+ MIT © TechSpokes
1563
+
1564
+ Generated artifacts are fully yours with no restrictions or attribution required.
1565
+
1566
+ See [LICENSE](LICENSE) for full text.
354
1567
 
355
1568
  ---
356
- ## 14. License
357
- MIT © TechSpokes — Generated artifacts are fully yours.
1569
+
1570
+ ## 17. Sponsors
1571
+
1572
+ Support ongoing development and maintenance:
1573
+
1574
+ **GitHub Sponsors**: https://github.com/sponsors/TechSpokes
1575
+
1576
+ ### Current Sponsors
1577
+
1578
+ *Your organization could be featured here!*
1579
+
1580
+ ### Why Sponsor?
1581
+
1582
+ - Priority support for issues and feature requests
1583
+ - Early access to new features
1584
+ - Recognition in README and release notes
1585
+ - Direct influence on roadmap priorities
1586
+ - Support open source sustainability
1587
+
1588
+ Thank you for considering sponsorship!
358
1589
 
359
1590
  ---
360
- ## 15. Sponsors
361
- Support ongoing maintenance: https://github.com/sponsors/TechSpokes
362
- *Your brand could be featured here.*
1591
+
1592
+ ## Links
1593
+
1594
+ - **Documentation**: [README.md](README.md) (you are here)
1595
+ - **Contributing Guide**: [CONTRIBUTING.md](CONTRIBUTING.md)
1596
+ - **Roadmap**: [ROADMAP.md](ROADMAP.md)
1597
+ - **Changelog**: [CHANGELOG.md](CHANGELOG.md)
1598
+ - **Security Policy**: [SECURITY.md](SECURITY.md)
1599
+ - **Support**: [SUPPORT.md](SUPPORT.md)
1600
+ - **Issues**: https://github.com/techspokes/typescript-wsdl-client/issues
1601
+ - **Discussions**: https://github.com/techspokes/typescript-wsdl-client/discussions
1602
+ - **npm Package**: https://www.npmjs.com/package/@techspokes/typescript-wsdl-client
1603
+