@thatopen/services 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1585,19 +1585,21 @@ export interface OriginData {
1585
1585
  height: number;
1586
1586
  rotation: number;
1587
1587
  }
1588
- export interface BimSite {
1589
- label: string;
1590
- description?: string;
1591
- lat: number;
1592
- lon: number;
1593
- height: number;
1594
- rotation: number;
1595
- /** Column-major 4x4 matrix (16 values) mapping BIM local space to the site's georeferenced frame. */
1596
- baseMatrix: number[];
1597
- }
1598
- export interface BimCoordinatesData {
1599
- defaultSiteId?: string;
1600
- sites: Record<string, BimSite>;
1588
+ /** Project-wide coordinate reference system + vertical datum config, shared by
1589
+ * every asset type that needs to decode raw projected coordinates (point
1590
+ * clouds, BIM) — see automatic-file-derived-georeferencing.md
1591
+ * (VisorUnificadoAqualia/docs/adrs). One value per project, not per asset:
1592
+ * every file at the same real-world site shares the same CRS/geoid. */
1593
+ export interface CrsData {
1594
+ /** EPSG code of the project's projected CRS (e.g. 25830 for ETRS89/UTM 30N).
1595
+ * EPSG is a global registry, not region-specific — every project has an
1596
+ * applicable code, most commonly a standard UTM zone. */
1597
+ epsgCode: number;
1598
+ /** Geoid undulation in meters at the project's origin (orthometric ->
1599
+ * ellipsoidal height correction). Sampled once from a geoid model
1600
+ * (client-supplied, or a global EGM2008 fallback) — varies negligibly
1601
+ * across a single project's extent, so one scalar per project suffices. */
1602
+ geoidUndulation: number;
1601
1603
  }
1602
1604
  export type AssetCoordinateType = "splat" | "ifc" | "point-cloud" | (string & {});
1603
1605
  export interface AssetCoordinate {
@@ -1653,7 +1655,7 @@ export interface ProjectManagerData {
1653
1655
  namespaces: Record<ProjectNamespaceKey, ProjectNamespace>;
1654
1656
  entities: {
1655
1657
  origin: ProjectEntity<OriginData>;
1656
- bimCoordinates: ProjectEntity<BimCoordinatesData>;
1658
+ crs: ProjectEntity<CrsData>;
1657
1659
  assetCoordinates: ProjectEntity<AssetCoordinate[]>;
1658
1660
  graphicsSettings: ProjectEntity<GraphicsSettingsData>;
1659
1661
  };
@@ -1663,19 +1665,15 @@ export interface SingletonEntity<T> {
1663
1665
  set(data: T): Promise<void>;
1664
1666
  update(partial: Partial<T>): Promise<void>;
1665
1667
  }
1666
- export interface BimCoordinatesEntity {
1667
- get(): BimCoordinatesData;
1668
- getSites(): Record<string, BimSite>;
1669
- getSite(siteId: string): BimSite | undefined;
1670
- getDefaultSite(): BimSite | undefined;
1671
- /** Creates a new site. `ProjectManager` generates the opaque `siteId` — callers
1672
- * never invent their own (see the class-level JSDoc on `ProjectManager` for why). */
1673
- createSite(site: BimSite): Promise<string>;
1674
- /** Updates a site that already exists (from `createSite`). Throws if `siteId`
1675
- * isn't in `sites` — this is not an upsert; use `createSite` to add one. */
1676
- setSite(siteId: string, site: BimSite): Promise<void>;
1677
- setDefaultSite(siteId: string): Promise<void>;
1678
- removeSite(siteId: string): Promise<void>;
1668
+ /**
1669
+ * A singleton entity that also announces its own changes — for values other
1670
+ * code needs to react to live (recompute/reposition something) rather than
1671
+ * just read on demand. `onChange` fires with the new value on every
1672
+ * `set`/`update`, regardless of whether that change has been persisted yet
1673
+ * (see `ProjectManager.dirty`/`onDirtyChange`).
1674
+ */
1675
+ export interface ReactiveSingletonEntity<T> extends SingletonEntity<T> {
1676
+ onChange: import('@thatopen/components').Event<T>;
1679
1677
  }
1680
1678
  export interface AssetCoordinatesEntity {
1681
1679
  getAll(): AssetCoordinate[];
@@ -1698,18 +1696,10 @@ export interface AssetCoordinatesEntity {
1698
1696
  * Schema shape (see `src/types.ts` for the full rationale):
1699
1697
  * - `namespaces`/`entities` are maps keyed by a fixed, readable slug — a
1700
1698
  * closed set this code defines, never created at runtime.
1701
- * - `bimCoordinates.data.sites` is the one open, runtime-created collection
1702
- * today, so its keys are opaque generated ids instead of slugs.
1703
- * - `origin`/`graphicsSettings` are singletons; `sites`/`assetCoordinates`
1704
- * are collections.
1699
+ * - `origin`/`crs`/`graphicsSettings` are singletons; `assetCoordinates` is
1700
+ * a collection.
1705
1701
  * - `entities[id]` is a uniform envelope: `namespaceId`, mandatory `label`,
1706
1702
  * optional `description` (omitted, not stored empty), free-form `data`.
1707
- *
1708
- * Id generation rule: whenever a collection needs an opaque id (today just
1709
- * `sites`, potentially more collections later), `ProjectManager` generates it
1710
- * internally (`crypto.randomUUID()`, no prefix) — callers never invent their
1711
- * own. `createSite` is the current example; follow the same pattern for any
1712
- * future `create*` method.
1713
1703
  */
1714
1704
  declare class _ProjectManager extends OBC.Component {
1715
1705
  static readonly uuid: "6f3a9c2e-8b1d-4e6a-9c3f-1d7b5a8e2c4f";
@@ -1720,6 +1710,31 @@ declare class _ProjectManager extends OBC.Component {
1720
1710
  private _loadingData;
1721
1711
  readonly onSaveStart: OBC.Event<void>;
1722
1712
  readonly onSaveComplete: OBC.Event<boolean>;
1713
+ /**
1714
+ * Entity ids (e.g. `"origin"`) with changes not yet persisted. Most entities
1715
+ * auto-save (see `_scheduleSave`) so they're only ever dirty for the instant
1716
+ * before their debounce fires — `origin` is the exception: its `set`/`update`
1717
+ * mark it dirty WITHOUT scheduling a save (see `origin` below), so a caller
1718
+ * driving it continuously (e.g. a drag gizmo) can update it every frame
1719
+ * without spamming the network, and a UI can surface "unsaved changes" +
1720
+ * call `flush()` once the user explicitly confirms.
1721
+ *
1722
+ * KNOWN GAP: `_doSave()` persists the whole `_data` blob (one JSON file for
1723
+ * every entity), so an auto-saving entity's save will also flush out
1724
+ * whatever `origin` currently holds in memory, even if the user hasn't
1725
+ * confirmed it yet — there's no separate "committed vs. draft" copy of
1726
+ * `origin`'s data. Accepted for now as a v1 gap (same spirit as this
1727
+ * package's other documented v1 gaps, see the ProjectManager ADR); revisit
1728
+ * if that coincidence turns out to matter in practice.
1729
+ */
1730
+ private _dirtyEntities;
1731
+ /** True while any entity has unsaved changes. */
1732
+ get dirty(): boolean;
1733
+ /** Ids of entities with unsaved changes right now. */
1734
+ get dirtyEntities(): string[];
1735
+ /** Fires with the current `dirtyEntities` list every time it changes. */
1736
+ readonly onDirtyChange: OBC.Event<string[]>;
1737
+ private _markDirty;
1723
1738
  private _client?;
1724
1739
  private _fileId?;
1725
1740
  private _data;
@@ -1728,15 +1743,26 @@ declare class _ProjectManager extends OBC.Component {
1728
1743
  private _scheduleSave;
1729
1744
  private _queueSave;
1730
1745
  private _doSave;
1731
- /** Cancels the pending debounce and runs the save immediately. Awaits completion. */
1746
+ /**
1747
+ * Cancels the pending debounce (if any) and runs the save immediately.
1748
+ * Also the only way to persist an entity that marks itself dirty WITHOUT
1749
+ * auto-scheduling (currently just `origin`) — call this once the user
1750
+ * explicitly confirms. Awaits completion.
1751
+ */
1732
1752
  flush(): Promise<void>;
1733
1753
  init(client: PlatformClient): Promise<void>;
1734
- /** Opaque id generator for any collection needing one (currently just
1735
- * `bimCoordinates.sites`) — see the class-level JSDoc's id-generation rule. */
1736
- private _generateId;
1737
- origin: SingletonEntity<OriginData>;
1754
+ /**
1755
+ * NOT auto-saving, unlike every other entity below — `set`/`update` mark it
1756
+ * dirty and fire `onChange` immediately, but leave persisting up to an
1757
+ * explicit `flush()` call. This is what lets a continuous interaction (e.g.
1758
+ * a drag gizmo) update `origin` every frame — live for anyone listening to
1759
+ * `onChange` — without writing to the network on every tick, while still
1760
+ * surfacing "there's an unconfirmed change" via `dirty`/`onDirtyChange` for
1761
+ * a UI to gate behind an explicit save action.
1762
+ */
1763
+ origin: ReactiveSingletonEntity<OriginData>;
1764
+ crs: ReactiveSingletonEntity<CrsData>;
1738
1765
  graphicsSettings: SingletonEntity<GraphicsSettingsData>;
1739
- bimCoordinates: BimCoordinatesEntity;
1740
1766
  assetCoordinates: AssetCoordinatesEntity;
1741
1767
  getNamespaces(): Record<ProjectNamespaceKey, ProjectNamespace>;
1742
1768
  getNamespace(key: ProjectNamespaceKey): Record<string, unknown>;
@@ -1755,18 +1781,10 @@ declare class _ProjectManager extends OBC.Component {
1755
1781
  * Schema shape (see `src/types.ts` for the full rationale):
1756
1782
  * - `namespaces`/`entities` are maps keyed by a fixed, readable slug — a
1757
1783
  * closed set this code defines, never created at runtime.
1758
- * - `bimCoordinates.data.sites` is the one open, runtime-created collection
1759
- * today, so its keys are opaque generated ids instead of slugs.
1760
- * - `origin`/`graphicsSettings` are singletons; `sites`/`assetCoordinates`
1761
- * are collections.
1784
+ * - `origin`/`crs`/`graphicsSettings` are singletons; `assetCoordinates` is
1785
+ * a collection.
1762
1786
  * - `entities[id]` is a uniform envelope: `namespaceId`, mandatory `label`,
1763
1787
  * optional `description` (omitted, not stored empty), free-form `data`.
1764
- *
1765
- * Id generation rule: whenever a collection needs an opaque id (today just
1766
- * `sites`, potentially more collections later), `ProjectManager` generates it
1767
- * internally (`crypto.randomUUID()`, no prefix) — callers never invent their
1768
- * own. `createSite` is the current example; follow the same pattern for any
1769
- * future `create*` method.
1770
1788
  */
1771
1789
  export type ProjectManager = InstanceType<typeof _ProjectManager>;
1772
1790
  /**
@@ -1783,18 +1801,10 @@ export type ProjectManager = InstanceType<typeof _ProjectManager>;
1783
1801
  * Schema shape (see `src/types.ts` for the full rationale):
1784
1802
  * - `namespaces`/`entities` are maps keyed by a fixed, readable slug — a
1785
1803
  * closed set this code defines, never created at runtime.
1786
- * - `bimCoordinates.data.sites` is the one open, runtime-created collection
1787
- * today, so its keys are opaque generated ids instead of slugs.
1788
- * - `origin`/`graphicsSettings` are singletons; `sites`/`assetCoordinates`
1789
- * are collections.
1804
+ * - `origin`/`crs`/`graphicsSettings` are singletons; `assetCoordinates` is
1805
+ * a collection.
1790
1806
  * - `entities[id]` is a uniform envelope: `namespaceId`, mandatory `label`,
1791
1807
  * optional `description` (omitted, not stored empty), free-form `data`.
1792
- *
1793
- * Id generation rule: whenever a collection needs an opaque id (today just
1794
- * `sites`, potentially more collections later), `ProjectManager` generates it
1795
- * internally (`crypto.randomUUID()`, no prefix) — callers never invent their
1796
- * own. `createSite` is the current example; follow the same pattern for any
1797
- * future `create*` method.
1798
1808
  */
1799
1809
  export declare const ProjectManager: typeof _ProjectManager & {
1800
1810
  uuid: "6f3a9c2e-8b1d-4e6a-9c3f-1d7b5a8e2c4f";
package/package.json CHANGED
@@ -15,7 +15,7 @@
15
15
  "access": "public"
16
16
  },
17
17
  "private": false,
18
- "version": "0.13.0",
18
+ "version": "0.14.0",
19
19
  "main": "dist/index.cjs.js",
20
20
  "module": "dist/index.es.js",
21
21
  "types": "dist/index.d.ts",
@@ -14,10 +14,9 @@
14
14
  per-builtin data.
15
15
 
16
16
  This tutorial covers initializing the manager from the platform client; the
17
- `origin` and `graphicsSettings` singletons; the `bimCoordinates` sites
18
- collection used for BIM georeferencing; the `assetCoordinates` collection
19
- used for splats and point clouds; auto-save and its events; and the
20
- read-only namespace introspection API.
17
+ `origin` and `graphicsSettings` singletons; the `assetCoordinates`
18
+ collection used for splats and point clouds; auto-save and its events; and
19
+ the read-only namespace introspection API.
21
20
 
22
21
  ProjectManager has no built-in UI panel — it's a pure data layer. Apps that
23
22
  need georeferencing or project-settings UI (like Aqualia's viewer) build it
@@ -76,44 +75,6 @@ await manager.flush();
76
75
 
77
76
  console.log("origin after update+flush:", manager.origin.get());
78
77
 
79
- /* MD
80
- ### 🗺️ bimCoordinates — the sites collection
81
- Sites are how a project keeps georeferencing for more than one BIM model,
82
- each with its own origin and transform matrix. Because sites are created by
83
- users at runtime, their ids are opaque and generated internally —
84
- `createSite` mints the id and returns it, while `setSite` only updates a
85
- site that already exists (it throws otherwise). This split keeps storage
86
- keys decoupled from mutable data like a site's label.
87
- */
88
-
89
- const siteId = await manager.bimCoordinates.createSite({
90
- label: "Site 1",
91
- description: "Primary IFC export.",
92
- lat: 40.41647848134075,
93
- lon: -3.703451491164702,
94
- height: 699.970526176243,
95
- rotation: 0,
96
- baseMatrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -498477.20216, -719.2375, 4389662.11289, 1],
97
- });
98
-
99
- await manager.bimCoordinates.setDefaultSite(siteId);
100
- await manager.flush();
101
-
102
- console.log("default site:", manager.bimCoordinates.getDefaultSite());
103
- console.log("all sites:", manager.bimCoordinates.getSites());
104
-
105
- /* MD
106
- Updating an existing site goes through `setSite`, not `createSite`:
107
- */
108
-
109
- await manager.bimCoordinates.setSite(siteId, {
110
- ...manager.bimCoordinates.getSite(siteId)!,
111
- label: "Site 1 (revised)",
112
- });
113
- await manager.flush();
114
-
115
- console.log("site after update:", manager.bimCoordinates.getSite(siteId));
116
-
117
78
  /* MD
118
79
  ### 🖼️ assetCoordinates — the files collection
119
80
  `assetCoordinates` georeferences individual files — splats, point clouds —
@@ -159,5 +120,5 @@ console.log("georeferencing namespace:", manager.getNamespace("georeferencing"))
159
120
  ### 🤖 What's not covered here
160
121
  ProjectManager ships without a UI panel — everything above is the data
161
122
  layer only. Building georeferencing or project-settings UI on top of
162
- `origin`/`bimCoordinates`/`assetCoordinates` is up to the consuming app.
123
+ `origin`/`crs`/`assetCoordinates` is up to the consuming app.
163
124
  */
@@ -1594,19 +1594,21 @@ export interface OriginData {
1594
1594
  height: number;
1595
1595
  rotation: number;
1596
1596
  }
1597
- export interface BimSite {
1598
- label: string;
1599
- description?: string;
1600
- lat: number;
1601
- lon: number;
1602
- height: number;
1603
- rotation: number;
1604
- /** Column-major 4x4 matrix (16 values) mapping BIM local space to the site's georeferenced frame. */
1605
- baseMatrix: number[];
1606
- }
1607
- export interface BimCoordinatesData {
1608
- defaultSiteId?: string;
1609
- sites: Record<string, BimSite>;
1597
+ /** Project-wide coordinate reference system + vertical datum config, shared by
1598
+ * every asset type that needs to decode raw projected coordinates (point
1599
+ * clouds, BIM) — see automatic-file-derived-georeferencing.md
1600
+ * (VisorUnificadoAqualia/docs/adrs). One value per project, not per asset:
1601
+ * every file at the same real-world site shares the same CRS/geoid. */
1602
+ export interface CrsData {
1603
+ /** EPSG code of the project's projected CRS (e.g. 25830 for ETRS89/UTM 30N).
1604
+ * EPSG is a global registry, not region-specific — every project has an
1605
+ * applicable code, most commonly a standard UTM zone. */
1606
+ epsgCode: number;
1607
+ /** Geoid undulation in meters at the project's origin (orthometric ->
1608
+ * ellipsoidal height correction). Sampled once from a geoid model
1609
+ * (client-supplied, or a global EGM2008 fallback) — varies negligibly
1610
+ * across a single project's extent, so one scalar per project suffices. */
1611
+ geoidUndulation: number;
1610
1612
  }
1611
1613
  export type AssetCoordinateType = "splat" | "ifc" | "point-cloud" | (string & {});
1612
1614
  export interface AssetCoordinate {
@@ -1662,7 +1664,7 @@ export interface ProjectManagerData {
1662
1664
  namespaces: Record<ProjectNamespaceKey, ProjectNamespace>;
1663
1665
  entities: {
1664
1666
  origin: ProjectEntity<OriginData>;
1665
- bimCoordinates: ProjectEntity<BimCoordinatesData>;
1667
+ crs: ProjectEntity<CrsData>;
1666
1668
  assetCoordinates: ProjectEntity<AssetCoordinate[]>;
1667
1669
  graphicsSettings: ProjectEntity<GraphicsSettingsData>;
1668
1670
  };
@@ -1672,19 +1674,15 @@ export interface SingletonEntity<T> {
1672
1674
  set(data: T): Promise<void>;
1673
1675
  update(partial: Partial<T>): Promise<void>;
1674
1676
  }
1675
- export interface BimCoordinatesEntity {
1676
- get(): BimCoordinatesData;
1677
- getSites(): Record<string, BimSite>;
1678
- getSite(siteId: string): BimSite | undefined;
1679
- getDefaultSite(): BimSite | undefined;
1680
- /** Creates a new site. `ProjectManager` generates the opaque `siteId` — callers
1681
- * never invent their own (see the class-level JSDoc on `ProjectManager` for why). */
1682
- createSite(site: BimSite): Promise<string>;
1683
- /** Updates a site that already exists (from `createSite`). Throws if `siteId`
1684
- * isn't in `sites` — this is not an upsert; use `createSite` to add one. */
1685
- setSite(siteId: string, site: BimSite): Promise<void>;
1686
- setDefaultSite(siteId: string): Promise<void>;
1687
- removeSite(siteId: string): Promise<void>;
1677
+ /**
1678
+ * A singleton entity that also announces its own changes — for values other
1679
+ * code needs to react to live (recompute/reposition something) rather than
1680
+ * just read on demand. `onChange` fires with the new value on every
1681
+ * `set`/`update`, regardless of whether that change has been persisted yet
1682
+ * (see `ProjectManager.dirty`/`onDirtyChange`).
1683
+ */
1684
+ export interface ReactiveSingletonEntity<T> extends SingletonEntity<T> {
1685
+ onChange: import("@thatopen/components").Event<T>;
1688
1686
  }
1689
1687
  export interface AssetCoordinatesEntity {
1690
1688
  getAll(): AssetCoordinate[];
@@ -1708,18 +1706,10 @@ export interface AssetCoordinatesEntity {
1708
1706
  * Schema shape (see `src/types.ts` for the full rationale):
1709
1707
  * - `namespaces`/`entities` are maps keyed by a fixed, readable slug — a
1710
1708
  * closed set this code defines, never created at runtime.
1711
- * - `bimCoordinates.data.sites` is the one open, runtime-created collection
1712
- * today, so its keys are opaque generated ids instead of slugs.
1713
- * - `origin`/`graphicsSettings` are singletons; `sites`/`assetCoordinates`
1714
- * are collections.
1709
+ * - `origin`/`crs`/`graphicsSettings` are singletons; `assetCoordinates` is
1710
+ * a collection.
1715
1711
  * - `entities[id]` is a uniform envelope: `namespaceId`, mandatory `label`,
1716
1712
  * optional `description` (omitted, not stored empty), free-form `data`.
1717
- *
1718
- * Id generation rule: whenever a collection needs an opaque id (today just
1719
- * `sites`, potentially more collections later), `ProjectManager` generates it
1720
- * internally (`crypto.randomUUID()`, no prefix) — callers never invent their
1721
- * own. `createSite` is the current example; follow the same pattern for any
1722
- * future `create*` method.
1723
1713
  */
1724
1714
  declare class _ProjectManager extends OBC.Component {
1725
1715
  static readonly uuid: "6f3a9c2e-8b1d-4e6a-9c3f-1d7b5a8e2c4f";
@@ -1730,6 +1720,31 @@ declare class _ProjectManager extends OBC.Component {
1730
1720
  private _loadingData;
1731
1721
  readonly onSaveStart: OBC.Event<void>;
1732
1722
  readonly onSaveComplete: OBC.Event<boolean>;
1723
+ /**
1724
+ * Entity ids (e.g. `"origin"`) with changes not yet persisted. Most entities
1725
+ * auto-save (see `_scheduleSave`) so they're only ever dirty for the instant
1726
+ * before their debounce fires — `origin` is the exception: its `set`/`update`
1727
+ * mark it dirty WITHOUT scheduling a save (see `origin` below), so a caller
1728
+ * driving it continuously (e.g. a drag gizmo) can update it every frame
1729
+ * without spamming the network, and a UI can surface "unsaved changes" +
1730
+ * call `flush()` once the user explicitly confirms.
1731
+ *
1732
+ * KNOWN GAP: `_doSave()` persists the whole `_data` blob (one JSON file for
1733
+ * every entity), so an auto-saving entity's save will also flush out
1734
+ * whatever `origin` currently holds in memory, even if the user hasn't
1735
+ * confirmed it yet — there's no separate "committed vs. draft" copy of
1736
+ * `origin`'s data. Accepted for now as a v1 gap (same spirit as this
1737
+ * package's other documented v1 gaps, see the ProjectManager ADR); revisit
1738
+ * if that coincidence turns out to matter in practice.
1739
+ */
1740
+ private _dirtyEntities;
1741
+ /** True while any entity has unsaved changes. */
1742
+ get dirty(): boolean;
1743
+ /** Ids of entities with unsaved changes right now. */
1744
+ get dirtyEntities(): string[];
1745
+ /** Fires with the current `dirtyEntities` list every time it changes. */
1746
+ readonly onDirtyChange: OBC.Event<string[]>;
1747
+ private _markDirty;
1733
1748
  private _client?;
1734
1749
  private _fileId?;
1735
1750
  private _data;
@@ -1738,15 +1753,26 @@ declare class _ProjectManager extends OBC.Component {
1738
1753
  private _scheduleSave;
1739
1754
  private _queueSave;
1740
1755
  private _doSave;
1741
- /** Cancels the pending debounce and runs the save immediately. Awaits completion. */
1756
+ /**
1757
+ * Cancels the pending debounce (if any) and runs the save immediately.
1758
+ * Also the only way to persist an entity that marks itself dirty WITHOUT
1759
+ * auto-scheduling (currently just `origin`) — call this once the user
1760
+ * explicitly confirms. Awaits completion.
1761
+ */
1742
1762
  flush(): Promise<void>;
1743
1763
  init(client: PlatformClient): Promise<void>;
1744
- /** Opaque id generator for any collection needing one (currently just
1745
- * `bimCoordinates.sites`) — see the class-level JSDoc's id-generation rule. */
1746
- private _generateId;
1747
- origin: SingletonEntity<OriginData>;
1764
+ /**
1765
+ * NOT auto-saving, unlike every other entity below — `set`/`update` mark it
1766
+ * dirty and fire `onChange` immediately, but leave persisting up to an
1767
+ * explicit `flush()` call. This is what lets a continuous interaction (e.g.
1768
+ * a drag gizmo) update `origin` every frame — live for anyone listening to
1769
+ * `onChange` — without writing to the network on every tick, while still
1770
+ * surfacing "there's an unconfirmed change" via `dirty`/`onDirtyChange` for
1771
+ * a UI to gate behind an explicit save action.
1772
+ */
1773
+ origin: ReactiveSingletonEntity<OriginData>;
1774
+ crs: ReactiveSingletonEntity<CrsData>;
1748
1775
  graphicsSettings: SingletonEntity<GraphicsSettingsData>;
1749
- bimCoordinates: BimCoordinatesEntity;
1750
1776
  assetCoordinates: AssetCoordinatesEntity;
1751
1777
  getNamespaces(): Record<ProjectNamespaceKey, ProjectNamespace>;
1752
1778
  getNamespace(key: ProjectNamespaceKey): Record<string, unknown>;
@@ -1766,18 +1792,10 @@ declare class _ProjectManager extends OBC.Component {
1766
1792
  * Schema shape (see `src/types.ts` for the full rationale):
1767
1793
  * - `namespaces`/`entities` are maps keyed by a fixed, readable slug — a
1768
1794
  * closed set this code defines, never created at runtime.
1769
- * - `bimCoordinates.data.sites` is the one open, runtime-created collection
1770
- * today, so its keys are opaque generated ids instead of slugs.
1771
- * - `origin`/`graphicsSettings` are singletons; `sites`/`assetCoordinates`
1772
- * are collections.
1795
+ * - `origin`/`crs`/`graphicsSettings` are singletons; `assetCoordinates` is
1796
+ * a collection.
1773
1797
  * - `entities[id]` is a uniform envelope: `namespaceId`, mandatory `label`,
1774
1798
  * optional `description` (omitted, not stored empty), free-form `data`.
1775
- *
1776
- * Id generation rule: whenever a collection needs an opaque id (today just
1777
- * `sites`, potentially more collections later), `ProjectManager` generates it
1778
- * internally (`crypto.randomUUID()`, no prefix) — callers never invent their
1779
- * own. `createSite` is the current example; follow the same pattern for any
1780
- * future `create*` method.
1781
1799
  */
1782
1800
  export type ProjectManager = InstanceType<typeof _ProjectManager>;
1783
1801
  /**
@@ -1794,18 +1812,10 @@ export type ProjectManager = InstanceType<typeof _ProjectManager>;
1794
1812
  * Schema shape (see `src/types.ts` for the full rationale):
1795
1813
  * - `namespaces`/`entities` are maps keyed by a fixed, readable slug — a
1796
1814
  * closed set this code defines, never created at runtime.
1797
- * - `bimCoordinates.data.sites` is the one open, runtime-created collection
1798
- * today, so its keys are opaque generated ids instead of slugs.
1799
- * - `origin`/`graphicsSettings` are singletons; `sites`/`assetCoordinates`
1800
- * are collections.
1815
+ * - `origin`/`crs`/`graphicsSettings` are singletons; `assetCoordinates` is
1816
+ * a collection.
1801
1817
  * - `entities[id]` is a uniform envelope: `namespaceId`, mandatory `label`,
1802
1818
  * optional `description` (omitted, not stored empty), free-form `data`.
1803
- *
1804
- * Id generation rule: whenever a collection needs an opaque id (today just
1805
- * `sites`, potentially more collections later), `ProjectManager` generates it
1806
- * internally (`crypto.randomUUID()`, no prefix) — callers never invent their
1807
- * own. `createSite` is the current example; follow the same pattern for any
1808
- * future `create*` method.
1809
1819
  */
1810
1820
  export const ProjectManager = { uuid: '6f3a9c2e-8b1d-4e6a-9c3f-1d7b5a8e2c4f' } as typeof _ProjectManager & { uuid: '6f3a9c2e-8b1d-4e6a-9c3f-1d7b5a8e2c4f' };
1811
1821