@techspokes/typescript-wsdl-client 0.11.5 → 0.13.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 +2 -1
- package/dist/app/generateApp.js +1 -1
- package/dist/client/generateClient.d.ts.map +1 -1
- package/dist/client/generateClient.js +9 -1
- package/dist/client/generateOperations.d.ts.map +1 -1
- package/dist/client/generateOperations.js +11 -1
- package/dist/client/generateTypes.d.ts.map +1 -1
- package/dist/client/generateTypes.js +49 -6
- package/dist/compiler/schemaCompiler.d.ts +8 -0
- package/dist/compiler/schemaCompiler.d.ts.map +1 -1
- package/dist/compiler/schemaCompiler.js +125 -12
- package/dist/gateway/generators.d.ts +2 -0
- package/dist/gateway/generators.d.ts.map +1 -1
- package/dist/gateway/generators.js +57 -23
- package/dist/gateway/helpers.d.ts +13 -0
- package/dist/gateway/helpers.d.ts.map +1 -1
- package/dist/gateway/helpers.js +58 -0
- package/dist/openapi/generatePaths.d.ts.map +1 -1
- package/dist/openapi/generatePaths.js +5 -1
- package/dist/openapi/generateSchemas.d.ts.map +1 -1
- package/dist/openapi/generateSchemas.js +29 -5
- package/dist/pipeline.d.ts +1 -0
- package/dist/pipeline.d.ts.map +1 -1
- package/dist/pipeline.js +1 -0
- package/dist/test/generateTests.d.ts +1 -0
- package/dist/test/generateTests.d.ts.map +1 -1
- package/dist/test/generateTests.js +9 -4
- package/dist/test/generators.d.ts +12 -7
- package/dist/test/generators.d.ts.map +1 -1
- package/dist/test/generators.js +41 -37
- package/dist/test/mockData.d.ts +23 -10
- package/dist/test/mockData.d.ts.map +1 -1
- package/dist/test/mockData.js +44 -4
- package/dist/util/catalogMeta.d.ts +33 -0
- package/dist/util/catalogMeta.d.ts.map +1 -0
- package/dist/util/catalogMeta.js +95 -0
- package/docs/architecture.md +2 -0
- package/docs/concepts.md +2 -0
- package/docs/generated-code.md +31 -3
- package/docs/testing.md +10 -9
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -13,6 +13,7 @@ Generate type-safe TypeScript SOAP clients, OpenAPI 3.1 specs, and production-re
|
|
|
13
13
|
- OpenAPI 3.1 specs that mirror your TypeScript types
|
|
14
14
|
- REST gateway over SOAP with automatic request/response transformation
|
|
15
15
|
- CI-friendly deterministic output for safe regeneration in version control
|
|
16
|
+
- WSDL/XSD documentation propagated into generated comments and OpenAPI descriptions
|
|
16
17
|
|
|
17
18
|
## Quick Start
|
|
18
19
|
|
|
@@ -57,7 +58,7 @@ curl -X POST http://localhost:3000/get-weather-information \
|
|
|
57
58
|
|
|
58
59
|
| Output | Files | Purpose |
|
|
59
60
|
|--------|-------|---------|
|
|
60
|
-
| TypeScript Client | client.ts, types.ts, utils.ts | Typed SOAP operations |
|
|
61
|
+
| TypeScript Client | client.ts, types.ts, utils.ts, operations.ts | Typed SOAP operations and mockable operations interface |
|
|
61
62
|
| OpenAPI 3.1 Spec | openapi.json or .yaml | REST API documentation |
|
|
62
63
|
| Fastify Gateway | plugin.ts, routes/, schemas/ | Production REST handlers |
|
|
63
64
|
| Catalog | catalog.json | Compiled WSDL (debuggable, cacheable) |
|
package/dist/app/generateApp.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateClient.d.ts","sourceRoot":"","sources":["../../src/client/generateClient.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,+BAA+B,CAAC;AAInE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"generateClient.d.ts","sourceRoot":"","sources":["../../src/client/generateClient.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,+BAA+B,CAAC;AAInE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,QA+WxE"}
|
|
@@ -34,6 +34,12 @@ import { error, warn } from "../util/cli.js";
|
|
|
34
34
|
*/
|
|
35
35
|
export function generateClient(outFile, compiled) {
|
|
36
36
|
const isValidIdent = (name) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name);
|
|
37
|
+
const normalizeDocLines = (text) => String(text)
|
|
38
|
+
.replace(/\r\n?/g, "\n")
|
|
39
|
+
.split("\n")
|
|
40
|
+
.map(line => line.trim())
|
|
41
|
+
.filter(Boolean)
|
|
42
|
+
.map(line => line.replace(/\*\//g, "*\\/"));
|
|
37
43
|
const reserved = new Set([
|
|
38
44
|
"break", "case", "catch", "class", "const", "continue", "debugger", "default", "delete",
|
|
39
45
|
"do", "else", "enum", "export", "extends", "false", "finally", "for", "function", "if",
|
|
@@ -61,11 +67,13 @@ export function generateClient(outFile, compiled) {
|
|
|
61
67
|
const inTs = inTypeName ? `T.${inTypeName}` : `any`;
|
|
62
68
|
const outTs = outTypeName ? `T.${outTypeName}` : `any`;
|
|
63
69
|
const secHints = Array.isArray(op.security) && op.security.length ? op.security : [];
|
|
70
|
+
const opDocLines = op.doc ? normalizeDocLines(op.doc) : [];
|
|
71
|
+
const opDocStr = opDocLines.length ? `\n *\n${opDocLines.map(line => ` * ${line}`).join("\n")}` : "";
|
|
64
72
|
const secHintsStr = secHints.length ? `\n *\n * Security (WSDL policy hint): ${secHints.join(", ")}` : "";
|
|
65
73
|
const methodTemplate = `
|
|
66
74
|
|
|
67
75
|
/**
|
|
68
|
-
* Calls the ${m} operation of the ${clientName}.${secHintsStr}
|
|
76
|
+
* Calls the ${m} operation of the ${clientName}.${opDocStr}${secHintsStr}
|
|
69
77
|
*
|
|
70
78
|
* @param args - The request arguments for the ${m} operation.
|
|
71
79
|
* @returns A promise resolving to the operation response containing data, headers, response raw XML, and request raw XML.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateOperations.d.ts","sourceRoot":"","sources":["../../src/client/generateOperations.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAIrE;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"generateOperations.d.ts","sourceRoot":"","sources":["../../src/client/generateOperations.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAIrE;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,IAAI,CAsEnF"}
|
|
@@ -22,6 +22,12 @@ export function generateOperations(outFile, compiled) {
|
|
|
22
22
|
const ext = compiled.options.imports ?? "bare";
|
|
23
23
|
const suffix = ext === "bare" ? "" : `.${ext}`;
|
|
24
24
|
const clientName = deriveClientName(compiled);
|
|
25
|
+
const normalizeDocLines = (text) => String(text)
|
|
26
|
+
.replace(/\r\n?/g, "\n")
|
|
27
|
+
.split("\n")
|
|
28
|
+
.map(line => line.trim())
|
|
29
|
+
.filter(Boolean)
|
|
30
|
+
.map(line => line.replace(/\*\//g, "*\\/"));
|
|
25
31
|
// Collect type names used in method signatures for the import statement
|
|
26
32
|
const importedTypes = new Set();
|
|
27
33
|
const methods = [];
|
|
@@ -37,7 +43,11 @@ export function generateOperations(outFile, compiled) {
|
|
|
37
43
|
importedTypes.add(inTypeName);
|
|
38
44
|
if (outTypeName)
|
|
39
45
|
importedTypes.add(outTypeName);
|
|
40
|
-
|
|
46
|
+
const docLines = op.doc ? normalizeDocLines(op.doc) : [];
|
|
47
|
+
const docBlock = docLines.length > 0
|
|
48
|
+
? ` /**\n${docLines.map(line => ` * ${line}`).join("\n")}\n */\n`
|
|
49
|
+
: "";
|
|
50
|
+
methods.push(`${docBlock} ${op.name}(\n` +
|
|
41
51
|
` args: ${inTs}\n` +
|
|
42
52
|
` ): Promise<{ response: ${outTs}; headers: unknown }>;\n`);
|
|
43
53
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateTypes.d.ts","sourceRoot":"","sources":["../../src/client/generateTypes.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAC,eAAe,EAAe,MAAM,+BAA+B,CAAC;AAGjF;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"generateTypes.d.ts","sourceRoot":"","sources":["../../src/client/generateTypes.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAC,eAAe,EAAe,MAAM,+BAA+B,CAAC;AAGjF;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,QAyLvE"}
|
|
@@ -35,6 +35,30 @@ import { error } from "../util/cli.js";
|
|
|
35
35
|
*/
|
|
36
36
|
export function generateTypes(outFile, compiled) {
|
|
37
37
|
const lines = [];
|
|
38
|
+
const normalizeDocLines = (text) => String(text)
|
|
39
|
+
.replace(/\r\n?/g, "\n")
|
|
40
|
+
.split("\n")
|
|
41
|
+
.map(line => line.trim())
|
|
42
|
+
.filter(Boolean)
|
|
43
|
+
.map(line => line.replace(/\*\//g, "*\\/"));
|
|
44
|
+
const emitDocBlock = (indent, docText, xsdTag) => {
|
|
45
|
+
if (!docText && !xsdTag) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
lines.push(`${indent}/**`);
|
|
49
|
+
if (docText) {
|
|
50
|
+
for (const line of normalizeDocLines(docText)) {
|
|
51
|
+
lines.push(`${indent} * ${line}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (xsdTag) {
|
|
55
|
+
if (docText) {
|
|
56
|
+
lines.push(`${indent} *`);
|
|
57
|
+
}
|
|
58
|
+
lines.push(`${indent} * @xsd ${xsdTag}`);
|
|
59
|
+
}
|
|
60
|
+
lines.push(`${indent} */`);
|
|
61
|
+
};
|
|
38
62
|
// Convenience lookups
|
|
39
63
|
const typeNames = new Set(compiled.types.map((t) => t.name));
|
|
40
64
|
const isValidIdent = (name) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name);
|
|
@@ -45,8 +69,14 @@ export function generateTypes(outFile, compiled) {
|
|
|
45
69
|
// sort aliases by name to ensure consistent order
|
|
46
70
|
compiled.aliases.sort((a, b) => a.name.localeCompare(b.name));
|
|
47
71
|
for (const a of compiled.aliases) {
|
|
48
|
-
|
|
49
|
-
|
|
72
|
+
if (a.doc) {
|
|
73
|
+
emitDocBlock("", a.doc, a.jsdoc);
|
|
74
|
+
lines.push(`export type ${a.name} = ${a.tsType};`);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
const ann = a.jsdoc ? `/** @xsd ${a.jsdoc} */\n` : "";
|
|
78
|
+
lines.push(`${ann}export type ${a.name} = ${a.tsType};`);
|
|
79
|
+
}
|
|
50
80
|
lines.push("");
|
|
51
81
|
}
|
|
52
82
|
//
|
|
@@ -64,6 +94,9 @@ export function generateTypes(outFile, compiled) {
|
|
|
64
94
|
typeNames.has(e.tsType));
|
|
65
95
|
const isSimpleContentExtension = !complexBase && (t.elems?.length || 0) === 1 && valueElems.length === 1;
|
|
66
96
|
const baseName = complexBase ?? (isSimpleContentExtension ? valueElems[0].tsType : undefined);
|
|
97
|
+
if (t.doc) {
|
|
98
|
+
emitDocBlock("", t.doc);
|
|
99
|
+
}
|
|
67
100
|
// Header: extend base type if applicable
|
|
68
101
|
if (baseName) {
|
|
69
102
|
lines.push(`export interface ${t.name} extends ${baseName} {`);
|
|
@@ -108,9 +141,14 @@ export function generateTypes(outFile, compiled) {
|
|
|
108
141
|
type: a.declaredType,
|
|
109
142
|
use: a.use || "optional",
|
|
110
143
|
};
|
|
111
|
-
const ann = ` /** @xsd ${JSON.stringify(annObj)} */`;
|
|
112
144
|
lines.push("");
|
|
113
|
-
|
|
145
|
+
if (a.doc) {
|
|
146
|
+
emitDocBlock(" ", a.doc, JSON.stringify(annObj));
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
const ann = ` /** @xsd ${JSON.stringify(annObj)} */`;
|
|
150
|
+
lines.push(ann);
|
|
151
|
+
}
|
|
114
152
|
lines.push(` ${emitPropName(a.name)}${opt}: ${a.tsType};`);
|
|
115
153
|
}
|
|
116
154
|
//
|
|
@@ -153,9 +191,14 @@ export function generateTypes(outFile, compiled) {
|
|
|
153
191
|
if ((e.name === "$value") && (1 < elementsToEmit.length)) {
|
|
154
192
|
lines.push("");
|
|
155
193
|
}
|
|
156
|
-
const ann = ` /** @xsd ${JSON.stringify(annObj)} */`;
|
|
157
194
|
lines.push("");
|
|
158
|
-
|
|
195
|
+
if (e.doc) {
|
|
196
|
+
emitDocBlock(" ", e.doc, JSON.stringify(annObj));
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
const ann = ` /** @xsd ${JSON.stringify(annObj)} */`;
|
|
200
|
+
lines.push(ann);
|
|
201
|
+
}
|
|
159
202
|
lines.push(` ${emitPropName(e.name)}${opt}: ${e.tsType}${arr};`);
|
|
160
203
|
}
|
|
161
204
|
lines.push("}");
|
|
@@ -43,6 +43,7 @@ export type CompiledType = {
|
|
|
43
43
|
tsType: string;
|
|
44
44
|
use?: "required" | "optional";
|
|
45
45
|
declaredType: string;
|
|
46
|
+
doc?: string;
|
|
46
47
|
}>;
|
|
47
48
|
elems: Array<{
|
|
48
49
|
name: string;
|
|
@@ -51,14 +52,17 @@ export type CompiledType = {
|
|
|
51
52
|
max: number | "unbounded";
|
|
52
53
|
nillable?: boolean;
|
|
53
54
|
declaredType: string;
|
|
55
|
+
doc?: string;
|
|
54
56
|
}>;
|
|
55
57
|
jsdoc?: string;
|
|
58
|
+
doc?: string;
|
|
56
59
|
base?: string;
|
|
57
60
|
localAttrs?: Array<{
|
|
58
61
|
name: string;
|
|
59
62
|
tsType: string;
|
|
60
63
|
use?: "required" | "optional";
|
|
61
64
|
declaredType: string;
|
|
65
|
+
doc?: string;
|
|
62
66
|
}>;
|
|
63
67
|
localElems?: Array<{
|
|
64
68
|
name: string;
|
|
@@ -67,6 +71,7 @@ export type CompiledType = {
|
|
|
67
71
|
max: number | "unbounded";
|
|
68
72
|
nillable?: boolean;
|
|
69
73
|
declaredType: string;
|
|
74
|
+
doc?: string;
|
|
70
75
|
}>;
|
|
71
76
|
};
|
|
72
77
|
/**
|
|
@@ -85,6 +90,7 @@ export type CompiledAlias = {
|
|
|
85
90
|
tsType: string;
|
|
86
91
|
declared: string;
|
|
87
92
|
jsdoc?: string;
|
|
93
|
+
doc?: string;
|
|
88
94
|
};
|
|
89
95
|
/**
|
|
90
96
|
* Complete compiled catalog with all types, aliases, operations and metadata
|
|
@@ -105,6 +111,7 @@ export type CompiledCatalog = {
|
|
|
105
111
|
aliases: CompiledAlias[];
|
|
106
112
|
meta: {
|
|
107
113
|
attrSpec: Record<string, string[]>;
|
|
114
|
+
attrType: Record<string, Record<string, string>>;
|
|
108
115
|
childType: Record<string, Record<string, string>>;
|
|
109
116
|
propMeta: Record<string, Record<string, any>>;
|
|
110
117
|
};
|
|
@@ -116,6 +123,7 @@ export type CompiledCatalog = {
|
|
|
116
123
|
security?: string[];
|
|
117
124
|
inputTypeName?: string;
|
|
118
125
|
outputTypeName?: string;
|
|
126
|
+
doc?: string;
|
|
119
127
|
}>;
|
|
120
128
|
wsdlTargetNS: string;
|
|
121
129
|
wsdlUri: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemaCompiler.d.ts","sourceRoot":"","sources":["../../src/compiler/schemaCompiler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,yBAAyB,CAAC;AAKzD;;;;;;GAMG;AACH,MAAM,MAAM,KAAK,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAElD;;;;;;;;;;;;GAYG;AACH,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;
|
|
1
|
+
{"version":3,"file":"schemaCompiler.d.ts","sourceRoot":"","sources":["../../src/compiler/schemaCompiler.ts"],"names":[],"mappings":"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"}
|
|
@@ -92,6 +92,57 @@ function collectSecurityFromPolicyNodes(policyNodes) {
|
|
|
92
92
|
visit(p);
|
|
93
93
|
return Array.from(found);
|
|
94
94
|
}
|
|
95
|
+
function extractNodeText(node) {
|
|
96
|
+
if (node == null) {
|
|
97
|
+
return "";
|
|
98
|
+
}
|
|
99
|
+
if (typeof node === "string" || typeof node === "number" || typeof node === "boolean") {
|
|
100
|
+
return String(node);
|
|
101
|
+
}
|
|
102
|
+
if (Array.isArray(node)) {
|
|
103
|
+
return node.map(extractNodeText).join(" ");
|
|
104
|
+
}
|
|
105
|
+
if (typeof node === "object") {
|
|
106
|
+
const parts = [];
|
|
107
|
+
if (node["#text"] != null) {
|
|
108
|
+
parts.push(extractNodeText(node["#text"]));
|
|
109
|
+
}
|
|
110
|
+
for (const [k, v] of Object.entries(node)) {
|
|
111
|
+
if ("#text" === k || k.startsWith("@_")) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
parts.push(extractNodeText(v));
|
|
115
|
+
}
|
|
116
|
+
return parts.join(" ");
|
|
117
|
+
}
|
|
118
|
+
return "";
|
|
119
|
+
}
|
|
120
|
+
function normalizeDocText(text) {
|
|
121
|
+
const compact = text
|
|
122
|
+
.replace(/\r\n?/g, "\n")
|
|
123
|
+
.split("\n")
|
|
124
|
+
.map(line => line.trim())
|
|
125
|
+
.filter(Boolean)
|
|
126
|
+
.join(" ")
|
|
127
|
+
.replace(/\s+/g, " ")
|
|
128
|
+
.trim();
|
|
129
|
+
return compact || undefined;
|
|
130
|
+
}
|
|
131
|
+
function extractDirectDocumentation(node) {
|
|
132
|
+
const docs = getChildrenWithLocalName(node, "documentation");
|
|
133
|
+
const merged = docs
|
|
134
|
+
.map(extractNodeText)
|
|
135
|
+
.join(" ");
|
|
136
|
+
return normalizeDocText(merged);
|
|
137
|
+
}
|
|
138
|
+
function extractAnnotationDocumentation(node) {
|
|
139
|
+
const annotations = getChildrenWithLocalName(node, "annotation");
|
|
140
|
+
const docs = annotations.flatMap(a => getChildrenWithLocalName(a, "documentation"));
|
|
141
|
+
const merged = docs
|
|
142
|
+
.map(extractNodeText)
|
|
143
|
+
.join(" ");
|
|
144
|
+
return normalizeDocText(merged);
|
|
145
|
+
}
|
|
95
146
|
/**
|
|
96
147
|
* Compile a WSDL catalog into an internal representation (CompiledCatalog).
|
|
97
148
|
* Steps:
|
|
@@ -136,6 +187,7 @@ export function compileCatalog(cat, options) {
|
|
|
136
187
|
const inProgress = new Set();
|
|
137
188
|
// meta accumulators
|
|
138
189
|
const attrSpec = {};
|
|
190
|
+
const attrType = {};
|
|
139
191
|
const childType = {};
|
|
140
192
|
const propMeta = {};
|
|
141
193
|
/** Compile a simpleType node to TS */
|
|
@@ -171,7 +223,14 @@ export function compileCatalog(cat, options) {
|
|
|
171
223
|
return present;
|
|
172
224
|
}
|
|
173
225
|
const { tsType, declared, jsdoc } = compileSimpleTypeNode(sNode, schemaNS, prefixes);
|
|
174
|
-
const alias = {
|
|
226
|
+
const alias = {
|
|
227
|
+
name: pascal(name),
|
|
228
|
+
ns: schemaNS,
|
|
229
|
+
tsType,
|
|
230
|
+
declared,
|
|
231
|
+
jsdoc,
|
|
232
|
+
doc: extractAnnotationDocumentation(sNode),
|
|
233
|
+
};
|
|
175
234
|
aliasMap.set(key, alias);
|
|
176
235
|
return alias;
|
|
177
236
|
}
|
|
@@ -220,6 +279,7 @@ export function compileCatalog(cat, options) {
|
|
|
220
279
|
}
|
|
221
280
|
inProgress.add(rawKey);
|
|
222
281
|
const outName = pascal(name);
|
|
282
|
+
const typeDoc = extractAnnotationDocumentation(cnode);
|
|
223
283
|
const key = `${schemaNS}|${outName}`;
|
|
224
284
|
// hoisted helpers for merging and collecting
|
|
225
285
|
const mergeAttrs = (into, list) => {
|
|
@@ -266,7 +326,8 @@ export function compileCatalog(cat, options) {
|
|
|
266
326
|
name: an,
|
|
267
327
|
tsType: r.tsType,
|
|
268
328
|
use: a["@_use"] === "required" ? "required" : "optional",
|
|
269
|
-
declaredType: r.declared
|
|
329
|
+
declaredType: r.declared,
|
|
330
|
+
doc: extractAnnotationDocumentation(a),
|
|
270
331
|
});
|
|
271
332
|
}
|
|
272
333
|
else {
|
|
@@ -278,7 +339,8 @@ export function compileCatalog(cat, options) {
|
|
|
278
339
|
name: an,
|
|
279
340
|
tsType: r.tsType,
|
|
280
341
|
use: a["@_use"] === "required" ? "required" : "optional",
|
|
281
|
-
declaredType: r.declared
|
|
342
|
+
declaredType: r.declared,
|
|
343
|
+
doc: extractAnnotationDocumentation(a),
|
|
282
344
|
});
|
|
283
345
|
}
|
|
284
346
|
}
|
|
@@ -309,18 +371,35 @@ export function compileCatalog(cat, options) {
|
|
|
309
371
|
min,
|
|
310
372
|
max,
|
|
311
373
|
nillable,
|
|
312
|
-
declaredType: `{${schemaNS}}${rec.name}
|
|
374
|
+
declaredType: `{${schemaNS}}${rec.name}`,
|
|
375
|
+
doc: extractAnnotationDocumentation(e),
|
|
313
376
|
});
|
|
314
377
|
}
|
|
315
378
|
else if (inlineSimple) {
|
|
316
379
|
const r = compileSimpleTypeNode(inlineSimple, schemaNS, prefixes);
|
|
317
|
-
out.push({
|
|
380
|
+
out.push({
|
|
381
|
+
name: propName || nameOrRef,
|
|
382
|
+
tsType: r.tsType,
|
|
383
|
+
min,
|
|
384
|
+
max,
|
|
385
|
+
nillable,
|
|
386
|
+
declaredType: r.declared,
|
|
387
|
+
doc: extractAnnotationDocumentation(e),
|
|
388
|
+
});
|
|
318
389
|
}
|
|
319
390
|
else {
|
|
320
391
|
const t = e["@_type"] || e["@_ref"];
|
|
321
392
|
const q = t ? resolveQName(t, schemaNS, prefixes) : { ns: XS, local: "string" };
|
|
322
393
|
const r = resolveTypeRef(q, schemaNS, prefixes);
|
|
323
|
-
out.push({
|
|
394
|
+
out.push({
|
|
395
|
+
name: propName || nameOrRef,
|
|
396
|
+
tsType: r.tsType,
|
|
397
|
+
min,
|
|
398
|
+
max,
|
|
399
|
+
nillable,
|
|
400
|
+
declaredType: r.declared,
|
|
401
|
+
doc: extractAnnotationDocumentation(e),
|
|
402
|
+
});
|
|
324
403
|
}
|
|
325
404
|
}
|
|
326
405
|
// recurse into nested compositor groups
|
|
@@ -340,6 +419,9 @@ export function compileCatalog(cat, options) {
|
|
|
340
419
|
const newElems = collectParticles(outName, cnode);
|
|
341
420
|
mergeAttrs(present.attrs, newAttrs);
|
|
342
421
|
mergeElems(present.elems, newElems);
|
|
422
|
+
if (!present.doc && typeDoc) {
|
|
423
|
+
present.doc = typeDoc;
|
|
424
|
+
}
|
|
343
425
|
// Remove from inProgress since we're done with this cycle
|
|
344
426
|
inProgress.delete(rawKey);
|
|
345
427
|
return present;
|
|
@@ -378,6 +460,7 @@ export function compileCatalog(cat, options) {
|
|
|
378
460
|
ns: schemaNS,
|
|
379
461
|
attrs,
|
|
380
462
|
elems,
|
|
463
|
+
doc: typeDoc,
|
|
381
464
|
base: baseName,
|
|
382
465
|
localAttrs: locals,
|
|
383
466
|
localElems
|
|
@@ -408,7 +491,7 @@ export function compileCatalog(cat, options) {
|
|
|
408
491
|
declaredType: r.declared,
|
|
409
492
|
}]);
|
|
410
493
|
mergeAttrs(attrs, collectAttributes(scNode));
|
|
411
|
-
const result = { name: outName, ns: schemaNS, attrs, elems };
|
|
494
|
+
const result = { name: outName, ns: schemaNS, attrs, elems, doc: typeDoc };
|
|
412
495
|
compiledMap.set(key, result);
|
|
413
496
|
inProgress.delete(rawKey);
|
|
414
497
|
return result;
|
|
@@ -423,7 +506,7 @@ export function compileCatalog(cat, options) {
|
|
|
423
506
|
// Attributes + particles
|
|
424
507
|
mergeAttrs(attrs, collectAttributes(cnode));
|
|
425
508
|
mergeElems(elems, collectParticles(outName, cnode));
|
|
426
|
-
const result = { name: outName, ns: schemaNS, attrs, elems };
|
|
509
|
+
const result = { name: outName, ns: schemaNS, attrs, elems, doc: typeDoc };
|
|
427
510
|
compiledMap.set(key, result);
|
|
428
511
|
inProgress.delete(rawKey);
|
|
429
512
|
return result;
|
|
@@ -431,6 +514,7 @@ export function compileCatalog(cat, options) {
|
|
|
431
514
|
// Helper: compile a global element into a surface type (wrapper)
|
|
432
515
|
function compileElementAsType(name, enode, schemaNS, prefixes) {
|
|
433
516
|
const outName = pascal(name);
|
|
517
|
+
const elementDoc = extractAnnotationDocumentation(enode);
|
|
434
518
|
const key = `${schemaNS}|${outName}`;
|
|
435
519
|
const present = compiledMap.get(key);
|
|
436
520
|
if (present)
|
|
@@ -447,6 +531,7 @@ export function compileCatalog(cat, options) {
|
|
|
447
531
|
ns: schemaNS,
|
|
448
532
|
attrs: [],
|
|
449
533
|
elems: [{ name: "$value", tsType: r.tsType, min: 0, max: 1, nillable: false, declaredType: r.declared }],
|
|
534
|
+
doc: elementDoc,
|
|
450
535
|
};
|
|
451
536
|
compiledMap.set(key, t);
|
|
452
537
|
return t;
|
|
@@ -469,6 +554,7 @@ export function compileCatalog(cat, options) {
|
|
|
469
554
|
nillable: false,
|
|
470
555
|
declaredType: label
|
|
471
556
|
}],
|
|
557
|
+
doc: elementDoc,
|
|
472
558
|
};
|
|
473
559
|
compiledMap.set(key, t);
|
|
474
560
|
return t;
|
|
@@ -484,10 +570,13 @@ export function compileCatalog(cat, options) {
|
|
|
484
570
|
const existingAlias = aliasMap.get(aliasKey);
|
|
485
571
|
const declared = `{${base.ns}}${base.name}`;
|
|
486
572
|
if (!existingAlias) {
|
|
487
|
-
aliasMap.set(aliasKey, { name: outName, ns: schemaNS, tsType: base.name, declared });
|
|
573
|
+
aliasMap.set(aliasKey, { name: outName, ns: schemaNS, tsType: base.name, declared, doc: elementDoc });
|
|
488
574
|
}
|
|
489
575
|
else {
|
|
490
576
|
// if an alias exists but points elsewhere, keep the first one (stable) and ignore
|
|
577
|
+
if (!existingAlias.doc && elementDoc) {
|
|
578
|
+
existingAlias.doc = elementDoc;
|
|
579
|
+
}
|
|
491
580
|
}
|
|
492
581
|
}
|
|
493
582
|
// Return base so callers have a CompiledType, but do not duplicate in compiledMap for wrapper
|
|
@@ -508,13 +597,14 @@ export function compileCatalog(cat, options) {
|
|
|
508
597
|
nillable: false,
|
|
509
598
|
declaredType: `{${a.ns}}${q.local}`
|
|
510
599
|
}],
|
|
600
|
+
doc: elementDoc,
|
|
511
601
|
};
|
|
512
602
|
compiledMap.set(key, t);
|
|
513
603
|
return t;
|
|
514
604
|
}
|
|
515
605
|
}
|
|
516
606
|
// default empty wrapper
|
|
517
|
-
const t = { name: outName, ns: schemaNS, attrs: [], elems: [] };
|
|
607
|
+
const t = { name: outName, ns: schemaNS, attrs: [], elems: [], doc: elementDoc };
|
|
518
608
|
compiledMap.set(key, t);
|
|
519
609
|
return t;
|
|
520
610
|
}
|
|
@@ -536,9 +626,28 @@ export function compileCatalog(cat, options) {
|
|
|
536
626
|
// emit lists
|
|
537
627
|
const typesList = Array.from(compiledMap.values());
|
|
538
628
|
const aliasList = Array.from(aliasMap.values());
|
|
629
|
+
// Build alias resolution map for simple type aliases (e.g. YesNoType -> '"Yes" | "No"')
|
|
630
|
+
const aliasResolve = new Map();
|
|
631
|
+
for (const a of aliasList) {
|
|
632
|
+
if (a.tsType && a.tsType !== a.name) {
|
|
633
|
+
aliasResolve.set(a.name, a.tsType);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
539
636
|
// meta
|
|
540
637
|
for (const t of typesList) {
|
|
541
638
|
attrSpec[t.name] = (t.attrs || []).map(a => a.name);
|
|
639
|
+
const attrMap = {};
|
|
640
|
+
for (const a of t.attrs || []) {
|
|
641
|
+
let tsType = typeof a.tsType === "string" ? a.tsType : "string";
|
|
642
|
+
// Resolve alias names to their underlying TS types for mock data generation
|
|
643
|
+
if (aliasResolve.has(tsType)) {
|
|
644
|
+
tsType = aliasResolve.get(tsType);
|
|
645
|
+
}
|
|
646
|
+
attrMap[a.name] = tsType;
|
|
647
|
+
}
|
|
648
|
+
if (Object.keys(attrMap).length > 0) {
|
|
649
|
+
attrType[t.name] = attrMap;
|
|
650
|
+
}
|
|
542
651
|
const child = {};
|
|
543
652
|
const meta = {};
|
|
544
653
|
for (const e of t.elems || []) {
|
|
@@ -561,6 +670,9 @@ export function compileCatalog(cat, options) {
|
|
|
561
670
|
childType[a.name] = childType[a.tsType];
|
|
562
671
|
propMeta[a.name] = propMeta[a.tsType];
|
|
563
672
|
attrSpec[a.name] = attrSpec[a.tsType];
|
|
673
|
+
if (a.tsType in attrType) {
|
|
674
|
+
attrType[a.name] = attrType[a.tsType];
|
|
675
|
+
}
|
|
564
676
|
}
|
|
565
677
|
}
|
|
566
678
|
}
|
|
@@ -629,10 +741,11 @@ export function compileCatalog(cat, options) {
|
|
|
629
741
|
const outMsg = findMessage(getFirstWithLocalName(po, "output")?.["@_message"]);
|
|
630
742
|
const inputElement = elementOfMessage(inMsg);
|
|
631
743
|
const outputElement = elementOfMessage(outMsg);
|
|
744
|
+
const doc = extractDirectDocumentation(po);
|
|
632
745
|
// Derive TypeScript type names from element local names
|
|
633
746
|
const inputTypeName = inputElement ? pascal(inputElement.local) : undefined;
|
|
634
747
|
const outputTypeName = outputElement ? pascal(outputElement.local) : undefined;
|
|
635
|
-
return { name, soapAction: bOps.get(name) || "", inputElement, outputElement, inputTypeName, outputTypeName };
|
|
748
|
+
return { name, soapAction: bOps.get(name) || "", inputElement, outputElement, inputTypeName, outputTypeName, doc };
|
|
636
749
|
})
|
|
637
750
|
.filter((x) => x != null));
|
|
638
751
|
// --- WS-Policy: scan for security requirements (inline policies only) ---
|
|
@@ -664,7 +777,7 @@ export function compileCatalog(cat, options) {
|
|
|
664
777
|
options: options,
|
|
665
778
|
types: typesList,
|
|
666
779
|
aliases: aliasList,
|
|
667
|
-
meta: { attrSpec, childType, propMeta },
|
|
780
|
+
meta: { attrSpec, attrType, childType, propMeta },
|
|
668
781
|
operations: ops,
|
|
669
782
|
wsdlTargetNS: defs?.["@_targetNamespace"] || "",
|
|
670
783
|
serviceName,
|
|
@@ -36,6 +36,8 @@ export interface OperationMetadata {
|
|
|
36
36
|
clientMethodName?: string;
|
|
37
37
|
requestTypeName?: string;
|
|
38
38
|
responseTypeName?: string;
|
|
39
|
+
/** When true, response schema is omitted from route registration to avoid fast-json-stringify stack overflow on deeply nested $ref graphs */
|
|
40
|
+
skipResponseSchema?: boolean;
|
|
39
41
|
}
|
|
40
42
|
/**
|
|
41
43
|
* Emits Fastify-compatible operation schema files
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../../src/gateway/generators.ts"],"names":[],"mappings":"AAcA,OAAO,EAAC,KAAK,UAAU,EAAE,KAAK,eAAe,
|
|
1
|
+
{"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../../src/gateway/generators.ts"],"names":[],"mappings":"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"}
|