feat(platform): add replaceable geozone data layer
This commit is contained in:
@@ -146,6 +146,64 @@ async function main() {
|
||||
publish.batch.idempotencyKey,
|
||||
contracts.buildPublishPayload(items, 'execution-42', 'workflow-7', 'node-3', 'fleet.positions.current.v2', 0).batch.idempotencyKey,
|
||||
);
|
||||
const zoneItems = [{
|
||||
json: {
|
||||
sourceId: 'gelios-zone-42',
|
||||
semanticType: 'map.zone',
|
||||
observedAt: '2026-07-15T12:10:00.000Z',
|
||||
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 = contracts.buildPublishPayload(
|
||||
zoneItems,
|
||||
'execution-43',
|
||||
'workflow-7',
|
||||
'node-zones',
|
||||
'map.zones.current.v1',
|
||||
0,
|
||||
'replace',
|
||||
);
|
||||
assert.equal(externalContract.validateDataProductPublish(replacement).ok, true);
|
||||
assert.equal(replacement.batch.mode, 'replace');
|
||||
assert.equal(replacement.batch.generationAt, zoneItems[0].json.observedAt);
|
||||
const replacementBatch = contracts.buildPublishPayload(
|
||||
[{ json: { generationAt: zoneItems[0].json.observedAt, facts: zoneItems.map((item) => item.json) } }],
|
||||
'execution-44',
|
||||
'workflow-7',
|
||||
'node-zones',
|
||||
'map.zones.current.v1',
|
||||
0,
|
||||
'replace',
|
||||
);
|
||||
assert.deepEqual(replacementBatch.facts, replacement.facts);
|
||||
assert.equal(replacementBatch.batch.generationAt, zoneItems[0].json.observedAt);
|
||||
const emptyReplacement = contracts.buildPublishPayload(
|
||||
[{ json: { generationAt: '2026-07-15T13:00:00.000Z', facts: [] } }],
|
||||
'execution-45',
|
||||
'workflow-7',
|
||||
'node-zones',
|
||||
'map.zones.current.v1',
|
||||
0,
|
||||
'replace',
|
||||
);
|
||||
assert.deepEqual(emptyReplacement.facts, []);
|
||||
assert.equal(externalContract.validateDataProductPublish(emptyReplacement).ok, true);
|
||||
assert.throws(
|
||||
() => contracts.buildPublishPayload(
|
||||
[{ json: { generationAt: '2026-07-15T13:00:00.000Z', facts: zoneItems.map((item) => item.json) } }],
|
||||
'execution-46',
|
||||
'workflow-7',
|
||||
'node-zones',
|
||||
'map.zones.current.v1',
|
||||
0,
|
||||
'replace',
|
||||
),
|
||||
/replace_generationAt_observedAt_mismatch/,
|
||||
);
|
||||
assert.throws(
|
||||
() => contracts.buildPublishPayload(
|
||||
[{ json: { ...items[0].json, attributes: { accessToken: 'forbidden' } } }],
|
||||
@@ -303,6 +361,29 @@ async function assertNodeHttpContracts(nodes, externalContract, constants) {
|
||||
assert.equal(externalContract.validateDataProductPublish(publishCalls[0].options.body).ok, true);
|
||||
assert.equal(publishResult[0][0].json.publishedFactCount, 1);
|
||||
|
||||
const replacementCalls = [];
|
||||
const replacementContext = executionContext({
|
||||
typeVersion: 2,
|
||||
parameters: { dataProductId: 'map.zones.current.v1', publishMode: 'replace', sequence: 0 },
|
||||
input: [{
|
||||
json: {
|
||||
generationAt: '2026-07-15T12:10:00.000Z',
|
||||
facts: [{
|
||||
sourceId: 'gelios-zone-42',
|
||||
semanticType: 'map.zone',
|
||||
observedAt: '2026-07-15T12:10:00.000Z',
|
||||
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]]] },
|
||||
}],
|
||||
},
|
||||
}],
|
||||
response: { ok: true, publishedFactCount: 1, currentRemovedCount: 0 },
|
||||
calls: replacementCalls,
|
||||
});
|
||||
await nodes.get('NdcDataProductPublish').execute.call(replacementContext);
|
||||
assert.equal(replacementCalls[0].options.body.batch.mode, 'replace');
|
||||
assert.equal(externalContract.validateDataProductPublish(replacementCalls[0].options.body).ok, true);
|
||||
|
||||
const readCalls = [];
|
||||
const readContext = executionContext({
|
||||
parameters: { dataProductId: 'fleet.positions.current.v1', pageSize: 1000 },
|
||||
@@ -411,7 +492,7 @@ async function assertNodeHttpContracts(nodes, externalContract, constants) {
|
||||
}
|
||||
}
|
||||
|
||||
function executionContext({ parameters, input = [{ json: {} }], response, calls }) {
|
||||
function executionContext({ parameters, input = [{ json: {} }], response, calls, typeVersion = 1 }) {
|
||||
return {
|
||||
getNodeParameter(name, _index, defaultValue) {
|
||||
return Object.prototype.hasOwnProperty.call(parameters, name) ? parameters[name] : defaultValue;
|
||||
@@ -419,7 +500,7 @@ function executionContext({ parameters, input = [{ json: {} }], response, calls
|
||||
getInputData() { return input; },
|
||||
getExecutionId() { return 'execution-42'; },
|
||||
getWorkflow() { return { id: 'workflow-7' }; },
|
||||
getNode() { return { id: 'node-3' }; },
|
||||
getNode() { return { id: 'node-3', typeVersion }; },
|
||||
helpers: {
|
||||
async httpRequestWithAuthentication(credentialName, options) {
|
||||
calls.push({ credentialName, options });
|
||||
|
||||
Reference in New Issue
Block a user