@techspokes/typescript-wsdl-client 1.4.1 → 1.5.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 +5 -0
- package/dist/checkedPipeline.d.ts +2 -1
- package/dist/checkedPipeline.js +1 -1
- package/dist/checkedResponseInspection.d.ts +22 -0
- package/dist/checkedResponseInspection.js +54 -4
- package/dist/client/checkedDirectRuntime.d.ts +2 -0
- package/dist/client/directClientRuntime.d.ts +2 -0
- package/dist/client/directClientRuntime.js +5 -1
- package/dist/client/generateDirectClient.js +2 -2
- package/dist/compiler/componentRecordProjection.js +13 -2
- package/dist/compiler/directCodec.d.ts +2 -0
- package/dist/compiler/directSoap.d.ts +2 -0
- package/dist/compiler/directSoap.js +2 -1
- package/dist/compiler/directStructure.d.ts +4 -0
- package/dist/compiler/directStructure.js +26 -6
- package/dist/compiler/directValues.d.ts +2 -0
- package/dist/compiler/directValues.js +14 -10
- package/dist/compiler/payloadDiagnostics.d.ts +60 -0
- package/dist/compiler/payloadDiagnostics.js +73 -0
- package/dist/compiler/sourceCorrections.d.ts +50 -1
- package/dist/compiler/sourceCorrections.js +157 -8
- package/dist/gateway/generateCheckedGateway.js +19 -3
- package/dist/index.d.ts +2 -1
- package/docs/api-reference.md +2 -0
- package/docs/checked-gateway.md +57 -1
- package/docs/migration.md +12 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,6 +9,10 @@ Turn legacy WSDL/SOAP services into typed TypeScript clients and optional REST A
|
|
|
9
9
|
|
|
10
10
|
Created from production integration work at [TechSpokes](https://www.techspokes.com); built for teams modernizing real enterprise SOAP integrations.
|
|
11
11
|
|
|
12
|
+
## Upgrading to 1.5.0
|
|
13
|
+
|
|
14
|
+
Version 1.5.0 adds scoped, value-redacted checked payload diagnostics and explicit digest-pinned declared-type corrections. Trusted local inspection can supply original correction targets; changed effective contracts need fresh qualification and matched artifact regeneration. Read the [1.4.x migration guidance](docs/migration.md#from-14x-to-150).
|
|
15
|
+
|
|
12
16
|
## Upgrading to 1.4.0
|
|
13
17
|
|
|
14
18
|
Version 1.4.0 adds explicit JSON source corrections, offline SOAP response inspection, and checked SOAP 1.1 protocol faults without invented application values. Existing runtime bindings remain available; regenerate matched SOAP 1.1 artifacts to adopt the additive V3 binding. Read the [1.3.x migration guidance](docs/migration.md#from-13x-to-140).
|
|
@@ -257,6 +261,7 @@ See [CLI Reference](docs/cli-reference.md) for all flags and examples.
|
|
|
257
261
|
| [Core Concepts](docs/concepts.md) | Flattening, $value, primitives, determinism |
|
|
258
262
|
| [Agent Skill Artifact](docs/agent-skill.md) | Release ZIP for consumer-project AI agents |
|
|
259
263
|
| [Version Migration](docs/migration.md) | Upgrading between package versions |
|
|
264
|
+
| [1.5.0 Release Notes](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/docs/releases/v1.5.0.md) | Scoped diagnostics and explicit declared-type corrections |
|
|
260
265
|
| [1.2.0 Release Notes](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/docs/releases/v1.2.0.md) | Composition, consumer compatibility and bounded RPC qualification |
|
|
261
266
|
| [1.4.1 Release Notes](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/docs/releases/v1.4.1.md) | Composable checked OpenAPI documentation |
|
|
262
267
|
| [1.4.0 Release Notes](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/docs/releases/v1.4.0.md) | Contract corrections, offline inspection and SOAP 1.1 protocol faults |
|
|
@@ -90,6 +90,7 @@ export declare function parseCheckedComponentChoices(value: unknown): Partial<Ch
|
|
|
90
90
|
export interface PreparedCheckedSourceInputs {
|
|
91
91
|
readonly main: SchemaInput;
|
|
92
92
|
readonly companions: ReadonlyMap<string, SchemaInput>;
|
|
93
|
+
readonly correctionPreparation: ReturnType<typeof prepareCorrectedSourceInputs>;
|
|
93
94
|
readonly provenance: Awaited<ReturnType<typeof prepareCorrectedSourceInputs>>['provenance'] & {
|
|
94
95
|
readonly recipeFile: {
|
|
95
96
|
readonly digest: string;
|
|
@@ -168,7 +169,7 @@ export declare function prepareComponentStages(wsdl: string, config: CheckedComp
|
|
|
168
169
|
changed: boolean;
|
|
169
170
|
}>[];
|
|
170
171
|
corrections: readonly Readonly<{
|
|
171
|
-
kind: "set-occurs" | "set-wildcard-namespaces" | "insert-element";
|
|
172
|
+
kind: "set-occurs" | "set-wildcard-namespaces" | "insert-element" | "set-declared-type";
|
|
172
173
|
target: import("./compiler/sourceCorrections.js").SourceCorrectionSelector;
|
|
173
174
|
}>[];
|
|
174
175
|
}> & {
|
package/dist/checkedPipeline.js
CHANGED
|
@@ -241,7 +241,7 @@ export async function prepareCheckedSourceInputs(source, config, acquiredMain) {
|
|
|
241
241
|
const effectiveCompanions = new Map();
|
|
242
242
|
for (const [key, input] of companions)
|
|
243
243
|
effectiveCompanions.set(key, await reload(input));
|
|
244
|
-
return { main: effectiveMain, companions: effectiveCompanions, provenance: { ...corrected.provenance,
|
|
244
|
+
return { main: effectiveMain, companions: effectiveCompanions, correctionPreparation: corrected, provenance: { ...corrected.provenance,
|
|
245
245
|
recipeFile: { digest: createHash('sha256').update(bytes).digest('hex') } } };
|
|
246
246
|
}
|
|
247
247
|
/**
|
|
@@ -2,6 +2,8 @@ import type { CheckedComponentOptions } from './checkedPipeline.js';
|
|
|
2
2
|
import type { DirectOperationSelector } from './compiler/directOperation.js';
|
|
3
3
|
import type { ObservedSoapResponseMetadata } from './compiler/directSoap.js';
|
|
4
4
|
import type { DirectXmlLimits } from './compiler/directCodec.js';
|
|
5
|
+
import type { SourceCorrectionSelector } from './compiler/sourceCorrections.js';
|
|
6
|
+
import type { CheckedPayloadDiagnostic } from './compiler/payloadDiagnostics.js';
|
|
5
7
|
export interface CheckedResponseInspectionOptions {
|
|
6
8
|
readonly checkedComponents?: Partial<CheckedComponentOptions>;
|
|
7
9
|
readonly selector: DirectOperationSelector;
|
|
@@ -10,6 +12,7 @@ export interface CheckedResponseInspectionOptions {
|
|
|
10
12
|
readonly signal?: AbortSignal;
|
|
11
13
|
readonly limits?: DirectXmlLimits;
|
|
12
14
|
readonly includeCorrectionDraft?: boolean;
|
|
15
|
+
readonly includeCorrectionTargets?: boolean;
|
|
13
16
|
}
|
|
14
17
|
type Assessment = 'conforming' | 'mismatch' | 'refused' | 'unassessed';
|
|
15
18
|
interface ScopedOutcome {
|
|
@@ -31,7 +34,25 @@ interface InspectionDiagnostic {
|
|
|
31
34
|
readonly source?: InspectionLocation;
|
|
32
35
|
readonly schemaPath?: string;
|
|
33
36
|
readonly payloadPath?: string;
|
|
37
|
+
readonly diagnostic?: CheckedPayloadDiagnostic;
|
|
34
38
|
}
|
|
39
|
+
/** Explicit trusted authoring data; available selectors retain original locators and digest pins.
|
|
40
|
+
* @since 1.5.0
|
|
41
|
+
* @constraints Only requested local authoring output may contain these locators; HTTP diagnostics never do.
|
|
42
|
+
*/
|
|
43
|
+
export type CheckedResponseCorrectionTarget = Readonly<{
|
|
44
|
+
diagnostic: number;
|
|
45
|
+
} & ({
|
|
46
|
+
kind: 'available';
|
|
47
|
+
target: SourceCorrectionSelector;
|
|
48
|
+
declaredType?: {
|
|
49
|
+
namespace: string;
|
|
50
|
+
local: string;
|
|
51
|
+
};
|
|
52
|
+
} | {
|
|
53
|
+
kind: 'unavailable';
|
|
54
|
+
reason: string;
|
|
55
|
+
})>;
|
|
35
56
|
/** A non-applicable recipe draft; null fields require an explicit consumer decision.
|
|
36
57
|
* @since Unreleased
|
|
37
58
|
*/
|
|
@@ -78,6 +99,7 @@ export interface CheckedResponseInspectionReport {
|
|
|
78
99
|
};
|
|
79
100
|
readonly diagnostics: readonly InspectionDiagnostic[];
|
|
80
101
|
readonly correctionDraft?: CheckedResponseCorrectionDraft;
|
|
102
|
+
readonly correctionTargets?: readonly CheckedResponseCorrectionTarget[];
|
|
81
103
|
readonly sourceCorrections?: {
|
|
82
104
|
readonly recipeDigest: string;
|
|
83
105
|
readonly resources: readonly {
|
|
@@ -16,7 +16,8 @@ import { createComponentValueMapping } from './compiler/directValues.js';
|
|
|
16
16
|
import { observeComponentXml, assessObservedComponentPayload, DIRECT_XML_LIMITS } from './compiler/directCodec.js';
|
|
17
17
|
import { inspectComponentRecordProjection } from './compiler/componentRecordProjection.js';
|
|
18
18
|
import { acquireStandardSchemaLibrary } from './compiler/standardSchemaComponents.js';
|
|
19
|
-
import { inspectSourceCorrectionInventory, SourceCorrectionError } from './compiler/sourceCorrections.js';
|
|
19
|
+
import { inspectSourceCorrectionInventory, recoverOriginalSourceCorrectionTarget, SourceCorrectionError } from './compiler/sourceCorrections.js';
|
|
20
|
+
import { inspectPayloadDiagnostic } from './compiler/payloadDiagnostics.js';
|
|
20
21
|
import { loadSemanticSchemaInput, prepareSchemaSnapshotFiles, copyOriginalSchemaResource } from './loader/schemaInput.js';
|
|
21
22
|
import { resolveResourceUri } from './loader/schemaResources.js';
|
|
22
23
|
import { syntaxElements, syntaxAttribute, resolveLexicalQName, XSD_NAMESPACE, WSDL_NAMESPACE, SchemaLoadingError } from './loader/orderedSyntax.js';
|
|
@@ -59,9 +60,11 @@ function failureAssessment(kind) {
|
|
|
59
60
|
export async function inspectCheckedResponse(source, options) {
|
|
60
61
|
if (typeof source !== 'string' || !source)
|
|
61
62
|
throw new TypeError('Local WSDL source string required');
|
|
62
|
-
const supplied = record(options, ['checkedComponents', 'selector', 'responseBytes', 'responseMetadata', 'signal', 'limits', 'includeCorrectionDraft']);
|
|
63
|
+
const supplied = record(options, ['checkedComponents', 'selector', 'responseBytes', 'responseMetadata', 'signal', 'limits', 'includeCorrectionDraft', 'includeCorrectionTargets']);
|
|
63
64
|
if (supplied.includeCorrectionDraft !== undefined && typeof supplied.includeCorrectionDraft !== 'boolean')
|
|
64
65
|
throw new TypeError('includeCorrectionDraft must be boolean');
|
|
66
|
+
if (supplied.includeCorrectionTargets !== undefined && typeof supplied.includeCorrectionTargets !== 'boolean')
|
|
67
|
+
throw new TypeError('includeCorrectionTargets must be boolean');
|
|
65
68
|
const selector = parseCheckedComponentChoices({ selectors: [supplied.selector] }).selectors[0];
|
|
66
69
|
const choices = parseCheckedComponentChoices(supplied.checkedComponents ?? {});
|
|
67
70
|
const responseByteLength = xmlByteLength(supplied.responseBytes);
|
|
@@ -90,6 +93,8 @@ export async function inspectCheckedResponse(source, options) {
|
|
|
90
93
|
const displaySelector = { portType: { namespace: bounded(selector.portType.namespace), local: bounded(selector.portType.local) },
|
|
91
94
|
binding: { namespace: bounded(selector.binding.namespace), local: bounded(selector.binding.local) }, operation: bounded(selector.operation) };
|
|
92
95
|
const diagnostics = [];
|
|
96
|
+
let sourcePreparation;
|
|
97
|
+
let correctionTargets = supplied.includeCorrectionTargets ? [] : undefined;
|
|
93
98
|
const inputs = [];
|
|
94
99
|
const locations = new Map();
|
|
95
100
|
const resources = [];
|
|
@@ -115,14 +120,53 @@ export async function inspectCheckedResponse(source, options) {
|
|
|
115
120
|
const location = (at) => ({ resource: at.uri === 'urn:typescript-wsdl-client:inspected-response' ? 'response' : locations.get(at.uri)?.resource ?? 'unlocated-source',
|
|
116
121
|
digest: at.uri === 'urn:typescript-wsdl-client:inspected-response' ? responseIdentity.digest : locations.get(at.uri)?.digest ?? at.digest,
|
|
117
122
|
path: bounded(at.path), line: at.start.line, column: at.start.column });
|
|
123
|
+
let authoringInventory;
|
|
124
|
+
const inventoryForAuthoring = () => {
|
|
125
|
+
if (authoringInventory?.inputCount === inputs.length)
|
|
126
|
+
return authoringInventory;
|
|
127
|
+
try {
|
|
128
|
+
authoringInventory = { inputCount: inputs.length, value: inspectSourceCorrectionInventory(inputs, signal) };
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
if (!(error instanceof SourceCorrectionError) && !(error instanceof SchemaLoadingError))
|
|
132
|
+
throw error;
|
|
133
|
+
authoringInventory = { inputCount: inputs.length, reason: `original-target-inventory-${error.category}` };
|
|
134
|
+
}
|
|
135
|
+
return authoringInventory;
|
|
136
|
+
};
|
|
118
137
|
const add = (scope, result) => {
|
|
119
138
|
if (diagnostics.length === 32) {
|
|
120
139
|
truncated = true;
|
|
121
140
|
return;
|
|
122
141
|
}
|
|
142
|
+
if (result.diagnostic?.truncated)
|
|
143
|
+
truncated = true;
|
|
123
144
|
diagnostics.push({ scope, kind: bounded(result.kind, 80), rule: result.kind === 'xml-invalid' ? 'observed-XML-invalid' : bounded(result.rule), guidance,
|
|
124
145
|
...(result.source ? { source: location(result.source) } : {}), ...(result.schemaPath ? { schemaPath: bounded(result.schemaPath) } : {}),
|
|
125
|
-
...(result.payloadPath ? { payloadPath: bounded(result.payloadPath) } : {}) });
|
|
146
|
+
...(result.payloadPath ? { payloadPath: bounded(result.payloadPath) } : {}), ...(result.diagnostic ? { diagnostic: result.diagnostic } : {}) });
|
|
147
|
+
if (correctionTargets) {
|
|
148
|
+
const diagnostic = diagnostics.length - 1;
|
|
149
|
+
const native = result.diagnostic && inspectPayloadDiagnostic(result.diagnostic);
|
|
150
|
+
if (!native)
|
|
151
|
+
correctionTargets.push({ diagnostic, kind: 'unavailable', reason: 'native-declaration-unavailable' });
|
|
152
|
+
else if (sourcePreparation)
|
|
153
|
+
correctionTargets.push({ diagnostic, ...recoverOriginalSourceCorrectionTarget(sourcePreparation.correctionPreparation, native.declaration.context.source, native.declaration.context.effectiveNamespace, native.declaration.kind) });
|
|
154
|
+
else {
|
|
155
|
+
const declaration = native.declaration;
|
|
156
|
+
const inventory = inventoryForAuthoring();
|
|
157
|
+
if (!inventory.value) {
|
|
158
|
+
correctionTargets.push({ diagnostic, kind: 'unavailable', reason: inventory.reason });
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const matches = inventory.value.nodes.filter(node => node.id === declaration.id && node.uri === declaration.context.source.uri
|
|
162
|
+
&& node.digest === declaration.context.source.digest && node.kind === declaration.kind
|
|
163
|
+
&& node.namespace === declaration.context.effectiveNamespace);
|
|
164
|
+
correctionTargets.push(matches.length === 1 && !matches[0].ambiguousContext
|
|
165
|
+
? { diagnostic, kind: 'available', target: { id: matches[0].id, uri: matches[0].uri, digest: matches[0].digest },
|
|
166
|
+
...(declaration.type.kind !== 'local' ? { declaredType: declaration.type.name } : {}) }
|
|
167
|
+
: { diagnostic, kind: 'unavailable', reason: matches.length > 1 || matches[0]?.ambiguousContext ? 'ambiguous-original-target' : 'original-target-not-established' });
|
|
168
|
+
}
|
|
169
|
+
}
|
|
126
170
|
};
|
|
127
171
|
let responseOutcome = { assessment: 'unassessed' };
|
|
128
172
|
let wrapper, companion;
|
|
@@ -138,12 +182,17 @@ export async function inspectCheckedResponse(source, options) {
|
|
|
138
182
|
const report = { version: 'checked-response-inspection-v1', kind, scope: metadata ? 'full-response' : 'xml-only',
|
|
139
183
|
admitted: false, executed: false, selector: displaySelector, response: responseIdentity, http, fault, resources,
|
|
140
184
|
outcomes: { response: scoped(responseOutcome), ...(wrapper ? { wrapper: scoped(wrapper) } : {}), ...(companion ? { companion: scoped(companion) } : {}) }, diagnostics,
|
|
141
|
-
...(correctionDraft ? { correctionDraft } : {}), ...(correctionEvidence ? { sourceCorrections: correctionEvidence } : {}), truncated };
|
|
185
|
+
...(correctionDraft ? { correctionDraft } : {}), ...(correctionTargets ? { correctionTargets } : {}), ...(correctionEvidence ? { sourceCorrections: correctionEvidence } : {}), truncated };
|
|
142
186
|
if (Buffer.byteLength(JSON.stringify(report)) > 128 * 1024 && correctionDraft) {
|
|
143
187
|
correctionDraft = undefined;
|
|
144
188
|
truncated = true;
|
|
145
189
|
return finish();
|
|
146
190
|
}
|
|
191
|
+
if (Buffer.byteLength(JSON.stringify(report)) > 128 * 1024 && correctionTargets?.some(target => target.kind === 'available')) {
|
|
192
|
+
correctionTargets = correctionTargets.map(target => ({ diagnostic: target.diagnostic, kind: 'unavailable', reason: 'authoring-target-exceeds-report-capacity' }));
|
|
193
|
+
truncated = true;
|
|
194
|
+
return finish();
|
|
195
|
+
}
|
|
147
196
|
return report;
|
|
148
197
|
};
|
|
149
198
|
if (signal?.aborted || !withinByteLimit || metadataOverLimit) {
|
|
@@ -161,6 +210,7 @@ export async function inspectCheckedResponse(source, options) {
|
|
|
161
210
|
await fs.access(localFile(choices.sourceCorrectionsFile));
|
|
162
211
|
const selectedChoices = { ...choices, sourceResources: choices.sourceResources ?? [], signal };
|
|
163
212
|
const prepared = await prepareCheckedComponentPlan(rootFile, selectedChoices, undefined, selector);
|
|
213
|
+
sourcePreparation = prepared.sources;
|
|
164
214
|
if (prepared.sourceInput)
|
|
165
215
|
retain(prepared.sourceInput);
|
|
166
216
|
if (prepared.sources) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CheckedPayloadDiagnostic } from '../compiler/payloadDiagnostics.js';
|
|
1
2
|
import type { ComponentClientResult } from './directClientRuntime.js';
|
|
2
3
|
import { DIRECT_CLIENT_RUNTIME_VERSION, COMPONENT_CLIENT_RUNTIME_VERSION, COMPONENT_SOAP12_CLIENT_RUNTIME_VERSION } from './directClientVersion.js';
|
|
3
4
|
interface Name {
|
|
@@ -34,6 +35,7 @@ interface Failure {
|
|
|
34
35
|
readonly usage: Usage;
|
|
35
36
|
readonly repair?: string;
|
|
36
37
|
readonly phase?: 'input' | 'response';
|
|
38
|
+
readonly diagnostic?: CheckedPayloadDiagnostic;
|
|
37
39
|
}
|
|
38
40
|
type Success = {
|
|
39
41
|
readonly value: unknown;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CheckedPayloadDiagnostic } from '../compiler/payloadDiagnostics.js';
|
|
1
2
|
import type { SemanticBudgetLimits, ResolverUsage } from '../compiler/semanticBudget.js';
|
|
2
3
|
import type { DirectCapsuleFailure } from '../compiler/directSourceCapsule.js';
|
|
3
4
|
import type { DirectSoapOptions, ComponentSoapOptions, DirectSoapFailure, ComponentProtocolFault, DeclaredSoapFault, Soap11FaultMetadata, Soap12FaultMetadata } from '../compiler/directSoap.js';
|
|
@@ -36,6 +37,7 @@ export interface DirectClientFailure {
|
|
|
36
37
|
readonly usage: ResolverUsage;
|
|
37
38
|
readonly repair?: string;
|
|
38
39
|
readonly phase?: 'input' | 'response';
|
|
40
|
+
readonly diagnostic?: CheckedPayloadDiagnostic;
|
|
39
41
|
}
|
|
40
42
|
export type DirectClientResult = DirectClientFailure | Readonly<{
|
|
41
43
|
kind: 'soap-response';
|
|
@@ -156,7 +156,11 @@ async function executeClient(expectedBase64, input, options, component, protocol
|
|
|
156
156
|
if (!('decoded' in result)) {
|
|
157
157
|
if (result.kind === 'soap-fault' && result.fault.version !== protocol)
|
|
158
158
|
throw new TypeError('Protocol fault requires its generated runtime binding');
|
|
159
|
-
|
|
159
|
+
if (result.kind === 'soap-fault')
|
|
160
|
+
return result;
|
|
161
|
+
// @constraints Native source provenance can contain endpoint secrets; only the safe diagnostic crosses the runtime boundary.
|
|
162
|
+
return Object.freeze({ kind: result.kind, rule: result.rule, usage: result.usage,
|
|
163
|
+
...(result.phase ? { phase: result.phase } : {}), ...(result.diagnostic ? { diagnostic: result.diagnostic } : {}) });
|
|
160
164
|
}
|
|
161
165
|
if (options.soap.signal?.aborted)
|
|
162
166
|
return fail('cancelled', 'cooperative-cancellation');
|
|
@@ -86,7 +86,7 @@ export function generateDirectClient(expected, signal) {
|
|
|
86
86
|
'}',
|
|
87
87
|
'export interface Failure {',
|
|
88
88
|
' readonly kind: "incompatible-artifact" | "unsupported" | "missing-authority" | "resource-limit" | "cancelled" | "inconclusive" | "invalid-schema" | "scalar-invalid" | "value-invalid" | "xml-invalid" | "mismatch" | "transport" | "protocol";',
|
|
89
|
-
' readonly rule: string; readonly repair?: string; readonly usage: Usage;',
|
|
89
|
+
' readonly rule: string; readonly repair?: string; readonly usage: Usage; readonly diagnostic?: import("@techspokes/typescript-wsdl-client").CheckedPayloadDiagnostic;',
|
|
90
90
|
'}',
|
|
91
91
|
'export interface NativeSuccess { readonly kind: "soap-response" | "soap-fault"; readonly value: unknown;',
|
|
92
92
|
' readonly admitted: false; readonly status: number; readonly usage: Usage; readonly responseBytes: Uint8Array;',
|
|
@@ -192,7 +192,7 @@ export async function generateComponentClient(expected, signal) {
|
|
|
192
192
|
' readonly limits?: {readonly maxBytes?: number; readonly maxDepth?: number; readonly maxNodes?: number; readonly maxText?: number}};',
|
|
193
193
|
'}',
|
|
194
194
|
'export interface Failure {readonly kind: "incompatible-artifact" | "unsupported" | "missing-authority" | "resource-limit" | "cancelled" | "inconclusive" | "invalid-schema" | "scalar-invalid" | "value-invalid" | "xml-invalid" | "mismatch" | "transport" | "protocol";',
|
|
195
|
-
' readonly rule: string; readonly repair?: string; readonly phase?: "input" | "response"; readonly usage: Usage}',
|
|
195
|
+
' readonly rule: string; readonly repair?: string; readonly phase?: "input" | "response"; readonly usage: Usage; readonly diagnostic?: import("@techspokes/typescript-wsdl-client").CheckedPayloadDiagnostic}',
|
|
196
196
|
'export interface NativeSuccess {readonly kind: "soap-response" | "soap-fault"; readonly value?: unknown; readonly admitted: false;',
|
|
197
197
|
' readonly status: number; readonly usage: Usage; readonly responseBytes: Uint8Array;',
|
|
198
198
|
' readonly fault?: {readonly name?: string; readonly code: Name; readonly string: string; readonly actor?: string}}',
|
|
@@ -9,6 +9,7 @@ import { assessSourceAttributeUses } from './schemaAttributeUses.js';
|
|
|
9
9
|
import { assessStandardSchemaElement } from './standardSchemaComponents.js';
|
|
10
10
|
import { namespaceAllows } from './wildcardAlgebra.js';
|
|
11
11
|
import { directDataOwnership } from './directExecutionPolicy.js';
|
|
12
|
+
import { createPayloadDiagnostic, diagnosticName } from './payloadDiagnostics.js';
|
|
12
13
|
import { DataOwnershipLimitError } from './dataOwnership.js';
|
|
13
14
|
import { isXmlNCName, syntaxElements } from '../loader/orderedSyntax.js';
|
|
14
15
|
const issued = new WeakMap();
|
|
@@ -318,8 +319,18 @@ export function decodeComponentRecordXml(outer, projection, bytes, options = {})
|
|
|
318
319
|
catch (error) {
|
|
319
320
|
if (budget.exhausted())
|
|
320
321
|
return failure('resource-limit', 'record-projection-budget');
|
|
321
|
-
if (error instanceof ScopeStop)
|
|
322
|
-
|
|
322
|
+
if (error instanceof ScopeStop) {
|
|
323
|
+
if (error.kind !== 'mismatch' || 'parts' in outer.output)
|
|
324
|
+
return failure(error.kind, error.rule);
|
|
325
|
+
const declaration = outer.output.element;
|
|
326
|
+
// @constraints Native metadata lookups consume the same budget and retain its terminal resource result.
|
|
327
|
+
const diagnosed = budget.guard(() => {
|
|
328
|
+
const diagnostic = createPayloadDiagnostic(context, declaration, '/' + diagnosticName(declaration.name) + '/[unknown-field]', { unknownField: true });
|
|
329
|
+
return Object.freeze({ ...failure(error.kind, error.rule), diagnostic });
|
|
330
|
+
});
|
|
331
|
+
return diagnosed.kind === 'resource-limit' && !('rule' in diagnosed)
|
|
332
|
+
? failure('resource-limit', 'record-projection-budget') : diagnosed;
|
|
333
|
+
}
|
|
323
334
|
throw error;
|
|
324
335
|
}
|
|
325
336
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CheckedPayloadDiagnostic } from './payloadDiagnostics.js';
|
|
1
2
|
import type { DirectOperationContract } from './directOperation.js';
|
|
2
3
|
import type { DirectValueMapping, DirectValueReceipt, DirectValueFailure, DirectExpandedValue, ComponentValueMapping, ProjectionExpandedValue, ProjectionValueReceipt } from './directValues.js';
|
|
3
4
|
import type { SyntaxElement, SyntaxSource } from '../loader/orderedSyntax.js';
|
|
@@ -31,6 +32,7 @@ export interface DirectCodecFailure {
|
|
|
31
32
|
readonly source?: SyntaxSource;
|
|
32
33
|
readonly schemaPath?: string;
|
|
33
34
|
readonly payloadPath?: string;
|
|
35
|
+
readonly diagnostic?: CheckedPayloadDiagnostic;
|
|
34
36
|
readonly usage: ResolverUsage;
|
|
35
37
|
}
|
|
36
38
|
export interface DirectEncodedXml {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CheckedPayloadDiagnostic } from './payloadDiagnostics.js';
|
|
1
2
|
import type { DirectOperationContract } from './directOperation.js';
|
|
2
3
|
import type { DirectCodecFailure, DirectDecodedXml, ComponentDecodedXml, DirectXmlLimits } from './directCodec.js';
|
|
3
4
|
import type { ExpandedName, SyntaxElement, SyntaxSource } from '../loader/orderedSyntax.js';
|
|
@@ -23,6 +24,7 @@ export interface DirectSoapFailure {
|
|
|
23
24
|
readonly source?: SyntaxSource;
|
|
24
25
|
readonly schemaPath?: string;
|
|
25
26
|
readonly payloadPath?: string;
|
|
27
|
+
readonly diagnostic?: CheckedPayloadDiagnostic;
|
|
26
28
|
}
|
|
27
29
|
/** Version-specific protocol metadata; application detail remains owned by native mappings.
|
|
28
30
|
* @since 1.3.0
|
|
@@ -560,7 +560,8 @@ function assessSoapResponse(contract, output, faults, bytes, profile, options) {
|
|
|
560
560
|
if (!decoded)
|
|
561
561
|
throw new TypeError('Missing decoded SOAP response');
|
|
562
562
|
if (!('validated' in decoded))
|
|
563
|
-
return profile.component ? Object.freeze({ ...decoded, phase: 'response' })
|
|
563
|
+
return profile.component ? Object.freeze({ ...decoded, phase: 'response' })
|
|
564
|
+
: Object.freeze({ ...fail(decoded.kind, decoded.rule), ...(decoded.diagnostic ? { diagnostic: decoded.diagnostic } : {}) });
|
|
564
565
|
check();
|
|
565
566
|
check();
|
|
566
567
|
return Object.freeze({ kind: faultInfo ? 'soap-fault' : 'soap-response', admitted: false, decoded,
|
|
@@ -5,6 +5,7 @@ import type { DirectProjectionSlot } from './directStructurePlan.js';
|
|
|
5
5
|
import type { SemanticContext } from './semanticContext.js';
|
|
6
6
|
import type { ResolverUsage } from './semanticBudget.js';
|
|
7
7
|
import type { ProjectionScalarList } from './projectionScalar.js';
|
|
8
|
+
import type { CheckedPayloadDiagnostic } from './payloadDiagnostics.js';
|
|
8
9
|
export type DirectDirection = Readonly<{
|
|
9
10
|
kind: 'input' | 'output';
|
|
10
11
|
} | {
|
|
@@ -20,6 +21,7 @@ export interface DirectScalarDuty {
|
|
|
20
21
|
readonly payloadSource: SyntaxSource;
|
|
21
22
|
readonly payloadPath: string;
|
|
22
23
|
readonly schemaPath: string;
|
|
24
|
+
readonly knownLocation?: string;
|
|
23
25
|
readonly fixedCanonical?: string;
|
|
24
26
|
readonly retainLexical?: true;
|
|
25
27
|
readonly list?: ProjectionScalarList;
|
|
@@ -81,6 +83,7 @@ export type ProjectionStructuralResult = Readonly<{
|
|
|
81
83
|
rule: string;
|
|
82
84
|
schemaPath?: string;
|
|
83
85
|
payloadPath?: string;
|
|
86
|
+
diagnostic?: CheckedPayloadDiagnostic;
|
|
84
87
|
usage: ResolverUsage;
|
|
85
88
|
}>;
|
|
86
89
|
export type ProjectionStructuralMatch = Extract<ProjectionStructuralResult, {
|
|
@@ -104,6 +107,7 @@ export type DirectStructuralResult = Readonly<{
|
|
|
104
107
|
rule: string;
|
|
105
108
|
schemaPath?: string;
|
|
106
109
|
payloadPath?: string;
|
|
110
|
+
diagnostic?: CheckedPayloadDiagnostic;
|
|
107
111
|
usage: ResolverUsage;
|
|
108
112
|
}>;
|
|
109
113
|
export type DirectStructuralMatch = Extract<DirectStructuralResult, {
|
|
@@ -3,6 +3,7 @@ import { inspectDirectOperation } from './directOperation.js';
|
|
|
3
3
|
import { planDirectProjection, flatDirectProjection, matchOrderedProjection, selectProjectionAttribute, isXmlCharacters, isXmlNamespaceBinding } from './directStructurePlan.js';
|
|
4
4
|
import { assertSemanticContext } from './semanticContext.js';
|
|
5
5
|
import { isXmlNCName } from '../loader/orderedSyntax.js';
|
|
6
|
+
import { createPayloadDiagnostic, diagnosticName, appendDiagnosticLocation } from './payloadDiagnostics.js';
|
|
6
7
|
const projectionIssued = new WeakMap();
|
|
7
8
|
/** Native context identity authenticates structure only, never source validity or operation admission. */
|
|
8
9
|
export function inspectProjectionStructuralMatch(match, context) {
|
|
@@ -24,12 +25,14 @@ class Stop extends Error {
|
|
|
24
25
|
rule;
|
|
25
26
|
schemaPath;
|
|
26
27
|
payloadPath;
|
|
27
|
-
|
|
28
|
+
diagnostic;
|
|
29
|
+
constructor(kind, rule, schemaPath, payloadPath, diagnostic) {
|
|
28
30
|
super(rule);
|
|
29
31
|
this.kind = kind;
|
|
30
32
|
this.rule = rule;
|
|
31
33
|
this.schemaPath = schemaPath;
|
|
32
34
|
this.payloadPath = payloadPath;
|
|
35
|
+
this.diagnostic = diagnostic;
|
|
33
36
|
}
|
|
34
37
|
}
|
|
35
38
|
/**
|
|
@@ -160,7 +163,11 @@ export function matchDirectProjection(context, root, payload, options = {}) {
|
|
|
160
163
|
}
|
|
161
164
|
}
|
|
162
165
|
const same = (a, b) => budget.compareText(a.namespace, b.namespace) === 0 && budget.compareText(a.local, b.local) === 0;
|
|
163
|
-
|
|
166
|
+
let currentLocation = '/' + diagnosticName(root.name);
|
|
167
|
+
const mismatch = (rule, declaration, path) => {
|
|
168
|
+
const unknownField = ['unexpected-child', 'unknown-attribute', 'root-name', 'scalar-child', 'ordered-particle-language'].includes(rule);
|
|
169
|
+
throw new Stop('mismatch', rule, declaration.context.source.path, path, createPayloadDiagnostic(context, declaration, unknownField ? appendDiagnosticLocation(currentLocation, '[unknown-field]') : currentLocation, { unknownField }));
|
|
170
|
+
};
|
|
164
171
|
const attributes = (node, declaration, path) => {
|
|
165
172
|
check();
|
|
166
173
|
if (node.attributes.length)
|
|
@@ -188,6 +195,7 @@ export function matchDirectProjection(context, root, payload, options = {}) {
|
|
|
188
195
|
end: { offset: s.end.offset, line: s.end.line, column: s.end.column } });
|
|
189
196
|
occurrences.push({ declaration, type: declaration.type, builtin, lexical, namespaces,
|
|
190
197
|
payloadSource, payloadPath: path, schemaPath: declaration.context.source.path,
|
|
198
|
+
knownLocation: declaration.kind === 'attribute' ? appendDiagnosticLocation(currentLocation, '@' + diagnosticName(declaration.name)) : currentLocation,
|
|
191
199
|
...(fixedCanonical === undefined ? {} : { fixedCanonical }), ...(retainLexical ? { retainLexical } : {}), ...(list ? { list } : {}) });
|
|
192
200
|
};
|
|
193
201
|
const text = (node, declaration, path) => {
|
|
@@ -216,6 +224,7 @@ export function matchDirectProjection(context, root, payload, options = {}) {
|
|
|
216
224
|
check();
|
|
217
225
|
const frame = frames.pop();
|
|
218
226
|
const { declaration, path: parentPath } = frame;
|
|
227
|
+
currentLocation = frame.location ?? '/' + diagnosticName(declaration.name);
|
|
219
228
|
let node = frame.node;
|
|
220
229
|
budget.chargeWork(128 + parentPath.length * 4);
|
|
221
230
|
if (node.kind === 'text') {
|
|
@@ -407,6 +416,15 @@ export function matchDirectProjection(context, root, payload, options = {}) {
|
|
|
407
416
|
dynamicDeclarations: selected.filter(slot => !('value' in slot) && slot.element).map(slot => slot.element),
|
|
408
417
|
...(record.keyed ? { keyed: true } : {}) });
|
|
409
418
|
let selectedIndex = elements.length - 1;
|
|
419
|
+
const occurrenceIndexes = new Map();
|
|
420
|
+
const locations = selected.map(slot => {
|
|
421
|
+
check();
|
|
422
|
+
if (!slot.element)
|
|
423
|
+
return currentLocation;
|
|
424
|
+
const key = slot.element.id, index = (occurrenceIndexes.get(key) ?? 0) + 1;
|
|
425
|
+
occurrenceIndexes.set(key, index);
|
|
426
|
+
return appendDiagnosticLocation(currentLocation, diagnosticName(slot.element.name, index));
|
|
427
|
+
});
|
|
410
428
|
for (let index = node.children.length - 1; index >= 0; index--) {
|
|
411
429
|
check();
|
|
412
430
|
const child = node.children[index];
|
|
@@ -415,13 +433,13 @@ export function matchDirectProjection(context, root, payload, options = {}) {
|
|
|
415
433
|
frames.push({ node: child, path: `${parentPath}/children/${index}`, declaration, value: frame.value, into: content });
|
|
416
434
|
continue;
|
|
417
435
|
}
|
|
418
|
-
const item = elements[selectedIndex], slot = selected[selectedIndex--];
|
|
436
|
+
const item = elements[selectedIndex], childLocation = locations[selectedIndex], slot = selected[selectedIndex--];
|
|
419
437
|
if (!slot.element) {
|
|
420
438
|
frames.push({ node: item.node, path: item.path, declaration, value: frame.value, unassessed: true, into: content });
|
|
421
439
|
continue;
|
|
422
440
|
}
|
|
423
441
|
frames.push({ node: item.node, path: item.path, declaration: slot.element,
|
|
424
|
-
value: 'value' in slot ? slot.value : wildcardValue(slot.element), into: content });
|
|
442
|
+
value: 'value' in slot ? slot.value : wildcardValue(slot.element), into: content, location: childLocation });
|
|
425
443
|
}
|
|
426
444
|
continue;
|
|
427
445
|
}
|
|
@@ -456,7 +474,8 @@ export function matchDirectProjection(context, root, payload, options = {}) {
|
|
|
456
474
|
return mismatch('unexpected-child', declaration, path);
|
|
457
475
|
if (slot.particle.occurs.max === '1' && count === 1)
|
|
458
476
|
return mismatch('duplicate-singleton', slot.element, path);
|
|
459
|
-
children.push({ node: child, declaration: slot.element, value: slot.value, path, into: matchedSlots[cursor].items
|
|
477
|
+
children.push({ node: child, declaration: slot.element, value: slot.value, path, into: matchedSlots[cursor].items,
|
|
478
|
+
location: appendDiagnosticLocation(currentLocation, diagnosticName(slot.element.name, count + 1)) });
|
|
460
479
|
count++;
|
|
461
480
|
}
|
|
462
481
|
for (; cursor < slots.length; cursor++, count = 0) {
|
|
@@ -488,7 +507,8 @@ export function matchDirectProjection(context, root, payload, options = {}) {
|
|
|
488
507
|
if (budget.exhausted())
|
|
489
508
|
return Object.freeze({ kind: 'resource-limit', rule: 'request-budget', usage: budget.usage() });
|
|
490
509
|
if (error instanceof Stop)
|
|
491
|
-
return Object.freeze({ kind: error.kind, rule: error.rule, schemaPath: error.schemaPath, payloadPath: error.payloadPath,
|
|
510
|
+
return Object.freeze({ kind: error.kind, rule: error.rule, schemaPath: error.schemaPath, payloadPath: error.payloadPath,
|
|
511
|
+
...(error.diagnostic ? { diagnostic: error.diagnostic } : {}), usage: Object.freeze({ ...budget.usage() }) });
|
|
492
512
|
throw error;
|
|
493
513
|
}
|
|
494
514
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CheckedPayloadDiagnostic } from './payloadDiagnostics.js';
|
|
1
2
|
import type { DirectOperationContract, DirectMessageRoot, RpcMessageRoot } from './directOperation.js';
|
|
2
3
|
import type { DirectDirection, DirectScalarDuty, DirectStructuralMatch } from './directStructure.js';
|
|
3
4
|
import type { DirectRootPlan, DirectProjectionPlan } from './directStructurePlan.js';
|
|
@@ -96,6 +97,7 @@ export interface DirectValueFailure {
|
|
|
96
97
|
readonly schemaPath?: string;
|
|
97
98
|
readonly payloadPath?: string;
|
|
98
99
|
readonly usage: ResolverUsage;
|
|
100
|
+
readonly diagnostic?: CheckedPayloadDiagnostic;
|
|
99
101
|
}
|
|
100
102
|
type Options = Readonly<{
|
|
101
103
|
signal?: AbortSignal;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { directDataOwnership, directLimit } from './directExecutionPolicy.js';
|
|
2
|
+
import { createPayloadDiagnostic, diagnosticName } from './payloadDiagnostics.js';
|
|
2
3
|
import { types } from 'node:util';
|
|
3
4
|
/** Internal direct value chain. No XML encoding, transport or runtime admission. */
|
|
4
5
|
import { checkSemanticBudget } from './semanticBudget.js';
|
|
@@ -60,12 +61,14 @@ class Stop extends Error {
|
|
|
60
61
|
rule;
|
|
61
62
|
schemaPath;
|
|
62
63
|
payloadPath;
|
|
63
|
-
|
|
64
|
+
diagnostic;
|
|
65
|
+
constructor(kind, rule, schemaPath, payloadPath, diagnostic) {
|
|
64
66
|
super(rule);
|
|
65
67
|
this.kind = kind;
|
|
66
68
|
this.rule = rule;
|
|
67
69
|
this.schemaPath = schemaPath;
|
|
68
70
|
this.payloadPath = payloadPath;
|
|
71
|
+
this.diagnostic = diagnostic;
|
|
69
72
|
}
|
|
70
73
|
}
|
|
71
74
|
function run(contract, options, work) {
|
|
@@ -96,7 +99,7 @@ function runContext(context, options, work) {
|
|
|
96
99
|
return { kind: 'resource-limit', rule: error.message, usage: budget.usage() };
|
|
97
100
|
if (error instanceof Stop)
|
|
98
101
|
return Object.freeze({ kind: error.kind, rule: error.rule, schemaPath: error.schemaPath,
|
|
99
|
-
payloadPath: error.payloadPath, usage: Object.freeze({ ...budget.usage() }) });
|
|
102
|
+
payloadPath: error.payloadPath, ...(error.diagnostic ? { diagnostic: error.diagnostic } : {}), usage: Object.freeze({ ...budget.usage() }) });
|
|
100
103
|
if (error instanceof ApplicationGroupValueError)
|
|
101
104
|
return Object.freeze({ kind: 'value-invalid', rule: error.message, usage: Object.freeze({ ...budget.usage() }) });
|
|
102
105
|
throw error;
|
|
@@ -192,8 +195,9 @@ export function inspectComponentValueMapping(value, contract) {
|
|
|
192
195
|
}
|
|
193
196
|
function scalar(duty, s, context) {
|
|
194
197
|
const { budget, check } = s;
|
|
195
|
-
const
|
|
196
|
-
const
|
|
198
|
+
const diagnostic = () => createPayloadDiagnostic(context, duty.declaration, duty.knownLocation ?? '/' + diagnosticName(duty.declaration.name), { builtin: duty.builtin });
|
|
199
|
+
const fail = (_owner, rule) => { throw new Stop('scalar-invalid', rule, duty.schemaPath, duty.payloadPath, diagnostic()); };
|
|
200
|
+
const unavailable = () => { throw new Stop('unsupported', 'direct-datatype-prerequisite', duty.schemaPath, duty.payloadPath, diagnostic()); };
|
|
197
201
|
// This is a neutral lexical operand, not a schema LexicalValue or checked receipt.
|
|
198
202
|
const core = datatypeValues({
|
|
199
203
|
step: (_owner, count = 1) => { check(); budget.chargeWork(count); },
|
|
@@ -208,11 +212,11 @@ function scalar(duty, s, context) {
|
|
|
208
212
|
const assessed = assessProjectionScalarOperand(context, duty.declaration, lexical, check);
|
|
209
213
|
check();
|
|
210
214
|
if (assessed.kind !== 'projection-scalar-operand')
|
|
211
|
-
throw new Stop(assessed.kind === 'scalar-invalid' ? 'scalar-invalid' : assessed.kind === 'resource-limit' ? 'resource-limit' : 'unsupported', 'rule' in assessed ? assessed.rule : 'request-budget', duty.schemaPath, duty.payloadPath);
|
|
215
|
+
throw new Stop(assessed.kind === 'scalar-invalid' ? 'scalar-invalid' : assessed.kind === 'resource-limit' ? 'resource-limit' : 'unsupported', 'rule' in assessed ? assessed.rule : 'request-budget', duty.schemaPath, duty.payloadPath, diagnostic());
|
|
212
216
|
result = assessed.operand;
|
|
213
217
|
}
|
|
214
218
|
if (duty.fixedCanonical !== undefined && budget.compareText(result.canonical, duty.fixedCanonical) !== 0)
|
|
215
|
-
throw new Stop('scalar-invalid', duty.declaration.kind === 'attribute' ? 'fixed-attribute-value' : 'fixed-element-value', duty.schemaPath, duty.payloadPath);
|
|
219
|
+
throw new Stop('scalar-invalid', duty.declaration.kind === 'attribute' ? 'fixed-attribute-value' : 'fixed-element-value', duty.schemaPath, duty.payloadPath, diagnostic());
|
|
216
220
|
const normalized = result.normalized ?? normalizeWhitespace(duty.lexical, whitespaceFor(duty.builtin.local));
|
|
217
221
|
const present = (operand, builtin, lexical, retainLexical) => {
|
|
218
222
|
check();
|
|
@@ -1097,14 +1101,14 @@ export function expandProjectionValue(context, root, application, options = {},
|
|
|
1097
1101
|
if (structural.kind !== 'projection-match') {
|
|
1098
1102
|
if (structural.kind === 'mismatch') {
|
|
1099
1103
|
if (structural.rule === 'ordered-particle-language')
|
|
1100
|
-
throw new Stop('value-invalid', structural.rule, structural.schemaPath, structural.payloadPath);
|
|
1104
|
+
throw new Stop('value-invalid', structural.rule, structural.schemaPath, structural.payloadPath, structural.diagnostic);
|
|
1101
1105
|
throw new Error('Internal projection expansion violated its source mapping');
|
|
1102
1106
|
}
|
|
1103
|
-
throw new Stop(structural.kind, structural.rule, structural.schemaPath, structural.payloadPath);
|
|
1107
|
+
throw new Stop(structural.kind, structural.rule, structural.schemaPath, structural.payloadPath, structural.diagnostic);
|
|
1104
1108
|
}
|
|
1105
1109
|
const validated = assessProjectionScalars(context, structural, options, mapping);
|
|
1106
1110
|
if (validated.kind !== 'projection-value')
|
|
1107
|
-
throw new Stop(validated.kind, validated.rule, validated.schemaPath, validated.payloadPath);
|
|
1111
|
+
throw new Stop(validated.kind, validated.rule, validated.schemaPath, validated.payloadPath, validated.diagnostic);
|
|
1108
1112
|
const expanded = s.publish({ kind: 'projection-expanded', provenance: 'generated-direct-value', admitted: false, payload, validated });
|
|
1109
1113
|
projectionExpansions.set(expanded, context);
|
|
1110
1114
|
return expanded;
|
|
@@ -1122,7 +1126,7 @@ export function expandDirectValue(contract, suppliedMapping, application, option
|
|
|
1122
1126
|
if (structural.kind !== 'structural-match') {
|
|
1123
1127
|
if (structural.kind === 'mismatch')
|
|
1124
1128
|
throw new Error('Internal direct expansion violated its source mapping');
|
|
1125
|
-
throw new Stop(structural.kind, structural.rule, structural.schemaPath, structural.payloadPath);
|
|
1129
|
+
throw new Stop(structural.kind, structural.rule, structural.schemaPath, structural.payloadPath, structural.diagnostic);
|
|
1126
1130
|
}
|
|
1127
1131
|
const validated = assessed(contract, structural, mapping, s);
|
|
1128
1132
|
const expanded = s.publish({ kind: 'direct-expanded', provenance: 'generated-direct-value', admitted: false, payload, validated });
|