{"version":3,"file":"index.bundle.cjs","sources":["../src/identify.ts","../src/integrity.ts","../src/schemaPatch.ts","../src/validate.ts","../src/index.ts"],"sourcesContent":["import type {\n\tAnchoredFloorTextFeature,\n\tAnchoredImageFeature,\n\tAnchoredImageProperties,\n\tAnchoredTextAreaFeature,\n\tAnchoredTextAreaProperties,\n\tFloatingImageFeature,\n\tFloatingImageProperties,\n\tFloatingTextAreaFeature,\n\tFloatingTextAreaProperties,\n\tFloorImageFeature,\n\tFloorTextFeature,\n\tLineStringStyle,\n\tPointStyle,\n\tPolygonStyle,\n\tTextAreaFeature,\n} from './extensions/index.js';\n\nexport const isPolygonStyle = (value: PolygonStyle | LineStringStyle | PointStyle): value is PolygonStyle =>\n\t'polygons' in value;\n\nexport const isLineStringStyle = (value: PolygonStyle | LineStringStyle | PointStyle): value is LineStringStyle =>\n\t'width' in value && 'lineStrings' in value;\n\nexport const isPointStyle = (value: PolygonStyle | LineStringStyle | PointStyle): value is PointStyle =>\n\t'points' in value;\n\nexport const isAnchoredImageProperties = (\n\tvalue: AnchoredImageProperties | FloatingImageProperties,\n): value is AnchoredImageProperties => 'anchorId' in value;\n\nexport const isFloatingImageProperties = (\n\tvalue: AnchoredImageProperties | FloatingImageProperties,\n): value is FloatingImageProperties => 'verticalOffset' in value;\n\nexport const isAnchoredTextAreaProperties = (\n\tvalue: AnchoredTextAreaProperties | FloatingTextAreaProperties,\n): value is AnchoredTextAreaProperties => 'anchorId' in value;\n\nexport const isFloatingTextAreaProperties = (\n\tvalue: AnchoredTextAreaProperties | FloatingTextAreaProperties,\n): value is FloatingTextAreaProperties => 'verticalOffset' in value;\n\nexport const isAnchoredImageOrTextLabelFeature = (\n\tvalue: FloorImageFeature | FloorTextFeature,\n): value is AnchoredImageFeature | AnchoredFloorTextFeature =>\n\t'anchorId' in value.properties || 'geometryId' in value.properties;\n\nexport const isFloatingImageFeature = (value: FloorImageFeature): value is FloatingImageFeature =>\n\t'verticalOffset' in value.properties;\n\nexport const isAnchoredTextAreaFeature = (value: TextAreaFeature): value is AnchoredTextAreaFeature =>\n\t'anchorId' in value.properties;\n\nexport const isFloatingTextAreaFeature = (value: TextAreaFeature): value is FloatingTextAreaFeature =>\n\t'verticalOffset' in value.properties;\n","import {\n\tAnchoredFloorTextUnknownObstructionError,\n\tAnchoredFloorTextUnknownSpaceError,\n\tAnchoredImageUnknownAreaError,\n\tAnchoredImageUnknownObstructionError,\n\tAnchoredImageUnknownSpaceError,\n\tAnnotationSymbolDuplicateError,\n\tAnnotationSymbolUnknownError,\n\tConnectionUnknownNodeError,\n\tDuplicateTilesetKeyError,\n\tEnterpriseCyclicalCategoryReferenceError,\n\tEnterpriseInconsistentMapError,\n\tEnterpriseInvalidTimeZoneError,\n\tEnterpriseLayerUnknownSpaceError,\n\tEnterpriseLocationUnknownSpaceError,\n\tEnterpriseStyleGeometryAnchorsUnknownSpaceError,\n\tEnterpriseTextureUnknownSpaceError,\n\tEnterpriseUnknownCategoryError,\n\tEnterpriseUnknownLocationError,\n\tEnterpriseUnknownMapError,\n\tFacadeUnknownFloorError,\n\tFacadeUnknownFloorStackError,\n\tFacadeUnknownSpaceError,\n\tFloorStackUnknownMapError,\n\tInvalidStyleError,\n\tNodeSelfReferenceError,\n\tNodeUnknownFloorError,\n\tNodeUnknownNeighborError,\n\tNodeUnknownSpaceError,\n\tObstructionCollectionUnknownMapError,\n\tObstructionUnknownEntranceError,\n\tSpaceCollectionUnknownMapError,\n\tSpaceUnknownNodeError,\n\tStyleUnknownLineStringError,\n\tStyleUnknownPointError,\n\tStyleUnknownPolygonError,\n\tTextAreaUnknownObstructionError,\n\tTextAreaUnknownSpaceError,\n} from './error.js';\nimport { isAnchoredImageOrTextLabelFeature, isLineStringStyle, isPointStyle, isPolygonStyle } from './identify.js';\nimport type { ParsedMVF } from './types/bundle.js';\nimport type { FloorId, FloorStackId } from './types/core.js';\n\nexport const availableFloorIds = (mvf: ParsedMVF): Set<FloorId> => {\n\tif (mvf['floor.geojson'] != null) {\n\t\treturn new Set(mvf['floor.geojson'].features.map((f) => f.properties.id));\n\t}\n\treturn new Set(mvf['map.geojson'].map((m) => m.id));\n};\n\nexport const availableFloorStackIds = (mvf: ParsedMVF): Set<FloorStackId> => {\n\tif (mvf['floorstack.json'] != null) {\n\t\treturn new Set(mvf['floorstack.json'].map((f) => f.id));\n\t}\n\treturn new Set(mvf['mapstack.geojson'].map((m) => m.id));\n};\n\n/**\n * For a map stack to be valid, all of the map IDs listed on the maps property must be a map listed in the maps\n * property.\n *\n * @throws {@link FloorStackUnknownMapError}\n */\nexport const validateMapStacks = (mvf: ParsedMVF) => {\n\tconst availableFloors = availableFloorIds(mvf);\n\tconst stacks = mvf['floorstack.json'] ?? mvf['mapstack.json'] ?? mvf['mapstack.geojson'];\n\n\tfor (const stack of stacks) {\n\t\tfor (const mapId of stack.maps) {\n\t\t\tif (!availableFloors.has(mapId)) {\n\t\t\t\tthrow new FloorStackUnknownMapError(stack, mapId);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n};\n\n/**\n * For a space collection to be valid:\n * - Each collection must have a map ID corresponding to a map available in the MVF\n * - Each space that has destination nodes must point to real nodes\n *\n * @throws {@link SpaceCollectionUnknownMapError}\n * @throws {@link SpaceUnknownNodeError}\n */\nexport const validateSpaces = (mvf: ParsedMVF) => {\n\tconst availableFloors = availableFloorIds(mvf);\n\tconst availableNodes = new Set(mvf['node.geojson'].features.map((n) => n.properties.id));\n\n\tfor (const [mapId, spaceCollection] of Object.entries(mvf.space)) {\n\t\tif (!availableFloors.has(mapId)) {\n\t\t\tthrow new SpaceCollectionUnknownMapError(mapId);\n\t\t}\n\t\tif (!spaceCollection) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tfor (const space of spaceCollection.features) {\n\t\t\tfor (const nodeId of space.properties.destinationNodes) {\n\t\t\t\tif (!availableNodes.has(nodeId)) {\n\t\t\t\t\tthrow new SpaceUnknownNodeError(space.properties, nodeId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n};\n\n/**\n * For an obstruction collection to be valid:\n * - Each collection must have a map ID corresponding to a map available in the MVF\n * - Each obstruction that has entrance IDs must have those entrances:\n *   - In the entrance collection, and\n *   - On the same map as the obstruction.\n *\n * @throws {@link ObstructionCollectionUnknownMapError}\n * @throws {@link ObstructionUnknownEntranceError}\n */\nexport const validateObstructions = (mvf: ParsedMVF) => {\n\tconst availableFloors = availableFloorIds(mvf);\n\tconst availableEntrances = Object.entries(mvf.entrance).reduce(\n\t\t(aggregate, [mapId, entranceCollection]) => {\n\t\t\taggregate[mapId] = new Set((entranceCollection ? entranceCollection.features : []).map((e) => e.properties.id));\n\t\t\treturn aggregate;\n\t\t},\n\t\t{} as Partial<Record<string, Set<string>>>,\n\t);\n\n\tfor (const [mapId, obstructionCollection] of Object.entries(mvf.obstruction)) {\n\t\tif (!availableFloors.has(mapId)) {\n\t\t\tthrow new ObstructionCollectionUnknownMapError(mapId);\n\t\t}\n\t\tif (!obstructionCollection) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tfor (const obstruction of obstructionCollection.features) {\n\t\t\tfor (const entranceId of obstruction.properties.entrances) {\n\t\t\t\tconst mapEntrances = availableEntrances[mapId];\n\t\t\t\tif (!mapEntrances || !mapEntrances.has(entranceId)) {\n\t\t\t\t\tthrow new ObstructionUnknownEntranceError(obstruction.properties, mapId, entranceId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n};\n\n/**\n * For a connection to be valid, it must only contain node IDs that exist in the MVF.\n *\n * @throws {@link ConnectionUnknownNodeError}\n */\nexport const validateConnections = (mvf: ParsedMVF): boolean => {\n\tconst availableNodes = new Set(mvf['node.geojson'].features.map((n) => n.properties.id));\n\n\tfor (const connection of mvf['connection.json']) {\n\t\tfor (const nodeId of connection.nodes) {\n\t\t\tif (!availableNodes.has(nodeId)) {\n\t\t\t\tthrow new ConnectionUnknownNodeError(connection, nodeId);\n\t\t\t}\n\t\t}\n\t}\n\n\t// This doesn't validate that a node referenced by a connection connects to other connection node(s).  While that\n\t// case is _probably_ an error, it's a connection setup error rather than an MVF spec error.\n\treturn true;\n};\n\n/**\n * For the node collection to be valid:\n * - Each node must have a valid map ID property\n * - Each space ID in a node's space property must be a valid space ID on the same map\n * - Each neighbor of a node should have a valid node ID\n *\n * @throws {@link NodeUnknownFloorError}\n * @throws {@link NodeUnknownSpaceError}\n * @throws {@link NodeUnknownNeighborError}\n */\nexport const validateNodes = (mvf: ParsedMVF): boolean => {\n\tconst availableFloors = availableFloorIds(mvf);\n\tconst availableSpaces = Object.entries(mvf.space).reduce(\n\t\t(aggregate, [mapId, spaceCollection]) => {\n\t\t\taggregate[mapId] = new Set((spaceCollection ? spaceCollection.features : []).map((e) => e.properties.id));\n\t\t\treturn aggregate;\n\t\t},\n\t\t{} as Partial<Record<string, Set<string>>>,\n\t);\n\tconst availableNodes = new Set(mvf['node.geojson'].features.map((n) => n.properties.id));\n\n\tfor (const node of mvf['node.geojson'].features) {\n\t\tconst floorId = node.properties.floor ?? node.properties.map;\n\t\tif (!availableFloors.has(floorId)) {\n\t\t\tthrow new NodeUnknownFloorError(node.properties);\n\t\t}\n\n\t\tfor (const spaceId of node.properties.space) {\n\t\t\tif (!availableSpaces[floorId]?.has(spaceId)) {\n\t\t\t\tthrow new NodeUnknownSpaceError(node.properties, spaceId);\n\t\t\t}\n\t\t}\n\n\t\tfor (const neighborNode of node.properties.neighbors) {\n\t\t\tif (!availableNodes.has(neighborNode.id)) {\n\t\t\t\tthrow new NodeUnknownNeighborError(node.properties, neighborNode.id);\n\t\t\t}\n\t\t\tif (neighborNode.id === node.properties.id) {\n\t\t\t\tthrow new NodeSelfReferenceError(node.properties);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n};\n\n/**\n * For a facade to be valid:\n * - The floor stack ID (key in mvf.facade) must correspond to an existing floor stack\n * - The floor ID must correspond to an existing floor\n * - The space ID must correspond to an existing space\n * - Empty or null collections are allowed\n *\n * @throws {@link FacadeUnknownFloorStackError}\n * @throws {@link FacadeUnknownSpaceError}\n * @throws {@link FacadeUnknownFloorError}\n */\nexport const validateFacades = (mvf: ParsedMVF): boolean => {\n\tif (!mvf.facade) {\n\t\treturn true;\n\t}\n\tconst availableFloorStacks = availableFloorStackIds(mvf);\n\tconst availableFloors = availableFloorIds(mvf);\n\tconst availableSpaces = Object.entries(mvf.space).reduce(\n\t\t(aggregate, [mapId, spaceCollection]) => {\n\t\t\taggregate[mapId] = new Set((spaceCollection ? spaceCollection.features : []).map((e) => e.properties.id));\n\t\t\treturn aggregate;\n\t\t},\n\t\t{} as Partial<Record<string, Set<string>>>,\n\t);\n\n\tfor (const [mapStackId, facade] of Object.entries(mvf.facade)) {\n\t\tif (!availableFloorStacks.has(mapStackId)) {\n\t\t\tthrow new FacadeUnknownFloorStackError(mapStackId);\n\t\t}\n\n\t\tif (!facade) continue;\n\n\t\tfor (const { floorId, spaceId } of facade.spaces) {\n\t\t\tif (!availableFloors.has(floorId)) {\n\t\t\t\tthrow new FacadeUnknownFloorError(facade.id, floorId);\n\t\t\t}\n\t\t\tconst floorSpaces = availableSpaces[floorId];\n\t\t\tif (!floorSpaces?.has(spaceId)) {\n\t\t\t\tthrow new FacadeUnknownSpaceError(facade.id, spaceId, floorId);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n};\n\n/**\n * For a style to be valid, it must only apply to valid space or obstruction.\n *\n * @throws {@link StyleUnknownPolygonError}\n * @throws {@link StyleUnknownLineStringError}\n * @throws {@link InvalidStyleError}\n */\nexport const validateStyles = (mvf: ParsedMVF): boolean => {\n\tif (!mvf['styles.json']) {\n\t\treturn true;\n\t}\n\n\tconst allowedPolygons: Record<string, string> = {};\n\tconst allowedLineStrings: Record<string, string> = {};\n\tconst allowedPoints: Record<string, string> = {};\n\n\t// Categorize spaces\n\tObject.values(mvf.space).forEach((spaceCollection) => {\n\t\tspaceCollection?.features.forEach((s) => {\n\t\t\tif (s.geometry.type === 'Polygon') {\n\t\t\t\tallowedPolygons[s.properties.id] = 'space';\n\t\t\t} else if (s.geometry.type === 'LineString') {\n\t\t\t\tallowedLineStrings[s.properties.id] = 'space';\n\t\t\t} else if (s.geometry.type === 'Point') {\n\t\t\t\tallowedPoints[s.properties.id] = 'space';\n\t\t\t}\n\t\t});\n\t});\n\n\t// Categorize obstructions\n\tObject.values(mvf.obstruction).forEach((obstructionCollection) => {\n\t\tobstructionCollection?.features.forEach((o) => {\n\t\t\tif (o.geometry.type === 'Polygon') {\n\t\t\t\tallowedPolygons[o.properties.id] = 'obstruction';\n\t\t\t} else if (o.geometry.type === 'LineString') {\n\t\t\t\tallowedLineStrings[o.properties.id] = 'obstruction';\n\t\t\t}\n\t\t});\n\t});\n\n\t// Categorize entrances\n\tObject.values(mvf.entrance).forEach((entranceCollection) => {\n\t\tentranceCollection?.features.forEach((e) => {\n\t\t\tallowedLineStrings[e.properties.id] = 'entrance';\n\t\t});\n\t});\n\n\tfor (const [styleId, style] of Object.entries(mvf['styles.json'])) {\n\t\tif (!style) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (isPolygonStyle(style)) {\n\t\t\tfor (const polyId of style.polygons) {\n\t\t\t\tconst polyKind = polyId.startsWith('s_') ? 'space' : polyId.startsWith('o_') ? 'obstruction' : 'unknown';\n\n\t\t\t\tif (!allowedPolygons[polyId]) {\n\t\t\t\t\tthrow new StyleUnknownPolygonError(styleId, polyKind, polyId);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (isLineStringStyle(style)) {\n\t\t\tfor (const lineId of style.lineStrings) {\n\t\t\t\tconst lineKind = lineId.startsWith('s_')\n\t\t\t\t\t? 'space'\n\t\t\t\t\t: lineId.startsWith('o_')\n\t\t\t\t\t\t? 'obstruction'\n\t\t\t\t\t\t: lineId.startsWith('e_')\n\t\t\t\t\t\t\t? 'entrance'\n\t\t\t\t\t\t\t: 'unknown';\n\n\t\t\t\tif (!allowedLineStrings[lineId]) {\n\t\t\t\t\tthrow new StyleUnknownLineStringError(styleId, lineKind, lineId);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (isPointStyle(style)) {\n\t\t\tfor (const pointId of style.points) {\n\t\t\t\tif (!allowedPoints[pointId]) {\n\t\t\t\t\tthrow new StyleUnknownPointError(styleId, 'space', pointId);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new InvalidStyleError(styleId);\n\t\t}\n\t}\n\n\treturn true;\n};\n\n/**\n * For a text to be valid, it must be either anchored or floating.\n * - Each anchored text must reference an existing space or obstruction on the correct map\n * - Each floating text must have a valid vertical offset\n *\n * @throws {@link AnchoredFloorTextUnknownSpaceError}\n * @throws {@link AnchoredFloorTextUnknownObstructionError}\n */\nexport const validateFloorText = (mvf: ParsedMVF): boolean => {\n\tconst floorText = mvf?.enterprise?.['floorText'];\n\tif (!floorText) {\n\t\treturn true;\n\t}\n\n\tconst availableSpaces = Object.entries(mvf.space).reduce(\n\t\t(aggregate, [mapId, spaceCollection]) => {\n\t\t\taggregate[mapId] = new Set((spaceCollection ? spaceCollection.features : []).map((e) => e.properties.id));\n\t\t\treturn aggregate;\n\t\t},\n\t\t{} as Partial<Record<string, Set<string>>>,\n\t);\n\tconst availablePolygonObstructions = Object.entries(mvf.obstruction).reduce(\n\t\t(aggregate, [mapId, obstructionCollection]) => {\n\t\t\taggregate[mapId] = new Set(\n\t\t\t\t(obstructionCollection ? obstructionCollection.features : [])\n\t\t\t\t\t.filter((e) => e.geometry.type === 'Polygon')\n\t\t\t\t\t.map((e) => e.properties.id),\n\t\t\t);\n\t\t\treturn aggregate;\n\t\t},\n\t\t{} as Partial<Record<string, Set<string>>>,\n\t);\n\n\tfor (const [floorId, floorTextCollection] of Object.entries(floorText)) {\n\t\tif (!floorTextCollection) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tfor (const textLabel of floorTextCollection.features) {\n\t\t\tif (isAnchoredImageOrTextLabelFeature(textLabel)) {\n\t\t\t\tconst geometryId = textLabel.properties.geometryId;\n\t\t\t\tif (geometryId.startsWith('o_') && !availablePolygonObstructions[floorId]?.has(geometryId)) {\n\t\t\t\t\tthrow new AnchoredFloorTextUnknownObstructionError(geometryId, floorId);\n\t\t\t\t}\n\t\t\t\tif (geometryId.startsWith('s_') && !availableSpaces[floorId]?.has(geometryId)) {\n\t\t\t\t\tthrow new AnchoredFloorTextUnknownSpaceError(geometryId, floorId);\n\t\t\t\t}\n\t\t\t} // Else, it is a floating text and doesn't need to reference anything\n\t\t}\n\t}\n\n\treturn true;\n};\n\n/**\n * For a map image entry to be valid, it must either be a floating image, or a polygon image that references a space,\n * obstruction, or area on the correct map.\n *\n * @throws {@link AnchoredImageUnknownSpaceError}\n * @throws {@link AnchoredImageUnknownObstructionError}\n * @throws {@link AnchoredImageUnknownAreaError}\n */\nexport const validateFloorImages = (mvf: ParsedMVF): boolean => {\n\tconst floorImages = mvf['floorImages'];\n\tif (!floorImages) {\n\t\treturn true;\n\t}\n\n\tconst availableSpaces = Object.entries(mvf.space).reduce(\n\t\t(aggregate, [mapId, spaceCollection]) => {\n\t\t\taggregate[mapId] = new Set((spaceCollection ? spaceCollection.features : []).map((e) => e.properties.id));\n\t\t\treturn aggregate;\n\t\t},\n\t\t{} as Partial<Record<string, Set<string>>>,\n\t);\n\tconst availablePolygonObstructions = Object.entries(mvf.obstruction).reduce(\n\t\t(aggregate, [mapId, obstructionCollection]) => {\n\t\t\taggregate[mapId] = new Set(\n\t\t\t\t(obstructionCollection ? obstructionCollection.features : [])\n\t\t\t\t\t.filter((e) => e.geometry.type === 'Polygon')\n\t\t\t\t\t.map((e) => e.properties.id),\n\t\t\t);\n\t\t\treturn aggregate;\n\t\t},\n\t\t{} as Partial<Record<string, Set<string>>>,\n\t);\n\tconst availableAreas = Object.entries(mvf.area ?? {}).reduce(\n\t\t(aggregate, [mapId, areaCollection]) => {\n\t\t\taggregate[mapId] = new Set((areaCollection ? areaCollection.features : []).map((e) => e.properties.id));\n\t\t\treturn aggregate;\n\t\t},\n\t\t{} as Partial<Record<string, Set<string>>>,\n\t);\n\n\tfor (const [floorId, polygonImageCollection] of Object.entries(floorImages)) {\n\t\tif (!polygonImageCollection) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tfor (const image of polygonImageCollection.features) {\n\t\t\tif (isAnchoredImageOrTextLabelFeature(image)) {\n\t\t\t\tconst anchorId = image.properties.anchorId;\n\t\t\t\tif (anchorId.startsWith('o_') && !availablePolygonObstructions[floorId]?.has(anchorId)) {\n\t\t\t\t\tthrow new AnchoredImageUnknownObstructionError(anchorId, floorId);\n\t\t\t\t}\n\t\t\t\tif (anchorId.startsWith('s_') && !availableSpaces[floorId]?.has(anchorId)) {\n\t\t\t\t\tthrow new AnchoredImageUnknownSpaceError(anchorId, floorId);\n\t\t\t\t}\n\t\t\t\tif (anchorId.startsWith('ar_') && !availableAreas[floorId]?.has(anchorId)) {\n\t\t\t\t\tthrow new AnchoredImageUnknownAreaError(anchorId, floorId);\n\t\t\t\t}\n\t\t\t} // Else, it is a floating image and doesn't need to reference anything\n\t\t}\n\t}\n\n\treturn true;\n};\n\n/**\n * For a text area to be valid, it must be either anchored or floating.\n * - Each anchored text area must reference an existing space or obstruction on the correct map\n * - Each floating text area must have a valid vertical offset\n *\n * @throws {@link TextAreaUnknownSpaceError}\n * @throws {@link TextAreaUnknownObstructionError}\n */\nexport const validateTextAreas = (mvf: ParsedMVF): boolean => {\n\tif (!mvf['textAreas']) {\n\t\treturn true;\n\t}\n\n\tconst availableSpaces = Object.entries(mvf.space).reduce(\n\t\t(aggregate, [mapId, spaceCollection]) => {\n\t\t\taggregate[mapId] = new Set((spaceCollection ? spaceCollection.features : []).map((e) => e.properties.id));\n\t\t\treturn aggregate;\n\t\t},\n\t\t{} as Partial<Record<string, Set<string>>>,\n\t);\n\n\tconst availableObstructions = Object.entries(mvf.obstruction).reduce(\n\t\t(aggregate, [mapId, obstructionCollection]) => {\n\t\t\taggregate[mapId] = new Set(\n\t\t\t\t(obstructionCollection ? obstructionCollection.features : []).map((e) => e.properties.id),\n\t\t\t);\n\t\t\treturn aggregate;\n\t\t},\n\t\t{} as Partial<Record<string, Set<string>>>,\n\t);\n\n\tfor (const [floorId, textAreaFeatureCollection] of Object.entries(mvf['textAreas'])) {\n\t\tif (!textAreaFeatureCollection) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tfor (const textArea of textAreaFeatureCollection.features) {\n\t\t\tif ('anchorId' in textArea.properties) {\n\t\t\t\tconst anchorId = textArea.properties.anchorId;\n\t\t\t\tif (anchorId.startsWith('s_')) {\n\t\t\t\t\tif (!availableSpaces[floorId]?.has(anchorId)) {\n\t\t\t\t\t\tthrow new TextAreaUnknownSpaceError(anchorId, floorId);\n\t\t\t\t\t}\n\t\t\t\t} else if (anchorId.startsWith('o_')) {\n\t\t\t\t\tif (!availableObstructions[floorId]?.has(anchorId)) {\n\t\t\t\t\t\tthrow new TextAreaUnknownObstructionError(anchorId, floorId);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(`Invalid text area anchor ID: ${anchorId}`);\n\t\t\t\t}\n\t\t\t} else if ('verticalOffset' in textArea.properties) {\n\t\t\t\tif (textArea.properties.verticalOffset < 0) {\n\t\t\t\t\tthrow new Error(`Invalid vertical offset for floating text area: ${textArea.properties.verticalOffset}`);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new Error(`Invalid text area properties: ${JSON.stringify(textArea.properties)}`);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n};\n\nexport const validateEnterprise = (mvf: ParsedMVF): boolean => {\n\tif (!mvf['enterprise']) {\n\t\treturn true;\n\t}\n\n\tconst enterprise = mvf['enterprise'];\n\n\t// Validate the venue's timezone\n\tif (enterprise.venue.tzid) {\n\t\ttry {\n\t\t\t// This will throw if the timezone is invalid. There does not seem to be a\n\t\t\t// better way to validate this.\n\t\t\tnew Intl.DateTimeFormat('en', { timeZone: enterprise.venue.tzid });\n\t\t} catch (_e) {\n\t\t\tthrow new EnterpriseInvalidTimeZoneError(enterprise.venue.tzid);\n\t\t}\n\t}\n\n\t// Collect all EnterpriseLocationIds\n\tconst enterpriseLocationIds = new Set<string>(enterprise.locations.map((loc) => loc.id));\n\n\t// Validate Venue's topLocations\n\tif (enterprise.venue.topLocations) {\n\t\tfor (const locId of enterprise.venue.topLocations) {\n\t\t\tif (!enterpriseLocationIds.has(locId)) {\n\t\t\t\tthrow new EnterpriseUnknownLocationError(locId);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Collect all map IDs from 'map.geojson'\n\tconst availableMaps = new Set<string>(mvf['floor.geojson']?.features.map((m) => m.properties.id));\n\n\t// Validate venue's defaultFloor\n\tif (enterprise.venue.defaultFloor && !availableMaps.has(enterprise.venue.defaultFloor)) {\n\t\tthrow new EnterpriseUnknownMapError(enterprise.venue.defaultFloor);\n\t}\n\n\t// Collect all space IDs per map\n\tconst availableSpacesPerMap: Record<string, Set<string>> = {};\n\tfor (const [floorId, spaceCollection] of Object.entries(mvf.space ?? {})) {\n\t\tavailableSpacesPerMap[floorId] = new Set(spaceCollection?.features.map((s) => s.properties.id));\n\t}\n\n\t// Validate Enterprise Locations\n\tfor (const location of enterprise.locations) {\n\t\t// Validate spaces\n\t\tfor (const space of location.spaces ?? []) {\n\t\t\tconst { floor: floorId, id: spaceId } = space;\n\t\t\tif (!availableMaps.has(floorId)) {\n\t\t\t\tthrow new EnterpriseUnknownMapError(floorId);\n\t\t\t}\n\t\t\tif (!availableSpacesPerMap[floorId]?.has(spaceId)) {\n\t\t\t\tconst actualMap = Array.from(availableMaps.values())\n\t\t\t\t\t.map((m) => (availableSpacesPerMap[m]?.has(spaceId) ? m : null))\n\t\t\t\t\t.find((m) => m !== null);\n\t\t\t\tif (actualMap != undefined) {\n\t\t\t\t\tthrow new EnterpriseInconsistentMapError(location.id, spaceId, floorId, actualMap);\n\t\t\t\t} else {\n\t\t\t\t\tthrow new EnterpriseLocationUnknownSpaceError(location.id, spaceId, floorId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const layer of enterprise.layers) {\n\t\tfor (const { spaceId, floorId } of layer.spaces) {\n\t\t\tif (!availableSpacesPerMap[floorId]?.has(spaceId)) {\n\t\t\t\tthrow new EnterpriseLayerUnknownSpaceError(spaceId, floorId);\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const [_, style] of Object.entries(enterprise.enterpriseStyles || {})) {\n\t\tfor (const { geometryId, floorId } of style.geometryAnchors) {\n\t\t\tif (!availableSpacesPerMap[floorId]?.has(geometryId)) {\n\t\t\t\tthrow new EnterpriseStyleGeometryAnchorsUnknownSpaceError(geometryId, floorId);\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const texture of enterprise.textures ?? []) {\n\t\tfor (const anchor of texture.geometryAnchors) {\n\t\t\tif (!availableSpacesPerMap[anchor.floorId]?.has(anchor.geometryId)) {\n\t\t\t\tthrow new EnterpriseTextureUnknownSpaceError(anchor.geometryId, anchor.floorId);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Collect all EnterpriseCategoryIds\n\tconst enterpriseCategoryIds = new Set<string>(enterprise.categories.map((cat) => cat.id));\n\n\t// Validate Categories\n\tconst categoryHierarchy: Record<string, Set<string>> = {};\n\tfor (const category of enterprise.categories) {\n\t\tcategoryHierarchy[category.id] = new Set(category.children);\n\t}\n\n\t// Check for cyclical references\n\tconst checkCyclicalReferences = (categoryId: string, visited: Set<string> = new Set()): void => {\n\t\tif (visited.has(categoryId)) {\n\t\t\tthrow new EnterpriseCyclicalCategoryReferenceError(categoryId);\n\t\t}\n\n\t\tvisited.add(categoryId);\n\t\tfor (const childId of categoryHierarchy[categoryId] || []) {\n\t\t\tcheckCyclicalReferences(childId, new Set(visited));\n\t\t}\n\t\tvisited.delete(categoryId);\n\t};\n\n\tfor (const category of enterprise.categories) {\n\t\tcheckCyclicalReferences(category.id);\n\n\t\t// Existing category validation logic\n\t\tfor (const childId of category.children) {\n\t\t\tif (!enterpriseCategoryIds.has(childId)) {\n\t\t\t\tthrow new EnterpriseUnknownCategoryError(childId);\n\t\t\t}\n\t\t}\n\n\t\tfor (const locId of category.locations) {\n\t\t\tif (!enterpriseLocationIds.has(locId)) {\n\t\t\t\tthrow new EnterpriseUnknownLocationError(locId);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n};\n\n/**\n * Validates that tileset keys are unique across the file\n *\n * @throws {@link DuplicateTilesetKeyError}\n */\nexport const validateTilesets = (mvf: ParsedMVF): boolean => {\n\tif (!mvf['tileset.json']) {\n\t\treturn true;\n\t}\n\n\tconst keys = new Set<string>();\n\tconst tileset = mvf['tileset.json'];\n\n\t// Check default tileset\n\tkeys.add(tileset.default.key);\n\n\t// Check other tilesets\n\tif (tileset.others) {\n\t\tfor (const style of tileset.others) {\n\t\t\tif (keys.has(style.key)) {\n\t\t\t\tthrow new DuplicateTilesetKeyError(style.key);\n\t\t\t}\n\t\t\tkeys.add(style.key);\n\t\t}\n\t}\n\n\treturn true;\n};\n\nexport const validateAnnotationSymbols = (mvf: ParsedMVF): boolean => {\n\tif (!mvf['annotation-symbols.json']) {\n\t\treturn true;\n\t}\n\n\tconst keys = new Set<string>();\n\tconst annotationSymbols = mvf['annotation-symbols.json'];\n\n\tfor (const key of Object.keys(annotationSymbols)) {\n\t\tif (keys.has(key)) {\n\t\t\tthrow new AnnotationSymbolDuplicateError(key);\n\t\t}\n\t\tkeys.add(key);\n\t}\n\n\tfor (const collection of Object.values(mvf['annotation'] ?? {})) {\n\t\tif (!collection) continue;\n\t\tfor (const annotation of collection.features) {\n\t\t\tif (!annotationSymbols[annotation.properties.symbolId]) {\n\t\t\t\tthrow new AnnotationSymbolUnknownError(annotation.properties.id, annotation.properties.symbolId);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n};\n\n/**\n * Assumes a valid MVF is being given to verify referential integrity is held.\n *\n * @throws {@link ConnectionUnknownNodeError}\n * @throws {@link FacadeUnknownFloorStackError}\n * @throws {@link FacadeUnknownSpaceError}\n * @throws {@link FacadeUnknownFloorError}\n * @throws {@link InvalidStyleError}\n * @throws {@link MapStackUnknownMapError}\n * @throws {@link NodeUnknownFloorError}\n * @throws {@link NodeUnknownNeighborError}\n * @throws {@link NodeUnknownSpaceError}\n * @throws {@link ObstructionCollectionUnknownMapError}\n * @throws {@link ObstructionUnknownEntranceError}\n * @throws {@link PolygonImageUnknownObstructionError}\n * @throws {@link PolygonImageUnknownSpaceError}\n * @throws {@link SpaceCollectionUnknownMapError}\n * @throws {@link SpaceUnknownNodeError}\n * @throws {@link StyleUnknownLineStringError}\n * @throws {@link StyleUnknownPolygonError}\n * @throws {@link EnterpriseUnknownLocationError}\n * @throws {@link EnterpriseUnknownMapError}\n * @throws {@link EnterpriseLocationUnknownSpaceError}\n * @throws {@link EnterpriseLocationUnknownNodeError}\n * @throws {@link EnterpriseUnknownCategoryError}\n * @throws {@link EnterpriseInconsistentMapError}\n * @throws {@link EnterpriseCyclicalCategoryReferenceError}\n * @throws {@link EnterpriseInvalidTimeZoneError}\n * @throws {@link AnnotationSymbolUnknownError}\n * @throws {@link AnnotationSymbolDuplicateError}\n */\nexport const verifyMvfIntegrity = (mvf: ParsedMVF): boolean => {\n\t// TODO: Each of these functions individually computes some useful sets for fast ID checks, but some could be reused\n\t// across multiple validation steps. Maybe this should compute all ID sets and pass those in where needed or this\n\t// could be a class that does this when constructed or something.\n\treturn (\n\t\tvalidateMapStacks(mvf) &&\n\t\tvalidateSpaces(mvf) &&\n\t\tvalidateObstructions(mvf) &&\n\t\tvalidateConnections(mvf) &&\n\t\tvalidateNodes(mvf) &&\n\t\tvalidateFacades(mvf) &&\n\t\tvalidateStyles(mvf) &&\n\t\tvalidateFloorImages(mvf) &&\n\t\tvalidateTextAreas(mvf) &&\n\t\tvalidateFloorText(mvf) &&\n\t\tvalidateEnterprise(mvf) &&\n\t\tvalidateTilesets(mvf) &&\n\t\tvalidateAnnotationSymbols(mvf)\n\t);\n};\n","type PotentiallyBadSchema = {\n\tallOf: { type?: string }[];\n\t[key: string]: unknown;\n};\n\nconst isPotentiallyBadSchema = (schema: unknown): schema is PotentiallyBadSchema => {\n\tconst schemaObj = schema as PotentiallyBadSchema;\n\treturn schemaObj?.allOf?.length === 2;\n};\n\n/**\n * TS-JSON-Schema-Generator does not handle Partial<T> correctly, creating these unsatisfiable schemas:\n * { \"allOf\": [ { \"type\": \"array\" }, { \"type\": \"object\" } ] }\n *\n * We need to clean up the schema to remove the allOf of type object when it is not needed.\n */\nexport function cleanupInvalidArrayAllOf(schema: unknown): unknown {\n\tif (typeof schema !== 'object' || schema === null) {\n\t\treturn schema;\n\t}\n\n\tif (Array.isArray(schema)) {\n\t\treturn schema.map(cleanupInvalidArrayAllOf);\n\t}\n\n\tconst result: Record<string, unknown> = { ...schema };\n\tfor (const [key, value] of Object.entries(result)) {\n\t\tif (typeof value === 'object' && value !== null) {\n\t\t\t// First recursively process the value\n\t\t\tconst processedValue = cleanupInvalidArrayAllOf(value);\n\n\t\t\t// Then check if it needs the allOf fix\n\t\t\tif (isPotentiallyBadSchema(processedValue)) {\n\t\t\t\tconst arrayIndex = processedValue.allOf.findIndex((item) => item.type === 'array');\n\t\t\t\tconst objectIndex = processedValue.allOf.findIndex((item) => item.type === 'object');\n\t\t\t\tif (arrayIndex !== -1 && objectIndex !== -1) {\n\t\t\t\t\tresult[key] = {\n\t\t\t\t\t\t...processedValue,\n\t\t\t\t\t\tallOf: [processedValue.allOf[arrayIndex]],\n\t\t\t\t\t};\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tresult[key] = processedValue;\n\t\t}\n\t}\n\n\treturn result;\n}\n","/* istanbul ignore file */\n\nimport { default as Ajv } from 'ajv';\nimport ajvFormats from 'ajv-formats';\nimport { cleanupInvalidArrayAllOf } from './schemaPatch.js';\nimport type { ParsedMVF } from './types/bundle.js';\n\n// This is just a stub file right now, it will be replaced at build time.\n// This seems to be the more `esm`-friendly way to do this vs. trying to\n// replicate with `createRequire`.\nimport schema from './parsed-mvf.schema.json' with { type: 'json' };\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst validator = ajvFormats.default(new Ajv.default()).compile<ParsedMVF>(cleanupInvalidArrayAllOf(schema) as any);\n\n/**\n * Given some value, verifies that it matches the MVF schema.\n *\n * @returns boolean\n */\nexport const validateMvf = (mvf: unknown): mvf is ParsedMVF => {\n\treturn validator(mvf);\n};\n\nexport const getMvfValidationErrors = (mvf: unknown): string[] => {\n\tvalidator(mvf);\n\treturn (\n\t\tvalidator.errors?.map((err) => {\n\t\t\t// @ts-expect-error this property exists but isn't typed\n\t\t\tconst name = validator.schema['$ref'];\n\t\t\tconst path = err.instancePath;\n\t\t\tconst msg = err.message;\n\t\t\treturn `${name}${path}: ${msg}`;\n\t\t}) ?? []\n\t);\n};\n","import { verifyMvfIntegrity } from './integrity.js';\nimport { getMvfValidationErrors, validateMvf } from './validate.js';\n\n/**\n * A convenience method for checking that some value which is supposed to be an MVF:\n * - Matches the MVF schema, and\n * - Maintains referential integrity\n *\n * This will not throw exceptions for bad MVFs. For detailed information and more granular error handling, use\n * {@link validateMvf} and {@link verifyMvfIntegrity} separately.\n */\nconst check = (mvf: unknown): boolean => {\n\ttry {\n\t\tconst validated = validateMvf(mvf);\n\t\tif (!validated) {\n\t\t\treturn false;\n\t\t}\n\t\tconst verified = verifyMvfIntegrity(mvf);\n\t\treturn verified;\n\t} catch {\n\t\treturn false;\n\t}\n};\n\nexport { check, validateMvf, verifyMvfIntegrity, getMvfValidationErrors };\nexport * from './no-validator.js';\n"],"names":["isPolygonStyle","value","isLineStringStyle","isPointStyle","isAnchoredImageOrTextLabelFeature","availableFloorIds","mvf","f","m","availableFloorStackIds","validateMapStacks","availableFloors","stacks","stack","mapId","FloorStackUnknownMapError","validateSpaces","availableNodes","n","spaceCollection","SpaceCollectionUnknownMapError","space","nodeId","SpaceUnknownNodeError","validateObstructions","availableEntrances","aggregate","entranceCollection","e","obstructionCollection","ObstructionCollectionUnknownMapError","obstruction","entranceId","mapEntrances","ObstructionUnknownEntranceError","validateConnections","connection","ConnectionUnknownNodeError","validateNodes","availableSpaces","node","floorId","NodeUnknownFloorError","spaceId","NodeUnknownSpaceError","neighborNode","NodeUnknownNeighborError","NodeSelfReferenceError","validateFacades","availableFloorStacks","mapStackId","facade","FacadeUnknownFloorStackError","FacadeUnknownFloorError","FacadeUnknownSpaceError","validateStyles","allowedPolygons","allowedLineStrings","allowedPoints","s","styleId","style","polyId","polyKind","StyleUnknownPolygonError","lineId","lineKind","StyleUnknownLineStringError","pointId","StyleUnknownPointError","InvalidStyleError","validateFloorText","floorText","availablePolygonObstructions","floorTextCollection","textLabel","geometryId","AnchoredFloorTextUnknownObstructionError","AnchoredFloorTextUnknownSpaceError","validateFloorImages","floorImages","availableAreas","areaCollection","polygonImageCollection","image","anchorId","AnchoredImageUnknownObstructionError","AnchoredImageUnknownSpaceError","AnchoredImageUnknownAreaError","validateTextAreas","availableObstructions","textAreaFeatureCollection","textArea","TextAreaUnknownSpaceError","TextAreaUnknownObstructionError","validateEnterprise","enterprise","EnterpriseInvalidTimeZoneError","enterpriseLocationIds","loc","locId","EnterpriseUnknownLocationError","availableMaps","EnterpriseUnknownMapError","availableSpacesPerMap","location","actualMap","EnterpriseInconsistentMapError","EnterpriseLocationUnknownSpaceError","layer","EnterpriseLayerUnknownSpaceError","_","EnterpriseStyleGeometryAnchorsUnknownSpaceError","texture","anchor","EnterpriseTextureUnknownSpaceError","enterpriseCategoryIds","cat","categoryHierarchy","category","checkCyclicalReferences","categoryId","visited","EnterpriseCyclicalCategoryReferenceError","childId","EnterpriseUnknownCategoryError","validateTilesets","keys","tileset","DuplicateTilesetKeyError","validateAnnotationSymbols","annotationSymbols","key","AnnotationSymbolDuplicateError","collection","annotation","AnnotationSymbolUnknownError","verifyMvfIntegrity","isPotentiallyBadSchema","schema","cleanupInvalidArrayAllOf","result","processedValue","arrayIndex","item","objectIndex","validator","ajvFormats","Ajv","validateMvf","getMvfValidationErrors","err","name","path","msg","check"],"mappings":"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"}