Check a supplier export with JavaScript or TypeScript
You receive a supplier's CMD export at a dealership. Check raw JSON with the schema validator first: a separate prerequisite, not an SDK feature. Then read, check and write the document. This complete example contains one fictional Party, without a VIN or globally required address/GLN.
Install a local package
@pobbd/cmd-sdk@0.26.0 is an independent ESM package for Node.js 24+ and
browsers supporting ES2022 and BigInt. There is no CommonJS build.
Build a local archive from the checkout:
cd packages/javascript/sdk
npm ci --ignore-scripts
npm run build
npm pack
The archive is packages/javascript/sdk/pobbd-cmd-sdk-0.26.0.tgz.
From an existing consumer project's directory, install its absolute local path:
npm install /absolute/path/to/packages/javascript/sdk/pobbd-cmd-sdk-0.26.0.tgz
The SDK has no runtime dependencies. Its build pins TypeScript 7.0.2 and Prettier
3.9.10 as development tools; formatting does not generate DTOs. These steps assume
neither a repository clone URL nor registry installation.
Read, check, write
Save as export-check.mjs in that installed consumer:
import { read, validate, write } from '@pobbd/cmd-sdk';
const json = `
{
"parties": [
{
"id": "party_example",
"organization_name": "Fictional supplier"
}
]
}
`;
const bundle = read(json, 'type', '0.26');
const violations = validate(bundle);
if (violations.length !== 0) {
throw new Error(JSON.stringify(violations));
}
console.log(bundle.parties[0].organization_name);
console.log(write(bundle));
Run node export-check.mjs. Expect Fictional supplier, then JSON containing the
same Party. Inspect violations through code, path, parameters and message;
some callback codes are null. Reject or quarantine failed exports before storage.
Reading alone proves neither semantic validity nor company identity.
For typed construction, use exported DTO types and hydrate the object before validation. A structurally similar plain object is not a hydrated SDK bundle:
import { hydrate, normalize, validate } from '@pobbd/cmd-sdk';
import type { TypeBundle } from '@pobbd/cmd-sdk';
const bundle: TypeBundle = hydrate('TypeBundle', {
parties: [{
id: 'party_example',
organization_name: 'Fictional supplier',
}],
});
if (validate(bundle).length !== 0) {
throw new Error('Invalid supplier export');
}
console.log(normalize(bundle));
The literal profile in read(json, 'type', '0.26') selects TypeBundle.
A dynamic profile string returns the Bundle union. Types are exported from the
installed package alongside declarations; runtime enum values remain wire strings.
Use self-hosted browser modules
Copy all emitted dist/ files, preserving names and relative .js imports,
to a self-hosted cmd-sdk/ directory beside this HTML document. Serve both via
HTTP with JavaScript MIME types. No CDN or Node runtime import is needed:
<script type="module">
import { read, validate } from './cmd-sdk/index.js';
const bundle = read(
'{"parties":[{"id":"party_example","organization_name":"Fictional supplier"}]}',
'type',
'0.26',
);
document.body.textContent = JSON.stringify(validate(bundle));
</script>
Expect [] for this valid export. The library fetches no supplier data, schemas or
external catalogs. Configure browser serving in your application; the SDK supplies
no production server.
Keep strict input and presence
read(json, profile, version) accepts only type, instance, recall and
wire version 0.26, not package version 0.26.0. hydrate(dtoName, input)
uses the same strict nested decoder and copies/freezes DTOs and collections.
Malformed JSON throws a parsing error; decoding failures throw HydrationError
with a property path. Unknown keys/enums, missing required keys, wrong scalar
kinds and unsafe/nonfinite numbers are rejected. Handle these failures separately
from semantic violations.
Optional absence, explicit null, empty collections and zero stay distinct under
normalize(bundle) and write(bundle). Required-nullable keys
Vehicle.first_registration and VehicleDamage.component cannot be omitted.
Preserving a null does not establish schema nullability. No inferred defaults
are inserted. Number spelling, member order and duplicate-member occurrences are
not round-trip guarantees. Integral 6.0 is accepted as an integer; numeric
strings are not. Numeric magnitude is limited to 9007199254740991; BigInt is
used internally for instant comparisons, not as a JSON field type.
Choose partial or closed graph checks
validate(bundle) checks fields and a document-local partial graph.
Visible contradictions fail; references outside the supplied data may remain
unresolved. validateGraph(keyedBundles, false) checks several documents in
partial mode. Object keys label violation paths.
For closed checks, use validateGraph(keyedBundles): the default mode, also
selected by a second argument of true. Supply every required referenced record. A Source pointing to party_example may
pass partial checks without its Party but fails closed checks until a compatible
Party is supplied. The Party-only example passes both. Neither mode fetches
references or interprets ID prefixes.
Validation boundaries explain storage-owned limits.
Apply the receiver's agreement
validateContract(payload, references, trustedContract, context) checks bilateral
completeness after core and closed-graph prerequisites. The receiver selects a
trusted hydrated DataContract and independently configured ContractContext,
never a weaker policy selected by incoming data_contracts. All six exact
bindings are required:
| Binding | Expected value |
|---|---|
contract_id, contract_version | Trusted agreement and immutable revision |
publisher_party_id, consumer_party_id | Supplier and receiving dealer, in order |
profile, cmd_version | Agreed wire profile and 0.26 |
The entire logical definition is immutable under an ID/version. Alternatives are
inclusive OR; every requirement in a chosen alternative must hold for every
selected target. min_occurs prevents empty target sets from passing accidentally.
FIELD paths traverse declared nested DTO properties, not collections, references
or expressions. IDENTIFIER checks compare supplied Party assertions, not external
issuance. Address and GLN requirements belong to an agreement, not every Party.
See agreement semantics and the
complete wire/PHP walkthrough; it is not a JavaScript API sample.
Query dated history
new VehicleHistory(instanceBundles) requires hydrated instance bundles and checks
their partial graph. equipment(vehicleId, item, asOf),
damageStatus(vehicleId, damageId, asOf) and
component(vehicleId, component, asOf) return the wire unions Presence,
RepairStatus and ComponentGrade. Supply a real YYYY-MM-DD date.
Undated evidence is not backdated. Equipment intervals are half-open; conflicting
latest equally ranked observations return UNKNOWN. Unknown does not prove
absence. History semantics describe the dated rules.
The SDK performs no database/registry lookup, identity certification, invoice validation or automatic version migration. Project licensing does not grant rights to supplier exports; source-data boundaries still apply.