@techspokes/typescript-wsdl-client 1.1.8 → 1.2.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 (73) hide show
  1. package/README.md +17 -3
  2. package/dist/checkedPlanning.js +27 -4
  3. package/dist/cli.js +17 -1
  4. package/dist/client/generateClient.js +72 -16
  5. package/dist/client/generateOperations.js +30 -11
  6. package/dist/client/generateUtils.js +5 -1
  7. package/dist/compiler/canonicalGraph.d.ts +4 -15
  8. package/dist/compiler/canonicalGraph.js +1 -8
  9. package/dist/compiler/componentRecordProjection.d.ts +3 -0
  10. package/dist/compiler/componentRecordProjection.js +10 -0
  11. package/dist/compiler/declarationIdentity.d.ts +22 -0
  12. package/dist/compiler/declarationIdentity.js +9 -0
  13. package/dist/compiler/directCodec.d.ts +22 -2
  14. package/dist/compiler/directCodec.js +40 -7
  15. package/dist/compiler/directOperation.d.ts +26 -4
  16. package/dist/compiler/directOperation.js +59 -5
  17. package/dist/compiler/directSoap.js +24 -7
  18. package/dist/compiler/directSourceCapsule.js +59 -3
  19. package/dist/compiler/directStructure.js +6 -2
  20. package/dist/compiler/directStructurePlan.d.ts +10 -1
  21. package/dist/compiler/directStructurePlan.js +27 -7
  22. package/dist/compiler/directValues.d.ts +15 -3
  23. package/dist/compiler/directValues.js +20 -4
  24. package/dist/compiler/legacyDeclarations.d.ts +26 -0
  25. package/dist/compiler/legacyDeclarations.js +144 -0
  26. package/dist/compiler/projectionScalar.d.ts +18 -1
  27. package/dist/compiler/projectionScalar.js +47 -13
  28. package/dist/compiler/rpcStringValues.d.ts +30 -0
  29. package/dist/compiler/rpcStringValues.js +196 -0
  30. package/dist/compiler/rpcTypedValues.d.ts +48 -0
  31. package/dist/compiler/rpcTypedValues.js +190 -0
  32. package/dist/compiler/schemaCompiler.js +44 -109
  33. package/dist/compiler/semanticCatalog.d.ts +2 -2
  34. package/dist/gateway/generateComposedGateway.d.ts +16 -0
  35. package/dist/gateway/generateComposedGateway.js +65 -0
  36. package/dist/gateway/generateGateway.js +1 -0
  37. package/dist/gateway/generators.js +19 -4
  38. package/dist/gateway/helpers.d.ts +1 -0
  39. package/dist/gateway/helpers.js +15 -0
  40. package/dist/generation/componentShape.js +25 -1
  41. package/dist/index.d.ts +4 -0
  42. package/dist/index.js +2 -0
  43. package/dist/loader/orderedSyntax.d.ts +4 -0
  44. package/dist/loader/orderedSyntax.js +18 -4
  45. package/dist/multiServicePipeline.d.ts +41 -0
  46. package/dist/multiServicePipeline.js +287 -0
  47. package/dist/openapi/composeOpenAPI.d.ts +29 -0
  48. package/dist/openapi/composeOpenAPI.js +322 -0
  49. package/dist/pipeline.d.ts +1 -1
  50. package/dist/pipeline.js +2 -0
  51. package/docs/agent-skill.md +10 -1
  52. package/docs/api-reference.md +127 -9
  53. package/docs/checked-gateway.md +2 -0
  54. package/docs/checked-generation.md +11 -5
  55. package/docs/cli-reference.md +25 -5
  56. package/docs/concepts.md +4 -5
  57. package/docs/configuration.md +10 -3
  58. package/docs/corpus.md +1 -1
  59. package/docs/gateway-guide.md +104 -27
  60. package/docs/generated-code.md +12 -6
  61. package/docs/migration-playbook.md +4 -0
  62. package/docs/migration.md +124 -6
  63. package/docs/output-anatomy.md +20 -17
  64. package/docs/production.md +7 -5
  65. package/docs/start-here.md +12 -2
  66. package/docs/supported-patterns.md +17 -0
  67. package/docs/testing.md +2 -0
  68. package/docs/troubleshooting.md +3 -1
  69. package/llms.txt +9 -1
  70. package/package.json +2 -2
  71. package/src/runtime/clientStreamMethods.tpl.txt +156 -148
  72. package/src/runtime/operationsStreamHelper.tpl.txt +6 -6
  73. package/src/runtime/streamXml.ts +48 -20
@@ -3,7 +3,7 @@ import { assessSourceAttributeUses } from './schemaAttributeUses.js';
3
3
  import { deriveActualComplexContent, particleContentNode } from './complexTypeContent.js';
4
4
  import { XSD_NAMESPACE, XML_NAMESPACE, isXmlNCName } from '../loader/orderedSyntax.js';
5
5
  import { occurrenceAlgebra } from './occurrenceAnalysis.js';
6
- import { describeProjectionScalar, assessProjectionScalarOperand } from './projectionScalar.js';
6
+ import { describeProjectionScalar, describeProjectionType, assessProjectionScalarOperand } from './projectionScalar.js';
7
7
  import { builtinListItem } from './datatypeValues.js';
8
8
  import { prepareSemanticParticleView, assertSemanticParticleView } from './particleSemanticView.js';
9
9
  import { effectiveSubstitutionMembers } from './schemaTypeRelations.js';
@@ -244,6 +244,20 @@ export function selectProjectionAttribute(context, record, name, check, unsuppor
244
244
  * The checked-direct preview adapter below retains its flat-only grammar.
245
245
  */
246
246
  export function planDirectProjection(context, root, check, unsupported) {
247
+ return planProjection(context, root, root.type, check, unsupported, root);
248
+ }
249
+ /** Plan a source-owned type using native scalar, content and particle owners.
250
+ * @param context Native source context.
251
+ * @param owner Exact source graph node owning the type reference.
252
+ * @param reference Selected source type.
253
+ * @param check Cooperative checkpoint.
254
+ * @param unsupported Explicit refusal callback.
255
+ * @returns The same native projection used by document elements, without element facts.
256
+ */
257
+ export function planProjectionType(context, owner, reference, check, unsupported) {
258
+ return planProjection(context, owner, reference, check, unsupported);
259
+ }
260
+ function planProjection(context, owner, reference, check, unsupported, root) {
247
261
  assertSemanticContext(context);
248
262
  if (context.kind !== 'actual')
249
263
  return unsupported();
@@ -259,13 +273,14 @@ export function planDirectProjection(context, root, check, unsupported) {
259
273
  return unsupported();
260
274
  return result.node;
261
275
  };
276
+ if (lookup(owner.id) !== owner)
277
+ return unsupported();
262
278
  const records = new Map();
263
279
  const pending = [];
264
280
  const value = (element) => {
265
281
  if (lookup(element.id) !== element)
266
282
  return unsupported();
267
283
  check();
268
- const type = context.resolve(element.type);
269
284
  if (element.abstract || element.substitutionGroup)
270
285
  return unsupported();
271
286
  const facts = { ...(element.nillable ? { nillable: true } : {}), ...(() => {
@@ -276,13 +291,18 @@ export function planDirectProjection(context, root, check, unsupported) {
276
291
  return unavailable(element, 'element-value-constraint');
277
292
  return { constraint: Object.freeze({ kind: element.value.kind, lexical: element.value.lexical.value, canonical: assessed.operand.canonical }) };
278
293
  })() };
294
+ return typeValue(element, element.type, facts);
295
+ };
296
+ const typeValue = (element, reference, facts = {}) => {
297
+ check();
298
+ const type = context.resolve(reference);
279
299
  if (type.kind === 'builtin' && !builtinListItem(type.name.local)) {
280
300
  if (!projectionScalarRepresentation(type.name))
281
301
  return unavailable(element, 'builtin-scalar-context-or-representation');
282
302
  return Object.freeze({ kind: 'scalar', builtin: type.name, ...facts });
283
303
  }
284
304
  if (type.kind === 'builtin' || type.kind === 'found' && type.node.kind === 'simpleType') {
285
- const scalar = describeProjectionScalar(context, element, check);
305
+ const scalar = describeProjectionType(context, element, reference, check);
286
306
  check();
287
307
  if (scalar.kind !== 'projection-scalar-type')
288
308
  return unavailable(element, 'rule' in scalar ? scalar.rule : 'scalar-source-definition');
@@ -295,13 +315,13 @@ export function planDirectProjection(context, root, check, unsupported) {
295
315
  return unavailable(element, 'unavailable-complex-type');
296
316
  if (!records.has(type.node.id)) {
297
317
  budget.chargeWork(64);
298
- records.set(type.node.id, { type: type.node, declaration: element, slots: [], attributes: [], content: 'element-only' });
318
+ records.set(type.node.id, { type: type.node, declaration: element, reference, slots: [], attributes: [], content: 'element-only' });
299
319
  pending.push(type.node);
300
320
  }
301
321
  return Object.freeze({ kind: 'record', type: type.node.id, ...facts });
302
322
  };
303
323
  budget.chargeWork(128);
304
- const rootValue = value(root);
324
+ const rootValue = root ? value(root) : typeValue(owner, reference);
305
325
  while (pending.length) {
306
326
  check();
307
327
  const type = pending.pop();
@@ -359,7 +379,7 @@ export function planDirectProjection(context, root, check, unsupported) {
359
379
  if (content.kind !== 'checked')
360
380
  return unavailable(type, 'native-content-properties');
361
381
  if (content.view.content.kind === 'simple') {
362
- const scalar = describeProjectionScalar(context, record.declaration, check);
382
+ const scalar = describeProjectionType(context, record.declaration, record.reference, check);
363
383
  check();
364
384
  if (scalar.kind !== 'projection-scalar-type')
365
385
  return unavailable(type, 'rule' in scalar ? scalar.rule : 'scalar-source-definition');
@@ -575,7 +595,7 @@ export function planDirectProjection(context, root, check, unsupported) {
575
595
  }
576
596
  }
577
597
  budget.chargeWork(32 + ordered.length * 64);
578
- return Object.freeze({ root: rootValue, records: Object.freeze(ordered.map(({ declaration: _declaration, grammar, ...record }) => {
598
+ return Object.freeze({ root: rootValue, records: Object.freeze(ordered.map(({ declaration: _declaration, reference: _reference, grammar, ...record }) => {
579
599
  const attributes = Object.freeze(record.attributes.map(attribute => {
580
600
  const local = attribute.declaration.name.local;
581
601
  const collision = record.slots.some(slot => slot.element.name.local === local)
@@ -1,4 +1,4 @@
1
- import type { DirectOperationContract, DirectMessageRoot } from './directOperation.js';
1
+ import type { DirectOperationContract, DirectMessageRoot, RpcMessageRoot } from './directOperation.js';
2
2
  import type { DirectDirection, DirectScalarDuty, DirectStructuralMatch } from './directStructure.js';
3
3
  import type { DirectRootPlan, DirectProjectionPlan } from './directStructurePlan.js';
4
4
  import type { SemanticContext } from './semanticContext.js';
@@ -7,6 +7,7 @@ import type { ProjectionStructuralMatch } from './directStructure.js';
7
7
  import type { ResolverUsage } from './semanticBudget.js';
8
8
  import type { SyntaxElement } from '../loader/orderedSyntax.js';
9
9
  import type { ApplicationGroupsOptions, ApplicationGroupPlan } from './applicationGroups.js';
10
+ import type { RpcPartPlan } from './rpcTypedValues.js';
10
11
  export type DirectPrimitive = string | boolean | number;
11
12
  /** Inverse construction caps; XML encoding may impose smaller byte/text/node limits. */
12
13
  export declare const DIRECT_VALUE_LIMITS: Readonly<{
@@ -28,7 +29,7 @@ export interface DirectValueMapping extends DirectRootPlan {
28
29
  readonly contextId: string;
29
30
  readonly usage: ResolverUsage;
30
31
  }
31
- export interface ComponentValueMapping {
32
+ export interface DocumentComponentValueMapping {
32
33
  readonly kind: 'component-mapping';
33
34
  readonly version: 'component-values-v1';
34
35
  readonly admitted: false;
@@ -37,6 +38,16 @@ export interface ComponentValueMapping {
37
38
  readonly contextId: string;
38
39
  readonly usage: ResolverUsage;
39
40
  }
41
+ export interface RpcComponentValueMapping {
42
+ readonly kind: 'component-mapping';
43
+ readonly version: 'component-rpc-string-values-v1' | 'component-rpc-typed-values-v1';
44
+ readonly admitted: false;
45
+ readonly root: RpcMessageRoot;
46
+ readonly direction: DirectDirection;
47
+ readonly contextId: string;
48
+ readonly usage: ResolverUsage;
49
+ }
50
+ export type ComponentValueMapping = DocumentComponentValueMapping | RpcComponentValueMapping;
40
51
  export interface DirectAssessedScalar extends DirectScalarDuty {
41
52
  readonly normalized: string;
42
53
  readonly canonical: string;
@@ -115,8 +126,9 @@ export declare function createComponentDirectionalMapping(contract: DirectOperat
115
126
  /** Authenticate the exact structured mapping and expose its existing native plan to local consumers only. */
116
127
  export declare function inspectComponentValueMapping(value: unknown, contract: DirectOperationContract): Readonly<{
117
128
  mapping: ComponentValueMapping;
118
- projection: DirectProjectionPlan;
129
+ projection?: DirectProjectionPlan;
119
130
  applicationGroups?: ApplicationGroupPlan;
131
+ rpcParts?: readonly RpcPartPlan[];
120
132
  }>;
121
133
  /** Validate scalar operands and retain nested application records without claiming source or operation admission. */
122
134
  export declare function assessProjectionScalars(context: SemanticContext, supplied: unknown, options?: Options, mapping?: ComponentValueMapping): ProjectionValueReceipt | DirectValueFailure;
@@ -3,7 +3,7 @@ import { types } from 'node:util';
3
3
  /** Internal direct value chain. No XML encoding, transport or runtime admission. */
4
4
  import { checkSemanticBudget } from './semanticBudget.js';
5
5
  import { DataOwnershipLimitError } from './dataOwnership.js';
6
- import { inspectDirectOperation } from './directOperation.js';
6
+ import { inspectDirectOperation, isRpcMessageRoot } from './directOperation.js';
7
7
  import { inspectDirectStructuralMatch, matchDirectOperation } from './directStructure.js';
8
8
  import { planDirectProjection, flatDirectProjection, projectionScalarRepresentation, resolveProjectionWildcard, selectProjectionWildcard, selectProjectionAttribute, isXmlCharacters, isXmlNamespaceBinding } from './directStructurePlan.js';
9
9
  import { assertSemanticContext } from './semanticContext.js';
@@ -12,6 +12,7 @@ import { datatypeValues, normalizeWhitespace, whitespaceFor } from './datatypeVa
12
12
  import { assessProjectionScalarOperand } from './projectionScalar.js';
13
13
  import { isXmlNCName, XML_NAMESPACE, XSD_NAMESPACE } from '../loader/orderedSyntax.js';
14
14
  import { planApplicationGroups, mapApplicationGroups, parseApplicationGroups, ApplicationGroupValueError } from './applicationGroups.js';
15
+ import { planRpcParts } from './rpcTypedValues.js';
15
16
  /** Inverse construction caps; XML encoding may impose smaller byte/text/node limits. */
16
17
  export const DIRECT_VALUE_LIMITS = Object.freeze({ maxText: 1024 * 1024, maxItems: 100_000 });
17
18
  export const DIRECT_VALUE_VERSION = 'direct-values-v1';
@@ -125,6 +126,8 @@ function mappingFor(contract, direction, s) {
125
126
  if (contract.basis !== 'native-direct-premises-v1' || contract.correspondence !== 'dated-XSD-2004-direct-v1')
126
127
  throw new Stop('unsupported', 'direct-mapping-version');
127
128
  const selected = mappingRoot(contract, direction, s), { root } = selected;
129
+ if (isRpcMessageRoot(root))
130
+ throw new Stop('unsupported', 'direct-mapping-version');
128
131
  const unsupported = () => { throw new Stop('unsupported', 'native-direct-shape', root.element.context.source.path); };
129
132
  const projection = planDirectProjection(context, root.element, check, unsupported);
130
133
  const plan = flatDirectProjection(projection, check, unsupported);
@@ -149,7 +152,18 @@ export function createComponentValueMapping(contract, direction, options = {}, a
149
152
  if (contract.basis !== 'native-component-premises-v1' || contract.correspondence !== 'dated-XSD-2004-components-v1')
150
153
  throw new Stop('unsupported', 'component-mapping-version');
151
154
  const selected = mappingRoot(contract, direction, s);
152
- const projection = planDirectProjection(context, selected.root.element, s.check, () => { throw new Stop('unsupported', 'native-component-shape', selected.root.element.context.source.path); });
155
+ if (isRpcMessageRoot(selected.root)) {
156
+ if (applicationGroups !== undefined)
157
+ throw new Stop('unsupported', 'rpc-application-groups');
158
+ const typed = isRpcMessageRoot(contract.input) && contract.input.parts.some(part => part.type.kind !== 'builtin' || part.type.name.local !== 'string' || part.type.name.namespace !== XSD_NAMESPACE);
159
+ const rpcParts = typed ? planRpcParts(context, selected.root, { ...s, fail: (kind, rule) => { throw new Stop(kind === 'mismatch' ? 'value-invalid' : kind, rule); } }) : undefined;
160
+ const mapping = s.publish({ kind: 'component-mapping', version: typed ? 'component-rpc-typed-values-v1' : 'component-rpc-string-values-v1', admitted: false,
161
+ root: selected.root, direction: selected.direction, contextId: context.contextId });
162
+ componentMappings.set(mapping, Object.freeze({ mapping, contract, rpcParts }));
163
+ return mapping;
164
+ }
165
+ const element = selected.root.element;
166
+ const projection = planDirectProjection(context, element, s.check, () => { throw new Stop('unsupported', 'native-component-shape', element.context.source.path); });
153
167
  const mapping = s.publish({ kind: 'component-mapping', version: 'component-values-v1',
154
168
  admitted: false, root: selected.root, direction: selected.direction, contextId: context.contextId });
155
169
  const groupOptions = applicationGroups ? directDataOwnership(s.budget).freeze(parseApplicationGroups(applicationGroups)) : undefined;
@@ -174,7 +188,7 @@ export function inspectComponentValueMapping(value, contract) {
174
188
  const owned = componentMappings.get(value);
175
189
  if (!owned || owned.contract !== contract)
176
190
  throw new TypeError('Fresh matching component value mapping required');
177
- return Object.freeze({ mapping: owned.mapping, projection: owned.projection, ...(owned.applicationGroups ? { applicationGroups: owned.applicationGroups } : {}) });
191
+ return Object.freeze({ mapping: owned.mapping, projection: owned.projection, rpcParts: owned.rpcParts, ...(owned.applicationGroups ? { applicationGroups: owned.applicationGroups } : {}) });
178
192
  }
179
193
  function scalar(duty, s, context) {
180
194
  const { budget, check } = s;
@@ -448,7 +462,7 @@ export function assessProjectionScalars(context, supplied, options = {}, mapping
448
462
  }
449
463
  let value = projectValue(structural.tree, operands, s);
450
464
  const owned = mapping && componentMappings.get(mapping);
451
- if (owned?.applicationGroups)
465
+ if (owned?.applicationGroups && owned.projection)
452
466
  value = mapApplicationGroups(owned.applicationGroups, owned.projection, value, 'from-native', s.check);
453
467
  const receipt = s.publish({ kind: 'projection-value', scope: 'direct-structure-and-scalars', admitted: false,
454
468
  root: structural.root, contextId: context.contextId, structural, operands, value });
@@ -1074,6 +1088,8 @@ export function expandProjectionValue(context, root, application, options = {},
1074
1088
  throw new ApplicationGroupValueError('application-group-data-required');
1075
1089
  throw error;
1076
1090
  }
1091
+ if (!owned.projection)
1092
+ throw new TypeError('Native document projection required');
1077
1093
  application = mapApplicationGroups(owned.applicationGroups, owned.projection, copied, 'to-native', s.check);
1078
1094
  }
1079
1095
  const payload = buildProjectionPayload(context, root, plan, application, options, s);
@@ -0,0 +1,26 @@
1
+ import { type NodeId } from "./declarationIdentity.js";
2
+ export type LegacyGlobal = Readonly<{
3
+ kind: "complex" | "simple" | "element";
4
+ name: string;
5
+ ns: string;
6
+ node: unknown;
7
+ prefixes: Record<string, string>;
8
+ }>;
9
+ /** Index legacy declarations without importing the checked loader's source or acceptance policies.
10
+ * @constraints Paths count equal role/name peers within a parent, never text nodes or unrelated global declarations.
11
+ * @constraints Name allocation is local to this compilation; independent catalogs still require conservative conflict checks.
12
+ */
13
+ export declare class LegacyDeclarations {
14
+ private readonly declarations;
15
+ private readonly names;
16
+ private readonly surfaces;
17
+ private readonly inlineByOwner;
18
+ constructor(globals: readonly LegacyGlobal[]);
19
+ type(ns: string, name: string): NodeId;
20
+ element(ns: string, name: string): NodeId;
21
+ surface(ns: string, name: string): NodeId;
22
+ name(id: NodeId): string;
23
+ inline(owner: NodeId, element: unknown): NodeId;
24
+ private walk;
25
+ private allocate;
26
+ }
@@ -0,0 +1,144 @@
1
+ import { createHash } from "node:crypto";
2
+ import { globalId, scopedId } from "./declarationIdentity.js";
3
+ import { pascal, resolveQName } from "../util/tools.js";
4
+ const object = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
5
+ const local = (key) => key.slice(key.indexOf(":") + 1);
6
+ const attribute = (node, name) => object(node) && typeof node[`@_${name}`] === "string" ? node[`@_${name}`] : "";
7
+ const children = (node, role) => object(node) ? Object.entries(node)
8
+ .filter(([key]) => local(key) === role).flatMap(([, value]) => Array.isArray(value) ? value : [value]) : [];
9
+ /** Index legacy declarations without importing the checked loader's source or acceptance policies.
10
+ * @constraints Paths count equal role/name peers within a parent, never text nodes or unrelated global declarations.
11
+ * @constraints Name allocation is local to this compilation; independent catalogs still require conservative conflict checks.
12
+ */
13
+ export class LegacyDeclarations {
14
+ declarations = new Map();
15
+ names = new Map();
16
+ surfaces = new Map();
17
+ inlineByOwner = new Map();
18
+ constructor(globals) {
19
+ const named = new Set(globals.filter(g => g.kind !== "element").map(g => this.type(g.ns, g.name)));
20
+ for (const g of globals) {
21
+ const id = g.kind === "element" ? this.element(g.ns, g.name) : this.type(g.ns, g.name);
22
+ if (g.kind === "element") {
23
+ const target = attribute(g.node, "type");
24
+ const q = target ? resolveQName(target, g.ns, g.prefixes) : undefined;
25
+ if (q && q.ns === g.ns && q.local === g.name && named.has(this.type(q.ns, q.local))) {
26
+ this.surfaces.set(id, this.type(q.ns, q.local));
27
+ continue;
28
+ }
29
+ }
30
+ const body = g.kind === "element" ? children(g.node, "complexType")[0] : g.node;
31
+ const surface = g.kind === "element" && body ? scopedId(id, "complexType", "type") : id;
32
+ this.surfaces.set(id, surface);
33
+ this.declarations.set(surface, { id: surface, candidate: pascal(g.name), stem: pascal(g.name), anonymous: false });
34
+ if (body && g.kind !== "simple")
35
+ this.walk(surface, body, pascal(g.name), []);
36
+ }
37
+ this.allocate();
38
+ }
39
+ type(ns, name) { return globalId("type", { namespace: ns, local: name }); }
40
+ element(ns, name) { return globalId("element", { namespace: ns, local: name }); }
41
+ surface(ns, name) {
42
+ const id = this.element(ns, name);
43
+ return this.surfaces.get(id) ?? id;
44
+ }
45
+ name(id) {
46
+ const name = this.names.get(id);
47
+ if (!name)
48
+ throw new Error(`Missing legacy declaration name: ${id}`);
49
+ return name;
50
+ }
51
+ inline(owner, element) {
52
+ const id = object(element) ? this.inlineByOwner.get(owner)?.get(element) : undefined;
53
+ if (!id)
54
+ throw new Error(`Missing inline declaration in ${owner}`);
55
+ return id;
56
+ }
57
+ walk(owner, node, stem, path) {
58
+ if (!object(node))
59
+ return;
60
+ const peers = new Map();
61
+ for (const [key, value] of Object.entries(node)) {
62
+ const role = local(key);
63
+ if (!["sequence", "choice", "all", "element", "complexContent", "simpleContent", "extension", "restriction"].includes(role))
64
+ continue;
65
+ for (const child of Array.isArray(value) ? value : [value]) {
66
+ const xmlName = attribute(child, "name") || attribute(child, "ref").split(":").at(-1) || "";
67
+ const peer = JSON.stringify([role, xmlName]);
68
+ const ordinal = peers.get(peer) ?? 0;
69
+ peers.set(peer, ordinal + 1);
70
+ const childPath = [...path, JSON.stringify([role, xmlName, ordinal])];
71
+ if (role === "element") {
72
+ const body = children(child, "complexType")[0];
73
+ if (!body || !object(child))
74
+ continue;
75
+ const elementId = scopedId(owner, JSON.stringify(childPath), "element");
76
+ const id = scopedId(elementId, "complexType", "type");
77
+ const candidate = pascal(xmlName);
78
+ const childStem = `${stem}${candidate}`;
79
+ this.declarations.set(id, { id, candidate, stem: childStem, anonymous: true });
80
+ let byNode = this.inlineByOwner.get(owner);
81
+ if (!byNode)
82
+ this.inlineByOwner.set(owner, byNode = new WeakMap());
83
+ byNode.set(child, id);
84
+ this.walk(id, body, childStem, []);
85
+ }
86
+ else
87
+ this.walk(owner, child, stem, childPath);
88
+ }
89
+ }
90
+ }
91
+ allocate() {
92
+ const groups = new Map();
93
+ for (const d of this.declarations.values()) {
94
+ const group = groups.get(d.candidate) ?? [];
95
+ group.push(d);
96
+ groups.set(d.candidate, group);
97
+ }
98
+ const proposed = new Map();
99
+ const fixed = new Set();
100
+ const preserved = new Set();
101
+ for (const [candidate, group] of groups) {
102
+ const named = group.filter(d => !d.anonymous);
103
+ if (group.length === 1 || named.length === 1) {
104
+ const declaration = group.length === 1 ? group[0] : named[0];
105
+ proposed.set(declaration.id, candidate);
106
+ preserved.add(declaration.id);
107
+ fixed.add(candidate);
108
+ }
109
+ for (const d of group) {
110
+ if (!proposed.has(d.id))
111
+ proposed.set(d.id, d.anonymous ? d.stem : d.candidate);
112
+ }
113
+ }
114
+ // @why No traversal-order winner: every unresolved member of a collision receives an identity-derived suffix.
115
+ const counts = new Map();
116
+ for (const name of proposed.values())
117
+ counts.set(name, (counts.get(name) ?? 0) + 1);
118
+ const pending = [];
119
+ for (const d of this.declarations.values()) {
120
+ const name = proposed.get(d.id);
121
+ if (preserved.has(d.id) || (counts.get(name) === 1 && !fixed.has(name)))
122
+ this.names.set(d.id, name);
123
+ else
124
+ pending.push(d);
125
+ }
126
+ const used = new Set(this.names.values());
127
+ for (let length = 12; pending.length > 0; length += 4) {
128
+ if (length > 64)
129
+ throw new Error("Cannot allocate unique legacy declaration names");
130
+ const candidates = pending.map(d => `${proposed.get(d.id)}_${createHash("sha256").update(d.id).digest("hex").slice(0, length)}`);
131
+ const occurrences = new Map();
132
+ for (const name of candidates)
133
+ occurrences.set(name, (occurrences.get(name) ?? 0) + 1);
134
+ for (let i = pending.length - 1; i >= 0; i--) {
135
+ const name = candidates[i];
136
+ if (used.has(name) || occurrences.get(name) > 1)
137
+ continue;
138
+ this.names.set(pending[i].id, name);
139
+ used.add(name);
140
+ pending.splice(i, 1);
141
+ }
142
+ }
143
+ }
144
+ }
@@ -1,5 +1,5 @@
1
1
  import type { SemanticContext } from './semanticContext.js';
2
- import type { AttributeNode, ElementNode } from './canonicalGraph.js';
2
+ import type { AttributeNode, ElementNode, GraphNode, Reference } from './canonicalGraph.js';
3
3
  import type { DatatypeOperand } from './datatypeValues.js';
4
4
  import type { ExpandedName } from '../loader/orderedSyntax.js';
5
5
  import type { ResourceLimitFailure } from './semanticBudget.js';
@@ -29,4 +29,21 @@ type OperandResult = Readonly<{
29
29
  export declare function describeProjectionScalar(context: SemanticContext, declaration: Declaration, check?: () => void): DescriptionResult;
30
30
  /** A successful calculation is payload-only data; it grants no schema, operation or portable artifact authority. */
31
31
  export declare function assessProjectionScalarOperand(context: SemanticContext, declaration: Declaration, lexical: DatatypeLexicalOperand, check?: () => void): OperandResult;
32
+ /** Describe a source-owned type without inventing an element declaration.
33
+ * @param context Native source context.
34
+ * @param owner Exact graph node owning the reference.
35
+ * @param reference Source-selected type reference.
36
+ * @param check Cooperative budget/cancellation checkpoint.
37
+ * @returns The existing native scalar description or explicit refusal.
38
+ */
39
+ export declare function describeProjectionType(context: SemanticContext, owner: GraphNode, reference: Reference, check?: () => void): DescriptionResult;
40
+ /** Assess a typed value through the same native restrictions as element values.
41
+ * @param context Native source context.
42
+ * @param owner Exact source node owning the reference.
43
+ * @param reference Source-selected type reference.
44
+ * @param lexical Observed lexical value and namespace context.
45
+ * @param check Cooperative checkpoint.
46
+ * @returns Native datatype operand or explicit refusal.
47
+ */
48
+ export declare function assessProjectionTypeOperand(context: SemanticContext, owner: GraphNode, reference: Reference, lexical: DatatypeLexicalOperand, check?: () => void): OperandResult;
32
49
  export {};
@@ -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 {};