@techspokes/typescript-wsdl-client 1.3.0 → 1.4.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 (34) hide show
  1. package/README.md +8 -0
  2. package/dist/checkedPipeline.d.ts +73 -2
  3. package/dist/checkedPipeline.js +118 -8
  4. package/dist/checkedPlanning.d.ts +5 -2
  5. package/dist/checkedPlanning.js +30 -5
  6. package/dist/checkedResponseInspection.d.ts +100 -0
  7. package/dist/checkedResponseInspection.js +499 -0
  8. package/dist/cli.js +55 -1
  9. package/dist/client/checkedDirectRuntime.d.ts +8 -0
  10. package/dist/client/checkedDirectRuntime.js +22 -14
  11. package/dist/client/directClientRuntime.d.ts +10 -3
  12. package/dist/client/directClientRuntime.js +14 -8
  13. package/dist/client/directClientVersion.d.ts +2 -0
  14. package/dist/client/directClientVersion.js +2 -0
  15. package/dist/client/generateDirectClient.js +7 -7
  16. package/dist/compiler/componentRecordProjection.d.ts +1 -0
  17. package/dist/compiler/componentRecordProjection.js +15 -4
  18. package/dist/compiler/directCodec.js +3 -11
  19. package/dist/compiler/directSoap.d.ts +50 -5
  20. package/dist/compiler/directSoap.js +204 -98
  21. package/dist/compiler/sourceCorrections.d.ts +118 -0
  22. package/dist/compiler/sourceCorrections.js +794 -0
  23. package/dist/gateway/generateCheckedGateway.js +9 -10
  24. package/dist/index.d.ts +3 -1
  25. package/dist/index.js +2 -1
  26. package/dist/util/readBoundedFile.d.ts +9 -0
  27. package/dist/util/readBoundedFile.js +36 -0
  28. package/dist/util/xmlBytes.d.ts +9 -0
  29. package/dist/util/xmlBytes.js +24 -0
  30. package/docs/api-reference.md +28 -1
  31. package/docs/checked-gateway.md +44 -0
  32. package/docs/cli-reference.md +16 -1
  33. package/docs/migration.md +10 -0
  34. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import { types } from 'node:util';
2
- import { directClientRuntime, componentClientRuntime, componentSoap12ClientRuntime } from './directClientRuntime.js';
3
- import { DIRECT_CLIENT_RUNTIME_VERSION, DIRECT_CLIENT_RUNTIME_REPAIR, COMPONENT_CLIENT_RUNTIME_VERSION, COMPONENT_CLIENT_RUNTIME_REPAIR, COMPONENT_SOAP12_CLIENT_RUNTIME_VERSION } from './directClientVersion.js';
2
+ import { directClientRuntime, componentClientRuntime, componentSoap11ClientRuntime, componentSoap12ClientRuntime } from './directClientRuntime.js';
3
+ import { DIRECT_CLIENT_RUNTIME_VERSION, DIRECT_CLIENT_RUNTIME_REPAIR, COMPONENT_CLIENT_RUNTIME_VERSION, COMPONENT_CLIENT_RUNTIME_REPAIR, COMPONENT_SOAP11_CLIENT_RUNTIME_VERSION, COMPONENT_SOAP12_CLIENT_RUNTIME_VERSION } from './directClientVersion.js';
4
4
  function dataOptions(options, allowed) {
5
5
  return !!options && typeof options === 'object' && !types.isProxy(options)
6
6
  && [null, Object.prototype].includes(Object.getPrototypeOf(options))
@@ -41,20 +41,28 @@ export const checkedComponentRuntimeV1 = Object.freeze({
41
41
  return componentClientRuntime.execute(expectedBase64, input, options);
42
42
  },
43
43
  });
44
+ function checkedProtocolRuntime(runtime) {
45
+ return Object.freeze({
46
+ version: runtime.version,
47
+ async execute(expectedBase64, input, options, version) {
48
+ if (version !== runtime.version)
49
+ return Object.freeze({ kind: 'incompatible-artifact',
50
+ rule: 'generated-runtime-version', repair: COMPONENT_CLIENT_RUNTIME_REPAIR, usage: Object.freeze({ nodes: 0, work: 0 }) });
51
+ if (!dataOptions(options, ['localSource', 'fileRoots', 'capsule', 'soap', 'sourceResources', 'sourceOrigins', 'sourceUri', 'namespaceLocations', 'standardLibraries', 'recordSources'])) {
52
+ return Object.freeze({ kind: 'unsupported', rule: 'data-only checked component options required', usage: Object.freeze({ nodes: 0, work: 0 }) });
53
+ }
54
+ return runtime.execute(expectedBase64, input, options);
55
+ },
56
+ });
57
+ }
44
58
  /** Additive SOAP 1.2 binding permits protocol faults without declared application detail.
45
59
  * @since 1.3.0
46
60
  * @remarks Source reconstruction, endpoint restrictions and native validation use the shared component runtime.
47
61
  * @returns Native component values, SOAP 1.2 protocol faults or explicit refusal; no full-profile admission.
48
62
  */
49
- export const checkedComponentRuntimeV2 = Object.freeze({
50
- version: COMPONENT_SOAP12_CLIENT_RUNTIME_VERSION,
51
- async execute(expectedBase64, input, options, version) {
52
- if (version !== COMPONENT_SOAP12_CLIENT_RUNTIME_VERSION)
53
- return Object.freeze({ kind: 'incompatible-artifact',
54
- rule: 'generated-runtime-version', repair: COMPONENT_CLIENT_RUNTIME_REPAIR, usage: Object.freeze({ nodes: 0, work: 0 }) });
55
- if (!dataOptions(options, ['localSource', 'fileRoots', 'capsule', 'soap', 'sourceResources', 'sourceOrigins', 'sourceUri', 'namespaceLocations', 'standardLibraries', 'recordSources'])) {
56
- return Object.freeze({ kind: 'unsupported', rule: 'data-only checked component options required', usage: Object.freeze({ nodes: 0, work: 0 }) });
57
- }
58
- return componentSoap12ClientRuntime.execute(expectedBase64, input, options);
59
- },
60
- });
63
+ export const checkedComponentRuntimeV2 = checkedProtocolRuntime(componentSoap12ClientRuntime);
64
+ /** SOAP 1.1 binding for generated clients that distinguish protocol faults from declared detail values.
65
+ * @since 1.4.0
66
+ * @returns Native-validated values, SOAP 1.1 protocol faults with their original bytes, or explicit refusal.
67
+ */
68
+ export const checkedComponentRuntimeV3 = checkedProtocolRuntime(componentSoap11ClientRuntime);
@@ -1,6 +1,6 @@
1
1
  import type { SemanticBudgetLimits, ResolverUsage } from '../compiler/semanticBudget.js';
2
2
  import type { DirectCapsuleFailure } from '../compiler/directSourceCapsule.js';
3
- import type { DirectSoapOptions, ComponentSoapOptions, DirectSoapFailure, ComponentProtocolFault, DeclaredSoapFault } from '../compiler/directSoap.js';
3
+ import type { DirectSoapOptions, ComponentSoapOptions, DirectSoapFailure, ComponentProtocolFault, DeclaredSoapFault, Soap11FaultMetadata, Soap12FaultMetadata } from '../compiler/directSoap.js';
4
4
  import type { DirectOperationSelector } from '../compiler/directOperation.js';
5
5
  import type { DirectApplicationValue } from '../compiler/directValues.js';
6
6
  import { DIRECT_CLIENT_RUNTIME_VERSION } from './directClientVersion.js';
@@ -68,9 +68,9 @@ export interface DirectClientRuntime {
68
68
  /** Component-only protocol faults retain raw bytes without claiming an application value.
69
69
  * @since 1.3.0
70
70
  */
71
- export type ComponentClientResult = Exclude<DirectClientResult, {
71
+ export type ComponentClientResult<F extends Soap11FaultMetadata | Soap12FaultMetadata = Soap12FaultMetadata> = Exclude<DirectClientResult, {
72
72
  kind: 'soap-fault';
73
- }> | ComponentProtocolFault | Readonly<Omit<Extract<DirectClientResult, {
73
+ }> | ComponentProtocolFault<F> | Readonly<Omit<Extract<DirectClientResult, {
74
74
  kind: 'soap-fault';
75
75
  }>, 'fault'> & {
76
76
  fault: Omit<DeclaredSoapFault, 'codeNode'>;
@@ -89,3 +89,10 @@ export declare const componentSoap12ClientRuntime: Readonly<{
89
89
  version: "checked-component-soap12-runtime-v1";
90
90
  execute: (expectedBase64: string, input: unknown, options: ComponentClientOptions) => Promise<ComponentClientResult>;
91
91
  }>;
92
+ /** SOAP 1.1 protocol faults require a generated client that can represent a missing application value.
93
+ * @since 1.4.0
94
+ */
95
+ export declare const componentSoap11ClientRuntime: Readonly<{
96
+ version: "checked-component-soap11-runtime-v1";
97
+ execute: (expectedBase64: string, input: unknown, options: ComponentClientOptions) => Promise<ComponentClientResult<Soap11FaultMetadata>>;
98
+ }>;
@@ -6,7 +6,7 @@ import { types } from 'node:util';
6
6
  import { createApplicationBudget } from '../compiler/semanticBudget.js';
7
7
  import { reconstructDirectSourceCapsuleInRequest, reconstructComponentSourceCapsuleInRequest, checkDirectSourceCompatibility, DIRECT_CAPSULE_LIMITS } from '../compiler/directSourceCapsule.js';
8
8
  import { exchangeDirectSoap, exchangeComponentSoap, directSoapOptionsShape } from '../compiler/directSoap.js';
9
- import { DIRECT_CLIENT_RUNTIME_VERSION, COMPONENT_CLIENT_RUNTIME_VERSION, COMPONENT_SOAP12_CLIENT_RUNTIME_VERSION } from './directClientVersion.js';
9
+ import { DIRECT_CLIENT_RUNTIME_VERSION, COMPONENT_CLIENT_RUNTIME_VERSION, COMPONENT_SOAP11_CLIENT_RUNTIME_VERSION, COMPONENT_SOAP12_CLIENT_RUNTIME_VERSION } from './directClientVersion.js';
10
10
  import { prepareSchemaSnapshotFiles } from '../loader/schemaInput.js';
11
11
  import { SchemaLoadingError } from '../loader/orderedSyntax.js';
12
12
  /** The generated literal is the expected artifact; caller bytes never choose its static contract. */
@@ -24,9 +24,16 @@ export const componentClientRuntime = Object.freeze({
24
24
  */
25
25
  export const componentSoap12ClientRuntime = Object.freeze({
26
26
  version: COMPONENT_SOAP12_CLIENT_RUNTIME_VERSION,
27
- execute: (expectedBase64, input, options) => executeClient(expectedBase64, input, options, true, true),
27
+ execute: (expectedBase64, input, options) => executeClient(expectedBase64, input, options, true, '1.2'),
28
28
  });
29
- async function executeClient(expectedBase64, input, options, component, allowSoap12 = false) {
29
+ /** SOAP 1.1 protocol faults require a generated client that can represent a missing application value.
30
+ * @since 1.4.0
31
+ */
32
+ export const componentSoap11ClientRuntime = Object.freeze({
33
+ version: COMPONENT_SOAP11_CLIENT_RUNTIME_VERSION,
34
+ execute: (expectedBase64, input, options) => executeClient(expectedBase64, input, options, true, '1.1'),
35
+ });
36
+ async function executeClient(expectedBase64, input, options, component, protocol) {
30
37
  // Constant-sized entry introspection precedes budget configuration and all reads.
31
38
  const entryFailure = () => ({ kind: 'unsupported', rule: 'data-only client options required', usage: { nodes: 0, work: 0 } });
32
39
  if (!options || typeof options !== 'object' || types.isProxy(options)
@@ -128,13 +135,12 @@ async function executeClient(expectedBase64, input, options, component, allowSoa
128
135
  standardLibraries: sources.standards, recordSources: sources.records }, budget);
129
136
  if (fresh.kind !== 'reconstructed-component')
130
137
  return fresh;
131
- if (fresh.contract.binding.version === '1.2' && !allowSoap12)
138
+ if (fresh.contract.binding.version === '1.2' && protocol !== '1.2')
132
139
  return fail('incompatible-artifact', 'SOAP 1.2 runtime binding required');
133
140
  if (fresh.selection.port !== options.soap.port || fresh.selection.service.namespace !== options.soap.service.namespace
134
141
  || fresh.selection.service.local !== options.soap.service.local)
135
142
  return fail('incompatible-artifact', 'explicit source selection mismatch');
136
- result = fresh.responseProjection ? await exchangeComponentSoap(fresh.contract, fresh.mappings[0], input, supplied.soap, fresh.responseProjection)
137
- : await exchangeComponentSoap(fresh.contract, fresh.mappings[0], input, supplied.soap);
143
+ result = await exchangeComponentSoap(fresh.contract, fresh.mappings[0], input, supplied.soap, fresh.responseProjection, protocol === '1.1');
138
144
  }
139
145
  else {
140
146
  const fresh = await reconstructDirectSourceCapsuleInRequest(bytes, options.localSource, { policy: { fileRoots: options.fileRoots }, limits: options.budget, signal: options.soap.signal }, budget);
@@ -148,8 +154,8 @@ async function executeClient(expectedBase64, input, options, component, allowSoa
148
154
  result = await exchangeDirectSoap(fresh.contract, fresh.mappings[0], input, options.soap);
149
155
  }
150
156
  if (!('decoded' in result)) {
151
- if (result.kind === 'soap-fault' && !allowSoap12)
152
- return fail('incompatible-artifact', 'SOAP 1.2 runtime binding required');
157
+ if (result.kind === 'soap-fault' && result.fault.version !== protocol)
158
+ throw new TypeError('Protocol fault requires its generated runtime binding');
153
159
  return result;
154
160
  }
155
161
  if (options.soap.signal?.aborted)
@@ -5,4 +5,6 @@ export declare const DIRECT_CLIENT_RUNTIME_REPAIR = "Regenerate matched direct c
5
5
  export declare const COMPONENT_CLIENT_RUNTIME_VERSION: "checked-component-runtime-v2";
6
6
  /** SOAP 1.2 can return protocol faults without declared application values. */
7
7
  export declare const COMPONENT_SOAP12_CLIENT_RUNTIME_VERSION: "checked-component-soap12-runtime-v1";
8
+ /** SOAP 1.1 component clients with value-less protocol faults use their own injection contract. */
9
+ export declare const COMPONENT_SOAP11_CLIENT_RUNTIME_VERSION: "checked-component-soap11-runtime-v1";
8
10
  export declare const COMPONENT_CLIENT_RUNTIME_REPAIR = "Regenerate matched component client and source artifacts with the installed runtime.";
@@ -5,4 +5,6 @@ export const DIRECT_CLIENT_RUNTIME_REPAIR = 'Regenerate matched direct client an
5
5
  export const COMPONENT_CLIENT_RUNTIME_VERSION = 'checked-component-runtime-v2';
6
6
  /** SOAP 1.2 can return protocol faults without declared application values. */
7
7
  export const COMPONENT_SOAP12_CLIENT_RUNTIME_VERSION = 'checked-component-soap12-runtime-v1';
8
+ /** SOAP 1.1 component clients with value-less protocol faults use their own injection contract. */
9
+ export const COMPONENT_SOAP11_CLIENT_RUNTIME_VERSION = 'checked-component-soap11-runtime-v1';
8
10
  export const COMPONENT_CLIENT_RUNTIME_REPAIR = 'Regenerate matched component client and source artifacts with the installed runtime.';
@@ -1,5 +1,5 @@
1
1
  import { directLimit } from '../compiler/directExecutionPolicy.js';
2
- import { DIRECT_CLIENT_RUNTIME_VERSION, DIRECT_CLIENT_RUNTIME_REPAIR, COMPONENT_CLIENT_RUNTIME_VERSION, COMPONENT_CLIENT_RUNTIME_REPAIR, COMPONENT_SOAP12_CLIENT_RUNTIME_VERSION } from './directClientVersion.js';
2
+ import { DIRECT_CLIENT_RUNTIME_VERSION, DIRECT_CLIENT_RUNTIME_REPAIR, COMPONENT_SOAP11_CLIENT_RUNTIME_VERSION, COMPONENT_CLIENT_RUNTIME_REPAIR, COMPONENT_SOAP12_CLIENT_RUNTIME_VERSION } from './directClientVersion.js';
3
3
  /** Native-plan generator consumed by the opt-in checked pipeline. */
4
4
  import { checkSemanticBudget } from '../compiler/semanticBudget.js';
5
5
  import { writeFileSync, mkdirSync } from 'node:fs';
@@ -171,9 +171,9 @@ export async function generateComponentClient(expected, signal) {
171
171
  ...faults.flatMap(({ shape }, index) => [...shape.declarations, `export type Fault_${index} = ${shape.type};`])
172
172
  ];
173
173
  const soap12 = expected.contract.binding.version === '1.2';
174
- const runtimeVersion = soap12 ? COMPONENT_SOAP12_CLIENT_RUNTIME_VERSION : COMPONENT_CLIENT_RUNTIME_VERSION;
174
+ const runtimeVersion = soap12 ? COMPONENT_SOAP12_CLIENT_RUNTIME_VERSION : COMPONENT_SOAP11_CLIENT_RUNTIME_VERSION;
175
175
  const lines = [
176
- `// Checked component client; inject ${soap12 ? 'checkedComponentRuntimeV2' : 'checkedComponentRuntimeV1'} from the package root.`,
176
+ `// Checked component client; inject ${soap12 ? 'checkedComponentRuntimeV2' : 'checkedComponentRuntimeV3'} from the package root.`,
177
177
  '// Scalar facets, ordered occurrence correlation and wildcard membership remain native runtime duties.',
178
178
  ...declarations,
179
179
  'export interface Usage {readonly nodes: number; readonly work: number}',
@@ -193,9 +193,9 @@ export async function generateComponentClient(expected, signal) {
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
195
  ' readonly rule: string; readonly repair?: string; readonly phase?: "input" | "response"; readonly usage: Usage}',
196
- `export interface NativeSuccess {readonly kind: "soap-response" | "soap-fault"; readonly value${soap12 ? '?' : ''}: unknown; readonly admitted: false;`,
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
- ` readonly fault?: {readonly name${soap12 ? '?' : ''}: string; readonly code: Name; readonly string: string; readonly actor?: string}}`,
198
+ ' readonly fault?: {readonly name?: string; readonly code: Name; readonly string: string; readonly actor?: string}}',
199
199
  `export interface Runtime {readonly version: ${literal(runtimeVersion)}; execute(expectedBase64: string, input: unknown, options: Options, version: ${literal(runtimeVersion)}): Promise<Failure | NativeSuccess>}`,
200
200
  'type Common = {readonly admitted: false; readonly status: number; readonly usage: Usage; readonly responseBytes: Uint8Array};',
201
201
  'export type Result = Failure | (Common & {readonly kind: "soap-response"; readonly value: Response})',
@@ -205,8 +205,8 @@ export async function generateComponentClient(expected, signal) {
205
205
  return soap12 ? ` | (Common & {readonly kind: "soap-fault"; readonly value: Fault_${index}; readonly fault: Soap12Fault & {readonly name: ${literal(mapping.direction.name)}}})`
206
206
  : ` | (Common & {readonly kind: "soap-fault"; readonly value: Fault_${index}; readonly fault: {readonly name: ${literal(mapping.direction.name)}; readonly code: Name; readonly string: string; readonly actor?: string}})`;
207
207
  }),
208
- ...(soap12 ? [' | (Common & {readonly kind: "soap-fault"; readonly value?: never; readonly fault: Soap12Fault & {readonly name?: never}})']
209
- : faults.length ? [] : [' | (Common & {readonly kind: "soap-fault"; readonly value: never; readonly fault: {readonly name: never; readonly code: Name; readonly string: string; readonly actor?: string}})']),
208
+ soap12 ? ' | (Common & {readonly kind: "soap-fault"; readonly value?: never; readonly fault: Soap12Fault & {readonly name?: never}})'
209
+ : ' | (Common & {readonly kind: "soap-fault"; readonly value?: never; readonly fault: {readonly version: "1.1"; readonly name?: never; readonly code: Name; readonly string: string; readonly actor?: string}})',
210
210
  ';',
211
211
  `export const expectedCapsuleBase64 = ${literal(Buffer.from(capsule.bytes).toString('base64'))};`,
212
212
  `export const selection = ${literal(JSON.stringify({ selector: expected.contract.selector, ...expected.selection }))};`,
@@ -57,6 +57,7 @@ export interface ComponentRecordDecodedXml {
57
57
  type Leaf = Readonly<{
58
58
  kind: 'standard';
59
59
  declaration: StandardSchemaElementDeclaration;
60
+ optional: boolean;
60
61
  } | {
61
62
  kind: 'boundary';
62
63
  namespace: NamespaceConstraint;
@@ -160,7 +160,9 @@ export function createComponentRecordProjection(outer, companion, supplied, opti
160
160
  while (pending.length) {
161
161
  check();
162
162
  const particle = pending.pop();
163
- if (particle.occurs.min !== '1' || particle.occurs.max !== '1')
163
+ // @why Only metadata may be absent, and only when the authenticated source declares it optional.
164
+ if (particle.occurs.max !== '1' || (particle.occurs.min !== '1'
165
+ && !(particle.standardElement && particle.occurs.min === '0')))
164
166
  stop('record-wrapper-unit-occurrence');
165
167
  if (particle.kind === 'sequence')
166
168
  for (let index = particle.children.length - 1; index >= 0; index--) {
@@ -168,7 +170,7 @@ export function createComponentRecordProjection(outer, companion, supplied, opti
168
170
  pending.push(particle.children[index]);
169
171
  }
170
172
  else if (particle.standardElement)
171
- leaves.push(Object.freeze({ kind: 'standard', declaration: particle.standardElement }));
173
+ leaves.push(Object.freeze({ kind: 'standard', declaration: particle.standardElement, optional: particle.occurs.min === '0' }));
172
174
  else if (particle.kind === 'any' && particle.wildcard?.processContents === 'strict') {
173
175
  if (++boundaries > 1 || !namespaceAllows(particle.wildcard.namespace, spec.payloadPath[0].namespace, budget.chargeWork))
174
176
  stop('record-wrapper-wildcard-boundary');
@@ -266,12 +268,19 @@ export function decodeComponentRecordXml(outer, projection, bytes, options = {})
266
268
  if (wrapper.attributes.length || wrapper.children.some(node => node.kind === 'text' && /[^\t\r\n ]/.test(node.value)))
267
269
  throw new ScopeStop('mismatch', 'record-wrapper-attributes-or-text');
268
270
  const children = syntaxElements(wrapper);
269
- if (children.length !== owned.leaves.length)
271
+ const required = owned.leaves.filter(leaf => leaf.kind === 'boundary' || !leaf.optional).length;
272
+ if (children.length < required || children.length > owned.leaves.length)
270
273
  throw new ScopeStop('mismatch', 'record-wrapper-child-count');
271
274
  let payload;
275
+ let cursor = 0;
272
276
  for (let index = 0; index < owned.leaves.length; index++) {
273
277
  check();
274
- const leaf = owned.leaves[index], child = children[index];
278
+ const leaf = owned.leaves[index], child = children[cursor];
279
+ if (leaf.kind === 'standard' && leaf.optional && (!child || !same(child.name, leaf.declaration.name)))
280
+ continue;
281
+ if (!child)
282
+ throw new ScopeStop('mismatch', 'record-wrapper-child-count');
283
+ cursor++;
275
284
  if (leaf.kind === 'standard') {
276
285
  if (!same(child.name, leaf.declaration.name))
277
286
  throw new ScopeStop('mismatch', 'record-wrapper-standard-order');
@@ -287,6 +296,8 @@ export function decodeComponentRecordXml(outer, projection, bytes, options = {})
287
296
  payload = child;
288
297
  }
289
298
  }
299
+ if (cursor !== children.length)
300
+ throw new ScopeStop('mismatch', 'record-wrapper-child-count');
290
301
  if (!payload)
291
302
  throw new TypeError('Native record boundary unavailable');
292
303
  const decoded = assessObservedComponentPayload(owned.companion, owned.mapping, observation, payload, options);
@@ -3,6 +3,7 @@ import { directDataOwnership, directLimit } from './directExecutionPolicy.js';
3
3
  import { checkSemanticBudget } from './semanticBudget.js';
4
4
  import { DataOwnershipLimitError } from './dataOwnership.js';
5
5
  import { types } from 'node:util';
6
+ import { xmlByteLength, snapshotXmlBytes } from '../util/xmlBytes.js';
6
7
  import { inspectDirectOperation, isRpcMessageRoot } from './directOperation.js';
7
8
  import { inspectDirectValueMapping, expandDirectValue, assessDirectScalars, inspectComponentValueMapping, expandProjectionValue, assessProjectionScalars } from './directValues.js';
8
9
  import { matchDirectOperation, matchDirectProjection } from './directStructure.js';
@@ -262,20 +263,11 @@ export function encodeComponentXml(contract, mapping, application, options = {})
262
263
  }
263
264
  /** Retain the shared byte-copy, XML-version, entity and explicit capacity boundaries for both profiles. */
264
265
  function parseObservedXml(bytes, { budget, limits, check }, sourceUri, componentResponseEncoding) {
265
- if (!types.isUint8Array(bytes) || types.isProxy(bytes))
266
- throw new TypeError('XML requires Uint8Array bytes');
267
- // Use native internal-slot access, avoiding subclass/own length, buffer and
268
- // iterator getters. Shared backing stores are outside the data-only contract.
269
- const typed = Object.getPrototypeOf(Uint8Array.prototype);
270
- const length = Object.getOwnPropertyDescriptor(typed, 'byteLength').get.call(bytes);
271
- const backing = Object.getOwnPropertyDescriptor(typed, 'buffer').get.call(bytes);
272
- if (types.isSharedArrayBuffer(backing))
273
- throw new TypeError('Shared XML bytes are unsupported');
266
+ const length = xmlByteLength(bytes);
274
267
  if (length > limits.maxBytes)
275
268
  throw new Stop('resource-limit', 'XML byte limit');
276
269
  check();
277
- const input = new Uint8Array(length);
278
- Uint8Array.prototype.set.call(input, bytes);
270
+ const input = snapshotXmlBytes(bytes);
279
271
  const uri = sourceUri ?? 'urn:typescript-wsdl-client:observed-direct-xml';
280
272
  if (typeof uri !== 'string')
281
273
  throw new TypeError('XML source URI must be a string');
@@ -1,6 +1,6 @@
1
1
  import type { DirectOperationContract } from './directOperation.js';
2
2
  import type { DirectCodecFailure, DirectDecodedXml, ComponentDecodedXml, DirectXmlLimits } from './directCodec.js';
3
- import type { ExpandedName, SyntaxElement } from '../loader/orderedSyntax.js';
3
+ import type { ExpandedName, SyntaxElement, SyntaxSource } from '../loader/orderedSyntax.js';
4
4
  import type { ResolverUsage } from './semanticBudget.js';
5
5
  import type { ComponentRecordProjection, ComponentRecordDecodedXml } from './componentRecordProjection.js';
6
6
  export interface DirectSoapOptions {
@@ -20,6 +20,9 @@ export interface DirectSoapFailure {
20
20
  readonly rule: string;
21
21
  readonly usage: ResolverUsage;
22
22
  readonly phase?: 'input' | 'response';
23
+ readonly source?: SyntaxSource;
24
+ readonly schemaPath?: string;
25
+ readonly payloadPath?: string;
23
26
  }
24
27
  /** Version-specific protocol metadata; application detail remains owned by native mappings.
25
28
  * @since 1.3.0
@@ -36,6 +39,16 @@ export interface Soap12FaultMetadata {
36
39
  readonly node?: string;
37
40
  readonly role?: string;
38
41
  }
42
+ /** SOAP 1.1 protocol fields retained when the selected operation supplies no matching detail.
43
+ * @since 1.4.0
44
+ */
45
+ export interface Soap11FaultMetadata {
46
+ readonly version: '1.1';
47
+ readonly code: ExpandedName;
48
+ readonly string: string;
49
+ readonly actor?: string;
50
+ }
51
+ type ProtocolFaultMetadata = Soap11FaultMetadata | Soap12FaultMetadata;
39
52
  export type DeclaredSoapFault = Readonly<{
40
53
  name: string;
41
54
  code: ExpandedName;
@@ -43,14 +56,14 @@ export type DeclaredSoapFault = Readonly<{
43
56
  string: string;
44
57
  actor?: string;
45
58
  }> & Partial<Soap12FaultMetadata>;
46
- /** A valid SOAP 1.2 fault without a uniquely declared application detail.
59
+ /** A valid protocol fault without an application detail mapped by the selected operation.
47
60
  * @since 1.3.0
48
61
  * @constraints Unassessed detail remains only in responseBytes; no native value receipt is issued.
49
62
  */
50
- export interface ComponentProtocolFault {
63
+ export interface ComponentProtocolFault<F extends ProtocolFaultMetadata = ProtocolFaultMetadata> {
51
64
  readonly kind: 'soap-fault';
52
65
  readonly admitted: false;
53
- readonly fault: Soap12FaultMetadata;
66
+ readonly fault: F;
54
67
  readonly responseBytes: Uint8Array;
55
68
  readonly status: number;
56
69
  readonly usage: ResolverUsage;
@@ -92,5 +105,37 @@ export declare function exchangeDirectSoap(contract: DirectOperationContract, in
92
105
  * @throws TypeError For foreign native handles. Invalid explicit timer/XML capacities throw RangeError.
93
106
  */
94
107
  export declare function exchangeComponentSoap(contract: DirectOperationContract, inputMapping: unknown, application: unknown, options: ComponentSoapOptions): Promise<ComponentSoapResult>;
95
- export declare function exchangeComponentSoap(contract: DirectOperationContract, inputMapping: unknown, application: unknown, options: ComponentSoapOptions, responseProjection: ComponentRecordProjection): Promise<ComponentRecordSoapResult>;
108
+ export declare function exchangeComponentSoap(contract: DirectOperationContract, inputMapping: unknown, application: unknown, options: ComponentSoapOptions, responseProjection: ComponentRecordProjection | undefined, soap11ProtocolFaults?: boolean): Promise<ComponentRecordSoapResult>;
109
+ /** Actual HTTP entity metadata; omission leaves HTTP status and media duties unassessed.
110
+ * @since Unreleased
111
+ */
112
+ export interface ObservedSoapResponseMetadata {
113
+ readonly status: number;
114
+ readonly contentType: string;
115
+ readonly contentEncoding?: string;
116
+ }
117
+ export type ComponentSoapResponseAssessment = DirectSoapFailure | Readonly<{
118
+ kind: 'soap-response' | 'soap-fault';
119
+ admitted: false;
120
+ decoded?: ComponentDecodedXml | ComponentRecordDecodedXml;
121
+ fault?: DeclaredSoapFault | ProtocolFaultMetadata;
122
+ ignoredHeaders?: readonly ExpandedName[];
123
+ usage: ResolverUsage;
124
+ }>;
125
+ /** Assess caller-observed response bytes through the same protocol and native decoder used by real exchanges.
126
+ * @param contract Authenticated selected component operation.
127
+ * @param inputMapping Exact operation input mapping, used only to derive response/fault mappings.
128
+ * @param bytes Actual observed SOAP entity bytes; no request or transport is constructed.
129
+ * @param options XML controls, optional actual HTTP metadata and exact response projection.
130
+ * @returns Native response/fault assessment or semantic failure; HTTP remains unassessed when metadata is absent.
131
+ * @throws TypeError For foreign native handles; RangeError for invalid explicit XML limits.
132
+ * @constraints This response-only helper performs no transport, endpoint authorization or request-value assessment.
133
+ */
134
+ export declare function inspectComponentSoapResponse(contract: DirectOperationContract, inputMapping: unknown, bytes: Uint8Array, options?: Readonly<{
135
+ signal?: AbortSignal;
136
+ limits?: DirectXmlLimits;
137
+ uri?: string;
138
+ responseMetadata?: ObservedSoapResponseMetadata;
139
+ responseProjection?: ComponentRecordProjection;
140
+ }>): ComponentSoapResponseAssessment;
96
141
  export {};