@techspokes/typescript-wsdl-client 1.4.0 → 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 +6 -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/checkedDocumentation.d.ts +14 -0
- package/dist/gateway/checkedDocumentation.js +106 -0
- package/dist/gateway/generateCheckedGateway.js +44 -50
- package/dist/index.d.ts +2 -1
- package/docs/api-reference.md +4 -0
- package/docs/checked-gateway.md +61 -1
- package/docs/migration.md +18 -0
- package/package.json +1 -1
|
@@ -7,6 +7,7 @@ import { mkdir, writeFile } from 'node:fs/promises';
|
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
import { componentSourceCapsuleBytes, inspectReconstructedComponentSource, inspectComponentSourceService } from '../compiler/directSourceCapsule.js';
|
|
9
9
|
import { lowerComponentShape } from '../generation/componentShape.js';
|
|
10
|
+
import { lowerCheckedDocumentation } from './checkedDocumentation.js';
|
|
10
11
|
import { checkSemanticBudget } from '../compiler/semanticBudget.js';
|
|
11
12
|
import { inspectDirectOperation } from '../compiler/directOperation.js';
|
|
12
13
|
import { inspectComponentValueMapping } from '../compiler/directValues.js';
|
|
@@ -31,15 +32,21 @@ async function generateGatewayFromReconstruction(expected, options) {
|
|
|
31
32
|
const output = expected.mappings.find(mapping => mapping.direction.kind === 'output');
|
|
32
33
|
if (!input || !output)
|
|
33
34
|
throw new TypeError('Issued input and output mappings required');
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
throw new Error('Checked gateway generation cancelled');
|
|
40
|
-
}).schema;
|
|
35
|
+
const { budget } = inspectDirectOperation(expected.contract).context;
|
|
36
|
+
const check = () => {
|
|
37
|
+
checkSemanticBudget(budget);
|
|
38
|
+
if (options.signal?.aborted)
|
|
39
|
+
throw new Error('Checked gateway generation cancelled');
|
|
41
40
|
};
|
|
41
|
+
const schema = (mapping, role) => lowerComponentShape(expected.contract, mapping, role, check).schema;
|
|
42
|
+
const components = Object.create(null);
|
|
43
|
+
const documented = (value, mapping, role) => lowerCheckedDocumentation(value, expected.contract.selector, role, mapping.kind === 'component-mapping'
|
|
44
|
+
&& !!inspectComponentValueMapping(mapping, expected.contract).applicationGroups, components, () => {
|
|
45
|
+
budget.chargeWork();
|
|
46
|
+
check();
|
|
47
|
+
});
|
|
42
48
|
const request = schema(input, 'Request'), response = schema(output, 'Response');
|
|
49
|
+
const documentation = { request: documented(request, input, 'Request'), response: documented(response, output, 'Response') };
|
|
43
50
|
const soap12 = expected.contract.binding.version === '1.2';
|
|
44
51
|
const nameSchema = { type: 'object', additionalProperties: false, required: ['namespace', 'local'],
|
|
45
52
|
properties: { namespace: { type: 'string' }, local: { type: 'string' } } };
|
|
@@ -53,12 +60,14 @@ async function generateGatewayFromReconstruction(expected, options) {
|
|
|
53
60
|
const faults = expected.mappings.filter(mapping => mapping.direction.kind === 'fault').map(mapping => {
|
|
54
61
|
if (mapping.direction.kind !== 'fault')
|
|
55
62
|
throw new TypeError('Declared fault mapping required');
|
|
56
|
-
|
|
63
|
+
const role = `Fault_${expected.mappings.filter(item => item.direction.kind === 'fault').indexOf(mapping)}`;
|
|
64
|
+
const value = schema(mapping, role);
|
|
65
|
+
return { name: mapping.direction.name, value, documented: documented(value, mapping, role) };
|
|
57
66
|
});
|
|
58
|
-
const faultVariants = faults.map(fault => ({
|
|
67
|
+
const faultVariants = (documentationOnly) => faults.map(fault => ({
|
|
59
68
|
type: 'object', additionalProperties: false, required: ['fault', 'value'],
|
|
60
69
|
properties: {
|
|
61
|
-
value: fault.value,
|
|
70
|
+
value: documentationOnly ? fault.documented : fault.value,
|
|
62
71
|
fault: {
|
|
63
72
|
type: 'object', additionalProperties: false, required: ['name', 'code', 'string', ...(soap12 ? ['version', 'subcodes', 'reasons'] : [])],
|
|
64
73
|
properties: soap12 ? { ...protocolFaultProperties, name: { const: fault.name } } : {
|
|
@@ -69,48 +78,32 @@ async function generateGatewayFromReconstruction(expected, options) {
|
|
|
69
78
|
},
|
|
70
79
|
},
|
|
71
80
|
}));
|
|
72
|
-
|
|
81
|
+
const protocolFault = { type: 'object', additionalProperties: false, required: ['fault'], properties: {
|
|
73
82
|
fault: { type: 'object', additionalProperties: false, required: ['version', 'code', 'string', ...(soap12 ? ['subcodes', 'reasons'] : [])],
|
|
74
83
|
properties: soap12 ? protocolFaultProperties : { version: { const: '1.1' }, code: nameSchema, string: { type: 'string' }, actor: { type: 'string' } } },
|
|
75
|
-
} }
|
|
76
|
-
const fault = { oneOf: faultVariants };
|
|
84
|
+
} };
|
|
85
|
+
const fault = { oneOf: [...faultVariants(false), protocolFault] };
|
|
86
|
+
const documentedFault = { oneOf: [...faultVariants(true), protocolFault] };
|
|
87
|
+
const diagnosticNameSchema = { type: 'object', additionalProperties: false, required: ['namespace', 'local'],
|
|
88
|
+
properties: { namespace: { type: 'string', maxLength: 256 }, local: { type: 'string', maxLength: 256 } } };
|
|
89
|
+
const diagnosticSchema = { type: 'object', additionalProperties: false,
|
|
90
|
+
required: ['version', 'universe', 'resource', 'digest', 'declaration', 'location'], properties: {
|
|
91
|
+
version: { const: 'checked-payload-diagnostic-v1' }, universe: { type: 'string', pattern: '^universe-[a-f0-9]{64}$' },
|
|
92
|
+
resource: { type: 'string', pattern: '^resource-[a-f0-9]{64}$' }, digest: { type: 'string', pattern: '^[a-f0-9]{64}$' },
|
|
93
|
+
declaration: { type: 'object', additionalProperties: false, required: ['kind', 'name'],
|
|
94
|
+
properties: { kind: { enum: ['element', 'attribute'] }, name: diagnosticNameSchema } },
|
|
95
|
+
owner: { type: 'object', additionalProperties: false, required: ['kind'],
|
|
96
|
+
properties: { kind: { type: 'string' }, name: diagnosticNameSchema } },
|
|
97
|
+
datatype: diagnosticNameSchema, builtin: diagnosticNameSchema, location: { type: 'string', maxLength: 2048 },
|
|
98
|
+
unknownField: { const: true }, truncated: { const: true },
|
|
99
|
+
} };
|
|
100
|
+
const failureSchema = { type: 'object', additionalProperties: false, required: ['kind', 'rule'],
|
|
101
|
+
properties: { kind: { type: 'string' }, rule: { type: 'string' }, diagnostic: diagnosticSchema } };
|
|
77
102
|
const schemas = { request: { $schema: draft07, ...request }, response: { $schema: draft07, ...response }, fault: { $schema: draft07, ...fault } };
|
|
78
|
-
const grouped = expected.mappings.some(mapping => mapping.kind === 'component-mapping'
|
|
79
|
-
&& inspectComponentValueMapping(mapping, expected.contract).applicationGroups);
|
|
80
|
-
const components = Object.create(null);
|
|
81
|
-
const documented = (value, dictionary = false) => {
|
|
82
|
-
if (Array.isArray(value))
|
|
83
|
-
return value.map(item => documented(item));
|
|
84
|
-
if (!value || typeof value !== 'object')
|
|
85
|
-
return value;
|
|
86
|
-
const record = value, result = Object.create(null);
|
|
87
|
-
// @why Property names belong to the application; definitions and $id are keywords only at schema nodes.
|
|
88
|
-
if (dictionary) {
|
|
89
|
-
for (const [key, item] of Object.entries(record))
|
|
90
|
-
result[key] = documented(item);
|
|
91
|
-
return result;
|
|
92
|
-
}
|
|
93
|
-
if (Object.hasOwn(record, 'definitions'))
|
|
94
|
-
for (const [key, definition] of Object.entries(record.definitions)) {
|
|
95
|
-
const resolved = documented(definition);
|
|
96
|
-
if (components[key] && JSON.stringify(components[key]) !== JSON.stringify(resolved))
|
|
97
|
-
throw new TypeError(`applicationGroups OpenAPI component collision ${key}`);
|
|
98
|
-
components[key] = resolved;
|
|
99
|
-
}
|
|
100
|
-
for (const [key, item] of Object.entries(record)) {
|
|
101
|
-
if (key === 'definitions' || key === '$id')
|
|
102
|
-
continue;
|
|
103
|
-
result[key] = ['const', 'enum', 'default', 'examples'].includes(key) ? item
|
|
104
|
-
: key === '$ref' && typeof item === 'string' && item.startsWith('#/definitions/') ? item.replace('#/definitions/', '#/components/schemas/')
|
|
105
|
-
: documented(item, ['properties', 'patternProperties', 'dependencies', 'dependentSchemas'].includes(key));
|
|
106
|
-
}
|
|
107
|
-
return result;
|
|
108
|
-
};
|
|
109
|
-
const documentation = grouped ? { request: documented(request), response: documented(response), fault: documented(fault) } : { request, response, fault };
|
|
110
103
|
const doc = {
|
|
111
104
|
openapi: '3.1.1', jsonSchemaDialect: 'https://json-schema.org/draft/2020-12/schema',
|
|
112
105
|
info: { title: expected.selection.service.local, version: '1.0.0' },
|
|
113
|
-
...(
|
|
106
|
+
...(Object.keys(components).length ? { components: { schemas: components } } : {}),
|
|
114
107
|
'x-checked-model': { model: 'checked-components-v1', scope: soap12 ? 'native-component-structured-soap12' : 'native-component-structured-soap11',
|
|
115
108
|
...(expected.responseProjection
|
|
116
109
|
? { responseProjection: { spec: expected.responseProjection.spec, delivery: 'buffered', retainedValue: 'complete-companion-payload' } } : {}),
|
|
@@ -123,9 +116,10 @@ async function generateGatewayFromReconstruction(expected, options) {
|
|
|
123
116
|
requestBody: { required: true, content: { 'application/json': { schema: documentation.request } } },
|
|
124
117
|
responses: { '200': { description: 'Independently validated SOAP response', content: { 'application/json': { schema: documentation.response } } },
|
|
125
118
|
'400': { description: 'Invalid HTTP request; no SOAP request is dispatched' },
|
|
126
|
-
'502': { description: 'SOAP fault or refused upstream response', content: { 'application/json': { schema: { oneOf: [
|
|
127
|
-
|
|
128
|
-
'
|
|
119
|
+
'502': { description: 'SOAP fault or refused upstream response', content: { 'application/json': { schema: { oneOf: [documentedFault,
|
|
120
|
+
failureSchema] } } } },
|
|
121
|
+
'499': { description: 'Cancelled request', content: { 'application/json': { schema: failureSchema } } },
|
|
122
|
+
'500': { description: 'Incompatible artifacts or gateway configuration', content: { 'application/json': { schema: failureSchema } } } } } } },
|
|
129
123
|
};
|
|
130
124
|
let clientImport = path.relative(options.gatewayDir, path.join(options.clientDir, 'client.js')).replace(/\\/g, '/');
|
|
131
125
|
if (!clientImport.startsWith('.'))
|
|
@@ -198,7 +192,7 @@ const plugin: FastifyPluginAsync<CheckedGatewayOptions> = async (fastify, option
|
|
|
198
192
|
}
|
|
199
193
|
const status = result.kind === 'incompatible-artifact' || result.kind === 'missing-authority' ? 500
|
|
200
194
|
: result.kind === 'cancelled' ? 499 : result.phase === 'input' ? 400 : 502;
|
|
201
|
-
return reply.code(status).send({kind: result.kind, rule: result.rule});
|
|
195
|
+
return reply.code(status).send({kind: result.kind, rule: result.rule, ...(result.diagnostic ? {diagnostic: result.diagnostic} : {})});
|
|
202
196
|
} finally {
|
|
203
197
|
request.raw.removeListener('aborted', disconnected);
|
|
204
198
|
reply.raw.removeListener('close', disconnected);
|
package/dist/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export type { CheckedComponentOptions, CheckedInventory } from './checkedPipelin
|
|
|
13
13
|
export { planCheckedComponents, formatCheckedComponentPlan, writeCheckedPlanningFile, CheckedPlanningError } from './checkedPlanning.js';
|
|
14
14
|
export type { CheckedComponentPlan, ComponentPlanBlocker } from './checkedPlanning.js';
|
|
15
15
|
export { inspectCheckedResponse } from './checkedResponseInspection.js';
|
|
16
|
-
export type { CheckedResponseInspectionOptions, CheckedResponseInspectionReport } from './checkedResponseInspection.js';
|
|
16
|
+
export type { CheckedResponseInspectionOptions, CheckedResponseInspectionReport, CheckedResponseCorrectionTarget } from './checkedResponseInspection.js';
|
|
17
17
|
export type { ComponentRecordProjectionSpec, ComponentRecordProjectionAssociation } from './compiler/componentRecordProjection.js';
|
|
18
18
|
export { loadStreamConfigFile, parseStreamConfig, StreamConfigError, type OperationStreamMetadata, type ShapeCatalogRef, type StreamConfig, } from "./util/streamConfig.js";
|
|
19
19
|
export { applyShapeCatalogs, type ApplyShapeCatalogsOptions } from "./compiler/shapeResolver.js";
|
|
@@ -50,3 +50,4 @@ export declare function compileWsdlToProject(input: {
|
|
|
50
50
|
export { assessSchemaSource, serializeAssessmentReport, parseAssessmentReport, assessmentExitCode, ASSESSMENT_VERSION, ASSESSMENT_BASIS } from './compiler/checkedAssessment.js';
|
|
51
51
|
export type { ApplicationGroupsOptions, ApplicationGroupName } from './compiler/applicationGroups.js';
|
|
52
52
|
export type { CheckedAssessmentReport, AssessmentObligation, AssessedOperation, AssessmentStatus } from './compiler/checkedAssessment.js';
|
|
53
|
+
export type { CheckedPayloadDiagnostic } from './compiler/payloadDiagnostics.js';
|
package/docs/api-reference.md
CHANGED
|
@@ -21,6 +21,8 @@ console.log(report.kind);
|
|
|
21
21
|
|
|
22
22
|
The report separates wrapper and companion outcomes and excludes raw XML and decoded values. Configuration can select a consumer-owned `sourceCorrectionsFile`; the same effective contract is used for planning, inspection and generation. A correction draft does not authorize execution until its semantic choices are completed. See [source corrections and offline inspection](checked-gateway.md#consumer-owned-source-corrections).
|
|
23
23
|
|
|
24
|
+
Optional `diagnostic` metadata uses `CheckedPayloadDiagnostic` and `checked-payload-diagnostic-v1` across inspection and newly generated runtime/gateway failures. It identifies native scoped declarations, effective types and bounded known-field locations without source locators or payload values. For explicit local authoring, `includeCorrectionTargets: true` adds `CheckedResponseCorrectionTarget` descriptors with original pinned selectors and original `declaredType`, or an unavailable reason; retain these trusted locators outside HTTP responses and logs. See [trusted original correction targets](checked-gateway.md#trusted-original-correction-targets) for compatibility and recovery rules.
|
|
25
|
+
|
|
24
26
|
Set `includeCorrectionDraft: true` to request an available correction draft. Its exact resource pins can contain local source URIs; default reports retain only diagnostic resource labels.
|
|
25
27
|
|
|
26
28
|
Pass the complete multi-operation checked configuration unchanged. Inspection authenticates the complete correction-source closure before selecting the requested operation and its projection; inactive companions retain their freshness checks.
|
|
@@ -362,6 +364,8 @@ The generated aggregate plugin exports `createClients`, `MultiServiceClientOptio
|
|
|
362
364
|
|
|
363
365
|
Compose existing OpenAPI 3.1 documents without generating clients or routers:
|
|
364
366
|
|
|
367
|
+
Checked documents regenerated with 1.4.1 or later support this API. Regeneration relocates generator-owned local schema resources while preserving configured names and native supplemental-validation metadata. Archived resource-bearing documents remain unsupported; composition does not replace native XML validation.
|
|
368
|
+
|
|
365
369
|
```typescript
|
|
366
370
|
interface OpenApiCompositionEntry {key: string; document: unknown}
|
|
367
371
|
interface OpenApiCompositionOptions {
|
package/docs/checked-gateway.md
CHANGED
|
@@ -104,7 +104,7 @@ Set `sourceCorrectionsFile` in checked generation configuration to apply a versi
|
|
|
104
104
|
|
|
105
105
|
Maintain upstream snapshots unchanged and keep the correction file under version control. The correction file pins the complete original resource set by logical URI and digest. Refreshing upstream metadata requires regenerating and reviewing the correction draft. Scoped targets identify original declarations and particles, not generated TypeScript names. All edits resolve against the original inventory before application.
|
|
106
106
|
|
|
107
|
-
The bounded operations change particle occurrence bounds, narrow element wildcard namespaces,
|
|
107
|
+
The bounded operations change particle occurrence bounds, narrow element wildcard namespaces, insert a typed element into an existing sequence, or change an authored element or attribute type reference. Insertions require an existing named type or global element reference. Corrections do not define new types, rewrite imports, or change incoming SOAP XML. Use replacement snapshots for unsupported restructuring or sources that cannot construct a canonical inventory.
|
|
108
108
|
|
|
109
109
|
The correction document has `version: 1`, `resources: [{uri, digest}]`, and `corrections`. Retain every original resource pin supplied by the tool. A target is `{id, uri, digest}` copied from the inventory or draft; do not replace it with a generated DTO name. Complete unresolved draft values before passing the file to generation.
|
|
110
110
|
|
|
@@ -113,6 +113,7 @@ The correction document has `version: 1`, `resources: [{uri, digest}]`, and `cor
|
|
|
113
113
|
| `set-occurs` | `target`, `min`, and `max`; bounds are canonical decimal strings, with `"unbounded"` also permitted for `max` |
|
|
114
114
|
| `set-wildcard-namespaces` | `target` and `namespaces`; use explicit namespace strings and `""` for the no-namespace case; the original `processContents` is preserved |
|
|
115
115
|
| `insert-element` | Sequence `target`, `position`, and `element`; position is `"append"` or `{kind: "before" or "after", target: originalChildTarget}` |
|
|
116
|
+
| `set-declared-type` | Declaration `target`, original `expectedType`, and replacement `type`, both as `{namespace, local}` |
|
|
116
117
|
|
|
117
118
|
For a local inserted declaration, `element` contains `{kind: "declaration", name, type: {namespace, local}, min, max}`. The type must be a built-in XSD type or an existing named type. A global element reference instead uses `{kind: "reference", target: globalElementTarget, min, max}`. For example, a reviewed new scalar can use `type: {namespace: "http://www.w3.org/2001/XMLSchema", local: "string"}`; selecting that type is a contract decision, not an inference from one text value. Local declarations follow the containing schema's element-form rules.
|
|
118
119
|
|
|
@@ -124,6 +125,27 @@ Effective metadata is freshly parsed and checked before generation. Native decod
|
|
|
124
125
|
|
|
125
126
|
One generated project retains one effective byte sequence per logical URI. Shared declarations change for all their uses in that project. Conflicting URI contents and interpretation-specific edits to shared chameleon declarations refuse; separate replacement snapshots are required for those cases. This feature does not extend checked multi-service composition or legacy generation.
|
|
126
127
|
|
|
128
|
+
#### Changing an existing declared type
|
|
129
|
+
|
|
130
|
+
Use `set-declared-type` for an existing authored element or attribute `@type`. Obtain the original declaration selector and `declaredType` through [trusted correction targets](#trusted-original-correction-targets), then copy `declaredType` into `expectedType`. Keep every original resource pin; an effective datatype or ordinal path alone does not establish an original target.
|
|
131
|
+
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"kind": "set-declared-type",
|
|
135
|
+
"target": {"id": "ORIGINAL_DECLARATION_ID", "uri": "ORIGINAL_RESOURCE_URI", "digest": "ORIGINAL_SHA256"},
|
|
136
|
+
"expectedType": {"namespace": "http://www.w3.org/2001/XMLSchema", "local": "anyURI"},
|
|
137
|
+
"type": {"namespace": "http://www.w3.org/2001/XMLSchema", "local": "string"}
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The original type guard compares expanded names resolved in the declaration's schema context. Replacements may select XML Schema builtins or existing named types from the declaration's authorized source universe. A foreign named type also requires an existing import in the declaring schema; another companion or including schema cannot lend its type declarations or import permissions. Namespace prefixes are emitted deterministically without changing expanded names.
|
|
142
|
+
|
|
143
|
+
Inline anonymous types, implicit types, `ref` uses, new definitions and new imports refuse. Attribute replacements require simple types. Missing or stale selectors, mismatched old types, conflicting edits and ambiguous shared chameleon interpretations also refuse; pins are never refreshed automatically.
|
|
144
|
+
|
|
145
|
+
Changing `anyURI` to `string` admits raw text and escaped embed content while removing the URI guarantee. Changing `dateTime` to `string` also admits nonsense. An existing constrained string type may check a timestamp layout while still accepting impossible calendar dates; it does not prove calendar validity or normalize timezones.
|
|
146
|
+
|
|
147
|
+
Every use of the selected shared declaration adopts its new type in that project. Independent source universes with colliding names keep their own declarations. Original source and response bytes remain unchanged; regenerate and qualify matching client, native/runtime, capsule and OpenAPI artifacts against the new effective bytes before adoption.
|
|
148
|
+
|
|
127
149
|
### Offline response inspection
|
|
128
150
|
|
|
129
151
|
Use `inspect-response` with a local WSDL, closed snapshot configuration, one configured operation and a saved SOAP response. It does not acquire missing remote metadata, dispatch SOAP, or read credentials. Create the output directory first; existing report or draft files are not overwritten.
|
|
@@ -140,6 +162,40 @@ Drafts retain exact logical source URIs, which can include local filesystem path
|
|
|
140
162
|
|
|
141
163
|
Exit codes are 0 for conformance within the reported scope, 1 for mismatch/refusal, and 2 for invocation/file errors. A conforming SOAP fault remains identified as a fault. The package-root `inspectCheckedResponse` API accepts the same checked choices, a full operation selector, response bytes, optional actual response metadata, cancellation and XML limits; it returns diagnostic data without writing files.
|
|
142
164
|
|
|
165
|
+
### Scoped payload diagnostics
|
|
166
|
+
|
|
167
|
+
Native element and attribute failures can include an optional `diagnostic` object in inspection reports, direct runtime failures and newly generated gateway error responses. `checked-payload-diagnostic-v1` identifies the source universe and resource with opaque hashes, retains the effective source digest, and identifies the declared field, owning declaration and effective datatype when established by the native owner. A scalar diagnostic also identifies its builtin datatype.
|
|
168
|
+
|
|
169
|
+
`location` uses schema-established expanded names and one-based occurrence indexes. An unknown child or wrapper is represented by `[unknown-field]` under the nearest known parent; its caller-controlled name is omitted. Diagnostics contain no XML values, source URI, absolute local path, raw exception or native handle.
|
|
170
|
+
|
|
171
|
+
Names and locations are bounded, and `truncated: true` indicates shortened diagnostic metadata. An occurrence above 100000 is displayed as `[>100000]`; omitted ancestor information is marked `[truncated]`. Neither marker is an exact original location or a correction selector.
|
|
172
|
+
|
|
173
|
+
This metadata is additive: the inspection report remains `checked-response-inspection-v1`, existing runtime bindings retain their versions, and consumers must continue branching on the existing failure `kind` and `rule`. Existing generated gateways keep their previous envelope until regenerated; regenerate the matching client, gateway and OpenAPI artifacts to obtain the documented optional `diagnostic`. HTTP status and native strict validation remain unchanged; a missing diagnostic never makes a failure acceptable.
|
|
174
|
+
|
|
175
|
+
### Trusted original correction targets
|
|
176
|
+
|
|
177
|
+
Pass `includeCorrectionTargets: true` to the public `inspectCheckedResponse()` API only for trusted local authoring. The optional `correctionTargets` array associates each descriptor with its zero-based `diagnostic` index. An available descriptor includes `target: {id, uri, digest}` for the original element or attribute declaration and its original expanded `declaredType` when named. Use that type as the explicit `expectedType` guard when authoring a declared-type correction.
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
import {inspectCheckedResponse} from '@techspokes/typescript-wsdl-client';
|
|
181
|
+
import type {CheckedComponentOptions} from '@techspokes/typescript-wsdl-client';
|
|
182
|
+
declare const source: string;
|
|
183
|
+
declare const selector: {portType: {namespace: string; local: string}; binding: {namespace: string; local: string}; operation: string};
|
|
184
|
+
declare const responseBytes: Uint8Array;
|
|
185
|
+
declare const checkedComponents: Partial<CheckedComponentOptions>;
|
|
186
|
+
const report = await inspectCheckedResponse(source, {
|
|
187
|
+
selector,
|
|
188
|
+
responseBytes,
|
|
189
|
+
checkedComponents,
|
|
190
|
+
includeCorrectionTargets: true,
|
|
191
|
+
});
|
|
192
|
+
const available = report.correctionTargets?.filter(item => item.kind === 'available');
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
These descriptors intentionally contain original source locators and must stay out of public HTTP responses and logs. Default inspection reports and generated gateway diagnostics do not include them. Requesting `includeCorrectionDraft` is a separate authoring operation.
|
|
196
|
+
|
|
197
|
+
Original target recovery uses native declaration ownership and retained edit-span correspondence when a recipe already exists. It never treats an effective ordinal path as an original target. A descriptor with `kind: 'unavailable'` states a reason, including absent native declaration evidence, an ambiguous original context, a newly inserted declaration without an original, or correspondence that cannot be established after encoding-declaration rewriting. Do not infer a selector or silently refresh pins from that result.
|
|
198
|
+
|
|
143
199
|
### Planning and missing-schema recovery
|
|
144
200
|
|
|
145
201
|
`--checked-report` writes versioned `checked-component-plan-v1` JSON on native success or refusal. Human refusals identify the native reason, stage, dimension, affected full operation identities and configuration pointer. Source legality, correspondence, mapping/artifact readiness and runtime remain separate dimensions. Unsupported or inconclusive qualification does not establish invalid vendor schemas. Loading interruptions retain discovered counts plus explicit incomplete inventory; independent operation refusals are collected before generation writes project artifacts.
|
|
@@ -255,6 +311,10 @@ Generated `buildServer` accepts runtime cancellation, timeout and XML limits. Or
|
|
|
255
311
|
|
|
256
312
|
## Validation and coverage evidence
|
|
257
313
|
|
|
314
|
+
Regenerate with 1.4.1 or later to compose checked OpenAPI documents through `composeOpenApiDocuments`. Documentation definitions are relocated into operation- and role-scoped components for ungrouped shapes; configured grouped names remain unchanged. Runtime draft-07 schemas, capsules and native supplemental validation retain their existing contracts.
|
|
315
|
+
|
|
316
|
+
Composition preserves structural JSON documentation, not complete native XML equivalence. Archived 1.4.0 documents with embedded schema resources still refuse composition; updating the runtime package alone does not repair those documents.
|
|
317
|
+
|
|
258
318
|
OpenAPI documentation uses 3.1.1 with separate draft-07 HTTP runtime plans. Route-local Ajv disables coercion, default insertion and property removal, and preserves unrelated host policy. The native runtime explicitly converts validated HTTP values through the issued mapping, performs actual SOAP execution and independently validates response/fault XML. HTTP response validation also runs independently of serializer selection; JSON serialization preserves the validated values.
|
|
259
319
|
|
|
260
320
|
`client/inventory.json` and the API result's `checked` field list every discovered portType operation, selected service/port/binding, requested/generated operation and unselected operations. Generation records `executed:false`; it does not claim a SOAP call occurred. Refused selection diagnostics name the requested operation and zero generated/executed operations. Unselected operations remain unassessed.
|
package/docs/migration.md
CHANGED
|
@@ -6,6 +6,24 @@ Versions are listed newest first. Find your current version and follow the steps
|
|
|
6
6
|
|
|
7
7
|
See the root [README](../README.md). Historical version sections below describe their original releases; 1.2.0 compatibility guidance supersedes earlier unchanged-output statements for this upgrade.
|
|
8
8
|
|
|
9
|
+
## From 1.4.x to 1.5.0
|
|
10
|
+
|
|
11
|
+
Checked payload failures gain optional `checked-payload-diagnostic-v1` metadata with opaque source/universe identities, source digests, declaration and datatype names, and bounded locations. Existing failure kinds, HTTP statuses and strict validation remain the same. Regenerate matched clients, capsules, gateways and OpenAPI to obtain the new generated diagnostic declarations and serialized fields; existing runtime bindings remain supported.
|
|
12
|
+
|
|
13
|
+
Offline inspection retains `checked-response-inspection-v1` and adds optional metadata. Request `includeCorrectionTargets: true` only in a trusted local authoring workflow: its original selectors contain source locators that must not be forwarded to HTTP clients or logs. An unavailable target requires an explicit authoring decision; an effective ordinal path is not an original selector.
|
|
14
|
+
|
|
15
|
+
Use `set-declared-type` in the existing pinned recipe only for a supported authored element or attribute `@type`. Preserve the original URI/digest and guard the expected original expanded type name, then qualify the changed effective sources and regenerate all matching artifacts. A shared declaration changes every use in its project, so review those uses before adoption.
|
|
16
|
+
|
|
17
|
+
Changing `xs:anyURI` to `xs:string` admits embed text and removes URI validation. Changing `xs:dateTime` to string also accepts nonsense; an existing constrained string type can enforce a layout without proving calendar validity or normalizing timezones. No observed response weakens validation automatically or refreshes source pins.
|
|
18
|
+
|
|
19
|
+
Alternate companion response branches remain a design investigation. This release does not add an application-error branch API or reinterpret an error payload as record data.
|
|
20
|
+
|
|
21
|
+
## From 1.4.0 to 1.4.1
|
|
22
|
+
|
|
23
|
+
Regenerate checked specifications to compose them with `composeOpenApiDocuments`. Ungrouped documentation uses operation- and role-scoped components; configured grouped names remain stable. Archived 1.4.0 specifications containing embedded resources remain explicitly refused by composition.
|
|
24
|
+
|
|
25
|
+
Existing runtime artifacts remain usable. Runtime draft-07 validation, capsules and native supplemental validation are unchanged; structural documentation parity does not establish complete native XML equivalence.
|
|
26
|
+
|
|
9
27
|
## General Upgrade Steps
|
|
10
28
|
|
|
11
29
|
These steps apply to every version upgrade:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@techspokes/typescript-wsdl-client",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Turn legacy WSDL/SOAP services into typed TypeScript clients, OpenAPI 3.1 specs, and production-ready Fastify REST gateways. Built for enterprise SOAP modernization.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"wsdl",
|