{"version":3,"file":"convert-F9RuiKUB.cjs","sources":["../src/error.ts","../src/extensions/enterprise.ts","../src/extensions/navigationFlags.ts","../../mvf-core/dist/utils/locale/deep-merge.js","../src/locale.ts","../src/raw-to-parsed.ts","../../../node_modules/.pnpm/@mappedin+safe-types@1.2.0/node_modules/@mappedin/safe-types/dist/option.js","../../../node_modules/.pnpm/@mappedin+safe-types@1.2.0/node_modules/@mappedin/safe-types/dist/result.js","../../mvf-core/dist/utils/typed-keys.js","../../mvf-core/dist/utils/typed-entries.js","../../mvf-cms/dist/subSchemas/floor-text-values.js","../../mvf-cms/dist/subSchemas/utils-values.js","../../mvf-cms/dist/subSchemas/text-area-values.js","../../mvf-cms/dist/subSchemas/texture-values.js","../../mvf-cms/dist/subSchemas/enterprise-venue-values.js","../../mvf-navigation-flags/dist/utils.js","../../mvf-navigation-flags/dist/well-known-flags.js","../../mvf-connections/dist/connection-types.js","../../mvf-kinds/dist/kind-values.js","../src/converter/converterUtils.ts","../src/converter/geoCenter.ts","../src/converter/builderOptions.ts","../src/converter/builders/annotationBuilder.ts","../src/converter/builders/connectionBuilder.ts","../src/converter/builders/enterpriseBuilder.ts","../src/converter/builders/facadeBuilder.ts","../src/converter/builders/floorBuilder.ts","../src/converter/builders/floorImagesBuilder.ts","../src/converter/builders/floorStackBuilder.ts","../src/converter/builders/geometryBuilder.ts","../src/converter/builders/locationBuilder.ts","../src/converter/builders/manifestBuilder.ts","../src/converter/builders/nodeBuilder.ts","../src/converter/builders/styleBuilder.ts","../src/converter/convert.ts"],"sourcesContent":["import type { AnnotationId } from './extensions/annotation.js';\nimport type { AreaId } from './extensions/area.js';\nimport type { FacadeId } from './extensions/facade.js';\nimport type {\n\tConnection,\n\tEntranceId,\n\tFloorId,\n\tFloorStack,\n\tNodeId,\n\tNodeProperties,\n\tObstructionId,\n\tObstructionProperties,\n\tSpaceId,\n\tSpaceProperties,\n} from './types/core.js';\n\nexport class IntegrityError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = 'IntegrityError';\n\t}\n}\n\nexport class FloorStackUnknownMapError extends IntegrityError {\n\tfloorStack: FloorStack;\n\tfloorId: FloorId;\n\n\tconstructor(floorStack: FloorStack, floorId: FloorId) {\n\t\tsuper(\n\t\t\t`Floor stack '${floorStack.id}' contains floor '${floorId}' which is not listed in floor.geojson / map.geojson`,\n\t\t);\n\t\tthis.floorStack = floorStack;\n\t\tthis.floorId = floorId;\n\t}\n}\n\nexport class SpaceCollectionUnknownMapError extends IntegrityError {\n\tfloorId: FloorId;\n\n\tconstructor(floorId: FloorId) {\n\t\tsuper(`A space collection references floor '${floorId}' which does not exist`);\n\t\tthis.floorId = floorId;\n\t}\n}\n\nexport class SpaceUnknownNodeError extends IntegrityError {\n\tspace: SpaceProperties;\n\tnodeId: NodeId;\n\n\tconstructor(space: SpaceProperties, nodeId: NodeId) {\n\t\tsuper(`Space '${space.id}' references a destination node '${nodeId}' which does not exist`);\n\t\tthis.space = space;\n\t\tthis.nodeId = nodeId;\n\t}\n}\n\nexport class ObstructionCollectionUnknownMapError extends IntegrityError {\n\tfloorId: FloorId;\n\n\tconstructor(floorId: FloorId) {\n\t\tsuper(`An obstruction collection references floor '${floorId}' which does not exist`);\n\t\tthis.floorId = floorId;\n\t}\n}\n\nexport class ObstructionUnknownEntranceError extends IntegrityError {\n\tobstruction: ObstructionProperties;\n\tfloorId: FloorId;\n\tentranceId: EntranceId;\n\n\tconstructor(obstruction: ObstructionProperties, floorId: FloorId, entranceId: EntranceId) {\n\t\tsuper(\n\t\t\t`Obstruction '${obstruction.id}' references an entrance '${entranceId}' which does not exist on floor '${floorId}'`,\n\t\t);\n\t\tthis.obstruction = obstruction;\n\t\tthis.floorId = floorId;\n\t\tthis.entranceId = entranceId;\n\t}\n}\n\nexport class ConnectionUnknownNodeError extends IntegrityError {\n\tconnection: Connection;\n\tnodeId: NodeId;\n\n\tconstructor(connection: Connection, nodeId: NodeId) {\n\t\tsuper(`Connection '${connection.id}' references a node '${nodeId}' which does not exist`);\n\t\tthis.connection = connection;\n\t\tthis.nodeId = nodeId;\n\t}\n}\n\nexport class NodeUnknownFloorError extends IntegrityError {\n\tnode: NodeProperties;\n\tfloorId: FloorId;\n\n\tconstructor(node: NodeProperties) {\n\t\tconst floorId = node.floor ?? node.map;\n\t\tsuper(`Node '${node.id}' claims to be on floor '${floorId}' which does not exist`);\n\t\tthis.node = node;\n\t\tthis.floorId = floorId;\n\t}\n}\n\nexport class NodeUnknownSpaceError extends IntegrityError {\n\tnode: NodeProperties;\n\tspaceId: SpaceId;\n\n\tconstructor(node: NodeProperties, spaceId: SpaceId) {\n\t\tsuper(`Node '${node.id}' references a space '${spaceId}' (on floor '${node.map}') which does not exist`);\n\t\tthis.node = node;\n\t\tthis.spaceId = spaceId;\n\t}\n}\n\nexport class NodeUnknownNeighborError extends IntegrityError {\n\tnode: NodeProperties;\n\tneighborId: NodeId;\n\n\tconstructor(node: NodeProperties, neighborId: NodeId) {\n\t\tsuper(`Node '${node.id}' has a neighbor node '${neighborId}' which does not exist`);\n\t\tthis.node = node;\n\t\tthis.neighborId = neighborId;\n\t}\n}\n\nexport class NodeSelfReferenceError extends IntegrityError {\n\tnode: NodeProperties;\n\n\tconstructor(node: NodeProperties) {\n\t\tsuper(`Node '${node.id}' has a self reference in its neighbors list`);\n\t\tthis.node = node;\n\t}\n}\n\nexport class StyleUnknownPolygonError extends IntegrityError {\n\tstyleId: string;\n\tpolygonKind: 'space' | 'obstruction' | 'unknown';\n\tpolygonId: SpaceId | ObstructionId;\n\n\tconstructor(styleId: string, polygonKind: 'space' | 'obstruction' | 'unknown', polygonId: SpaceId | ObstructionId) {\n\t\tsuper(`Style ${styleId} references a ${polygonKind} polygon ${polygonId} which does not exist.`);\n\t\tthis.styleId = styleId;\n\t\tthis.polygonKind = polygonKind;\n\t\tthis.polygonId = polygonId;\n\t}\n}\n\nexport class StyleUnknownLineStringError extends IntegrityError {\n\tstyleId: string;\n\tlineStringKind: 'space' | 'obstruction' | 'entrance' | 'unknown';\n\tlineStringId: SpaceId | ObstructionId | EntranceId;\n\n\tconstructor(\n\t\tstyleId: string,\n\t\tlineStringKind: 'space' | 'obstruction' | 'entrance' | 'unknown',\n\t\tlineStringId: SpaceId | ObstructionId | EntranceId,\n\t) {\n\t\tsuper(`Style ${styleId} references a ${lineStringKind} line string ${lineStringId} which does not exist.`);\n\t\tthis.styleId = styleId;\n\t\tthis.lineStringKind = lineStringKind;\n\t\tthis.lineStringId = lineStringId;\n\t}\n}\n\nexport class StyleUnknownPointError extends IntegrityError {\n\tstyleId: string;\n\tpointKind: 'space';\n\tpointId: SpaceId;\n\n\tconstructor(styleId: string, pointKind: 'space', pointId: SpaceId) {\n\t\tsuper(`Style ${styleId} references a ${pointKind} point ${pointId} which does not exist.`);\n\t\tthis.styleId = styleId;\n\t\tthis.pointKind = pointKind;\n\t\tthis.pointId = pointId;\n\t}\n}\n\nexport class InvalidStyleError extends IntegrityError {\n\tstyleId: string;\n\n\tconstructor(styleId: string) {\n\t\tsuper(`Style ${styleId} does not appear to be a valid polygon or line string style.`);\n\t\tthis.styleId = styleId;\n\t}\n}\n\nexport class AnchoredImageUnknownSpaceError extends IntegrityError {\n\tspaceId: SpaceId;\n\tfloorId: FloorId;\n\n\tconstructor(spaceId: SpaceId, floorId: FloorId) {\n\t\tsuper(`An image for space polygon ${spaceId} is defined, but this polygon does not exist on floor ${floorId}.`);\n\t\tthis.spaceId = spaceId;\n\t\tthis.floorId = floorId;\n\t}\n}\n\nexport class AnchoredFloorTextUnknownSpaceError extends IntegrityError {\n\tspaceId: SpaceId;\n\tfloorId: FloorId;\n\n\tconstructor(spaceId: SpaceId, floorId: FloorId) {\n\t\tsuper(`Text for space ${spaceId} is defined, but this space does not exist on floor ${floorId}.`);\n\t\tthis.spaceId = spaceId;\n\t\tthis.floorId = floorId;\n\t}\n}\n\nexport class AnchoredFloorTextUnknownObstructionError extends IntegrityError {\n\tobstructionId: ObstructionId;\n\tfloorId: FloorId;\n\n\tconstructor(obstructionId: ObstructionId, floorId: FloorId) {\n\t\tsuper(`Text for obstruction ${obstructionId} is defined, but this obstruction does not exist on floor ${floorId}.`);\n\t\tthis.obstructionId = obstructionId;\n\t\tthis.floorId = floorId;\n\t}\n}\n\nexport class AnchoredImageUnknownObstructionError extends IntegrityError {\n\tobstructionId: ObstructionId;\n\tfloorId: FloorId;\n\n\tconstructor(obstructionId: ObstructionId, floorId: FloorId) {\n\t\tsuper(\n\t\t\t`An image for obstruction polygon ${obstructionId} is defined, but this polygon does not exist on floor ${floorId}, or does not have allowed geometry.`,\n\t\t);\n\t\tthis.obstructionId = obstructionId;\n\t\tthis.floorId = floorId;\n\t}\n}\n\nexport class AnchoredImageUnknownAreaError extends IntegrityError {\n\tareaId: AreaId;\n\tfloorId: FloorId;\n\n\tconstructor(areaId: AreaId, floorId: FloorId) {\n\t\tsuper(`An image for area ${areaId} is defined, but this area does not exist on floor ${floorId}.`);\n\t\tthis.areaId = areaId;\n\t\tthis.floorId = floorId;\n\t}\n}\n\nexport class TextAreaUnknownSpaceError extends Error {\n\tspaceId: SpaceId;\n\tfloorId: FloorId;\n\n\tconstructor(spaceId: SpaceId, floorId: FloorId) {\n\t\tsuper(`A text area for space ${spaceId} is defined, but this space does not exist on floor ${floorId}.`);\n\t\tthis.spaceId = spaceId;\n\t\tthis.floorId = floorId;\n\t}\n}\n\nexport class EnterpriseLayerUnknownSpaceError extends Error {\n\tspaceId: SpaceId;\n\tfloorId: FloorId;\n\n\tconstructor(spaceId: SpaceId, floorId: FloorId) {\n\t\tsuper(`A layer with space ${spaceId} is defined, but this space does not exist on floor ${floorId}.`);\n\t\tthis.spaceId = spaceId;\n\t\tthis.floorId = floorId;\n\t}\n}\n\nexport class EnterpriseStyleGeometryAnchorsUnknownSpaceError extends Error {\n\tgeometryId: SpaceId;\n\tfloorId: FloorId;\n\n\tconstructor(geometryId: SpaceId, floorId: FloorId) {\n\t\tsuper(`An enterprise style references a space ${geometryId} which does not exist on floor ${floorId}.`);\n\t\tthis.geometryId = geometryId;\n\t\tthis.floorId = floorId;\n\t}\n}\n\nexport class EnterpriseTextureUnknownSpaceError extends Error {\n\tspaceId: SpaceId;\n\tfloorId: FloorId;\n\n\tconstructor(spaceId: SpaceId, floorId: FloorId) {\n\t\tsuper(`A texture for space ${spaceId} is defined, but this space does not exist on floor ${floorId}.`);\n\t\tthis.spaceId = spaceId;\n\t\tthis.floorId = floorId;\n\t}\n}\n\nexport class TextAreaUnknownObstructionError extends Error {\n\tobstructionId: ObstructionId;\n\tfloorId: FloorId;\n\n\tconstructor(obstructionId: ObstructionId, floorId: FloorId) {\n\t\tsuper(\n\t\t\t`A text area for obstruction ${obstructionId} is defined, but this obstruction does not exist on floor ${floorId}.`,\n\t\t);\n\t\tthis.obstructionId = obstructionId;\n\t\tthis.floorId = floorId;\n\t}\n}\n\nexport class EnterpriseUnknownLocationError extends Error {\n\tconstructor(locationId: string) {\n\t\tsuper(`Enterprise location '${locationId}' does not exist.`);\n\t\tthis.name = 'EnterpriseUnknownLocationError';\n\t}\n}\n\nexport class EnterpriseUnknownMapError extends Error {\n\tconstructor(mapId: string) {\n\t\tsuper(`Enterprise location references unknown map '${mapId}'.`);\n\t\tthis.name = 'EnterpriseUnknownMapError';\n\t}\n}\n\nexport class EnterpriseLocationUnknownSpaceError extends Error {\n\tconstructor(locationId: string, spaceId: string, mapId: string) {\n\t\tsuper(`Enterprise location '${locationId}' references unknown space '${spaceId}' on map '${mapId}'.`);\n\t\tthis.name = 'EnterpriseLocationUnknownSpaceError';\n\t}\n}\n\nexport class EnterpriseUnknownCategoryError extends Error {\n\tconstructor(categoryId: string) {\n\t\tsuper(`Enterprise category '${categoryId}' does not exist.`);\n\t\tthis.name = 'EnterpriseUnknownCategoryError';\n\t}\n}\n\nexport class EnterpriseInconsistentMapError extends Error {\n\tconstructor(locationId: string, spaceOrNodeId: string, mapId1: string, mapId2: string) {\n\t\tsuper(\n\t\t\t`Enterprise location '${locationId}' has an item '${spaceOrNodeId}' that references maps '${mapId1}', but it is actually on '${mapId2}'.`,\n\t\t);\n\t\tthis.name = 'EnterpriseInconsistentMapError';\n\t}\n}\n\nexport class EnterpriseCyclicalCategoryReferenceError extends Error {\n\tconstructor(categoryId: string) {\n\t\tsuper(`Cyclical reference detected in category hierarchy starting from category '${categoryId}'`);\n\t\tthis.name = 'EnterpriseCyclicalCategoryReferenceError';\n\t}\n}\n\nexport class EnterpriseInvalidTimeZoneError extends Error {\n\tconstructor(tzid: string) {\n\t\tsuper(`Invalid timezone '${tzid}'`);\n\t\tthis.name = 'EnterpriseInvalidTimeZoneError';\n\t}\n}\n\nexport class FacadeUnknownFloorStackError extends Error {\n\tconstructor(floorStackId: string) {\n\t\tsuper(`An facade references floor stack '${floorStackId}' which does not exist`);\n\t\tthis.name = 'FacadeUnknownFloorStackError';\n\t}\n}\n\nexport class FacadeUnknownFloorError extends Error {\n\tconstructor(facadeId: FacadeId, floorId: FloorId) {\n\t\tsuper(`Facade '${facadeId}' references floor '${floorId}' which does not exist`);\n\t\tthis.name = 'FacadeUnknownFloorError';\n\t}\n}\n\nexport class FacadeUnknownSpaceError extends Error {\n\tconstructor(facadeId: FacadeId, spaceId: SpaceId, floorId: FloorId) {\n\t\tsuper(`Facade '${facadeId}' references space '${spaceId}' (on floor '${floorId}') which does not exist`);\n\t\tthis.name = 'FacadeUnknownSpaceError';\n\t}\n}\n\nexport class DuplicateTilesetKeyError extends IntegrityError {\n\tconstructor(key: string) {\n\t\tsuper(`Duplicate tileset key found: ${key}`);\n\t\tthis.name = 'DuplicateTilesetKeyError';\n\t}\n}\n\nexport class AnnotationSymbolUnknownError extends IntegrityError {\n\tconstructor(annotationId: AnnotationId, symbolId: string) {\n\t\tsuper(`Annotation '${annotationId}' references a symbol '${symbolId}', but this symbol is not defined.`);\n\t\tthis.name = 'AnnotationSymbolUnknownError';\n\t}\n}\n\nexport class AnnotationSymbolDuplicateError extends IntegrityError {\n\tconstructor(symbolId: string) {\n\t\tsuper(`The annotation symbol '${symbolId}' is defined more than once.`);\n\t\tthis.name = 'AnnotationSymbolDuplicateError';\n\t}\n}\n","/**\n * The Mappedin Enterprise Extension\n *\n * Contains data the Enterprise Apps use, in the format generated by Mappedin CMS.\n */\n\nimport type { FloorId, NodeId, ObstructionId, SpaceId } from '../types/core.js';\nimport type { Feature, FeatureCollection, Point } from '../types/geojson.js';\n\n// Utility types\n\n/**\n * A time in the format of HH:MM:SS\n *\n * @pattern ^[0-2][0-9]:[0-6][0-9](:[0-6][0-9])?$\n */\nexport type Time = string;\n\nexport type Day = 'Sunday' | 'Monday' | 'Tuesday' | 'Wednesday' | 'Thursday' | 'Friday' | 'Saturday';\nexport const PUBLIC_HOLIDAYS = 'PublicHolidays';\nexport type DayOrPublicHoliday = Day | typeof PUBLIC_HOLIDAYS;\n/**\n * We (almost) follow this schema (http://schema.org/OpeningHoursSpecification)\n * The only difference is that we (like Google: https://developers.google.com/search/docs/data-types/local-businesses)\n * accept dayOfWeek as an array as well as an individual day.\n * */\nexport type OperationHours = {\n\t/**\n\t * The type of operation hours\n\t *\n\t * @default 'OpeningHoursSpecification'\n\t */\n\t'@type'?: 'OpeningHoursSpecification';\n\t/**\n\t * The time the operation hours start\n\t *\n\t */\n\topens?: Time;\n\t/**\n\t * The time the operation hours end\n\t */\n\tcloses?: Time;\n\n\t/**\n\t * The days of the week the operation hours apply to\n\t */\n\tdayOfWeek?: DayOrPublicHoliday | [DayOrPublicHoliday] | DayOrPublicHoliday[];\n\n\t/**\n\t * The date the operation hours start, in ISO 8601 format\n\t * @format date-time\n\t */\n\tvalidFrom?: string;\n\n\t/**\n\t * The date the operation hours end, in ISO 8601 format\n\t * @format date-time\n\t */\n\tvalidThrough?: string;\n};\n\n/**\n * The state of a location. Start and end dates are optional.\n */\nexport type LocationState = {\n\t/**\n\t * The type of the location state. Technically not limited, but should be one of the following:\n\t * - closed-temporarily\n\t * - new\n\t * - pop-up\n\t * - coming-soon\n\t * - relocated\n\t */\n\ttype: 'closed-temporarily' | 'new' | 'pop-up' | 'coming-soon' | 'relocated' | string;\n\t/**\n\t * The start date of the state\n\t * @format date\n\t */\n\tstart?: string;\n\t/**\n\t * The start date of the state\n\t * @format date\n\t */\n\tend?: string;\n};\n\nexport type SiblingGroup = {\n\tlabel: string;\n\tsiblings: EnterpriseLocationId[];\n\ttype?: string;\n\tsubtype?: string;\n};\n\nexport type Language = {\n\tname: string;\n\tcode: string;\n};\n\n/**\n * A collection of extra data, with no validation.\n * All classic x_ properties go here, with the x_ prefix stripped.\n */\nexport type Extras = { extra?: Record<string, unknown> };\n\n// IDs\n/**\n * An ID for an enterprise location\n *\n * **Important**: While the suffix can be any length, it is strongly recommended to use\n * suffixes of at least 8 characters to ensure uniqueness and avoid collisions.\n *\n * @pattern ^el_[A-Za-z0-9_-]+$\n */\nexport type EnterpriseLocationId = string;\n\n/**\n * An ID for an enterprise category\n *\n * **Important**: While the suffix can be any length, it is strongly recommended to use\n * suffixes of at least 8 characters to ensure uniqueness and avoid collisions.\n *\n * @pattern ^ec_[A-Za-z0-9_-]+$\n */\nexport type EnterpriseCategoryId = string;\n\n/**\n * An ID for an enterprise location instance\n *\n * **Important**: While the suffix can be any length, it is strongly recommended to use\n * suffixes of at least 8 characters to ensure uniqueness and avoid collisions.\n *\n * @pattern ^eli_[A-Za-z0-9_-]+$\n */\n\nexport const ENTERPRISE_VENUE_TYPES = [\n\t'agriculture',\n\t'airport',\n\t'casino',\n\t'city-district',\n\t'convention-center',\n\t'entertainment',\n\t'event-centre',\n\t'first-responder-building',\n\t'government-building',\n\t'grocery-store',\n\t'healthcare',\n\t'higher-education',\n\t'hotel',\n\t'library',\n\t'manufacturing',\n\t'medical-centre',\n\t'mixed-use',\n\t'multifamily',\n\t'museum',\n\t'office-building',\n\t'oil-and-energy',\n\t'other',\n\t'parking-facility',\n\t'religious-institution',\n\t'resort',\n\t'retail-store',\n\t'schools-k-12',\n\t'shopping-mall',\n\t'stadium-or-arena',\n\t'storage-facility',\n\t'theme-park',\n\t'transit',\n\t'transportation-hub',\n\t'warehousing',\n\t'unknown',\n] as const;\n\nexport type EnterpriseVenueType = (typeof ENTERPRISE_VENUE_TYPES)[number];\n\nexport type EnterpriseLocationInstanceId = string;\n\n// Enterprise types\n\nexport type EnterpriseVenue = {\n\tslug: string;\n\tname: string;\n\texternalId: string;\n\tdefaultLanguage: Language;\n\tlanguages: Language[];\n\n\t/**\n\t * @deprecated Use `defaultFloor` instead\n\t */\n\tdefaultMap?: FloorId;\n\n\t/**\n\t * The venue's default floor\n\t */\n\tdefaultFloor?: FloorId;\n\n\t/**\n\t * The venue's timezone, from the IANA Time Zone Database.\n\t * Should be in the format of `America/New_York`\n\t *\n\t * @pattern ^[A-Za-z0-9\\/_-]+$\n\t */\n\ttzid?: string;\n\n\t/**\n\t * The ISO 3166-1 alpha-2 country code of the venue, if known\n\t *\n\t * Eg. `US` or `GB`\n\t */\n\tcountrycode?: string;\n\n\t/**\n\t * The venue's logo\n\t *\n\t * @format uri\n\t */\n\tlogo?: string;\n\n\t/**\n\t * The venue's icon\n\t *\n\t * @format uri\n\t */\n\ticon?: string;\n\n\t/**\n\t * The venue's cover image\n\t *\n\t * @format uri\n\t */\n\tcoverImage?: string;\n\n\t/**\n\t * The base URL for Mappedin Web for this venue\n\t *\n\t * Better name?\n\t */\n\tmappedinWebUrl?: string;\n\n\ttopLocations?: EnterpriseLocationId[];\n\n\t/**\n\t * When this venue is open.\n\t *  @type array */\n\toperationHours?: Array<OperationHours>;\n\n\t/**\n\t * The type of the venue, if known.\n\t */\n\ttype?: EnterpriseVenueType;\n\n\t/**\n\t * An image of the venue property\n\t *\n\t * @format uri\n\t */\n\tpropertyImage?: string;\n} & Extras;\n\n/**\n * @deprecated Use `spaces` instead\n */\ntype LocationNodes = { map: FloorId; id: NodeId }[];\n\n/**\n * The places that this location is anchored to in the physical world. These are either Polygon\n * or Point spaces. A location can be attached to many spaces, and a space can be attached to\n * many locations.\n *\n * If there are different properties for the location on those spaces, they will show up in the location's {@link EnterpriseLocation.instances instances} property.\n */\ntype LocationSpaces = { floor: FloorId; id: SpaceId }[];\n\n/**\n * @deprecated Use `spaces` instead\n */\ntype LocationPolygons = { map: FloorId; id: SpaceId }[];\n\nexport type EnterpriseLocation = {\n\tid: EnterpriseLocationId;\n\tname: string;\n\texternalId: string;\n\ttype: string;\n\tsortOrder: number;\n\n\t/**\n\t *  @deprecated Use `spaces` instead. All of a location's polygons will be in the spaces array.\n\t *  @type array */\n\tpolygons: LocationPolygons;\n\n\t/**\n\t *  @deprecated Use `spaces` instead. A location's nodes that are not attached to a polygon will be in the spaces array as a point space. Nodes that are attached to one of it's polygons will be destinationNodes on that polygon's space\n\t *  @type array */\n\tnodes: LocationNodes;\n\n\t/**\n\t * The places that this location is anchored to in the physical world. These are either Polygon\n\t * or Point spaces. A location can be attached to many spaces, and a space can be attached to\n\t * many locations.\n\t *\n\t * If there are different properties for the location on those spaces, they will show up in the location's {@link EnterpriseLocation.instances instances} property\n\t */\n\tspaces: LocationSpaces;\n\n\tdescription?: string;\n\n\ttags?: Array<string>;\n\tshortName?: string;\n\n\t/**\n\t * The location's logo\n\t *\n\t * @format uri\n\t */\n\tlogo?: string;\n\n\t/**\n\t * The picture of the location\n\t *\n\t * @format uri\n\t */\n\tpicture?: string;\n\n\tphone?: {\n\t\tnumber: string;\n\t\textension?: string;\n\t};\n\n\t/** @type array */\n\toperationHours?: Array<OperationHours>;\n\n\t/**\n\t * The location's social media links\n\t */\n\tsocial?: {\n\t\tfacebook?: string;\n\t\tinstagram?: string;\n\t\ttwitter?: string;\n\t\twebsite?: string;\n\t};\n\n\t// These are being currently requested by our apps, but should not go into MVF.\n\t// color?: unknown;\n\t// filterFlags?: unknown;\n\n\t/**\n\t * The location's state. No more than one state should be active at a time,\n\t * and all but at most one should have dates set\n\t */\n\tstates?: Array<LocationState>;\n\n\t/**\n\t * Locations that are related to this location in some manner (described by the label)\n\t */\n\tsiblingGroups?: Array<SiblingGroup>;\n\n\t/**\n\t * The location's image gallery\n\t */\n\tgallery?: Array<{\n\t\tcaption?: string | null;\n\t\timage: string;\n\t\t/**\n\t\t * The URL to link from the image\n\t\t * @format uri\n\t\t */\n\t\tembeddedUrl?: string | null;\n\t}>;\n\n\t/**\n\t * Whether to show the flat label when an image is present\n\t */\n\tshowFloatingLabelWhenImagePresent?: boolean;\n\n\t/**\n\t * The location's amenity type. Only set if the location is an amenity\n\t */\n\tamenity?: string;\n\n\t/**\n\t * Whether to show the logo of the location\n\t */\n\tshowLogo?: boolean;\n\n\t/**\n\t * Web links for the location\n\t *\n\t * @type array\n\t */\n\tlinks?: Array<{\n\t\tlabel: string;\n\t\t/**\n\t\t * The URL of the link\n\t\t * @format uri\n\t\t */\n\t\turl: string;\n\t}>;\n\n\t/**\n\t * Whether to show the location in applications\n\t */\n\thidden?: boolean;\n\n\t/**\n\t * The main category of the location. It must be one of the categories in the Location's categories array.\n\t */\n\tprimaryCategory?: EnterpriseCategoryId;\n\n\t/**\n\t * The navigation flags that must be set for this location to be reachable when wayfinding.\n\t * For example, if a location is only accessible through a certain entrance, that entrance should get a navigation flag that\n\t * matches the filter flags.\n\t *\n\t * NOTE: This is an array of strings, which are the keys in the Navigation Flags Declarations.\n\t */\n\tfilterFlags?: string[];\n\n\t/**\n\t * The header image of the location\n\t *\n\t * @format uri\n\t */\n\theaderImage?: string;\n} & Extras;\n\nexport type EnterpriseCategory = {\n\tid: EnterpriseCategoryId;\n\texternalId: string;\n\tname: string;\n\tcolor?: string;\n\tsortOrder: number;\n\tchildren: EnterpriseCategoryId[];\n\tlocations: EnterpriseLocationId[];\n\n\t/**\n\t * The category's icon\n\t *\n\t * @format uri\n\t */\n\ticon?: string;\n\ticonFromDefaultList?: string | null;\n\n\t/**\n\t * The category's picture\n\t *\n\t * @format uri\n\t */\n\tpicture?: string;\n} & Extras;\n\n// Skipped:\n// Vortexes: Only needed for filterFlags. That should be core when we know how to use it\n\n/**\n * A locationInstance is a particular instance of an Enterprise Location that has some properties\n * different from the parent. Eg, it may have different hours, or a slightly different name.\n *\n * A LocationInstance:\n * - MUST have a parent, referring to an Enterprise Location.\n * - MUST have a unique ID, for localization to work.\n * - SHOULD have AT LEAST ONE polygon or node to anchor it in space.\n * - SHOULD have AT LEAST ONE other Enterprise Location property set.\n *\n * It is otherwise a Partial<EnterpriseLocation>\n *\n * Usage examples:\n * - A locationInstance for a location with a different externalId so a customer can identify them individually.\n * - A locationInstance with different operationHours, that might indicate different hours for that particular entrance.\n */\nexport type EnterpriseLocationInstance = Partial<Omit<EnterpriseLocation, 'id' | 'parent'>> & {\n\tid: EnterpriseLocationInstanceId;\n\tparent: EnterpriseLocationId;\n};\n\n/**\n * The ordered list of category ids that this location belongs to\n * The order here determines the priority of the categories, with the first category being the highest priority\n * for determining application logic like icon and color preference.\n * @type array\n */\nexport type EnterpriseCategoryPriority = Record<EnterpriseLocationId, EnterpriseCategoryId[]>;\n\n/**\n * **Important**: While the suffix can be any length, it is strongly recommended to use\n * suffixes of at least 8 characters to ensure uniqueness and avoid collisions.\n *\n * @pattern ^ely_[A-Za-z0-9_-]+$\n */\nexport type EnterpriseLayerId = string;\n\nexport type EnterpriseLayerSpace = { floorId: FloorId; spaceId: SpaceId };\n\nexport type EnterpriseLayer = {\n\tid: EnterpriseLayerId;\n\tname: string;\n\t/**\n\t * @minItems 1\n\t */\n\tspaces: EnterpriseLayerSpace[];\n};\n\nexport type EnterpriseStyles = Record<\n\tstring,\n\t{ edgeOffset?: number; geometryAnchors: { geometryId: SpaceId; floorId: FloorId }[] }\n>;\n\nexport type EnterpriseTextureUV = {\n\tu: number;\n\tv: number;\n};\n\nexport type EnterpriseTextureFace = 'top' | 'side';\nexport type EnterpriseTextureGeometryAnchor = {\n\tgeometryId: SpaceId;\n\tfloorId: FloorId;\n};\nexport type EnterpriseTextureSurface = 'inside' | 'outside' | 'both';\n\nexport type EnterpriseTexture = {\n\t/**\n\t * Controls how many times the texture repeats across the surface.\n\t * The u value controls horizontal repetition and v controls vertical repetition.\n\t */\n\trepeat: EnterpriseTextureUV;\n\t/**\n\t * Controls the starting position of the texture on the surface.\n\t * The u value shifts the texture horizontally and v shifts vertically.\n\t */\n\toffset: EnterpriseTextureUV;\n\t/**\n\t * Rotation of the texture in degrees clockwise.\n\t *\n\t * For top textures this is relative to north. North is 0, east is 90.\n\t *\n\t * For side textures this is relative to the upward direction, with 0 degrees being upright.\n\t *\n\t * @minimum 0\n\t * @maximum 360\n\t */\n\trotation: number;\n\t/**\n\t * Path to the texture image. Must be either a PNG or JPG format.\n\t */\n\tpath: string;\n\t/**\n\t * Face of the polygon that the texture will be applied to.\n\t *\n\t * 'top' means that the texture will be applied to the upward-pointing face of the polygon.\n\t *\n\t * 'side' means that the texture will be applied to every side face of the polygon.\n\t */\n\tface: EnterpriseTextureFace;\n\t/**\n\t * Surface of the polygon that the texture will be applied to.\n\t *\n\t * 'inside' means that the texture will only be applied to the interior surface of the polygon.\n\t *\n\t * 'outside' means that the texture will only be applied to the exterior surface of the polygon.\n\t *\n\t * 'both' means that the texture will be applied to both interior and exterior surfaces of the polygon.\n\t *\n\t */\n\tsurface: EnterpriseTextureSurface;\n\t/**\n\t * Coordinates of the texture's bounding box in format: [minLon, minLat, maxLon, maxLat].\n\t */\n\tbounds: [number, number, number, number];\n\t/**\n\t * Anchors for the texture on the geometry of the polygon.\n\t *\n\t * @minItems 1\n\t */\n\tgeometryAnchors: EnterpriseTextureGeometryAnchor[];\n};\n\n/**\n * Text and some transformations that may be applied to superimpose the text onto a map, which can\n * either be anchored to a specific space or floating.\n */\nexport type FloorTextCommonProperties = {\n\t/**\n\t * The text to display. Newline characters are supported.\n\t */\n\ttext: string;\n\n\t/**\n\t * Whether the text is visible.\n\t *\n\t * @default true\n\t */\n\tvisible: boolean;\n\n\t/**\n\t * The em-height (multiplier of the font's height) at which to render the font, in meters.\n\t * The font height is the distance between the ascender (highest point, height of an A) and descender (lowest point, bottom of a g) of the font.\n\t * For example, if the font-size is 12, the space for a single character will be 12 meters high.\n\t *\n\t * @default 12\n\t */\n\tfontSize: number;\n\n\t/**\n\t * The font family of the text.\n\t *\n\t * @default 'Droid Sans'\n\t */\n\tfontFamily: string;\n\n\t/**\n\t * The color of the text in CSS format (e.g. `#000000`, `rgb(0, 0, 0)`, `black`).\n\t *\n\t * @default 'black'\n\t */\n\tcolor: string;\n\t/**\n\t * Rotation in degrees, about the center of the text. North is 0, east is 90.\n\t *\n\t * @minimum 0\n\t * @maximum 360\n\t */\n\trotation: number;\n\t/**\n\t * Horizontal alignment of multi-line text.\n\t *\n\t * @default 'center'\n\t */\n\talign: 'left' | 'center' | 'right';\n};\n\nexport type AnchoredFloorTextProperties = FloorTextCommonProperties & {\n\t/**\n\t * The geometry to which this text belongs. It will be displayed on top of it.\n\t */\n\tgeometryId: SpaceId | ObstructionId;\n};\n\nexport type FloatingFloorTextProperties = FloorTextCommonProperties & {\n\t/**\n\t * The vertical offset of the text, in meters.\n\t */\n\tverticalOffset: number;\n};\n\nexport type FloorTextProperties = AnchoredFloorTextProperties | FloatingFloorTextProperties;\n\nexport type FloorTextFeature = Feature<Point, FloorTextProperties>;\nexport type AnchoredFloorTextFeature = Feature<Point, AnchoredFloorTextProperties>;\nexport type FloatingFloorTextFeature = Feature<Point, FloatingFloorTextProperties>;\n\n/**\n * A collection of text to be displayed on a map. They are either attached to a space or are floating.\n */\nexport type FloorTextFeatureCollection = FeatureCollection<Point, FloorTextProperties>;\n\n/**\n * The text to display on a map, split into  feature collection per floor.\n */\nexport type EnterpriseFloorText = {\n\t[floorId: FloorId]: FloorTextFeatureCollection | undefined;\n};\n\nexport type EnterpriseCollection = {\n\tlocations: EnterpriseLocation[];\n\tcategories: EnterpriseCategory[];\n\tvenue: EnterpriseVenue;\n\tlocationInstances: EnterpriseLocationInstance[];\n\tlayers: EnterpriseLayer[];\n\tcategoryPriorities?: EnterpriseCategoryPriority;\n\ttextures?: EnterpriseTexture[];\n\tenterpriseStyles?: EnterpriseStyles;\n\tfloorText?: EnterpriseFloorText;\n};\n","import type { Details } from '../types/core.js';\n/**\n * A NavigationFlagDeclaration describes the relationship between a \"key\" that a developer might use to wayfind using that flag, and the index and bit position in an object's `flags` array.\n * Ie, if there is a flag with a key of `vip`, index 1 and bit position 0, then an item with flags as `[0, 0]` does not have the flag, `[0, 1]` does, and `[1, 2]` or `[1, 0]` do not.\n *\n * NavigationFlagDeclarations also may contain details about the flag, which can be displayed to a user if present.\n */\nexport type NavigationFlagDeclaration = {\n\t/**\n\t * The index of the flag in a flags array. ie, 0 means the first bitfield, 1 means the second bitfield, etc.\n\t * @minimum 0\n\t */\n\tindex: number;\n\t/**\n\t * The bit position of the flag in a flag's bitfield. ie, 0 means the first bit, 1 means the second bit, etc.\n\t * A flag bitfield with that bit set to 1 means the flag is present. Other than for Well Known Flags, this is not expected to be durable across different versions of the same MVF.\n\t * @minimum 0\n\t * @maximum 31\n\t */\n\tbit: number;\n\tdetails?: Details;\n};\n\n/**\n * A map of all NavigationFlagDeclarations present in the MVF. The key is the durable value a developer should use to interact with the flag when wayfinding, and the\n * value is the definition of the flag that describes how to determine whether it's set in an object's flags array.\n */\nexport type NavigationFlagDeclarations = {\n\t[key: string]: NavigationFlagDeclaration;\n};\n\n/**\n * A Flags array is an array of 32 bit integers, each representing a bit string of included flags. 1 means the flag is present, 0 means it's not.\n */\nexport type Flags = number[];\n\n/**\n * All well known navigation flags. These may or may not be present in an MVF, but if they are, they always mean the same thing.\n */\nexport const WELL_KNOWN_FLAGS = {\n\t/**\n\t * A flag indicating that something is accessible, specifically that it can be crossed by users with reduced mobility, including those using wheelchairs.\n\t */\n\taccessible: 'accessible',\n\t/**\n\t * A flag indicating that something is outside of a building, in the open air. The sky is NOT NECESSARILY visible, an 'outdoors' path may be under a bridge or awning.\n\t */\n\toutdoors: 'outdoors',\n\t/**\n\t * A flag indicating that something is navigable by the public users of the building or space. By default, consumers of MVF should not route through non-public things unless specifically requested.\n\t */\n\tpublic: 'public',\n} as const;\n","/**\n * Deeply merges a partial object into a full object, using specified identifier keys for array merging.\n *\n * This function performs a deep merge with special handling for arrays containing objects with identifier keys.\n * It's particularly useful for merging complex nested structures where some properties should be merged\n * rather than replaced.\n *\n * @param full - The complete object to merge into.\n * @param partial - The partial object containing updates. All properties are optional except those specified by idKeys.\n * @param idKeys - The keys used as identifiers for merging array items. Can be a single key or an array of keys.\n *                 When multiple keys are provided, an object is expected to have only one of these keys.\n *\n * @returns A new object that is the result of merging `partial` into `full`.\n *\n * @throws {Error} If trying to merge an identified array into a non-array property.\n *\n * Merging behavior:\n * 1. Simple properties: Overwrites values in `full` with non-undefined values from `partial`.\n * 2. Objects: Recursively merges properties.\n * 3. Arrays:\n *    a. If array items have the specified `idKey`, it merges items with matching IDs.\n *    b. If array items don't have the `idKey`, it replaces the entire array.\n * 4. New properties: Adds properties from `partial` that don't exist in `full`.\n *\n * @example\n * // Merging simple objects\n * const full = { a: 1, b: 2 };\n * const partial = { b: -1 };\n * deepMergeOn(full, partial, 'id'); // Returns { a: 1, b: -1 }\n *\n * @example\n * // Merging nested objects with arrays\n * const full = {\n *   a: 1,\n *   b: 2,\n *   children: [\n *     { id: '1', x: 10 },\n *     { id: '2', y: 20 }\n *   ]\n * };\n * const partial = {\n *   b: 3,\n *   children: [\n *     { id: '2', y: 30 }\n *   ]\n * };\n * deepMergeOn(full, partial, 'id');\n * // Returns:\n * // {\n * //   a: 1,\n * //   b: 3,\n * //   children: [\n * //     { id: '1', x: 10 },\n * //     { id: '2', y: 30 }\n * //   ]\n * // }\n *\n * @example\n * // Merging arrays without identifier keys\n * const full = { data: [1, 2, 3] };\n * const partial = { data: [4, 5] };\n * deepMergeOn(full, partial, 'id'); // Returns { data: [4, 5] }\n *\n * @example\n * // Adding new properties\n * const full = { a: 1 };\n * const partial = { b: 2 };\n * deepMergeOn(full, partial, 'id'); // Returns { a: 1, b: 2 }\n *\n * @example\n * // Deeply nested merging\n * const full = { a: { b: { c: 1 } } };\n * const partial = { a: { b: { d: 2 } } };\n * deepMergeOn(full, partial, 'id'); // Returns { a: { b: { c: 1, d: 2 } } }\n *\n * @example\n * // Error case: merging identified array into non-array\n * const full = { a: 1 };\n * const partial = { a: [{ id: '1', value: 2 }] };\n * // Throws Error: \"Expected array at a, got number\"\n * deepMergeOn(full, partial, 'id');\n */\nexport function deepMergeOn(full, partial, idKeys = []) {\n    const result = { ...full };\n    for (const [key, partialValue] of Object.entries(partial)) {\n        if (partialValue !== undefined) {\n            if (key in result) {\n                const typedKey = key;\n                if (Array.isArray(partialValue) && partialValue.length > 0) {\n                    const keyPath = findIdentifierKey(partialValue[0], idKeys);\n                    if (keyPath) {\n                        const fullObjectArray = result[typedKey];\n                        // If this happens, we are trying to merge two different types of objects, which is not allowed for identified arrays.\n                        if (!Array.isArray(fullObjectArray)) {\n                            throw new Error(`Expected array at ${key}, got ${typeof fullObjectArray}`);\n                        }\n                        const partialsById = new Map(partialValue.map((v) => [getValueByKeyPath(v, keyPath), v]));\n                        const typedFullObjectArray = fullObjectArray;\n                        const merged = typedFullObjectArray.map((fullObject) => {\n                            const partial = partialsById.get(getValueByKeyPath(fullObject, keyPath));\n                            // This means the partial has an object with the same ID as the full object, so we merge them.\n                            if (partial) {\n                                return deepMergeOn(fullObject, partial, idKeys);\n                            }\n                            // Otherwise, we just return the original object.\n                            return fullObject;\n                        });\n                        result[typedKey] = merged;\n                    }\n                    else {\n                        // This array does not have ID objects, so we just replace it.\n                        result[typedKey] = partialValue;\n                    }\n                }\n                else {\n                    const fullValue = result[typedKey];\n                    if (typeof fullValue === 'object' &&\n                        fullValue !== null &&\n                        typeof partialValue === 'object' &&\n                        partialValue !== null) {\n                        // If the full value is an empty object, we replace it with the partial value to \"unset\" all values\n                        if (Object.keys(partialValue).length === 0) {\n                            result[typedKey] = partialValue;\n                        }\n                        else {\n                            // This property exists on both objects and is an object with values, so we recursively merge all properties.\n                            result[typedKey] = deepMergeOn(fullValue, partialValue, idKeys);\n                        }\n                    }\n                    else {\n                        // This is not an object, so we just set it.\n                        result[key] = partialValue;\n                    }\n                }\n            }\n            else {\n                // This is a new property, so we just set it. Presumably it was optional in the full object.\n                result[key] = partialValue;\n            }\n        }\n    }\n    return result;\n}\n/**\n * Finds the path to the first matching identifier key in an object.\n * Uses any of the provided keys as valid identifiers.\n *\n * @param obj - The object to search.\n * @param idKeys - The keys that can be used as identifiers for merging array items.\n *\n * @returns The key path to the first found identifier key, or null if no identifier key is found.\n */\nexport function findIdentifierKey(obj, idKeys) {\n    function search(current) {\n        if (typeof current !== 'object' || current === null) {\n            return null;\n        }\n        // Check for any of the identifier keys\n        for (const idKey of idKeys) {\n            if (idKey in current && typeof current[idKey] !== 'undefined') {\n                return [idKey];\n            }\n        }\n        if (Array.isArray(current)) {\n            return null;\n        }\n        else {\n            for (const [key, value] of Object.entries(current)) {\n                const result = search(value);\n                if (result)\n                    return [key, ...result];\n            }\n        }\n        return null;\n    }\n    return search(obj);\n}\n/**\n * Gets a value from an object using a key path. Key usually comes\n * Used as a helper function for deepMergeOn.\n *\n * @param obj - The object to search.\n * @param keyPath - The key path to the value.\n *\n * @returns The value at the key path, or undefined if the key path does not exist.\n *\n * @example\n    const base = { id: '1', items: [{ properties: { id: 'a', value: 10 }, coords: [[1, 2, 3]] }] };\n\n    const valueDifferent = { id: '1', items: [{ properties: { id: 'a', value: 11 }, coords: [[1, 2, 3]] }] };\n    expect(deepDiffOn(base, valueDifferent, 'id')).toEqual({\n        id: '1',\n        items: [{ properties: { id: 'a', value: 11 } }],\n    });\n\n    const coordsDifferent = { id: '1', items: [{ properties: { id: 'a', value: 10 }, coords: [[1, 2, 4]] }] };\n    expect(deepDiffOn(base, coordsDifferent, 'id')).toEqual({\n        id: '1',\n        items: [{ properties: { id: 'a' }, coords: [[1, 2, 4]] }],\n    });\n    const bothDifferent = { id: '1', items: [{ properties: { id: 'a', value: 11 }, coords: [[1, 2, 4]] }] };\n    expect(deepDiffOn(base, bothDifferent, 'id')).toEqual({\n        id: '1',\n        items: [{ properties: { id: 'a', value: 11 }, coords: [[1, 2, 4]] }],\n    });\n\n    const same = { id: '1', items: [{ properties: { id: 'a', value: 10 }, coords: [[1, 2, 3]] }] };\n    expect(deepDiffOn(base, same, 'id')).toEqual({ id: '1' });\n */\nexport function getValueByKeyPath(obj, keyPath) {\n    return keyPath.reduce((current, key) => {\n        if (current && typeof current === 'object') {\n            return current[key];\n        }\n        return undefined;\n    }, obj);\n}\n/**\n * Checks if an object has only the identifier key.\n * Used as a helper function for deepDiffOn.\n */\nexport function hasOnlyIdKeys(value, idKeys) {\n    if (Array.isArray(value)) {\n        return value.every((item) => hasOnlyIdKeys(item, idKeys));\n    }\n    if (isObject(value)) {\n        const keys = Object.keys(value);\n        if (keys.length === 0)\n            return true;\n        if (keys.length === 1 && idKeys.includes(keys[0]))\n            return true;\n        return keys.every((key) => idKeys.includes(key) || hasOnlyIdKeys(value[key], idKeys));\n    }\n    return false;\n}\nfunction isObject(value) {\n    return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n/**\n * Deeply diffs two objects, returning a new object with the properties on the second object that do not match the first.\n *\n * For objects, if the objects are different, the deep diff of the second object is returned. If the objects are the same, the entry is omitted.\n *\n * For arrays, if the second array is empty, it is returned. Otherwise, if they contain objects with one of the idKeys (see findIdentifierKey),\n * the objects in the second array are recursively diffed with corresponding object with that identifier key in the first array. If the objects are different, the deep diff\n * of the second object is returned. If the objects are the same, the entry is omitted from the array.\n *\n * If a mix of the idkeys is present in an array, which is matched, if any, is undefined.\n *\n * If the array does not contain identifiable objects and is different, the second array is returned as is. Otherwise, the array is omitted.\n *\n * For simple properties, if the key is the id key, it is always kept. If not, and the property is different, the second property is returned.\n * If the properties are the same, the entry is omitted.\n *\n * @param first - The first object.\n * @param second - The second object.\n * @param idKey - The key used as an identifier for merging array items.\n *\n * @returns A PartialExcept<T, K> object that is the properties on the second object that do not match the first.\n */\nexport function deepDiffOn(first, second, idKeys) {\n    const result = {};\n    for (const key in second) {\n        const secondValue = second[key];\n        const firstValue = first[key];\n        if (idKeys.includes(key)) {\n            // If the key is one of the id key, we always keep it.\n            result[key] = secondValue;\n        }\n        else if (secondValue === firstValue) {\n            // If the two values are the same, we omit the key.\n            continue;\n        }\n        else if (Array.isArray(secondValue) && Array.isArray(firstValue)) {\n            if (Array.isArray(secondValue) && Array.isArray(firstValue)) {\n                // If both arrays are empty, we omit the key.\n                if (secondValue.length === 0 && firstValue.length === 0) {\n                    continue;\n                }\n                // If the second array is the only empty one, return it to clear the array in the diff\n                if (secondValue.length === 0) {\n                    result[key] = secondValue;\n                    continue;\n                }\n                // Otherwise, compare the arrays.\n                const keyPath = findIdentifierKey(secondValue[0], idKeys);\n                // If the array contains identifiable objects, we compare deep diff them based on their identifier keys.\n                if (keyPath) {\n                    // Making the map from the second value and going through the first will\n                    // mean that IDs only in the second array are omitted. This is intentional, since\n                    // for our usecases that should be impossible, and deepMergeOn will throw an error if\n                    // that happens. If that turns out to not be true, this implementation should be changed.\n                    const secondValueMap = new Map(secondValue.map((v) => [getValueByKeyPath(v, keyPath), v]));\n                    const diffs = firstValue\n                        .map((v) => {\n                        const second = secondValueMap.get(getValueByKeyPath(v, keyPath));\n                        if (second) {\n                            const diff = deepDiffOn(v, second, idKeys);\n                            // If the diff is only ids, we omit the key.\n                            if (Object.keys(diff).length === 1 && hasOnlyIdKeys(diff, idKeys)) {\n                                return undefined;\n                            }\n                            return diff;\n                        }\n                        return undefined;\n                    })\n                        .filter((v) => v !== undefined);\n                    if (diffs.length > 0) {\n                        result[key] = diffs;\n                    }\n                }\n                else if (JSON.stringify(firstValue) !== JSON.stringify(secondValue)) {\n                    result[key] = secondValue;\n                }\n            }\n            // else {\n            // \tIf the two values point the same object, it's definitely not different.\n            // }\n        }\n        else if (typeof secondValue === 'object' &&\n            secondValue !== null &&\n            typeof firstValue === 'object' &&\n            firstValue !== null) {\n            // If the second value is explicitly set to empty, we return the empty object to \"unset\" all values\n            // Unless the first value is also empty, in which case we omit the key.\n            if (Object.keys(secondValue).length === 0) {\n                if (Object.keys(firstValue).length > 0) {\n                    result[key] = {};\n                }\n                continue;\n            }\n            const nestedDiff = deepDiffOn(firstValue, secondValue, idKeys);\n            if (Object.keys(nestedDiff).length > 0) {\n                result[key] = nestedDiff;\n            }\n        }\n        else {\n            if (firstValue !== secondValue) {\n                result[key] = secondValue;\n            }\n        }\n    }\n    // WE know that we kept IDs.\n    return result;\n}\n//# sourceMappingURL=deep-merge.js.map","import { deepDiffOn, deepMergeOn } from '@mappedin/mvf-core/locale';\nimport type {\n\tManifestCollection,\n\tManifestFile,\n\tManifestProperties,\n\tParsedMVF,\n\tParsedMVFLocalePack,\n} from './types/bundle.js';\n\nimport type { PartialExcept } from '@mappedin/mvf-core/locale';\n\nexport { deepDiffOn, deepMergeOn };\n\n/**\n * Cleans up the folder_struct to only include files and folders that are present as keys in the partial parsed MVF.\n * This is used in cleanUpManifest to remove unnecessary folder_struct entries.\n *\n * We do this instead of re-creating the folder_struct so the locale pack functions do not need to understand\n * what file extensions are used.\n *\n * @param folderStruct - The original folder structure from the manifest of the orginal MVF.\n * @param localePack - A partial ParsedMVF object containing the keys still in the data, usually from a locale pack.\n * @returns A cleaned up folder structure array.\n */\nfunction cleanUpFolderStruct(\n\tfolderStruct: ManifestProperties['folder_struct'],\n\tlocalePack: PartialExcept<ParsedMVF, 'id'>,\n): ManifestProperties['folder_struct'] {\n\tconst result: ManifestProperties['folder_struct'] = [];\n\tfor (const item of folderStruct) {\n\t\t// Check if the file or folder exists in the parsed MVF, with or without the file extension\n\t\tif (!Object.hasOwn(localePack, item.name) && !Object.hasOwn(localePack, item.name.split('.')[0])) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (item.type === 'file') {\n\t\t\tresult.push(item);\n\t\t} else if (item.type === 'folder' && item.name in localePack) {\n\t\t\tconst folder: ManifestFile[] = [];\n\t\t\tconst folderProperty = localePack[item.name as keyof ParsedMVF] as Record<string, unknown>;\n\t\t\tfor (const child of item.children) {\n\t\t\t\tif (\n\t\t\t\t\tObject.hasOwn(folderProperty, child.name) ||\n\t\t\t\t\tObject.hasOwn(folderProperty, child.name.split('.')[0]) // In case the file extension is not present\n\t\t\t\t) {\n\t\t\t\t\tfolder.push(child);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (folder.length > 0) {\n\t\t\t\tresult.push({\n\t\t\t\t\t...item,\n\t\t\t\t\tchildren: folder,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Cleans up the manifest and removes unnecessary folder_struct entries. Used in createLocalePack.\n * Speficially, it removes folder_struct entries that are not present in the locale pack.\n *\n * @param manifest - The original manifest collection.\n * @param localePack - The partial MVF locale pack.\n * @returns A ParsedMVFLocalePack with the correct manifest\n */\nexport function cleanUpManifest(\n\tmanifest: ManifestCollection,\n\tlocalePack: PartialExcept<ParsedMVF, 'id'>,\n): ParsedMVFLocalePack {\n\tconst cleanedManifest: ManifestCollection = {\n\t\t...manifest,\n\t\tfeatures: manifest.features.map((feature) => {\n\t\t\tif (feature.properties && 'folder_struct' in feature.properties) {\n\t\t\t\treturn {\n\t\t\t\t\t...feature,\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\t...feature.properties,\n\t\t\t\t\t\tfolder_struct: cleanUpFolderStruct(feature.properties.folder_struct, localePack),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn feature;\n\t\t}),\n\t};\n\n\treturn {\n\t\t...localePack,\n\t\t'manifest.geojson': cleanedManifest,\n\t};\n}\n\n/**\n * Merges a partial locale pack into a full ParsedMVF object.\n *\n * This function uses a deep merge strategy to combine the full ParsedMVF with a partial\n * locale pack, preserving the original structure while updating or adding new content\n * from the locale pack.\n *\n * It has special handling for arrays containing \"identifiable objects\" (ie, an object with an\n * 'id' or 'key' property somewhere in it's structure, like a Feature with 'properties.id' or 'properties.key'). In those cases,\n * the merge will only update the objects that have a corresponding 'id' or 'key' in the locale pack, by merging\n * in only the properties that are present in the locale pack.\n *\n * This allows a locale pack to contain updates to only some objects in an array, without having to\n * update every object in the array.\n *\n * Also, this function does NOT have detailed understanding of MVF's structure, outside of the manifest,\n * which should make it robust to changes / additions to MVF in the future.\n *\n * Key features:\n * 1. Clones the original parsed MVF\n * 2. Deep merges objects and arrays, with special handling for arrays containing objects with 'id' or 'key' properties somewhere.\n * 3. Adds new properties from the locale pack that don't exist in the full ParsedMVF.\n * 4. Keeps the original folder_struct from the full ParsedMVF.\n *\n * @param full - The complete ParsedMVF object to merge into.\n * @param partial - The partial ParsedMVFLocalePack containing localized updates.\n * @returns A new ParsedMVF object that is the result of merging the partial locale pack into the full ParsedMVF.\n *\n *\n * @example\n * // Basic merge with enterprise extension\n * // It work with any collection, but this extension is simple to create and read test data for.\n * const full: ParsedMVF = {\n *   'enterprise': {\n *     locations: [\n *       {\n *         id: 'el_store1',\n *         name: 'Clothing Store',\n *         externalId: 'CS001',\n *         type: 'store',\n *         sortOrder: 1,\n *         description: 'A great clothing store',\n *         polygons: [{ map: 'map1', id: 'space1' }],\n *         nodes: [{ map: 'map1', id: 'node1' }]\n *       }\n *     ],\n *     categories: []\n *   }\n * };\n *\n * const partial: ParsedMVFLocalePack = {\n *   'enterprise.json': {\n *     locations: [\n *       {\n *         id: 'el_store1',\n *         name: 'Magasin de Vêtements',\n *         description: 'Un excellent magasin de vêtements'\n *       }\n *     ]\n *   }\n * };\n *\n * const result = mergeLocalePack(full, partial);\n * // Result:\n * // {\n * //   'enterprise.json': {\n * //     locations: [\n * //       {\n * //         id: 'el_store1',\n * //         name: 'Magasin de Vêtements',\n * //         externalId: 'CS001',\n * //         type: 'store',\n * //         sortOrder: 1,\n * //         description: 'Un excellent magasin de vêtements',\n * //         polygons: [{ map: 'map1', id: 'space1' }],\n * //         nodes: [{ map: 'map1', id: 'node1' }]\n * //       }\n * //     ],\n * //     categories: []\n * //   }\n * // }\n *\n * @example\n * // Merge with nested arrays containing identifiable objects, showing partial updates\n * const full: ParsedMVF = {\n *   'enterprise.json': {\n *     locations: [\n *       {\n *         id: 'el_store1',\n *         name: 'Store 1',\n *         externalId: 'S1',\n *         type: 'store',\n *         sortOrder: 1,\n *         description: 'A great store',\n *         polygons: [{ map: 'map1', id: 'space1' }],\n *         nodes: [{ map: 'map1', id: 'node1' }]\n *       },\n *       {\n *         id: 'el_store2',\n *         name: 'Store 2',\n *         externalId: 'S2',\n *         type: 'store',\n *         sortOrder: 2,\n *         description: 'Another great store',\n *         polygons: [{ map: 'map1', id: 'space2' }],\n *         nodes: [{ map: 'map1', id: 'node2' }]\n *       }\n *     ]\n *   }\n * };\n *\n * const partial: ParsedMVFLocalePack = {\n *   'enterprise.json': {\n *     locations: [\n *       {\n *         id: 'el_store1',\n *         name: 'Magasin 1',\n *         description: 'Un excellent magasin'\n *       }\n *       // Note: el_store2 is not included because it hasn't changed\n *     ]\n *   }\n * };\n *\n * const result = mergeLocalePack(full, partial);\n * // Result:\n * // {\n * //   'enterprise.json': {\n * //     locations: [\n * //       {\n * //         id: 'el_store1',\n * //         name: 'Magasin 1',\n * //         externalId: 'S1',\n * //         type: 'store',\n * //         sortOrder: 1,\n * //         description: 'Un excellent magasin',\n * //         polygons: [{ map: 'map1', id: 'space1' }],\n * //         nodes: [{ map: 'map1', id: 'node1' }]\n * //       },\n * //       {\n * //         id: 'el_store2',\n * //         name: 'Store 2',\n * //         externalId: 'S2',\n * //         type: 'store',\n * //         sortOrder: 2,\n * //         description: 'Another great store',\n * //         polygons: [{ map: 'map1', id: 'space2' }],\n * //         nodes: [{ map: 'map1', id: 'node2' }]\n * //       }\n * //     ]\n * //   }\n * // }\n *\n * Note: The merging process always preserves the 'id' field and the structure of the\n * 'manifest.geojson' file, ensuring the integrity of the MVF structure while allowing\n * for localized content updates.\n */\nexport function mergeLocalePack(full: ParsedMVF, partial: ParsedMVFLocalePack): ParsedMVF {\n\tconst originalFolderStruct = full['manifest.geojson'].features[0].properties.folder_struct;\n\tconst partialMerge = deepMergeOn(full, partial, ['id']);\n\tconst partialManifest = partial['manifest.geojson'];\n\treturn {\n\t\t...partialMerge,\n\t\t'manifest.geojson': {\n\t\t\ttype: 'FeatureCollection',\n\t\t\tfeatures: [\n\t\t\t\t{\n\t\t\t\t\t...partialManifest.features[0],\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\t...partialManifest.features[0].properties,\n\t\t\t\t\t\tfolder_struct: originalFolderStruct,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t};\n}\n\n/**\n * Creates a partial locale pack by comparing two full ParsedMVF objects.\n *\n * This function generates a ParsedMVFLocalePack by identifying the differences\n * between a base ParsedMVF and a localized ParsedMVF. It's particularly useful\n * for extracting localized content changes from a fully localized MVF.\n *\n * Key features:\n * 1. Compares the base and localized ParsedMVF objects deeply.\n * 2. Includes only the properties and nested objects that differ in the locale pack.\n * 3. Handles arrays of objects with identifier keys, including only changed items.\n * 4. Preserves the structure of changed elements while omitting unchanged ones.\n * 5. Cleans up the manifest to include only relevant folder structure entries.\n *\n * @param base - The original ParsedMVF object to compare against.\n * @param locale - The localized ParsedMVF object containing changes.\n * @returns A ParsedMVFLocalePack containing only the differences between base and locale.\n *\n * @example\n * // Basic creation of a locale pack with enterprise extension\n * const base: ParsedMVF = {\n *   'enterprise.json': {\n *     venue: {\n *       name: 'Shopping Mall',\n *       slug: 'shopping-mall',\n *       externalId: 'SM001',\n *       defaultLanguage: { name: 'English', code: 'en' },\n *       languages: [{ name: 'English', code: 'en' }, { name: 'French', code: 'fr' }]\n *     },\n *     locations: [\n *       {\n *         id: 'el_store1',\n *         name: 'Clothing Store',\n *         externalId: 'CS001',\n *         type: 'store',\n *         sortOrder: 1,\n *         description: 'A great clothing store',\n *         polygons: [{ map: 'map1', id: 'space1' }],\n *         nodes: [{ map: 'map1', id: 'node1' }]\n *       }\n *     ],\n *     categories: []\n *   }\n * };\n *\n * const locale: ParsedMVF = {\n *   'enterprise.json': {\n *     venue: {\n *       name: 'Centre Commercial',\n *       slug: 'shopping-mall',\n *       externalId: 'SM001',\n *       defaultLanguage: { name: 'English', code: 'en' },\n *       languages: [{ name: 'English', code: 'en' }, { name: 'French', code: 'fr' }]\n *     },\n *     locations: [\n *       {\n *         id: 'el_store1',\n *         name: 'Magasin de Vêtements',\n *         externalId: 'CS001',\n *         type: 'store',\n *         sortOrder: 1,\n *         description: 'Un excellent magasin de vêtements',\n *         polygons: [{ map: 'map1', id: 'space1' }],\n *         nodes: [{ map: 'map1', id: 'node1' }]\n *       }\n *     ],\n *     categories: []\n *   }\n * };\n *\n * const result = createLocalePack(base, locale);\n * // Result:\n * // {\n * //   'enterprise.json': {\n * //     venue: {\n * //       name: 'Centre Commercial'\n * //     },\n * //     locations: [\n * //       {\n * //         id: 'el_store1',\n * //         name: 'Magasin de Vêtements',\n * //         description: 'Un excellent magasin de vêtements'\n * //       }\n * //     ]\n * //   }\n * // }\n *\n * @example\n * // Creating a locale pack with partial changes in nested arrays\n * const base: ParsedMVF = {\n *   'enterprise.json': {\n *     locations: [\n *       {\n *         id: 'el_store1',\n *         name: 'Store 1',\n *         externalId: 'S1',\n *         type: 'store',\n *         sortOrder: 1,\n *         description: 'A great store',\n *         polygons: [{ map: 'map1', id: 'space1' }],\n *         nodes: [{ map: 'map1', id: 'node1' }]\n *       },\n *       {\n *         id: 'el_store2',\n *         name: 'Store 2',\n *         externalId: 'S2',\n *         type: 'store',\n *         sortOrder: 2,\n *         description: 'Another great store',\n *         polygons: [{ map: 'map1', id: 'space2' }],\n *         nodes: [{ map: 'map1', id: 'node2' }]\n *       }\n *     ]\n *   }\n * };\n *\n * const locale: ParsedMVF = {\n *   'enterprise.json': {\n *     locations: [\n *       {\n *         id: 'el_store1',\n *         name: 'Magasin 1',\n *         externalId: 'S1',\n *         type: 'store',\n *         sortOrder: 1,\n *         description: 'Un excellent magasin',\n *         polygons: [{ map: 'map1', id: 'space1' }],\n *         nodes: [{ map: 'map1', id: 'node1' }]\n *       },\n *       {\n *         id: 'el_store2',\n *         name: 'Store 2',\n *         externalId: 'S2',\n *         type: 'store',\n *         sortOrder: 2,\n *         description: 'Another great store',\n *         polygons: [{ map: 'map1', id: 'space2' }],\n *         nodes: [{ map: 'map1', id: 'node2' }]\n *       }\n *     ]\n *   }\n * };\n *\n * const result = createLocalePack(base, locale);\n * // Result:\n * // {\n * //   'enterprise.json': {\n * //     locations: [\n * //       {\n * //         id: 'el_store1',\n * //         name: 'Magasin 1',\n * //         description: 'Un excellent magasin'\n * //       }\n * //       // Note: el_store2 is not included because it hasn't changed\n * //     ]\n * //   }\n * // }\n *\n * Note: The resulting locale pack includes only the changed properties and\n * maintains the structure necessary for these changes. The manifest is also\n * cleaned up to include only relevant folder structure entries.\n */\nexport function createLocalePack(base: ParsedMVF, locale: ParsedMVF): ParsedMVFLocalePack {\n\tconst localeManifest = locale['manifest.geojson'];\n\tconst diff = deepDiffOn(base, locale, ['id', 'key']);\n\tconst localePack = cleanUpManifest(localeManifest, diff);\n\treturn localePack;\n}\n","import type { ParsedMVF, RawMVF } from './types/bundle.js';\n\nexport type TextDecoderFn = typeof TextDecoder.prototype.decode;\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\ntype FolderKey<S extends string> = S extends `${infer _}.geojson` ? never : S extends `${infer _}.json` ? never : S;\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\ntype FileKey<S extends string> = S extends `${infer _}.geojson` ? S : S extends `${infer _}.json` ? S : never;\n\ntype ExhaustiveArray<T extends readonly unknown[], U> = [U] extends [T[number]] ? T : [...T, Exclude<U, T[number]>];\n\nconst defaultEntry = <K extends FolderKey<keyof RawMVF>>(folder: K): ParsedMVF[K] => {\n\t// Per the spec, these are required to exist, but could potentially be empty.\n\tif (folder === 'space' || folder === 'obstruction' || folder === 'entrance') {\n\t\treturn {} as unknown as ParsedMVF[K];\n\t}\n\treturn undefined as unknown as ParsedMVF[K];\n};\n\nconst FILE_EXTENSION = /\\.json|\\.geojson$/;\n\nconst rawFolderToParsed = <K extends FolderKey<keyof RawMVF>>(\n\traw: RawMVF,\n\tfolder: K,\n\tdecode: TextDecoderFn,\n): ParsedMVF[K] => {\n\tconst rawFolder = raw[folder];\n\tif (typeof rawFolder !== 'object' || Object.keys(rawFolder).length === 0) {\n\t\treturn defaultEntry(folder);\n\t}\n\n\tconst contents: Record<string, string> = {};\n\tfor (const [key, value] of Object.entries(rawFolder)) {\n\t\tconst floorId = key.replace(FILE_EXTENSION, '');\n\t\tcontents[floorId] = JSON.parse(decode(value));\n\t}\n\treturn contents as unknown as ParsedMVF[K];\n};\n\n// This oddity is a way to enforce a compiler error if either of these arrays\n// is missing a file or folder that should be mentioned.\n\ntype OptionalKeys<O> = { [K in keyof O]-?: undefined extends O[K] ? K : never }[keyof O];\ntype OptionalFiles = FileKey<OptionalKeys<RawMVF>>;\nconst _OPTIONAL_FILES = [\n\t'floorstack.json',\n\t'styles.json',\n\t'shapes.json',\n\t'mapstack.json',\n\t'floor.geojson',\n\t'tileset.json',\n\t'location.json',\n\t'category.json',\n\t'navigationFlags.json',\n\t'annotation-symbols.json',\n] as const;\nconst OPTIONAL_FILES = _OPTIONAL_FILES satisfies ExhaustiveArray<typeof _OPTIONAL_FILES, OptionalFiles>;\n\ntype OptionalFolders = FolderKey<OptionalKeys<RawMVF>>;\nconst _OPTIONAL_FOLDERS = [\n\t'annotation',\n\t'textAreas',\n\t'enterprise',\n\t'floorImages',\n\t'shapeInstances',\n\t'modelInstances',\n\t'window',\n\t'area',\n\t'facade',\n] as const;\nconst OPTIONAL_FOLDERS = _OPTIONAL_FOLDERS satisfies ExhaustiveArray<typeof _OPTIONAL_FOLDERS, OptionalFolders>;\n\nexport const rawToParsedMVF = (raw: RawMVF): ParsedMVF => {\n\tconst decoder = new TextDecoder('utf-8');\n\tconst decode = decoder.decode.bind(decoder) satisfies TextDecoderFn;\n\n\tconst parsedMVF: ParsedMVF = {\n\t\t'manifest.geojson': JSON.parse(decode(raw['manifest.geojson'])),\n\t\t'mapstack.geojson': JSON.parse(decode(raw['mapstack.geojson'])),\n\t\t'map.geojson': JSON.parse(decode(raw['map.geojson'])),\n\t\t'node.geojson': JSON.parse(decode(raw['node.geojson'])),\n\t\t'connection.json': JSON.parse(decode(raw['connection.json'])),\n\t\tspace: rawFolderToParsed(raw, 'space', decode),\n\t\tobstruction: rawFolderToParsed(raw, 'obstruction', decode),\n\t\tentrance: rawFolderToParsed(raw, 'entrance', decode),\n\t};\n\n\tfor (const key of OPTIONAL_FILES) {\n\t\tif (raw[key]) {\n\t\t\tparsedMVF[key] = JSON.parse(decode(raw[key]));\n\t\t}\n\t}\n\n\tfor (const key of OPTIONAL_FOLDERS) {\n\t\tif (raw[key]) {\n\t\t\t// @ts-expect-error since the type of each of these keys when parsed\n\t\t\t// is different.\n\t\t\tparsedMVF[key] = rawFolderToParsed(raw, key, decode);\n\t\t}\n\t}\n\n\treturn parsedMVF;\n};\n","/* eslint-disable @typescript-eslint/no-unused-vars */\n// This is disabled because we want function signatures to look the same even\n// when the value might be None.\nimport { err, ok } from './result.js';\nclass OptionIterator {\n    _value;\n    constructor(value) {\n        this._value = value;\n    }\n    [Symbol.iterator]() {\n        return this;\n    }\n    next() {\n        if (this._value == null) {\n            return { done: true, value: undefined };\n        }\n        const value = this._value;\n        this._value = null;\n        return { done: false, value };\n    }\n}\nexport class Some {\n    _tag = 'Some';\n    _value;\n    constructor(value) {\n        this._value = value;\n    }\n    get value() {\n        return this._value;\n    }\n    isSome() {\n        return true;\n    }\n    isSomeAnd(fn) {\n        return fn(this.value);\n    }\n    isNone() {\n        return false;\n    }\n    equals(other) {\n        return other.isSome() && other.value === this.value;\n    }\n    expect(message) {\n        return this.value;\n    }\n    unwrap() {\n        return this.value;\n    }\n    unwrapOr(fallback) {\n        return this.value;\n    }\n    unwrapOrElse(fn) {\n        return this.value;\n    }\n    inspect(fn) {\n        fn(this.value);\n        return this;\n    }\n    inspectNone(fn) {\n        return this;\n    }\n    map(fn) {\n        return option(fn(this.value));\n    }\n    mapAsync(fn) {\n        return fn(this.value).then((value) => option(value));\n    }\n    mapOr(fn, fallback) {\n        return this.map(fn).unwrapOr(fallback);\n    }\n    mapOrAsync(fn, fallback) {\n        return this.mapAsync(fn).then((value) => value.unwrapOr(fallback));\n    }\n    mapOrElse(fn, fallback) {\n        return this.map(fn).unwrapOrElse(fallback);\n    }\n    mapOrElseAsync(fn, fallback) {\n        return this.mapAsync(fn).then((value) => value.unwrapOrElse(fallback));\n    }\n    and(other) {\n        return other;\n    }\n    andThen(fn) {\n        return fn(this.value);\n    }\n    andThenAsync(fn) {\n        return fn(this.value);\n    }\n    filter(fn) {\n        return fn(this.value) ? this : none();\n    }\n    or(other) {\n        return this;\n    }\n    orElse(fn) {\n        return this;\n    }\n    xor(other) {\n        return other.isSome() ? none() : this;\n    }\n    toString() {\n        return `Some(${this.value})`;\n    }\n    okOr(error) {\n        return ok(this.value);\n    }\n    okOrElse(fn) {\n        return ok(this.value);\n    }\n    iter() {\n        return new OptionIterator(this.value);\n    }\n    [Symbol.iterator]() {\n        return this.iter();\n    }\n    zip(other) {\n        return other.isSome()\n            ? some([this.value, other.value])\n            : none();\n    }\n    zipWith(other, fn) {\n        return other.isSome() ? some(fn(this.value, other.value)) : none();\n    }\n    get [Symbol.toStringTag]() {\n        return 'Some';\n    }\n}\nexport class None {\n    _tag = 'None';\n    get value() {\n        return null;\n    }\n    isSome() {\n        return false;\n    }\n    isSomeAnd(fn) {\n        return false;\n    }\n    isNone() {\n        return true;\n    }\n    equals(other) {\n        return other.isNone();\n    }\n    expect(message) {\n        throw new Error(message);\n    }\n    unwrap() {\n        throw new Error('Tried to unwrap a None value!');\n    }\n    unwrapOr(fallback) {\n        return fallback;\n    }\n    unwrapOrElse(fn) {\n        return fn();\n    }\n    inspect(fn) {\n        return this;\n    }\n    inspectNone(fn) {\n        fn();\n        return this;\n    }\n    map(fn) {\n        return this;\n    }\n    mapAsync(fn) {\n        return Promise.resolve(this);\n    }\n    mapOr(fn, fallback) {\n        return fallback;\n    }\n    mapOrAsync(fn, fallback) {\n        return Promise.resolve(fallback);\n    }\n    mapOrElse(fn, fallback) {\n        return fallback();\n    }\n    mapOrElseAsync(fn, fallback) {\n        return fallback();\n    }\n    and(other) {\n        return this;\n    }\n    andThen(fn) {\n        return this;\n    }\n    andThenAsync(fn) {\n        return Promise.resolve(this);\n    }\n    filter(fn) {\n        return this;\n    }\n    or(other) {\n        return other;\n    }\n    orElse(fn) {\n        return fn();\n    }\n    xor(other) {\n        return other;\n    }\n    toString() {\n        return 'None';\n    }\n    okOr(error) {\n        return err(error);\n    }\n    okOrElse(fn) {\n        return err(fn());\n    }\n    iter() {\n        return new OptionIterator(null);\n    }\n    [Symbol.iterator]() {\n        return this.iter();\n    }\n    zip(other) {\n        return this;\n    }\n    zipWith(other, fn) {\n        return this;\n    }\n    get [Symbol.toStringTag]() {\n        return 'None';\n    }\n}\nexport const some = (value) => {\n    return new Some(value);\n};\nexport const none = () => {\n    return new None();\n};\nexport const option = (value) => {\n    if (value instanceof Some || value instanceof None) {\n        return value;\n    }\n    if (value == null) {\n        return none();\n    }\n    return some(value);\n};\n//# sourceMappingURL=option.js.map","/* eslint-disable @typescript-eslint/no-unused-vars */\n// This is disabled because we want function signatures to look the same even\n// when the value might be Err.\nimport { none, some } from './option.js';\nclass ResultIterator {\n    _value;\n    constructor(value) {\n        this._value = value;\n    }\n    [Symbol.iterator]() {\n        return this;\n    }\n    next() {\n        if (this._value == null) {\n            return { done: true, value: undefined };\n        }\n        const value = this._value;\n        this._value = null;\n        return { done: false, value };\n    }\n}\nexport class Ok {\n    _tag = 'Ok';\n    _value;\n    constructor(value) {\n        this._value = value;\n    }\n    get value() {\n        return this._value;\n    }\n    get error() {\n        return null;\n    }\n    isOk() {\n        return true;\n    }\n    isOkAnd(fn) {\n        return fn(this.value);\n    }\n    isErr() {\n        return false;\n    }\n    isErrAnd(fn) {\n        return false;\n    }\n    ok() {\n        return some(this.value);\n    }\n    err() {\n        return none();\n    }\n    expect(message) {\n        return this.value;\n    }\n    expectErr(message) {\n        throw new Error(message);\n    }\n    unwrap() {\n        return this.value;\n    }\n    unwrapOr(fallback) {\n        return this.value;\n    }\n    unwrapOrElse(fn) {\n        return this.value;\n    }\n    inspect(fn) {\n        fn(this.value);\n        return this;\n    }\n    inspectErr() {\n        return this;\n    }\n    map(fn) {\n        return ok(fn(this.value));\n    }\n    async mapAsync(fn) {\n        return fn(this.value).then(ok);\n    }\n    mapOr(fn, fallback) {\n        return fn(this.value);\n    }\n    async mapOrAsync(fn, fallback) {\n        return fn(this.value);\n    }\n    mapOrElse(fn, fallback) {\n        return fn(this.value);\n    }\n    async mapOrElseAsync(fn, fallback) {\n        return fn(this.value);\n    }\n    mapErr(fn) {\n        return this;\n    }\n    iter() {\n        return new ResultIterator(this.value);\n    }\n    [Symbol.iterator]() {\n        return this.iter();\n    }\n    and(result) {\n        return result;\n    }\n    andThen(fn) {\n        return fn(this.value);\n    }\n    or(result) {\n        return this;\n    }\n    orElse(fn) {\n        return this;\n    }\n    async andThenAsync(fn) {\n        return fn(this.value);\n    }\n    toString() {\n        return `Ok(${this.value})`;\n    }\n    get [Symbol.toStringTag]() {\n        return 'Ok';\n    }\n}\nexport class Err {\n    _tag = 'Err';\n    _error;\n    constructor(error) {\n        this._error = error;\n    }\n    get value() {\n        return null;\n    }\n    get error() {\n        return this._error;\n    }\n    isOk() {\n        return false;\n    }\n    isOkAnd(fn) {\n        return false;\n    }\n    isErr() {\n        return true;\n    }\n    isErrAnd(fn) {\n        return fn(this.error);\n    }\n    ok() {\n        return none();\n    }\n    err() {\n        return some(this.error);\n    }\n    expect(message) {\n        throw new Error(message);\n    }\n    expectErr(message) {\n        return this.error;\n    }\n    unwrap() {\n        throw this.error;\n    }\n    unwrapOr(fallback) {\n        return fallback;\n    }\n    unwrapOrElse(fn) {\n        return fn();\n    }\n    inspect() {\n        return this;\n    }\n    inspectErr(fn) {\n        fn(this.error);\n        return this;\n    }\n    map(fn) {\n        return this;\n    }\n    iter() {\n        return new ResultIterator(null);\n    }\n    [Symbol.iterator]() {\n        return this.iter();\n    }\n    async mapAsync(fn) {\n        return this;\n    }\n    mapOr(fn, fallback) {\n        return fallback;\n    }\n    async mapOrAsync(fn, fallback) {\n        return fallback;\n    }\n    mapOrElse(fn, fallback) {\n        return fallback();\n    }\n    async mapOrElseAsync(fn, fallback) {\n        return fallback();\n    }\n    mapErr(fn) {\n        return new Err(fn(this.error));\n    }\n    and(other) {\n        return this;\n    }\n    andThen(fn) {\n        return this;\n    }\n    async andThenAsync(fn) {\n        return this;\n    }\n    or(result) {\n        return result;\n    }\n    orElse(fn) {\n        return fn(this.error);\n    }\n    toString() {\n        return `Err(${this.error})`;\n    }\n    get [Symbol.toStringTag]() {\n        return 'Err';\n    }\n}\nexport const ok = (value) => new Ok(value);\nexport const err = (error) => new Err(error);\n//# sourceMappingURL=result.js.map","export const typedKeys = (obj) => {\n    return Object.keys(obj);\n};\n//# sourceMappingURL=typed-keys.js.map","export const typedEntries = (record) => {\n    return Object.entries(record);\n};\n//# sourceMappingURL=typed-entries.js.map","export const TEXT_ALIGNMENT_VALUES = ['left', 'center', 'right'];\nexport const TEXT_ALIGNMENTS = [...TEXT_ALIGNMENT_VALUES, 'unknown'];\nexport const TEXT_ALIGNMENT = Object.freeze(Object.fromEntries([...TEXT_ALIGNMENT_VALUES, 'unknown'].map((value) => [value, value])));\nexport const isTextAlignment = (value) => Object.hasOwn(TEXT_ALIGNMENT, value);\n//# sourceMappingURL=floor-text-values.js.map","export const SIBLING_GROUP_TYPE_VALUES = ['reference-point', 'checkpoint', 'checkpoint-passport', 'parent'];\nexport const ENTERPRISE_SIBLING_GROUP_TYPES = [\n    ...SIBLING_GROUP_TYPE_VALUES,\n    'unknown',\n];\nexport const ENTERPRISE_SIBLING_GROUP_TYPE = Object.freeze(Object.fromEntries([...SIBLING_GROUP_TYPE_VALUES, 'unknown'].map((value) => [value, value])));\nexport const isSiblingGroupType = (value) => Object.hasOwn(ENTERPRISE_SIBLING_GROUP_TYPE, value);\nexport const LOCATION_STATE_VALUES = ['closed-temporarily', 'new', 'pop-up', 'coming-soon', 'relocated'];\n/**\n * An array representing all the possible location states.\n */\nexport const LOCATION_STATES = [...LOCATION_STATE_VALUES, 'unknown'];\n/**\n * A record of all the possible location states. The key and value are the same.\n */\nexport const LOCATION_STATE = Object.freeze(Object.fromEntries([...LOCATION_STATE_VALUES, 'unknown'].map((value) => [value, value])));\n/**\n * A type guard function that checks if a value is a valid location state.\n */\nexport const isLocationState = (value) => Object.hasOwn(LOCATION_STATE, value);\n//# sourceMappingURL=utils-values.js.map","export const TEXT_AREA_ALIGNMENT_VALUES = ['near', 'center'];\n/**\n * The possible values for the alignment of the text within a text area.\n */\nexport const TEXT_AREA_ALIGNMENTS = [\n    ...TEXT_AREA_ALIGNMENT_VALUES,\n    'unknown',\n];\n/**\n * A record of possible alignments for a text area.\n */\nexport const TEXT_AREA_ALIGNMENT = Object.freeze(Object.fromEntries([...TEXT_AREA_ALIGNMENT_VALUES, 'unknown'].map((value) => [value, value])));\n/**\n * A type guard function that checks if a value is a valid alignment for a text area.\n */\nexport const isTextAreaAlignment = (value) => Object.hasOwn(TEXT_AREA_ALIGNMENT, value);\n//# sourceMappingURL=text-area-values.js.map","export const TEXTURE_FACE_VALUES = ['top', 'side'];\n/**\n * An array representing all the possible faces that a texture can be applied to.\n */\nexport const ENTERPRISE_TEXTURE_FACES = [...TEXTURE_FACE_VALUES, 'unknown'];\n/**\n * A record of all the possible enterprise texture faces. The key and value are the same.\n */\nexport const ENTERPRISE_TEXTURE_FACE = Object.freeze(Object.fromEntries([...TEXTURE_FACE_VALUES, 'unknown'].map((value) => [value, value])));\n/**\n * A type guard function that checks if a value is a valid face for a texture.\n */\nexport const isEnterpriseTextureFace = (value) => Object.hasOwn(ENTERPRISE_TEXTURE_FACE, value);\nexport const TEXTURE_SURFACE_VALUES = ['inside', 'outside', 'both'];\n/**\n * An array representing all the possible surfaces that a texture can be applied to.\n */\nexport const ENTERPRISE_TEXTURE_SURFACES = [\n    ...TEXTURE_SURFACE_VALUES,\n    'unknown',\n];\n/**\n * A record of all the possible enterprise texture surfaces. The key and value are the same.\n */\nexport const ENTERPRISE_TEXTURE_SURFACE = Object.freeze(Object.fromEntries([...TEXTURE_SURFACE_VALUES, 'unknown'].map((value) => [value, value])));\n/**\n * A type guard function that checks if a value is a valid surface for a texture.\n */\nexport const isEnterpriseTextureSurface = (value) => Object.hasOwn(ENTERPRISE_TEXTURE_SURFACE, value);\n//# sourceMappingURL=texture-values.js.map","export const ENTERPRISE_VENUE_TYPE_VALUES = [\n    'agriculture',\n    'airport',\n    'casino',\n    'city-district',\n    'convention-center',\n    'entertainment',\n    'event-centre',\n    'first-responder-building',\n    'government-building',\n    'grocery-store',\n    'healthcare',\n    'higher-education',\n    'hotel',\n    'library',\n    'manufacturing',\n    'medical-centre',\n    'mixed-use',\n    'multifamily',\n    'museum',\n    'office-building',\n    'oil-and-energy',\n    'other',\n    'parking-facility',\n    'religious-institution',\n    'resort',\n    'retail-store',\n    'schools-k-12',\n    'shopping-mall',\n    'stadium-or-arena',\n    'storage-facility',\n    'theme-park',\n    'transit',\n    'transportation-hub',\n    'warehousing',\n];\nexport const ENTERPRISE_VENUE_TYPES = [\n    ...ENTERPRISE_VENUE_TYPE_VALUES,\n    'unknown',\n];\nexport const ENTERPRISE_VENUE_TYPE = Object.freeze(Object.fromEntries([...ENTERPRISE_VENUE_TYPE_VALUES, 'unknown'].map((value) => [value, value])));\nexport const isEnterpriseVenueType = (value) => Object.hasOwn(ENTERPRISE_VENUE_TYPE, value);\n//# sourceMappingURL=enterprise-venue-values.js.map","/**\n * Checks if a flag is set in an object WithFlags.\n *\n * First find the NavigationFlagDeclaration using the key, then check\n * a flagged object with this function to see if it's present. You can\n * safely pass an undefined flag (the check will return false). This is useful when\n * trying to use a well-known flag, which may or may not be actually present in the MVF.\n *\n * @category Utils\n * @example\n * ```typescript\n * const obj: WithFlags = { flags: [1] };\n * const flag: NavigationFlagDeclaration = { index: 0, bit: 0 };\n * const hasAccessible = hasFlag(obj, flag); // true\n * ```\n *\n * @param withFlags - The WithFlags object to check\n * @param flag - The flag to check for\n * @returns true if the flag is set, false otherwise\n * @see {@link NavigationFlagDeclaration}\n * @see {@link WithFlags}\n */\nexport function hasFlag(withFlags, flag) {\n    return flag && (withFlags.flags[flag.index] & (1 << flag.bit)) !== 0;\n}\n//# sourceMappingURL=utils.js.map","/**\n * All well known navigation flags. These may or may not be present in an MVF, but if they are, they always mean the same thing.\n */\nexport const WELL_KNOWN_FLAGS = {\n    /**\n     * A flag indicating that something is accessible, specifically that it can be crossed by users with reduced mobility, including those using wheelchairs.\n     */\n    accessible: 'accessible',\n    /**\n     * A flag indicating that something is outside of a building, in the open air. The sky is NOT NECESSARILY visible, an 'outdoors' path may be under a bridge or awning.\n     */\n    outdoors: 'outdoors',\n    /**\n     * A flag indicating that something is navigable by the public users of the building or space. By default, consumers of MVF should not route through non-public things unless specifically requested.\n     */\n    public: 'public',\n};\n//# sourceMappingURL=well-known-flags.js.map","export const CONNECTION_TYPE_VALUES = [\n    'elevator',\n    'escalator',\n    'travelator',\n    'stairs',\n    'door',\n    'ramp',\n    'ladder',\n];\n/**\n * {@inheritDoc ConnectionType}\n */\nexport const CONNECTION_TYPES = [...CONNECTION_TYPE_VALUES, 'unknown'];\n/**\n * {@inheritDoc ConnectionType}\n */\nexport const CONNECTION_TYPE = Object.freeze(Object.fromEntries([...CONNECTION_TYPE_VALUES, 'unknown'].map((value) => [value, value])));\n/**\n * A type guard function that checks if a value is a valid connection type.\n */\nexport const isConnectionType = (value) => Object.hasOwn(CONNECTION_TYPE, value);\n//# sourceMappingURL=connection-types.js.map","export const KIND_VALUES = ['room', 'hallway', 'wall', 'object', 'poi', 'area', 'window'];\n/**\n * {@inheritDoc Kind}\n */\nexport const KINDS = [...KIND_VALUES, 'unknown'];\n/**\n * {@inheritDoc Kind}\n */\nexport const KIND = Object.freeze(Object.fromEntries([...KIND_VALUES, 'unknown'].map((value) => [value, value])));\n/**\n * A type guard function that checks if a value is a valid kind.\n */\nexport const isKind = (value) => Object.hasOwn(KIND, value);\n//# sourceMappingURL=kind-values.js.map","import type { EnterpriseCategoryId, EnterpriseLocationId, EnterpriseLocationInstanceId } from '@mappedin/mvf-cms';\nimport type { GeometryFeature, GeometryId } from '@mappedin/mvf-core';\nimport { typedEntries } from '@mappedin/mvf-core/utils/typed-entries';\nimport { typedKeys } from '@mappedin/mvf-core/utils/typed-keys';\nimport type { LocationCategoryId, LocationId, LocationInstanceId } from '@mappedin/mvf-locations';\nimport type { Flags } from '@mappedin/mvf-navigation-flags';\nimport type { AreaId } from '../extensions/area.js';\nimport type { WindowId } from '../extensions/window.js';\nimport type { NodeId, ObstructionId } from '../types/core.js';\nimport type { SpaceId } from '../types/core.js';\nimport type { MVFv2_STANDARD_MVFv3 } from './index.js';\n\nexport function toSpaceId(id: GeometryId): SpaceId {\n\treturn id.replace(/^g_/, 's_');\n}\n\nexport function toObstructionId(id: GeometryId): ObstructionId {\n\treturn id.replace(/^g_/, 'o_');\n}\nexport function convertGeometryId(id: GeometryId, obstructionIds: Set<GeometryId>): SpaceId | ObstructionId {\n\tif (obstructionIds.has(id)) {\n\t\treturn toObstructionId(id);\n\t}\n\treturn toSpaceId(id);\n}\n\nexport function toWindowId(id: GeometryId): WindowId {\n\treturn id.replace(/^g_/, 'w_');\n}\n\nexport function convertLocationInstanceId(id: LocationInstanceId): EnterpriseLocationInstanceId {\n\treturn id.replace(/^loci_/, 'eli_') as EnterpriseLocationInstanceId;\n}\n\nexport function convertLocationId(id: LocationId): EnterpriseLocationId {\n\treturn id.replace(/^loc_/, 'el_') as EnterpriseLocationId;\n}\n\nexport function convertLocationCategoryId(id: LocationCategoryId): EnterpriseCategoryId {\n\treturn id.replace(/^lcat_/, 'ec_') as EnterpriseCategoryId;\n}\n\nexport type GeometryIdConverter = (id: GeometryId) => SpaceId | ObstructionId;\n\nexport function generateIdConverter(obstructionIds: Set<GeometryId>): GeometryIdConverter {\n\treturn (id: GeometryId) => convertGeometryId(id, obstructionIds);\n}\n\nexport function convertAreaId(id: GeometryId): AreaId {\n\treturn id.replace(/^g_/, 'ar_');\n}\n\nexport function convertNodeToSpaceId(id: NodeId): SpaceId {\n\treturn id.replace(/^n_/, 's_');\n}\n\nexport function splitMultiPartGeometryFeatureWithNewId<T extends string>(\n\tfeature: GeometryFeature,\n\tnewId: T,\n\tkind?: string,\n): PartiallyTransformedGeometryFeature<T>[] {\n\tswitch (feature.geometry.type) {\n\t\tcase 'MultiPoint':\n\t\tcase 'MultiLineString':\n\t\tcase 'MultiPolygon': {\n\t\t\tconst result: PartiallyTransformedGeometryFeature<T>[] = [];\n\t\t\tlet index = 0;\n\t\t\tconst type = feature.geometry.type.replace('Multi', '') as 'Point' | 'LineString' | 'Polygon';\n\t\t\tfor (const coordinates of feature.geometry.coordinates) {\n\t\t\t\tresult.push({\n\t\t\t\t\t...feature,\n\t\t\t\t\tgeometry: { type, coordinates } as GeometryFeature['geometry'],\n\t\t\t\t\tproperties: { ...feature.properties, id: `${newId}-${index++}` as T, kind },\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\t\tdefault:\n\t\t\treturn [{ ...feature, properties: { ...feature.properties, id: newId, kind } }];\n\t}\n}\n\n/**\n * A geometry feature that has been partially transformed into v2. In particular,\n * the `id` has been converted to the new ID type, and the `kind` has been added.\n * These are also probably not multi geometry features, but this is not actually enforced.\n *\n */\nexport type PartiallyTransformedGeometryFeature<T> = Omit<GeometryFeature, 'properties'> & {\n\tproperties: Omit<GeometryFeature['properties'], 'id'> & { id: T; kind: string | undefined };\n};\n\nexport type MappedGeometry<T> = Map<\n\tGeometryId,\n\t{\n\t\tids: T[];\n\t\tfeatures: PartiallyTransformedGeometryFeature<T>[];\n\t\tanchors: {\n\t\t\tgeometryId: T;\n\t\t\tfloorId: string;\n\t\t}[];\n\t}\n>;\n\nexport function mapGeometryToOtherIds<T extends string>(\n\tgeometry: { feature: GeometryFeature; floorId: string }[],\n\txIds: { has: (id: GeometryId) => boolean }, // Probably a set, but can be any object with that function\n\tconvertToX: (id: GeometryId) => T,\n\tkindsMap: Map<GeometryId, string | undefined>,\n): MappedGeometry<T> {\n\tconst result: MappedGeometry<T> = new Map();\n\tfor (const { feature, floorId } of geometry) {\n\t\tconst id = feature.properties.id;\n\t\tconst kind = kindsMap.get(id);\n\t\tif (xIds.has(id)) {\n\t\t\tconst converted = splitMultiPartGeometryFeatureWithNewId(feature, convertToX(id), kind);\n\t\t\tconst ids = converted.map((x) => x.properties.id);\n\t\t\tconst anchors = ids.map((geometryId) => ({\n\t\t\t\tgeometryId,\n\t\t\t\tfloorId,\n\t\t\t}));\n\t\t\tresult.set(id, { ids, features: converted, anchors });\n\t\t}\n\t}\n\treturn result;\n}\n\nexport type GeometryMaps = {\n\tspace: MappedGeometry<SpaceId>;\n\tobstruction: MappedGeometry<ObstructionId>;\n\tarea: MappedGeometry<AreaId>;\n\twindow: MappedGeometry<WindowId>;\n\tobject: MappedGeometry<ObstructionId>;\n};\n\nexport function createGeometryMaps(\n\tv3: Partial<Pick<MVFv2_STANDARD_MVFv3, 'geometry' | 'kinds' | 'nonwalkable' | 'walkable' | 'connections'>>,\n): GeometryMaps {\n\tconst result: GeometryMaps = {\n\t\tspace: new Map(),\n\t\tobstruction: new Map(),\n\t\tarea: new Map(),\n\t\twindow: new Map(),\n\t\tobject: new Map(),\n\t};\n\tif (!v3.geometry) {\n\t\treturn result;\n\t}\n\n\tconst kindsMap = createKindsMap(v3);\n\n\tconst flatFeatures = typedEntries(v3.geometry)\n\t\t.flatMap(([floor, featureCollection]) =>\n\t\t\t(featureCollection?.features ?? []).map((x) => ({ feature: x, floorId: floor })),\n\t\t)\n\t\t.flat();\n\n\tconst walkableIds = new Set(\n\t\tObject.values(v3.walkable ?? {})\n\t\t\t.filter((x) => x !== undefined)\n\t\t\t.flatMap(typedKeys),\n\t);\n\tconst obstructionIds = new Set(\n\t\tObject.values(v3.nonwalkable ?? {})\n\t\t\t.filter((x) => x !== undefined)\n\t\t\t.flatMap(typedKeys),\n\t);\n\n\tconst areaIds = new Set(\n\t\tArray.from(kindsMap.entries())\n\t\t\t.filter(([_, kind]) => kind === 'area')\n\t\t\t.map(([id]) => id),\n\t);\n\n\tconst objectsIds = new Set(\n\t\tArray.from(kindsMap.entries())\n\t\t\t.filter(([_, kind]) => kind === 'object')\n\t\t\t.map(([id]) => id),\n\t);\n\n\tconst windowIds = new Set(\n\t\tArray.from(kindsMap.entries())\n\t\t\t.filter(([_, kind]) => kind === 'window')\n\t\t\t.map(([id]) => id),\n\t);\n\n\tif (walkableIds.size > 0) {\n\t\tresult.space = mapGeometryToOtherIds(flatFeatures, walkableIds, toSpaceId, kindsMap);\n\t}\n\tif (obstructionIds.size > 0) {\n\t\tresult.obstruction = mapGeometryToOtherIds(flatFeatures, obstructionIds, toObstructionId, kindsMap);\n\t}\n\tif (areaIds.size > 0) {\n\t\tresult.area = mapGeometryToOtherIds(flatFeatures, areaIds, convertAreaId, kindsMap);\n\t}\n\tif (objectsIds.size > 0) {\n\t\tresult.object = mapGeometryToOtherIds(flatFeatures, objectsIds, toObstructionId, kindsMap);\n\t}\n\n\t// I don't think anyone actually cares about window ids to keep the MVFv3 ones vs re-writing them like this\n\tif (windowIds.size > 0) {\n\t\tresult.window = mapGeometryToOtherIds(flatFeatures, windowIds, toWindowId, kindsMap);\n\t}\n\n\t// Incase we have no information about the geometry, we will just map everything to a space\n\t// This is the Enterprise case.\n\t// If Enterprise ever produces v3 data with areas, it will need to fill in walkable to get spaces again.\n\tif (walkableIds.size === 0 && obstructionIds.size === 0 && areaIds.size === 0) {\n\t\tresult.space = mapGeometryToOtherIds(\n\t\t\tflatFeatures,\n\t\t\tnew Set(flatFeatures.map((x) => x.feature.properties.id)),\n\t\t\ttoSpaceId,\n\t\t\tkindsMap,\n\t\t);\n\t}\n\n\treturn result;\n}\n\nexport function createKindsMap(v3: Pick<MVFv2_STANDARD_MVFv3, 'kinds' | 'connections'>): Map<GeometryId, string> {\n\tconst kindsMap = new Map(\n\t\tObject.values(v3.kinds ?? {})\n\t\t\t.filter((x) => x !== undefined)\n\t\t\t.flatMap(typedEntries),\n\t) as Map<GeometryId, string>;\n\n\t// All connections (except doors) should override the kind of their geometry to connection.<type>\n\tfor (const connection of v3.connections?.filter((c) => c.type !== 'door') ?? []) {\n\t\tfor (const entrance of connection.entrances) {\n\t\t\tkindsMap.set(entrance.geometryId, `connection.${connection.type}`);\n\t\t}\n\t\tfor (const exit of connection.exits) {\n\t\t\tkindsMap.set(exit.geometryId, `connection.${connection.type}`);\n\t\t}\n\t}\n\treturn kindsMap;\n}\n\nexport function someFlags(flags: Flags[]): Flags {\n\tif (!flags || flags.length === 0) {\n\t\treturn [];\n\t}\n\tconst maxLength = Math.max(...flags.map((f) => f.length));\n\treturn flags.reduce((acc, flag) => {\n\t\treturn acc.map((x, i) => x | (flag[i] ?? 0));\n\t}, Array(maxLength).fill(0));\n}\n","// Center-of-mass strategy re-implements turf's `centerOfMass` algorithm (the\n// algorithm Maker uses to generate MVFv2 centers) so v3 → v2 conversion\n// reproduces the same `space.center` values without pulling in the turf\n// dependency tree. Turf is MIT-licensed; this is an independent re-implementation\n// of the (uncopyrightable) shoelace-centroid math, matched to turf's behavior.\n// See https://github.com/Turfjs/turf/tree/master/packages/turf-center-of-mass.\n\nimport { type Result, err, ok } from '@mappedin/safe-types/result';\nimport polylabel from 'polylabel';\nimport type { Feature, Polygon } from '../types/geojson.js';\n\n/**\n * Computes the `[longitude, latitude]` center of a polygon feature (used for the\n * `center` of spaces, obstructions, and areas). Return an `err` for geometry\n * that cannot be centered so the converter can leave `center` undefined.\n *\n * Supply a custom implementation via {@link CenterStrategy} to fully control how\n * centers are computed.\n */\nexport type CenterCalculator = (feature: Feature<Polygon, unknown>) => Result<[number, number], Error>;\n\n/**\n * Selects how polygon centers are computed during v3 → v2 conversion.\n *\n * - `'center-of-mass'` (default): the area-weighted centroid, matching turf's\n *   `centerOfMass` — the algorithm Maker uses when it generates MVFv2 natively.\n *   Reproduces the `space.center` of native MVFv2 bundles, is a single O(n) pass\n *   (no measurable conversion overhead), and falls back to `polylabel` only when\n *   the centroid lands outside a concave shape.\n * - `'visual-center'`: the pole of inaccessibility via `polylabel` — the interior\n *   point furthest from any edge. Stays deep inside concave shapes but costs\n *   ~20× more per polygon and does not match native MVFv2 centers.\n * - a {@link CenterCalculator}: a fully custom implementation.\n */\nexport type CenterStrategy = 'center-of-mass' | 'visual-center' | CenterCalculator;\n\n/**\n * Unsigned shoelace area of the polygon's outer ring. Used only to scale the\n * `polylabel` fallback precision.\n */\nconst calculateArea = (polygon: Feature<Polygon, unknown>): number => {\n\tconst coordinates = polygon.geometry.coordinates[0];\n\tlet area = 0;\n\n\tfor (let i = 0; i < coordinates.length - 1; i++) {\n\t\tarea += coordinates[i][0] * coordinates[i + 1][1] - coordinates[i + 1][0] * coordinates[i][1];\n\t}\n\n\treturn Math.abs(area / 2);\n};\n\n/** Ray-casting test for whether a point lies inside a single ring. */\nconst pointInRing = (x: number, y: number, ring: readonly (readonly number[])[]): boolean => {\n\tlet inside = false;\n\tfor (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {\n\t\tconst xi = ring[i][0];\n\t\tconst yi = ring[i][1];\n\t\tconst xj = ring[j][0];\n\t\tconst yj = ring[j][1];\n\n\t\tconst intersect = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;\n\n\t\tif (intersect) inside = !inside;\n\t}\n\treturn inside;\n};\n\n/**\n * True when the point lies inside the outer ring and outside every hole. Used to\n * decide whether the area centroid needs the `polylabel` fallback.\n */\nconst pointInPolygon = (point: [number, number], polygon: Feature<Polygon, unknown>): boolean => {\n\tconst [x, y] = point;\n\tconst rings = polygon.geometry.coordinates;\n\n\tif (!pointInRing(x, y, rings[0])) return false;\n\tfor (let h = 1; h < rings.length; h++) {\n\t\tif (pointInRing(x, y, rings[h])) return false;\n\t}\n\treturn true;\n};\n\n/**\n * Area-weighted centroid of a polygon, a re-implementation of turf's\n * `centerOfMass` algorithm for the `Polygon` case (the algorithm Maker uses to\n * compute MVFv2 centers).\n *\n * Coordinates are neutralized by the vertex centroid before the signed-area\n * accumulation and restored afterwards; this is essential for precision at\n * geographic coordinates (lon ≈ -79, lat ≈ 43), where running the shoelace on\n * raw values loses the polygon's ~1e-5° signal to catastrophic cancellation.\n * As in turf, all rings are walked as one flattened path (so holes are handled\n * exactly as turf handles them) and a zero signed area degrades to the vertex\n * centroid.\n */\nconst calculateCenterOfMass = (polygon: Feature<Polygon, unknown>): [number, number] => {\n\tconst rings = polygon.geometry.coordinates;\n\n\t// Neutralize by the mean of the unique vertices (each ring's closing vertex\n\t// dropped), matching turf's `centroid`.\n\tlet xSum = 0;\n\tlet ySum = 0;\n\tlet count = 0;\n\tfor (const ring of rings) {\n\t\tfor (let k = 0; k < ring.length - 1; k++) {\n\t\t\txSum += ring[k][0];\n\t\t\tySum += ring[k][1];\n\t\t\tcount++;\n\t\t}\n\t}\n\tif (count === 0) throw new Error('Polygon has no vertices');\n\tconst tx = xSum / count;\n\tconst ty = ySum / count;\n\n\tlet sx = 0;\n\tlet sy = 0;\n\tlet sArea = 0;\n\tlet prevX: number | undefined;\n\tlet prevY: number | undefined;\n\tfor (const ring of rings) {\n\t\tfor (const pt of ring) {\n\t\t\tconst xj = pt[0] - tx;\n\t\t\tconst yj = pt[1] - ty;\n\t\t\tif (prevX !== undefined && prevY !== undefined) {\n\t\t\t\tconst cross = prevX * yj - xj * prevY;\n\t\t\t\tsArea += cross;\n\t\t\t\tsx += (prevX + xj) * cross;\n\t\t\t\tsy += (prevY + yj) * cross;\n\t\t\t}\n\t\t\tprevX = xj;\n\t\t\tprevY = yj;\n\t\t}\n\t}\n\n\tif (sArea === 0) return [tx, ty];\n\tconst areaFactor = 1 / (3 * sArea);\n\treturn [tx + areaFactor * sx, ty + areaFactor * sy];\n};\n\n/**\n * Picks a precision for `polylabel` proportional to the polygon's linear size\n * (≈1% of its extent). A precision relative to the geometry keeps polylabel's\n * cost bounded and independent of the coordinate system's scale: a fixed\n * absolute precision is pathologically fine — and slow — for large coordinate\n * ranges, yet needlessly coarse for tiny ones. For real lon/lat indoor geometry\n * this works out to roughly 1e-6° (~0.1 m).\n */\nconst estimatePrecision = (f: Feature<Polygon, unknown>): number => {\n\tconst polygonArea = calculateArea(f);\n\tif (!Number.isFinite(polygonArea) || polygonArea <= 0) return 1e-9;\n\treturn Math.sqrt(polygonArea) * 0.01;\n};\n\n/**\n * `'center-of-mass'` strategy: the area-weighted centroid (turf `centerOfMass`),\n * with a `polylabel` fallback when the centroid lands outside a concave polygon.\n * This is the default {@link CenterStrategy} and reproduces the `space.center`\n * values of natively generated Maker MVFv2 bundles.\n *\n * @param f - The polygon feature to center.\n * @returns The `[longitude, latitude]` center, or an error for invalid geometry.\n */\nexport const centerOfMass: CenterCalculator = (f) => {\n\ttry {\n\t\tconst center = calculateCenterOfMass(f);\n\t\tif (pointInPolygon(center, f)) {\n\t\t\treturn ok(center);\n\t\t}\n\t\t// @ts-expect-error the polylabel types are wrong\n\t\tconst centerPt = polylabel(f.geometry.coordinates, estimatePrecision(f));\n\t\treturn ok([centerPt[0], centerPt[1]]);\n\t} catch {\n\t\treturn err(new Error('Unable to calculate center of polygon'));\n\t}\n};\n\n/**\n * `'visual-center'` strategy: the pole of inaccessibility via `polylabel`. This\n * is the interior point furthest from any edge, so it stays inside concave\n * shapes and is not skewed by dense runs of vertices along one edge. Opt in via\n * {@link CenterStrategy} when you want the most visually centered point rather\n * than parity with native MVFv2 centers.\n *\n * @param f - The polygon feature to center.\n * @returns The `[longitude, latitude]` center, or an error for invalid geometry.\n */\nexport const labelCenter: CenterCalculator = (f) => {\n\ttry {\n\t\t// @ts-expect-error the polylabel types are wrong\n\t\tconst centerPt = polylabel(f.geometry.coordinates, estimatePrecision(f));\n\t\treturn ok([centerPt[0], centerPt[1]]);\n\t} catch {\n\t\treturn err(new Error('Unable to calculate center of polygon'));\n\t}\n};\n\n/**\n * Resolves a {@link CenterStrategy} to the {@link CenterCalculator} that\n * implements it. A function strategy is returned as-is.\n *\n * @param strategy - The strategy to resolve.\n * @default 'center-of-mass'\n * @returns The center calculator for the strategy.\n */\nexport const resolveCenterCalculator = (strategy: CenterStrategy = 'center-of-mass'): CenterCalculator => {\n\tif (typeof strategy === 'function') {\n\t\treturn strategy;\n\t}\n\tswitch (strategy) {\n\t\tcase 'visual-center':\n\t\t\treturn labelCenter;\n\t\tcase 'center-of-mass':\n\t\t\treturn centerOfMass;\n\t}\n};\n","import type { GeometryFeature, GeometryId } from '@mappedin/mvf-core';\nimport type { NavigationFlagDeclarations } from '@mappedin/mvf-navigation-flags';\nimport type { NodeFeature, NodeId, NodeNeighbor } from '@mappedin/mvf-nodes';\nimport { type GeometryMaps, createGeometryMaps } from './converterUtils.js';\nimport { type CenterCalculator, type CenterStrategy, resolveCenterCalculator } from './geoCenter.js';\nimport type { MVFv2_STANDARD_MVFv3 } from './index.js';\n\n/**\n * Options that tune how an MVFv3 bundle is converted to MVFv2.\n */\nexport type ConvertOptions = {\n\t/**\n\t * How polygon centers (`center` of spaces, obstructions, and areas) are\n\t * computed. Defaults to `'center-of-mass'` (the area-weighted centroid that\n\t * matches natively generated Maker MVFv2 bundles). Use `'visual-center'` for\n\t * the `polylabel` pole of inaccessibility, or pass a {@link CenterCalculator}\n\t * for a custom implementation.\n\t *\n\t * @default 'center-of-mass'\n\t */\n\tcenterStrategy?: CenterStrategy;\n};\n\nexport type BuilderOptions = {\n\tgeometryMaps: GeometryMaps;\n\tnodesByGeometryId: Map<GeometryId, NodeId[]>;\n\tgeometryFeatureById: Map<GeometryId, GeometryFeature>;\n\tnavigationFlags: NavigationFlagDeclarations;\n\tincomingEdgesByNodeId: Map<NodeId, Array<NodeNeighbor>>;\n\tnodesById: Map<NodeId, NodeFeature>;\n\tcenterCalculator: CenterCalculator;\n};\nexport function buildBuilderOptions(\n\tv3: Partial<MVFv2_STANDARD_MVFv3>,\n\tconvertOptions?: ConvertOptions,\n): BuilderOptions {\n\tconst { nodesByGeometryId, incomingEdgesByNodeId, nodesById } = buildNodeMaps(v3);\n\tconst geometryMaps = createGeometryMaps(v3);\n\tconst geometryFeatureById = buildGeometryFeatureById(v3);\n\tconst navigationFlags = v3.navigationFlags ?? {};\n\tconst options: BuilderOptions = {\n\t\tgeometryMaps,\n\t\tnodesByGeometryId,\n\t\tgeometryFeatureById,\n\t\tnavigationFlags,\n\t\tincomingEdgesByNodeId,\n\t\tnodesById,\n\t\tcenterCalculator: resolveCenterCalculator(convertOptions?.centerStrategy),\n\t};\n\n\treturn options;\n}\n\nexport function buildNodeMaps(v3: Pick<MVFv2_STANDARD_MVFv3, 'nodes'>): {\n\tnodesByGeometryId: Map<GeometryId, NodeId[]>;\n\tincomingEdgesByNodeId: Map<NodeId, Array<NodeNeighbor>>;\n\tnodesById: Map<NodeId, NodeFeature>;\n} {\n\tconst nodesByGeometryId: Map<GeometryId, NodeId[]> = new Map();\n\tconst incomingEdgesByNodeId: Map<NodeId, Array<NodeNeighbor>> = new Map();\n\tconst nodesById: Map<NodeId, NodeFeature> = new Map();\n\tfor (const floorNodes of Object.values(v3.nodes ?? {})) {\n\t\tfor (const node of floorNodes?.features ?? []) {\n\t\t\tnodesById.set(node.properties.id, node);\n\t\t\tif (node.properties.geometryIds.length > 0) {\n\t\t\t\tfor (const geometryId of node.properties.geometryIds) {\n\t\t\t\t\tconst existingNodes = nodesByGeometryId.get(geometryId) ?? [];\n\t\t\t\t\texistingNodes.push(node.properties.id);\n\t\t\t\t\tnodesByGeometryId.set(geometryId, existingNodes);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (node.properties.neighbors.length > 0) {\n\t\t\t\tfor (const neighbor of node.properties.neighbors) {\n\t\t\t\t\tconst existing = incomingEdgesByNodeId.get(neighbor.id);\n\t\t\t\t\tif (existing != null) {\n\t\t\t\t\t\texisting.push(neighbor);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tincomingEdgesByNodeId.set(neighbor.id, [neighbor]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn { nodesByGeometryId, incomingEdgesByNodeId, nodesById };\n}\n\nexport function buildGeometryFeatureById(\n\tv3: Partial<Pick<MVFv2_STANDARD_MVFv3, 'geometry'>>,\n): Map<GeometryId, GeometryFeature> {\n\tconst geometryFeatureById: Map<GeometryId, GeometryFeature> = new Map();\n\tfor (const floorGeometry of Object.values(v3.geometry ?? {})) {\n\t\tfor (const geometry of floorGeometry?.features ?? []) {\n\t\t\tgeometryFeatureById.set(geometry.properties.id, geometry);\n\t\t}\n\t}\n\treturn geometryFeatureById;\n}\n","import { typedEntries } from '@mappedin/mvf-core/utils/typed-entries';\nimport type { AnnotationCollection, AnnotationProperties } from '../../extensions/annotation.js';\nimport type { ParsedMVF } from '../../types/bundle.js';\nimport type { MVFv2_STANDARD_MVFv3 } from '../index.js';\n\nexport type V3Annotations = Pick<MVFv2_STANDARD_MVFv3, 'annotations' | 'annotationSymbols' | 'geometry'>;\nexport type V2Annotations = Pick<ParsedMVF, 'annotation'>;\n\nexport function buildAnnotations(v3: V3Annotations, _: Record<string, unknown>): V2Annotations {\n\tif (!v3.annotations || !v3.annotationSymbols || !v3.geometry) {\n\t\treturn {};\n\t}\n\n\tconst v2Annotations: V2Annotations['annotation'] = {};\n\n\tfor (const [floorId, annotations] of typedEntries(v3.annotations)) {\n\t\tif (\n\t\t\t!annotations ||\n\t\t\tannotations.length === 0 ||\n\t\t\t!v3.geometry[floorId] ||\n\t\t\tv3.geometry[floorId].features.length === 0\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst geometryById = new Map(v3.geometry[floorId].features.map((g) => [g.properties.id, g]));\n\n\t\tconst v2AnnotationCollection: AnnotationCollection = {\n\t\t\ttype: 'FeatureCollection',\n\t\t\tfeatures: [],\n\t\t};\n\n\t\tfor (const v3Annotation of annotations) {\n\t\t\tconst geometry = geometryById.get(v3Annotation.geometryId);\n\t\t\tif (!geometry || geometry.geometry.type !== 'Point') {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst v2AnnotationProperties: AnnotationProperties = {\n\t\t\t\tid: v3Annotation.id,\n\t\t\t\texternalId: v3Annotation.externalId,\n\t\t\t\tsymbolId: v3Annotation.symbolKey,\n\t\t\t};\n\n\t\t\tv2AnnotationCollection.features.push({\n\t\t\t\ttype: 'Feature',\n\t\t\t\tgeometry: geometry.geometry,\n\t\t\t\tproperties: v2AnnotationProperties,\n\t\t\t});\n\t\t}\n\n\t\tv2Annotations[floorId] = v2AnnotationCollection;\n\t}\n\n\treturn {\n\t\tannotation: v2Annotations,\n\t};\n}\n","import type { Connection } from '@mappedin/mvf-connections';\nimport { CONNECTION_TYPE } from '@mappedin/mvf-connections/values';\nimport type { FloorId, GeometryFeature } from '@mappedin/mvf-core';\nimport type { NavigationFlagDeclaration } from '@mappedin/mvf-navigation-flags';\nimport { hasFlag } from '@mappedin/mvf-navigation-flags/utils';\nimport { WELL_KNOWN_FLAGS } from '@mappedin/mvf-navigation-flags/well-known-flags';\nimport type { ParsedMVF } from '../../types/bundle.js';\nimport type { EntranceFeature } from '../../types/core.js';\nimport type { BuilderOptions } from '../builderOptions.js';\nimport { someFlags } from '../converterUtils.js';\nimport type { MVFv2_STANDARD_MVFv3 } from '../index.js';\n\nexport type V3Connections = Pick<MVFv2_STANDARD_MVFv3, 'connections' | 'navigationFlags' | 'nodes' | 'geometry'>;\nexport type V2Connections = Pick<ParsedMVF, 'connection.json' | 'entrance'>;\nexport type V2Connection = V2Connections['connection.json'][number];\n\nexport function buildConnections(\n\tv3: V3Connections,\n\t{ nodesByGeometryId }: Pick<BuilderOptions, 'nodesByGeometryId'>,\n): V2Connections {\n\tconst v2: V2Connections = {\n\t\t'connection.json': [],\n\t\tentrance: {},\n\t};\n\n\tconst ACCESSIBLE_FLAG = v3.navigationFlags?.[WELL_KNOWN_FLAGS.accessible];\n\tconst OUTDOORS_FLAG = v3.navigationFlags?.[WELL_KNOWN_FLAGS.outdoors];\n\tconst geometryFeatureById = new Map(\n\t\tObject.values(v3.geometry ?? {})\n\t\t\t.flatMap((floor) => floor?.features ?? [])\n\t\t\t.map((f) => [f.properties.id, f]),\n\t);\n\n\tfor (const connection of v3.connections ?? []) {\n\t\t// Convert line string doors to entrances, except when they transition\n\t\t// between floors (as these then become \"real\" connections). Keep CMS\n\t\t// style point doors\n\t\tif (isLineDoor(connection, geometryFeatureById) && !doesConnectionTransitionFloors(connection)) {\n\t\t\tconst entrances = buildEntranceFeaturesFromConnection(\n\t\t\t\tconnection,\n\t\t\t\tgeometryFeatureById,\n\t\t\t\tnodesByGeometryId,\n\t\t\t\tOUTDOORS_FLAG,\n\t\t\t);\n\t\t\tfor (const [floorId, entrance] of entrances) {\n\t\t\t\tif (!v2.entrance[floorId]) {\n\t\t\t\t\tv2.entrance[floorId] = {\n\t\t\t\t\t\ttype: 'FeatureCollection',\n\t\t\t\t\t\tfeatures: [],\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tv2.entrance[floorId].features.push(entrance);\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\t// A connection is accessible if it has the accessible flag set for some entrance and exit\n\t\tconst accessible =\n\t\t\tACCESSIBLE_FLAG != undefined &&\n\t\t\tconnection.entrances.some((e) => hasFlag(e, ACCESSIBLE_FLAG)) &&\n\t\t\tconnection.exits.some((e) => hasFlag(e, ACCESSIBLE_FLAG));\n\n\t\t// Asymmetric connections are not supported in V2, so we just give it all the nodes\n\t\tconst nodes = Array.from(\n\t\t\tnew Set(\n\t\t\t\t[\n\t\t\t\t\t...connection.entrances.map((e) => nodesByGeometryId.get(e.geometryId)),\n\t\t\t\t\t...connection.exits.map((e) => nodesByGeometryId.get(e.geometryId)),\n\t\t\t\t]\n\t\t\t\t\t.flat()\n\t\t\t\t\t.filter((n) => n != undefined),\n\t\t\t),\n\t\t);\n\n\t\t// Similar to accessibility, we assume a flag is set for the connection as a whole if any of its entrances or exits have it set\n\t\tconst flags = someFlags([...connection.entrances.map((e) => e.flags), ...connection.exits.map((e) => e.flags)]);\n\n\t\tconst v2Connection: V2Connection = {\n\t\t\tid: connection.id,\n\t\t\texternalId: connection.details?.externalId ?? '',\n\t\t\ttype: connection.type,\n\t\t\taccessible,\n\t\t\tnodes,\n\t\t\tflags,\n\t\t};\n\t\tif (connection.details?.name) {\n\t\t\tv2Connection.details = { name: connection.details.name };\n\t\t}\n\t\tif (connection.extra) {\n\t\t\tv2Connection.extra = connection.extra;\n\t\t}\n\n\t\tv2['connection.json'].push(v2Connection);\n\t}\n\treturn v2;\n}\n\nexport function isLineDoor(connection: Connection, geometryFeatureById: Map<string, GeometryFeature>): boolean {\n\treturn (\n\t\tconnection.type == CONNECTION_TYPE.door &&\n\t\tconnection.entrances.every((e) => {\n\t\t\tconst feature = geometryFeatureById.get(e.geometryId);\n\t\t\t// It's not clear what to do in MVFv2 if this was a multi-line string. Probably not multiple identical entrances.\n\t\t\treturn feature?.geometry.type === 'LineString';\n\t\t})\n\t);\n}\n\nexport function doesConnectionTransitionFloors(connection: Connection): boolean {\n\tif (connection.entrances.length === 0 || connection.exits.length === 0) {\n\t\t// If a connection can't be traversed, it can't transition floors\n\t\treturn false;\n\t}\n\tconst visitedFloors = new Set([\n\t\t...connection.entrances.map((e) => e.floorId),\n\t\t...connection.exits.map((e) => e.floorId),\n\t]);\n\treturn visitedFloors.size >= 2;\n}\n\n/**\n * This builds one or more entrances from a connection. It will only produce anything if isLineDoor\n * is true for this connection, but it doesn't rely on that function.\n *\n * It will produce tuples of [FloorId, EntranceFeature[]] for every entrance line string entrance in the connection\n * in the connection.\n * @param connection\n * @param geometryFeatureById\n */\nexport function buildEntranceFeaturesFromConnection(\n\tconnection: Connection,\n\tgeometryFeatureById: Map<string, GeometryFeature>,\n\tnodesByGeometryId: BuilderOptions['nodesByGeometryId'],\n\toutdoorsFlag?: NavigationFlagDeclaration,\n): [FloorId, EntranceFeature][] {\n\tif (connection.type !== CONNECTION_TYPE.door) {\n\t\treturn [];\n\t}\n\n\tconst entrances: [FloorId, EntranceFeature][] = [];\n\n\tfor (const entrance of connection.entrances) {\n\t\tconst geometryFeature = geometryFeatureById.get(entrance.geometryId);\n\t\tif (geometryFeature?.geometry.type === 'LineString') {\n\t\t\tconst entranceFeature: EntranceFeature = {\n\t\t\t\ttype: 'Feature',\n\t\t\t\tgeometry: geometryFeature.geometry,\n\t\t\t\tproperties: {\n\t\t\t\t\tid: connection.id, // Entrance IDs will not be unique. Is that a problem?\n\t\t\t\t\texternalId: connection.details?.externalId ?? '',\n\t\t\t\t\tisExterior: isExterior(connection, outdoorsFlag),\n\t\t\t\t},\n\t\t\t};\n\t\t\tconst details = connection.details;\n\t\t\tif (details) {\n\t\t\t\tentranceFeature.properties.details = {\n\t\t\t\t\tname: details.name,\n\t\t\t\t\tdescription: details.description,\n\t\t\t\t};\n\t\t\t\tif (details.icon) {\n\t\t\t\t\tentranceFeature.properties.details.images = [{ url: details.icon, altText: `${details.name} icon` }];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst nodes = nodesByGeometryId.get(entrance.geometryId);\n\t\t\tif (nodes && nodes.length > 0) {\n\t\t\t\tentranceFeature.properties.node = nodes[0];\n\t\t\t}\n\t\t\tentrances.push([entrance.floorId, entranceFeature]);\n\t\t}\n\t}\n\treturn entrances;\n}\n\n/**\n * A connection is exterior if ANY of it's entrances or exits have the well-known outdoors flag.\n *\n * This also means a connection that is fully outdoors (such as a pedestrian bridge) is also exterior.\n * @param connection\n * @param outdoorsFlag\n * @returns true if the connection goes or comes from the exterior\n */\nexport function isExterior(connection: Connection, outdoorsFlag?: NavigationFlagDeclaration): boolean {\n\treturn (\n\t\tconnection.entrances.some((e) => hasFlag(e, outdoorsFlag)) || connection.exits.some((e) => hasFlag(e, outdoorsFlag))\n\t);\n}\n","import type {\n\tEnterpriseCategory as V3EnterpriseCategory,\n\tEnterpriseCategoryId as V3EnterpriseCategoryId,\n\tEnterpriseLocation as V3EnterpriseLocation,\n\tEnterpriseLocationInstance as V3EnterpriseLocationInstance,\n} from '@mappedin/mvf-cms';\nimport { ENTERPRISE_VENUE_TYPE } from '@mappedin/mvf-cms/values';\nimport type { FloorId } from '@mappedin/mvf-core/identifiers';\nimport { typedEntries } from '@mappedin/mvf-core/utils/typed-entries';\nimport type { Location, LocationCategory, LocationCategoryId, LocationId } from '@mappedin/mvf-locations';\nimport type {\n\tAnchoredFloorTextProperties,\n\tEnterpriseCategoryPriority,\n\tEnterpriseCollection,\n\tEnterpriseFloorText,\n\tEnterpriseLayer,\n\tEnterpriseStyles,\n\tEnterpriseTexture,\n\tFloatingFloorTextProperties,\n\tFloorTextCommonProperties,\n\tFloorTextFeatureCollection,\n\tFloorTextProperties,\n\tEnterpriseCategory as V2EnterpriseCategory,\n\tEnterpriseLocation as V2EnterpriseLocation,\n\tEnterpriseLocationInstance as V2EnterpriseLocationInstance,\n} from '../../extensions/enterprise.js';\nimport type {\n\tAnchoredTextAreaProperties,\n\tBaseTextAreaProperties,\n\tFloatingTextAreaProperties,\n\tTextAreaFeature,\n\tTextAreaFeatureCollection,\n\tTextAreaProperties,\n} from '../../extensions/textArea.js';\nimport type { ParsedMVF } from '../../types/bundle.js';\nimport type { BuilderOptions } from '../builderOptions.js';\nimport { convertLocationCategoryId, convertLocationId, convertLocationInstanceId } from '../converterUtils.js';\nimport type { MVFv2_STANDARD_MVFv3 } from '../index.js';\n\nexport type V3Enterprise = Pick<\n\tMVFv2_STANDARD_MVFv3,\n\t'cms' | 'manifest' | 'locations' | 'locationCategories' | 'defaultStyle' | 'locationInstances'\n>;\nexport type V2Enterprise = Pick<ParsedMVF, 'enterprise' | 'textAreas'>;\n\nexport function buildEnterprise(\n\tv3: V3Enterprise,\n\t{ geometryMaps, nodesByGeometryId }: Pick<BuilderOptions, 'geometryMaps' | 'nodesByGeometryId'>,\n): V2Enterprise {\n\tconst v2Enterprise: EnterpriseCollection = {\n\t\tcategories: [],\n\t\tlocations: [],\n\t\tlocationInstances: [],\n\t\tlayers: [],\n\t\tvenue: {\n\t\t\tslug: '',\n\t\t\tname: '',\n\t\t\texternalId: '',\n\t\t\tdefaultLanguage: {\n\t\t\t\tname: 'English',\n\t\t\t\tcode: 'en',\n\t\t\t},\n\t\t\tlanguages: [],\n\t\t},\n\t};\n\n\t// Enterprise Venue\n\tconst v3Manifest = v3.manifest?.features[0];\n\n\t// Start by filling in what we can off the manifest\n\tif (v3Manifest) {\n\t\tv2Enterprise.venue.defaultFloor = v3Manifest.properties.defaultFloor;\n\t\tv2Enterprise.venue.tzid = v3Manifest.properties.tzid;\n\t\tv2Enterprise.venue.name = v3Manifest.properties.name;\n\t\tv2Enterprise.venue.defaultLanguage = {\n\t\t\tname: v3Manifest.properties.language ?? 'English',\n\t\t\tcode: v3Manifest.properties.language ?? 'en',\n\t\t};\n\t}\n\t//  Then fill in the rest off the enterprise\n\n\tconst v3Venue = v3.cms?.venue;\n\n\tif (v3Venue) {\n\t\tv2Enterprise.venue = {\n\t\t\t...v2Enterprise.venue,\n\t\t\tslug: v3Venue.slug,\n\t\t\tname: v3Venue.details?.name ?? v2Enterprise.venue.name ?? v3Manifest.properties.name,\n\t\t\texternalId: v3Venue.details?.externalId ?? '',\n\t\t\tdefaultLanguage: v3Venue.defaultLanguage,\n\t\t\tlanguages: v3Venue.languages ?? [],\n\t\t\tcountrycode: v3Venue.countrycode,\n\t\t\tcoverImage: v3Venue.coverImage,\n\t\t\tlogo: v3Venue.logo,\n\t\t\ticon: v3Venue.details?.icon,\n\t\t\textra: v3Venue.extra,\n\t\t\tmappedinWebUrl: v3Venue.mappedinWebUrl,\n\t\t\toperationHours: v3Venue.operationHours,\n\t\t\ttopLocations: v3Venue.topLocations,\n\t\t\ttype: v3Venue.type && v3Venue.type in ENTERPRISE_VENUE_TYPE ? v3Venue.type : 'unknown',\n\t\t\tpropertyImage: v3Venue.propertyImage,\n\t\t};\n\t}\n\n\t// Build this for the Enterprise Categories to use later\n\tconst locationsByLocationCategoryId = new Map<LocationCategoryId, LocationId[]>();\n\n\t// Enterprise Locations\n\tconst v3Locations = v3.locations ?? [];\n\tconst v3EnterpriseLocations = v3.cms?.locations ?? [];\n\tconst v3EnterpriseCategories = v3.cms?.categories ?? [];\n\n\t// Create mapping from V3 location category IDs to V2 enterprise category IDs\n\tconst enterpriseCategoryByLocationCategoryId = new Map<LocationCategoryId | undefined, V3EnterpriseCategory>(\n\t\t(v3EnterpriseCategories ?? []).map((cat) => [cat.categoryId, cat]),\n\t);\n\n\tif (v3Locations.length > 0) {\n\t\tconst enterpriseLocationsByLocationId = new Map(\n\t\t\tv3EnterpriseLocations.map((enterpriseLocation) => [enterpriseLocation.locationId, enterpriseLocation]),\n\t\t);\n\t\tfor (const v3Location of v3Locations) {\n\t\t\tconst v3EnterpriseLocation = (enterpriseLocationsByLocationId.get(v3Location.id) ??\n\t\t\t\t{}) as Partial<V3EnterpriseLocation>;\n\t\t\tif (v3Location) {\n\t\t\t\tconst details = v3Location.details;\n\t\t\t\tconst v2EnterpriseLocation: V2EnterpriseLocation = {\n\t\t\t\t\tid:\n\t\t\t\t\t\tv3EnterpriseLocation?.cmsId !== undefined\n\t\t\t\t\t\t\t? `el_${v3EnterpriseLocation?.cmsId}`\n\t\t\t\t\t\t\t: convertLocationId(v3Location.id),\n\t\t\t\t\tname: details.name,\n\t\t\t\t\texternalId: details.externalId ?? '',\n\t\t\t\t\ttype: v3EnterpriseLocation.type ?? 'location',\n\t\t\t\t\tsortOrder: v3EnterpriseLocation.sortOrder ?? 0,\n\t\t\t\t\tamenity: v3EnterpriseLocation.amenity,\n\t\t\t\t\tdescription: details.description,\n\t\t\t\t\textra: v3Location.extra,\n\t\t\t\t\tlinks: v3Location.links,\n\t\t\t\t\toperationHours: v3Location.openingHours,\n\t\t\t\t\tgallery: v3EnterpriseLocation.gallery,\n\t\t\t\t\tlogo: v3Location.logo,\n\t\t\t\t\tshortName: details.shortName,\n\t\t\t\t\tpicture: v3EnterpriseLocation.picture,\n\t\t\t\t\tshowFloatingLabelWhenImagePresent: v3EnterpriseLocation.showFloatingLabelWhenImagePresent,\n\t\t\t\t\tshowLogo: v3EnterpriseLocation.showLogo,\n\t\t\t\t\tsiblingGroups: v3EnterpriseLocation.siblingGroups,\n\t\t\t\t\tstates: v3EnterpriseLocation.states,\n\t\t\t\t\ttags: v3EnterpriseLocation.tags,\n\t\t\t\t\tspaces: [],\n\t\t\t\t\tnodes: [],\n\t\t\t\t\tpolygons: [],\n\t\t\t\t\theaderImage: v3EnterpriseLocation.headerImage,\n\t\t\t\t};\n\n\t\t\t\tif (v3Location.phone) {\n\t\t\t\t\tv2EnterpriseLocation.phone = { number: v3Location.phone };\n\t\t\t\t}\n\t\t\t\tif (v3EnterpriseLocation.primaryCategory) {\n\t\t\t\t\tconst v2EnterpriseCategory = enterpriseCategoryByLocationCategoryId.get(v3EnterpriseLocation.primaryCategory);\n\t\t\t\t\tif (v2EnterpriseCategory) {\n\t\t\t\t\t\tv2EnterpriseLocation.primaryCategory = v2EnterpriseCategory.id;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst social = convertSocials(v3Location.social);\n\n\t\t\t\tif (v3Location.website) {\n\t\t\t\t\tsocial.website = v3Location.website.url;\n\t\t\t\t}\n\t\t\t\tv2EnterpriseLocation.social = social;\n\n\t\t\t\tfor (const anchor of v3Location.geometryAnchors) {\n\t\t\t\t\tconst space = geometryMaps.space.get(anchor.geometryId);\n\t\t\t\t\tconst obstruction = geometryMaps.obstruction.get(anchor.geometryId);\n\t\t\t\t\t// A CMS generated MVFv3 will never have obstruction anchors\n\t\t\t\t\tconst converted = space ?? obstruction;\n\t\t\t\t\tif (converted) {\n\t\t\t\t\t\tconst polygons = new Set<string>(\n\t\t\t\t\t\t\tconverted.features.filter((f) => f.geometry.type === 'Polygon').map((f) => f.properties.id),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tfor (const anchor of converted.anchors) {\n\t\t\t\t\t\t\tif (space != null && converted === space) {\n\t\t\t\t\t\t\t\tv2EnterpriseLocation.spaces.push({\n\t\t\t\t\t\t\t\t\tfloor: anchor.floorId,\n\t\t\t\t\t\t\t\t\tid: anchor.geometryId,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (polygons.has(anchor.geometryId)) {\n\t\t\t\t\t\t\t\tv2EnterpriseLocation.polygons.push({\n\t\t\t\t\t\t\t\t\tmap: anchor.floorId,\n\t\t\t\t\t\t\t\t\tid: anchor.geometryId,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tconst nodes = nodesByGeometryId.get(anchor.geometryId);\n\t\t\t\t\tfor (const node of nodes ?? []) {\n\t\t\t\t\t\tv2EnterpriseLocation.nodes.push({\n\t\t\t\t\t\t\tmap: anchor.floorId,\n\t\t\t\t\t\t\tid: node,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tv2Enterprise.locations.push(v2EnterpriseLocation);\n\n\t\t\t\t// To be used when building enterprise categories\n\t\t\t\tfor (const category of v3Location.categories) {\n\t\t\t\t\tlocationsByLocationCategoryId.set(category, [\n\t\t\t\t\t\t...(locationsByLocationCategoryId.get(category) ?? []),\n\t\t\t\t\t\tv3Location.id,\n\t\t\t\t\t]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Enterprise Location Instances\n\tconst v3EnterpriseLocationInstances = v3.cms?.locationInstances ?? [];\n\tconst v3LocationInstances = v3.locationInstances;\n\tif (v3LocationInstances) {\n\t\tconst v3EnterpriseLocationInstancesByLocationInstanceId = new Map(\n\t\t\tv3EnterpriseLocationInstances.map((instance) => [instance.locationInstanceId, instance]),\n\t\t);\n\t\tconst v2EnterpriseLocationInstances: V2EnterpriseLocationInstance[] = [];\n\n\t\tfor (const v3LocationInstance of v3LocationInstances) {\n\t\t\tconst v3EnterpriseLocationInstance =\n\t\t\t\tv3EnterpriseLocationInstancesByLocationInstanceId.get(v3LocationInstance.id) ??\n\t\t\t\t({} as Partial<V3EnterpriseLocationInstance>);\n\n\t\t\tif (v3LocationInstance) {\n\t\t\t\tconst v2EnterpriseLocationInstance: V2EnterpriseLocationInstance = {\n\t\t\t\t\tid: convertLocationInstanceId(v3LocationInstance.id),\n\t\t\t\t\tparent: v3EnterpriseLocationInstance.parentId ?? convertLocationId(v3LocationInstance.parentId),\n\t\t\t\t\tname: v3LocationInstance.details?.name,\n\t\t\t\t\texternalId: v3LocationInstance.details?.externalId,\n\t\t\t\t\ttype: v3EnterpriseLocationInstance.type,\n\t\t\t\t\tsortOrder: v3EnterpriseLocationInstance.sortOrder,\n\t\t\t\t\tamenity: v3EnterpriseLocationInstance.amenity,\n\t\t\t\t\tdescription: v3LocationInstance.details?.description,\n\t\t\t\t\textra: v3LocationInstance.extra,\n\t\t\t\t\tlinks: v3LocationInstance.links,\n\t\t\t\t\toperationHours: v3LocationInstance.openingHours,\n\t\t\t\t\tgallery: v3EnterpriseLocationInstance.gallery,\n\t\t\t\t\tpicture: v3EnterpriseLocationInstance.picture,\n\t\t\t\t\tshowFloatingLabelWhenImagePresent: v3EnterpriseLocationInstance.showFloatingLabelWhenImagePresent,\n\t\t\t\t\tshowLogo: v3EnterpriseLocationInstance.showLogo,\n\t\t\t\t\tsiblingGroups: v3EnterpriseLocationInstance.siblingGroups,\n\t\t\t\t\tstates: v3EnterpriseLocationInstance.states,\n\t\t\t\t\ttags: v3EnterpriseLocationInstance.tags,\n\t\t\t\t\tlogo: v3LocationInstance.logo,\n\t\t\t\t\tshortName: v3LocationInstance.details?.shortName,\n\t\t\t\t\theaderImage: v3EnterpriseLocationInstance.headerImage,\n\t\t\t\t};\n\t\t\t\tif (v3LocationInstance.phone) {\n\t\t\t\t\tv2EnterpriseLocationInstance.phone = { number: v3LocationInstance.phone };\n\t\t\t\t}\n\t\t\t\tconst social = convertSocials(v3LocationInstance.social ?? []);\n\t\t\t\tif (v3LocationInstance.website) {\n\t\t\t\t\tsocial.website = v3LocationInstance.website.url;\n\t\t\t\t}\n\n\t\t\t\tif (Object.keys(social).length > 0) {\n\t\t\t\t\tv2EnterpriseLocationInstance.social = social;\n\t\t\t\t}\n\t\t\t\tif (v3LocationInstance.geometryAnchors?.length) {\n\t\t\t\t\tconst spaces = v3LocationInstance.geometryAnchors.flatMap(\n\t\t\t\t\t\t(anchor) => geometryMaps.space.get(anchor.geometryId)?.anchors ?? [],\n\t\t\t\t\t);\n\t\t\t\t\tif (spaces.length > 0) {\n\t\t\t\t\t\tv2EnterpriseLocationInstance.spaces = spaces.map((space) => ({\n\t\t\t\t\t\t\tfloor: space.floorId,\n\t\t\t\t\t\t\tid: space.geometryId,\n\t\t\t\t\t\t}));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If we have any geometry anchors, we must have overrides for spaces, polygons, and ndoes.\n\t\t\t\tif (v3LocationInstance.geometryAnchors) {\n\t\t\t\t\tv2EnterpriseLocationInstance.spaces = [];\n\t\t\t\t\tv2EnterpriseLocationInstance.polygons = [];\n\t\t\t\t\tv2EnterpriseLocationInstance.nodes = [];\n\t\t\t\t\tfor (const anchor of v3LocationInstance.geometryAnchors) {\n\t\t\t\t\t\tconst converted = geometryMaps.space.get(anchor.geometryId);\n\t\t\t\t\t\tif (converted) {\n\t\t\t\t\t\t\tconst polygons = new Set<string>(\n\t\t\t\t\t\t\t\tconverted.features.filter((f) => f.geometry.type === 'Polygon').map((f) => f.properties.id),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tfor (const anchor of converted.anchors) {\n\t\t\t\t\t\t\t\tv2EnterpriseLocationInstance.spaces.push({\n\t\t\t\t\t\t\t\t\tfloor: anchor.floorId,\n\t\t\t\t\t\t\t\t\tid: anchor.geometryId,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tif (polygons.has(anchor.geometryId)) {\n\t\t\t\t\t\t\t\t\tv2EnterpriseLocationInstance.polygons.push({\n\t\t\t\t\t\t\t\t\t\tmap: anchor.floorId,\n\t\t\t\t\t\t\t\t\t\tid: anchor.geometryId,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst nodes = nodesByGeometryId.get(anchor.geometryId);\n\t\t\t\t\t\tfor (const node of nodes ?? []) {\n\t\t\t\t\t\t\tv2EnterpriseLocationInstance.nodes.push({\n\t\t\t\t\t\t\t\tmap: anchor.floorId,\n\t\t\t\t\t\t\t\tid: node,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tv2EnterpriseLocationInstances.push(v2EnterpriseLocationInstance);\n\t\t\t}\n\t\t}\n\t\tif (v2EnterpriseLocationInstances.length > 0) {\n\t\t\tv2Enterprise.locationInstances = v2EnterpriseLocationInstances;\n\t\t}\n\t}\n\n\t// Enterprise Categories\n\tconst v3Categories = v3.locationCategories;\n\tif (v3Categories) {\n\t\t// V2 Enterprise Categories have children references to other Enterprise Categories,\n\t\t// but V3 Enterprise categories have a parent to a Location Category, which then has a parent to another Location category.\n\t\t// This means we need to pre-build a map of children.\n\t\tconst v2EnterpriseCategories: V2EnterpriseCategory[] = [];\n\t\tconst v3CategoriesById = new Map<LocationCategoryId | undefined, LocationCategory>(\n\t\t\tv3Categories.map((cat) => [cat.id, cat]),\n\t\t);\n\t\tconst enterpriseCategoryByLocationCategoryId = new Map<LocationCategoryId | undefined, V3EnterpriseCategory>(\n\t\t\t(v3EnterpriseCategories ?? []).map((cat) => [cat.categoryId, cat]),\n\t\t);\n\t\tconst categoryChildren = new Map<LocationCategoryId, LocationCategoryId[]>();\n\n\t\tfor (const v3Category of v3Categories) {\n\t\t\tconst parent = v3CategoriesById.get(v3Category.parent);\n\t\t\tif (parent) {\n\t\t\t\tconst children = categoryChildren.get(parent.id) ?? [];\n\t\t\t\tchildren.push(v3Category.id);\n\t\t\t\tcategoryChildren.set(parent.id, children);\n\t\t\t}\n\t\t}\n\t\t// Now build the actual Enterprise Categories\n\t\tfor (const v3Category of v3Categories) {\n\t\t\tconst v3EnterpriseCategory = enterpriseCategoryByLocationCategoryId.get(v3Category.id);\n\t\t\tif (v3Category) {\n\t\t\t\tconst children = (categoryChildren.get(v3Category.id) ?? []).map(convertLocationCategoryId);\n\n\t\t\t\tconst v2EnterpriseCategory: V2EnterpriseCategory = {\n\t\t\t\t\tid: convertLocationCategoryId(v3Category.id),\n\t\t\t\t\tname: v3Category.details.name,\n\t\t\t\t\texternalId: v3Category.details.externalId ?? '',\n\t\t\t\t\tsortOrder: v3EnterpriseCategory?.sortOrder ?? 0,\n\t\t\t\t\tchildren,\n\t\t\t\t\tlocations: (locationsByLocationCategoryId.get(v3Category.id) ?? []).map(convertLocationId),\n\t\t\t\t\ticon: v3Category.details.icon,\n\t\t\t\t\tpicture: v3EnterpriseCategory?.picture,\n\t\t\t\t\tcolor: v3EnterpriseCategory?.color,\n\t\t\t\t\textra: v3Category.extra,\n\t\t\t\t\ticonFromDefaultList: v3EnterpriseCategory?.iconFromDefaultList,\n\t\t\t\t};\n\t\t\t\tv2EnterpriseCategories.push(v2EnterpriseCategory);\n\t\t\t}\n\t\t}\n\t\tv2Enterprise.categories = v2EnterpriseCategories;\n\n\t\t// Build the category priorities\n\t\tconst v2CategoryPriorities: EnterpriseCategoryPriority = {};\n\t\tfor (const v3Location of v3Locations) {\n\t\t\tv2CategoryPriorities[convertLocationId(v3Location.id)] = v3Location.categories\n\t\t\t\t.map(convertLocationCategoryId)\n\t\t\t\t.filter((e): e is V3EnterpriseCategoryId => e !== undefined);\n\t\t}\n\t\tv2Enterprise.categoryPriorities = v2CategoryPriorities;\n\t}\n\n\t// Build the enterprise styles\n\tconst v2EnterpriseStyles: EnterpriseStyles = {};\n\tfor (const [styleId, style] of Object.entries(v3.defaultStyle ?? {})) {\n\t\t// 0 or undefined buffers can be ignored. Positive or negative buffers get converted to edgeOffset.\n\t\tif (style.buffer) {\n\t\t\tconst convertedAnchors = style.geometryAnchors.flatMap(\n\t\t\t\t(anchor) => geometryMaps.space.get(anchor.geometryId)?.anchors ?? [],\n\t\t\t);\n\n\t\t\tv2EnterpriseStyles[styleId] = {\n\t\t\t\tedgeOffset: style.buffer,\n\t\t\t\tgeometryAnchors: convertedAnchors,\n\t\t\t};\n\t\t}\n\t}\n\tif (Object.keys(v2EnterpriseStyles).length > 0) {\n\t\tv2Enterprise.enterpriseStyles = v2EnterpriseStyles;\n\t}\n\n\t// Build the enterprise layers\n\tconst v2EnterpriseLayers: Map<string, EnterpriseLayer> = new Map();\n\tfor (const layers of Object.values(v3.cms?.layers ?? {})) {\n\t\tif (!layers) {\n\t\t\tcontinue;\n\t\t}\n\t\tfor (const [geometryId, layer] of typedEntries(layers)) {\n\t\t\t// This shouldn't happen, but typescript doesn't seem to know that\n\t\t\tif (typeof layer !== 'string') {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst v2EnterpriseLayer: EnterpriseLayer = v2EnterpriseLayers.get(layer) ?? {\n\t\t\t\tname: layer,\n\t\t\t\tid: `ely_${layer}`,\n\t\t\t\tspaces: [],\n\t\t\t};\n\t\t\tv2EnterpriseLayer.spaces.push(\n\t\t\t\t...(geometryMaps.space.get(geometryId)?.anchors.map((anchor) => ({\n\t\t\t\t\tfloorId: anchor.floorId,\n\t\t\t\t\tspaceId: anchor.geometryId,\n\t\t\t\t})) ?? []),\n\t\t\t);\n\t\t\tv2EnterpriseLayers.set(layer, v2EnterpriseLayer);\n\t\t}\n\t}\n\tif (v2EnterpriseLayers.size > 0) {\n\t\tv2Enterprise.layers = Array.from(v2EnterpriseLayers.values());\n\t}\n\n\t// Build the enterprise textures\n\tconst v2EnterpriseTextures: EnterpriseTexture[] = [];\n\tfor (const textures of Object.values(v3.cms?.textures ?? {})) {\n\t\tfor (const texture of textures) {\n\t\t\tconst anchors = geometryMaps.space.get(texture.geometryId)?.anchors;\n\t\t\t// No anchor,s or Unsupported texture types\n\t\t\tif (!anchors || anchors.length < 1 || texture.face === 'unknown' || texture.surface === 'unknown') {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tv2EnterpriseTextures.push({\n\t\t\t\trepeat: texture.repeat,\n\t\t\t\toffset: texture.offset,\n\t\t\t\trotation: texture.rotation,\n\t\t\t\tpath: texture.path,\n\t\t\t\tface: texture.face,\n\t\t\t\tsurface: texture.surface,\n\t\t\t\tbounds: texture.bounds,\n\t\t\t\tgeometryAnchors: anchors,\n\t\t\t});\n\t\t}\n\t}\n\tif (v2EnterpriseTextures.length > 0) {\n\t\tv2Enterprise.textures = v2EnterpriseTextures;\n\t}\n\n\t// Build the enterprise floor text\n\tconst v2EnterpriseFloorText: EnterpriseFloorText = {};\n\tfor (const [floorId, floorText] of Object.entries(v3.cms?.floorText ?? {})) {\n\t\tconst v2FloorTextFeatureCollection: FloorTextFeatureCollection = {\n\t\t\ttype: 'FeatureCollection',\n\t\t\tfeatures: [],\n\t\t};\n\t\tfor (const feature of floorText.features) {\n\t\t\tif (feature.properties.align === 'unknown') {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst commonProperties: FloorTextCommonProperties = {\n\t\t\t\talign: feature.properties.align as 'left' | 'center' | 'right',\n\t\t\t\tcolor: feature.properties.color,\n\t\t\t\tfontFamily: feature.properties.fontFamily,\n\t\t\t\tfontSize: feature.properties.fontSize,\n\t\t\t\trotation: feature.properties.rotation,\n\t\t\t\ttext: feature.properties.text,\n\t\t\t\tvisible: feature.properties.visible,\n\t\t\t};\n\t\t\tif ('geometryId' in feature.properties) {\n\t\t\t\t(commonProperties as AnchoredFloorTextProperties).geometryId = feature.properties.geometryId;\n\t\t\t} else {\n\t\t\t\t(commonProperties as FloatingFloorTextProperties).verticalOffset = feature.properties.verticalOffset;\n\t\t\t}\n\t\t\tv2FloorTextFeatureCollection.features.push({\n\t\t\t\ttype: 'Feature',\n\t\t\t\tgeometry: feature.geometry,\n\t\t\t\tproperties: commonProperties as FloorTextProperties,\n\t\t\t});\n\t\t}\n\t\tif (v2FloorTextFeatureCollection.features.length > 0) {\n\t\t\tv2EnterpriseFloorText[floorId] = v2FloorTextFeatureCollection;\n\t\t}\n\t}\n\tif (Object.keys(v2EnterpriseFloorText).length > 0) {\n\t\tv2Enterprise.floorText = v2EnterpriseFloorText;\n\t}\n\n\tconst result: V2Enterprise = { enterprise: v2Enterprise };\n\n\t// Build regular v2 text areas from enterprise text areas\n\tif (v3.cms?.textAreas) {\n\t\tconst v2TextAreas: { [floorId: FloorId]: TextAreaFeatureCollection } = {};\n\t\tfor (const [floorId, floorText] of typedEntries(v3.cms.textAreas)) {\n\t\t\tconst v2FloorTextFeatureCollection: TextAreaFeatureCollection = {\n\t\t\t\ttype: 'FeatureCollection',\n\t\t\t\tfeatures: [],\n\t\t\t};\n\t\t\tfor (const feature of floorText.features) {\n\t\t\t\tif (feature.properties.align === 'unknown') {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst commonProperties: BaseTextAreaProperties = {\n\t\t\t\t\talign: feature.properties.align as 'near' | 'center',\n\t\t\t\t\tmaxWidth: feature.properties.maxWidth,\n\t\t\t\t\tmaxHeight: feature.properties.maxHeight,\n\t\t\t\t\trotation: feature.properties.rotation,\n\t\t\t\t};\n\t\t\t\tif ('geometryId' in feature.properties) {\n\t\t\t\t\t(commonProperties as AnchoredTextAreaProperties).anchorId = feature.properties.geometryId;\n\t\t\t\t} else {\n\t\t\t\t\t(commonProperties as FloatingTextAreaProperties).verticalOffset = feature.properties.verticalOffset;\n\t\t\t\t}\n\t\t\t\tconst v2FloorTextFeature: TextAreaFeature = {\n\t\t\t\t\ttype: 'Feature',\n\t\t\t\t\tgeometry: feature.geometry,\n\t\t\t\t\tproperties: commonProperties as TextAreaProperties,\n\t\t\t\t};\n\t\t\t\tv2FloorTextFeatureCollection.features.push(v2FloorTextFeature);\n\t\t\t}\n\t\t\tv2TextAreas[floorId] = v2FloorTextFeatureCollection;\n\t\t}\n\t\tresult.textAreas = v2TextAreas;\n\t}\n\treturn result;\n}\n\nconst SUPPORTED_SOCIALS = ['facebook', 'instagram', 'twitter'] as const;\nexport function convertSocials(v3Socials: Location['social']): NonNullable<V2EnterpriseLocation['social']> {\n\tconst v2Socials: NonNullable<V2EnterpriseLocation['social']> = {};\n\tfor (const { name, url } of v3Socials) {\n\t\tconst lowerName = name.toLowerCase() as (typeof SUPPORTED_SOCIALS)[number];\n\t\tif (SUPPORTED_SOCIALS.includes(lowerName)) {\n\t\t\tv2Socials[lowerName] = url;\n\t\t}\n\t}\n\treturn v2Socials;\n}\n","import { typedEntries } from '@mappedin/mvf-core/utils/typed-entries';\nimport type { FloorStackId } from '@mappedin/mvf-floor-stacks';\nimport type { ParsedMVF } from '../../types/bundle.js';\nimport type { BuilderOptions } from '../builderOptions.js';\nimport type { MVFv2_STANDARD_MVFv3 } from '../index.js';\n\nexport type V3Facade = Pick<MVFv2_STANDARD_MVFv3, 'facade'>;\nexport type V2Facade = Pick<ParsedMVF, 'facade'>;\n\nconst convertFloorStackIdToFacadeId = (floorStackId: FloorStackId) => `fc_${floorStackId.slice(3)}`;\n\nexport function buildFacade(v3: V3Facade, { geometryMaps }: Pick<BuilderOptions, 'geometryMaps'>): V2Facade {\n\tif (!v3.facade) {\n\t\treturn {};\n\t}\n\n\tconst v2: V2Facade = {};\n\n\tconst v2FacadeCollection: V2Facade['facade'] = {};\n\n\tfor (const [floorId, v3Facades] of typedEntries(v3.facade)) {\n\t\tif (!v3Facades) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tfor (const v3Facade of Object.values(v3Facades)) {\n\t\t\tconst { floorStackId, geometryIds } = v3Facade;\n\t\t\tconst facadeId = convertFloorStackIdToFacadeId(floorStackId);\n\n\t\t\tv2FacadeCollection[floorStackId] ??= {\n\t\t\t\tid: facadeId,\n\t\t\t\tspaces: [],\n\t\t\t};\n\n\t\t\tv2FacadeCollection[floorStackId].spaces.push(\n\t\t\t\t...geometryIds.map((geometryId) => ({\n\t\t\t\t\tfloorId,\n\t\t\t\t\tspaceId: geometryMaps.space.get(geometryId)?.ids[0] ?? '',\n\t\t\t\t})),\n\t\t\t);\n\t\t}\n\t}\n\n\tif (Object.keys(v2FacadeCollection).length > 0) {\n\t\tv2.facade = v2FacadeCollection;\n\t}\n\treturn v2;\n}\n","import type { ParsedMVF } from '../../types/bundle.ts';\nimport type { BuilderOptions } from '../builderOptions.js';\nimport type { MVFv2_STANDARD_MVFv3 } from '../index.ts';\n\nexport type V3Floors = Pick<MVFv2_STANDARD_MVFv3, 'floors'>;\nexport type V2Floors = Pick<ParsedMVF, 'floor.geojson' | 'map.geojson'>;\n\nexport function buildFloors(v3: V3Floors, _builderOptions: Partial<BuilderOptions> = {}): V2Floors {\n\tconst floors: V2Floors['floor.geojson'] = {\n\t\ttype: 'FeatureCollection',\n\t\tfeatures: [],\n\t};\n\n\tconst maps: V2Floors['map.geojson'] = [];\n\n\tfor (const floor of v3.floors.features) {\n\t\tmaps.push({\n\t\t\tid: floor.properties.id,\n\t\t\texternalId: floor.properties.details?.externalId ?? '',\n\t\t\televation: floor.properties.elevation,\n\t\t\tname: floor.properties.details?.name ?? '',\n\t\t\tshortName: floor.properties.details?.shortName ?? '',\n\t\t\tsubtitle: floor.properties.subtitle,\n\t\t\tmaxHeight: floor.properties.maxHeight,\n\t\t});\n\n\t\tfloors.features.push({\n\t\t\ttype: 'Feature',\n\t\t\tgeometry: floor.geometry,\n\t\t\tproperties: {\n\t\t\t\tid: floor.properties.id,\n\t\t\t\texternalId: floor.properties.details?.externalId ?? '',\n\t\t\t\televation: floor.properties.elevation,\n\t\t\t\tname: floor.properties.details?.name ?? '',\n\t\t\t\tshortName: floor.properties.details?.shortName ?? '',\n\t\t\t\tsubtitle: floor.properties.subtitle,\n\t\t\t\tmaxHeight: floor.properties.maxHeight,\n\t\t\t},\n\t\t});\n\t}\n\treturn {\n\t\t'floor.geojson': floors,\n\t\t'map.geojson': maps,\n\t};\n}\n","import { typedEntries } from '@mappedin/mvf-core/utils/typed-entries';\nimport type {\n\tAnchoredImageFeature,\n\tFloatingImageFeature,\n\tFloorImageFeature,\n\tFloorImageFeatureCollection,\n} from '../../extensions/floorImage.js';\nimport type { ParsedMVF } from '../../types/bundle.js';\nimport type { BuilderOptions } from '../builderOptions.js';\nimport type { MVFv2_STANDARD_MVFv3 } from '../index.js';\n\nexport type V3FloorImages = Pick<MVFv2_STANDARD_MVFv3, 'floorImages'>;\nexport type V2FloorImages = Pick<ParsedMVF, 'floorImages'>;\nexport type V2FloorImage = FloorImageFeature;\n\nexport function buildFloorImages(\n\tv3: V3FloorImages,\n\t{ geometryMaps }: Pick<BuilderOptions, 'geometryMaps'>,\n): V2FloorImages {\n\tconst v2: V2FloorImages = {};\n\n\tconst v2FloorImages: V2FloorImages['floorImages'] = {};\n\n\tfor (const [floorId, v3FloorImageCollection] of typedEntries(v3.floorImages ?? {})) {\n\t\tconst v2FloorImageCollection: FloorImageFeatureCollection = {\n\t\t\tfeatures: [],\n\t\t\ttype: 'FeatureCollection',\n\t\t};\n\n\t\tfor (const v3FloorImage of v3FloorImageCollection?.features ?? []) {\n\t\t\tif ('verticalOffset' in v3FloorImage.properties) {\n\t\t\t\tv2FloorImageCollection.features.push(v3FloorImage as FloatingImageFeature);\n\t\t\t} else {\n\t\t\t\tconst { geometryId, ...rest } = v3FloorImage.properties;\n\t\t\t\t// There's no way to assign an image to part of a multi-part geometry, so pulling the first ID is the best we can do\n\t\t\t\tconst anchorId = geometryMaps.space.get(geometryId)?.ids[0] ?? geometryMaps.obstruction.get(geometryId)?.ids[0];\n\t\t\t\tif (!anchorId) {\n\t\t\t\t\t// Images can only be anchored to spaces or obstructions, so if we don't have an anchor, skip it\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst feature: AnchoredImageFeature = {\n\t\t\t\t\tgeometry: v3FloorImage.geometry,\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\t...rest,\n\t\t\t\t\t\tanchorId,\n\t\t\t\t\t},\n\t\t\t\t\ttype: v3FloorImage.type,\n\t\t\t\t};\n\n\t\t\t\tv2FloorImageCollection.features.push(feature);\n\t\t\t}\n\t\t}\n\t\tv2FloorImages[floorId] = v2FloorImageCollection;\n\t}\n\tif (Object.keys(v2FloorImages).length > 0) {\n\t\tv2.floorImages = v2FloorImages;\n\t}\n\n\treturn v2;\n}\n","import type { ParsedMVF } from '../../types/bundle.js';\nimport type { BuilderOptions } from '../builderOptions.js';\nimport type { MVFv2_STANDARD_MVFv3 } from '../index.js';\n\nexport type V3FloorStacks = Pick<MVFv2_STANDARD_MVFv3, 'floorStacks' | 'outdoors'>;\nexport type V2FloorStacks = Pick<ParsedMVF, 'floorstack.json' | 'mapstack.geojson'>;\nexport type V2FloorStack = NonNullable<V2FloorStacks['floorstack.json']>[number];\nexport type V2MapStack = NonNullable<V2FloorStacks['mapstack.geojson']>[number];\nexport function buildFloorStacks(v3: V3FloorStacks, _builderOptions: Partial<BuilderOptions> = {}): V2FloorStacks {\n\tconst floorStacks: V2FloorStacks['floorstack.json'] = [];\n\n\tfor (const floorStack of v3?.floorStacks ?? []) {\n\t\tconst v2FloorStack: V2FloorStack = {\n\t\t\tid: floorStack.id,\n\t\t\tfloors: floorStack.floors,\n\t\t\tmaps: floorStack.floors,\n\t\t\texternalId: floorStack.details?.externalId ?? '',\n\t\t\tname: floorStack.details?.name ?? '',\n\t\t\tshortName: floorStack.details?.shortName ?? '',\n\t\t\ttype: 'Building',\n\t\t};\n\t\tif (floorStack.defaultFloor) {\n\t\t\tv2FloorStack.defaultFloor = floorStack.defaultFloor;\n\t\t}\n\n\t\tfloorStacks.push(v2FloorStack);\n\t}\n\n\tif (v3.outdoors && v3.outdoors.floors.length > 0) {\n\t\tconst v2Outdoors: V2FloorStack = {\n\t\t\tid: 'outdoors',\n\t\t\tfloors: v3.outdoors.floors,\n\t\t\tmaps: v3.outdoors.floors,\n\t\t\ttype: 'Outdoor',\n\t\t\tname: 'Outdoors',\n\t\t\texternalId: 'outdoors',\n\t\t};\n\t\tfloorStacks.push(v2Outdoors);\n\t}\n\n\tconst v2: V2FloorStacks = {\n\t\t'floorstack.json': floorStacks,\n\t\t'mapstack.geojson': floorStacks,\n\t};\n\n\treturn v2;\n}\n","import type { GeometryId } from '@mappedin/mvf-core/identifiers';\nimport { typedKeys } from '@mappedin/mvf-core/utils/typed-keys';\nimport type { DefaultStyleCollection } from '@mappedin/mvf-default-style';\nimport type { Area, AreaId } from '../../extensions/area.js';\nimport type { WindowFeature, WindowId } from '../../extensions/window.js';\nimport type { ParsedMVF } from '../../types/bundle.ts';\nimport type { NodeId, ObstructionFeature, ObstructionId, SpaceFeature, SpaceId } from '../../types/core.js';\nimport type { Feature, Geometry, Polygon } from '../../types/geojson.js';\nimport type { BuilderOptions } from '../builderOptions.js';\nimport { type PartiallyTransformedGeometryFeature, convertNodeToSpaceId, toObstructionId } from '../converterUtils.js';\nimport { type CenterCalculator, centerOfMass } from '../geoCenter.js';\nimport type { MVFv2_STANDARD_MVFv3 } from '../index.ts';\n\nexport type V3Geometry = Pick<MVFv2_STANDARD_MVFv3, 'geometry' | 'defaultStyle'>;\nexport type V2Geometry = Pick<ParsedMVF, 'space' | 'obstruction' | 'area' | 'window'>;\n\n// Helper function to check if a feature has a Polygon geometry\nfunction isPolygonFeature(feature: Feature<Geometry, unknown>): feature is Feature<Polygon, unknown> {\n\treturn feature?.geometry?.type === 'Polygon';\n}\n\nexport function buildGeometry(\n\tv3: V3Geometry,\n\t{\n\t\tgeometryMaps,\n\t\tnodesByGeometryId,\n\t\tnodesById,\n\t\tcenterCalculator = centerOfMass,\n\t}: Pick<BuilderOptions, 'geometryMaps' | 'nodesByGeometryId' | 'nodesById'> &\n\t\tPartial<Pick<BuilderOptions, 'centerCalculator'>>,\n): V2Geometry {\n\tconst footprintGeometryIds = calculateFootprintGeometry(v3.defaultStyle);\n\tconst spaces: V2Geometry['space'] = {};\n\tconst obstructions: V2Geometry['obstruction'] = {};\n\tconst areas: V2Geometry['area'] = {};\n\tconst windows: V2Geometry['window'] = {};\n\tfor (const floorId of typedKeys(v3.geometry)) {\n\t\tconst floorFeatureCollection = v3.geometry[floorId];\n\t\tif (!floorFeatureCollection) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst spaceFeatures: (SpaceFeature | null)[] = [];\n\t\tconst obstructionFeatures: (ObstructionFeature | null)[] = [];\n\t\tconst areaFeatures: (Area | null)[] = [];\n\t\tconst windowFeatures: (WindowFeature | null)[] = [];\n\t\tfor (const feature of floorFeatureCollection.features) {\n\t\t\tconst id = feature.properties.id;\n\t\t\tconst isFootprint = footprintGeometryIds.has(id);\n\n\t\t\tconst nodes = nodesByGeometryId.get(id) ?? [];\n\n\t\t\tfor (const space of geometryMaps.space.get(id)?.features ?? []) {\n\t\t\t\tspaceFeatures.push(buildSpace(space, nodes, centerCalculator));\n\t\t\t}\n\n\t\t\tfor (const obstruction of geometryMaps.obstruction.get(id)?.features ?? []) {\n\t\t\t\tobstructionFeatures.push(buildObstruction(obstruction, isFootprint, centerCalculator));\n\t\t\t\tif (geometryMaps.object.has(id)) {\n\t\t\t\t\t/**\n\t\t\t\t\t * Objects in MVFv2 don't have destination nodes like spaces do. So in order to navigate to objects in MVFv2,\n\t\t\t\t\t * we need to create entrance spaces for each of its nodes, where the externalId is the ID of the object.\n\t\t\t\t\t */\n\t\t\t\t\tconst entranceNodeIds = nodesByGeometryId.get(id) ?? [];\n\t\t\t\t\tconst entranceNodes = entranceNodeIds.map((nodeId) => nodesById.get(nodeId)).filter((x) => x != null);\n\t\t\t\t\tfor (const node of entranceNodes) {\n\t\t\t\t\t\tconst entranceSpace = buildSpace(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'Feature',\n\t\t\t\t\t\t\t\tgeometry: node.geometry,\n\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\tid: convertNodeToSpaceId(node.properties.id),\n\t\t\t\t\t\t\t\t\tkind: 'desk-entrance', // This identifies these special spaces\n\t\t\t\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\t\t\t\texternalId: toObstructionId(id),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tentranceNodeIds,\n\t\t\t\t\t\t\tcenterCalculator,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tspaceFeatures.push(entranceSpace);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const area of geometryMaps.area.get(id)?.features ?? []) {\n\t\t\t\tareaFeatures.push(buildArea(area, nodes, centerCalculator));\n\t\t\t}\n\n\t\t\tfor (const window of geometryMaps.window.get(id)?.features ?? []) {\n\t\t\t\twindowFeatures.push(buildWindow(window));\n\t\t\t}\n\t\t}\n\n\t\tif (spaceFeatures.length > 0) {\n\t\t\tspaces[floorId] = {\n\t\t\t\ttype: 'FeatureCollection',\n\t\t\t\tfeatures: spaceFeatures.filter((x) => x !== null),\n\t\t\t};\n\t\t}\n\n\t\tif (obstructionFeatures.length > 0) {\n\t\t\tobstructions[floorId] = {\n\t\t\t\ttype: 'FeatureCollection',\n\t\t\t\tfeatures: obstructionFeatures.filter((x) => x !== null),\n\t\t\t};\n\t\t}\n\n\t\tif (areaFeatures.length > 0) {\n\t\t\tareas[floorId] = {\n\t\t\t\ttype: 'FeatureCollection',\n\t\t\t\tfeatures: areaFeatures.filter((x) => x !== null),\n\t\t\t};\n\t\t}\n\n\t\tif (windowFeatures.length > 0) {\n\t\t\twindows[floorId] = {\n\t\t\t\ttype: 'FeatureCollection',\n\t\t\t\tfeatures: windowFeatures.filter((x) => x !== null),\n\t\t\t};\n\t\t}\n\t}\n\tconst result: V2Geometry = {\n\t\tspace: spaces,\n\t\tobstruction: obstructions,\n\t};\n\tif (Object.keys(areas).length > 0) {\n\t\tresult.area = areas;\n\t}\n\tif (Object.keys(windows).length > 0) {\n\t\tresult.window = windows;\n\t}\n\n\treturn result;\n}\n\nexport function buildSpace(\n\tfeature: PartiallyTransformedGeometryFeature<SpaceId>,\n\tnodes: NodeId[],\n\tcenterCalculator: CenterCalculator = centerOfMass,\n): SpaceFeature | null {\n\tswitch (feature.geometry.type) {\n\t\tcase 'MultiPoint':\n\t\tcase 'MultiLineString':\n\t\tcase 'MultiPolygon':\n\t\t\t// Multis will have already been split\n\t\t\treturn null;\n\t}\n\tconst space: SpaceFeature = {\n\t\ttype: 'Feature',\n\t\tgeometry: feature.geometry,\n\t\tproperties: {\n\t\t\tdestinationNodes: nodes,\n\t\t\tid: feature.properties.id,\n\t\t\texternalId: feature.properties.details?.externalId ?? '',\n\t\t\tkind: feature.properties.kind,\n\t\t},\n\t};\n\tif (feature.properties.details) {\n\t\tspace.properties.details = {\n\t\t\tname: feature.properties.details.name,\n\t\t\tdescription: feature.properties.details.description,\n\t\t\timages: feature.properties.details.icon\n\t\t\t\t? [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\turl: feature.properties.details.icon,\n\t\t\t\t\t\t\taltText: feature.properties.details.name ? `${feature.properties.details.name} icon` : 'icon',\n\t\t\t\t\t\t},\n\t\t\t\t\t]\n\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\tif (isPolygonFeature(space)) {\n\t\tspace.properties.center = centerCalculator(space).unwrapOr(undefined);\n\t}\n\n\treturn space;\n}\n\nexport function buildObstruction(\n\tfeature: PartiallyTransformedGeometryFeature<ObstructionId>,\n\tfootprintComponent: boolean,\n\tcenterCalculator: CenterCalculator = centerOfMass,\n): ObstructionFeature | null {\n\tswitch (feature.geometry.type) {\n\t\tcase 'MultiPoint':\n\t\tcase 'MultiLineString':\n\t\tcase 'MultiPolygon':\n\t\tcase 'Point':\n\t\t\t// Multis will have already been split, point obstructions are meaningless\n\t\t\treturn null;\n\t}\n\n\tconst properties = feature.properties;\n\tconst obstruction: ObstructionFeature = {\n\t\ttype: 'Feature' as const,\n\t\tgeometry: feature.geometry,\n\t\tproperties: {\n\t\t\tid: properties.id,\n\t\t\texternalId: properties.details?.externalId ?? '',\n\t\t\tentrances: [],\n\t\t\tkind: properties.kind,\n\t\t\tfootprintComponent,\n\t\t},\n\t};\n\n\tif (isPolygonFeature(obstruction)) {\n\t\tobstruction.properties.center = centerCalculator(obstruction).unwrapOr(undefined);\n\t}\n\n\tif (properties.details) {\n\t\tobstruction.properties.details = {\n\t\t\tname: properties.details.name,\n\t\t\tdescription: properties.details.description,\n\t\t\timages: properties.details.icon\n\t\t\t\t? [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\turl: properties.details.icon,\n\t\t\t\t\t\t\taltText: properties.details.name ? `${properties.details.name} icon` : 'icon',\n\t\t\t\t\t\t},\n\t\t\t\t\t]\n\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\treturn obstruction;\n}\n\nexport function buildArea(\n\tfeature: PartiallyTransformedGeometryFeature<AreaId>,\n\tnodes: NodeId[],\n\tcenterCalculator: CenterCalculator = centerOfMass,\n): Area | null {\n\tif (feature.geometry.type !== 'Polygon') {\n\t\t//  Multi polygons are already split. Otherwise, it is nonsense\n\t\treturn null;\n\t}\n\tconst properties = feature.properties;\n\tconst area: Area = {\n\t\ttype: 'Feature',\n\t\tgeometry: feature.geometry,\n\t\tproperties: {\n\t\t\tid: properties.id,\n\t\t\texternalId: properties.details?.externalId ?? '',\n\t\t\tdestinationNodes: nodes,\n\t\t},\n\t};\n\n\tif (isPolygonFeature(area)) {\n\t\tarea.properties.center = centerCalculator(area).unwrapOr(undefined);\n\t}\n\n\tif (properties.details) {\n\t\tarea.properties.details = {\n\t\t\tname: properties.details.name,\n\t\t\tdescription: properties.details.description,\n\t\t\timages: properties.details.icon\n\t\t\t\t? [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\turl: properties.details.icon,\n\t\t\t\t\t\t\taltText: properties.details.name ? `${properties.details.name} icon` : 'icon',\n\t\t\t\t\t\t},\n\t\t\t\t\t]\n\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\treturn area;\n}\n\nexport function buildWindow(feature: PartiallyTransformedGeometryFeature<WindowId>): WindowFeature | null {\n\tif (feature.geometry.type !== 'LineString') {\n\t\treturn null;\n\t}\n\tconst window: WindowFeature = {\n\t\ttype: 'Feature',\n\t\tgeometry: feature.geometry,\n\t\tproperties: {\n\t\t\tid: feature.properties.id,\n\t\t},\n\t};\n\treturn window;\n}\n\nexport function calculateFootprintGeometry(styles?: DefaultStyleCollection): Set<GeometryId> {\n\tconst geometries = new Set<GeometryId>((styles?.ExteriorWalls?.geometryAnchors ?? []).map((a) => a.geometryId));\n\treturn geometries;\n}\n","import { typedEntries } from '@mappedin/mvf-core/utils/typed-entries';\nimport type { Category } from '../../extensions/category.js';\nimport type { Location, LocationAnnotationMapping, LocationEntranceMapping } from '../../extensions/location.js';\nimport type { ParsedMVF } from '../../types/bundle.js';\nimport type { ConnectionId } from '../../types/core.js';\nimport type { BuilderOptions } from '../builderOptions.js';\nimport type { MVFv2_STANDARD_MVFv3 } from '../index.js';\nimport { isLineDoor } from './connectionBuilder.js';\n\nexport type V3Locations = Pick<\n\tMVFv2_STANDARD_MVFv3,\n\t'locationCategories' | 'locations' | 'annotations' | 'connections'\n>;\nexport type V2Locations = Pick<ParsedMVF, 'category.json' | 'location.json'>;\n\n/**\n * Builds locations and categories, primarily based on the Locations extension\n * @param v3\n * @returns\n */\nexport function buildLocations(\n\tv3: V3Locations,\n\t{ geometryMaps, geometryFeatureById }: Pick<BuilderOptions, 'geometryMaps' | 'geometryFeatureById'>,\n): V2Locations {\n\tif (!v3.locationCategories && !v3.locations) {\n\t\treturn {};\n\t}\n\n\tconst v2: V2Locations = {};\n\n\tif (v3.locationCategories?.length) {\n\t\tconst v2Categories: Category[] = [];\n\t\tfor (const v3Category of v3.locationCategories) {\n\t\t\tconst v2Category: Category = {\n\t\t\t\tid: v3Category.id,\n\t\t\t\tname: v3Category.details.name,\n\t\t\t\ticon: v3Category.details.icon ?? '',\n\t\t\t};\n\t\t\tif (v3Category.parent) {\n\t\t\t\tv2Category.parent = v3Category.parent;\n\t\t\t}\n\t\t\tv2Categories.push(v2Category);\n\t\t}\n\t\tv2['category.json'] = v2Categories;\n\t}\n\n\tif (v3.locations?.length) {\n\t\tconst attachmentMaps = buildLocationAttachmentMaps(v3, { geometryFeatureById });\n\n\t\tconst v2Locations: Location[] = [];\n\t\tfor (const v3Location of v3.locations) {\n\t\t\tconst v2Location: Location = {\n\t\t\t\tid: v3Location.id,\n\t\t\t\tname: v3Location.details.name,\n\t\t\t\tcategories: v3Location.categories,\n\t\t\t\tspaces: [],\n\t\t\t\tobstructions: [],\n\t\t\t\tareas: [],\n\t\t\t\tannotations: [],\n\t\t\t\tconnections: [],\n\t\t\t\tentrances: [],\n\t\t\t\tlinks: v3Location.links,\n\t\t\t\topeningHoursSpecification: v3Location.openingHours ?? [],\n\t\t\t\tpictures: v3Location.images,\n\t\t\t\tsocial: v3Location.social,\n\t\t\t\tdescription: v3Location.details.description,\n\t\t\t\texternalId: v3Location.details.externalId,\n\t\t\t\ticon: v3Location.details.icon,\n\t\t\t\tlogo: v3Location.logo,\n\t\t\t\tphone: v3Location.phone,\n\t\t\t\twebsite: v3Location.website,\n\t\t\t\tsearchTags: v3Location.searchTags,\n\t\t\t};\n\t\t\tv2Locations.push(v2Location);\n\n\t\t\tfor (const { geometryId, floorId } of v3Location.geometryAnchors) {\n\t\t\t\tv2Location.spaces.push(\n\t\t\t\t\t...(geometryMaps.space.get(geometryId)?.ids.map((id) => ({ id, floor: floorId })) ?? []),\n\t\t\t\t);\n\t\t\t\tv2Location.obstructions.push(\n\t\t\t\t\t...(geometryMaps.obstruction.get(geometryId)?.ids.map((id) => ({ id, floor: floorId })) ?? []),\n\t\t\t\t);\n\t\t\t\tv2Location.areas.push(...(geometryMaps.area.get(geometryId)?.ids.map((id) => ({ id, floor: floorId })) ?? []));\n\n\t\t\t\tv2Location.entrances.push(...(attachmentMaps.entrancesByGeometryId.get(geometryId) ?? []));\n\t\t\t\tv2Location.connections.push(...(attachmentMaps.connectionsByGeometryId.get(geometryId) ?? []));\n\t\t\t\tv2Location.annotations.push(...(attachmentMaps.annotationsByGeometryId.get(geometryId) ?? []));\n\t\t\t}\n\t\t}\n\t\tv2['location.json'] = v2Locations;\n\t}\n\treturn v2;\n}\n\nexport type LocationAttachmentMaps = {\n\tannotationsByGeometryId: Map<string, LocationAnnotationMapping[]>;\n\tconnectionsByGeometryId: Map<string, ConnectionId[]>;\n\tentrancesByGeometryId: Map<string, LocationEntranceMapping[]>;\n};\nexport function buildLocationAttachmentMaps(\n\tv3: Pick<V3Locations, 'annotations' | 'connections'>,\n\t{ geometryFeatureById }: Pick<BuilderOptions, 'geometryFeatureById'>,\n): LocationAttachmentMaps {\n\tconst maps: LocationAttachmentMaps = {\n\t\tannotationsByGeometryId: new Map(),\n\t\tconnectionsByGeometryId: new Map(),\n\t\tentrancesByGeometryId: new Map(),\n\t};\n\n\tif (v3.annotations) {\n\t\tfor (const [floorId, annotations] of typedEntries(v3.annotations)) {\n\t\t\tfor (const annotation of annotations ?? []) {\n\t\t\t\tconst geometryId = annotation.geometryId;\n\t\t\t\tconst annotationId = annotation.id;\n\t\t\t\tconst annotationIds = maps.annotationsByGeometryId.get(geometryId) ?? [];\n\t\t\t\tannotationIds.push({ floor: floorId, id: annotationId });\n\t\t\t\tmaps.annotationsByGeometryId.set(geometryId, annotationIds);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (v3.connections) {\n\t\tfor (const connection of v3.connections) {\n\t\t\tconst isEntrance = isLineDoor(connection, geometryFeatureById);\n\t\t\t// Make a unique array of geometryIds for the connection\n\t\t\t// Create a unique array of geometry anchors by comparing geometryId and floorId\n\t\t\tconst geometryAnchors = Array.from(\n\t\t\t\tnew Map(\n\t\t\t\t\t[...connection.entrances, ...connection.exits].map((anchor) => [\n\t\t\t\t\t\t`${anchor.geometryId}_${anchor.floorId}`,\n\t\t\t\t\t\tanchor,\n\t\t\t\t\t]),\n\t\t\t\t).values(),\n\t\t\t);\n\t\t\tfor (const anchor of geometryAnchors) {\n\t\t\t\tconst geometryId = anchor.geometryId;\n\t\t\t\tif (isEntrance) {\n\t\t\t\t\tconst entranceIds = maps.entrancesByGeometryId.get(geometryId) ?? [];\n\t\t\t\t\tentranceIds.push({ floor: anchor.floorId, id: connection.id });\n\t\t\t\t\tmaps.entrancesByGeometryId.set(geometryId, entranceIds);\n\t\t\t\t} else {\n\t\t\t\t\tconst connectionIds = maps.connectionsByGeometryId.get(geometryId) ?? [];\n\t\t\t\t\tconnectionIds.push(connection.id);\n\t\t\t\t\tmaps.connectionsByGeometryId.set(geometryId, connectionIds);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn maps;\n}\n","import type { ManifestCollection, ManifestFeature, ParsedMVF } from '../../types/bundle.js';\nimport type { BuilderOptions } from '../builderOptions.js';\nimport type { MVFv2_STANDARD_MVFv3 } from '../index.js';\n\nexport type V3Manifest = Pick<MVFv2_STANDARD_MVFv3, 'manifest'>;\nexport type V2Manifest = Pick<ParsedMVF, 'manifest.geojson'>;\n\nexport function buildManifest(v3: V3Manifest, _builderOptions: Partial<BuilderOptions>): V2Manifest {\n\tconst v2Manifest: ManifestCollection = {\n\t\tfeatures: [],\n\t\ttype: 'FeatureCollection',\n\t};\n\tconst v2: V2Manifest = {\n\t\t'manifest.geojson': v2Manifest,\n\t};\n\tconst v3Manifest = v3.manifest;\n\tif (v3Manifest.features.length > 0) {\n\t\tconst v3ManifestFeature = v3Manifest.features[0];\n\n\t\tconst properties = v3ManifestFeature.properties;\n\t\tconst details =\n\t\t\tproperties.details != null\n\t\t\t\t? {\n\t\t\t\t\t\t...(properties.details.externalId != null && { externalId: properties.details.externalId }),\n\t\t\t\t\t}\n\t\t\t\t: undefined;\n\n\t\tconst v2ManifestFeature: ManifestFeature = {\n\t\t\ttype: 'Feature',\n\t\t\tgeometry: v3ManifestFeature.geometry,\n\t\t\tproperties: {\n\t\t\t\t// Intentionally empty\n\t\t\t\tfolder_struct: [],\n\t\t\t\tversion: '2.0.0',\n\t\t\t\ttime: properties.time,\n\t\t\t\tname: properties.name,\n\t\t\t\tnaturalBearing: properties.naturalBearing,\n\t\t\t\ttzid: properties.tzid,\n\t\t\t\tmap: properties.mapId,\n\t\t\t\torg_id: properties.orgId,\n\t\t\t\tlanguage: properties.language,\n\t\t\t\t...(details != null && Object.keys(details).length > 0 && { details }),\n\t\t\t},\n\t\t};\n\n\t\tv2Manifest.features.push(v2ManifestFeature);\n\t}\n\treturn v2;\n}\n","import type { Connection } from '@mappedin/mvf-connections';\nimport type { FloorId, GeometryId } from '@mappedin/mvf-core';\nimport { typedEntries } from '@mappedin/mvf-core/utils/typed-entries';\nimport type { NavigationFlagDeclaration, NavigationFlagDeclarations } from '@mappedin/mvf-navigation-flags';\nimport { hasFlag } from '@mappedin/mvf-navigation-flags/utils';\nimport type { NodeId } from '@mappedin/mvf-nodes';\nimport type { ParsedMVF } from '../../types/bundle.js';\nimport type { BuilderOptions } from '../builderOptions.js';\nimport type { MVFv2_STANDARD_MVFv3 } from '../index.js';\n\nexport type V3Nodes = Pick<MVFv2_STANDARD_MVFv3, 'nodes' | 'connections' | 'floors'>;\nexport type V2Nodes = Pick<ParsedMVF, 'node.geojson'>;\nexport type V2Node = V2Nodes['node.geojson']['features'][number];\n\nexport function buildNodes(\n\tv3: V3Nodes,\n\t{\n\t\tgeometryMaps,\n\t\tnavigationFlags,\n\t\tincomingEdgesByNodeId,\n\t}: Pick<BuilderOptions, 'geometryMaps' | 'navigationFlags' | 'incomingEdgesByNodeId'>,\n): V2Nodes {\n\tconst v2: V2Nodes = {\n\t\t'node.geojson': {\n\t\t\ttype: 'FeatureCollection',\n\t\t\tfeatures: [],\n\t\t},\n\t};\n\tconst v2Nodes = v2['node.geojson'].features;\n\n\t/**\n\t * Connections\n\t *\n\t * Connections in MVFv3 don't depend on nodes directly. Their entrances and exits should\n\t * link to geometry, and then nodes should also link to those geometries. These can all be\n\t * many to many relationships.\n\t *\n\t * We also need to know the change in elevation between floors to correctly calculate the cost\n\t * of traversing a connection.\n\t *\n\t * In MVFv2, there is a single giant node graph, connecting all the floors. Connections are decoration\n\t * that adds information to a path, like icons and whether it's accessible or not.\n\t *\n\t * Therefore, we have to do a fair bit of transformation to generate V2 node edges from V3 connections\n\t */\n\n\t// Map of floor id to elevation for determining elevation deltas between floors\n\tconst floorElevationById = createFloorElevationById(v3);\n\n\t// A map of the nodes that reference a particular geometry id, so we can connect Connection entrances and exits\n\t// to the correct nodes\n\tconst nodesByGeometryId = createNodesByGeometryId(v3);\n\n\t// A map of the neighbors a node should get from Connections\n\tconst connectionNeighborsByNodeId = createConnectionNeighborsByNodeId(v3, nodesByGeometryId, floorElevationById);\n\n\tfor (const [floorId, v3Nodes] of typedEntries(v3.nodes ?? {})) {\n\t\tfor (const v3node of v3Nodes?.features ?? []) {\n\t\t\tconst firstSpace = geometryMaps.space.get(v3node.properties.geometryIds[0])?.features[0];\n\t\t\tconst externalId =\n\t\t\t\tfirstSpace?.geometry.type === 'Point' && firstSpace?.properties.details?.externalId\n\t\t\t\t\t? firstSpace.properties.details.externalId\n\t\t\t\t\t: '';\n\n\t\t\t// A node has a flag if:\n\t\t\t// - It has incoming edges\n\t\t\t// - Some incoming edge has that flag\n\t\t\tconst incomingEdges = incomingEdgesByNodeId.get(v3node.properties.id) ?? [];\n\t\t\tconst knownFlags = Object.keys(navigationFlags ?? {});\n\t\t\tconst declarations: NavigationFlagDeclaration[] = [];\n\t\t\tfor (const edge of incomingEdges) {\n\t\t\t\tfor (const knownFlag of knownFlags) {\n\t\t\t\t\tif (hasFlag(edge, navigationFlags[knownFlag])) {\n\t\t\t\t\t\tdeclarations.push(navigationFlags[knownFlag]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst v2node: V2Node = {\n\t\t\t\ttype: 'Feature',\n\t\t\t\tgeometry: v3node.geometry,\n\t\t\t\tproperties: {\n\t\t\t\t\tid: v3node.properties.id,\n\t\t\t\t\tfloor: floorId,\n\t\t\t\t\t// If connections are not walkable, they won't make it into V2. V2 expects connections to attach to spaces.\n\t\t\t\t\tspace: v3node.properties.geometryIds\n\t\t\t\t\t\t.map((id) => geometryMaps.space.get(id)?.ids)\n\t\t\t\t\t\t.flat()\n\t\t\t\t\t\t.filter((x) => x !== undefined),\n\t\t\t\t\tneighbors: [\n\t\t\t\t\t\t...v3node.properties.neighbors.map((n) => ({ id: n.id, weight: n.extraCost })),\n\t\t\t\t\t\t...(connectionNeighborsByNodeId.get(v3node.properties.id) ?? []),\n\t\t\t\t\t],\n\t\t\t\t\tmap: floorId,\n\t\t\t\t\texternalId,\n\t\t\t\t\tflags: declarations.length > 0 ? buildFlagsArray(declarations) : undefined,\n\t\t\t\t},\n\t\t\t};\n\t\t\tv2Nodes.push(v2node);\n\t\t}\n\t}\n\treturn v2;\n}\n\nexport function createFloorElevationById(v3: Pick<V3Nodes, 'floors'>): Map<FloorId, number> {\n\tconst floorElevationById = new Map<FloorId, number>();\n\tfor (const floor of v3.floors?.features ?? []) {\n\t\tfloorElevationById.set(floor.properties.id, floor.properties.elevation);\n\t}\n\treturn floorElevationById;\n}\n\nexport function createNodesByGeometryId(v3: Pick<V3Nodes, 'nodes'>): Map<GeometryId, NodeId[]> {\n\tconst nodesByGeometryId = new Map<GeometryId, NodeId[]>();\n\tfor (const floorNodes of Object.values(v3.nodes ?? {})) {\n\t\tfor (const node of floorNodes?.features ?? []) {\n\t\t\tif (node.properties.geometryIds.length === 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tfor (const geometryId of node.properties.geometryIds) {\n\t\t\t\tconst existingNodes = nodesByGeometryId.get(geometryId) ?? [];\n\t\t\t\tif (existingNodes.includes(node.properties.id)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\texistingNodes.push(node.properties.id);\n\t\t\t\tnodesByGeometryId.set(geometryId, existingNodes);\n\t\t\t}\n\t\t}\n\t}\n\treturn nodesByGeometryId;\n}\n\nexport function createConnectionNeighborsByNodeId(\n\tv3: V3Nodes,\n\tnodesByGeometryId: Map<GeometryId, NodeId[]>,\n\tfloorElevationById: Map<FloorId, number>,\n): Map<NodeId, { id: NodeId; weight: number }[]> {\n\t// A map of the neighbors a node should get from Connections\n\tconst connectionNeighborsByNodeId = new Map<NodeId, { id: NodeId; weight: number }[]>();\n\n\t// For each connection, connect all nodes for all entrances to all nodes for all exits, using the difference\n\t// in elevation between floors plus the entry cost to calculate the cost\n\tfor (const connection of v3.connections ?? []) {\n\t\tconst exitNodes: (Connection['exits'][number] & { nodes: NodeId[] })[] = connection.exits.map((exit) => ({\n\t\t\t...exit,\n\t\t\tnodes: nodesByGeometryId.get(exit.geometryId) ?? [],\n\t\t}));\n\t\tfor (const entrance of connection.entrances) {\n\t\t\tconst entranceNodeIds = nodesByGeometryId.get(entrance.geometryId) ?? [];\n\t\t\tfor (const entranceNode of entranceNodeIds) {\n\t\t\t\tfor (const exitNode of exitNodes) {\n\t\t\t\t\tconst floorCost =\n\t\t\t\t\t\tMath.abs(\n\t\t\t\t\t\t\t(floorElevationById.get(entrance.floorId) ?? 0) - (floorElevationById.get(exitNode.floorId) ?? 0),\n\t\t\t\t\t\t) * connection.floorCostMultiplier;\n\t\t\t\t\tconst existingNeighbors = connectionNeighborsByNodeId.get(entranceNode) ?? [];\n\t\t\t\t\t// Technically there could be multiple nodes linked to the same geometry id, so we need to connect all of them\n\t\t\t\t\t// It will PROBABLY just be one though.\n\t\t\t\t\texistingNeighbors.push(\n\t\t\t\t\t\t...exitNode.nodes\n\t\t\t\t\t\t\t.filter((id) => id !== entranceNode)\n\t\t\t\t\t\t\t.map((id) => ({ id, weight: floorCost + connection.entryCost })),\n\t\t\t\t\t);\n\t\t\t\t\tconnectionNeighborsByNodeId.set(entranceNode, existingNeighbors);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn connectionNeighborsByNodeId;\n}\n\nexport function buildFlagsArray(\n\tflagDeclarations: NonNullable<NavigationFlagDeclarations[string]>[],\n): number[] | undefined {\n\tif (flagDeclarations == null || flagDeclarations.length === 0) {\n\t\treturn;\n\t}\n\n\tconst flags = new Array(Math.max(...flagDeclarations.map((f) => f.index)) + 1).fill(0);\n\n\tfor (const declaration of flagDeclarations) {\n\t\tflags[declaration.index] |= 1 << declaration.bit;\n\t}\n\n\treturn flags;\n}\n","import type { GeometryFeature } from '@mappedin/mvf-core';\nimport { typedEntries } from '@mappedin/mvf-core/utils/typed-entries';\nimport type { LineStringStyle, PointStyle, PolygonStyle, StyleCollection } from '../../extensions/style.js';\nimport type { ParsedMVF } from '../../types/bundle.js';\nimport type { BuilderOptions } from '../builderOptions.js';\nimport type { MVFv2_STANDARD_MVFv3 } from '../index.js';\n\nexport type V3Styles = Pick<MVFv2_STANDARD_MVFv3, 'defaultStyle'>;\nexport type V2Styles = Pick<ParsedMVF, 'styles.json'>;\nexport type V2Style = StyleCollection[string];\n\ntype GeometryType = GeometryFeature['geometry']['type'];\nexport type GeometryByType = Map<string, GeometryType>;\n\nexport function groupGeometryByType(\n\tgeometryIds: string[],\n\tgeometryByType: GeometryByType,\n): Partial<Record<GeometryType, string[]>> {\n\tconst grouped: Partial<Record<GeometryType, string[]>> = {};\n\n\tfor (const id of geometryIds) {\n\t\tconst type = geometryByType.get(id);\n\t\tif (type) {\n\t\t\tgrouped[type] ??= [];\n\t\t\tgrouped[type].push(id);\n\t\t}\n\t}\n\n\treturn grouped;\n}\nexport function buildStyles(v3: V3Styles, { geometryMaps }: Pick<BuilderOptions, 'geometryMaps'>): V2Styles {\n\tif (!v3.defaultStyle) {\n\t\treturn {};\n\t}\n\tconst v2: V2Styles = {};\n\n\tconst styles: StyleCollection = {};\n\tv2['styles.json'] = styles;\n\n\tconst spacesAndObstructions = [\n\t\t...Array.from(geometryMaps.space.values()).map((space) => space.features),\n\t\t...Array.from(geometryMaps.obstruction.values()).map((obstruction) => obstruction.features),\n\t];\n\n\tconst geometryTypeById: GeometryByType = new Map(\n\t\tspacesAndObstructions.flatMap((feature) =>\n\t\t\tfeature.map((geometry) => [geometry.properties.id, geometry.geometry.type]),\n\t\t),\n\t);\n\n\tfor (const [groupId, v3Style] of typedEntries(v3.defaultStyle)) {\n\t\tconst grouped = groupGeometryByType(\n\t\t\tv3Style.geometryAnchors.flatMap((anchor) => [\n\t\t\t\t...(geometryMaps.space.get(anchor.geometryId)?.ids ?? []),\n\t\t\t\t...(geometryMaps.obstruction.get(anchor.geometryId)?.ids ?? []),\n\t\t\t]),\n\t\t\tgeometryTypeById,\n\t\t);\n\n\t\tif (grouped.Point && grouped.Point.length > 0) {\n\t\t\tconst pointStyle: PointStyle = {\n\t\t\t\tpoints: Array.from(grouped.Point.values()),\n\t\t\t\tshowImage: v3Style.extra?.showImage !== undefined ? v3Style.extra?.showImage === true : v3Style.opacity !== 0,\n\t\t\t};\n\t\t\tstyles[`${groupId}.Point`] = pointStyle;\n\t\t}\n\n\t\tif (grouped.LineString && grouped.LineString.length > 0) {\n\t\t\tconst lineStringStyle: LineStringStyle = {\n\t\t\t\tlineStrings: Array.from(grouped.LineString.values()),\n\t\t\t\taltitude: v3Style.altitude,\n\t\t\t\tcolor: v3Style.color,\n\t\t\t\theight: v3Style.height,\n\t\t\t\topacity: v3Style.opacity,\n\t\t\t\twidth: v3Style.buffer,\n\t\t\t};\n\t\t\tif (v3Style.topColor !== undefined) {\n\t\t\t\tlineStringStyle.topColor = v3Style.topColor;\n\t\t\t}\n\t\t\tstyles[`${groupId}.LineString`] = lineStringStyle;\n\t\t}\n\n\t\tif (grouped.Polygon && grouped.Polygon.length > 0) {\n\t\t\tconst polygonStyle: PolygonStyle = {\n\t\t\t\tpolygons: Array.from(grouped.Polygon.values()),\n\t\t\t\taltitude: v3Style.altitude,\n\t\t\t\tcolor: v3Style.color,\n\t\t\t\theight: v3Style.height,\n\t\t\t\topacity: v3Style.opacity,\n\t\t\t};\n\t\t\tif (v3Style.extra?.showImage !== undefined) {\n\t\t\t\tpolygonStyle.showImage = v3Style.extra.showImage === true;\n\t\t\t}\n\t\t\tif (v3Style.topColor !== undefined) {\n\t\t\t\tpolygonStyle.topColor = v3Style.topColor;\n\t\t\t}\n\t\t\tstyles[`${groupId}.Polygon`] = polygonStyle;\n\t\t}\n\t}\n\n\treturn v2;\n}\n","import type { ParsedMVF } from '../types/bundle.js';\nimport { type ConvertOptions, buildBuilderOptions } from './builderOptions.js';\nimport { buildAnnotations } from './builders/annotationBuilder.js';\nimport { buildConnections } from './builders/connectionBuilder.js';\nimport { buildEnterprise } from './builders/enterpriseBuilder.js';\nimport { buildFacade } from './builders/facadeBuilder.js';\nimport { buildFloors } from './builders/floorBuilder.js';\nimport { buildFloorImages } from './builders/floorImagesBuilder.js';\nimport { buildFloorStacks } from './builders/floorStackBuilder.js';\nimport { buildGeometry } from './builders/geometryBuilder.js';\nimport { buildLocations } from './builders/locationBuilder.js';\nimport { buildManifest } from './builders/manifestBuilder.js';\nimport { buildNodes } from './builders/nodeBuilder.js';\nimport { buildStyles } from './builders/styleBuilder.js';\nimport type { MVFv2_STANDARD_MVFv3 } from './index.js';\n\n/**\n * Converts an unzipped MVFv3 object that has the extensions needed for the MVFv2 converter\n * into a MVFv2 object.\n *\n * If the MVFv3 is still zipped, use {@link extractAndConvertMVFv3} instead.\n *\n * @param v3 - The unzipped MVFv3 object to convert.\n * @param options - Optional conversion options, e.g. the polygon\n * {@link ConvertOptions.centerStrategy | center strategy}.\n * @returns The converted MVFv2 object.\n */\nexport function convertUnzippedStandardMVFv3ToParsedMVFv2(\n\tv3: MVFv2_STANDARD_MVFv3,\n\toptions?: ConvertOptions,\n): ParsedMVF {\n\tconst builderOptions = buildBuilderOptions(v3, options);\n\n\tconst floors = buildFloors(v3, builderOptions);\n\tconst geometry = buildGeometry(v3, builderOptions);\n\tconst nodes = buildNodes(v3, builderOptions);\n\tconst connections = buildConnections(v3, builderOptions);\n\tconst styles = buildStyles(v3, builderOptions);\n\tconst floorStacks = buildFloorStacks(v3, builderOptions);\n\tconst floorImages = buildFloorImages(v3, builderOptions);\n\tconst facade = buildFacade(v3, builderOptions);\n\tconst annotations = buildAnnotations(v3, builderOptions);\n\tconst locations = buildLocations(v3, builderOptions);\n\tconst enterprise = buildEnterprise(v3, builderOptions);\n\tconst manifest = buildManifest(v3, builderOptions);\n\tconst v2: ParsedMVF = {\n\t\t...(v3.tileset ? { 'tileset.json': v3.tileset } : {}),\n\t\t...(v3.navigationFlags ? { 'navigationFlags.json': v3.navigationFlags } : {}),\n\t\t...(v3.annotationSymbols ? { 'annotation-symbols.json': v3.annotationSymbols } : {}),\n\t\t...floors,\n\t\t...geometry,\n\t\t...nodes,\n\t\t...connections,\n\t\t...styles,\n\t\t...floorStacks,\n\t\t...floorImages,\n\t\t...facade,\n\t\t...annotations,\n\t\t...locations,\n\t\t...enterprise,\n\t\t...manifest,\n\t};\n\n\treturn v2;\n}\n"],"names":["IntegrityError","message","FloorStackUnknownMapError","floorStack","floorId","SpaceCollectionUnknownMapError","SpaceUnknownNodeError","space","nodeId","ObstructionCollectionUnknownMapError","ObstructionUnknownEntranceError","obstruction","entranceId","ConnectionUnknownNodeError","connection","NodeUnknownFloorError","node","NodeUnknownSpaceError","spaceId","NodeUnknownNeighborError","neighborId","NodeSelfReferenceError","StyleUnknownPolygonError","styleId","polygonKind","polygonId","StyleUnknownLineStringError","lineStringKind","lineStringId","StyleUnknownPointError","pointKind","pointId","InvalidStyleError","AnchoredImageUnknownSpaceError","AnchoredFloorTextUnknownSpaceError","AnchoredFloorTextUnknownObstructionError","obstructionId","AnchoredImageUnknownObstructionError","AnchoredImageUnknownAreaError","areaId","TextAreaUnknownSpaceError","EnterpriseLayerUnknownSpaceError","EnterpriseStyleGeometryAnchorsUnknownSpaceError","geometryId","EnterpriseTextureUnknownSpaceError","TextAreaUnknownObstructionError","EnterpriseUnknownLocationError","locationId","EnterpriseUnknownMapError","mapId","EnterpriseLocationUnknownSpaceError","EnterpriseUnknownCategoryError","categoryId","EnterpriseInconsistentMapError","spaceOrNodeId","mapId1","mapId2","EnterpriseCyclicalCategoryReferenceError","EnterpriseInvalidTimeZoneError","tzid","FacadeUnknownFloorStackError","floorStackId","FacadeUnknownFloorError","facadeId","FacadeUnknownSpaceError","DuplicateTilesetKeyError","key","AnnotationSymbolUnknownError","annotationId","symbolId","AnnotationSymbolDuplicateError","PUBLIC_HOLIDAYS","ENTERPRISE_VENUE_TYPES","WELL_KNOWN_FLAGS","deepMergeOn","full","partial","idKeys","result","partialValue","typedKey","keyPath","findIdentifierKey","fullObjectArray","partialsById","v","getValueByKeyPath","merged","fullObject","fullValue","obj","search","current","idKey","value","hasOnlyIdKeys","item","isObject","keys","deepDiffOn","first","second","secondValue","firstValue","secondValueMap","diffs","diff","nestedDiff","cleanUpFolderStruct","folderStruct","localePack","folder","folderProperty","child","cleanUpManifest","manifest","cleanedManifest","feature","mergeLocalePack","originalFolderStruct","partialMerge","partialManifest","createLocalePack","base","locale","localeManifest","defaultEntry","FILE_EXTENSION","rawFolderToParsed","raw","decode","rawFolder","contents","_OPTIONAL_FILES","OPTIONAL_FILES","_OPTIONAL_FOLDERS","OPTIONAL_FOLDERS","rawToParsedMVF","decoder","parsedMVF","OptionIterator","Some","fn","other","fallback","option","none","error","ok","some","None","err","ResultIterator","Ok","Err","typedKeys","typedEntries","record","TEXT_ALIGNMENT_VALUES","SIBLING_GROUP_TYPE_VALUES","LOCATION_STATE_VALUES","TEXT_AREA_ALIGNMENT_VALUES","TEXTURE_FACE_VALUES","TEXTURE_SURFACE_VALUES","ENTERPRISE_VENUE_TYPE_VALUES","ENTERPRISE_VENUE_TYPE","hasFlag","withFlags","flag","CONNECTION_TYPE_VALUES","CONNECTION_TYPE","KIND_VALUES","toSpaceId","id","toObstructionId","toWindowId","convertLocationInstanceId","convertLocationId","convertLocationCategoryId","convertAreaId","convertNodeToSpaceId","splitMultiPartGeometryFeatureWithNewId","newId","kind","index","type","coordinates","mapGeometryToOtherIds","geometry","xIds","convertToX","kindsMap","converted","ids","x","anchors","createGeometryMaps","v3","createKindsMap","flatFeatures","floor","featureCollection","walkableIds","obstructionIds","areaIds","_","objectsIds","windowIds","c","entrance","exit","someFlags","flags","maxLength","f","acc","calculateArea","polygon","area","i","pointInRing","y","ring","inside","j","xi","yi","xj","yj","pointInPolygon","point","rings","h","calculateCenterOfMass","xSum","ySum","count","k","tx","ty","sx","sy","sArea","prevX","prevY","pt","cross","areaFactor","estimatePrecision","polygonArea","centerOfMass","center","centerPt","polylabel","labelCenter","resolveCenterCalculator","strategy","buildBuilderOptions","convertOptions","nodesByGeometryId","incomingEdgesByNodeId","nodesById","buildNodeMaps","geometryMaps","geometryFeatureById","buildGeometryFeatureById","navigationFlags","floorNodes","existingNodes","neighbor","existing","floorGeometry","buildAnnotations","v2Annotations","annotations","geometryById","g","v2AnnotationCollection","v3Annotation","v2AnnotationProperties","buildConnections","v2","ACCESSIBLE_FLAG","OUTDOORS_FLAG","isLineDoor","doesConnectionTransitionFloors","entrances","buildEntranceFeaturesFromConnection","accessible","e","nodes","n","v2Connection","outdoorsFlag","geometryFeature","entranceFeature","isExterior","details","buildEnterprise","v2Enterprise","v3Manifest","v3Venue","locationsByLocationCategoryId","v3Locations","v3EnterpriseLocations","v3EnterpriseCategories","enterpriseCategoryByLocationCategoryId","cat","enterpriseLocationsByLocationId","enterpriseLocation","v3Location","v3EnterpriseLocation","v2EnterpriseLocation","v2EnterpriseCategory","social","convertSocials","anchor","polygons","category","v3EnterpriseLocationInstances","v3LocationInstances","v3EnterpriseLocationInstancesByLocationInstanceId","instance","v2EnterpriseLocationInstances","v3LocationInstance","v3EnterpriseLocationInstance","v2EnterpriseLocationInstance","spaces","v3Categories","v2EnterpriseCategories","v3CategoriesById","categoryChildren","v3Category","parent","children","v3EnterpriseCategory","v2CategoryPriorities","v2EnterpriseStyles","style","convertedAnchors","v2EnterpriseLayers","layers","layer","v2EnterpriseLayer","v2EnterpriseTextures","textures","texture","v2EnterpriseFloorText","floorText","v2FloorTextFeatureCollection","commonProperties","v2TextAreas","v2FloorTextFeature","SUPPORTED_SOCIALS","v3Socials","v2Socials","name","url","lowerName","convertFloorStackIdToFacadeId","buildFacade","v2FacadeCollection","v3Facades","v3Facade","geometryIds","buildFloors","_builderOptions","floors","maps","buildFloorImages","v2FloorImages","v3FloorImageCollection","v2FloorImageCollection","v3FloorImage","rest","anchorId","buildFloorStacks","floorStacks","v2FloorStack","v2Outdoors","isPolygonFeature","buildGeometry","centerCalculator","footprintGeometryIds","calculateFootprintGeometry","obstructions","areas","windows","floorFeatureCollection","spaceFeatures","obstructionFeatures","areaFeatures","windowFeatures","isFootprint","buildSpace","buildObstruction","entranceNodeIds","entranceNodes","entranceSpace","buildArea","window","buildWindow","footprintComponent","properties","styles","a","buildLocations","v2Categories","v2Category","attachmentMaps","buildLocationAttachmentMaps","v2Locations","v2Location","annotation","annotationIds","isEntrance","geometryAnchors","entranceIds","connectionIds","buildManifest","v2Manifest","v3ManifestFeature","v2ManifestFeature","buildNodes","v2Nodes","floorElevationById","createFloorElevationById","createNodesByGeometryId","connectionNeighborsByNodeId","createConnectionNeighborsByNodeId","v3Nodes","v3node","firstSpace","externalId","incomingEdges","knownFlags","declarations","edge","knownFlag","v2node","buildFlagsArray","exitNodes","entranceNode","exitNode","floorCost","existingNeighbors","flagDeclarations","declaration","groupGeometryByType","geometryByType","grouped","buildStyles","spacesAndObstructions","geometryTypeById","groupId","v3Style","pointStyle","lineStringStyle","polygonStyle","convertUnzippedStandardMVFv3ToParsedMVFv2","options","builderOptions","connections","floorImages","facade","locations","enterprise"],"mappings":"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","x_google_ignoreList":[6,7]}