@techspokes/typescript-wsdl-client 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +245 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +94 -0
  6. package/dist/compiler/schemaCompiler.d.ts +50 -0
  7. package/dist/compiler/schemaCompiler.d.ts.map +1 -0
  8. package/dist/compiler/schemaCompiler.js +372 -0
  9. package/dist/config.d.ts +13 -0
  10. package/dist/config.d.ts.map +1 -0
  11. package/dist/config.js +7 -0
  12. package/dist/emit/clientEmitter.d.ts +6 -0
  13. package/dist/emit/clientEmitter.d.ts.map +1 -0
  14. package/dist/emit/clientEmitter.js +31 -0
  15. package/dist/emit/metaEmitter.d.ts +4 -0
  16. package/dist/emit/metaEmitter.d.ts.map +1 -0
  17. package/dist/emit/metaEmitter.js +9 -0
  18. package/dist/emit/opsEmitter.d.ts +4 -0
  19. package/dist/emit/opsEmitter.d.ts.map +1 -0
  20. package/dist/emit/opsEmitter.js +13 -0
  21. package/dist/emit/runtimeEmitter.d.ts +2 -0
  22. package/dist/emit/runtimeEmitter.d.ts.map +1 -0
  23. package/dist/emit/runtimeEmitter.js +90 -0
  24. package/dist/emit/typesEmitter.d.ts +11 -0
  25. package/dist/emit/typesEmitter.d.ts.map +1 -0
  26. package/dist/emit/typesEmitter.js +91 -0
  27. package/dist/index.d.ts +11 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +46 -0
  30. package/dist/loader/fetch.d.ts +5 -0
  31. package/dist/loader/fetch.d.ts.map +1 -0
  32. package/dist/loader/fetch.js +19 -0
  33. package/dist/loader/wsdlLoader.d.ts +14 -0
  34. package/dist/loader/wsdlLoader.d.ts.map +1 -0
  35. package/dist/loader/wsdlLoader.js +88 -0
  36. package/dist/util/xml.d.ts +13 -0
  37. package/dist/util/xml.d.ts.map +1 -0
  38. package/dist/util/xml.js +40 -0
  39. package/dist/xsd/primitives.d.ts +8 -0
  40. package/dist/xsd/primitives.d.ts.map +1 -0
  41. package/dist/xsd/primitives.js +116 -0
  42. package/package.json +74 -0
@@ -0,0 +1,372 @@
1
+ import { getChildrenWithLocalName, getFirstWithLocalName, normalizeArray, pascal, resolveQName, } from "../util/xml.js";
2
+ import { xsdToTsPrimitive } from "../xsd/primitives.js";
3
+ const XS = "http://www.w3.org/2001/XMLSchema";
4
+ function qkey(q) {
5
+ return `{${q.ns}}${q.local}`;
6
+ }
7
+ /** Inline complex type naming */
8
+ function makeInlineTypeName(parentTypeName, propName, _max) {
9
+ const base = pascal(parentTypeName || "AnonParent");
10
+ const prop = pascal(propName || "");
11
+ if (prop)
12
+ return prop;
13
+ return `${base}Anon`;
14
+ }
15
+ export function compileCatalog(cat, _opts) {
16
+ // symbol tables discovered across all schemas
17
+ const complexTypes = new Map();
18
+ const simpleTypes = new Map();
19
+ const elements = new Map();
20
+ for (const s of cat.schemas) {
21
+ const tns = s.targetNS;
22
+ for (const n of getChildrenWithLocalName(s.xml, "complexType")) {
23
+ const name = n["@_name"];
24
+ if (name)
25
+ complexTypes.set(qkey({ ns: tns, local: name }), { node: n, tns, prefixes: s.prefixes });
26
+ }
27
+ for (const n of getChildrenWithLocalName(s.xml, "simpleType")) {
28
+ const name = n["@_name"];
29
+ if (name)
30
+ simpleTypes.set(qkey({ ns: tns, local: name }), { node: n, tns, prefixes: s.prefixes });
31
+ }
32
+ for (const n of getChildrenWithLocalName(s.xml, "element")) {
33
+ const name = n["@_name"];
34
+ if (name)
35
+ elements.set(qkey({ ns: tns, local: name }), { node: n, tns, prefixes: s.prefixes });
36
+ }
37
+ }
38
+ // outputs & state
39
+ const compiledMap = new Map(); // key: ns|name
40
+ const aliasMap = new Map(); // key: ns|name
41
+ const inProgress = new Set();
42
+ // meta accumulators
43
+ const attrSpec = {};
44
+ const childType = {};
45
+ const propMeta = {};
46
+ /** Compile a simpleType node to TS */
47
+ function compileSimpleTypeNode(simpleNode, schemaNS, prefixes) {
48
+ const rest = getFirstWithLocalName(simpleNode, "restriction");
49
+ if (rest) {
50
+ const enums = normalizeArray(rest["xs:enumeration"] || rest["enumeration"])
51
+ .map((e) => e["@_value"])
52
+ .filter(Boolean);
53
+ const base = rest["@_base"];
54
+ const q = base ? resolveQName(base, schemaNS, prefixes) : { ns: XS, local: "string" };
55
+ const declared = q.ns === XS ? `xs:${q.local}` : `{${q.ns}}${q.local}`;
56
+ if (enums.length) {
57
+ const union = enums.map((v) => JSON.stringify(v)).join(" | ");
58
+ return { tsType: union, declared, jsdoc: JSON.stringify({ kind: "enum", values: enums }) };
59
+ }
60
+ return { tsType: xsdToTsPrimitive(declared, _opts?.primitive), declared };
61
+ }
62
+ const list = getFirstWithLocalName(simpleNode, "list");
63
+ if (list?.["@_itemType"]) {
64
+ const q = resolveQName(list["@_itemType"], schemaNS, prefixes);
65
+ const declared = q.ns === XS ? `xs:${q.local}` : `{${q.ns}}${q.local}`;
66
+ return { tsType: `${xsdToTsPrimitive(declared, _opts?.primitive)}[]`, declared };
67
+ }
68
+ // fallback
69
+ return { tsType: "string", declared: "xs:string" };
70
+ }
71
+ /** Compile and cache a named simpleType */
72
+ function getOrCompileAlias(name, sNode, schemaNS, prefixes) {
73
+ const key = `${schemaNS}|${name}`;
74
+ const present = aliasMap.get(key);
75
+ if (present)
76
+ return present;
77
+ const { tsType, declared, jsdoc } = compileSimpleTypeNode(sNode, schemaNS, prefixes);
78
+ const alias = { name: pascal(name), ns: schemaNS, tsType, declared, jsdoc };
79
+ aliasMap.set(key, alias);
80
+ return alias;
81
+ }
82
+ /** Resolve a QName reference to a TS type; compile targets if needed. */
83
+ function resolveTypeRef(q, schemaNS, prefixes) {
84
+ if (!q.ns)
85
+ q = resolveQName(q.local, schemaNS, prefixes);
86
+ if (q.ns === XS) {
87
+ const label = `xs:${q.local}`;
88
+ return { tsType: xsdToTsPrimitive(label, _opts?.primitive), declared: label };
89
+ }
90
+ const k = qkey(q);
91
+ const srec = simpleTypes.get(k);
92
+ if (srec) {
93
+ const a = getOrCompileAlias(q.local, srec.node, srec.tns, srec.prefixes);
94
+ return { tsType: a.name, declared: `{${a.ns}}${q.local}` };
95
+ }
96
+ const crec = complexTypes.get(k);
97
+ if (crec) {
98
+ const t = getOrCompileComplex(q.local, crec.node, crec.tns, crec.prefixes);
99
+ return { tsType: t.name, declared: `{${t.ns}}${q.local}` };
100
+ }
101
+ // fallback
102
+ return { tsType: "any", declared: `{${q.ns}}${q.local}` };
103
+ }
104
+ function findComplexRec(q) {
105
+ const k = qkey(q);
106
+ return complexTypes.get(k);
107
+ }
108
+ function getOrCompileComplex(name, cnode, schemaNS, prefixes) {
109
+ const outName = pascal(name);
110
+ const key = `${schemaNS}|${outName}`;
111
+ const present = compiledMap.get(key);
112
+ if (present)
113
+ return present;
114
+ if (inProgress.has(key)) {
115
+ // minimal cycle break
116
+ return { name: outName, ns: schemaNS, attrs: [], elems: [] };
117
+ }
118
+ inProgress.add(key);
119
+ const mergeAttrs = (into, list) => {
120
+ const idx = new Map();
121
+ into.forEach((a, i) => idx.set(a.name, i));
122
+ for (const a of list) {
123
+ const pos = idx.get(a.name);
124
+ if (pos == null) {
125
+ idx.set(a.name, into.length);
126
+ into.push(a);
127
+ }
128
+ else {
129
+ into[pos] = a; // override
130
+ }
131
+ }
132
+ };
133
+ const mergeElems = (into, list) => {
134
+ const idx = new Map();
135
+ into.forEach((e, i) => idx.set(e.name, i));
136
+ for (const e of list) {
137
+ const pos = idx.get(e.name);
138
+ if (pos == null) {
139
+ idx.set(e.name, into.length);
140
+ into.push(e);
141
+ }
142
+ else {
143
+ into[pos] = e; // override
144
+ }
145
+ }
146
+ };
147
+ const collectAttributes = (node) => {
148
+ const out = [];
149
+ const attrs = getChildrenWithLocalName(node, "attribute");
150
+ for (const a of attrs) {
151
+ const an = a["@_name"];
152
+ if (!an)
153
+ continue;
154
+ const inlineSimple = getFirstWithLocalName(a, "simpleType");
155
+ if (inlineSimple) {
156
+ 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
+ });
163
+ }
164
+ else {
165
+ const t = a["@_type"];
166
+ const q = t ? resolveQName(t, schemaNS, prefixes) : { ns: XS, local: "string" };
167
+ 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
+ });
174
+ }
175
+ }
176
+ return out;
177
+ };
178
+ const collectParticles = (ownerTypeName, node) => {
179
+ const out = [];
180
+ const groups = [
181
+ ...getChildrenWithLocalName(node, "sequence"),
182
+ ...getChildrenWithLocalName(node, "all"),
183
+ ...getChildrenWithLocalName(node, "choice"),
184
+ ];
185
+ for (const grp of groups) {
186
+ for (const e of getChildrenWithLocalName(grp, "element")) {
187
+ const nameOrRef = e["@_name"] || e["@_ref"];
188
+ if (!nameOrRef)
189
+ continue;
190
+ let propName = e["@_name"] || undefined;
191
+ const min = e["@_minOccurs"] ? Number(e["@_minOccurs"]) : 1;
192
+ const maxAttr = e["@_maxOccurs"];
193
+ const max = maxAttr === "unbounded" ? "unbounded" : maxAttr ? Number(maxAttr) : 1;
194
+ const nillable = e["@_nillable"] === "true";
195
+ // inline complex/simple types
196
+ const inlineComplex = getFirstWithLocalName(e, "complexType");
197
+ const inlineSimple = getFirstWithLocalName(e, "simpleType");
198
+ if (inlineComplex) {
199
+ const inlineName = makeInlineTypeName(ownerTypeName, propName || nameOrRef, max);
200
+ 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
+ });
209
+ }
210
+ else if (inlineSimple) {
211
+ 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
+ });
220
+ }
221
+ else {
222
+ // normal ref/type
223
+ const t = e["@_type"] || e["@_ref"];
224
+ const q = t ? resolveQName(t, schemaNS, prefixes) : { ns: XS, local: "string" };
225
+ 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
+ });
234
+ }
235
+ }
236
+ }
237
+ return out;
238
+ };
239
+ // Result accumulators
240
+ const attrs = [];
241
+ const elems = [];
242
+ // Inheritance: complexContent
243
+ const complexContent = getFirstWithLocalName(cnode, "complexContent");
244
+ if (complexContent) {
245
+ const ext = getFirstWithLocalName(complexContent, "extension");
246
+ const res = getFirstWithLocalName(complexContent, "restriction");
247
+ const node = ext || res;
248
+ if (node) {
249
+ const baseAttr = node["@_base"];
250
+ if (baseAttr) {
251
+ const baseQ = resolveQName(baseAttr, schemaNS, prefixes);
252
+ const baseRec = findComplexRec(baseQ);
253
+ if (baseRec) {
254
+ const base = getOrCompileComplex(baseRec.node["@_name"], baseRec.node, baseRec.tns, baseRec.prefixes);
255
+ // inherit base
256
+ mergeAttrs(attrs, base.attrs);
257
+ mergeElems(elems, base.elems);
258
+ }
259
+ }
260
+ // local additions/overrides
261
+ mergeAttrs(attrs, collectAttributes(node));
262
+ mergeElems(elems, collectParticles(outName, node));
263
+ const result = { name: outName, ns: schemaNS, attrs, elems };
264
+ compiledMap.set(key, result);
265
+ inProgress.delete(key);
266
+ return result;
267
+ }
268
+ }
269
+ // Simple content: text + attributes (IMPORTANT: model text as "$value")
270
+ const simpleContent = getFirstWithLocalName(cnode, "simpleContent");
271
+ if (simpleContent) {
272
+ const ext = getFirstWithLocalName(simpleContent, "extension");
273
+ const res = getFirstWithLocalName(simpleContent, "restriction");
274
+ const model = (scNode) => {
275
+ const baseAttr = scNode["@_base"];
276
+ let r = { tsType: "string", declared: "xs:string" };
277
+ if (baseAttr) {
278
+ r = resolveTypeRef(resolveQName(baseAttr, schemaNS, prefixes), schemaNS, prefixes);
279
+ }
280
+ // 👇👇 text node is modeled as "$value" (not "value")
281
+ mergeElems(elems, [{
282
+ name: "$value",
283
+ tsType: r.tsType,
284
+ min: 0,
285
+ max: 1,
286
+ nillable: false,
287
+ declaredType: r.declared,
288
+ }]);
289
+ mergeAttrs(attrs, collectAttributes(scNode));
290
+ const result = { name: outName, ns: schemaNS, attrs, elems };
291
+ compiledMap.set(key, result);
292
+ inProgress.delete(key);
293
+ return result;
294
+ };
295
+ if (ext)
296
+ return model(ext);
297
+ if (res)
298
+ return model(res);
299
+ }
300
+ // Attributes + particles
301
+ mergeAttrs(attrs, collectAttributes(cnode));
302
+ mergeElems(elems, collectParticles(outName, cnode));
303
+ const result = { name: outName, ns: schemaNS, attrs, elems };
304
+ compiledMap.set(key, result);
305
+ inProgress.delete(key);
306
+ return result;
307
+ }
308
+ // compile every discovered complex type
309
+ for (const rec of complexTypes.values()) {
310
+ const name = rec.node["@_name"];
311
+ if (!name)
312
+ continue;
313
+ getOrCompileComplex(name, rec.node, rec.tns, rec.prefixes);
314
+ }
315
+ // emit lists
316
+ const typesList = Array.from(compiledMap.values());
317
+ const aliasList = Array.from(aliasMap.values());
318
+ // meta
319
+ for (const t of typesList) {
320
+ attrSpec[t.name] = (t.attrs || []).map(a => a.name);
321
+ const child = {};
322
+ const meta = {};
323
+ for (const e of t.elems || []) {
324
+ child[e.name] = typeof e.tsType === "string" ? e.tsType : "any";
325
+ meta[e.name] = {
326
+ declaredType: e.declaredType,
327
+ min: e.min,
328
+ max: e.max,
329
+ nillable: !!e.nillable,
330
+ };
331
+ }
332
+ childType[t.name] = child;
333
+ propMeta[t.name] = meta;
334
+ }
335
+ // operations / soapAction (minimal)
336
+ const defs = cat.wsdlXml["wsdl:definitions"] || cat.wsdlXml["definitions"];
337
+ const portType = defs?.["wsdl:portType"] || defs?.["portType"];
338
+ const binding = defs?.["wsdl:binding"] || defs?.["binding"];
339
+ const pOps = normalizeArray(portType?.["wsdl:operation"] || portType?.["operation"]);
340
+ const bOps = new Map();
341
+ const bindingOps = normalizeArray(binding?.["wsdl:operation"] || binding?.["operation"]);
342
+ const bindingOpsAny = bindingOps.length ? bindingOps : getChildrenWithLocalName(binding || {}, "operation");
343
+ for (const bo of bindingOpsAny) {
344
+ const name = bo?.["@_name"];
345
+ if (!name)
346
+ continue;
347
+ let action = "";
348
+ for (const [k, v] of Object.entries(bo || {})) {
349
+ if (k === "operation" || k.endsWith(":operation")) {
350
+ const node = Array.isArray(v) ? v[0] : v;
351
+ action = node?.["@_soapAction"] || node?.["@_soapActionURI"] || node?.["@_soapActionUrl"] || "";
352
+ if (action)
353
+ break;
354
+ }
355
+ }
356
+ bOps.set(name, action);
357
+ }
358
+ const ops = [];
359
+ for (const po of pOps) {
360
+ const name = po?.["@_name"];
361
+ if (!name)
362
+ continue;
363
+ ops.push({ name, soapAction: bOps.get(name) || "" });
364
+ }
365
+ return {
366
+ types: typesList,
367
+ aliases: aliasList,
368
+ meta: { attrSpec, childType, propMeta },
369
+ operations: ops,
370
+ wsdlTargetNS: defs?.["@_targetNamespace"] || "",
371
+ };
372
+ }
@@ -0,0 +1,13 @@
1
+ import type { PrimitiveOptions } from "./xsd/primitives.js";
2
+ export type CompilerOptions = {
3
+ choice?: "all-optional" | "union";
4
+ dateAs?: "string" | "date";
5
+ intAs?: "number" | "string";
6
+ failOnUnresolved?: boolean;
7
+ /** Attribute bag key for the runtime mapper (node-soap). */
8
+ attributesKey?: string;
9
+ /** Controls how XSD primitives are mapped to TypeScript. Safe defaults apply. */
10
+ primitive?: PrimitiveOptions;
11
+ };
12
+ export declare const defaultOptions: CompilerOptions;
13
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +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,4DAA4D;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAChC,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,eAM5B,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,7 @@
1
+ export const defaultOptions = {
2
+ choice: "all-optional",
3
+ dateAs: "string",
4
+ intAs: "number",
5
+ failOnUnresolved: false,
6
+ attributesKey: "$attributes",
7
+ };
@@ -0,0 +1,6 @@
1
+ import type { CompiledCatalog } from "../compiler/schemaCompiler.js";
2
+ import type { CompilerOptions } from "../config.js";
3
+ export declare function emitClient(outFile: string, compiled: CompiledCatalog, opts: CompilerOptions & {
4
+ importExt?: string;
5
+ }): void;
6
+ //# sourceMappingURL=clientEmitter.d.ts.map
@@ -0,0 +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;AAEpD,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,eAAe,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,QA6BpH"}
@@ -0,0 +1,31 @@
1
+ import fs from "node:fs";
2
+ export function emitClient(outFile, compiled, opts) {
3
+ const ext = opts.importExt ?? ".js";
4
+ const lines = [];
5
+ lines.push(`import { createSoapClient, toSoapArgs, fromSoapResult } from "./runtime${ext}";`);
6
+ lines.push(`import { ATTR_SPEC, CHILD_TYPE, PROP_META } from "./meta${ext}";`);
7
+ lines.push(`import type * as T from "./types${ext}";`);
8
+ lines.push("");
9
+ lines.push(`export class GeneratedSoapClient {`);
10
+ lines.push(` constructor(private source: string | any, private attributesKey: string = "${opts.attributesKey || "$attributes"}") {}`);
11
+ lines.push(` async _client() {`);
12
+ lines.push(` if (typeof this.source === 'string') return createSoapClient({ wsdlUrl: this.source });`);
13
+ lines.push(` return this.source;`);
14
+ lines.push(` }`);
15
+ for (const op of compiled.operations) {
16
+ const m = op.name;
17
+ lines.push(` /** SOAPAction: ${op.soapAction} */`);
18
+ lines.push(` async ${m}(args: any): Promise<any> {`);
19
+ lines.push(` const c: any = await this._client();`);
20
+ lines.push(` const meta = { ATTR_SPEC, CHILD_TYPE, PROP_META } as const;`);
21
+ lines.push(` const soapArgs = toSoapArgs(args, "${m}", meta, this.attributesKey);`);
22
+ lines.push(` return new Promise((resolve, reject) => {`);
23
+ lines.push(` c['${m}'](soapArgs, (err: any, result: any) => {`);
24
+ lines.push(` if (err) reject(err); else resolve(fromSoapResult(result, "${m}", meta, this.attributesKey));`);
25
+ lines.push(` });`);
26
+ lines.push(` });`);
27
+ lines.push(` }`);
28
+ }
29
+ lines.push(`}`);
30
+ fs.writeFileSync(outFile, lines.join("\n"), "utf8");
31
+ }
@@ -0,0 +1,4 @@
1
+ import type { CompiledCatalog } from "../compiler/schemaCompiler.js";
2
+ import type { CompilerOptions } from "../config.js";
3
+ export declare function emitMeta(outFile: string, compiled: CompiledCatalog, opts?: CompilerOptions): void;
4
+ //# sourceMappingURL=metaEmitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metaEmitter.d.ts","sourceRoot":"","sources":["../../src/emit/metaEmitter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,IAAI,CAAC,EAAE,eAAe,QAQ1F"}
@@ -0,0 +1,9 @@
1
+ import fs from "node:fs";
2
+ export function emitMeta(outFile, compiled, opts) {
3
+ const { attrSpec, childType, propMeta } = compiled.meta;
4
+ const src = `export const ATTR_SPEC = ${JSON.stringify(attrSpec, null, 2)} as const;\n` +
5
+ `export const CHILD_TYPE = ${JSON.stringify(childType, null, 2)} as const;\n` +
6
+ `export const PROP_META = ${JSON.stringify(propMeta, null, 2)} as const;\n` +
7
+ `export const OPTIONS = ${JSON.stringify(opts || {}, null, 2)} as const;\n`;
8
+ fs.writeFileSync(outFile, src, "utf8");
9
+ }
@@ -0,0 +1,4 @@
1
+ import type { CompiledCatalog } from "../compiler/schemaCompiler.js";
2
+ export declare function emitOperations(outFile: string, compiled: CompiledCatalog): void;
3
+ export declare function emitOps(outFile: string, compiled: CompiledCatalog): void;
4
+ //# sourceMappingURL=opsEmitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opsEmitter.d.ts","sourceRoot":"","sources":["../../src/emit/opsEmitter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAErE,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,QAExE;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,QAOjE"}
@@ -0,0 +1,13 @@
1
+ import fs from "node:fs";
2
+ export function emitOperations(outFile, compiled) {
3
+ fs.writeFileSync(outFile, JSON.stringify(compiled.operations, null, 2), "utf8");
4
+ }
5
+ export function emitOps(outFile, compiled) {
6
+ if (outFile.endsWith(".ts")) {
7
+ const src = `export const OPERATIONS = ${JSON.stringify(compiled.operations, null, 2)} as const;\n`;
8
+ fs.writeFileSync(outFile, src, "utf8");
9
+ }
10
+ else {
11
+ emitOperations(outFile, compiled);
12
+ }
13
+ }
@@ -0,0 +1,2 @@
1
+ export declare function emitRuntime(outFile: string): void;
2
+ //# sourceMappingURL=runtimeEmitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtimeEmitter.d.ts","sourceRoot":"","sources":["../../src/emit/runtimeEmitter.ts"],"names":[],"mappings":"AAGA,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,QAuF1C"}
@@ -0,0 +1,90 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ export function emitRuntime(outFile) {
4
+ const code = `// noinspection NpmUsedModulesInstalled,JSLastCommaInObjectLiteral,CommaExpressionJS,JSUnresolvedReference
5
+
6
+ import soap from "soap";
7
+ export type CreateSoapClientOptions = {
8
+ wsdlUrl: string;
9
+ endpoint?: string;
10
+ wsdlOptions?: Record<string, any>;
11
+ requestOptions?: Record<string, any>;
12
+ }
13
+ export type AttrSpec = Record<string, readonly string[]>;
14
+ export type ChildType = Record<string, Readonly<Record<string, string>>>;
15
+ export type PropMeta = Record<string, Readonly<Record<string, any>>>;
16
+
17
+ export async function createSoapClient(opts: CreateSoapClientOptions): Promise<any> {
18
+ const client = await soap.createClientAsync(opts.wsdlUrl, opts.wsdlOptions || {});
19
+ if (opts.endpoint) client.setEndpoint(opts.endpoint);
20
+ if (opts.requestOptions) {
21
+ const { wsdlUrl, endpoint, wsdlOptions, ...req } = opts as any;
22
+ if (client.setSecurity && req) {
23
+ // security is caller's responsibility (if needed)
24
+ }
25
+ }
26
+ return client;
27
+ }
28
+
29
+ export function toSoapArgs(
30
+ value: any,
31
+ typeName?: string,
32
+ meta?: { ATTR_SPEC: AttrSpec; CHILD_TYPE: ChildType; PROP_META: PropMeta },
33
+ attributesKey: string = "$attributes"
34
+ ): any {
35
+ if (value == null) return value;
36
+ if (typeof value !== "object") return value;
37
+ const attrList = (typeName && meta?.ATTR_SPEC?.[typeName]) || [];
38
+ const childType = (typeName && meta?.CHILD_TYPE?.[typeName]) || {};
39
+ const out: any = {};
40
+ const attrBag: any = {};
41
+ // map TS $value -> SOAP $value
42
+ if ("$value" in value && Object.keys(value).length >= 1) out.$value = (value as any).$value;
43
+
44
+ for (const [k, v] of Object.entries<any>(value)) {
45
+ if (k === "$value") continue; // skip text node (already mapped)
46
+ if (k === attributesKey) continue; // user shouldn't send raw attr bag
47
+ if (attrList.includes(k)) { attrBag[k] = v; continue; }
48
+ const childT = (childType as any)[k] as string | undefined;
49
+ out[k] = Array.isArray(v)
50
+ ? v.map(it => toSoapArgs(it, childT, meta, attributesKey))
51
+ : toSoapArgs(v, childT, meta, attributesKey);
52
+ }
53
+ if (Object.keys(attrBag).length) out[attributesKey] = attrBag;
54
+ return out;
55
+ }
56
+
57
+ export function fromSoapResult(
58
+ node: any,
59
+ typeName?: string,
60
+ meta?: { ATTR_SPEC: AttrSpec; CHILD_TYPE: ChildType; PROP_META: PropMeta },
61
+ attributesKey: string = "$attributes"
62
+ ): any {
63
+ if (node == null) return node;
64
+ if (typeof node !== "object") return node;
65
+ if (Array.isArray(node)) return node.map(n => fromSoapResult(n, typeName, meta, attributesKey));
66
+
67
+ const childType = (typeName && meta?.CHILD_TYPE?.[typeName]) || {};
68
+ const result: any = {};
69
+
70
+ // map SOAP $value -> TS $value
71
+ if ("$value" in node) result.$value = (node as any).$value;
72
+
73
+ // hoist attributes
74
+ if (attributesKey in node && node[attributesKey] && typeof node[attributesKey] === "object") {
75
+ Object.assign(result, node[attributesKey]);
76
+ }
77
+
78
+ for (const [k, v] of Object.entries<any>(node)) {
79
+ if (k === attributesKey || k === "$value") continue;
80
+ const childT = (childType as any)[k] as string | undefined;
81
+ result[k] = Array.isArray(v)
82
+ ? v.map(it => fromSoapResult(it, childT, meta, attributesKey))
83
+ : fromSoapResult(v, childT, meta, attributesKey);
84
+ }
85
+ return result;
86
+ }
87
+ `;
88
+ fs.mkdirSync(path.dirname(outFile), { recursive: true });
89
+ fs.writeFileSync(outFile, code, "utf8");
90
+ }
@@ -0,0 +1,11 @@
1
+ import type { CompiledCatalog } from "../compiler/schemaCompiler.js";
2
+ /**
3
+ * Emit TypeScript types from a compiled XSD catalog.
4
+ *
5
+ * - Text node is modeled as "$value" (not "value") to avoid collisions with real elements.
6
+ * - xs:complexType + xs:simpleContent/extension is flattened to `extends <BaseType>`.
7
+ * - All properties (attributes and elements) include @xsd JSDoc.
8
+ * - If a "$value" element is present, it is emitted last.
9
+ */
10
+ export declare function emitTypes(outFile: string, compiled: CompiledCatalog): void;
11
+ //# sourceMappingURL=typesEmitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typesEmitter.d.ts","sourceRoot":"","sources":["../../src/emit/typesEmitter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAErE;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,QA+FnE"}