@techspokes/typescript-wsdl-client 0.2.71 → 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,QAoF1C"}
1
+ {"version":3,"file":"runtimeEmitter.d.ts","sourceRoot":"","sources":["../../src/emit/runtimeEmitter.ts"],"names":[],"mappings":"AAGA,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,QAgJ1C"}
@@ -1,53 +1,112 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  export function emitRuntime(outFile) {
4
- const code = `// noinspection NpmUsedModulesInstalled,JSLastCommaInObjectLiteral,CommaExpressionJS,JSUnresolvedReference
5
-
6
- import soap from "soap";
7
- export type CreateSoapClientOptions = {
4
+ // noinspection UnreachableCodeJS,NpmUsedModulesInstalled,JSLastCommaInObjectLiteral,CommaExpressionJS,JSUnresolvedReference,BadExpressionStatementJS,JSCheckFunctionSignatures
5
+ const code = `export type CreateSoapClientOptions = {
8
6
  wsdlUrl: string;
9
7
  endpoint?: string;
10
8
  wsdlOptions?: Record<string, any>;
11
9
  requestOptions?: Record<string, any>;
12
- security?: any; // pass an instance of a node-soap security class, e.g., new soap.WSSecurity("user","pass")
10
+ security?: any;
13
11
  }
12
+
14
13
  export type AttrSpec = Record<string, readonly string[]>;
15
14
  export type ChildType = Record<string, Readonly<Record<string, string>>>;
16
15
  export type PropMeta = Record<string, Readonly<Record<string, any>>>;
17
16
 
17
+ // Universal CJS/ESM loader without import.meta
18
+ async function loadSoap(): Promise<any> {
19
+ // Prefer CJS require when available (CommonJS or transpiled output)
20
+ try {
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
26
+ }
27
+ // ESM fallback (Node wraps CJS under default)
28
+ const esmMod: any = await import("soap");
29
+ return (esmMod && esmMod.default) ? esmMod.default : esmMod;
30
+ }
31
+
18
32
  export async function createSoapClient(opts: CreateSoapClientOptions): Promise<any> {
19
- const client = await soap.createClientAsync(opts.wsdlUrl, opts.wsdlOptions || {});
20
- if (opts.endpoint) client.setEndpoint(opts.endpoint);
21
- if (opts.security) client.setSecurity(opts.security);
22
- // security and any request-specific configuration are the caller's responsibility
23
- 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
+ }
49
+ }
50
+
51
+ // Normalize simple attribute values to strings (WCF prefers string attrs)
52
+ function normalizeAttrValue(v: unknown): string {
53
+ if (v == null) return "";
54
+ if (typeof v === "boolean") return v ? "true" : "false";
55
+ if (typeof v === "number") return Number.isFinite(v) ? String(v) : "";
56
+ return String(v);
24
57
  }
25
58
 
26
59
  export function toSoapArgs(
27
60
  value: any,
28
61
  typeName?: string,
29
62
  meta?: { ATTR_SPEC: AttrSpec; CHILD_TYPE: ChildType; PROP_META: PropMeta },
30
- attributesKey: string = "$attributes"
63
+ attributesKeyIn: string = "$attributes", // accepted TS-side bag
64
+ attributesKeyOut: string = "attributes" // node-soap expects "attributes"
31
65
  ): any {
32
66
  if (value == null) return value;
33
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
+
34
72
  const attrList = (typeName && meta?.ATTR_SPEC?.[typeName]) || [];
35
73
  const childType = (typeName && meta?.CHILD_TYPE?.[typeName]) || {};
74
+
36
75
  const out: any = {};
37
- const attrBag: any = {};
38
- // map TS $value -> SOAP $value
39
- if ("$value" in value && Object.keys(value).length >= 1) out.$value = (value as any).$value;
76
+ const attrBag: Record<string, any> = {};
77
+
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"];
85
+ if (inAttrNode && typeof inAttrNode === "object") {
86
+ for (const [ak, av] of Object.entries(inAttrNode)) {
87
+ attrBag[ak] = normalizeAttrValue(av);
88
+ }
89
+ }
40
90
 
91
+ // split attributes vs elements
41
92
  for (const [k, v] of Object.entries<any>(value)) {
42
- if (k === "$value") continue; // skip text node (already mapped)
43
- if (k === attributesKey) continue; // user shouldn't send raw attr bag
44
- if (attrList.includes(k)) { attrBag[k] = 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
+
45
100
  const childT = (childType as any)[k] as string | undefined;
46
101
  out[k] = Array.isArray(v)
47
- ? v.map(it => toSoapArgs(it, childT, meta, attributesKey))
48
- : toSoapArgs(v, childT, meta, attributesKey);
102
+ ? v.map(it => toSoapArgs(it, childT, meta, attributesKeyIn, attributesKeyOut))
103
+ : toSoapArgs(v, childT, meta, attributesKeyIn, attributesKeyOut);
104
+ }
105
+
106
+ if (Object.keys(attrBag).length) {
107
+ out[attributesKeyOut] = attrBag; // renders as XML attributes
49
108
  }
50
- if (Object.keys(attrBag).length) out[attributesKey] = attrBag;
109
+
51
110
  return out;
52
111
  }
53
112
 
@@ -55,30 +114,31 @@ export function fromSoapResult(
55
114
  node: any,
56
115
  typeName?: string,
57
116
  meta?: { ATTR_SPEC: AttrSpec; CHILD_TYPE: ChildType; PROP_META: PropMeta },
58
- attributesKey: string = "$attributes"
117
+ attributesKeyOut: string = "$attributes"
59
118
  ): any {
60
119
  if (node == null) return node;
61
120
  if (typeof node !== "object") return node;
62
- 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));
63
122
 
64
123
  const childType = (typeName && meta?.CHILD_TYPE?.[typeName]) || {};
65
124
  const result: any = {};
66
125
 
67
- // map SOAP $value -> TS $value
68
126
  if ("$value" in node) result.$value = (node as any).$value;
69
127
 
70
- // hoist attributes
71
- if (attributesKey in node && node[attributesKey] && typeof node[attributesKey] === "object") {
72
- Object.assign(result, node[attributesKey]);
128
+ // hoist attributes from supported buckets
129
+ const inAttrNode = (node as any)[attributesKeyOut] || (node as any)["attributes"] || (node as any)["$"];
130
+ if (inAttrNode && typeof inAttrNode === "object") {
131
+ Object.assign(result, inAttrNode);
73
132
  }
74
133
 
75
134
  for (const [k, v] of Object.entries<any>(node)) {
76
- if (k === attributesKey || k === "$value") continue;
135
+ if (k === attributesKeyOut || k === "attributes" || k === "$" || k === "$value") continue;
77
136
  const childT = (childType as any)[k] as string | undefined;
78
137
  result[k] = Array.isArray(v)
79
- ? v.map(it => fromSoapResult(it, childT, meta, attributesKey))
80
- : fromSoapResult(v, childT, meta, attributesKey);
138
+ ? v.map(it => fromSoapResult(it, childT, meta, attributesKeyOut))
139
+ : fromSoapResult(v, childT, meta, attributesKeyOut);
81
140
  }
141
+
82
142
  return result;
83
143
  }
84
144
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@techspokes/typescript-wsdl-client",
3
- "version": "0.2.71",
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",