NODEDC_PLATFORM/packages/external-provider-contract/providers/gelios/v10/package.mjs

189 lines
6.1 KiB
JavaScript

import { geliosProviderPackageV9 } from "../v9/package.mjs";
export const GELIOS_PROVIDER_PACKAGE_ID = "gelios.provider.v10";
export const GELIOS_PROVIDER_PACKAGE_VERSION = "10.0.0";
export const GELIOS_UNIT_CONTACTS_DATA_PRODUCT_ID = "fleet.units.contacts.current.v1";
export const GELIOS_UNIT_CONTACTS_DATA_PRODUCT_VERSION = "1.0.0";
export const GELIOS_UNIT_CONTACTS_ONTOLOGY_REVISION = "ontology.map.moving_object.v3";
const FIELD_POLICY_ID = "gelios.units.contacts.fields.v1";
const COLLECTION_PROFILE_ID = "gelios.units.contacts.cold.v1";
const MAPPING_ID = "gelios.units.to.fleet.units.contacts.current.v1";
const TEMPLATE_ID = "gelios.units.contacts.l2.v1";
const contactFields = Object.freeze([
"device_imei",
"device_phone_primary",
"device_phone_secondary",
"display_name",
"provider_creator_login",
]);
const value = structuredClone(geliosProviderPackageV9);
value.id = GELIOS_PROVIDER_PACKAGE_ID;
value.version = GELIOS_PROVIDER_PACKAGE_VERSION;
value.manifest = {
...value.manifest,
id: "gelios.provider.manifest.v10",
version: GELIOS_PROVIDER_PACKAGE_VERSION,
fieldPolicyIds: [...value.manifest.fieldPolicyIds, FIELD_POLICY_ID],
collectionProfileIds: [...value.manifest.collectionProfileIds, COLLECTION_PROFILE_ID],
dataProductIds: [...value.manifest.dataProductIds, GELIOS_UNIT_CONTACTS_DATA_PRODUCT_ID],
mappingContractIds: [...value.manifest.mappingContractIds, MAPPING_ID],
l2TemplateIds: [...value.manifest.l2TemplateIds, TEMPLATE_ID],
};
value.fieldPolicies.push({
id: FIELD_POLICY_ID,
version: GELIOS_UNIT_CONTACTS_DATA_PRODUCT_VERSION,
dataProductId: GELIOS_UNIT_CONTACTS_DATA_PRODUCT_ID,
targetFields: [...contactFields],
unknownSourceFields: "drop",
dynamicSourceFields: "drop_until_classified",
restrictedSourcePaths: [
"availableToUsers",
"commands",
"currentUserAccess",
"customFields",
"driver",
"extraInfo",
"hwDecryptKey",
"lastMsg.address",
"lastMsg.params",
"lastSensorsVal",
"preSetCommandGroup",
"sensors",
"stationaryLat",
"stationaryLon",
],
});
value.collectionProfiles.push({
id: COLLECTION_PROFILE_ID,
version: GELIOS_PROVIDER_PACKAGE_VERSION,
mode: "realtime",
schedule: { intervalMs: 6 * 60 * 60 * 1000 },
capabilityIds: ["gelios.units.current.read"],
dataProductId: GELIOS_UNIT_CONTACTS_DATA_PRODUCT_ID,
mappingContractId: MAPPING_ID,
fieldPolicyId: FIELD_POLICY_ID,
l2TemplateId: TEMPLATE_ID,
entityScope: {
mode: "all_visible_to_credential",
refresh: "each_collection_run",
businessEntityFilter: "forbidden",
},
batching: { maxFacts: 5000 },
cardinality: {
maxCurrentEntities: 5000,
onExceed: "require_partitioned_data_product",
},
retry: { maxAttempts: 4, backoff: "fixed_delay", delayMs: 2000 },
});
value.dataProducts.push({
id: GELIOS_UNIT_CONTACTS_DATA_PRODUCT_ID,
version: GELIOS_UNIT_CONTACTS_DATA_PRODUCT_VERSION,
ontologyRevision: GELIOS_UNIT_CONTACTS_ONTOLOGY_REVISION,
deliveryMode: "snapshot+patch",
semanticTypes: ["map.moving_object"],
fields: [...contactFields],
fieldContracts: {
device_imei: optionalString(),
device_phone_primary: optionalString(),
device_phone_secondary: optionalString(),
display_name: { type: "string", required: true },
provider_creator_login: optionalString(),
},
history: { mode: "none", retentionDays: 1 },
});
value.mappingContracts.push({
schemaVersion: "nodedc.semantic-mapping/v1",
id: MAPPING_ID,
version: GELIOS_PROVIDER_PACKAGE_VERSION,
sourceCapabilityId: "gelios.units.current.read",
fieldPolicyId: FIELD_POLICY_ID,
target: {
dataProductId: GELIOS_UNIT_CONTACTS_DATA_PRODUCT_ID,
version: GELIOS_UNIT_CONTACTS_DATA_PRODUCT_VERSION,
ontologyRevision: GELIOS_UNIT_CONTACTS_ONTOLOGY_REVISION,
semanticType: "map.moving_object",
},
derivations: {},
fact: {
sourceId: {
strategy: "first_non_empty",
paths: ["id", "unit_id", "unitId"],
coerce: "string",
prefix: "gelios-unit-",
},
semanticType: { constant: "map.moving_object" },
observedAt: {
strategy: "first_non_empty",
paths: ["updatedAt"],
coerce: "unix_or_iso_timestamp",
fallback: "collection_received_at",
},
attributes: {
device_imei: guardedStringField(["imei"], "imeiIsVisible"),
device_phone_primary: guardedStringField(["phone"], "phoneIsVisible"),
device_phone_secondary: guardedStringField(["phone2"], "phone2IsVisible"),
display_name: stringField(["name", "unit_name", "title", "label"], false),
provider_creator_login: stringField(["creator.login"]),
},
},
});
const profileTemplate = value.l2Templates.find(
(template) => template.id === "gelios.units.profile.l2.v1",
);
if (!profileTemplate) throw new Error("gelios_v10_profile_template_missing");
value.l2Templates.push({
...structuredClone(profileTemplate),
id: TEMPLATE_ID,
version: GELIOS_PROVIDER_PACKAGE_VERSION,
steps: [
{ id: "collection.trigger", kind: "collection_trigger", collectionProfileDriven: true },
{ id: "provider.fetch-units", kind: "provider_request", capabilityId: "gelios.units.current.read" },
{ id: "provider.extract-units", kind: "extract_items", capabilityId: "gelios.units.current.read" },
{ id: "ontology.map", kind: "semantic_mapping", mappingContractId: MAPPING_ID },
{
id: "data-product.publish",
kind: "data_product_publish",
dataProductId: GELIOS_UNIT_CONTACTS_DATA_PRODUCT_ID,
nodeType: "n8n-nodes-ndc.ndcDataProductPublish",
},
],
});
export const geliosProviderPackageV10 = deepFreeze(value);
function optionalString() {
return { type: "string", required: false };
}
function stringField(paths, omitIfMissing = true) {
return {
strategy: "first_non_empty",
paths,
coerce: "string",
...(omitIfMissing ? { omitIfMissing: true } : {}),
};
}
function guardedStringField(paths, guardPath) {
return {
...stringField(paths),
guardPath,
guardEquals: true,
};
}
function deepFreeze(input) {
if (!input || typeof input !== "object" || Object.isFrozen(input)) return input;
Object.freeze(input);
for (const child of Object.values(input)) deepFreeze(child);
return input;
}