@thatopen/services 0.0.1

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 (80) hide show
  1. package/CONTEXT.md +258 -0
  2. package/README.md +285 -0
  3. package/dist/built-in/index.d.ts +723 -0
  4. package/dist/cli/commands/create-tests.d.ts +3 -0
  5. package/dist/cli/commands/create.d.ts +3 -0
  6. package/dist/cli/commands/local-server.d.ts +3 -0
  7. package/dist/cli/commands/login.d.ts +3 -0
  8. package/dist/cli/commands/publish.d.ts +3 -0
  9. package/dist/cli/commands/run.d.ts +3 -0
  10. package/dist/cli/commands/serve-tests.d.ts +3 -0
  11. package/dist/cli/commands/serve.d.ts +3 -0
  12. package/dist/cli/index.d.ts +1 -0
  13. package/dist/cli/lib/config.d.ts +25 -0
  14. package/dist/cli/lib/declarations.d.ts +19 -0
  15. package/dist/cli/lib/engine-script.d.ts +10 -0
  16. package/dist/cli/lib/execution-manager.d.ts +52 -0
  17. package/dist/cli/lib/zip.d.ts +6 -0
  18. package/dist/cli.js +11566 -0
  19. package/dist/core/client.d.ts +682 -0
  20. package/dist/core/client.test.d.ts +1 -0
  21. package/dist/core/platform-client.d.ts +106 -0
  22. package/dist/core/platform-client.test.d.ts +1 -0
  23. package/dist/core/request-error.d.ts +25 -0
  24. package/dist/core/request-error.test.d.ts +1 -0
  25. package/dist/index.cjs.js +2 -0
  26. package/dist/index.d.ts +12 -0
  27. package/dist/index.es.js +3310 -0
  28. package/dist/types/base.d.ts +9 -0
  29. package/dist/types/context.d.ts +20 -0
  30. package/dist/types/execution.d.ts +19 -0
  31. package/dist/types/files.d.ts +19 -0
  32. package/dist/types/item.dto.d.ts +24 -0
  33. package/dist/types/items.d.ts +57 -0
  34. package/dist/types/projects.d.ts +59 -0
  35. package/dist/types/response.d.ts +10 -0
  36. package/dist/types/storage.d.ts +11 -0
  37. package/dist/vite-env.d.ts +1 -0
  38. package/package.json +100 -0
  39. package/src/built-in/index.ts +755 -0
  40. package/src/cli/templates/bim/CONTEXT.md +244 -0
  41. package/src/cli/templates/bim/package.json +26 -0
  42. package/src/cli/templates/bim/src/app.ts +16 -0
  43. package/src/cli/templates/bim/src/bim-components/CloudRunner/index.ts +91 -0
  44. package/src/cli/templates/bim/src/bim-components/CloudRunner/src/index.ts +1 -0
  45. package/src/cli/templates/bim/src/bim-components/CloudRunner/src/types.ts +5 -0
  46. package/src/cli/templates/bim/src/bim-components/index.ts +1 -0
  47. package/src/cli/templates/bim/src/globals.ts +1 -0
  48. package/src/cli/templates/bim/src/main.ts +90 -0
  49. package/src/cli/templates/bim/src/setups/cloud-runner.ts +13 -0
  50. package/src/cli/templates/bim/src/setups/index.ts +3 -0
  51. package/src/cli/templates/bim/src/setups/ui-manager.ts +27 -0
  52. package/src/cli/templates/bim/src/setups/viewports-manager.ts +22 -0
  53. package/src/cli/templates/bim/src/ui-components/app-info-section/index.ts +26 -0
  54. package/src/cli/templates/bim/src/ui-components/app-info-section/src/index.ts +1 -0
  55. package/src/cli/templates/bim/src/ui-components/app-info-section/src/types.ts +15 -0
  56. package/src/cli/templates/bim/src/ui-components/cloud-runner-section/index.ts +37 -0
  57. package/src/cli/templates/bim/src/ui-components/cloud-runner-section/src/index.ts +1 -0
  58. package/src/cli/templates/bim/src/ui-components/cloud-runner-section/src/types.ts +14 -0
  59. package/src/cli/templates/bim/src/ui-components/index.ts +2 -0
  60. package/src/cli/templates/cloud/CONTEXT.md +205 -0
  61. package/src/cli/templates/cloud/_thatopen +5 -0
  62. package/src/cli/templates/cloud/declarations.json +4 -0
  63. package/src/cli/templates/cloud/package.json +22 -0
  64. package/src/cli/templates/cloud/src/main.ts +70 -0
  65. package/src/cli/templates/cloud-test/CONTEXT.md +56 -0
  66. package/src/cli/templates/cloud-test/_thatopen +5 -0
  67. package/src/cli/templates/cloud-test/package.json +22 -0
  68. package/src/cli/templates/cloud-test/src/main.ts +565 -0
  69. package/src/cli/templates/default/CONTEXT.md +92 -0
  70. package/src/cli/templates/default/package.json +15 -0
  71. package/src/cli/templates/default/src/main.ts +62 -0
  72. package/src/cli/templates/shared/_gitignore +4 -0
  73. package/src/cli/templates/shared/app/index.html +27 -0
  74. package/src/cli/templates/shared/app/tsconfig.json +16 -0
  75. package/src/cli/templates/shared/app/vite.config.js +23 -0
  76. package/src/cli/templates/shared/cloud/tsconfig.json +16 -0
  77. package/src/cli/templates/shared/cloud/vite.config.js +27 -0
  78. package/src/cli/templates/test/CONTEXT.md +53 -0
  79. package/src/cli/templates/test/package.json +25 -0
  80. package/src/cli/templates/test/src/main.ts +955 -0
package/CONTEXT.md ADDED
@@ -0,0 +1,258 @@
1
+ # thatopen-services
2
+
3
+ Client library and CLI for the That Open Platform — a cloud platform for building BIM (Building Information Modeling) software.
4
+
5
+ ## What this repo contains
6
+
7
+ 1. **Library** (`src/core/client.ts`) — `EngineServicesClient`, a TypeScript API client for managing files, folders, apps, cloud components, and executions on the platform.
8
+ 2. **CLI** (`src/cli/`) — The `thatopen` command-line tool for scaffolding and publishing apps and cloud components.
9
+ 3. **Built-in components** (`src/built-in/`) — Type stubs for platform-provided UI components (AppManager, ViewportManager, etc.) that are fetched and evaluated at runtime.
10
+
11
+ ## Project structure
12
+
13
+ ```
14
+ src/
15
+ core/client.ts # EngineServicesClient — the main API class
16
+ cli/
17
+ commands/create.ts # thatopen create — scaffolds new projects
18
+ commands/serve.ts # thatopen serve — dev server (esbuild watch + serve)
19
+ commands/login.ts # thatopen login — authenticate with the platform
20
+ commands/publish.ts # thatopen publish — build and upload to the platform
21
+ commands/run.ts # thatopen run — test cloud components locally
22
+ commands/create-tests.ts # thatopen create-tests — scaffolds test app + test component
23
+ commands/serve-tests.ts # thatopen serve-tests — serves both test projects in parallel
24
+ templates/ # Template generators for scaffolded projects
25
+ lib/ # CLI helper utilities (config, certificates)
26
+ built-in/index.ts # Built-in component type stubs + runtime UUID constants
27
+ types/ # TypeScript type definitions (items, execution, etc.)
28
+ index.ts # Library entry point (re-exports everything)
29
+ ```
30
+
31
+ ## Build system
32
+
33
+ - **Library** builds to CommonJS (`dist/index.cjs.js`) + ESM (`dist/index.es.js`) + types (`dist/index.d.ts`) via Vite (`vite.config.mts`).
34
+ - **CLI** builds to a single `dist/cli.js` executable via Vite (`vite.config.cli.mts`). It bundles commander, jszip, and all library code.
35
+ - TypeScript strict mode is enabled.
36
+
37
+ ### Commands
38
+
39
+ ```bash
40
+ npm run build # Full build (library + CLI)
41
+ npm run build:lib # Library only
42
+ npm run build:cli # CLI only
43
+ ```
44
+
45
+ ### Testing
46
+
47
+ ```bash
48
+ npm run test # Run vitest unit tests (HTTP client contract)
49
+ npm run test:watch # Vitest watch mode
50
+ npm run test:ui # Interactive browser test page
51
+ npm run test:cli-build-app # Scaffold + build a test app
52
+ npm run test:cli-build-component # Scaffold + build a test cloud component
53
+ npm run test:cli-run-component # Run the test cloud component locally
54
+ npm run test:cli-build-tests # Build CLI + scaffold test app & test component into temp/
55
+ npm run test:cli-serve-tests # Serve the test app and test component's local server in parallel
56
+ ```
57
+
58
+ ## Two clients — components vs apps/FE
59
+
60
+ This package ships two clients with overlapping but intentionally different
61
+ surfaces. Pick the one that matches who's calling.
62
+
63
+ ### `EngineServicesClient`
64
+ **For cloud components running inside the platform.** Authenticates via
65
+ API token by default (`?accessToken=`). Supports local-server execution,
66
+ WebSocket execution progress, built-in component runtime helpers, and the
67
+ low-level HTTP surface. This is what you get via
68
+ `EngineServicesClient.fromPlatformContext()` inside a component bundle.
69
+
70
+ ### `PlatformClient`
71
+ **For apps, frontends, and any caller using a user JWT.** Extends
72
+ `EngineServicesClient`; the API-token-compatible surface is inherited and
73
+ the constructor forces `useBearer: true`. On top, it owns the JWT-only
74
+ routes — `getProject`, `getProjectData`, `checkPermission`,
75
+ `checkPermissionBatch` — which hit `ProjectController` in the backend
76
+ (guarded by JWT) and are not reachable with an access token.
77
+
78
+ The constructor accepts either a static JWT or a provider function
79
+ (sync or async) that returns the current JWT. The provider is called on
80
+ every request, so Auth0's `getAccessTokenSilently()` and similar
81
+ refreshing sources Just Work:
82
+
83
+ ```ts
84
+ import { PlatformClient } from 'thatopen-services';
85
+ const client = new PlatformClient(
86
+ () => auth0.getAccessTokenSilently(),
87
+ 'https://api.thatopen.com',
88
+ );
89
+ await client.getProjectData(projectId);
90
+ ```
91
+
92
+ `PlatformClient.fromPlatformContext()` is available for apps running inside
93
+ the platform iframe — it pulls the JWT from
94
+ `window.__THATOPEN_CONTEXT__` and returns a ready-to-use client.
95
+
96
+ Choose by audience:
97
+ - Component code → `EngineServicesClient` (or `EngineServicesClient.fromPlatformContext()`).
98
+ - App / FE / integration with a user JWT → `PlatformClient`.
99
+
100
+ ## Permissions contract (backend coupling)
101
+
102
+ The platform API enforces **project-scoped permission checks**: whenever a
103
+ request carries a `projectId` (URL param, query, or body), the backend
104
+ rejects the call if the resource does not belong to that project or the
105
+ caller lacks permission there — regardless of whether the caller has access
106
+ to the same resource in a different project.
107
+
108
+ Relevant client methods:
109
+
110
+ - `executeComponent(componentId, executionParams, versionTag?)`: include
111
+ `projectId` in `executionParams` to scope the execution. The backend
112
+ validates that the component is linked to that project. Without a
113
+ `projectId`, the execution runs in the user's personal/ownership scope.
114
+ - `listExecutions(componentId, projectId?)`: pass `projectId` to filter
115
+ executions to that project's context.
116
+ - `checkPermission({ resourceType, action, resourceId?, projectId? })`:
117
+ returns `{ hasPermission, scope }`. `scope` is `'global' | 'project' |
118
+ 'entity' | 'none'` — `global` for admin/owner bypass, `project` for a
119
+ role broad grant, `entity` for a per-entity override, `none` for denied.
120
+ - `checkPermissionBatch(checks)`: evaluates a list of checks in one
121
+ round-trip. Useful for hydrating action visibility for many rows without
122
+ N+1 calls.
123
+
124
+ Per-entity permission overrides (`ResourcePermission.removePermission`,
125
+ `ResourcePermission.appliesToDescendants`) are applied automatically on the
126
+ server side when listing project files/folders — no client change needed.
127
+
128
+
129
+ ### Publishing to npm
130
+
131
+ ```bash
132
+ yarn create-version # Build → changeset → version → publish
133
+ ```
134
+
135
+ ## Key concepts
136
+
137
+ ### Apps vs Cloud Components
138
+
139
+ | | Apps | Cloud Components |
140
+ |---|---|---|
141
+ | **Runs in** | Browser (iframe on the platform) | Server (Node.js child process) |
142
+ | **Item type** | `APP` | `TOOL` |
143
+ | **Entry point** | Side effects in `main.ts` (renders UI) | `export async function main()` |
144
+ | **Context** | `window.__THATOPEN_CONTEXT__` provides `{ appId, projectId, accessToken, apiUrl }` | Globals: `thatOpenServices`, `executionParams`, `executionContext` (`{ projectId?, executionId, toolId, toolVersion }`), `executionReporter` (`message/error/progress`). `OBC`, `THREE`, `web-ifc`, `fs` are NOT injected — import them and let the bundler include them. |
145
+ | **Build output** | IIFE `dist/bundle.js` (all deps bundled) | IIFE `dist/bundle.js` (only `thatopen-services` externalized) |
146
+ | **Template** | `bim`, `default`, or `test` | `cloud` or `cloud-test` |
147
+
148
+ ### Authentication
149
+
150
+ Two modes, controlled by `useBearer` in the constructor:
151
+ - **Query parameter** (default): Sends `accessToken` as a URL query param. Used with platform API tokens.
152
+ - **Bearer header** (`useBearer: true`): Sends as `Authorization: Bearer <token>`. Used with Auth0 JWTs inside platform apps.
153
+
154
+ ### Built-in components
155
+
156
+ Built-in components are platform-hosted UI modules fetched at runtime. Usage pattern:
157
+
158
+ ```ts
159
+ import { AppManager, ViewportManager } from "thatopen-services";
160
+
161
+ // Register all library globals once
162
+ client.setBuiltInGlobals({ OBC, OBF, BUI, CUI, THREE, FRAGS });
163
+
164
+ // Fetch, evaluate, and register with OBC — globals are automatically applied
165
+ await client.initBuiltInComponent(AppManager, components);
166
+ await client.initBuiltInComponent(ViewportManager, components);
167
+
168
+ // Use via OBC component system
169
+ const app = components.get(AppManager);
170
+ const viewports = components.get(ViewportManager);
171
+ ```
172
+
173
+ Available built-in components:
174
+
175
+ | Component | Purpose |
176
+ |-----------|---------|
177
+ | `AppManager` | App shell — CSS grid layout with sidebar for switching layouts |
178
+ | `ViewportManager` | Factory for 3D viewports with pre-configured world |
179
+ | `LoadModelButton` | Button + dropdown for loading IFC / Fragments files |
180
+ | `ViewerToolbar` | Toolbar with Show/Hide/Focus/Isolate and color palette |
181
+ | `ModelsPanel` | Panel listing loaded models with search and load button |
182
+ | `ModelsDropdown` | Dropdown selector listing loaded models |
183
+ | `ClassificationsList` | Hierarchical table of IFC classification data |
184
+ | `ClashesList` | Interactive clash detection results with highlighting |
185
+ | `ClippingsList` | Panel listing clipping planes with controls |
186
+ | `LengthMeasuringsList` | Panel listing length measurements with totals |
187
+ | `AreaMeasuringsList` | Panel listing area measurements with totals |
188
+ | `ColorsPalette` | Color picker with Highlighter style swatches |
189
+ | `HighlightersList` | Panel listing Highlighter styles with manage actions |
190
+ | `QtoComparisonList` | Side-by-side quantity comparison for two elements |
191
+ | `QueriesHierarchy` | Recursive multi-level query browser |
192
+ | `CustomViewLegend` | Color legend overlay |
193
+ | `ScreenshotAnnotator` | Modal for annotating screenshots via MarkerJS |
194
+
195
+ Full API reference with config interfaces, method signatures, and `@example` blocks: `src/built-in/index.ts`.
196
+
197
+ ### Configuration files
198
+
199
+ - **Global**: `~/.thatopen/config.json` — `{ accessToken, apiUrl }`
200
+ - **Local** (per project): `.thatopen` — `{ accessToken, apiUrl, appId?, componentId?, itemType? }`
201
+ - Local config takes priority. Created by `thatopen login --local`.
202
+
203
+ ## API surface (EngineServicesClient)
204
+
205
+ ### Files
206
+ - `listFiles(filters?)` / `getFile(id, props?)` / `createFile(data)` / `updateFile(id, data)`
207
+ - `archiveFile(id)` / `recoverFile(id)` / `downloadFile(id, params?)` / `getFileMetadata(id, params?)`
208
+
209
+ ### Folders
210
+ - `listFolders(params?)` / `getFolder(id)` / `createFolder(name, parentId?)`
211
+ - `updateFolder(id, params)` / `archiveFolder(id)` / `recoverFolder(id)` / `downloadFolder(id)`
212
+
213
+ ### Components
214
+ - `listComponents(params?)` / `getComponent(id, props?)` / `createComponent(data)` / `updateComponent(id, data)`
215
+ - `archiveComponent(id)` / `recoverComponent(id)` / `downloadComponent(id, params?)` / `downloadComponentBundle(id, params?)`
216
+
217
+ ### Apps
218
+ - `listApps(params?)` / `createApp(data)` / `archiveApp(id)`
219
+ - `downloadApp(id, params?)` / `downloadAppBundle(id, params?)`
220
+
221
+ ### Execution (cloud components)
222
+ - `executeComponent(componentId, params, versionTag?)` — triggers server-side execution, returns `{ executionId }`
223
+ - `abortExecution(executionId)` / `listExecutions(componentId)` / `getExecution(executionId)`
224
+ - `onExecutionProgress(executionId, callback)` — real-time WebSocket subscription
225
+
226
+ ### Built-in components
227
+ - `setBuiltInGlobals(globals)` — registers globals once; subsequent `initBuiltInComponent` calls use them automatically
228
+ - `getBuiltInComponent(name)` — fetches JS bundle by name
229
+ - `initBuiltInComponent(component, components, globals?)` — fetches, evaluates, and registers (uses stored globals if `globals` omitted)
230
+
231
+ ### Hidden files
232
+ - `createHiddenFile(file, parentId)` / `deleteHiddenFile(id)` / `getHiddenFile(id)`
233
+ - `downloadHiddenFile(id)` / `getHiddenFilesByParent(parentId)` / `deleteHiddenFilesByParent(parentId)`
234
+
235
+ ### General
236
+ - `updateItem(id, params)` / `createVersion(id, file, tag, extraProps?, metadata?)`
237
+ - `getProjectData(projectId)` / `checkPermission(params)`
238
+
239
+ ## CLI commands
240
+
241
+ ```bash
242
+ thatopen create <name> [--template bim|default|cloud|test|cloud-test]
243
+ # Scaffold project + auto npm install
244
+ # Use "." as name to scaffold in current directory
245
+ thatopen serve [--port N] # Dev server (esbuild watch + serve bundle)
246
+ thatopen login [--token T] [--api-url U] [--local] # Authenticate
247
+ thatopen publish [--name N] [--version-tag T] [--skip-build] [--app-id ID | --component-id ID]
248
+ thatopen run [--params '{}'] [--skip-build] # Test cloud component locally
249
+ thatopen local-server [--port N] [--skip-build] # Local execution server (API-compatible)
250
+ thatopen create-tests [directory] # Scaffold test app + test component (cleans directory first)
251
+ thatopen serve-tests [directory] # Serve test app + test component in parallel
252
+ ```
253
+
254
+ ## Dependencies
255
+
256
+ - **Runtime**: `dotenv`, `socket.io-client`
257
+ - **Peer** (optional): `@thatopen/components` ^3.3.1, `@thatopen/ui` ^3.3.3, `three` ^0.182.0
258
+ - **CLI bundled**: `commander`, `jszip`
package/README.md ADDED
@@ -0,0 +1,285 @@
1
+ # thatopen-services
2
+
3
+ Client library and CLI for building BIM apps and cloud components on the [That Open Platform](https://platform.thatopen.com).
4
+
5
+ ## Quick Start
6
+
7
+ ### Create a BIM app
8
+
9
+ ```bash
10
+ # Install the services package globally
11
+ npm i thatopen-services -g
12
+ ```
13
+
14
+ Then, create a brand new app repository:
15
+
16
+ ```bash
17
+ npx thatopen create my-app
18
+ cd my-app
19
+ npm run dev
20
+
21
+ # Open your project on platform.thatopen.com and click the debug button
22
+ ```
23
+
24
+ You can also scaffold in the current directory:
25
+
26
+ ```bash
27
+ mkdir my-app && cd my-app
28
+ npx thatopen create .
29
+ npm run dev
30
+ ```
31
+
32
+ ### Create a cloud component
33
+
34
+ ```bash
35
+ npx thatopen create my-component --template cloud
36
+ cd my-component
37
+ npm run run # Build and test locally
38
+ ```
39
+
40
+ ### Templates
41
+
42
+ | Template | Command | What you get |
43
+ |----------|---------|--------------|
44
+ | `bim` (default) | `npx thatopen create my-app` | Three.js + BIM viewer + platform UI components |
45
+ | `default` | `npx thatopen create my-app --template default` | Minimal app showing platform context |
46
+ | `cloud` | `npx thatopen create my-component --template cloud` | Server-side Node.js component |
47
+ | `test` | `npx thatopen create my-tests --template test` | Browser test app that exercises every API endpoint |
48
+ | `cloud-test` | `npx thatopen create my-tests --template cloud-test` | Cloud component test suite for server-side API testing |
49
+
50
+ Use `npx thatopen create .` to scaffold in the current directory instead of creating a new one.
51
+
52
+ ## What's in this package
53
+
54
+ - **Library** — `EngineServicesClient` for interacting with the That Open API (files, folders, apps, cloud components, executions, permissions)
55
+ - **CLI** — `thatopen` command for scaffolding and publishing
56
+ - **Built-in component types** — TypeScript stubs for platform-hosted UI components (AppManager, ViewportManager, etc.)
57
+
58
+ ## Library usage
59
+
60
+ ```typescript
61
+ import { EngineServicesClient } from 'thatopen-services';
62
+
63
+ const client = new EngineServicesClient(accessToken, apiUrl);
64
+
65
+ // Files
66
+ const files = await client.listFiles();
67
+ await client.createFile({ file: blob, name: "model.ifc", versionTag: "v1" });
68
+ const response = await client.downloadFile(fileId);
69
+
70
+ // Folders
71
+ const folders = await client.listFolders();
72
+ await client.createFolder("My Folder");
73
+
74
+ // Cloud component execution
75
+ const { executionId } = await client.executeComponent(componentId, { param: "value" });
76
+ client.onExecutionProgress(executionId, (data) => {
77
+ console.log(data.progressUpdate, data.messageUpdate);
78
+ });
79
+ ```
80
+
81
+ Inside platform apps, use the Auth0 JWT from the platform context:
82
+
83
+ ```typescript
84
+ const ctx = window.__THATOPEN_CONTEXT__; // { appId, projectId, accessToken, apiUrl }
85
+ const client = new EngineServicesClient(ctx.accessToken, ctx.apiUrl, { useBearer: true });
86
+ ```
87
+
88
+ ## CLI commands
89
+
90
+ | Command | Description |
91
+ |---------|-------------|
92
+ | `thatopen create <name> [--template bim\|default\|cloud\|test\|cloud-test]` | Scaffold a new project (use `.` for current directory) |
93
+ | `thatopen serve [--port N]` | Dev server (esbuild watch + serve bundle) |
94
+ | `thatopen login [--token T] [--local]` | Authenticate with the platform |
95
+ | `thatopen publish` | Build and publish to the platform |
96
+ | `thatopen run [--params '{}']` | Build and test a cloud component locally |
97
+ | `thatopen create-tests [directory]` | Scaffold both a test app and test cloud component |
98
+ | `thatopen serve-tests [directory]` | Serve both the test app and test component in parallel |
99
+
100
+ ## App workflow
101
+
102
+ Apps run inside the That Open Platform (platform.thatopen.com) within a project. They are served inside the platform's iframe — not as standalone websites.
103
+
104
+ ```bash
105
+ # 1. Create project (dependencies are installed automatically)
106
+ npx thatopen create my-app
107
+ cd my-app
108
+
109
+ # 2. Develop locally
110
+ npm run dev
111
+ # Open your project on the platform and click the debug button.
112
+ # Live reload is enabled — save a file to rebuild.
113
+
114
+ # 3. Authenticate
115
+ npm run login -- --token <your-token>
116
+
117
+ # 4. Publish
118
+ npm run publish
119
+ ```
120
+
121
+ ## Cloud component workflow
122
+
123
+ ```bash
124
+ # 1. Create project (dependencies are installed automatically)
125
+ npx thatopen create my-component --template cloud
126
+ cd my-component
127
+
128
+ # 2. Run locally
129
+ npm run run
130
+
131
+ # 3. Pass parameters
132
+ npx thatopen run --params '{"inputFile": "model.ifc"}'
133
+
134
+ # 4. Authenticate and publish
135
+ npm run login -- --token <your-token>
136
+ npm run publish
137
+ ```
138
+
139
+ Cloud components export an `async function main()` that runs on the server. The execution engine provides globals:
140
+
141
+ | Global | Purpose |
142
+ |--------|---------|
143
+ | `thatOpenServices` | Authenticated `EngineServicesClient` |
144
+ | `executionParams` | Parameters passed by the caller |
145
+ | `executionReporter` | `{ message(msg), progress(pct) }` for live feedback |
146
+ | `OBC` | `@thatopen/components` — BIM engine |
147
+ | `THREE` | `three` — 3D math and geometry |
148
+ | `fs` | Node.js filesystem |
149
+
150
+ ## Built-in components
151
+
152
+ Platform-hosted UI components loaded at runtime:
153
+
154
+ ```typescript
155
+ import { AppManager, ViewportManager } from "thatopen-services";
156
+
157
+ // Register all library globals once
158
+ client.setBuiltInGlobals({ OBC, OBF, BUI, CUI, THREE, FRAGS });
159
+
160
+ // Load built-in components — globals are automatically applied
161
+ await client.initBuiltInComponent(AppManager, components);
162
+ await client.initBuiltInComponent(ViewportManager, components);
163
+
164
+ const app = components.get(AppManager);
165
+ const viewports = components.get(ViewportManager);
166
+ const { element, world } = await viewports.create();
167
+ ```
168
+
169
+ | Component | Purpose |
170
+ |-----------|---------|
171
+ | `AppManager` | App shell — CSS grid layout with sidebar for switching layouts |
172
+ | `ViewportManager` | Factory for 3D viewports with pre-configured world |
173
+ | `LoadModelButton` | Button + dropdown for loading IFC / Fragments files |
174
+ | `ViewerToolbar` | Toolbar with Show/Hide/Focus/Isolate and color palette |
175
+ | `ModelsPanel` | Panel listing loaded models with search and load button |
176
+ | `ModelsDropdown` | Dropdown selector listing loaded models |
177
+ | `ClassificationsList` | Hierarchical table of IFC classification data |
178
+ | `ClashesList` | Interactive clash detection results with highlighting |
179
+ | `ClippingsList` | Panel listing clipping planes with controls |
180
+ | `LengthMeasuringsList` | Panel listing length measurements with totals |
181
+ | `AreaMeasuringsList` | Panel listing area measurements with totals |
182
+ | `ColorsPalette` | Color picker with Highlighter style swatches |
183
+ | `HighlightersList` | Panel listing Highlighter styles with manage actions |
184
+ | `QtoComparisonList` | Side-by-side quantity comparison for two elements |
185
+ | `QueriesHierarchy` | Recursive multi-level query browser |
186
+ | `CustomViewLegend` | Color legend overlay |
187
+ | `ScreenshotAnnotator` | Modal for annotating screenshots via MarkerJS |
188
+
189
+ See `src/built-in/index.ts` for full API reference with config interfaces and `@example` blocks.
190
+
191
+ ## Config files
192
+
193
+ | File | Scope | Contains |
194
+ |------|-------|----------|
195
+ | `~/.thatopen/config.json` | Global | `accessToken`, `apiUrl` |
196
+ | `.thatopen` (project root) | Per-project (gitignored) | `accessToken`, `apiUrl`, `appId` or `componentId` |
197
+
198
+ The CLI checks the local `.thatopen` first, then falls back to the global config.
199
+
200
+ ---
201
+
202
+ ## Development (working on this repo)
203
+
204
+ ### Setup
205
+
206
+ ```bash
207
+ npm install
208
+ npm run build # Builds both library and CLI
209
+ ```
210
+
211
+ ### Build commands
212
+
213
+ ```bash
214
+ npm run build # Full build (library + CLI)
215
+ npm run build:lib # Library only
216
+ npm run build:cli # CLI only
217
+ ```
218
+
219
+ ### Testing the CLI locally
220
+
221
+ ```bash
222
+ # Link the CLI globally so `thatopen` points to this repo
223
+ npm link
224
+
225
+ # Build CLI and scaffold a test app
226
+ npm run test:cli-build-app
227
+
228
+ # Build and scaffold a test cloud component
229
+ npm run test:cli-build-component
230
+
231
+ # Run the test cloud component locally
232
+ npm run test:cli-run-component
233
+ ```
234
+
235
+ ### Running the platform API test suite
236
+
237
+ The test suite consists of two projects scaffolded together: a **test app** (browser-based, template `test`) and a **test cloud component** (server-side, template `cloud-test`). Both exercise every `EngineServicesClient` endpoint.
238
+
239
+ ```bash
240
+ # 1. Build the CLI and scaffold both test projects into a temp/ directory
241
+ # (deletes temp/ first if it already exists)
242
+ yarn test:cli-build-tests
243
+
244
+ # 2. Serve both the test app and the test component's local server
245
+ yarn test:cli-serve-tests
246
+ ```
247
+
248
+ Then open your project on [platform.thatopen.com](https://platform.thatopen.com) and click the debug button. The test app will show a panel with:
249
+
250
+ - **Context** — current app/project/API info
251
+ - **Execution Config** — input fields for a deployed Component ID and the local server URL (defaults to `http://localhost:4001`)
252
+ - **Controls** — "Run All Tests" button
253
+ - **Results** — test results grouped by API area (Context & Auth, Folders, Files, Hidden Files, Icons, Components, Apps, Execution, Built-in Components)
254
+
255
+ When execution tests run, the cloud component's output appears in the same Results section as additional groups prefixed with "Local Component:" or "Deployed Component:".
256
+
257
+ ### Publishing a new version
258
+
259
+ Publishing is handled automatically by CI when a PR with changesets is merged to `main`.
260
+
261
+ **1. Create a changeset (developer does this with their changes):**
262
+
263
+ ```bash
264
+ yarn changeset
265
+ # Pick the bump type (patch / minor / major) and write a summary
266
+ # This creates a .changeset/<random-name>.md file — commit it with your PR
267
+ ```
268
+
269
+ **2. Merge the PR to `main`:**
270
+
271
+ CI will automatically:
272
+ - Consume the changeset files
273
+ - Bump `package.json` version and update `CHANGELOG.md`
274
+ - Commit the version bump back to `main`
275
+ - Build and publish to npm
276
+
277
+ **Manual publishing (if CI is not available):**
278
+
279
+ ```bash
280
+ yarn version # Consume changesets, bump version
281
+ yarn build
282
+ yarn changeset publish
283
+ ```
284
+
285
+ Keep in mind the importance of semver — don't release a major for non-breaking changes.