@thatopen/services 0.3.15 → 0.4.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.
Files changed (68) hide show
  1. package/README.md +62 -62
  2. package/dist/built-in/index.d.ts +165 -2
  3. package/dist/cli.js +27 -13
  4. package/dist/core/client.d.ts +1 -0
  5. package/dist/core/platform-client.d.ts +7 -0
  6. package/dist/index.cjs.js +2 -2
  7. package/dist/index.es.js +396 -374
  8. package/dist/vite-env.d.ts +1 -1
  9. package/docs/builtin/paths.json +94 -86
  10. package/docs/cli/create.md +29 -29
  11. package/docs/cli/local-server.md +38 -38
  12. package/docs/cli/login.md +32 -32
  13. package/docs/cli/publish.md +31 -31
  14. package/docs/cli/run.md +26 -26
  15. package/docs/cli/serve.md +43 -43
  16. package/docs/cli/swap.md +30 -30
  17. package/package.json +4 -4
  18. package/resources/AGENTS.md +40 -40
  19. package/src/built-in/CDEManager/example.ts +214 -214
  20. package/src/built-in/CDEManager/examples/FileEditing/example.ts +226 -226
  21. package/src/built-in/CDEManager/examples/FileMoves/example.ts +186 -186
  22. package/src/built-in/CDEManager/examples/FileOperations/example.ts +295 -295
  23. package/src/built-in/CDEManager/examples/FileTransfers/example.ts +210 -210
  24. package/src/built-in/CDEManager/examples/FolderManagement/example.ts +230 -230
  25. package/src/built-in/CDEManager/examples/MetadataSchema/example.ts +230 -230
  26. package/src/built-in/CDEManager/examples/MetadataViews/example.ts +166 -166
  27. package/src/built-in/CDEManager/examples/ProjectConfig/example.ts +177 -177
  28. package/src/built-in/ClashesManager/example.ts +283 -283
  29. package/src/built-in/UIManager/src/app/example.ts +97 -97
  30. package/src/built-in/UIManager/src/app/examples/AppState/example.ts +140 -140
  31. package/src/built-in/UIManager/src/app/examples/Banner/example.ts +159 -159
  32. package/src/built-in/UIManager/src/app/examples/Contexts/example.ts +123 -123
  33. package/src/built-in/UIManager/src/app/examples/FileDrop/example.ts +124 -124
  34. package/src/built-in/UIManager/src/app/examples/FloatingLayout/example.ts +90 -90
  35. package/src/built-in/UIManager/src/app/examples/Modal/example.ts +163 -163
  36. package/src/built-in/UIManager/src/app/examples/Notifications/example.ts +133 -133
  37. package/src/built-in/UIManager/src/app/examples/ProjectFileStorage/example.ts +150 -0
  38. package/src/built-in/UIManager/src/app/examples/Sidebar/example.ts +102 -102
  39. package/src/built-in/UIManager/src/clashes-panel/example.ts +183 -160
  40. package/src/built-in/UIManager/src/models-list/example.ts +122 -122
  41. package/src/built-in/UIManager/src/topics-panel/example.ts +170 -0
  42. package/src/built-in/index.ts +1048 -881
  43. package/src/cli/templates/app/index.html +35 -35
  44. package/src/cli/templates/app/package.json +32 -32
  45. package/src/cli/templates/app/src/bim-components/CloudRunner/index.ts +95 -95
  46. package/src/cli/templates/app/src/bim-components/CloudRunner/src/index.ts +1 -1
  47. package/src/cli/templates/app/src/bim-components/CloudRunner/src/types.ts +5 -5
  48. package/src/cli/templates/app/src/bim-components/index.ts +1 -1
  49. package/src/cli/templates/app/src/globals.ts +1 -1
  50. package/src/cli/templates/app/src/ui-components/app-info-section/index.ts +26 -26
  51. package/src/cli/templates/app/src/ui-components/app-info-section/src/index.ts +1 -1
  52. package/src/cli/templates/app/src/ui-components/app-info-section/src/types.ts +15 -15
  53. package/src/cli/templates/app/src/ui-components/cloud-runner-section/index.ts +37 -37
  54. package/src/cli/templates/app/src/ui-components/cloud-runner-section/src/index.ts +1 -1
  55. package/src/cli/templates/app/src/ui-components/cloud-runner-section/src/types.ts +14 -14
  56. package/src/cli/templates/app/src/ui-components/index.ts +2 -2
  57. package/src/cli/templates/app/tsconfig.json +16 -16
  58. package/src/cli/templates/app/vite.config.js +57 -57
  59. package/src/cli/templates/cloud-component/README.md +205 -205
  60. package/src/cli/templates/cloud-component/_thatopen +5 -5
  61. package/src/cli/templates/cloud-component/declarations.json +4 -4
  62. package/src/cli/templates/cloud-component/package.json +21 -21
  63. package/src/cli/templates/cloud-component/src/main.ts +70 -70
  64. package/src/cli/templates/cloud-component/tsconfig.json +16 -16
  65. package/src/cli/templates/cloud-component/vite.config.js +46 -46
  66. package/src/cli/templates/shared/AGENTS.md +8 -8
  67. package/src/cli/templates/shared/CLAUDE.md +1 -1
  68. package/src/cli/templates/shared/_gitignore +5 -5
@@ -1,166 +1,166 @@
1
- /* MD
2
- ## Metadata views — organize fields into named table layouts
3
- ---
4
- A structural engineer and an MEP coordinator look at the same file list but care
5
- about completely different metadata. Showing every field to everyone produces a
6
- wide table that is hard to navigate. Metadata views let each role define which
7
- fields appear in which order — saving the layout so the table opens correctly next
8
- time without requiring a manual setup every session.
9
-
10
- CDEManager stores a list of named views, each carrying an ordered set of field keys.
11
- An active view filters both which columns are visible and which metadata groupings
12
- appear in the sidebar. Changes to the view list are staged in memory first, just like
13
- schema changes, and saved in one batch — so the user can add, rename, and remove
14
- views without any partial state reaching the backend.
15
-
16
- This tutorial covers initializing views from a saved configuration; switching the
17
- active view and reading the result; adding, updating, and removing views in the
18
- pending list; and committing the full batch, which saves to the user's personal
19
- config and fires an event with the final view list.
20
-
21
- By the end, you'll know how to load, display, edit, and persist named metadata
22
- layouts through the state machine.
23
- */
24
-
25
- import * as OBC from "@thatopen/components";
26
- // In production platform apps, CDEManager is loaded through the platform client:
27
- // const cde = await client.initBuiltInComponent(CDEManager.uuid, components);
28
- // Here we import directly from source for local testing.
29
- import { CDEManager } from "../../index";
30
- import type { CDEMetadataView } from "../../src/types";
31
-
32
- /* MD
33
- ### 🛠️ Setting up
34
- Loading views from a saved config and switching the active view don't require
35
- permissions. We still simulate the startup step to load permissions so the save
36
- path works later, then clear the context — staging is in-memory only.
37
- */
38
-
39
- const components = new OBC.Components();
40
- const cde = components.get(CDEManager);
41
-
42
- const output = document.getElementById("output") as HTMLPreElement;
43
- const log = (msg: string) => { console.log(msg); output.textContent += msg + "\n"; };
44
-
45
- cde.ctx = {
46
- client: {
47
- checkPermissionBatch: async () => Array(5).fill({ hasPermission: true }),
48
- getProjectData: async () => ({ project: { title: "" }, users: [] }),
49
- listFolders: async () => [],
50
- } as any,
51
- projectId: "mock",
52
- };
53
- await cde.loadFolders();
54
- cde.ctx = undefined;
55
-
56
- cde.onMachineStateChanged.add((s) => log(` → ${s.kind}`));
57
- cde.onMetadataViewsChanged.add((views) => log(` [onMetadataViewsChanged] ${views.length} view(s)`));
58
-
59
- /* MD
60
- ### 📋 Initializing views from config
61
- After loading from the backend, views and the last active view ID are pushed into
62
- CDEManager through `initMetadataViews`. This populates the internal view list and
63
- fires the views-changed event so any subscribed component can render immediately.
64
- The active view controls which fields `getSelectedFiles` uses for grouping when
65
- metadata mode is on.
66
- */
67
-
68
- log("\n--- init views ---");
69
- const savedViews: CDEMetadataView[] = [
70
- { id: "view-str", name: "Structural", fields: ["discipline", "phase"] },
71
- { id: "view-mep", name: "MEP", fields: ["discipline", "zone"] },
72
- ];
73
- cde.initMetadataViews(savedViews, "view-str");
74
-
75
- log(` metadataViews: ${cde.metadataViews.length}`);
76
- log(` activeMetadataViewId: ${cde.activeMetadataViewId}`);
77
- log(` activeMetadataView name: ${cde.activeMetadataView?.name}`);
78
-
79
- /* MD
80
- ### 🔀 Switching the active view
81
- The active view can be changed from idle, a selection, or while the viewer is open.
82
- Switching resets the selected metadata group so the table doesn't show a stale
83
- filter from the previous view's grouping. The transition doesn't change the machine
84
- state kind — it's a targeted property update, not a full state change.
85
- */
86
-
87
- log("\n--- switch active view ---");
88
- cde.sendMachineEvent({ type: "SET_ACTIVE_METADATA_VIEW", id: "view-mep" });
89
- log(` active: ${cde.activeMetadataView?.name}`);
90
-
91
- cde.sendMachineEvent({ type: "SET_ACTIVE_METADATA_VIEW", id: "view-str" });
92
- log(` active: ${cde.activeMetadataView?.name}`);
93
-
94
- /* MD
95
- ### ✏️ Staging view changes
96
- Adding, updating, and removing views all operate on the `pendingViews` list inside
97
- the machine state. The committed view list is unchanged until the save fires. Adding
98
- a view generates a stable random ID immediately, so the UI can reference it for
99
- subsequent updates within the same session without waiting for a server response.
100
- */
101
-
102
- log("\n--- stage: add, update, delete ---");
103
- cde.sendMachineEvent({ type: "START_CONFIGURE_METADATA_VIEWS" });
104
-
105
- // Add a new view — gets a UUID immediately.
106
- cde.sendMachineEvent({ type: "ADD_METADATA_VIEW" });
107
-
108
- if (cde.machineState.kind === "configuringMetadataViews") {
109
- const newView = cde.machineState.pendingViews.find(v => v.name === "New View")!;
110
- log(` new view id: ${newView.id.slice(0, 8)}…`);
111
-
112
- // Name it and set its fields.
113
- cde.sendMachineEvent({
114
- type: "UPDATE_METADATA_VIEW",
115
- id: newView.id,
116
- view: { ...newView, name: "Civil", fields: ["discipline", "zone", "level"] },
117
- });
118
-
119
- log(` views in pending: ${cde.machineState.pendingViews.length}`);
120
- log(` updated view name: ${cde.machineState.pendingViews.find(v => v.id === newView.id)?.name}`);
121
- }
122
-
123
- // Remove an existing view from the pending list.
124
- cde.sendMachineEvent({ type: "DELETE_METADATA_VIEW", id: "view-mep" });
125
- if (cde.machineState.kind === "configuringMetadataViews") {
126
- log(` views after delete: ${cde.machineState.pendingViews.length}`);
127
- }
128
-
129
- cde.sendMachineEvent({ type: "CANCEL_CONFIGURE_METADATA_VIEWS" });
130
- // Cancelled — committed view list is unchanged.
131
- log(` committed views after cancel: ${cde.metadataViews.length}`);
132
-
133
- /* MD
134
- ### 💾 Committing views
135
- Saving replaces the committed view list with the pending one and fires the views-
136
- changed event. The user's personal config is updated at the same time if the account
137
- has create permission — the same config that `loadUserConfig` reads back on the
138
- next session load. Without a real user identity in the mock, the persistence step is
139
- silently skipped but the local update still applies.
140
- */
141
-
142
- log("\n--- commit ---");
143
- cde.sendMachineEvent({ type: "START_CONFIGURE_METADATA_VIEWS" });
144
-
145
- cde.sendMachineEvent({ type: "ADD_METADATA_VIEW" });
146
- if (cde.machineState.kind === "configuringMetadataViews") {
147
- const civil = cde.machineState.pendingViews.find(v => v.name === "New View")!;
148
- cde.sendMachineEvent({
149
- type: "UPDATE_METADATA_VIEW",
150
- id: civil.id,
151
- view: { ...civil, name: "Civil", fields: ["discipline", "zone"] },
152
- });
153
- }
154
- cde.sendMachineEvent({ type: "DELETE_METADATA_VIEW", id: "view-mep" });
155
-
156
- if (cde.machineState.kind === "configuringMetadataViews") {
157
- log(` pending: ${cde.machineState.pendingViews.length} view(s)`);
158
- }
159
-
160
- await new Promise<void>(resolve => {
161
- cde.onMachineStateChanged.add((s) => { if (s.kind === "idle") resolve(); });
162
- cde.sendMachineEvent({ type: "SAVE_METADATA_VIEWS" });
163
- });
164
-
165
- log(` state after save: ${cde.machineState.kind}`);
166
- log(` committed views: ${cde.metadataViews.map(v => v.name).join(", ")}`);
1
+ /* MD
2
+ ## Metadata views — organize fields into named table layouts
3
+ ---
4
+ A structural engineer and an MEP coordinator look at the same file list but care
5
+ about completely different metadata. Showing every field to everyone produces a
6
+ wide table that is hard to navigate. Metadata views let each role define which
7
+ fields appear in which order — saving the layout so the table opens correctly next
8
+ time without requiring a manual setup every session.
9
+
10
+ CDEManager stores a list of named views, each carrying an ordered set of field keys.
11
+ An active view filters both which columns are visible and which metadata groupings
12
+ appear in the sidebar. Changes to the view list are staged in memory first, just like
13
+ schema changes, and saved in one batch — so the user can add, rename, and remove
14
+ views without any partial state reaching the backend.
15
+
16
+ This tutorial covers initializing views from a saved configuration; switching the
17
+ active view and reading the result; adding, updating, and removing views in the
18
+ pending list; and committing the full batch, which saves to the user's personal
19
+ config and fires an event with the final view list.
20
+
21
+ By the end, you'll know how to load, display, edit, and persist named metadata
22
+ layouts through the state machine.
23
+ */
24
+
25
+ import * as OBC from "@thatopen/components";
26
+ // In production platform apps, CDEManager is loaded through the platform client:
27
+ // const cde = await client.initBuiltInComponent(CDEManager.uuid, components);
28
+ // Here we import directly from source for local testing.
29
+ import { CDEManager } from "../../index";
30
+ import type { CDEMetadataView } from "../../src/types";
31
+
32
+ /* MD
33
+ ### 🛠️ Setting up
34
+ Loading views from a saved config and switching the active view don't require
35
+ permissions. We still simulate the startup step to load permissions so the save
36
+ path works later, then clear the context — staging is in-memory only.
37
+ */
38
+
39
+ const components = new OBC.Components();
40
+ const cde = components.get(CDEManager);
41
+
42
+ const output = document.getElementById("output") as HTMLPreElement;
43
+ const log = (msg: string) => { console.log(msg); output.textContent += msg + "\n"; };
44
+
45
+ cde.ctx = {
46
+ client: {
47
+ checkPermissionBatch: async () => Array(5).fill({ hasPermission: true }),
48
+ getProjectData: async () => ({ project: { title: "" }, users: [] }),
49
+ listFolders: async () => [],
50
+ } as any,
51
+ projectId: "mock",
52
+ };
53
+ await cde.loadFolders();
54
+ cde.ctx = undefined;
55
+
56
+ cde.onMachineStateChanged.add((s) => log(` → ${s.kind}`));
57
+ cde.onMetadataViewsChanged.add((views) => log(` [onMetadataViewsChanged] ${views.length} view(s)`));
58
+
59
+ /* MD
60
+ ### 📋 Initializing views from config
61
+ After loading from the backend, views and the last active view ID are pushed into
62
+ CDEManager through `initMetadataViews`. This populates the internal view list and
63
+ fires the views-changed event so any subscribed component can render immediately.
64
+ The active view controls which fields `getSelectedFiles` uses for grouping when
65
+ metadata mode is on.
66
+ */
67
+
68
+ log("\n--- init views ---");
69
+ const savedViews: CDEMetadataView[] = [
70
+ { id: "view-str", name: "Structural", fields: ["discipline", "phase"] },
71
+ { id: "view-mep", name: "MEP", fields: ["discipline", "zone"] },
72
+ ];
73
+ cde.initMetadataViews(savedViews, "view-str");
74
+
75
+ log(` metadataViews: ${cde.metadataViews.length}`);
76
+ log(` activeMetadataViewId: ${cde.activeMetadataViewId}`);
77
+ log(` activeMetadataView name: ${cde.activeMetadataView?.name}`);
78
+
79
+ /* MD
80
+ ### 🔀 Switching the active view
81
+ The active view can be changed from idle, a selection, or while the viewer is open.
82
+ Switching resets the selected metadata group so the table doesn't show a stale
83
+ filter from the previous view's grouping. The transition doesn't change the machine
84
+ state kind — it's a targeted property update, not a full state change.
85
+ */
86
+
87
+ log("\n--- switch active view ---");
88
+ cde.sendMachineEvent({ type: "SET_ACTIVE_METADATA_VIEW", id: "view-mep" });
89
+ log(` active: ${cde.activeMetadataView?.name}`);
90
+
91
+ cde.sendMachineEvent({ type: "SET_ACTIVE_METADATA_VIEW", id: "view-str" });
92
+ log(` active: ${cde.activeMetadataView?.name}`);
93
+
94
+ /* MD
95
+ ### ✏️ Staging view changes
96
+ Adding, updating, and removing views all operate on the `pendingViews` list inside
97
+ the machine state. The committed view list is unchanged until the save fires. Adding
98
+ a view generates a stable random ID immediately, so the UI can reference it for
99
+ subsequent updates within the same session without waiting for a server response.
100
+ */
101
+
102
+ log("\n--- stage: add, update, delete ---");
103
+ cde.sendMachineEvent({ type: "START_CONFIGURE_METADATA_VIEWS" });
104
+
105
+ // Add a new view — gets a UUID immediately.
106
+ cde.sendMachineEvent({ type: "ADD_METADATA_VIEW" });
107
+
108
+ if (cde.machineState.kind === "configuringMetadataViews") {
109
+ const newView = cde.machineState.pendingViews.find(v => v.name === "New View")!;
110
+ log(` new view id: ${newView.id.slice(0, 8)}…`);
111
+
112
+ // Name it and set its fields.
113
+ cde.sendMachineEvent({
114
+ type: "UPDATE_METADATA_VIEW",
115
+ id: newView.id,
116
+ view: { ...newView, name: "Civil", fields: ["discipline", "zone", "level"] },
117
+ });
118
+
119
+ log(` views in pending: ${cde.machineState.pendingViews.length}`);
120
+ log(` updated view name: ${cde.machineState.pendingViews.find(v => v.id === newView.id)?.name}`);
121
+ }
122
+
123
+ // Remove an existing view from the pending list.
124
+ cde.sendMachineEvent({ type: "DELETE_METADATA_VIEW", id: "view-mep" });
125
+ if (cde.machineState.kind === "configuringMetadataViews") {
126
+ log(` views after delete: ${cde.machineState.pendingViews.length}`);
127
+ }
128
+
129
+ cde.sendMachineEvent({ type: "CANCEL_CONFIGURE_METADATA_VIEWS" });
130
+ // Cancelled — committed view list is unchanged.
131
+ log(` committed views after cancel: ${cde.metadataViews.length}`);
132
+
133
+ /* MD
134
+ ### 💾 Committing views
135
+ Saving replaces the committed view list with the pending one and fires the views-
136
+ changed event. The user's personal config is updated at the same time if the account
137
+ has create permission — the same config that `loadUserConfig` reads back on the
138
+ next session load. Without a real user identity in the mock, the persistence step is
139
+ silently skipped but the local update still applies.
140
+ */
141
+
142
+ log("\n--- commit ---");
143
+ cde.sendMachineEvent({ type: "START_CONFIGURE_METADATA_VIEWS" });
144
+
145
+ cde.sendMachineEvent({ type: "ADD_METADATA_VIEW" });
146
+ if (cde.machineState.kind === "configuringMetadataViews") {
147
+ const civil = cde.machineState.pendingViews.find(v => v.name === "New View")!;
148
+ cde.sendMachineEvent({
149
+ type: "UPDATE_METADATA_VIEW",
150
+ id: civil.id,
151
+ view: { ...civil, name: "Civil", fields: ["discipline", "zone"] },
152
+ });
153
+ }
154
+ cde.sendMachineEvent({ type: "DELETE_METADATA_VIEW", id: "view-mep" });
155
+
156
+ if (cde.machineState.kind === "configuringMetadataViews") {
157
+ log(` pending: ${cde.machineState.pendingViews.length} view(s)`);
158
+ }
159
+
160
+ await new Promise<void>(resolve => {
161
+ cde.onMachineStateChanged.add((s) => { if (s.kind === "idle") resolve(); });
162
+ cde.sendMachineEvent({ type: "SAVE_METADATA_VIEWS" });
163
+ });
164
+
165
+ log(` state after save: ${cde.machineState.kind}`);
166
+ log(` committed views: ${cde.metadataViews.map(v => v.name).join(", ")}`);