import assert from "node:assert/strict"; import { normalizeDataProductDefinition } from "../src/data-product-policy.mjs"; const input = { id: "fleet.positions.current.v1", version: "1.0.0", ontologyRevision: "ontology.map.v1", deliveryMode: "snapshot+patch", semanticTypes: ["vehicle.trike", "map.moving_object"], fields: ["status", "source_id", "observed_at", "geometry"], history: { mode: "sampled", intervalMs: 60_000, strategy: "latest-per-entity-per-bucket", retentionDays: 365, }, }; const definition = normalizeDataProductDefinition(input); assert.equal(definition.history.mode, "sampled"); assert.equal(definition.history.intervalMs, 60_000); assert.deepEqual(definition.semanticTypes, ["map.moving_object", "vehicle.trike"]); assert.deepEqual(definition.fields, ["geometry", "observed_at", "source_id", "status"]); assert.deepEqual(input.semanticTypes, ["vehicle.trike", "map.moving_object"]); assert.deepEqual(input.fields, ["status", "source_id", "observed_at", "geometry"]); assert.equal(Object.isFrozen(definition.semanticTypes), true); assert.equal(Object.isFrozen(definition.fields), true); const reordered = normalizeDataProductDefinition({ ...input, semanticTypes: [...input.semanticTypes].reverse(), fields: [...input.fields].reverse(), }); assert.deepEqual(reordered.semanticTypes, definition.semanticTypes); assert.deepEqual(reordered.fields, definition.fields); assert.throws(() => normalizeDataProductDefinition({ ...definition, providerId: "gelios" }), /data_product_definition_invalid/); assert.throws(() => normalizeDataProductDefinition({ ...definition, history: { mode: "none", intervalMs: 1000 } }), /history_policy_none_has_sampling_fields/); for (const semanticTypes of [ undefined, "map.moving_object", [], ["map.moving_object", null], ["map.moving_object", "Map.invalid"], ]) { assert.throws( () => normalizeDataProductDefinition({ ...input, semanticTypes }), /data_product_definition_(semantic_types_invalid|shape_invalid)/, ); } assert.throws( () => normalizeDataProductDefinition({ ...input, semanticTypes: ["map.moving_object", "map.moving_object"] }), /data_product_definition_semantic_types_duplicate/, ); assert.throws( () => normalizeDataProductDefinition({ ...input, semanticTypes: ["map.moving_object", " map.moving_object "] }), /data_product_definition_semantic_types_duplicate/, ); for (const fields of [ undefined, "source_id", [], ["source_id", null], ["source_id", "Invalid"], ]) { assert.throws( () => normalizeDataProductDefinition({ ...input, fields }), /data_product_definition_(fields_invalid|shape_invalid)/, ); } assert.throws( () => normalizeDataProductDefinition({ ...input, fields: ["source_id", "source_id"] }), /data_product_definition_fields_duplicate/, ); assert.throws( () => normalizeDataProductDefinition({ ...input, fields: ["source_id", " source_id "] }), /data_product_definition_fields_duplicate/, ); console.log("external-data-plane data product policy: ok");