@thatopen/services 0.6.0 → 0.7.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 (71) hide show
  1. package/README.md +62 -62
  2. package/dist/built-in/index.d.ts +485 -100
  3. package/dist/cli.js +12 -23
  4. package/dist/index.cjs.js +2 -2
  5. package/dist/index.es.js +41 -50
  6. package/dist/vite-env.d.ts +1 -1
  7. package/docs/ai-quickstart.md +18 -3
  8. package/docs/cli/create.md +29 -29
  9. package/docs/cli/local-server.md +38 -38
  10. package/docs/cli/login.md +32 -32
  11. package/docs/cli/publish.md +31 -31
  12. package/docs/cli/run.md +26 -26
  13. package/docs/cli/serve.md +43 -43
  14. package/docs/cli/swap.md +30 -30
  15. package/docs/flow-architecture.md +1 -1
  16. package/docs/flow-plugin-guide.md +1 -1
  17. package/docs/platform-token.md +81 -0
  18. package/docs/revit-collab-quickstart.md +89 -18
  19. package/docs/rhino-interop-quickstart.md +391 -0
  20. package/package.json +1 -1
  21. package/resources/AGENTS.md +40 -40
  22. package/src/built-in/CDEManager/example.ts +214 -214
  23. package/src/built-in/CDEManager/examples/FileEditing/example.ts +226 -226
  24. package/src/built-in/CDEManager/examples/FileMoves/example.ts +186 -186
  25. package/src/built-in/CDEManager/examples/FileOperations/example.ts +295 -295
  26. package/src/built-in/CDEManager/examples/FileTransfers/example.ts +210 -210
  27. package/src/built-in/CDEManager/examples/FolderManagement/example.ts +230 -230
  28. package/src/built-in/CDEManager/examples/MetadataSchema/example.ts +230 -230
  29. package/src/built-in/CDEManager/examples/MetadataViews/example.ts +166 -166
  30. package/src/built-in/CDEManager/examples/ProjectConfig/example.ts +177 -177
  31. package/src/built-in/UIManager/src/app/example.ts +97 -97
  32. package/src/built-in/UIManager/src/app/examples/AppState/example.ts +140 -140
  33. package/src/built-in/UIManager/src/app/examples/Banner/example.ts +159 -159
  34. package/src/built-in/UIManager/src/app/examples/Contexts/example.ts +123 -123
  35. package/src/built-in/UIManager/src/app/examples/FileDrop/example.ts +124 -124
  36. package/src/built-in/UIManager/src/app/examples/FloatingLayout/example.ts +90 -90
  37. package/src/built-in/UIManager/src/app/examples/Modal/example.ts +163 -163
  38. package/src/built-in/UIManager/src/app/examples/Notifications/example.ts +133 -133
  39. package/src/built-in/UIManager/src/app/examples/ProjectFileStorage/example.ts +150 -150
  40. package/src/built-in/UIManager/src/app/examples/Sidebar/example.ts +102 -102
  41. package/src/built-in/UIManager/src/clashes-panel/example.ts +183 -183
  42. package/src/built-in/UIManager/src/git-history-panel/example.ts +70 -70
  43. package/src/built-in/UIManager/src/models-list/example.ts +122 -122
  44. package/src/built-in/UIManager/src/topics-panel/example.ts +170 -170
  45. package/src/built-in/index.ts +485 -100
  46. package/src/cli/templates/app/index.html +35 -35
  47. package/src/cli/templates/app/package.json +32 -32
  48. package/src/cli/templates/app/src/bim-components/CloudRunner/index.ts +95 -95
  49. package/src/cli/templates/app/src/bim-components/CloudRunner/src/index.ts +1 -1
  50. package/src/cli/templates/app/src/bim-components/CloudRunner/src/types.ts +5 -5
  51. package/src/cli/templates/app/src/bim-components/index.ts +1 -1
  52. package/src/cli/templates/app/src/globals.ts +1 -1
  53. package/src/cli/templates/app/src/ui-components/app-info-section/index.ts +26 -26
  54. package/src/cli/templates/app/src/ui-components/app-info-section/src/index.ts +1 -1
  55. package/src/cli/templates/app/src/ui-components/app-info-section/src/types.ts +15 -15
  56. package/src/cli/templates/app/src/ui-components/cloud-runner-section/index.ts +37 -37
  57. package/src/cli/templates/app/src/ui-components/cloud-runner-section/src/index.ts +1 -1
  58. package/src/cli/templates/app/src/ui-components/cloud-runner-section/src/types.ts +14 -14
  59. package/src/cli/templates/app/src/ui-components/index.ts +2 -2
  60. package/src/cli/templates/app/tsconfig.json +16 -16
  61. package/src/cli/templates/app/vite.config.js +57 -57
  62. package/src/cli/templates/cloud-component/README.md +205 -205
  63. package/src/cli/templates/cloud-component/_thatopen +5 -5
  64. package/src/cli/templates/cloud-component/declarations.json +4 -4
  65. package/src/cli/templates/cloud-component/package.json +21 -21
  66. package/src/cli/templates/cloud-component/src/main.ts +70 -70
  67. package/src/cli/templates/cloud-component/tsconfig.json +16 -16
  68. package/src/cli/templates/cloud-component/vite.config.js +46 -46
  69. package/src/cli/templates/shared/AGENTS.md +8 -8
  70. package/src/cli/templates/shared/CLAUDE.md +1 -1
  71. 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(", ")}`);