@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.
- package/README.md +17 -3
- package/dist/checkedPlanning.js +27 -4
- package/dist/cli.js +17 -1
- package/dist/client/generateClient.js +72 -16
- package/dist/client/generateOperations.js +30 -11
- package/dist/client/generateUtils.js +5 -1
- package/dist/compiler/canonicalGraph.d.ts +4 -15
- package/dist/compiler/canonicalGraph.js +1 -8
- package/dist/compiler/componentRecordProjection.d.ts +3 -0
- package/dist/compiler/componentRecordProjection.js +10 -0
- package/dist/compiler/declarationIdentity.d.ts +22 -0
- package/dist/compiler/declarationIdentity.js +9 -0
- package/dist/compiler/directCodec.d.ts +22 -2
- package/dist/compiler/directCodec.js +40 -7
- package/dist/compiler/directOperation.d.ts +26 -4
- package/dist/compiler/directOperation.js +59 -5
- package/dist/compiler/directSoap.js +24 -7
- package/dist/compiler/directSourceCapsule.js +59 -3
- package/dist/compiler/directStructure.js +6 -2
- package/dist/compiler/directStructurePlan.d.ts +10 -1
- package/dist/compiler/directStructurePlan.js +27 -7
- package/dist/compiler/directValues.d.ts +15 -3
- package/dist/compiler/directValues.js +20 -4
- package/dist/compiler/legacyDeclarations.d.ts +26 -0
- package/dist/compiler/legacyDeclarations.js +144 -0
- package/dist/compiler/projectionScalar.d.ts +18 -1
- package/dist/compiler/projectionScalar.js +47 -13
- package/dist/compiler/rpcStringValues.d.ts +30 -0
- package/dist/compiler/rpcStringValues.js +196 -0
- package/dist/compiler/rpcTypedValues.d.ts +48 -0
- package/dist/compiler/rpcTypedValues.js +190 -0
- package/dist/compiler/schemaCompiler.js +44 -109
- package/dist/compiler/semanticCatalog.d.ts +2 -2
- package/dist/gateway/generateComposedGateway.d.ts +16 -0
- package/dist/gateway/generateComposedGateway.js +65 -0
- package/dist/gateway/generateGateway.js +1 -0
- package/dist/gateway/generators.js +19 -4
- package/dist/gateway/helpers.d.ts +1 -0
- package/dist/gateway/helpers.js +15 -0
- package/dist/generation/componentShape.js +25 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +2 -0
- package/dist/loader/orderedSyntax.d.ts +4 -0
- package/dist/loader/orderedSyntax.js +18 -4
- package/dist/multiServicePipeline.d.ts +41 -0
- package/dist/multiServicePipeline.js +287 -0
- package/dist/openapi/composeOpenAPI.d.ts +29 -0
- package/dist/openapi/composeOpenAPI.js +322 -0
- package/dist/pipeline.d.ts +1 -1
- package/dist/pipeline.js +2 -0
- package/docs/agent-skill.md +10 -1
- package/docs/api-reference.md +127 -9
- package/docs/checked-gateway.md +2 -0
- package/docs/checked-generation.md +11 -5
- package/docs/cli-reference.md +25 -5
- package/docs/concepts.md +4 -5
- package/docs/configuration.md +10 -3
- package/docs/corpus.md +1 -1
- package/docs/gateway-guide.md +104 -27
- package/docs/generated-code.md +12 -6
- package/docs/migration-playbook.md +4 -0
- package/docs/migration.md +124 -6
- package/docs/output-anatomy.md +20 -17
- package/docs/production.md +7 -5
- package/docs/start-here.md +12 -2
- package/docs/supported-patterns.md +17 -0
- package/docs/testing.md +2 -0
- package/docs/troubleshooting.md +3 -1
- package/llms.txt +9 -1
- package/package.json +2 -2
- package/src/runtime/clientStreamMethods.tpl.txt +156 -148
- package/src/runtime/operationsStreamHelper.tpl.txt +6 -6
- 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 =
|
|
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 =
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
47
|
+
const key = keyFor(declaration, selected);
|
|
48
|
+
const cached = descriptions.get(key);
|
|
46
49
|
if (cached)
|
|
47
50
|
return cached;
|
|
48
|
-
let reference =
|
|
49
|
-
const type = context.resolve(
|
|
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(
|
|
99
|
-
references.set(
|
|
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
|
-
|
|
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
|
|
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(() =>
|
|
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(() =>
|
|
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 {};
|