191 lines
7.8 KiB
JavaScript
191 lines
7.8 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import {
|
|
DATA_PRODUCT_HISTORY_SCHEMA_VERSION,
|
|
DATA_PRODUCT_PATCH_SCHEMA_VERSION,
|
|
DATA_PRODUCT_PUBLISH_SCHEMA_VERSION,
|
|
DATA_PRODUCT_SNAPSHOT_SCHEMA_VERSION,
|
|
validateDataProductHistory,
|
|
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, attributes: { status: `ndc_edppr_${"P".repeat(43)}` } }],
|
|
}).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 zoneGenerationAt = "2026-07-15T10:10:00.000Z";
|
|
const zoneFact = {
|
|
sourceId: "gelios-zone-42",
|
|
semanticType: "map.zone",
|
|
observedAt: zoneGenerationAt,
|
|
attributes: { display_name: "Zone 42" },
|
|
geometry: {
|
|
type: "Polygon",
|
|
coordinates: [[[37.60, 55.74], [37.62, 55.74], [37.62, 55.76], [37.60, 55.74]]],
|
|
},
|
|
};
|
|
const replacement = {
|
|
...publish,
|
|
batch: { ...publish.batch, mode: "replace", generationAt: zoneGenerationAt },
|
|
facts: [zoneFact],
|
|
};
|
|
assert.equal(validateDataProductPublish(replacement).ok, true);
|
|
assert.equal(validateDataProductPublish({ ...replacement, facts: [] }).ok, true);
|
|
assert.equal(validateDataProductPublish({
|
|
...replacement,
|
|
facts: [{ ...zoneFact, observedAt: "2026-07-15T10:09:59.000Z" }],
|
|
}).errors.includes("facts[0].observedAt_must_equal_generationAt"), true);
|
|
assert.equal(validateDataProductPublish({
|
|
...replacement,
|
|
facts: [{ ...zoneFact, geometry: { ...zoneFact.geometry, coordinates: [[[37.60, 55.74], [37.62, 55.74], [37.62, 55.76], [37.61, 55.75]]] } }],
|
|
}).errors.includes("facts[0].geometry[0]_linear_ring_must_be_closed"), 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 history = {
|
|
schemaVersion: DATA_PRODUCT_HISTORY_SCHEMA_VERSION,
|
|
dataProduct: { id: "fleet.positions.current.v1", version: "1.0.0" },
|
|
generatedAt: "2026-07-15T10:05:00.000Z",
|
|
query: {
|
|
from: "2026-07-15T10:00:00.000Z",
|
|
to: "2026-07-15T10:05:00.000Z",
|
|
resolutionMs: 60_000,
|
|
sourceIds: ["unit-42"],
|
|
order: "asc",
|
|
},
|
|
facts: [{ ...canonicalFact, bucketStart: "2026-07-15T10:00:00.000Z" }],
|
|
nextCursor: "opaque_cursor",
|
|
};
|
|
assert.equal(validateDataProductHistory(history).ok, true);
|
|
assert.equal(validateDataProductHistory({
|
|
...history,
|
|
query: { ...history.query, order: "desc" },
|
|
}).errors.includes("query.order_must_be_asc"), true);
|
|
assert.equal(validateDataProductHistory({
|
|
...history,
|
|
query: { ...history.query, from: history.query.to, to: history.query.from },
|
|
}).errors.includes("query.range_invalid"), true);
|
|
assert.equal(validateDataProductHistory({
|
|
...history,
|
|
query: { ...history.query, sourceIds: ["unit-42", "unit-42"] },
|
|
}).errors.includes("query.sourceIds_must_be_unique_and_sorted"), true);
|
|
assert.equal(validateDataProductHistory({
|
|
...history,
|
|
facts: [
|
|
{ ...history.facts[0], sourceId: "unit-43" },
|
|
history.facts[0],
|
|
],
|
|
}).errors.includes("facts[1]_not_strictly_ordered"), true);
|
|
assert.equal(validateDataProductHistory({
|
|
...history,
|
|
facts: [{ ...history.facts[0], attributes: { token: "forbidden" } }],
|
|
}).errors.includes("history_must_not_contain_secret_material"), true);
|
|
assert.equal(validateDataProductSnapshot({
|
|
...snapshot,
|
|
facts: [{ ...canonicalFact, attributes: { status: `ndc_edppr_${"P".repeat(43)}` } }],
|
|
}).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_invalid"), true);
|
|
assert.equal(validateDataProductPatch({
|
|
...patch,
|
|
operations: [{ op: "remove", sourceId: "gelios-zone-42", semanticType: "map.zone" }],
|
|
}).ok, 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");
|