feat(foundry): render geozones as independent map layer
This commit is contained in:
+48
-13
@@ -1166,11 +1166,53 @@ async function inspectFoundryConsumerReaderGrant(target, { generation = 1 } = {}
|
||||
return { product: planned.product, readerGrantAction: "ensure", readerGrantGeneration: generation };
|
||||
}
|
||||
|
||||
function runtimePointGeometry(value) {
|
||||
if (!isObject(value) || value.type !== "Point" || !Array.isArray(value.coordinates) || value.coordinates.length !== 2) return null;
|
||||
const [longitude, latitude] = value.coordinates;
|
||||
if (typeof longitude !== "number" || !Number.isFinite(longitude) || typeof latitude !== "number" || !Number.isFinite(latitude)) return null;
|
||||
return { type: "Point", coordinates: [longitude, latitude] };
|
||||
function runtimePosition(value) {
|
||||
if (!Array.isArray(value) || value.length !== 2) return null;
|
||||
const [longitude, latitude] = value;
|
||||
if (
|
||||
typeof longitude !== "number"
|
||||
|| !Number.isFinite(longitude)
|
||||
|| longitude < -180
|
||||
|| longitude > 180
|
||||
|| typeof latitude !== "number"
|
||||
|| !Number.isFinite(latitude)
|
||||
|| latitude < -90
|
||||
|| latitude > 90
|
||||
) return null;
|
||||
return [longitude, latitude];
|
||||
}
|
||||
|
||||
function runtimeLinearRing(value) {
|
||||
if (!Array.isArray(value) || value.length < 4 || value.length > 10_000) return null;
|
||||
const positions = value.map(runtimePosition);
|
||||
if (positions.some((position) => !position)) return null;
|
||||
const first = positions[0];
|
||||
const last = positions.at(-1);
|
||||
if (!last || first[0] !== last[0] || first[1] !== last[1]) return null;
|
||||
return positions;
|
||||
}
|
||||
|
||||
function runtimePolygonCoordinates(value) {
|
||||
if (!Array.isArray(value) || value.length < 1 || value.length > 256) return null;
|
||||
const rings = value.map(runtimeLinearRing);
|
||||
return rings.some((ring) => !ring) ? null : rings;
|
||||
}
|
||||
|
||||
function runtimeGeometry(value) {
|
||||
if (!isObject(value) || JSON.stringify(value).length > 196_608) return null;
|
||||
if (value.type === "Point") {
|
||||
const coordinates = runtimePosition(value.coordinates);
|
||||
return coordinates ? { type: "Point", coordinates } : null;
|
||||
}
|
||||
if (value.type === "Polygon") {
|
||||
const coordinates = runtimePolygonCoordinates(value.coordinates);
|
||||
return coordinates ? { type: "Polygon", coordinates } : null;
|
||||
}
|
||||
if (value.type === "MultiPolygon" && Array.isArray(value.coordinates) && value.coordinates.length >= 1 && value.coordinates.length <= 256) {
|
||||
const coordinates = value.coordinates.map(runtimePolygonCoordinates);
|
||||
return coordinates.some((polygon) => !polygon) ? null : { type: "MultiPolygon", coordinates };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const RUNTIME_SECRET_LIKE_KEY = /(token|secret|password|authorization|access[_-]?token|refresh[_-]?token|api[_-]?key)/i;
|
||||
@@ -1203,7 +1245,7 @@ function sanitizeRuntimeFact(value, binding) {
|
||||
observedAt: value.observedAt,
|
||||
receivedAt: value.receivedAt,
|
||||
attributes,
|
||||
geometry: runtimePointGeometry(value.geometry),
|
||||
geometry: runtimeGeometry(value.geometry),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1285,23 +1327,16 @@ function sanitizeRuntimePatch(value, binding) {
|
||||
const fact = sanitizeRuntimeFact(operation.fact, binding);
|
||||
return fact ? [{ op: "upsert", fact }] : [];
|
||||
}
|
||||
// Current EDP v1 emits only upserts. Foundry already understands the
|
||||
// canonical removal shape so a future versioned product can revoke a
|
||||
// subject without turning a transient stream failure into deletion.
|
||||
if (
|
||||
operation.op === "remove"
|
||||
&& isRuntimeIdentifier(operation.sourceId)
|
||||
&& isRuntimeIdentifier(operation.semanticType)
|
||||
&& binding.semanticTypes.includes(operation.semanticType)
|
||||
&& isRuntimeTimestamp(operation.removedAt)
|
||||
&& ["tombstone", "revoked"].includes(operation.reason)
|
||||
) {
|
||||
return [{
|
||||
op: "remove",
|
||||
sourceId: operation.sourceId,
|
||||
semanticType: operation.semanticType,
|
||||
removedAt: operation.removedAt,
|
||||
reason: operation.reason,
|
||||
}];
|
||||
}
|
||||
return [];
|
||||
|
||||
Reference in New Issue
Block a user