# CLI Reference The `wsdl-tsc` tool generates TypeScript SOAP clients, OpenAPI specifications, and Fastify gateways from WSDL files. ## Commands Overview The tool provides six commands for different integration scenarios. | Command | Purpose | Typical Use Case | |---------|---------|------------------| | pipeline | Full pipeline: client + OpenAPI + gateway + app | CI/CD automation, complete stack generation | | client | TypeScript SOAP client from WSDL or catalog | Standard SOAP integration | | openapi | OpenAPI 3.1 spec from WSDL or catalog | Documentation, REST proxies, API gateways | | gateway | Fastify gateway from OpenAPI spec | Production REST gateway with SOAP backend | | app | Runnable Fastify app from client + gateway + OpenAPI | Local testing, demos | | compile | Parse WSDL to catalog.json only | Debugging, multi-stage builds | ## pipeline 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. ### Usage ```bash npx wsdl-tsc pipeline \ --wsdl-source \ [--catalog-file ] \ [--client-dir ] \ [--openapi-file ] \ [--gateway-dir ] \ [options] ``` ### Required Flags | Flag | Description | |------|-------------| | `--wsdl-source` | Path or URL to WSDL file | At least one of `--client-dir`, `--openapi-file`, or `--gateway-dir` must be provided. ### Output Flags | Flag | Default | Description | |------|---------|-------------| | `--catalog-file` | Co-located with first output | Output path for catalog.json | The catalog is auto-placed alongside the first available output directory: `{client-dir}`, `{openapi-file-dir}`, or `{gateway-dir}`. ### Generation Control Flags | Flag | Description | |------|-------------| | `--client-dir` | Generate TypeScript client in this directory | | `--openapi-file` | Generate OpenAPI spec at this path | | `--gateway-dir` | Generate Fastify gateway in this directory | | `--clean` | Remove existing client output directory contents before generation | ### Client Flags | Flag | Default | Description | |------|---------|-------------| | `--import-extensions` | `js` | Import style: js, ts, or bare | | `--client-attributes-key` | `$attributes` | Attribute bag key | | `--client-class-name` | (derived) | Override client class name | | `--client-int64-as` | `string` | Map 64-bit integers | | `--client-bigint-as` | `string` | Map arbitrary-size integers | | `--client-decimal-as` | `string` | Map xs:decimal | | `--client-date-as` | `string` | Map date/time types | | `--client-choice-mode` | `all-optional` | Controls `xs:choice` modeling | | `--client-fail-on-unresolved` | `false` | Fail on unresolved references | | `--client-nillable-as-optional` | `false` | Treat nillable as optional | `--client-choice-mode` accepts `all-optional` and `union`. The default `all-optional` mode emits parallel optional choice fields. The `union` mode emits exclusive generated client type branches and catalog-backed OpenAPI schema constraints. ### OpenAPI Flags | Flag | Default | Description | |------|---------|-------------| | `--openapi-format` | `json` | Output format: json, yaml, or both | | `--openapi-title` | (derived) | API title | | `--openapi-version-tag` | `0.0.0` | API version for `info.version` | | `--openapi-servers` | `/` | Comma-separated server URLs (see note below) | | `--openapi-base-path` | (empty) | Base path prefix | | `--openapi-path-style` | `kebab` | Path transform: kebab, asis, or lower | | `--openapi-default-method` | `post` | Default HTTP method | | `--openapi-tag-style` | `default` | Tag inference: default, service, or first | | `--openapi-closed-schemas` | `false` | Add additionalProperties: false | | `--openapi-flatten-array-wrappers` | `true` | Flatten ArrayOf* wrappers to plain arrays; emit runtime unwrap in gateway | | `--openapi-prune-unused-schemas` | `false` | Emit only referenced schemas | | `--openapi-envelope-namespace` | `ResponseEnvelope` | Envelope component name suffix | | `--openapi-error-namespace` | `ErrorObject` | Error object name suffix | | `--openapi-security-config-file` | | Path to security.json; `--openapi-security-file` is accepted as an alias | | `--openapi-tags-file` | | Path to tags.json | | `--openapi-ops-file` | | Path to ops.json | CLI OpenAPI generation always validates the generated spec with `@apidevtools/swagger-parser`. When `--init-app` is used and `--openapi-servers` is not provided, servers default to `http://localhost:3000`. The app scaffold also rewrites the servers array in its local `openapi.json` copy to match the configured port and prefix. ### Gateway Flags | Flag | Default | Description | |------|---------|-------------| | `--gateway-service-name` | (required if --gateway-dir) | Service identifier for URN | | `--gateway-version-prefix` | (required if --gateway-dir) | Version prefix for URN | | `--gateway-default-status-codes` | 200,400,401,403,404,409,422,429,500,502,503,504 | Status codes to backfill | | `--gateway-stub-handlers` | `false` | Generate stubs instead of full handlers | | `--gateway-client-class-name` | (auto-detected) | Override SOAP client class name | | `--gateway-decorator-name` | {serviceSlug}Client | Fastify decorator name | | `--gateway-skip-plugin` | `false` | Skip plugin.ts generation | | `--gateway-skip-runtime` | `false` | Skip runtime.ts generation | | `--openapi-flatten-array-wrappers` | `true` | Generate runtime unwrap for ArrayOf* wrapper types | ### App Scaffold Flags | Flag | Default | Description | |------|---------|-------------| | `--init-app` | `false` | Scaffold runnable Fastify app (requires client, gateway, OpenAPI) | | `--force-init` | `false` | Overwrite existing scaffold files | | `--app-dir` | sibling `app/` | Output directory for app scaffold | | `--app-openapi-mode` | `copy` | How to handle OpenAPI file: copy or reference | | `--app-host` | `127.0.0.1` | Default server host | | `--app-port` | `3000` | Default server port | | `--app-prefix` | (empty) | Route prefix | ### Test Suite Flags | Flag | Default | Description | |------|---------|-------------| | `--test-dir` | (none) | Generate Vitest test suite in this directory (requires client, gateway) | | `--force-test` | `false` | Overwrite existing test files when using --test-dir | ### Stream Configuration Flags | Flag | Default | Description | |------|---------|-------------| | `--stream-config` | (none) | Path to a JSON stream-configuration file (ADR-002). Marks selected operations as streaming: client emits `AsyncIterable`, gateway serves NDJSON or JSON array output, OpenAPI advertises the record schema via `x-wsdl-tsc-stream`. Buffered output is unchanged when the flag is omitted. | `--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. Stream-config file shape (see `docs/decisions/002-streamable-responses.md`): ```json { "shapeCatalogs": { "main": { "wsdlSource": "https://api.example.com/Main.svc?singleWsdl" } }, "operations": { "UnitDescriptiveInfoStream": { "recordType": "UnitDescriptiveContentType", "recordPath": [ "UnitDescriptiveInfoStream", "EVRN_UnitDescriptiveInfoRS", "UnitDescriptiveContents", "UnitDescriptiveContent" ], "shapeCatalog": "main" } } } ``` ### Pipeline Workflow Steps execute in order: 1. Parse WSDL and validate 2. Compile catalog (intermediate representation) 3. Write catalog.json (always) 4. Generate client (if --client-dir) 5. Generate OpenAPI (if --openapi-file) 6. Generate gateway (if --gateway-dir) 7. Scaffold app (if --init-app) 8. Generate test suite (if --test-dir) All steps share the same parsed WSDL and compiled catalog. ### Examples Complete stack: ```bash npx wsdl-tsc pipeline \ --wsdl-source examples/minimal/weather.wsdl \ --client-dir tmp/client \ --openapi-file tmp/openapi.json \ --gateway-dir tmp/gateway \ --gateway-service-name weather \ --gateway-version-prefix v1 ``` With app scaffold: ```bash npx wsdl-tsc pipeline \ --wsdl-source https://example.com/weather?wsdl \ --client-dir ./generated/client \ --openapi-file ./generated/openapi.json \ --gateway-dir ./generated/gateway \ --gateway-service-name weather \ --gateway-version-prefix v1 \ --init-app ``` With union-mode choice modeling: ```bash npx wsdl-tsc pipeline \ --wsdl-source ./service.wsdl \ --client-dir ./generated/client \ --openapi-file ./generated/openapi.json \ --gateway-dir ./generated/gateway \ --gateway-service-name service \ --gateway-version-prefix v1 \ --client-choice-mode union ``` With generated test suite: ```bash npx wsdl-tsc pipeline \ --wsdl-source examples/minimal/weather.wsdl \ --client-dir tmp/client \ --openapi-file tmp/openapi.json \ --gateway-dir tmp/gateway \ --gateway-service-name weather \ --gateway-version-prefix v1 \ --test-dir tmp/tests ``` Client and OpenAPI only: ```bash npx wsdl-tsc pipeline \ --wsdl-source https://example.com/Hotel.wsdl \ --client-dir ./build/client \ --openapi-file ./docs/hotel-api.json \ --openapi-format both ``` ## client Generate strongly-typed TypeScript SOAP client code from WSDL or a pre-compiled catalog. ### Usage ```bash npx wsdl-tsc client --wsdl-source --client-dir [options] npx wsdl-tsc client --catalog-file --client-dir [options] ``` ### Required Flags | Flag | Description | |------|-------------| | `--wsdl-source` | Path or URL to WSDL file | | `--client-dir` | Output directory for generated files | 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`. ### Generated Files | File | Purpose | |------|---------| | `client.ts` | Typed SOAP client with one method per operation | | `types.ts` | Flattened TypeScript interfaces, type aliases, enums | | `utils.ts` | Runtime metadata for JSON-to-SOAP conversion | | `catalog.json` | Generated in client directory when using --wsdl-source | ### Optional Flags All flags from the compile command apply, plus the client-specific flags listed in the pipeline section. | Flag | Default | Description | |------|---------|-------------| | `--client-choice-mode` | `all-optional` | Controls `xs:choice` modeling | `--client-choice-mode` accepts `all-optional` and `union`. The `client` command stores the selected mode in `catalog.json` when it compiles from WSDL and uses that catalog metadata when emitting generated TypeScript. ### Key Modeling Rules - Attributes and elements become peer properties (flattened) - Text content becomes `$value` property - Required: `use!="optional"` for attributes; `minOccurs>=1` for elements - Arrays: `maxOccurs>1` or `unbounded` become arrays - Nillable: `nillable="true"` preserved (optionally model as optional) - Inheritance: extensions merged or emitted as extends ### Examples Basic: ```bash npx wsdl-tsc client \ --wsdl-source examples/minimal/weather.wsdl \ --client-dir tmp/client ``` From catalog: ```bash npx wsdl-tsc client \ --catalog-file build/hotel-catalog.json \ --client-dir ./src/services/hotel ``` ## openapi Generate OpenAPI 3.1 specification from WSDL or pre-compiled catalog. ### Usage ```bash npx wsdl-tsc openapi --wsdl-source --openapi-file [options] npx wsdl-tsc openapi --catalog-file --openapi-file [options] ``` ### Required Flags | Flag | Description | |------|-------------| | `--openapi-file` | Output path for OpenAPI specification | ### Input Source Flags These flags are mutually exclusive. | Flag | Default | Description | |------|---------|-------------| | `--wsdl-source` | (none) | Path or URL to WSDL | | `--catalog-file` | {openapi-file-dir}/catalog.json | Pre-compiled catalog | ### Response Envelope All responses are wrapped in a standard envelope (always-on since v0.7.1). Base structure: ```typescript { status: string; message: string | null; data: T | null; error: ErrorObject | null; } ``` Error structure: ```typescript { code: string; message: string; details: object | null; } ``` The base envelope is named `${serviceName}ResponseEnvelope` (override with `--openapi-envelope-namespace`). The error object is named `${serviceName}ErrorObject` (override with `--openapi-error-namespace`). Per-operation envelopes are named ``. If a payload type ends with the namespace prefix, an underscore is inserted to avoid collisions. ### Tag Inference Strategies | Strategy | Behavior | |----------|----------| | `default` | Single tag = service name (fallback SOAP) | | `service` | Always service name | | `first` | First lexical CamelCase segment | Use `--openapi-tags-file` for explicit mapping. ### Output Determinism All specs have deterministic ordering. Paths, methods, schemas, security schemes, parameters, and tags are sorted alphabetically. ### Examples Basic: ```bash npx wsdl-tsc openapi \ --wsdl-source examples/minimal/weather.wsdl \ --openapi-file ./docs/weather-api.json ``` Multi-format: ```bash npx wsdl-tsc openapi \ --wsdl-source https://example.com/Hotel.wsdl \ --openapi-file ./docs/hotel-api \ --openapi-format both \ --openapi-servers https://api.example.com/v1 ``` ## gateway Generate production-ready Fastify gateway with route handlers from an OpenAPI specification. ### Usage ```bash npx wsdl-tsc gateway \ --openapi-file \ --client-dir \ --gateway-dir \ --gateway-service-name \ --gateway-version-prefix \ [options] ``` ### Required Flags | Flag | Description | |------|-------------| | `--openapi-file` | Path to OpenAPI 3.1 JSON or YAML file | | `--client-dir` | Path to client directory | | `--gateway-dir` | Output directory for gateway code | | `--gateway-service-name` | Service identifier for URN generation | | `--gateway-version-prefix` | Version prefix for URN generation | Route URLs are derived from OpenAPI paths, which include any base path from `--openapi-base-path`. ### Generated Output Structure ```text {gateway-dir}/ ├── schemas/ │ ├── models/ # JSON Schema with URN IDs │ └── operations/ # Fastify operation schemas ├── routes/ # Route handlers with full implementations ├── schemas.ts # Schema registration module ├── routes.ts # Route aggregator ├── runtime.ts # Envelope builders, error handlers └── plugin.ts # Fastify plugin wrapper (recommended entry point) ``` ### URN-Based Schema IDs Format: `urn:services:{serviceSlug}:{versionSlug}:schemas:{models|operations}:{schemaSlug}` ### Contract Assumptions - All request/response bodies must use `$ref` to `components.schemas` - Every operation must have a default response with `application/json` - All referenced schemas must exist in `components.schemas` ### Examples Basic: ```bash npx wsdl-tsc gateway \ --openapi-file ./docs/weather-api.json \ --client-dir ./src/services/weather \ --gateway-dir ./src/gateway/weather \ --gateway-service-name weather \ --gateway-version-prefix v1 ``` ## app Scaffold a runnable Fastify application integrating client, gateway, and OpenAPI spec. The generated app is TypeScript and includes `package.json` and `tsconfig.json` for immediate use. Scaffold files that already exist are skipped by default. Use `--force` to overwrite. ### Usage ```bash npx wsdl-tsc app \ --client-dir \ --gateway-dir \ --openapi-file \ [--app-dir ] \ [options] ``` ### Required Flags | Flag | Description | |------|-------------| | `--client-dir` | Path to client directory | | `--gateway-dir` | Path to gateway directory | | `--openapi-file` | Path to OpenAPI spec | ### Optional Flags | Flag | Default | Description | |------|---------|-------------| | `--catalog-file` | {client-dir}/catalog.json | Path to catalog.json | | `--app-dir` | {gateway-dir}/../app | Output directory | | `--import-extensions` | Inferred or js | Import style | | `--host` | 127.0.0.1 | Default server host | | `--port` | 3000 | Default server port | | `--prefix` | (empty) | Route prefix | | `--logger` | true | Enable Fastify logger | | `--openapi-mode` | copy | copy or reference | | `--security-config-file` | (none) | Path to security.json for upstream SOAP security scaffold | | `--force` | false | Overwrite existing scaffold files | ### Generated Structure ```text app/ ├── server.ts # Main entry point (TypeScript) ├── config.ts # Configuration with env support ├── package.json # Dependencies (fastify, soap, tsx) ├── tsconfig.json # NodeNext/ES2022 configuration ├── .env.example # Environment template ├── README.md # Usage instructions └── openapi.json # OpenAPI spec (when --openapi-mode=copy) ``` ### Environment Variables | Variable | Default | Description | |----------|---------|-------------| | `WSDL_SOURCE` | URL fallback or required | WSDL URL or path | | `HOST` | 127.0.0.1 | Server bind address | | `PORT` | 3000 | Server listen port | | `PREFIX` | (empty) | Route prefix | | `LOGGER` | true | Fastify logger | | `OPENAPI_SERVER_URL` | (empty) | Override OpenAPI spec server URL at runtime | When `--security-config-file` is supplied and it contains an `upstream` profile, `.env.example` also lists the environment variables referenced by that profile. ### Endpoints - `GET /health` returns `{ "ok": true }` - `GET /openapi.json` returns the OpenAPI specification - All SOAP operations are exposed as REST endpoints ### Quick Start ```bash cd app/ npm install cp .env.example .env # Edit .env — set WSDL_SOURCE to your WSDL URL npm start ``` The app can also be scaffolded via pipeline with `--init-app`. ## compile Parse WSDL and generate only the intermediate catalog.json representation. This is an advanced command for debugging and multi-stage builds. ### Usage ```bash npx wsdl-tsc compile --wsdl-source --catalog-file [options] ``` ### Required Flags | Flag | Description | |------|-------------| | `--wsdl-source` | Path or URL to WSDL file | | `--catalog-file` | Output path for catalog.json | ### Compiler Flags | Flag | Default | Description | |------|---------|-------------| | `--client-choice-mode` | `all-optional` | Controls `xs:choice` modeling | `--client-choice-mode` accepts `all-optional` and `union`. The `compile` command writes the selected mode to `catalog.json` so later catalog-backed generation stages can use the same choice strategy. ### Catalog Co-location Default behavior varies by command: | Command | Default catalog location | |---------|--------------------------| | compile | Always requires explicit `--catalog-file` | | client | `{client-dir}/catalog.json` | | openapi | `{openapi-file-dir}/catalog.json` | | pipeline | Cascade: `{client-dir}` then `{openapi-dir}` then `{gateway-dir}` then `tmp/` | ## Common Workflows ### Choosing a Command | Goal | Command | Example | |------|---------|---------| | Everything | pipeline | `npx wsdl-tsc pipeline --wsdl-source svc.wsdl --client-dir ./client --openapi-file ./api.json --gateway-dir ./gw --gateway-service-name svc --gateway-version-prefix v1` | | TypeScript client only | client | `npx wsdl-tsc client --wsdl-source svc.wsdl --client-dir ./client` | | OpenAPI spec only | openapi | `npx wsdl-tsc openapi --wsdl-source svc.wsdl --openapi-file ./api.json` | | REST gateway only | gateway | `npx wsdl-tsc gateway --openapi-file ./api.json --client-dir ./client --gateway-dir ./gw --gateway-service-name svc --gateway-version-prefix v1` | | Runnable server | app | `npx wsdl-tsc app --client-dir ./client --gateway-dir ./gw --openapi-file ./api.json` | | Debug WSDL | compile | `npx wsdl-tsc compile --wsdl-source svc.wsdl --catalog-file ./catalog.json` | ### CI/CD Multi-Stage Build Compile once and reuse the catalog across multiple generation steps: ```bash npx wsdl-tsc compile \ --wsdl-source ./wsdl/Service.wsdl \ --catalog-file ./build/service-catalog.json ``` ```bash npx wsdl-tsc client \ --catalog-file ./build/service-catalog.json \ --client-dir ./src/services/service ``` ```bash npx wsdl-tsc openapi \ --catalog-file ./build/service-catalog.json \ --openapi-file ./docs/service-api.json ``` ### Debugging Complex WSDL Compile to catalog and inspect the intermediate representation: ```bash npx wsdl-tsc compile \ --wsdl-source ./wsdl/Complex.wsdl \ --catalog-file ./debug/catalog.json ``` Inspect types and operations with `jq`: ```bash cat ./debug/catalog.json | jq '.types' ``` ```bash cat ./debug/catalog.json | jq '.operations' ```