@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
@@ -0,0 +1,205 @@
1
+ # ThatOpen Cloud Component
2
+
3
+ This is a cloud component for the That Open Platform.
4
+ It runs on the server as a Node.js process, triggered via the platform API.
5
+
6
+ ## How this component works
7
+
8
+ - **Entry point**: `src/main.ts` — must export an `async function main()`.
9
+ - **Parameter schema**: `declarations.json` — the list of parameters this component accepts. Bundled next to the code so the platform, the UI, and `thatopen run` know what to pass in.
10
+ - **Build output**: `dist/bundle.js` — an IIFE built by Vite with `thatopen-services` externalized.
11
+ - **Execution**: The platform (or `thatopen run` locally) wraps the bundle in an execution engine that provides globals and calls `main()`.
12
+
13
+ ## Parameters (`declarations.json`)
14
+
15
+ Every cloud component declares its runtime parameters in a root-level `declarations.json` file. The CLI includes this file in the zip at publish time, and the platform refuses to publish a component without it. It's a plain JSON array of `{ id, label, type }` entries:
16
+
17
+ ```json
18
+ [
19
+ { "id": "projectName", "label": "Project Name", "type": "string" },
20
+ { "id": "iterations", "label": "Number of Iterations", "type": "number" }
21
+ ]
22
+ ```
23
+
24
+ - `id` — the key users read off `executionParams` inside `main()`.
25
+ - `label` — human-readable name shown to the user on the platform's execution form.
26
+ - `type` — `"string"` or `"number"` (the only supported types for now).
27
+
28
+ **Rule:** `declarations.json` and `src/main.ts` must stay in sync. When you add, remove, or rename a parameter in one, update the other. `thatopen publish` fails if `declarations.json` is missing, and `thatopen run --params '{...}'` warns if the keys or types don't match the schema.
29
+
30
+ ## Commands
31
+
32
+ ```bash
33
+ npm run build # Build dist/bundle.js
34
+ npm run run # Build and run locally (one-shot execution via thatopen run)
35
+ npm run local-server # Start local execution server (API-compatible with EngineServicesClient)
36
+ npm run login # Authenticate with the platform (saves token locally)
37
+ npm run publish # Publish to the platform
38
+ ```
39
+
40
+ To pass parameters when running locally:
41
+
42
+ ```bash
43
+ npx thatopen run --params '{"inputFile": "model.ifc", "threshold": 0.5}'
44
+ ```
45
+
46
+ ### Local execution server
47
+
48
+ The local server (`npm run local-server`) starts an HTTP + WebSocket server that implements
49
+ the same execution API as the cloud. This lets apps using `EngineServicesClient` test against
50
+ local component code without publishing:
51
+
52
+ ```bash
53
+ npm run local-server # Start on default port 4001
54
+ npx thatopen local-server --port 5000 # Custom port
55
+ ```
56
+
57
+ Then in your app or test script:
58
+
59
+ ```ts
60
+ import { EngineServicesClient } from "thatopen-services";
61
+
62
+ const client = new EngineServicesClient(token, apiUrl, {
63
+ localServerUrl: "http://localhost:4001",
64
+ });
65
+
66
+ const { executionId } = await client.executeComponent("any-id", { param: "value" });
67
+ client.onExecutionProgress(executionId, (data) => {
68
+ console.log(data.progressUpdate?.progress);
69
+ });
70
+ ```
71
+
72
+ The server watches source files and auto-rebuilds — changes are picked up on the next execution.
73
+
74
+ ## Globals available at runtime
75
+
76
+ The execution engine injects **exactly these four** into scope — do NOT import them, do NOT assume anything else is available:
77
+
78
+ | Global | Type | Purpose |
79
+ |--------|------|---------|
80
+ | `thatOpenServices` | `EngineServicesClient` | Authenticated API client (files, folders, components, executions) |
81
+ | `executionParams` | `Record<string, any>` | User-supplied parameters (shape defined in `declarations.json`) |
82
+ | `executionContext` | `{ projectId?, executionId, toolId, toolVersion }` | Platform-supplied run context. Use `executionContext.projectId` to scope operations to the project the component was launched from. Undefined when run outside a project context. |
83
+ | `executionReporter` | `{ message(msg), error(msg), progress(pct) }` | Send live status updates, error lines, and a numeric progress percentage to the execution UI |
84
+
85
+ Libraries like `@thatopen/components`, `three`, `web-ifc`, or Node's `fs` are **not** available as globals. If you need them, `import` them the normal way and let the bundler include them in `dist/bundle.js`. The execution environment is a plain Node.js process with no special additions beyond the four globals above.
86
+
87
+ ### TypeScript declarations
88
+
89
+ Already declared in `src/main.ts`. Keep them there for type checking:
90
+
91
+ ```ts
92
+ declare const thatOpenServices: import("thatopen-services").EngineServicesClient;
93
+ declare const executionParams: Record<string, unknown>;
94
+ declare const executionContext: {
95
+ projectId?: string;
96
+ executionId: string;
97
+ toolId: string;
98
+ toolVersion: string;
99
+ };
100
+ declare const executionReporter: {
101
+ message(msg: string): void;
102
+ error(msg: string): void;
103
+ progress(pct: number): void;
104
+ };
105
+ ```
106
+
107
+ ## Return value
108
+
109
+ `main()` must return an object with `type` and `message`:
110
+
111
+ ```ts
112
+ return { type: "SUCCESS", message: "Processed 42 elements" };
113
+ // type: "SUCCESS" | "FAIL" | "WARNING"
114
+ ```
115
+
116
+ ## Common patterns
117
+
118
+ ### Scoping uploads to the launching project
119
+
120
+ ```ts
121
+ export async function main() {
122
+ const projectId = executionContext?.projectId;
123
+ if (!projectId) {
124
+ return { type: "FAIL", message: "This component must be launched from a project" };
125
+ }
126
+
127
+ const blob = new Blob(["hello"], { type: "text/plain" });
128
+ await thatOpenServices.createFile({
129
+ file: blob,
130
+ name: "hello.txt",
131
+ versionTag: "v1",
132
+ projectId,
133
+ });
134
+
135
+ return { type: "SUCCESS", message: "Uploaded into the project" };
136
+ }
137
+ ```
138
+
139
+ ### Processing a file from platform storage
140
+
141
+ ```ts
142
+ export async function main() {
143
+ const { fileId } = executionParams;
144
+
145
+ executionReporter.message("Downloading file...");
146
+ const response = await thatOpenServices.downloadFile(fileId as string);
147
+ const buffer = await response.arrayBuffer();
148
+
149
+ executionReporter.progress(50);
150
+ // ... process the buffer ...
151
+ executionReporter.progress(100);
152
+
153
+ return { type: "SUCCESS", message: "Done" };
154
+ }
155
+ ```
156
+
157
+ ### Triggering another cloud component
158
+
159
+ ```ts
160
+ const { executionId } = await thatOpenServices.executeComponent(otherComponentId, { param: "value" });
161
+ const result = await thatOpenServices.getExecution(executionId);
162
+ ```
163
+
164
+ ### Listing resources inside a project
165
+
166
+ Pass `projectId` to the list methods to enumerate a specific project's
167
+ resources. The backend enforces project-scoped permissions — the token
168
+ running your component must have `STORAGE:READ` (or the relevant role)
169
+ on that project; otherwise the call is rejected with `403`. A missing
170
+ `projectId` still works and lists items in the caller's personal scope.
171
+
172
+ ```ts
173
+ const projectId = executionContext?.projectId;
174
+ if (projectId) {
175
+ const files = await thatOpenServices.listFiles({ projectId });
176
+ const folders = await thatOpenServices.listFolders({ projectId });
177
+ // listApps / listComponents / listExecutions all accept projectId too
178
+ }
179
+ ```
180
+
181
+ ### Gating an action with a permission check
182
+
183
+ ```ts
184
+ const { hasPermission, scope } = await thatOpenServices.checkPermission({
185
+ resourceType: "STORAGE",
186
+ action: "WRITE",
187
+ projectId: executionContext?.projectId,
188
+ });
189
+ if (!hasPermission) {
190
+ return { type: "FAIL", message: "Caller cannot write to this project" };
191
+ }
192
+ // scope is 'global' | 'project' | 'entity' | 'none' — useful when you
193
+ // want the UI to know *why* a permission was granted. checkPermissionBatch
194
+ // accepts a list of checks in a single round-trip.
195
+ ```
196
+
197
+ ## Build configuration
198
+
199
+ - `vite.config.js` builds to IIFE format.
200
+ - Only `thatopen-services` is externalized — the wrapper provides it at runtime via `require()`. Everything else (including any third-party npm dependency you install) is bundled into `dist/bundle.js`.
201
+ - The build output has a footer `var main = ThatOpenComponent.main;` so the engine can find the entry point as a top-level `main` variable.
202
+
203
+ ## Configuration
204
+
205
+ - `.thatopen` — local config (gitignored). Created by `npm run login`. Contains `accessToken`, `apiUrl`, `itemType: "COMPONENT"`, and `componentId` after first publish.
@@ -0,0 +1,5 @@
1
+ {
2
+ "accessToken": "",
3
+ "apiUrl": "",
4
+ "itemType": "COMPONENT"
5
+ }
@@ -0,0 +1,4 @@
1
+ [
2
+ { "id": "projectName", "label": "Project Name", "type": "string" },
3
+ { "id": "iterations", "label": "Number of Iterations", "type": "number" }
4
+ ]
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "{{PROJECT_NAME}}",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "build": "vite build",
7
+ "run": "thatopen run",
8
+ "local-server": "thatopen local-server",
9
+ "login": "thatopen login --local",
10
+ "publish": "thatopen publish"
11
+ },
12
+ "dependencies": {
13
+ "@thatopen/components": "~3.4.0",
14
+ "thatopen-services": "^{{VERSION}}",
15
+ "three": "^0.182.0"
16
+ },
17
+ "devDependencies": {
18
+ "@types/three": "^0.182.0",
19
+ "typescript": "^5.2.0",
20
+ "vite": "^5.2.0"
21
+ }
22
+ }
@@ -0,0 +1,70 @@
1
+ // Cloud Component Entry Point
2
+ //
3
+ // Your component runs on the server as a Node.js process.
4
+ // The execution engine provides these globals — do NOT import them:
5
+ //
6
+ // thatOpenServices — pre-authenticated EngineServicesClient
7
+ // executionParams — parameters passed by the caller (shape defined in ../declarations.json)
8
+ // executionContext — platform-supplied run context: { projectId?, executionId, toolId, toolVersion }
9
+ // Use executionContext.projectId to scope uploads/lookups to the launching project.
10
+ // Undefined when the component is run outside a project context.
11
+ // executionReporter — { message(msg), error(msg), progress(pct) } for live feedback
12
+ //
13
+ // Parameters are declared in `declarations.json` at the project root. That
14
+ // file is bundled alongside this code at publish time so the platform (and
15
+ // the CLI's `thatopen run`) knows which parameters the component accepts
16
+ // and their types. Whenever you add, remove, or rename a parameter in this
17
+ // file you MUST update `declarations.json` to match — `thatopen publish`
18
+ // fails if they drift.
19
+ //
20
+ // Return value — must be { type, message }:
21
+ // type: "SUCCESS" | "FAIL" | "WARNING"
22
+
23
+ // Globals injected by the execution engine at runtime — keep these for type checking
24
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
25
+ declare const thatOpenServices: import("thatopen-services").EngineServicesClient;
26
+ declare const executionParams: Record<string, unknown>;
27
+ declare const executionContext: {
28
+ projectId?: string;
29
+ executionId: string;
30
+ toolId: string;
31
+ toolVersion: string;
32
+ };
33
+ declare const executionReporter: {
34
+ message(msg: string): void;
35
+ error(msg: string): void;
36
+ progress(pct: number): void;
37
+ };
38
+
39
+ export async function main() {
40
+ const projectName = executionParams.projectName as string | undefined;
41
+ const iterations = Number(executionParams.iterations);
42
+
43
+ executionReporter.message(
44
+ `Starting for "${projectName ?? "(unnamed)"}"`,
45
+ );
46
+ executionReporter.message(`Will run ${iterations} iteration(s)`);
47
+ if (executionContext?.projectId) {
48
+ executionReporter.message(`Scoped to project ${executionContext.projectId}`);
49
+ }
50
+
51
+ if (!projectName) {
52
+ return { type: "FAIL", message: "projectName parameter is required" };
53
+ }
54
+ if (!Number.isFinite(iterations) || iterations <= 0) {
55
+ return { type: "FAIL", message: "iterations must be a positive number" };
56
+ }
57
+
58
+ for (let i = 1; i <= iterations; i++) {
59
+ executionReporter.message(`Iteration ${i} of ${iterations}`);
60
+ executionReporter.progress(Math.round((i / iterations) * 100));
61
+ await new Promise((resolve) => setTimeout(resolve, 500));
62
+ }
63
+
64
+ executionReporter.message("All iterations completed");
65
+
66
+ return {
67
+ type: "SUCCESS",
68
+ message: `Processed "${projectName}" across ${iterations} iteration(s)`,
69
+ };
70
+ }
@@ -0,0 +1,56 @@
1
+ # ThatOpen Platform API Test Suite (Cloud Component)
2
+
3
+ This is a cloud component that exercises every EngineServicesClient endpoint from a
4
+ server-side context. It verifies that the platform API and runtime globals work correctly.
5
+
6
+ ## How this component works
7
+
8
+ - **Entry point**: `src/main.ts` — exports `async function main()`.
9
+ - **Build output**: `dist/bundle.js` — an IIFE built by Vite with platform deps externalized.
10
+ - **Execution**: The platform (or `thatopen run` locally) calls `main()`.
11
+
12
+ ## What it tests
13
+
14
+ | Group | Endpoints tested |
15
+ |-------|-----------------|
16
+ | **Runtime Globals** | thatOpenServices, executionParams, executionReporter, OBC, THREE, fs |
17
+ | **Folders** | createFolder, getFolder, listFolders, updateFolder, archiveFolder, recoverFolder, downloadFolder |
18
+ | **Files** | createFile, getFile, listFiles, downloadFile, getFileVersionMetadata, updateFileVersionMetadata, deleteFileVersionMetadata, updateFile, archiveFile, recoverFile |
19
+ | **Hidden Files** | createHiddenFile, getHiddenFile, getHiddenFilesByParent, downloadHiddenFile, deleteHiddenFile, deleteHiddenFilesByParent |
20
+ | **Icons** | uploadItemIcon, getItemIcon, removeItemIcon |
21
+ | **General Items** | updateItem, createVersion |
22
+ | **Components** | createComponent, getComponent, listComponents, updateComponent, downloadComponent, downloadComponentBundle, archiveComponent, recoverComponent |
23
+ | **Apps** | createApp, listApps, downloadApp, downloadAppBundle, archiveApp |
24
+ | **Execution** | executeComponent, getExecution, listExecutions, onExecutionProgress, abortExecution |
25
+ | **Built-in** | getBuiltInComponent |
26
+
27
+ ## Running locally
28
+
29
+ ```bash
30
+ npm run run # Build and run once
31
+ npm run local-server # Start local execution server
32
+ ```
33
+
34
+ ## Running on the platform
35
+
36
+ ```bash
37
+ npm run login # Authenticate
38
+ npm run publish # Publish to the platform
39
+ ```
40
+
41
+ Then execute via the platform UI or from another app:
42
+ ```ts
43
+ const { executionId } = await client.executeComponent(componentId, {});
44
+ client.onExecutionProgress(executionId, (data) => { ... });
45
+ ```
46
+
47
+ ## Output
48
+
49
+ - **Progress**: Reported via `executionReporter` after each test group
50
+ - **Messages**: Each group logs individual test results (pass/fail/skip)
51
+ - **Return**: `{ type: "SUCCESS", message }` if all pass, `{ type: "WARNING", message }` if any fail
52
+
53
+ ## Cleanup
54
+
55
+ All test resources (folders, files, components, apps, hidden files) are archived after tests.
56
+ The execution tests use the test component created in the Components test group.
@@ -0,0 +1,5 @@
1
+ {
2
+ "accessToken": "",
3
+ "apiUrl": "",
4
+ "itemType": "COMPONENT"
5
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "{{PROJECT_NAME}}",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "build": "vite build",
7
+ "run": "thatopen run",
8
+ "local-server": "thatopen local-server",
9
+ "login": "thatopen login --local",
10
+ "publish": "thatopen publish"
11
+ },
12
+ "dependencies": {
13
+ "@thatopen/components": "~3.4.0",
14
+ "thatopen-services": "^{{VERSION}}",
15
+ "three": "^0.182.0"
16
+ },
17
+ "devDependencies": {
18
+ "@types/three": "^0.182.0",
19
+ "typescript": "^5.2.0",
20
+ "vite": "^5.2.0"
21
+ }
22
+ }