112 lines
4.6 KiB
JavaScript
112 lines
4.6 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import {
|
|
DATA_PRODUCT_PATCH_SCHEMA_VERSION,
|
|
DATA_PRODUCT_PUBLISH_SCHEMA_VERSION,
|
|
DATA_PRODUCT_SNAPSHOT_SCHEMA_VERSION,
|
|
validateDataProductPatch,
|
|
validateDataProductPublish,
|
|
validateDataProductSnapshot,
|
|
} from "../src/index.mjs";
|
|
|
|
const fact = {
|
|
sourceId: "unit-42",
|
|
semanticType: "map.moving_object",
|
|
observedAt: "2026-07-15T10:00:00.000Z",
|
|
attributes: { status: "online" },
|
|
geometry: { type: "Point", coordinates: [37.6173, 55.7558] },
|
|
};
|
|
|
|
const attributesWithSerializedSize = (size) => ({
|
|
blob: "x".repeat(size - Buffer.byteLength(JSON.stringify({ blob: "" }))),
|
|
});
|
|
|
|
const publish = {
|
|
schemaVersion: DATA_PRODUCT_PUBLISH_SCHEMA_VERSION,
|
|
batch: { runId: "execution-42", sequence: 0, idempotencyKey: "execution-42.node-01.chunk-0" },
|
|
facts: [fact],
|
|
};
|
|
assert.equal(validateDataProductPublish(publish).ok, true);
|
|
assert.equal(validateDataProductPublish({
|
|
...publish,
|
|
source: { tenantId: "forged" },
|
|
}).errors.includes("publish.source_not_allowed"), true);
|
|
assert.equal(validateDataProductPublish({
|
|
...publish,
|
|
facts: [{ ...fact, attributes: { accessToken: "must-never-cross-the-boundary" } }],
|
|
}).errors.includes("publish_must_not_contain_secret_material"), true);
|
|
assert.equal(validateDataProductPublish({
|
|
...publish,
|
|
facts: [fact, { ...fact, observedAt: "2026-07-15T10:00:01.000Z" }],
|
|
}).errors.includes("facts_duplicate_entity_key"), true);
|
|
assert.equal(validateDataProductPublish({
|
|
...publish,
|
|
batch: { ...publish.batch, sequence: 2_147_483_647 },
|
|
}).ok, true);
|
|
assert.equal(validateDataProductPublish({
|
|
...publish,
|
|
batch: { ...publish.batch, sequence: 2_147_483_648 },
|
|
}).errors.includes("batch.sequence_must_be_integer_0_to_2147483647"), true);
|
|
assert.equal(validateDataProductPublish({
|
|
...publish,
|
|
facts: [{ ...fact, attributes: attributesWithSerializedSize(64 * 1024) }],
|
|
}).ok, true);
|
|
assert.equal(validateDataProductPublish({
|
|
...publish,
|
|
facts: [{ ...fact, attributes: attributesWithSerializedSize((64 * 1024) + 1) }],
|
|
}).errors.includes("facts[0].attributes_size_exceeded"), true);
|
|
assert.equal(validateDataProductPublish({
|
|
...publish,
|
|
facts: [{ ...fact, attributes: attributesWithSerializedSize((64 * 1024) + 1) }],
|
|
}, { maxAttributesBytes: 1024 * 1024 }).errors.includes("facts[0].attributes_size_exceeded"), true);
|
|
assert.equal(validateDataProductPublish({
|
|
...publish,
|
|
facts: [{ ...fact, geometry: { type: "Point", coordinates: [-180.0001, 55.7558] } }],
|
|
}).errors.includes("facts[0].geometry.longitude_out_of_range"), true);
|
|
assert.equal(validateDataProductPublish({
|
|
...publish,
|
|
facts: [{ ...fact, geometry: { type: "Point", coordinates: [37.6173, 90.0001] } }],
|
|
}).errors.includes("facts[0].geometry.latitude_out_of_range"), true);
|
|
|
|
const canonicalFact = { ...fact, receivedAt: "2026-07-15T10:00:01.000Z" };
|
|
const snapshot = {
|
|
schemaVersion: DATA_PRODUCT_SNAPSHOT_SCHEMA_VERSION,
|
|
dataProduct: { id: "fleet.positions.current.v1", version: "1.0.0" },
|
|
generatedAt: "2026-07-15T10:00:01.000Z",
|
|
cursor: "12",
|
|
facts: [canonicalFact],
|
|
};
|
|
assert.equal(validateDataProductSnapshot(snapshot).ok, true);
|
|
assert.equal(validateDataProductSnapshot({ ...snapshot, transport: "sse" }).errors.includes("snapshot.transport_not_allowed"), true);
|
|
assert.equal(validateDataProductSnapshot({
|
|
...snapshot,
|
|
facts: [{ ...canonicalFact, attributes: attributesWithSerializedSize((64 * 1024) + 1) }],
|
|
}).errors.includes("facts[0].attributes_size_exceeded"), true);
|
|
assert.equal(validateDataProductSnapshot({
|
|
...snapshot,
|
|
facts: [{ ...canonicalFact, attributes: { status: "ndc_edprb_forbidden-reader-token" } }],
|
|
}).errors.includes("snapshot_must_not_contain_secret_material"), true);
|
|
|
|
const patch = {
|
|
schemaVersion: DATA_PRODUCT_PATCH_SCHEMA_VERSION,
|
|
dataProduct: { id: "fleet.positions.current.v1", version: "1.0.0" },
|
|
cursor: "13",
|
|
previousCursor: "12",
|
|
emittedAt: "2026-07-15T10:00:02.000Z",
|
|
operations: [{ op: "upsert", fact: canonicalFact }],
|
|
};
|
|
assert.equal(validateDataProductPatch(patch).ok, true);
|
|
assert.equal(validateDataProductPatch({
|
|
...patch,
|
|
operations: [{ op: "delete", fact: canonicalFact }],
|
|
}).errors.includes("operations[0].op_must_be_upsert"), true);
|
|
assert.equal(validateDataProductPatch({
|
|
...patch,
|
|
operations: [{ op: "upsert", fact: { ...canonicalFact, attributes: attributesWithSerializedSize((64 * 1024) + 1) } }],
|
|
}).errors.includes("operations[0].fact.attributes_size_exceeded"), true);
|
|
assert.equal(validateDataProductPatch({
|
|
...patch,
|
|
operations: [{ op: "upsert", fact: { ...canonicalFact, attributes: { status: "ndc_edpwb_forbidden-writer-token" } } }],
|
|
}).errors.includes("patch_must_not_contain_secret_material"), true);
|
|
|
|
console.log("data-product-contract: ok");
|