@techspokes/typescript-wsdl-client 0.18.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/app/generateApp.d.ts +1 -0
- package/dist/app/generateApp.d.ts.map +1 -1
- package/dist/app/generateApp.js +76 -9
- package/dist/cli.js +12 -2
- package/dist/gateway/helpers.js +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/openapi/casing.d.ts +0 -14
- package/dist/openapi/casing.d.ts.map +1 -1
- package/dist/openapi/casing.js +3 -3
- package/dist/openapi/generateOpenAPI.d.ts.map +1 -1
- package/dist/openapi/generateOpenAPI.js +3 -0
- package/dist/openapi/security.d.ts +1 -81
- package/dist/openapi/security.d.ts.map +1 -1
- package/dist/openapi/security.js +1 -146
- package/dist/pipeline.d.ts +1 -0
- package/dist/pipeline.d.ts.map +1 -1
- package/dist/pipeline.js +1 -0
- package/dist/test/generateTests.js +2 -2
- package/dist/util/builder.js +1 -1
- package/dist/util/runtimeSource.d.ts +1 -0
- package/dist/util/runtimeSource.d.ts.map +1 -1
- package/dist/util/runtimeSource.js +4 -0
- package/dist/util/securityConfig.d.ts +115 -0
- package/dist/util/securityConfig.d.ts.map +1 -0
- package/dist/util/securityConfig.js +274 -0
- package/dist/util/tools.d.ts +8 -0
- package/dist/util/tools.d.ts.map +1 -1
- package/dist/util/tools.js +16 -0
- package/docs/README.md +3 -2
- package/docs/api-reference.md +28 -4
- package/docs/architecture.md +1 -1
- package/docs/cli-reference.md +4 -1
- package/docs/configuration.md +33 -18
- package/docs/gateway-guide.md +8 -8
- package/docs/generated-code.md +7 -0
- package/docs/migration-playbook.md +14 -5
- package/docs/releases/README.md +42 -0
- package/docs/releases/v0.20.0.md +22 -0
- package/docs/troubleshooting.md +1 -1
- package/package.json +4 -4
- package/src/runtime/appSecurity.tpl.txt +108 -0
package/docs/configuration.md
CHANGED
|
@@ -8,28 +8,43 @@ See [CLI Reference](cli-reference.md) for flag details and [README](../README.md
|
|
|
8
8
|
|
|
9
9
|
Pass via `--openapi-security-config-file`.
|
|
10
10
|
|
|
11
|
-
Defines security
|
|
11
|
+
Defines REST gateway security, request headers, and upstream SOAP security. The `gateway` section describes the generated REST API in OpenAPI and adds Fastify header validation. The `upstream` section is used by the generated app scaffold to build `node-soap` runtime options from environment variables.
|
|
12
12
|
|
|
13
13
|
```json
|
|
14
14
|
{
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
15
|
+
"gateway": {
|
|
16
|
+
"global": {
|
|
17
|
+
"scheme": "bearer",
|
|
18
|
+
"bearer": { "bearerFormat": "JWT" },
|
|
19
|
+
"headers": [
|
|
20
|
+
{
|
|
21
|
+
"name": "X-Correlation-Id",
|
|
22
|
+
"required": false,
|
|
23
|
+
"schema": { "type": "string" }
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
"operations": {
|
|
28
|
+
"CancelBooking": { "scheme": "apiKey" },
|
|
29
|
+
"HealthCheck": { "scheme": "none" }
|
|
30
|
+
}
|
|
25
31
|
},
|
|
26
|
-
"
|
|
27
|
-
"
|
|
32
|
+
"upstream": {
|
|
33
|
+
"profile": "ws-security-username-token",
|
|
34
|
+
"usernameEnv": "SOAP_USERNAME",
|
|
35
|
+
"passwordEnv": "SOAP_PASSWORD",
|
|
36
|
+
"endpointEnv": "SOAP_ENDPOINT"
|
|
28
37
|
}
|
|
29
38
|
}
|
|
30
39
|
```
|
|
31
40
|
|
|
32
|
-
|
|
41
|
+
Gateway schemes: none, basic, bearer, apiKey, oauth2, mutualTLS, openIdConnect.
|
|
42
|
+
|
|
43
|
+
Upstream SOAP profiles: none, basic, bearer, ws-security-username-token, client-ssl, client-ssl-pfx, x509, ntlm, custom.
|
|
44
|
+
|
|
45
|
+
The older OpenAPI-only shape with top-level `global` and `overrides` is still accepted. New projects should use `gateway.global` and `gateway.operations`.
|
|
46
|
+
|
|
47
|
+
The generated app scaffold reads upstream secrets from environment variables. It does not embed secret values in generated source and does not implement production JWT, OAuth, or API-key verification for inbound gateway requests. Add that verification in app hooks or your platform gateway.
|
|
33
48
|
|
|
34
49
|
## Tags Configuration
|
|
35
50
|
|
|
@@ -107,8 +122,8 @@ terminal-error policy.
|
|
|
107
122
|
|
|
108
123
|
## Example Files
|
|
109
124
|
|
|
110
|
-
Example configuration files are available in the `examples/
|
|
125
|
+
Example configuration files are available in the `examples/config/` directory:
|
|
111
126
|
|
|
112
|
-
- `examples/
|
|
113
|
-
- `examples/
|
|
114
|
-
- `examples/
|
|
127
|
+
- `examples/config/security.json` for gateway and upstream security configuration
|
|
128
|
+
- `examples/config/tags.json` for tag mapping
|
|
129
|
+
- `examples/config/ops.json` for operation overrides
|
package/docs/gateway-guide.md
CHANGED
|
@@ -122,13 +122,13 @@ terminating zero-chunk.
|
|
|
122
122
|
|
|
123
123
|
The centralized error handler (runtime.ts) automatically classifies errors:
|
|
124
124
|
|
|
125
|
-
| Error Type
|
|
126
|
-
|
|
127
|
-
| Validation errors
|
|
128
|
-
| SOAP faults
|
|
129
|
-
| Connection refused | 503
|
|
130
|
-
| Timeout
|
|
131
|
-
| Other errors
|
|
125
|
+
| Error Type | HTTP Status | Error Code |
|
|
126
|
+
|--------------------|-------------|---------------------|
|
|
127
|
+
| Validation errors | 400 | VALIDATION_ERROR |
|
|
128
|
+
| SOAP faults | 502 | SOAP_FAULT |
|
|
129
|
+
| Connection refused | 503 | SERVICE_UNAVAILABLE |
|
|
130
|
+
| Timeout | 504 | GATEWAY_TIMEOUT |
|
|
131
|
+
| Other errors | 500 | INTERNAL_ERROR |
|
|
132
132
|
|
|
133
133
|
All errors are wrapped in the standard envelope format. See [Concepts](concepts.md) for the envelope structure.
|
|
134
134
|
|
|
@@ -186,7 +186,7 @@ await app.register(async (scope) => {
|
|
|
186
186
|
await app.listen({ port: 3000 });
|
|
187
187
|
```
|
|
188
188
|
|
|
189
|
-
See [`examples/fastify-gateway
|
|
189
|
+
See [`examples/fastify-gateway`](../examples/fastify-gateway/README.md) for a complete example.
|
|
190
190
|
|
|
191
191
|
## Contract Assumptions
|
|
192
192
|
|
package/docs/generated-code.md
CHANGED
|
@@ -18,6 +18,13 @@ const client = new Weather({
|
|
|
18
18
|
|
|
19
19
|
The `source` parameter accepts a URL or local file path to the WSDL.
|
|
20
20
|
|
|
21
|
+
When generating a runnable app with a security config, the scaffold can create
|
|
22
|
+
`security.ts` to build `soap.IOptions` and `soap.ISecurity` from environment
|
|
23
|
+
variables. The generated helper supports common `node-soap` profiles such as
|
|
24
|
+
Basic auth, bearer auth, WS-Security UsernameToken, TLS client certificates,
|
|
25
|
+
X509 signing, and NTLM. Secrets are read at runtime and are not embedded in
|
|
26
|
+
generated source.
|
|
27
|
+
|
|
21
28
|
## Calling Operations
|
|
22
29
|
|
|
23
30
|
```typescript
|
|
@@ -126,9 +126,16 @@ Create a security configuration file to add authentication to the OpenAPI spec a
|
|
|
126
126
|
|
|
127
127
|
```json
|
|
128
128
|
{
|
|
129
|
-
"
|
|
130
|
-
"
|
|
131
|
-
|
|
129
|
+
"gateway": {
|
|
130
|
+
"global": {
|
|
131
|
+
"scheme": "bearer",
|
|
132
|
+
"bearer": { "bearerFormat": "JWT" }
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
"upstream": {
|
|
136
|
+
"profile": "ws-security-username-token",
|
|
137
|
+
"usernameEnv": "SOAP_USERNAME",
|
|
138
|
+
"passwordEnv": "SOAP_PASSWORD"
|
|
132
139
|
}
|
|
133
140
|
}
|
|
134
141
|
```
|
|
@@ -142,11 +149,13 @@ npx wsdl-tsc pipeline \
|
|
|
142
149
|
...
|
|
143
150
|
```
|
|
144
151
|
|
|
145
|
-
See [Configuration](configuration.md) for all options including per-operation overrides and
|
|
152
|
+
See [Configuration](configuration.md) for all options including per-operation overrides, custom headers, and upstream SOAP security profiles.
|
|
146
153
|
|
|
147
154
|
### Custom middleware
|
|
148
155
|
|
|
149
|
-
Add middleware in your application code, not in the generated gateway files. The generated app scaffold (`
|
|
156
|
+
Add middleware in your application code, not in the generated gateway files. The generated app scaffold (`server.ts`) is the right place for auth verification, logging, CORS, and other cross-cutting concerns.
|
|
157
|
+
|
|
158
|
+
The security config describes gateway authentication in OpenAPI and can scaffold upstream SOAP credentials for `node-soap`. It does not validate JWTs, OAuth tokens, or API keys for inbound REST requests. Use Fastify hooks, platform middleware, or your API gateway for that enforcement.
|
|
150
159
|
|
|
151
160
|
```typescript
|
|
152
161
|
import Fastify from "fastify";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Release Notes
|
|
2
|
+
|
|
3
|
+
Add one Markdown file per release tag. The draft release workflow requires this file before it creates or updates a GitHub draft release.
|
|
4
|
+
|
|
5
|
+
## File Naming
|
|
6
|
+
|
|
7
|
+
Use the Git tag as the filename:
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
vX.Y.Z.md
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
For example, release `0.20.1` uses tag `v0.20.1` and release notes file `docs/releases/v0.20.1.md`.
|
|
14
|
+
|
|
15
|
+
## File Structure
|
|
16
|
+
|
|
17
|
+
Each release notes file must use this structure:
|
|
18
|
+
|
|
19
|
+
```markdown
|
|
20
|
+
# TypeScript WSDL Client vX.Y.Z
|
|
21
|
+
|
|
22
|
+
Short summary paragraph.
|
|
23
|
+
|
|
24
|
+
## Highlights
|
|
25
|
+
|
|
26
|
+
- User-facing release highlight.
|
|
27
|
+
|
|
28
|
+
## Upgrade Notes
|
|
29
|
+
|
|
30
|
+
No special upgrade steps.
|
|
31
|
+
|
|
32
|
+
## Validation
|
|
33
|
+
|
|
34
|
+
- `npm run maint:deps`
|
|
35
|
+
- `npm run ci`
|
|
36
|
+
|
|
37
|
+
## Notes
|
|
38
|
+
|
|
39
|
+
Release tag: `vX.Y.Z`.
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Write release notes for users and maintainers, not as a file-by-file change log. Use `CHANGELOG.md` for the canonical version history.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# TypeScript WSDL Client v0.20.0
|
|
2
|
+
|
|
3
|
+
This release refreshes dependency minimums and adds a tag-driven draft release workflow so each GitHub release starts from a reviewed release notes document.
|
|
4
|
+
|
|
5
|
+
## Highlights
|
|
6
|
+
|
|
7
|
+
- Bump root and generated app dependency minimums for `@types/node`, `soap`, and `tsx`.
|
|
8
|
+
- Add a `vX.Y.Z` tag workflow that validates the release state and creates or updates a GitHub draft release from `docs/releases/vX.Y.Z.md`.
|
|
9
|
+
- Require release notes in agent and contributor guidance so the changelog, package version, tag, and release description stay synchronized.
|
|
10
|
+
|
|
11
|
+
## Upgrade Notes
|
|
12
|
+
|
|
13
|
+
No special upgrade steps.
|
|
14
|
+
|
|
15
|
+
## Validation
|
|
16
|
+
|
|
17
|
+
- `npm run maint:deps`
|
|
18
|
+
- `npm run ci`
|
|
19
|
+
|
|
20
|
+
## Notes
|
|
21
|
+
|
|
22
|
+
Release tag: `v0.20.0`.
|
package/docs/troubleshooting.md
CHANGED
|
@@ -12,7 +12,7 @@ See [README](../README.md) for quick start and [CLI Reference](cli-reference.md)
|
|
|
12
12
|
| Unresolved type references | Re-run with --client-fail-on-unresolved=false to inspect partial graph |
|
|
13
13
|
| Missing schema in OpenAPI | Ensure the global element exists (catalog shows compiled symbols) |
|
|
14
14
|
| Wrong array modeling | Check maxOccurs in WSDL; tool only arrays when maxOccurs>1 or unbounded |
|
|
15
|
-
| Authentication errors | Provide proper soap.ISecurity instance
|
|
15
|
+
| Authentication errors | Provide proper upstream security config or `soap.ISecurity` instance |
|
|
16
16
|
| Date/time confusion | Use --client-date-as Date for runtime Date objects |
|
|
17
17
|
| TypeScript compilation errors | Check --import-extensions matches your tsconfig moduleResolution |
|
|
18
18
|
| Gateway validation failures | Ensure OpenAPI has valid $ref paths and all schemas in components.schemas |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@techspokes/typescript-wsdl-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "Turn legacy WSDL/SOAP services into typed TypeScript clients, OpenAPI 3.1 specs, and production-ready Fastify REST gateways. Built for enterprise SOAP modernization.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"wsdl",
|
|
@@ -83,12 +83,12 @@
|
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
85
|
"@types/js-yaml": "^4.0.9",
|
|
86
|
-
"@types/node": "^25.
|
|
86
|
+
"@types/node": "^25.9.0",
|
|
87
87
|
"@types/yargs": "^17.0.35",
|
|
88
88
|
"fastify": "^5.8.5",
|
|
89
89
|
"fastify-plugin": "^5.1.0",
|
|
90
90
|
"rimraf": "^6.1.3",
|
|
91
|
-
"tsx": "^4.
|
|
91
|
+
"tsx": "^4.22.2",
|
|
92
92
|
"typescript": "^6.0.3",
|
|
93
93
|
"vitest": "^4.1.6"
|
|
94
94
|
},
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"fast-xml-parser": "^5.8.0",
|
|
98
98
|
"js-yaml": "^4.1.1",
|
|
99
99
|
"saxes": "^6.0.0",
|
|
100
|
-
"soap": "^1.9.
|
|
100
|
+
"soap": "^1.9.2",
|
|
101
101
|
"yargs": "^18.0.0"
|
|
102
102
|
},
|
|
103
103
|
"funding": {
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Upstream SOAP Security
|
|
3
|
+
*
|
|
4
|
+
* Builds node-soap runtime options from environment variables referenced by
|
|
5
|
+
* the generation-time security config. Secrets are intentionally read at
|
|
6
|
+
* runtime and are never embedded in generated source.
|
|
7
|
+
*
|
|
8
|
+
* Scaffolded by wsdl-tsc. Customize freely.
|
|
9
|
+
*/
|
|
10
|
+
import fs from "node:fs";
|
|
11
|
+
import soap from "soap";
|
|
12
|
+
|
|
13
|
+
const upstream: any = __UPSTREAM_JSON__;
|
|
14
|
+
|
|
15
|
+
export interface SoapRuntimeConfig {
|
|
16
|
+
options?: soap.IOptions;
|
|
17
|
+
security?: soap.ISecurity;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function buildSoapRuntimeConfig(): SoapRuntimeConfig {
|
|
21
|
+
const options: soap.IOptions = {};
|
|
22
|
+
const wsdlHeaders = buildHeaders(upstream.wsdlHeaders, upstream.wsdlHeaderEnv);
|
|
23
|
+
if (Object.keys(wsdlHeaders).length) {
|
|
24
|
+
options.wsdl_headers = wsdlHeaders;
|
|
25
|
+
}
|
|
26
|
+
const requestHeaders = buildHeaders(upstream.requestHeaders, upstream.requestHeaderEnv);
|
|
27
|
+
if (Object.keys(requestHeaders).length) {
|
|
28
|
+
options.extraHeaders = requestHeaders;
|
|
29
|
+
}
|
|
30
|
+
if (upstream.endpointEnv) {
|
|
31
|
+
const endpoint = process.env[upstream.endpointEnv];
|
|
32
|
+
if (endpoint) options.endpoint = endpoint;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const security = buildSoapSecurity();
|
|
36
|
+
return {
|
|
37
|
+
...(Object.keys(options).length ? { options } : {}),
|
|
38
|
+
...(security ? { security } : {}),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function buildSoapSecurity(): soap.ISecurity | undefined {
|
|
43
|
+
const soapRuntime = soap as any;
|
|
44
|
+
switch (upstream.profile ?? "none") {
|
|
45
|
+
case "none":
|
|
46
|
+
return undefined;
|
|
47
|
+
case "basic":
|
|
48
|
+
return new soapRuntime.BasicAuthSecurity(requiredEnv(upstream.usernameEnv, "upstream.usernameEnv"), requiredEnv(upstream.passwordEnv, "upstream.passwordEnv"));
|
|
49
|
+
case "bearer":
|
|
50
|
+
return new soapRuntime.BearerSecurity(requiredEnv(upstream.tokenEnv, "upstream.tokenEnv"));
|
|
51
|
+
case "ws-security-username-token":
|
|
52
|
+
return new soapRuntime.WSSecurity(
|
|
53
|
+
requiredEnv(upstream.usernameEnv, "upstream.usernameEnv"),
|
|
54
|
+
requiredEnv(upstream.passwordEnv, "upstream.passwordEnv"),
|
|
55
|
+
upstream.wsSecurity ?? {},
|
|
56
|
+
);
|
|
57
|
+
case "ntlm":
|
|
58
|
+
return new soapRuntime.NTLMSecurity({
|
|
59
|
+
username: requiredEnv(upstream.usernameEnv, "upstream.usernameEnv"),
|
|
60
|
+
password: requiredEnv(upstream.passwordEnv, "upstream.passwordEnv"),
|
|
61
|
+
domain: envValue(upstream.domainEnv),
|
|
62
|
+
workstation: envValue(upstream.workstationEnv),
|
|
63
|
+
});
|
|
64
|
+
case "client-ssl":
|
|
65
|
+
return new soapRuntime.ClientSSLSecurity(
|
|
66
|
+
readFileFromEnv(upstream.keyFileEnv, "upstream.keyFileEnv"),
|
|
67
|
+
readFileFromEnv(upstream.certFileEnv, "upstream.certFileEnv"),
|
|
68
|
+
upstream.caFileEnv ? readFileFromEnv(upstream.caFileEnv, "upstream.caFileEnv") : undefined,
|
|
69
|
+
);
|
|
70
|
+
case "client-ssl-pfx":
|
|
71
|
+
return new soapRuntime.ClientSSLSecurityPFX(
|
|
72
|
+
readFileFromEnv(upstream.pfxFileEnv, "upstream.pfxFileEnv"),
|
|
73
|
+
envValue(upstream.passphraseEnv),
|
|
74
|
+
);
|
|
75
|
+
case "x509":
|
|
76
|
+
return new soapRuntime.WSSecurityCert(
|
|
77
|
+
readFileFromEnv(upstream.keyFileEnv, "upstream.keyFileEnv"),
|
|
78
|
+
readFileFromEnv(upstream.certFileEnv, "upstream.certFileEnv"),
|
|
79
|
+
envValue(upstream.passphraseEnv) ?? "",
|
|
80
|
+
);
|
|
81
|
+
case "custom":
|
|
82
|
+
throw new Error("upstream.profile=custom requires editing security.ts to return a soap.ISecurity implementation.");
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function buildHeaders(staticHeaders?: Record<string, string>, envHeaders?: Record<string, string>): Record<string, string> {
|
|
87
|
+
const headers: Record<string, string> = {...(staticHeaders ?? {})};
|
|
88
|
+
for (const [headerName, envName] of Object.entries(envHeaders ?? {})) {
|
|
89
|
+
const value = process.env[envName];
|
|
90
|
+
if (value) headers[headerName] = value;
|
|
91
|
+
}
|
|
92
|
+
return headers;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function requiredEnv(envName: string | undefined, label: string): string {
|
|
96
|
+
if (!envName) throw new Error(`${label} must name an environment variable.`);
|
|
97
|
+
const value = process.env[envName];
|
|
98
|
+
if (!value) throw new Error(`${envName} environment variable is required for upstream SOAP security.`);
|
|
99
|
+
return value;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function envValue(envName: string | undefined): string | undefined {
|
|
103
|
+
return envName ? process.env[envName] : undefined;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function readFileFromEnv(envName: string | undefined, label: string): Buffer {
|
|
107
|
+
return fs.readFileSync(requiredEnv(envName, label));
|
|
108
|
+
}
|