@techspokes/typescript-wsdl-client 0.2.72 → 0.3.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.
@@ -1 +1 @@
1
- {"version":3,"file":"runtimeEmitter.d.ts","sourceRoot":"","sources":["../../src/emit/runtimeEmitter.ts"],"names":[],"mappings":"AAGA,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,QAsH1C"}
1
+ {"version":3,"file":"runtimeEmitter.d.ts","sourceRoot":"","sources":["../../src/emit/runtimeEmitter.ts"],"names":[],"mappings":"AAGA,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,QAgJ1C"}
@@ -7,39 +7,48 @@ export function emitRuntime(outFile) {
7
7
  endpoint?: string;
8
8
  wsdlOptions?: Record<string, any>;
9
9
  requestOptions?: Record<string, any>;
10
- security?: any; // pass an instance of a node-soap security class, e.g., new soap.WSSecurity("user","pass")
10
+ security?: any;
11
11
  }
12
+
12
13
  export type AttrSpec = Record<string, readonly string[]>;
13
14
  export type ChildType = Record<string, Readonly<Record<string, string>>>;
14
15
  export type PropMeta = Record<string, Readonly<Record<string, any>>>;
15
16
 
16
- async function loadSoapModule(): Promise<any> {
17
- // Prefer dynamic import (works in ESM). Fallback to require where available (CJS).
17
+ // Universal CJS/ESM loader without import.meta
18
+ async function loadSoap(): Promise<any> {
19
+ // Prefer CJS require when available (CommonJS or transpiled output)
18
20
  try {
19
- // @ts-ignore
20
- const m: any = await import("soap");
21
- return (m && (m.default || m.createClient || m.createClientAsync)) ? (m.default ?? m) : m;
22
- } catch (e) {
23
- try {
24
- // eslint-disable-next-line @typescript-eslint/no-var-requires
25
- const req = (typeof require !== "undefined") ? require : (await import("node:module")).createRequire(import.meta.url);
26
- return req("soap");
27
- } catch {
28
- throw e;
29
- }
21
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
22
+ const cjsMod = typeof require === "function" ? require("soap") : undefined;
23
+ if (cjsMod) return cjsMod;
24
+ } catch {
25
+ // ignore and fall back to dynamic import
30
26
  }
27
+ // ESM fallback (Node wraps CJS under default)
28
+ const esmMod: any = await import("soap");
29
+ return (esmMod && esmMod.default) ? esmMod.default : esmMod;
31
30
  }
32
31
 
33
32
  export async function createSoapClient(opts: CreateSoapClientOptions): Promise<any> {
34
- const soapModule = await loadSoapModule();
35
- const client = await soapModule.createClientAsync(opts.wsdlUrl, opts.wsdlOptions || {});
36
- if (opts.endpoint) client.setEndpoint(opts.endpoint);
37
- if (opts.security) client.setSecurity(opts.security);
38
- // security and any request-specific configuration are the caller's responsibility
39
- return client;
33
+ try {
34
+ const soapModule = await loadSoap();
35
+
36
+ console.log("Creating SOAP client with WSDL:", opts.wsdlUrl);
37
+ console.log("SOAP module methods available:", typeof soapModule.createClientAsync);
38
+
39
+ const client = await soapModule.createClientAsync(opts.wsdlUrl, opts.wsdlOptions || {});
40
+ if (opts.endpoint) client.setEndpoint(opts.endpoint);
41
+ if (opts.security) client.setSecurity(opts.security);
42
+
43
+ console.log("SOAP client created successfully");
44
+ return client;
45
+ } catch (error) {
46
+ console.error("Error creating SOAP client:", error);
47
+ throw error;
48
+ }
40
49
  }
41
50
 
42
- // Normalize booleans/numbers for XML attributes (node-soap handles strings best)
51
+ // Normalize simple attribute values to strings (WCF prefers string attrs)
43
52
  function normalizeAttrValue(v: unknown): string {
44
53
  if (v == null) return "";
45
54
  if (typeof v === "boolean") return v ? "true" : "false";
@@ -51,36 +60,53 @@ export function toSoapArgs(
51
60
  value: any,
52
61
  typeName?: string,
53
62
  meta?: { ATTR_SPEC: AttrSpec; CHILD_TYPE: ChildType; PROP_META: PropMeta },
54
- attributesKey: string = "$attributes" // input bag name accepted from TS-side
63
+ attributesKeyIn: string = "$attributes", // accepted TS-side bag
64
+ attributesKeyOut: string = "attributes" // node-soap expects "attributes"
55
65
  ): any {
56
66
  if (value == null) return value;
57
67
  if (typeof value !== "object") return value;
68
+ if (Array.isArray(value)) {
69
+ return value.map(v => toSoapArgs(v, typeName, meta, attributesKeyIn, attributesKeyOut));
70
+ }
71
+
58
72
  const attrList = (typeName && meta?.ATTR_SPEC?.[typeName]) || [];
59
73
  const childType = (typeName && meta?.CHILD_TYPE?.[typeName]) || {};
74
+
60
75
  const out: any = {};
61
76
  const attrBag: Record<string, any> = {};
62
- // map TS $value -> SOAP $value
63
- if ("$value" in value && Object.keys(value).length >= 1) out.$value = (value as any).$value;
64
77
 
65
- // merge user-provided attr bag(s) first (support both attributesKey and 'attributes')
66
- const inAttrNode = (value as any)[attributesKey] ?? (value as any)["attributes"];
78
+ // text content
79
+ if ("$value" in value) {
80
+ out.$value = (value as any).$value;
81
+ }
82
+
83
+ // merge user-provided attr bags ("$attributes" or "attributes")
84
+ const inAttrNode = (value as any)[attributesKeyIn] ?? (value as any)["attributes"];
67
85
  if (inAttrNode && typeof inAttrNode === "object") {
68
86
  for (const [ak, av] of Object.entries(inAttrNode)) {
69
87
  attrBag[ak] = normalizeAttrValue(av);
70
88
  }
71
89
  }
72
90
 
91
+ // split attributes vs elements
73
92
  for (const [k, v] of Object.entries<any>(value)) {
74
- if (k === "$value") continue; // skip text node (already mapped)
75
- if (k === attributesKey || k === "attributes") continue; // user shouldn't send raw attr bag beyond merge above
76
- if (attrList.includes(k)) { attrBag[k] = normalizeAttrValue(v); continue; }
93
+ if (k === "$value" || k === attributesKeyIn || k === "attributes") continue;
94
+
95
+ if (attrList.includes(k)) {
96
+ attrBag[k] = normalizeAttrValue(v);
97
+ continue;
98
+ }
99
+
77
100
  const childT = (childType as any)[k] as string | undefined;
78
101
  out[k] = Array.isArray(v)
79
- ? v.map(it => toSoapArgs(it, childT, meta, attributesKey))
80
- : toSoapArgs(v, childT, meta, attributesKey);
102
+ ? v.map(it => toSoapArgs(it, childT, meta, attributesKeyIn, attributesKeyOut))
103
+ : toSoapArgs(v, childT, meta, attributesKeyIn, attributesKeyOut);
81
104
  }
82
- // node-soap expects 'attributes' bag to render as XML attributes
83
- if (Object.keys(attrBag).length) (out as any).attributes = attrBag;
105
+
106
+ if (Object.keys(attrBag).length) {
107
+ out[attributesKeyOut] = attrBag; // renders as XML attributes
108
+ }
109
+
84
110
  return out;
85
111
  }
86
112
 
@@ -88,31 +114,31 @@ export function fromSoapResult(
88
114
  node: any,
89
115
  typeName?: string,
90
116
  meta?: { ATTR_SPEC: AttrSpec; CHILD_TYPE: ChildType; PROP_META: PropMeta },
91
- attributesKey: string = "$attributes" // keep exposing attrs to TS via hoisting; this name is only used to skip if present
117
+ attributesKeyOut: string = "$attributes"
92
118
  ): any {
93
119
  if (node == null) return node;
94
120
  if (typeof node !== "object") return node;
95
- if (Array.isArray(node)) return node.map(n => fromSoapResult(n, typeName, meta, attributesKey));
121
+ if (Array.isArray(node)) return node.map(n => fromSoapResult(n, typeName, meta, attributesKeyOut));
96
122
 
97
123
  const childType = (typeName && meta?.CHILD_TYPE?.[typeName]) || {};
98
124
  const result: any = {};
99
125
 
100
- // map SOAP $value -> TS $value
101
126
  if ("$value" in node) result.$value = (node as any).$value;
102
127
 
103
- // hoist attributes from any supported bucket: node-soap may use 'attributes'; xml2js often uses '$'
104
- const inAttrNode = (node as any)[attributesKey] || (node as any)["attributes"] || (node as any)["$"];
128
+ // hoist attributes from supported buckets
129
+ const inAttrNode = (node as any)[attributesKeyOut] || (node as any)["attributes"] || (node as any)["$"];
105
130
  if (inAttrNode && typeof inAttrNode === "object") {
106
131
  Object.assign(result, inAttrNode);
107
132
  }
108
133
 
109
134
  for (const [k, v] of Object.entries<any>(node)) {
110
- if (k === attributesKey || k === "attributes" || k === "$" || k === "$value") continue;
135
+ if (k === attributesKeyOut || k === "attributes" || k === "$" || k === "$value") continue;
111
136
  const childT = (childType as any)[k] as string | undefined;
112
137
  result[k] = Array.isArray(v)
113
- ? v.map(it => fromSoapResult(it, childT, meta, attributesKey))
114
- : fromSoapResult(v, childT, meta, attributesKey);
138
+ ? v.map(it => fromSoapResult(it, childT, meta, attributesKeyOut))
139
+ : fromSoapResult(v, childT, meta, attributesKeyOut);
115
140
  }
141
+
116
142
  return result;
117
143
  }
118
144
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@techspokes/typescript-wsdl-client",
3
- "version": "0.2.72",
3
+ "version": "0.3.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",