@techspokes/typescript-wsdl-client 0.1.8 → 0.2.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 +36 -20
- package/dist/cli.js +4 -0
- package/dist/compiler/schemaCompiler.d.ts +10 -0
- package/dist/compiler/schemaCompiler.d.ts.map +1 -1
- package/dist/compiler/schemaCompiler.js +188 -81
- package/dist/config.d.ts +24 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -0
- package/dist/emit/clientEmitter.d.ts.map +1 -1
- package/dist/emit/clientEmitter.js +10 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40 -29
- package/package.json +2 -2
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
|
|
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
|
---
|
|
@@ -76,37 +76,53 @@ console.log(rs);
|
|
|
76
76
|
wsdl-tsc --wsdl <path-or-url> --out <dir> [options]
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
+
### Local development
|
|
80
|
+
|
|
81
|
+
By default, `npx wsdl-tsc` invokes the published npm version. To run the CLI from your local source (with your latest changes), use one of these approaches:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Directly via tsx (requires tsx in devDependencies)
|
|
85
|
+
npx tsx src/cli.ts --wsdl <path-or-url> --out <dir> [options]
|
|
86
|
+
|
|
87
|
+
# Via npm script
|
|
88
|
+
git clone ... then:
|
|
89
|
+
npm install
|
|
90
|
+
git checkout <branch>
|
|
91
|
+
npm run dev -- --wsdl <path-or-url> --out <dir> [options]
|
|
92
|
+
|
|
93
|
+
# Using npm link to symlink your working copy
|
|
94
|
+
npm link
|
|
95
|
+
wsdl-tsc --wsdl <path-or-url> --out <dir> [options]
|
|
96
|
+
```
|
|
97
|
+
|
|
79
98
|
**Required**
|
|
80
99
|
|
|
81
100
|
* `--wsdl` — WSDL path or URL
|
|
82
101
|
* `--out` — output directory (created if missing)
|
|
83
102
|
|
|
84
|
-
**
|
|
103
|
+
**Options**
|
|
85
104
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
105
|
+
| Flag | Type | Choices | Default | Description |
|
|
106
|
+
|---------------------|-----------|--------------------------------|--------------|------------------------------------------------------------------|
|
|
107
|
+
| `--imports` | string | js, ts, bare | js | Intra-generated import specifiers: '.js', '.ts', or bare |
|
|
108
|
+
| `--ops-ts` | boolean | true, false | true | Emit `operations.ts` instead of JSON |
|
|
109
|
+
| `--attributes-key` | string | any | $attributes | Key used by runtime marshaller for XML attributes |
|
|
110
|
+
| `--int64-as` | string | string, number, bigint | string | How to map xs:long/xs:unsignedLong |
|
|
111
|
+
| `--bigint-as` | string | string, number | string | How to map xs:integer family (positive/nonNegative/etc.) |
|
|
112
|
+
| `--decimal-as` | string | string, number | string | How to map xs:decimal (money/precision) |
|
|
113
|
+
| `--date-as` | string | string, Date | string | How to map date/time/duration types |
|
|
94
114
|
|
|
95
115
|
**Primitive mapping (safe defaults)**
|
|
96
116
|
|
|
97
|
-
|
|
98
|
-
* `--bigint-as string|number` (default `string`) — `xs:integer` family
|
|
99
|
-
* `--decimal-as string|number` (default `string`) — `xs:decimal` (money/precision)
|
|
100
|
-
* `--date-as string|Date` (default `string`) — `xs:date`, `xs:dateTime`, `xs:time`, `g*`, durations
|
|
101
|
-
|
|
102
|
-
**Other**
|
|
117
|
+
Defaults are **string-first** to avoid precision & timezone surprises:
|
|
103
118
|
|
|
104
|
-
*
|
|
105
|
-
|
|
119
|
+
* `xs:decimal` → `string` (money/precision safe)
|
|
120
|
+
* 64-bit integers → `string` (you can opt into `bigint` or `number`)
|
|
121
|
+
* dates/times → `string` (transport-friendly, no implicit tz conversion)
|
|
106
122
|
|
|
107
|
-
|
|
123
|
+
Override these defaults using the CLI flags above as needed for your use case.
|
|
108
124
|
|
|
109
|
-
|
|
125
|
+
# What gets generated
|
|
110
126
|
|
|
111
127
|
```
|
|
112
128
|
<out>/
|
package/dist/cli.js
CHANGED
|
@@ -78,6 +78,10 @@ const compiled = compileCatalog(catalog, {
|
|
|
78
78
|
dateAs: argv["date-as"],
|
|
79
79
|
},
|
|
80
80
|
});
|
|
81
|
+
// Report counts of types and operations for user visibility
|
|
82
|
+
console.log(`Schemas discovered: ${catalog.schemas.length}`);
|
|
83
|
+
console.log(`Compiled types: ${compiled.types.length}`);
|
|
84
|
+
console.log(`Operations: ${compiled.operations.length}`);
|
|
81
85
|
// Emit files
|
|
82
86
|
const importExt = argv.imports === "js" ? ".js" : argv.imports === "ts" ? ".ts" : "";
|
|
83
87
|
emitTypes(path.join(outDir, "types.ts"), compiled);
|
|
@@ -46,5 +46,15 @@ export type CompiledCatalog = {
|
|
|
46
46
|
}>;
|
|
47
47
|
wsdlTargetNS: string;
|
|
48
48
|
};
|
|
49
|
+
/**
|
|
50
|
+
* Compile a WSDL catalog into an internal representation (CompiledCatalog).
|
|
51
|
+
* Steps:
|
|
52
|
+
* 1. Collect and index complexType, simpleType, and element definitions across all schemas.
|
|
53
|
+
* 2. Recursively compile each named type to a TS interface or alias, handling inheritance,
|
|
54
|
+
* inline definitions, and XSD primitives.
|
|
55
|
+
* 3. Build metadata maps for runtime marshalling (attributes, children, nillable, occurrence).
|
|
56
|
+
* 4. Extract WSDL operations: pick the appropriate SOAP binding (v1.1 or v1.2), resolve its
|
|
57
|
+
* portType reference, then enumerate operations and their soapAction URIs.
|
|
58
|
+
*/
|
|
49
59
|
export declare function compileCatalog(cat: WsdlCatalog, _opts: CompilerOptions): CompiledCatalog;
|
|
50
60
|
//# sourceMappingURL=schemaCompiler.d.ts.map
|
|
@@ -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;KACvB,CAAC,CAAC;IACH,YAAY,EAAE,MAAM,CAAC;CACtB,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;KACvB,CAAC,CAAC;IACH,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAsBF;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,eAAe,GAAG,eAAe,CA+exF"}
|
|
@@ -8,10 +8,21 @@ function qkey(q) {
|
|
|
8
8
|
function makeInlineTypeName(parentTypeName, propName, _max) {
|
|
9
9
|
const base = pascal(parentTypeName || "AnonParent");
|
|
10
10
|
const prop = pascal(propName || "");
|
|
11
|
-
if (prop)
|
|
11
|
+
if (prop) {
|
|
12
12
|
return prop;
|
|
13
|
+
}
|
|
13
14
|
return `${base}Anon`;
|
|
14
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Compile a WSDL catalog into an internal representation (CompiledCatalog).
|
|
18
|
+
* Steps:
|
|
19
|
+
* 1. Collect and index complexType, simpleType, and element definitions across all schemas.
|
|
20
|
+
* 2. Recursively compile each named type to a TS interface or alias, handling inheritance,
|
|
21
|
+
* inline definitions, and XSD primitives.
|
|
22
|
+
* 3. Build metadata maps for runtime marshalling (attributes, children, nillable, occurrence).
|
|
23
|
+
* 4. Extract WSDL operations: pick the appropriate SOAP binding (v1.1 or v1.2), resolve its
|
|
24
|
+
* portType reference, then enumerate operations and their soapAction URIs.
|
|
25
|
+
*/
|
|
15
26
|
export function compileCatalog(cat, _opts) {
|
|
16
27
|
// symbol tables discovered across all schemas
|
|
17
28
|
const complexTypes = new Map();
|
|
@@ -19,20 +30,25 @@ export function compileCatalog(cat, _opts) {
|
|
|
19
30
|
const elements = new Map();
|
|
20
31
|
for (const s of cat.schemas) {
|
|
21
32
|
const tns = s.targetNS;
|
|
33
|
+
// merge WSDL-level prefixes with schema-level (schema wins)
|
|
34
|
+
const mergedPrefixes = { ...cat.prefixMap, ...s.prefixes };
|
|
22
35
|
for (const n of getChildrenWithLocalName(s.xml, "complexType")) {
|
|
23
36
|
const name = n["@_name"];
|
|
24
|
-
if (name)
|
|
25
|
-
complexTypes.set(qkey({ ns: tns, local: name }), { node: n, tns, prefixes:
|
|
37
|
+
if (name) {
|
|
38
|
+
complexTypes.set(qkey({ ns: tns, local: name }), { node: n, tns, prefixes: mergedPrefixes });
|
|
39
|
+
}
|
|
26
40
|
}
|
|
27
41
|
for (const n of getChildrenWithLocalName(s.xml, "simpleType")) {
|
|
28
42
|
const name = n["@_name"];
|
|
29
|
-
if (name)
|
|
30
|
-
simpleTypes.set(qkey({ ns: tns, local: name }), { node: n, tns, prefixes:
|
|
43
|
+
if (name) {
|
|
44
|
+
simpleTypes.set(qkey({ ns: tns, local: name }), { node: n, tns, prefixes: mergedPrefixes });
|
|
45
|
+
}
|
|
31
46
|
}
|
|
32
47
|
for (const n of getChildrenWithLocalName(s.xml, "element")) {
|
|
33
48
|
const name = n["@_name"];
|
|
34
|
-
if (name)
|
|
35
|
-
elements.set(qkey({ ns: tns, local: name }), { node: n, tns, prefixes:
|
|
49
|
+
if (name) {
|
|
50
|
+
elements.set(qkey({ ns: tns, local: name }), { node: n, tns, prefixes: mergedPrefixes });
|
|
51
|
+
}
|
|
36
52
|
}
|
|
37
53
|
}
|
|
38
54
|
// outputs & state
|
|
@@ -72,8 +88,9 @@ export function compileCatalog(cat, _opts) {
|
|
|
72
88
|
function getOrCompileAlias(name, sNode, schemaNS, prefixes) {
|
|
73
89
|
const key = `${schemaNS}|${name}`;
|
|
74
90
|
const present = aliasMap.get(key);
|
|
75
|
-
if (present)
|
|
91
|
+
if (present) {
|
|
76
92
|
return present;
|
|
93
|
+
}
|
|
77
94
|
const { tsType, declared, jsdoc } = compileSimpleTypeNode(sNode, schemaNS, prefixes);
|
|
78
95
|
const alias = { name: pascal(name), ns: schemaNS, tsType, declared, jsdoc };
|
|
79
96
|
aliasMap.set(key, alias);
|
|
@@ -81,8 +98,9 @@ export function compileCatalog(cat, _opts) {
|
|
|
81
98
|
}
|
|
82
99
|
/** Resolve a QName reference to a TS type; compile targets if needed. */
|
|
83
100
|
function resolveTypeRef(q, schemaNS, prefixes) {
|
|
84
|
-
if (!q.ns)
|
|
101
|
+
if (!q.ns) {
|
|
85
102
|
q = resolveQName(q.local, schemaNS, prefixes);
|
|
103
|
+
}
|
|
86
104
|
if (q.ns === XS) {
|
|
87
105
|
const label = `xs:${q.local}`;
|
|
88
106
|
return { tsType: xsdToTsPrimitive(label, _opts?.primitive), declared: label };
|
|
@@ -109,16 +127,20 @@ export function compileCatalog(cat, _opts) {
|
|
|
109
127
|
const outName = pascal(name);
|
|
110
128
|
const key = `${schemaNS}|${outName}`;
|
|
111
129
|
const present = compiledMap.get(key);
|
|
112
|
-
if (present)
|
|
130
|
+
if (present) {
|
|
113
131
|
return present;
|
|
132
|
+
}
|
|
114
133
|
if (inProgress.has(key)) {
|
|
115
134
|
// minimal cycle break
|
|
116
135
|
return { name: outName, ns: schemaNS, attrs: [], elems: [] };
|
|
117
136
|
}
|
|
118
137
|
inProgress.add(key);
|
|
138
|
+
// mergeAttrs: combine base attributes with local ones, overriding duplicates by name
|
|
119
139
|
const mergeAttrs = (into, list) => {
|
|
140
|
+
// build index of existing attribute names
|
|
120
141
|
const idx = new Map();
|
|
121
142
|
into.forEach((a, i) => idx.set(a.name, i));
|
|
143
|
+
// for each new attr, add or override existing
|
|
122
144
|
for (const a of list) {
|
|
123
145
|
const pos = idx.get(a.name);
|
|
124
146
|
if (pos == null) {
|
|
@@ -126,10 +148,11 @@ export function compileCatalog(cat, _opts) {
|
|
|
126
148
|
into.push(a);
|
|
127
149
|
}
|
|
128
150
|
else {
|
|
129
|
-
into[pos] = a; // override
|
|
151
|
+
into[pos] = a; // override existing attribute details
|
|
130
152
|
}
|
|
131
153
|
}
|
|
132
154
|
};
|
|
155
|
+
// mergeElems: combine base elements (particles) with local ones, preserving unique names and overriding duplicates
|
|
133
156
|
const mergeElems = (into, list) => {
|
|
134
157
|
const idx = new Map();
|
|
135
158
|
into.forEach((e, i) => idx.set(e.name, i));
|
|
@@ -140,41 +163,39 @@ export function compileCatalog(cat, _opts) {
|
|
|
140
163
|
into.push(e);
|
|
141
164
|
}
|
|
142
165
|
else {
|
|
143
|
-
into[pos] = e; // override
|
|
166
|
+
into[pos] = e; // override existing element details
|
|
144
167
|
}
|
|
145
168
|
}
|
|
146
169
|
};
|
|
170
|
+
// collectAttributes: read all <attribute> children, handle inline simpleType vs named type references
|
|
171
|
+
// maps each attribute to a TS type, tracks required vs optional via @use, and records the original declared XSD type
|
|
147
172
|
const collectAttributes = (node) => {
|
|
148
173
|
const out = [];
|
|
149
174
|
const attrs = getChildrenWithLocalName(node, "attribute");
|
|
150
175
|
for (const a of attrs) {
|
|
151
176
|
const an = a["@_name"];
|
|
152
|
-
if (!an)
|
|
177
|
+
if (!an) {
|
|
153
178
|
continue;
|
|
179
|
+
}
|
|
154
180
|
const inlineSimple = getFirstWithLocalName(a, "simpleType");
|
|
155
181
|
if (inlineSimple) {
|
|
182
|
+
// inline enumeration or restriction inside attribute
|
|
156
183
|
const r = compileSimpleTypeNode(inlineSimple, schemaNS, prefixes);
|
|
157
|
-
out.push({
|
|
158
|
-
name: an,
|
|
159
|
-
tsType: r.tsType,
|
|
160
|
-
use: a["@_use"] === "required" ? "required" : "optional",
|
|
161
|
-
declaredType: r.declared,
|
|
162
|
-
});
|
|
184
|
+
out.push({ name: an, tsType: r.tsType, use: a["@_use"] === "required" ? "required" : "optional", declaredType: r.declared });
|
|
163
185
|
}
|
|
164
186
|
else {
|
|
187
|
+
// named type or default xs:string
|
|
165
188
|
const t = a["@_type"];
|
|
166
189
|
const q = t ? resolveQName(t, schemaNS, prefixes) : { ns: XS, local: "string" };
|
|
167
190
|
const r = resolveTypeRef(q, schemaNS, prefixes);
|
|
168
|
-
out.push({
|
|
169
|
-
name: an,
|
|
170
|
-
tsType: r.tsType,
|
|
171
|
-
use: a["@_use"] === "required" ? "required" : "optional",
|
|
172
|
-
declaredType: r.declared,
|
|
173
|
-
});
|
|
191
|
+
out.push({ name: an, tsType: r.tsType, use: a["@_use"] === "required" ? "required" : "optional", declaredType: r.declared });
|
|
174
192
|
}
|
|
175
193
|
}
|
|
176
194
|
return out;
|
|
177
195
|
};
|
|
196
|
+
// collectParticles: parse compositor elements (sequence, all, choice), extract <element> definitions
|
|
197
|
+
// handles inline complex/simple definitions by generating a unique inline type name
|
|
198
|
+
// resolves type refs or @ref, applies min/max occurrence and nillable flags
|
|
178
199
|
const collectParticles = (ownerTypeName, node) => {
|
|
179
200
|
const out = [];
|
|
180
201
|
const groups = [
|
|
@@ -185,52 +206,33 @@ export function compileCatalog(cat, _opts) {
|
|
|
185
206
|
for (const grp of groups) {
|
|
186
207
|
for (const e of getChildrenWithLocalName(grp, "element")) {
|
|
187
208
|
const nameOrRef = e["@_name"] || e["@_ref"];
|
|
188
|
-
if (!nameOrRef)
|
|
209
|
+
if (!nameOrRef) {
|
|
189
210
|
continue;
|
|
190
|
-
|
|
211
|
+
}
|
|
212
|
+
const propName = e["@_name"];
|
|
191
213
|
const min = e["@_minOccurs"] ? Number(e["@_minOccurs"]) : 1;
|
|
192
214
|
const maxAttr = e["@_maxOccurs"];
|
|
193
215
|
const max = maxAttr === "unbounded" ? "unbounded" : maxAttr ? Number(maxAttr) : 1;
|
|
194
216
|
const nillable = e["@_nillable"] === "true";
|
|
195
|
-
// inline
|
|
217
|
+
// inline complexType: create a nested interface with a generated name
|
|
196
218
|
const inlineComplex = getFirstWithLocalName(e, "complexType");
|
|
197
219
|
const inlineSimple = getFirstWithLocalName(e, "simpleType");
|
|
198
220
|
if (inlineComplex) {
|
|
199
221
|
const inlineName = makeInlineTypeName(ownerTypeName, propName || nameOrRef, max);
|
|
200
222
|
const rec = getOrCompileComplex(inlineName, inlineComplex, schemaNS, prefixes);
|
|
201
|
-
out.push({
|
|
202
|
-
name: propName || nameOrRef,
|
|
203
|
-
tsType: rec.name,
|
|
204
|
-
min,
|
|
205
|
-
max,
|
|
206
|
-
nillable,
|
|
207
|
-
declaredType: `{${schemaNS}}${rec.name}`,
|
|
208
|
-
});
|
|
223
|
+
out.push({ name: propName || nameOrRef, tsType: rec.name, min, max, nillable, declaredType: `{${schemaNS}}${rec.name}` });
|
|
209
224
|
}
|
|
210
225
|
else if (inlineSimple) {
|
|
226
|
+
// inline simpleType (e.g., list or enumeration)
|
|
211
227
|
const r = compileSimpleTypeNode(inlineSimple, schemaNS, prefixes);
|
|
212
|
-
out.push({
|
|
213
|
-
name: propName || nameOrRef,
|
|
214
|
-
tsType: r.tsType,
|
|
215
|
-
min,
|
|
216
|
-
max,
|
|
217
|
-
nillable,
|
|
218
|
-
declaredType: r.declared,
|
|
219
|
-
});
|
|
228
|
+
out.push({ name: propName || nameOrRef, tsType: r.tsType, min, max, nillable, declaredType: r.declared });
|
|
220
229
|
}
|
|
221
230
|
else {
|
|
222
|
-
//
|
|
231
|
+
// named type or ref: resolve via QName
|
|
223
232
|
const t = e["@_type"] || e["@_ref"];
|
|
224
233
|
const q = t ? resolveQName(t, schemaNS, prefixes) : { ns: XS, local: "string" };
|
|
225
234
|
const r = resolveTypeRef(q, schemaNS, prefixes);
|
|
226
|
-
out.push({
|
|
227
|
-
name: propName || nameOrRef,
|
|
228
|
-
tsType: r.tsType,
|
|
229
|
-
min,
|
|
230
|
-
max,
|
|
231
|
-
nillable,
|
|
232
|
-
declaredType: r.declared,
|
|
233
|
-
});
|
|
235
|
+
out.push({ name: propName || nameOrRef, tsType: r.tsType, min, max, nillable, declaredType: r.declared });
|
|
234
236
|
}
|
|
235
237
|
}
|
|
236
238
|
}
|
|
@@ -277,7 +279,7 @@ export function compileCatalog(cat, _opts) {
|
|
|
277
279
|
if (baseAttr) {
|
|
278
280
|
r = resolveTypeRef(resolveQName(baseAttr, schemaNS, prefixes), schemaNS, prefixes);
|
|
279
281
|
}
|
|
280
|
-
//
|
|
282
|
+
// text node is modeled as "$value" (not "value")
|
|
281
283
|
mergeElems(elems, [{
|
|
282
284
|
name: "$value",
|
|
283
285
|
tsType: r.tsType,
|
|
@@ -292,10 +294,12 @@ export function compileCatalog(cat, _opts) {
|
|
|
292
294
|
inProgress.delete(key);
|
|
293
295
|
return result;
|
|
294
296
|
};
|
|
295
|
-
if (ext)
|
|
297
|
+
if (ext) {
|
|
296
298
|
return model(ext);
|
|
297
|
-
|
|
299
|
+
}
|
|
300
|
+
if (res) {
|
|
298
301
|
return model(res);
|
|
302
|
+
}
|
|
299
303
|
}
|
|
300
304
|
// Attributes + particles
|
|
301
305
|
mergeAttrs(attrs, collectAttributes(cnode));
|
|
@@ -305,13 +309,84 @@ export function compileCatalog(cat, _opts) {
|
|
|
305
309
|
inProgress.delete(key);
|
|
306
310
|
return result;
|
|
307
311
|
}
|
|
312
|
+
// Helper: compile a global element into a surface type (wrapper)
|
|
313
|
+
function compileElementAsType(name, enode, schemaNS, prefixes) {
|
|
314
|
+
const outName = pascal(name);
|
|
315
|
+
const key = `${schemaNS}|${outName}`;
|
|
316
|
+
const present = compiledMap.get(key);
|
|
317
|
+
if (present)
|
|
318
|
+
return present;
|
|
319
|
+
const inlineComplex = getFirstWithLocalName(enode, "complexType");
|
|
320
|
+
if (inlineComplex) {
|
|
321
|
+
return getOrCompileComplex(name, inlineComplex, schemaNS, prefixes);
|
|
322
|
+
}
|
|
323
|
+
const inlineSimple = getFirstWithLocalName(enode, "simpleType");
|
|
324
|
+
if (inlineSimple) {
|
|
325
|
+
const r = compileSimpleTypeNode(inlineSimple, schemaNS, prefixes);
|
|
326
|
+
const t = {
|
|
327
|
+
name: outName,
|
|
328
|
+
ns: schemaNS,
|
|
329
|
+
attrs: [],
|
|
330
|
+
elems: [{ name: "$value", tsType: r.tsType, min: 0, max: 1, nillable: false, declaredType: r.declared }],
|
|
331
|
+
};
|
|
332
|
+
compiledMap.set(key, t);
|
|
333
|
+
return t;
|
|
334
|
+
}
|
|
335
|
+
const tAttr = enode["@_type"];
|
|
336
|
+
if (tAttr) {
|
|
337
|
+
const q = resolveQName(tAttr, schemaNS, prefixes);
|
|
338
|
+
// If references a simple type → $value; if complex type → copy members
|
|
339
|
+
if (q.ns === XS) {
|
|
340
|
+
const label = `xs:${q.local}`;
|
|
341
|
+
const t = {
|
|
342
|
+
name: outName,
|
|
343
|
+
ns: schemaNS,
|
|
344
|
+
attrs: [],
|
|
345
|
+
elems: [{ name: "$value", tsType: xsdToTsPrimitive(label, _opts?.primitive), min: 0, max: 1, nillable: false, declaredType: label }],
|
|
346
|
+
};
|
|
347
|
+
compiledMap.set(key, t);
|
|
348
|
+
return t;
|
|
349
|
+
}
|
|
350
|
+
const baseRec = complexTypes.get(qkey(q));
|
|
351
|
+
if (baseRec) {
|
|
352
|
+
const base = getOrCompileComplex(baseRec.node["@_name"], baseRec.node, baseRec.tns, baseRec.prefixes);
|
|
353
|
+
const t = { name: outName, ns: schemaNS, attrs: [...(base.attrs || [])], elems: [...(base.elems || [])] };
|
|
354
|
+
compiledMap.set(key, t);
|
|
355
|
+
return t;
|
|
356
|
+
}
|
|
357
|
+
const srec = simpleTypes.get(qkey(q));
|
|
358
|
+
if (srec) {
|
|
359
|
+
const a = getOrCompileAlias(q.local, srec.node, srec.tns, srec.prefixes);
|
|
360
|
+
const t = {
|
|
361
|
+
name: outName,
|
|
362
|
+
ns: schemaNS,
|
|
363
|
+
attrs: [],
|
|
364
|
+
elems: [{ name: "$value", tsType: a.name, min: 0, max: 1, nillable: false, declaredType: `{${a.ns}}${q.local}` }],
|
|
365
|
+
};
|
|
366
|
+
compiledMap.set(key, t);
|
|
367
|
+
return t;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
// default empty wrapper
|
|
371
|
+
const t = { name: outName, ns: schemaNS, attrs: [], elems: [] };
|
|
372
|
+
compiledMap.set(key, t);
|
|
373
|
+
return t;
|
|
374
|
+
}
|
|
308
375
|
// compile every discovered complex type
|
|
309
376
|
for (const rec of complexTypes.values()) {
|
|
310
377
|
const name = rec.node["@_name"];
|
|
311
|
-
if (!name)
|
|
378
|
+
if (!name) {
|
|
312
379
|
continue;
|
|
380
|
+
}
|
|
313
381
|
getOrCompileComplex(name, rec.node, rec.tns, rec.prefixes);
|
|
314
382
|
}
|
|
383
|
+
// compile global element wrappers, so metadata contains operation wrappers
|
|
384
|
+
for (const rec of elements.values()) {
|
|
385
|
+
const name = rec.node["@_name"];
|
|
386
|
+
if (!name)
|
|
387
|
+
continue;
|
|
388
|
+
compileElementAsType(name, rec.node, rec.tns, rec.prefixes);
|
|
389
|
+
}
|
|
315
390
|
// emit lists
|
|
316
391
|
const typesList = Array.from(compiledMap.values());
|
|
317
392
|
const aliasList = Array.from(aliasMap.values());
|
|
@@ -332,36 +407,68 @@ export function compileCatalog(cat, _opts) {
|
|
|
332
407
|
childType[t.name] = child;
|
|
333
408
|
propMeta[t.name] = meta;
|
|
334
409
|
}
|
|
335
|
-
// operations / soapAction (
|
|
410
|
+
// operations / soapAction (enriched)
|
|
411
|
+
// 1) Gather all binding definitions and select the SOAP binding (soap:binding or soap12:binding child).
|
|
412
|
+
// 2) Use the binding's @type to locate the matching portType in definitions.
|
|
413
|
+
// 3) Enumerate operations on that portType (wsdl:operation) for input/output WSDL messages.
|
|
414
|
+
// 4) In the chosen binding, extract the <soap:operation> child to read SOAP action URIs.
|
|
336
415
|
const defs = cat.wsdlXml["wsdl:definitions"] || cat.wsdlXml["definitions"];
|
|
337
|
-
const
|
|
338
|
-
const
|
|
339
|
-
const
|
|
416
|
+
const tns = defs?.["@_targetNamespace"] || "";
|
|
417
|
+
const bindingDefs = normalizeArray(defs?.["wsdl:binding"] || defs?.["binding"]);
|
|
418
|
+
const soapBinding = bindingDefs.find(b => Object.keys(b).some(k => k === "soap:binding" || k === "soap12:binding")) || bindingDefs[0];
|
|
419
|
+
// binding @type typically looks like "tns:MyPortType", so resolve via prefixes map
|
|
420
|
+
const portTypeAttr = soapBinding?.["@_type"];
|
|
421
|
+
const portTypeQName = portTypeAttr ? resolveQName(portTypeAttr, tns, cat.prefixMap) : undefined;
|
|
422
|
+
const portTypeDefs = normalizeArray(defs?.["wsdl:portType"] || defs?.["portType"]);
|
|
423
|
+
const targetPortType = portTypeQName
|
|
424
|
+
? portTypeDefs.find(pt => pt?.["@_name"] === portTypeQName.local)
|
|
425
|
+
: portTypeDefs[0];
|
|
426
|
+
// operations listed under <wsdl:portType>
|
|
427
|
+
const pOps = targetPortType ? getChildrenWithLocalName(targetPortType, "operation") : [];
|
|
340
428
|
const bOps = new Map();
|
|
341
|
-
|
|
342
|
-
const
|
|
343
|
-
for (const bo of
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
const node = Array.isArray(v) ? v[0] : v;
|
|
351
|
-
action = node?.["@_soapAction"] || node?.["@_soapActionURI"] || node?.["@_soapActionUrl"] || "";
|
|
352
|
-
if (action)
|
|
353
|
-
break;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
429
|
+
// in the <wsdl:binding>, each operation has a nested <soap:operation> child
|
|
430
|
+
const opsNodes = getChildrenWithLocalName(soapBinding, "operation").filter(o => o["@_name"]);
|
|
431
|
+
for (const bo of opsNodes) {
|
|
432
|
+
// operation name must match portType operation name
|
|
433
|
+
const name = bo["@_name"];
|
|
434
|
+
// find nested soap:operation node for the soapAction attribute
|
|
435
|
+
const soapOps = getChildrenWithLocalName(bo, "operation");
|
|
436
|
+
const soapOp = soapOps[0];
|
|
437
|
+
const action = soapOp?.["@_soapAction"] || soapOp?.["@_soapActionURI"] || soapOp?.["@_soapActionUrl"] || "";
|
|
356
438
|
bOps.set(name, action);
|
|
357
439
|
}
|
|
358
|
-
const
|
|
359
|
-
|
|
440
|
+
const msgDefs = normalizeArray(defs?.["wsdl:message"] || defs?.["message"]);
|
|
441
|
+
const findMessage = (qstr) => {
|
|
442
|
+
if (!qstr)
|
|
443
|
+
return undefined;
|
|
444
|
+
const q = resolveQName(qstr, tns, cat.prefixMap);
|
|
445
|
+
return msgDefs.find(m => m?.["@_name"] === q.local);
|
|
446
|
+
};
|
|
447
|
+
const elementOfMessage = (msg) => {
|
|
448
|
+
if (!msg)
|
|
449
|
+
return undefined;
|
|
450
|
+
const parts = getChildrenWithLocalName(msg, "part");
|
|
451
|
+
// Prefer element-based part (doc/literal)
|
|
452
|
+
const withElem = parts.find(p => p?.["@_element"]);
|
|
453
|
+
const el = withElem?.["@_element"];
|
|
454
|
+
if (!el)
|
|
455
|
+
return undefined;
|
|
456
|
+
const q = resolveQName(el, tns, cat.prefixMap);
|
|
457
|
+
return { ns: q.ns, local: q.local };
|
|
458
|
+
};
|
|
459
|
+
// build operations list
|
|
460
|
+
const ops = (pOps
|
|
461
|
+
.map(po => {
|
|
360
462
|
const name = po?.["@_name"];
|
|
361
463
|
if (!name)
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
464
|
+
return undefined;
|
|
465
|
+
const inMsg = findMessage(getFirstWithLocalName(po, "input")?.["@_message"]);
|
|
466
|
+
const outMsg = findMessage(getFirstWithLocalName(po, "output")?.["@_message"]);
|
|
467
|
+
const inputElement = elementOfMessage(inMsg);
|
|
468
|
+
const outputElement = elementOfMessage(outMsg);
|
|
469
|
+
return { name, soapAction: bOps.get(name) || "", inputElement, outputElement };
|
|
470
|
+
})
|
|
471
|
+
.filter((x) => x != null));
|
|
365
472
|
return {
|
|
366
473
|
types: typesList,
|
|
367
474
|
aliases: aliasList,
|
package/dist/config.d.ts
CHANGED
|
@@ -1,13 +1,35 @@
|
|
|
1
1
|
import type { PrimitiveOptions } from "./xsd/primitives.js";
|
|
2
|
+
/**
|
|
3
|
+
* Options to control WSDL-to-TypeScript compilation behavior.
|
|
4
|
+
*/
|
|
2
5
|
export type CompilerOptions = {
|
|
6
|
+
/**
|
|
7
|
+
* How to represent XML <choice> elements: as all-optional properties or a discriminated union.
|
|
8
|
+
*/
|
|
3
9
|
choice?: "all-optional" | "union";
|
|
10
|
+
/**
|
|
11
|
+
* Legacy flag: map all date/time/duration types to string or Date. Superceded by primitive.dateAs if set.
|
|
12
|
+
*/
|
|
4
13
|
dateAs?: "string" | "date";
|
|
14
|
+
/**
|
|
15
|
+
* Legacy flag: shorthand for int64As and bigIntegerAs. Maps integer types to number or string.
|
|
16
|
+
*/
|
|
5
17
|
intAs?: "number" | "string";
|
|
18
|
+
/**
|
|
19
|
+
* Emit errors if any type references cannot be resolved in the WSDL schema.
|
|
20
|
+
*/
|
|
6
21
|
failOnUnresolved?: boolean;
|
|
7
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* Attribute bag key for the runtime mapper (node-soap).
|
|
24
|
+
*/
|
|
8
25
|
attributesKey?: string;
|
|
9
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Controls low-level mapping of XSD primitives to TypeScript types. Safe defaults are provided.
|
|
28
|
+
*/
|
|
10
29
|
primitive?: PrimitiveOptions;
|
|
11
30
|
};
|
|
31
|
+
/**
|
|
32
|
+
* Default compiler options. Users may override selectively.
|
|
33
|
+
*/
|
|
12
34
|
export declare const defaultOptions: CompilerOptions;
|
|
13
35
|
//# sourceMappingURL=config.d.ts.map
|
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,MAAM,MAAM,eAAe,GAAG;IAC1B,MAAM,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC;IAClC,MAAM,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC3B,KAAK,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B
|
|
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"}
|
package/dist/config.js
CHANGED
|
@@ -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;
|
|
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,QAmCpH"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
+
import { pascal } from "../util/xml.js";
|
|
2
3
|
export function emitClient(outFile, compiled, opts) {
|
|
3
4
|
const ext = opts.importExt ?? ".js";
|
|
4
5
|
const lines = [];
|
|
@@ -14,14 +15,20 @@ export function emitClient(outFile, compiled, opts) {
|
|
|
14
15
|
lines.push(` }`);
|
|
15
16
|
for (const op of compiled.operations) {
|
|
16
17
|
const m = op.name;
|
|
18
|
+
const inTypeName = op.inputElement ? pascal(op.inputElement.local) : undefined;
|
|
19
|
+
const outTypeName = op.outputElement ? pascal(op.outputElement.local) : undefined;
|
|
20
|
+
const inTs = inTypeName ? `T.${inTypeName}` : `any`;
|
|
21
|
+
const outTs = outTypeName ? `T.${outTypeName}` : `any`;
|
|
22
|
+
const inMetaKey = inTypeName ?? m;
|
|
23
|
+
const outMetaKey = outTypeName ?? m;
|
|
17
24
|
lines.push(` /** SOAPAction: ${op.soapAction} */`);
|
|
18
|
-
lines.push(` async ${m}(args:
|
|
25
|
+
lines.push(` async ${m}(args: ${inTs}): Promise<${outTs}> {`);
|
|
19
26
|
lines.push(` const c: any = await this._client();`);
|
|
20
27
|
lines.push(` const meta = { ATTR_SPEC, CHILD_TYPE, PROP_META } as const;`);
|
|
21
|
-
lines.push(` const soapArgs = toSoapArgs(args, "${
|
|
28
|
+
lines.push(` const soapArgs = toSoapArgs(args as any, "${inMetaKey}", meta, this.attributesKey);`);
|
|
22
29
|
lines.push(` return new Promise((resolve, reject) => {`);
|
|
23
30
|
lines.push(` c['${m}'](soapArgs, (err: any, result: any) => {`);
|
|
24
|
-
lines.push(` if (err) reject(err); else resolve(fromSoapResult(result, "${
|
|
31
|
+
lines.push(` if (err) reject(err); else resolve(fromSoapResult(result, "${outMetaKey}", meta, this.attributesKey));`);
|
|
25
32
|
lines.push(` });`);
|
|
26
33
|
lines.push(` });`);
|
|
27
34
|
lines.push(` }`);
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAcnD,wBAAsB,oBAAoB,CACtC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAE,iBA6CrE;AAGD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -8,39 +8,50 @@ import { emitClient } from "./emit/clientEmitter.js";
|
|
|
8
8
|
import { emitRuntime } from "./emit/runtimeEmitter.js";
|
|
9
9
|
import fs from "node:fs";
|
|
10
10
|
import path from "node:path";
|
|
11
|
+
// Entry point for programmatic API: compile a WSDL into a set of TypeScript files in a project layout
|
|
11
12
|
// noinspection JSUnusedGlobalSymbols
|
|
12
13
|
export async function compileWsdlToProject(input) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if (primitive.int64As == null)
|
|
21
|
-
primitive.int64As = as;
|
|
22
|
-
if (primitive.bigIntegerAs == null)
|
|
23
|
-
primitive.bigIntegerAs = as;
|
|
14
|
+
// Merge defaults with user overrides
|
|
15
|
+
const baseOptions = { ...defaultOptions, ...(input.options || {}) };
|
|
16
|
+
// Backward compatibility: legacy flags map to the new primitive preferences if not set
|
|
17
|
+
const normalizedPrimitive = { ...(baseOptions.primitive || {}) };
|
|
18
|
+
if (baseOptions.dateAs && normalizedPrimitive.dateAs == null) {
|
|
19
|
+
// dateAs legacy: choose Date or string based on flag
|
|
20
|
+
normalizedPrimitive.dateAs = baseOptions.dateAs === "date" ? "Date" : "string";
|
|
24
21
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
22
|
+
if (baseOptions.intAs && (normalizedPrimitive.int64As == null || normalizedPrimitive.bigIntegerAs == null)) {
|
|
23
|
+
// intAs legacy: apply to both 64-bit and big integer types
|
|
24
|
+
const as = baseOptions.intAs;
|
|
25
|
+
if (normalizedPrimitive.int64As == null)
|
|
26
|
+
normalizedPrimitive.int64As = as;
|
|
27
|
+
if (normalizedPrimitive.bigIntegerAs == null)
|
|
28
|
+
normalizedPrimitive.bigIntegerAs = as;
|
|
29
|
+
}
|
|
30
|
+
// Final merged options including computed primitive mappings
|
|
31
|
+
const finalOptions = { ...baseOptions, primitive: normalizedPrimitive };
|
|
32
|
+
// Load WSDL definitions and schema catalog (remote or local file)
|
|
33
|
+
const wsdlCatalog = await loadWsdl(input.wsdl);
|
|
34
|
+
console.log(`Loaded WSDL: ${wsdlCatalog.wsdlUri}`);
|
|
35
|
+
// Compile schemas and operations into intermediate data structures
|
|
36
|
+
const compiledCatalog = compileCatalog(wsdlCatalog, finalOptions);
|
|
37
|
+
console.log(`Schemas discovered: ${wsdlCatalog.schemas.length}`);
|
|
38
|
+
console.log(`Compiled types: ${compiledCatalog.types.length}`);
|
|
39
|
+
console.log(`Operations: ${compiledCatalog.operations.length}`);
|
|
40
|
+
// Prepare output directory for generated files
|
|
32
41
|
fs.mkdirSync(input.outDir, { recursive: true });
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
// Define target paths
|
|
43
|
+
const typesFile = path.join(input.outDir, "types.ts");
|
|
44
|
+
const metaFile = path.join(input.outDir, "meta.ts");
|
|
45
|
+
const opsFile = path.join(input.outDir, "operations.json");
|
|
46
|
+
const clientFile = path.join(input.outDir, "client.ts");
|
|
47
|
+
const runtimeFile = path.join(input.outDir, "runtime.ts");
|
|
48
|
+
// Emit code artifacts: types, metadata, operations listing, client harness, runtime helpers
|
|
49
|
+
emitTypes(typesFile, compiledCatalog);
|
|
50
|
+
emitMeta(metaFile, compiledCatalog, finalOptions);
|
|
51
|
+
emitOperations(opsFile, compiledCatalog);
|
|
52
|
+
emitClient(clientFile, compiledCatalog, finalOptions);
|
|
53
|
+
emitRuntime(runtimeFile);
|
|
43
54
|
}
|
|
44
|
-
//
|
|
55
|
+
// Re-export public API for library consumers
|
|
45
56
|
export { compileCatalog } from "./compiler/schemaCompiler.js";
|
|
46
57
|
export { xsdToTsPrimitive } from "./xsd/primitives.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@techspokes/typescript-wsdl-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
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",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"prepublishOnly": "npm run clean && npm run build",
|
|
54
54
|
"test": "exit 0",
|
|
55
55
|
"smoke": "tsx src/cli.ts --help",
|
|
56
|
-
"smoke:gen": "rimraf tmp && tsx src/cli.ts --wsdl examples/minimal/
|
|
56
|
+
"smoke:gen": "rimraf tmp && tsx src/cli.ts --wsdl examples/minimal/weather.wsdl --out tmp && tsc --noEmit --module NodeNext --moduleResolution NodeNext --target ES2022 tmp/types.ts tmp/meta.ts tmp/operations.ts tmp/runtime.ts tmp/client.ts src/types/soap.d.ts",
|
|
57
57
|
"ci": "npm run build && npm run typecheck && npm run smoke && npm run smoke:gen"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|