@techspokes/typescript-wsdl-client 1.1.8 → 1.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.
Files changed (85) hide show
  1. package/README.md +22 -3
  2. package/dist/checkedPlanning.js +27 -4
  3. package/dist/cli.js +17 -1
  4. package/dist/client/checkedDirectRuntime.d.ts +11 -1
  5. package/dist/client/checkedDirectRuntime.js +19 -2
  6. package/dist/client/directClientRuntime.d.ts +18 -1
  7. package/dist/client/directClientRuntime.js +15 -3
  8. package/dist/client/directClientVersion.d.ts +2 -0
  9. package/dist/client/directClientVersion.js +2 -0
  10. package/dist/client/generateClient.js +72 -16
  11. package/dist/client/generateDirectClient.js +14 -9
  12. package/dist/client/generateOperations.js +30 -11
  13. package/dist/client/generateUtils.js +5 -1
  14. package/dist/compiler/canonicalGraph.d.ts +4 -15
  15. package/dist/compiler/canonicalGraph.js +1 -8
  16. package/dist/compiler/componentRecordProjection.d.ts +3 -0
  17. package/dist/compiler/componentRecordProjection.js +10 -0
  18. package/dist/compiler/declarationIdentity.d.ts +22 -0
  19. package/dist/compiler/declarationIdentity.js +9 -0
  20. package/dist/compiler/directCodec.d.ts +22 -2
  21. package/dist/compiler/directCodec.js +40 -7
  22. package/dist/compiler/directOperation.d.ts +28 -5
  23. package/dist/compiler/directOperation.js +84 -14
  24. package/dist/compiler/directSoap.d.ts +40 -10
  25. package/dist/compiler/directSoap.js +151 -18
  26. package/dist/compiler/directSoapSource.js +3 -2
  27. package/dist/compiler/directSourceCapsule.js +69 -4
  28. package/dist/compiler/directStructure.js +6 -2
  29. package/dist/compiler/directStructurePlan.d.ts +10 -1
  30. package/dist/compiler/directStructurePlan.js +27 -7
  31. package/dist/compiler/directValues.d.ts +15 -3
  32. package/dist/compiler/directValues.js +20 -4
  33. package/dist/compiler/legacyDeclarations.d.ts +26 -0
  34. package/dist/compiler/legacyDeclarations.js +144 -0
  35. package/dist/compiler/projectionScalar.d.ts +18 -1
  36. package/dist/compiler/projectionScalar.js +47 -13
  37. package/dist/compiler/rpcStringValues.d.ts +30 -0
  38. package/dist/compiler/rpcStringValues.js +196 -0
  39. package/dist/compiler/rpcTypedValues.d.ts +48 -0
  40. package/dist/compiler/rpcTypedValues.js +190 -0
  41. package/dist/compiler/schemaCompiler.js +44 -109
  42. package/dist/compiler/semanticCatalog.d.ts +2 -2
  43. package/dist/compiler/soapHeaders.d.ts +10 -4
  44. package/dist/compiler/soapHeaders.js +28 -9
  45. package/dist/gateway/generateCheckedGateway.js +26 -6
  46. package/dist/gateway/generateComposedGateway.d.ts +16 -0
  47. package/dist/gateway/generateComposedGateway.js +65 -0
  48. package/dist/gateway/generateGateway.js +1 -0
  49. package/dist/gateway/generators.js +19 -4
  50. package/dist/gateway/helpers.d.ts +1 -0
  51. package/dist/gateway/helpers.js +15 -0
  52. package/dist/generation/componentShape.js +25 -1
  53. package/dist/index.d.ts +5 -1
  54. package/dist/index.js +3 -1
  55. package/dist/loader/orderedSyntax.d.ts +4 -0
  56. package/dist/loader/orderedSyntax.js +18 -4
  57. package/dist/multiServicePipeline.d.ts +41 -0
  58. package/dist/multiServicePipeline.js +287 -0
  59. package/dist/openapi/composeOpenAPI.d.ts +29 -0
  60. package/dist/openapi/composeOpenAPI.js +322 -0
  61. package/dist/pipeline.d.ts +1 -1
  62. package/dist/pipeline.js +2 -0
  63. package/docs/agent-skill.md +10 -1
  64. package/docs/api-reference.md +127 -9
  65. package/docs/checked-gateway.md +10 -0
  66. package/docs/checked-generation.md +11 -5
  67. package/docs/cli-reference.md +25 -5
  68. package/docs/concepts.md +4 -5
  69. package/docs/configuration.md +10 -3
  70. package/docs/corpus.md +1 -1
  71. package/docs/gateway-guide.md +104 -27
  72. package/docs/generated-code.md +12 -6
  73. package/docs/migration-playbook.md +4 -0
  74. package/docs/migration.md +134 -6
  75. package/docs/output-anatomy.md +20 -17
  76. package/docs/production.md +7 -5
  77. package/docs/start-here.md +12 -2
  78. package/docs/supported-patterns.md +23 -0
  79. package/docs/testing.md +2 -0
  80. package/docs/troubleshooting.md +3 -1
  81. package/llms.txt +9 -1
  82. package/package.json +2 -2
  83. package/src/runtime/clientStreamMethods.tpl.txt +156 -148
  84. package/src/runtime/operationsStreamHelper.tpl.txt +6 -6
  85. package/src/runtime/streamXml.ts +48 -20
@@ -29,6 +29,8 @@ function kernel(context) {
29
29
  const core = scalarSchemaAssessment(c);
30
30
  const descriptions = new Map();
31
31
  const references = new Map();
32
+ const keyFor = (declaration, reference) => JSON.stringify([declaration.id,
33
+ reference.kind, reference.kind === 'local' ? reference.target : [reference.name.namespace, reference.name.local]]);
32
34
  const owner = (declaration) => {
33
35
  if (types.isProxy(declaration))
34
36
  throw new TypeError('Expected exact native scalar declaration');
@@ -40,13 +42,14 @@ function kernel(context) {
40
42
  throw new TypeError('Expected exact native scalar declaration');
41
43
  return declaration;
42
44
  };
43
- const describe = (declaration) => {
45
+ const describe = (declaration, selected) => {
44
46
  owner(declaration);
45
- const cached = descriptions.get(declaration.id);
47
+ const key = keyFor(declaration, selected);
48
+ const cached = descriptions.get(key);
46
49
  if (cached)
47
50
  return cached;
48
- let reference = declaration.type;
49
- const type = context.resolve(declaration.type);
51
+ let reference = selected;
52
+ const type = context.resolve(selected);
50
53
  if (type.kind === 'found' && type.node.kind === 'complexType') {
51
54
  const content = deriveActualComplexContent(context, type.node.id);
52
55
  if (content.kind !== 'checked' || content.view.content.kind !== 'simple')
@@ -95,8 +98,8 @@ function kernel(context) {
95
98
  const retainLexical = union || plan.layers.some(layer => layer.patterns.length > 0);
96
99
  const result = Object.freeze({ kind: 'projection-scalar-type', builtin: Object.freeze({ namespace: XSD_NAMESPACE, local }),
97
100
  ...(retainLexical ? { retainLexical: true } : {}), ...(item ? { list: item } : {}) });
98
- descriptions.set(declaration.id, result);
99
- references.set(declaration.id, reference);
101
+ descriptions.set(key, result);
102
+ references.set(key, reference);
100
103
  return result;
101
104
  };
102
105
  const failure = (error, operand) => {
@@ -107,14 +110,18 @@ function kernel(context) {
107
110
  return Object.freeze({ kind: operand && error.category === 'invalid-schema' ? 'scalar-invalid' : 'unavailable', rule: error.rule });
108
111
  };
109
112
  return {
110
- describe(declaration, cooperative) {
113
+ declarationType(declaration) {
114
+ owner(declaration);
115
+ return declaration.type;
116
+ },
117
+ describe(declaration, reference, cooperative) {
111
118
  const previous = callerCheck;
112
119
  callerCheck = cooperative;
113
120
  interrupted = false;
114
121
  try {
115
122
  return context.budget.guard(() => {
116
123
  try {
117
- return describe(declaration);
124
+ return describe(declaration, reference);
118
125
  }
119
126
  catch (error) {
120
127
  return failure(error, false);
@@ -127,7 +134,7 @@ function kernel(context) {
127
134
  callerCheck = previous;
128
135
  }
129
136
  },
130
- assess(declaration, supplied, cooperative) {
137
+ assess(declaration, reference, supplied, cooperative) {
131
138
  const previous = callerCheck;
132
139
  callerCheck = cooperative;
133
140
  interrupted = false;
@@ -135,7 +142,7 @@ function kernel(context) {
135
142
  return context.budget.guard(() => {
136
143
  let operand = false;
137
144
  try {
138
- const description = describe(declaration);
145
+ const description = describe(declaration, reference);
139
146
  if (description.kind !== 'projection-scalar-type')
140
147
  return description;
141
148
  const input = context.budget.freeze(context.budget.snapshot(supplied));
@@ -143,7 +150,7 @@ function kernel(context) {
143
150
  const lexical = { value: input.value, context: { ...declaration.context,
144
151
  namespaces: input.context.namespaces, source: input.context.source, baseUri: input.context.source.uri } };
145
152
  operand = true;
146
- const value = core.assess(references.get(declaration.id), lexical, declaration);
153
+ const value = core.assess(references.get(keyFor(declaration, reference)), lexical, declaration);
147
154
  context.budget.chargeWork(16);
148
155
  return Object.freeze({ kind: 'projection-scalar-operand', operand: value });
149
156
  }
@@ -175,10 +182,37 @@ function get(context) {
175
182
  /** Native declaration lookup and source-type formation precede any payload calculation. */
176
183
  export function describeProjectionScalar(context, declaration, check) {
177
184
  assertSemanticContext(context);
178
- return context.budget.guard(() => get(context).describe(declaration, check));
185
+ return context.budget.guard(() => {
186
+ const scalar = get(context);
187
+ return scalar.describe(declaration, scalar.declarationType(declaration), check);
188
+ });
179
189
  }
180
190
  /** A successful calculation is payload-only data; it grants no schema, operation or portable artifact authority. */
181
191
  export function assessProjectionScalarOperand(context, declaration, lexical, check) {
182
192
  assertSemanticContext(context);
183
- return context.budget.guard(() => get(context).assess(declaration, lexical, check));
193
+ return context.budget.guard(() => {
194
+ const scalar = get(context);
195
+ return scalar.assess(declaration, scalar.declarationType(declaration), lexical, check);
196
+ });
197
+ }
198
+ /** Describe a source-owned type without inventing an element declaration.
199
+ * @param context Native source context.
200
+ * @param owner Exact graph node owning the reference.
201
+ * @param reference Source-selected type reference.
202
+ * @param check Cooperative budget/cancellation checkpoint.
203
+ * @returns The existing native scalar description or explicit refusal.
204
+ */
205
+ export function describeProjectionType(context, owner, reference, check) {
206
+ return context.budget.guard(() => get(context).describe(owner, reference, check));
207
+ }
208
+ /** Assess a typed value through the same native restrictions as element values.
209
+ * @param context Native source context.
210
+ * @param owner Exact source node owning the reference.
211
+ * @param reference Source-selected type reference.
212
+ * @param lexical Observed lexical value and namespace context.
213
+ * @param check Cooperative checkpoint.
214
+ * @returns Native datatype operand or explicit refusal.
215
+ */
216
+ export function assessProjectionTypeOperand(context, owner, reference, lexical, check) {
217
+ return context.budget.guard(() => get(context).assess(owner, reference, lexical, check));
184
218
  }
@@ -0,0 +1,30 @@
1
+ import type { SyntaxElement } from '../loader/orderedSyntax.js';
2
+ import type { RpcMessageRoot } from './directOperation.js';
3
+ import type { SemanticBudget } from './semanticBudget.js';
4
+ type Fail = (kind: 'value-invalid' | 'unsupported' | 'mismatch', rule: string, node?: SyntaxElement) => never;
5
+ type Control = {
6
+ budget: SemanticBudget;
7
+ check(): void;
8
+ fail: Fail;
9
+ };
10
+ /** Build canonical inline string parameters in source declaration order.
11
+ * @param root Source-owned typed parameters.
12
+ * @param value Data-only application object.
13
+ * @param control Shared invocation ownership and work budget.
14
+ * @returns A generated RPC wrapper and preserved string values.
15
+ * @throws Through the supplied failure callback for invalid application values.
16
+ */
17
+ export declare function expandRpcStrings(root: RpcMessageRoot, value: unknown, control: Control): {
18
+ payload: SyntaxElement;
19
+ value: Readonly<Record<string, string>>;
20
+ };
21
+ /** Decode only the selected inline/local-reference string profile within one retained Body.
22
+ * @param root Source-owned typed parameters and body namespace.
23
+ * @param payload Observed RPC wrapper or observed SOAP Body.
24
+ * @param output Whether SOAP response local names are insignificant.
25
+ * @param control Shared native invocation budget and explicit failure callback.
26
+ * @returns Values keyed by the original WSDL part names.
27
+ * @throws Through the failure callback for malformed, ambiguous or unsupported encoded values.
28
+ */
29
+ export declare function readRpcStrings(root: RpcMessageRoot, payload: SyntaxElement, output: boolean, control: Control): Readonly<Record<string, string>>;
30
+ export {};
@@ -0,0 +1,196 @@
1
+ /** Bounded SOAP 1.1 RPC string serialization, without a second schema engine.
2
+ * @since 1.1.9
3
+ * @see https://www.w3.org/TR/2000/NOTE-SOAP-20000508/ Sections 5 and 7.
4
+ */
5
+ import { isXmlNCName, resolveLexicalQName, syntaxAttribute, syntaxElements, XSD_NAMESPACE, XML_NAMESPACE } from '../loader/orderedSyntax.js';
6
+ import { isXmlCharacters } from './directStructurePlan.js';
7
+ import { directDataOwnership } from './directExecutionPolicy.js';
8
+ const SOAP = 'http://schemas.xmlsoap.org/soap/envelope/';
9
+ const ENC = 'http://schemas.xmlsoap.org/soap/encoding/';
10
+ const XSI = 'http://www.w3.org/2001/XMLSchema-instance';
11
+ /** Build canonical inline string parameters in source declaration order.
12
+ * @param root Source-owned typed parameters.
13
+ * @param value Data-only application object.
14
+ * @param control Shared invocation ownership and work budget.
15
+ * @returns A generated RPC wrapper and preserved string values.
16
+ * @throws Through the supplied failure callback for invalid application values.
17
+ */
18
+ export function expandRpcStrings(root, value, control) {
19
+ const { budget, check, fail } = control;
20
+ let owned;
21
+ try {
22
+ owned = directDataOwnership(budget).snapshot(value, check);
23
+ }
24
+ catch (error) {
25
+ if (error instanceof TypeError)
26
+ return fail('value-invalid', 'rpc-data-object-required');
27
+ throw error;
28
+ }
29
+ if (!owned || typeof owned !== 'object' || Array.isArray(owned))
30
+ return fail('value-invalid', 'rpc-data-object-required');
31
+ const object = owned;
32
+ const keys = Object.keys(object), names = new Set(root.parts.map(part => { check(); return part.name; }));
33
+ budget.chargeWork(64 + keys.length * 32 + names.size * 32);
34
+ if (keys.length !== root.parts.length || keys.some(key => { check(); return !names.has(key); }))
35
+ return fail('value-invalid', 'rpc-required-string-parts');
36
+ const namespaces = { xml: XML_NAMESPACE, '': '', rpc: root.bodyNamespace, xsi: XSI, xsd: XSD_NAMESPACE, enc: ENC, soap: SOAP };
37
+ const attribute = (namespace, local, value) => ({ name: { namespace, local }, lexicalName: local, value });
38
+ const result = Object.create(null);
39
+ const children = root.parts.map(part => {
40
+ check();
41
+ const text = object[part.name];
42
+ if (typeof text !== 'string')
43
+ return fail('value-invalid', 'rpc-required-string-parts');
44
+ budget.chargeWork(64 + text.length * 8);
45
+ if (!isXmlCharacters(text))
46
+ return fail('value-invalid', 'rpc-string-xml-characters');
47
+ result[part.name] = text;
48
+ return { kind: 'element', name: { namespace: '', local: part.name }, lexicalName: part.name, namespaces, baseUri: root.source.uri,
49
+ attributes: [attribute(XSI, 'type', 'xsd:string')], children: [{ kind: 'text', value: text, source: root.source }], source: root.source };
50
+ });
51
+ return { payload: { kind: 'element', name: root.wrapper, lexicalName: 'rpc:' + root.wrapper.local, namespaces,
52
+ baseUri: root.source.uri, attributes: [attribute(SOAP, 'encodingStyle', ENC)], children, source: root.source }, value: result };
53
+ }
54
+ /** Decode only the selected inline/local-reference string profile within one retained Body.
55
+ * @param root Source-owned typed parameters and body namespace.
56
+ * @param payload Observed RPC wrapper or observed SOAP Body.
57
+ * @param output Whether SOAP response local names are insignificant.
58
+ * @param control Shared native invocation budget and explicit failure callback.
59
+ * @returns Values keyed by the original WSDL part names.
60
+ * @throws Through the failure callback for malformed, ambiguous or unsupported encoded values.
61
+ */
62
+ export function readRpcStrings(root, payload, output, control) {
63
+ const { budget, check, fail } = control;
64
+ const elements = (node) => {
65
+ check();
66
+ budget.chargeWork(32 + node.children.length * 8 + node.attributes.length * 16);
67
+ if (node.children.some(c => c.kind === 'text' && /[^\t\r\n ]/.test(c.value)))
68
+ return fail('mismatch', 'rpc-unexpected-text', node);
69
+ return syntaxElements(node);
70
+ };
71
+ const encoding = (node) => {
72
+ const declared = syntaxAttribute(node, 'encodingStyle', SOAP);
73
+ if (declared !== undefined && declared.trim() !== ENC)
74
+ return fail('unsupported', 'rpc-encoding-style', node);
75
+ };
76
+ const rootMarker = (node) => {
77
+ const marker = syntaxAttribute(node, 'root', ENC);
78
+ if (marker !== undefined && marker !== '0' && marker !== '1')
79
+ return fail('mismatch', 'rpc-root-marker', node);
80
+ return marker;
81
+ };
82
+ const attrs = (node, wrapper = false) => {
83
+ encoding(node);
84
+ rootMarker(node);
85
+ for (const attr of node.attributes) {
86
+ check();
87
+ if (attr.name.namespace === SOAP && attr.name.local === 'encodingStyle' || attr.name.namespace === ENC && attr.name.local === 'root'
88
+ || attr.name.namespace === '' && attr.name.local === 'id' || !wrapper && (attr.name.namespace === '' && attr.name.local === 'href'
89
+ || attr.name.namespace === XSI && attr.name.local === 'type'))
90
+ continue;
91
+ return fail('unsupported', 'rpc-encoded-attribute', node);
92
+ }
93
+ };
94
+ const body = payload.name.namespace === SOAP && payload.name.local === 'Body' ? payload : undefined;
95
+ if (body) {
96
+ encoding(body);
97
+ if (body.attributes.some(a => a.name.namespace !== SOAP || a.name.local !== 'encodingStyle'))
98
+ return fail('unsupported', 'rpc-body-attribute', body);
99
+ }
100
+ const top = body ? elements(body) : [payload];
101
+ const ids = new Map();
102
+ const pending = [...top];
103
+ while (pending.length) {
104
+ check();
105
+ const node = pending.pop();
106
+ budget.chargeWork(32 + node.children.length * 8);
107
+ const id = syntaxAttribute(node, 'id');
108
+ if (id !== undefined) {
109
+ if (!isXmlNCName(id) || ids.has(id))
110
+ return fail('mismatch', 'rpc-duplicate-or-invalid-id', node);
111
+ ids.set(id, node);
112
+ }
113
+ pending.push(...syntaxElements(node));
114
+ }
115
+ const wrappers = top.filter(node => {
116
+ check();
117
+ return node.name.namespace === root.bodyNamespace && rootMarker(node) !== '0'
118
+ && syntaxAttribute(node, 'href') === undefined && syntaxAttribute(node, 'type', XSI) === undefined
119
+ && (!output ? node.name.local === root.wrapper.local : true);
120
+ });
121
+ if (wrappers.length !== 1)
122
+ return fail('mismatch', 'rpc-unambiguous-response-root', payload);
123
+ const wrapper = wrappers[0];
124
+ attrs(wrapper, true);
125
+ const parameters = elements(wrapper);
126
+ if (parameters.length !== root.parts.length)
127
+ return fail('mismatch', 'rpc-result-accessor-count', wrapper);
128
+ const visited = new Set([wrapper]);
129
+ const stringValue = (initial) => {
130
+ const chain = new Set();
131
+ let node = initial, inheritedType = true;
132
+ // @constraints Flat local-reference chains must not consume the JavaScript call stack.
133
+ for (;;) {
134
+ check();
135
+ budget.chargeWork(32 + node.children.length * 8);
136
+ attrs(node);
137
+ if (chain.has(node))
138
+ return fail('unsupported', 'rpc-cyclic-reference', node);
139
+ chain.add(node);
140
+ visited.add(node);
141
+ const explicit = syntaxAttribute(node, 'type', XSI);
142
+ const implicit = node.name.namespace === ENC && node.name.local === 'string';
143
+ if (node.name.namespace === ENC && !implicit)
144
+ return fail('unsupported', 'rpc-string-type', node);
145
+ if (explicit !== undefined) {
146
+ let type;
147
+ try {
148
+ type = resolveLexicalQName(explicit, node);
149
+ }
150
+ catch {
151
+ return fail('unsupported', 'rpc-string-type', node);
152
+ }
153
+ if (type.local !== 'string' || type.namespace !== XSD_NAMESPACE && type.namespace !== ENC)
154
+ return fail('unsupported', 'rpc-string-type', node);
155
+ }
156
+ else if (!inheritedType && !implicit)
157
+ return fail('unsupported', 'rpc-string-type-required', node);
158
+ const href = syntaxAttribute(node, 'href');
159
+ if (href !== undefined) {
160
+ if (syntaxElements(node).length || node.children.some(c => c.kind === 'text' && /[^\t\r\n ]/.test(c.value)))
161
+ return fail('mismatch', 'rpc-reference-content', node);
162
+ if (!href.startsWith('#') || !isXmlNCName(href.slice(1)))
163
+ return fail('unsupported', 'rpc-local-reference-required', node);
164
+ const target = ids.get(href.slice(1));
165
+ if (!target)
166
+ return fail('mismatch', 'rpc-dangling-reference', node);
167
+ node = target;
168
+ inheritedType = false;
169
+ continue;
170
+ }
171
+ if (syntaxElements(node).length)
172
+ return fail('unsupported', 'rpc-string-compound-value', node);
173
+ const value = node.children.map(c => c.kind === 'text' ? c.value : '').join('');
174
+ budget.chargeWork(32 + value.length * 8);
175
+ return value;
176
+ }
177
+ };
178
+ const result = Object.create(null);
179
+ root.parts.forEach((part, index) => {
180
+ check();
181
+ const accessor = parameters[index];
182
+ if (accessor.name.namespace !== '' || !output && accessor.name.local !== part.name)
183
+ return fail('mismatch', 'rpc-parameter-name-order', accessor);
184
+ if (rootMarker(accessor) !== undefined)
185
+ return fail('unsupported', 'rpc-accessor-root-marker', accessor);
186
+ result[part.name] = stringValue(accessor);
187
+ });
188
+ for (const independent of top) {
189
+ check();
190
+ if (independent === wrapper)
191
+ continue;
192
+ if (!visited.has(independent) || rootMarker(independent) === '1')
193
+ return fail('mismatch', 'rpc-unexpected-body-content', independent);
194
+ }
195
+ return result;
196
+ }
@@ -0,0 +1,48 @@
1
+ import type { GraphNode, Reference } from './canonicalGraph.js';
2
+ import type { SemanticContext } from './semanticContext.js';
3
+ import type { RpcMessageRoot } from './directOperation.js';
4
+ import type { DirectProjectionPlan } from './directStructurePlan.js';
5
+ import type { ExpandedName, SyntaxElement } from '../loader/orderedSyntax.js';
6
+ type Scalar = string | boolean;
7
+ export type RpcTypedValue = Readonly<Record<string, Scalar | Readonly<Record<string, boolean>>>>;
8
+ type Fail = (kind: 'value-invalid' | 'unsupported' | 'mismatch', rule: string, node?: SyntaxElement) => never;
9
+ type Control = {
10
+ check(): void;
11
+ fail: Fail;
12
+ };
13
+ export interface RpcPartPlan {
14
+ readonly name: string;
15
+ readonly reference: Reference;
16
+ readonly owner: GraphNode;
17
+ readonly type: ExpandedName;
18
+ readonly projection: DirectProjectionPlan;
19
+ }
20
+ /** Plan actual message parts; original source references remain native authority.
21
+ * @param context Exact qualified context.
22
+ * @param root Source-owned RPC message.
23
+ * @param control Shared cancellation and refusal controls.
24
+ * @returns Native scalar/flat Boolean record plans in WSDL declaration order.
25
+ */
26
+ export declare function planRpcParts(context: SemanticContext, root: RpcMessageRoot, control: Control): readonly RpcPartPlan[];
27
+ /** Expand typed values with native restrictions and canonical inline type accessors.
28
+ * @param context Exact qualified context.
29
+ * @param root Source-owned RPC parameters.
30
+ * @param plans Native type plans.
31
+ * @param application Data-only JSON value.
32
+ * @param control Shared invocation controls.
33
+ * @returns Canonical RPC wrapper plus its validated application value.
34
+ */
35
+ export declare function expandRpcTyped(context: SemanticContext, root: RpcMessageRoot, plans: readonly RpcPartPlan[], application: unknown, control: Control): {
36
+ payload: SyntaxElement;
37
+ value: RpcTypedValue;
38
+ };
39
+ /** Validate actual dispatched inline parameters through native scalar/particle duties.
40
+ * @param context Exact source context.
41
+ * @param root Source-owned RPC input.
42
+ * @param plans Native type plans.
43
+ * @param payload Actual outgoing envelope Body or wrapper.
44
+ * @param control Shared execution controls.
45
+ * @returns Validated values keyed by original message part names.
46
+ */
47
+ export declare function readRpcTyped(context: SemanticContext, root: RpcMessageRoot, plans: readonly RpcPartPlan[], payload: SyntaxElement, control: Control): RpcTypedValue;
48
+ export {};
@@ -0,0 +1,190 @@
1
+ /** Typed RPC composition over native scalar and record owners.
2
+ * @since 1.1.9
3
+ * @constraints Canonical inline parameters; no encoded request graph or array support.
4
+ */
5
+ import { globalId } from './canonicalGraph.js';
6
+ import { planProjectionType, matchOrderedProjection, isXmlCharacters } from './directStructurePlan.js';
7
+ import { assessProjectionTypeOperand } from './projectionScalar.js';
8
+ import { resolveLexicalQName, syntaxAttribute, syntaxElements, XSD_NAMESPACE, XML_NAMESPACE } from '../loader/orderedSyntax.js';
9
+ import { directDataOwnership } from './directExecutionPolicy.js';
10
+ const SOAP = 'http://schemas.xmlsoap.org/soap/envelope/';
11
+ const ENC = 'http://schemas.xmlsoap.org/soap/encoding/';
12
+ const XSI = 'http://www.w3.org/2001/XMLSchema-instance';
13
+ /** Plan actual message parts; original source references remain native authority.
14
+ * @param context Exact qualified context.
15
+ * @param root Source-owned RPC message.
16
+ * @param control Shared cancellation and refusal controls.
17
+ * @returns Native scalar/flat Boolean record plans in WSDL declaration order.
18
+ */
19
+ export function planRpcParts(context, root, control) {
20
+ const found = context.lookup(globalId('message', root.message));
21
+ if (found.kind !== 'found' || found.node.kind !== 'wsdl' || found.node.role !== 'message')
22
+ return control.fail('unsupported', 'rpc-message-owner');
23
+ const owner = found.node;
24
+ return Object.freeze(root.parts.map(part => {
25
+ control.check();
26
+ context.budget.chargeWork(128);
27
+ const resolved = context.resolve(part.type);
28
+ const type = resolved.kind === 'builtin' ? resolved.name : resolved.kind === 'found' && resolved.node.identity.kind === 'global'
29
+ ? resolved.node.identity.name : control.fail('unsupported', 'rpc-named-type-required');
30
+ const projection = planProjectionType(context, owner, part.type, control.check, () => control.fail('unsupported', 'rpc-native-type-shape'));
31
+ const scalar = (value) => value.kind === 'scalar' && !value.list && !value.nillable
32
+ && ['string', 'boolean', 'decimal', 'integer', 'date', 'dateTime'].includes(value.builtin.local);
33
+ if (projection.root.kind === 'scalar') {
34
+ if (!scalar(projection.root))
35
+ return control.fail('unsupported', 'rpc-scalar-representation');
36
+ }
37
+ else {
38
+ const record = projection.records.find(record => record.type.id === projection.root.type);
39
+ if (projection.records.length !== 1 || record.content !== 'element-only' || record.attributes.length || record.attributeWildcard
40
+ || !record.ordered || record.keyed || record.contextual || record.slots.some(slot => !scalar(slot.value)
41
+ || slot.value.kind !== 'scalar' || slot.value.builtin.local !== 'boolean' || slot.particle.occurs.min !== '1' || slot.particle.occurs.max !== '1'))
42
+ return control.fail('unsupported', 'rpc-flat-boolean-record');
43
+ }
44
+ return Object.freeze({ name: part.name, reference: part.type, owner, type, projection });
45
+ }));
46
+ }
47
+ function scalar(context, owner, reference, shape, lexical, node, control) {
48
+ if (shape.kind !== 'scalar' || !isXmlCharacters(lexical))
49
+ return control.fail('value-invalid', 'rpc-scalar-characters', node);
50
+ const assessed = assessProjectionTypeOperand(context, owner, reference, { value: lexical, context: { namespaces: node.namespaces, source: node.source } }, control.check);
51
+ if (assessed.kind !== 'projection-scalar-operand')
52
+ return control.fail('value-invalid', 'rule' in assessed ? assessed.rule : 'rpc-scalar-budget', node);
53
+ if (shape.constraint?.kind === 'fixed' && assessed.operand.canonical !== shape.constraint.canonical)
54
+ return control.fail('value-invalid', 'fixed-element-value', node);
55
+ return shape.builtin.local === 'boolean' ? assessed.operand.canonical === 'true' : lexical;
56
+ }
57
+ function recordOf(part) { return part.projection.records[0]; }
58
+ function object(value, names, control) {
59
+ if (!value || typeof value !== 'object' || Array.isArray(value))
60
+ return control.fail('value-invalid', 'rpc-data-object-required');
61
+ const keys = Object.keys(value);
62
+ if (keys.length !== names.length || keys.some(key => !names.includes(key)))
63
+ return control.fail('value-invalid', 'rpc-required-parts');
64
+ return value;
65
+ }
66
+ /** Expand typed values with native restrictions and canonical inline type accessors.
67
+ * @param context Exact qualified context.
68
+ * @param root Source-owned RPC parameters.
69
+ * @param plans Native type plans.
70
+ * @param application Data-only JSON value.
71
+ * @param control Shared invocation controls.
72
+ * @returns Canonical RPC wrapper plus its validated application value.
73
+ */
74
+ export function expandRpcTyped(context, root, plans, application, control) {
75
+ let owned;
76
+ try {
77
+ owned = directDataOwnership(context.budget).snapshot(application, control.check);
78
+ }
79
+ catch (error) {
80
+ if (error instanceof TypeError)
81
+ return control.fail('value-invalid', 'rpc-data-object-required');
82
+ throw error;
83
+ }
84
+ const input = object(owned, plans.map(part => part.name), control);
85
+ const namespaces = { xml: XML_NAMESPACE, '': '', rpc: root.bodyNamespace, xsi: XSI, xsd: XSD_NAMESPACE, enc: ENC, soap: SOAP };
86
+ const typeNamespaces = [...new Set(plans.map(part => part.type.namespace))].filter(ns => ns !== XSD_NAMESPACE).sort();
87
+ typeNamespaces.forEach((namespace, index) => { namespaces['t' + index] = namespace; });
88
+ const element = (name, value, shape, owner, reference, type) => {
89
+ control.check();
90
+ context.budget.chargeWork(256);
91
+ const prefix = type?.namespace === XSD_NAMESPACE ? 'xsd' : type ? 't' + typeNamespaces.indexOf(type.namespace) : '';
92
+ const node = { kind: 'element', name, lexicalName: name.local, namespaces, baseUri: root.source.uri, source: root.source,
93
+ attributes: type ? [{ name: { namespace: XSI, local: 'type' }, lexicalName: 'xsi:type', value: prefix + ':' + type.local }] : [], children: [] };
94
+ if (shape.kind !== 'scalar')
95
+ return control.fail('unsupported', 'rpc-scalar-required');
96
+ const lexical = shape.builtin.local === 'boolean' ? typeof value === 'boolean' ? String(value) : control.fail('value-invalid', 'boolean-required')
97
+ : typeof value === 'string' ? value : control.fail('value-invalid', 'string-required');
98
+ scalar(context, owner, reference, shape, lexical, node, control);
99
+ return { ...node, children: [{ kind: 'text', value: lexical, source: root.source }] };
100
+ };
101
+ const children = plans.map(part => {
102
+ if (part.projection.root.kind === 'scalar')
103
+ return element({ namespace: '', local: part.name }, input[part.name], part.projection.root, part.owner, part.reference, part.type);
104
+ const record = recordOf(part), value = object(input[part.name], record.slots.map(slot => slot.element.name.local), control);
105
+ const fields = record.slots.map(slot => element(slot.element.name, value[slot.element.name.local], slot.value, slot.element, slot.element.type, slot.value.kind === 'scalar' ? slot.value.builtin : undefined));
106
+ const prefix = 't' + typeNamespaces.indexOf(part.type.namespace);
107
+ return { kind: 'element', name: { namespace: '', local: part.name }, lexicalName: part.name, namespaces, baseUri: root.source.uri, source: root.source,
108
+ attributes: [{ name: { namespace: XSI, local: 'type' }, lexicalName: 'xsi:type', value: prefix + ':' + part.type.local }], children: fields };
109
+ });
110
+ const payload = { kind: 'element', name: root.wrapper, lexicalName: 'rpc:' + root.wrapper.local, namespaces,
111
+ baseUri: root.source.uri, source: root.source, attributes: [{ name: { namespace: SOAP, local: 'encodingStyle' }, lexicalName: 'soap:encodingStyle', value: ENC }], children };
112
+ return { payload, value: readRpcTyped(context, root, plans, payload, control) };
113
+ }
114
+ /** Validate actual dispatched inline parameters through native scalar/particle duties.
115
+ * @param context Exact source context.
116
+ * @param root Source-owned RPC input.
117
+ * @param plans Native type plans.
118
+ * @param payload Actual outgoing envelope Body or wrapper.
119
+ * @param control Shared execution controls.
120
+ * @returns Validated values keyed by original message part names.
121
+ */
122
+ export function readRpcTyped(context, root, plans, payload, control) {
123
+ const elements = (node) => {
124
+ control.check();
125
+ context.budget.chargeWork(64 + node.children.length * 16);
126
+ if (node.children.some(child => child.kind === 'text' && /[^\t\r\n ]/.test(child.value)))
127
+ return control.fail('mismatch', 'rpc-unexpected-text', node);
128
+ return syntaxElements(node);
129
+ };
130
+ const attrs = (node, type) => {
131
+ for (const attribute of node.attributes) {
132
+ control.check();
133
+ if (attribute.name.namespace === SOAP && attribute.name.local === 'encodingStyle' && attribute.value === ENC)
134
+ continue;
135
+ if (type && attribute.name.namespace === XSI && attribute.name.local === 'type') {
136
+ let actual;
137
+ try {
138
+ actual = resolveLexicalQName(attribute.value, node);
139
+ }
140
+ catch {
141
+ return control.fail('unsupported', 'rpc-typed-accessor', node);
142
+ }
143
+ if (actual.namespace === type.namespace && actual.local === type.local)
144
+ continue;
145
+ }
146
+ return control.fail('unsupported', 'rpc-typed-accessor', node);
147
+ }
148
+ };
149
+ if (payload.name.namespace === SOAP && payload.name.local === 'Body') {
150
+ attrs(payload);
151
+ const wrappers = elements(payload);
152
+ if (wrappers.length !== 1)
153
+ return control.fail('mismatch', 'rpc-request-wrapper', payload);
154
+ payload = wrappers[0];
155
+ }
156
+ if (payload.name.namespace !== root.wrapper.namespace || payload.name.local !== root.wrapper.local)
157
+ return control.fail('mismatch', 'rpc-request-wrapper', payload);
158
+ attrs(payload);
159
+ const parameters = elements(payload);
160
+ if (parameters.length !== plans.length)
161
+ return control.fail('mismatch', 'rpc-parameter-count', payload);
162
+ const result = Object.create(null);
163
+ plans.forEach((part, index) => {
164
+ const node = parameters[index];
165
+ if (node.name.namespace !== '' || node.name.local !== part.name)
166
+ return control.fail('mismatch', 'rpc-parameter-name-order', node);
167
+ attrs(node, part.type);
168
+ const readScalar = (node, owner, reference, shape) => {
169
+ if (syntaxElements(node).length)
170
+ return control.fail('mismatch', 'rpc-scalar-content', node);
171
+ return scalar(context, owner, reference, shape, node.children.map(child => child.kind === 'text' ? child.value : '').join(''), node, control);
172
+ };
173
+ if (part.projection.root.kind === 'scalar')
174
+ result[part.name] = readScalar(node, part.owner, part.reference, part.projection.root);
175
+ else {
176
+ const record = recordOf(part), fields = elements(node);
177
+ const matched = matchOrderedProjection(context, record, fields.map(field => field.name), control.check);
178
+ if (!matched || matched.some(slot => 'kind' in slot))
179
+ return control.fail('mismatch', 'rpc-native-record-content', node);
180
+ const value = Object.create(null);
181
+ fields.forEach(field => {
182
+ const slot = record.slots.find(slot => slot.element.name.local === field.name.local && slot.element.name.namespace === field.name.namespace);
183
+ attrs(field, slot.value.kind === 'scalar' ? slot.value.builtin : undefined);
184
+ value[slot.element.name.local] = readScalar(field, slot.element, slot.element.type, slot.value);
185
+ });
186
+ result[part.name] = value;
187
+ }
188
+ });
189
+ return result;
190
+ }