@techspokes/typescript-wsdl-client 0.2.0 → 0.2.2
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 +40 -9
- package/dist/cli.js +5 -0
- package/dist/compiler/schemaCompiler.d.ts +3 -0
- package/dist/compiler/schemaCompiler.d.ts.map +1 -1
- package/dist/compiler/schemaCompiler.js +77 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/emit/clientEmitter.d.ts.map +1 -1
- package/dist/emit/clientEmitter.js +17 -2
- package/dist/emit/runtimeEmitter.d.ts.map +1 -1
- package/dist/emit/runtimeEmitter.js +3 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ Reads WSDL/XSD (with imports) and emits a small, typed client you can compile in
|
|
|
23
23
|
* Deterministic metadata (`ATTR_SPEC`, `PROP_META`) for clean JSON ⇄ SOAP mapping
|
|
24
24
|
* ESM **and** CommonJS friendly output
|
|
25
25
|
|
|
26
|
-
Vendor: **[TechSpokes](https://www.techspokes.com)** · Contact: **[contact page](https://www.techspokes.com/contact/)
|
|
26
|
+
Vendor: **[TechSpokes](https://www.techspokes.com)** · Contact: **[contact page](https://www.techspokes.com/contact/)**
|
|
27
27
|
Maintainer: **Serge Liatko** ([@sergeliatko](https://github.com/sergeliatko)) · GitHub org: [@techspokes](https://github.com/techspokes)
|
|
28
28
|
|
|
29
29
|
---
|
|
@@ -33,7 +33,7 @@ Maintainer: **Serge Liatko** ([@sergeliatko](https://github.com/sergeliatko)) ·
|
|
|
33
33
|
Install the generator (dev-time) in your project:
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
|
-
npm i -D typescript-wsdl-client
|
|
36
|
+
npm i -D @techspokes/typescript-wsdl-client
|
|
37
37
|
# your app will use node-soap at runtime:
|
|
38
38
|
npm i soap
|
|
39
39
|
```
|
|
@@ -49,17 +49,28 @@ Use the generated client:
|
|
|
49
49
|
```ts
|
|
50
50
|
// ESM / NodeNext app
|
|
51
51
|
import { createSoapClient } from "./generated/my/runtime.js";
|
|
52
|
-
|
|
52
|
+
// class name defaults to <ServiceName>SoapClient (from WSDL), e.g., MyServiceSoapClient
|
|
53
|
+
import { MyServiceSoapClient } from "./generated/my/client.js";
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
// optional: pass security straight into createSoapClient (node-soap security instance)
|
|
56
|
+
import soap from "soap";
|
|
57
|
+
const security = new soap.WSSecurity("user", "pass");
|
|
56
58
|
|
|
59
|
+
const soapClient = await createSoapClient({
|
|
60
|
+
wsdlUrl: "https://example.com/MyService?wsdl",
|
|
61
|
+
security, // or configure after creation: (await createSoapClient(...)).setSecurity(security)
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const client = new MyServiceSoapClient(soapClient, "$attributes"); // attributes key optional
|
|
65
|
+
|
|
66
|
+
// Example: To set literal text content for an XML element, use the reserved `$value` key.
|
|
67
|
+
// Other keys in the object represent XML attributes (e.g. `MyAttribute`) and child elements (e.g. `MyElement`).
|
|
68
|
+
// This lets you build mixed-content XML: `$value` for text, attribute keys for XML attributes, and element keys for nested elements.
|
|
57
69
|
const rs = await client.MyOperation({
|
|
58
70
|
MyOperationRQ: {
|
|
59
71
|
MyAttribute: "passed as attribute",
|
|
60
72
|
MyElement: "passed as child element",
|
|
61
|
-
|
|
62
|
-
// attributes appear as top-level props; child elements as nested objects
|
|
73
|
+
$value: "passed text content here",
|
|
63
74
|
}
|
|
64
75
|
});
|
|
65
76
|
|
|
@@ -70,6 +81,17 @@ console.log(rs);
|
|
|
70
81
|
|
|
71
82
|
---
|
|
72
83
|
|
|
84
|
+
## Security and WS-Policy hints
|
|
85
|
+
|
|
86
|
+
- node-soap leaves security up to you. Create a security instance (e.g., `new soap.BasicAuthSecurity(...)`, `new soap.WSSecurity(...)`, `new soap.ClientSSLSecurity(...)`) and set it on the client via `client.setSecurity(...)`.
|
|
87
|
+
- The runtime factory `createSoapClient({ wsdlUrl, endpoint?, wsdlOptions?, security? })` accepts an optional `security` and will call `client.setSecurity(security)` for you.
|
|
88
|
+
- The generated client includes minimal WS-Policy hints if your WSDL embeds inline `wsp:Policy` under `wsdl:binding` or `wsdl:binding/wsdl:operation`.
|
|
89
|
+
- Hints are surfaced in method JSDoc as “Security (WSDL policy hint): …” and in `operations.json`/`operations.ts` as a `security: string[]` field (e.g., `usernameToken`, `https`, `x509`, `messageSecurity`).
|
|
90
|
+
- These hints are best-effort and not authoritative (no `wsp:PolicyReference` dereferencing yet). They’re intended to nudge you to configure the right security.
|
|
91
|
+
- At runtime, if an operation has hints and your client has no `security` configured, a console warning is emitted.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
73
95
|
## CLI
|
|
74
96
|
|
|
75
97
|
```
|
|
@@ -107,11 +129,19 @@ wsdl-tsc --wsdl <path-or-url> --out <dir> [options]
|
|
|
107
129
|
| `--imports` | string | js, ts, bare | js | Intra-generated import specifiers: '.js', '.ts', or bare |
|
|
108
130
|
| `--ops-ts` | boolean | true, false | true | Emit `operations.ts` instead of JSON |
|
|
109
131
|
| `--attributes-key` | string | any | $attributes | Key used by runtime marshaller for XML attributes |
|
|
132
|
+
| `--client-name` | string | any | — | Override the exported client class name (exact) |
|
|
110
133
|
| `--int64-as` | string | string, number, bigint | string | How to map xs:long/xs:unsignedLong |
|
|
111
134
|
| `--bigint-as` | string | string, number | string | How to map xs:integer family (positive/nonNegative/etc.) |
|
|
112
135
|
| `--decimal-as` | string | string, number | string | How to map xs:decimal (money/precision) |
|
|
113
136
|
| `--date-as` | string | string, Date | string | How to map date/time/duration types |
|
|
114
137
|
|
|
138
|
+
### Client naming
|
|
139
|
+
|
|
140
|
+
- By default, the generated client class is named after the WSDL service: `<ServiceName>SoapClient`.
|
|
141
|
+
- If the service name can’t be determined, we fall back to the WSDL filename: `<WsdlFileBaseName>SoapClient`.
|
|
142
|
+
- If neither is available, we fall back to `GeneratedSoapClient`.
|
|
143
|
+
- You can override the name entirely with `--client-name MyCustomClient` (the exact export name will be used).
|
|
144
|
+
|
|
115
145
|
**Primitive mapping (safe defaults)**
|
|
116
146
|
|
|
117
147
|
Defaults are **string-first** to avoid precision & timezone surprises:
|
|
@@ -195,8 +225,8 @@ TypeScript will compile to `require("./runtime")` cleanly.
|
|
|
195
225
|
## Programmatic API (optional)
|
|
196
226
|
|
|
197
227
|
```ts
|
|
198
|
-
import { compileCatalog, xsdToTsPrimitive, type CompilerOptions } from "typescript-wsdl-client";
|
|
199
|
-
import { loadWsdlCatalog } from "typescript-wsdl-client/internal-or-your-loader"; // if you expose it
|
|
228
|
+
import { compileCatalog, xsdToTsPrimitive, type CompilerOptions } from "@techspokes/typescript-wsdl-client";
|
|
229
|
+
import { loadWsdlCatalog } from "@techspokes/typescript-wsdl-client/internal-or-your-loader"; // if you expose it
|
|
200
230
|
|
|
201
231
|
const catalog = await loadWsdlCatalog("./spec/wsdl/MyService.wsdl");
|
|
202
232
|
const compiled = compileCatalog(catalog, {
|
|
@@ -237,6 +267,7 @@ npx tsc --noEmit --module NodeNext --moduleResolution NodeNext --target ES2022 .
|
|
|
237
267
|
* **“Cannot find './runtime.js'”** — Your app must be `module: "NodeNext"` when using `--imports js`.
|
|
238
268
|
Use `--imports bare` for CommonJS apps.
|
|
239
269
|
* **“node-soap not found”** — Install it in your **app**: `npm i soap`.
|
|
270
|
+
* **“Security required?”** — If your generated client warns or JSDoc shows a security hint, configure node-soap security: `client.setSecurity(new soap.WSSecurity(...))` or pass `security` to `createSoapClient`.
|
|
240
271
|
|
|
241
272
|
---
|
|
242
273
|
|
package/dist/cli.js
CHANGED
|
@@ -37,6 +37,10 @@ const argv = await yargs(hideBin(process.argv))
|
|
|
37
37
|
type: "string",
|
|
38
38
|
default: "$attributes",
|
|
39
39
|
desc: "Key used by runtime marshaller for XML attributes",
|
|
40
|
+
})
|
|
41
|
+
.option("client-name", {
|
|
42
|
+
type: "string",
|
|
43
|
+
desc: "Override the generated client class name (exact export name)",
|
|
40
44
|
})
|
|
41
45
|
// Primitive mapping knobs (safe defaults)
|
|
42
46
|
.option("int64-as", {
|
|
@@ -94,5 +98,6 @@ emitClient(path.join(outDir, "client.ts"), compiled, {
|
|
|
94
98
|
// @ts-ignore runtime-only options for emitter
|
|
95
99
|
importExt,
|
|
96
100
|
attributesKey: String(argv["attributes-key"]),
|
|
101
|
+
clientName: argv["client-name"],
|
|
97
102
|
});
|
|
98
103
|
console.log(`✅ Generated TypeScript client in ${outDir}`);
|
|
@@ -43,8 +43,11 @@ export type CompiledCatalog = {
|
|
|
43
43
|
soapAction: string;
|
|
44
44
|
inputElement?: QName;
|
|
45
45
|
outputElement?: QName;
|
|
46
|
+
security?: string[];
|
|
46
47
|
}>;
|
|
47
48
|
wsdlTargetNS: string;
|
|
49
|
+
serviceName?: string;
|
|
50
|
+
wsdlUri: string;
|
|
48
51
|
};
|
|
49
52
|
/**
|
|
50
53
|
* Compile a WSDL catalog into an internal representation (CompiledCatalog).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemaCompiler.d.ts","sourceRoot":"","sources":["../../src/compiler/schemaCompiler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAU3D,MAAM,MAAM,KAAK,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAElD,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,KAAK,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;QAC9B,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IACH,KAAK,EAAE,KAAK,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC;QAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,IAAI,EAAE;QACJ,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACnC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QAClD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;KAC/C,CAAC;IACF,UAAU,EAAE,KAAK,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,CAAC,EAAE,KAAK,CAAC;QACrB,aAAa,CAAC,EAAE,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"schemaCompiler.d.ts","sourceRoot":"","sources":["../../src/compiler/schemaCompiler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAU3D,MAAM,MAAM,KAAK,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAElD,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,KAAK,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;QAC9B,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IACH,KAAK,EAAE,KAAK,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC;QAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,IAAI,EAAE;QACJ,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACnC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QAClD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;KAC/C,CAAC;IACF,UAAU,EAAE,KAAK,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,CAAC,EAAE,KAAK,CAAC;QACrB,aAAa,CAAC,EAAE,KAAK,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC,CAAC;IACH,YAAY,EAAE,MAAM,CAAC;IAErB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AA6DF;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,eAAe,GAAG,eAAe,CA2gBxF"}
|
|
@@ -13,6 +13,56 @@ function makeInlineTypeName(parentTypeName, propName, _max) {
|
|
|
13
13
|
}
|
|
14
14
|
return `${base}Anon`;
|
|
15
15
|
}
|
|
16
|
+
// --- Minimal WS-Policy scanning (inline policies only; PolicyReference not resolved) ---
|
|
17
|
+
function collectSecurityFromPolicyNodes(policyNodes) {
|
|
18
|
+
const found = new Set();
|
|
19
|
+
const targets = new Set([
|
|
20
|
+
"UsernameToken",
|
|
21
|
+
"TransportBinding",
|
|
22
|
+
"HttpsToken",
|
|
23
|
+
"TransportToken",
|
|
24
|
+
"AsymmetricBinding",
|
|
25
|
+
"SymmetricBinding",
|
|
26
|
+
"SignedSupportingTokens",
|
|
27
|
+
"X509Token",
|
|
28
|
+
]);
|
|
29
|
+
const visit = (n) => {
|
|
30
|
+
if (n == null || typeof n !== "object")
|
|
31
|
+
return;
|
|
32
|
+
for (const [k, v] of Object.entries(n)) {
|
|
33
|
+
if (k.startsWith("@_"))
|
|
34
|
+
continue; // attribute
|
|
35
|
+
// localName match (prefix-agnostic) by checking tail after ':' or whole key if no ':'
|
|
36
|
+
const ln = k.includes(":") ? k.split(":").pop() : k;
|
|
37
|
+
if (targets.has(ln)) {
|
|
38
|
+
switch (ln) {
|
|
39
|
+
case "UsernameToken":
|
|
40
|
+
found.add("usernameToken");
|
|
41
|
+
break;
|
|
42
|
+
case "HttpsToken":
|
|
43
|
+
case "TransportBinding":
|
|
44
|
+
case "TransportToken":
|
|
45
|
+
found.add("https");
|
|
46
|
+
break;
|
|
47
|
+
case "X509Token":
|
|
48
|
+
found.add("x509");
|
|
49
|
+
break;
|
|
50
|
+
case "AsymmetricBinding":
|
|
51
|
+
case "SymmetricBinding":
|
|
52
|
+
case "SignedSupportingTokens":
|
|
53
|
+
found.add("messageSecurity");
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// recurse
|
|
58
|
+
if (v && typeof v === "object")
|
|
59
|
+
visit(v);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
for (const p of policyNodes)
|
|
63
|
+
visit(p);
|
|
64
|
+
return Array.from(found);
|
|
65
|
+
}
|
|
16
66
|
/**
|
|
17
67
|
* Compile a WSDL catalog into an internal representation (CompiledCatalog).
|
|
18
68
|
* Steps:
|
|
@@ -469,11 +519,38 @@ export function compileCatalog(cat, _opts) {
|
|
|
469
519
|
return { name, soapAction: bOps.get(name) || "", inputElement, outputElement };
|
|
470
520
|
})
|
|
471
521
|
.filter((x) => x != null));
|
|
522
|
+
// --- WS-Policy: scan for security requirements (inline policies only) ---
|
|
523
|
+
const bindingPolicies = getChildrenWithLocalName(soapBinding || {}, "Policy");
|
|
524
|
+
const bindingSec = collectSecurityFromPolicyNodes(bindingPolicies);
|
|
525
|
+
for (const op of ops) {
|
|
526
|
+
const bo = opsNodes.find(o => o?.["@_name"] === op.name) || {};
|
|
527
|
+
const opPolicies = getChildrenWithLocalName(bo, "Policy");
|
|
528
|
+
const opSec = collectSecurityFromPolicyNodes(opPolicies);
|
|
529
|
+
const secSet = new Set([...bindingSec, ...opSec]);
|
|
530
|
+
op.security = Array.from(secSet);
|
|
531
|
+
}
|
|
532
|
+
// --- Service discovery (for client naming) ---
|
|
533
|
+
let serviceName;
|
|
534
|
+
const soapBindingName = soapBinding?.["@_name"];
|
|
535
|
+
const serviceDefs = normalizeArray(defs?.["wsdl:service"] || defs?.["service"]);
|
|
536
|
+
const serviceUsingBinding = serviceDefs.find(s => {
|
|
537
|
+
const ports = getChildrenWithLocalName(s, "port");
|
|
538
|
+
return ports.some(p => {
|
|
539
|
+
const bq = p?.["@_binding"];
|
|
540
|
+
if (!bq || !soapBindingName)
|
|
541
|
+
return false;
|
|
542
|
+
const q = resolveQName(bq, tns, cat.prefixMap);
|
|
543
|
+
return q.local === soapBindingName; // match by local name
|
|
544
|
+
});
|
|
545
|
+
});
|
|
546
|
+
serviceName = serviceUsingBinding?.["@_name"] || serviceDefs[0]?.["@_name"];
|
|
472
547
|
return {
|
|
473
548
|
types: typesList,
|
|
474
549
|
aliases: aliasList,
|
|
475
550
|
meta: { attrSpec, childType, propMeta },
|
|
476
551
|
operations: ops,
|
|
477
552
|
wsdlTargetNS: defs?.["@_targetNamespace"] || "",
|
|
553
|
+
serviceName,
|
|
554
|
+
wsdlUri: cat.wsdlUri,
|
|
478
555
|
};
|
|
479
556
|
}
|
package/dist/config.d.ts
CHANGED
|
@@ -23,6 +23,11 @@ export type CompilerOptions = {
|
|
|
23
23
|
* Attribute bag key for the runtime mapper (node-soap).
|
|
24
24
|
*/
|
|
25
25
|
attributesKey?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Optional override for the generated client class name.
|
|
28
|
+
* If provided, the emitter will export this exact class name.
|
|
29
|
+
*/
|
|
30
|
+
clientName?: string;
|
|
26
31
|
/**
|
|
27
32
|
* Controls low-level mapping of XSD primitives to TypeScript types. Safe defaults are provided.
|
|
28
33
|
*/
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC1B;;OAEG;IACH,MAAM,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC;IAClC;;OAEG;IACH,MAAM,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC3B;;OAEG;IACH,KAAK,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC5B;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAChC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,eAM5B,CAAC"}
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC1B;;OAEG;IACH,MAAM,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC;IAClC;;OAEG;IACH,MAAM,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC3B;;OAEG;IACH,KAAK,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC5B;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAChC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,eAM5B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clientEmitter.d.ts","sourceRoot":"","sources":["../../src/emit/clientEmitter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGpD,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,eAAe,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"clientEmitter.d.ts","sourceRoot":"","sources":["../../src/emit/clientEmitter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGpD,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,eAAe,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,QAkDpH"}
|
|
@@ -7,7 +7,18 @@ export function emitClient(outFile, compiled, opts) {
|
|
|
7
7
|
lines.push(`import { ATTR_SPEC, CHILD_TYPE, PROP_META } from "./meta${ext}";`);
|
|
8
8
|
lines.push(`import type * as T from "./types${ext}";`);
|
|
9
9
|
lines.push("");
|
|
10
|
-
|
|
10
|
+
// Derive class name: prefer explicit override, else WSDL service name, else base filename, else default
|
|
11
|
+
const overrideName = (opts.clientName || "").trim();
|
|
12
|
+
const svcName = compiled.serviceName && pascal(compiled.serviceName);
|
|
13
|
+
const fileBase = (() => {
|
|
14
|
+
const uri = compiled.wsdlUri || "";
|
|
15
|
+
// extract last path segment and strip extension for both URL and file path
|
|
16
|
+
const seg = uri.split(/[\\/]/).pop() || "";
|
|
17
|
+
const noExt = seg.replace(/\.[^.]+$/, "");
|
|
18
|
+
return noExt ? pascal(noExt) : "";
|
|
19
|
+
})();
|
|
20
|
+
const className = overrideName || ((svcName || fileBase) ? `${svcName || fileBase}SoapClient` : "GeneratedSoapClient");
|
|
21
|
+
lines.push(`export class ${className} {`);
|
|
11
22
|
lines.push(` constructor(private source: string | any, private attributesKey: string = "${opts.attributesKey || "$attributes"}") {}`);
|
|
12
23
|
lines.push(` async _client() {`);
|
|
13
24
|
lines.push(` if (typeof this.source === 'string') return createSoapClient({ wsdlUrl: this.source });`);
|
|
@@ -21,9 +32,13 @@ export function emitClient(outFile, compiled, opts) {
|
|
|
21
32
|
const outTs = outTypeName ? `T.${outTypeName}` : `any`;
|
|
22
33
|
const inMetaKey = inTypeName ?? m;
|
|
23
34
|
const outMetaKey = outTypeName ?? m;
|
|
24
|
-
|
|
35
|
+
const secHints = Array.isArray(op.security) && op.security.length ? op.security : [];
|
|
36
|
+
lines.push(` /** SOAPAction: ${op.soapAction}${secHints.length ? `\n * Security (WSDL policy hint): ${secHints.join(", ")}` : ""} */`);
|
|
25
37
|
lines.push(` async ${m}(args: ${inTs}): Promise<${outTs}> {`);
|
|
26
38
|
lines.push(` const c: any = await this._client();`);
|
|
39
|
+
if (secHints.length) {
|
|
40
|
+
lines.push(` if (!c || !c.security) { console.warn("[wsdl-client] Operation '${m}' may require security: ${secHints.join(", ")}. Configure client.setSecurity(...) or pass { security } to createSoapClient()."); }`);
|
|
41
|
+
}
|
|
27
42
|
lines.push(` const meta = { ATTR_SPEC, CHILD_TYPE, PROP_META } as const;`);
|
|
28
43
|
lines.push(` const soapArgs = toSoapArgs(args as any, "${inMetaKey}", meta, this.attributesKey);`);
|
|
29
44
|
lines.push(` return new Promise((resolve, reject) => {`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtimeEmitter.d.ts","sourceRoot":"","sources":["../../src/emit/runtimeEmitter.ts"],"names":[],"mappings":"AAGA,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"runtimeEmitter.d.ts","sourceRoot":"","sources":["../../src/emit/runtimeEmitter.ts"],"names":[],"mappings":"AAGA,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,QAoF1C"}
|
|
@@ -9,6 +9,7 @@ export type CreateSoapClientOptions = {
|
|
|
9
9
|
endpoint?: string;
|
|
10
10
|
wsdlOptions?: Record<string, any>;
|
|
11
11
|
requestOptions?: Record<string, any>;
|
|
12
|
+
security?: any; // pass an instance of a node-soap security class, e.g., new soap.WSSecurity("user","pass")
|
|
12
13
|
}
|
|
13
14
|
export type AttrSpec = Record<string, readonly string[]>;
|
|
14
15
|
export type ChildType = Record<string, Readonly<Record<string, string>>>;
|
|
@@ -17,12 +18,8 @@ export type PropMeta = Record<string, Readonly<Record<string, any>>>;
|
|
|
17
18
|
export async function createSoapClient(opts: CreateSoapClientOptions): Promise<any> {
|
|
18
19
|
const client = await soap.createClientAsync(opts.wsdlUrl, opts.wsdlOptions || {});
|
|
19
20
|
if (opts.endpoint) client.setEndpoint(opts.endpoint);
|
|
20
|
-
if (opts.
|
|
21
|
-
|
|
22
|
-
if (client.setSecurity && req) {
|
|
23
|
-
// security is caller's responsibility (if needed)
|
|
24
|
-
}
|
|
25
|
-
}
|
|
21
|
+
if (opts.security) client.setSecurity(opts.security);
|
|
22
|
+
// security and any request-specific configuration are the caller's responsibility
|
|
26
23
|
return client;
|
|
27
24
|
}
|
|
28
25
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@techspokes/typescript-wsdl-client",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "TypeScript WSDL → SOAP client generator with full xs:attribute support, complex types, sequences, inheritance, and namespace-collision merging.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"wsdl",
|