@thatopen/services 0.0.4 → 0.0.6
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.
- package/README.md +24 -263
- package/dist/cli/commands/swap.d.ts +3 -0
- package/dist/cli/lib/beta.d.ts +2 -0
- package/dist/cli/lib/config.d.ts +2 -0
- package/dist/cli.js +85 -126
- package/dist/core/examples/apps.d.ts +1 -0
- package/dist/core/examples/components.d.ts +1 -0
- package/dist/core/examples/execution.d.ts +1 -0
- package/dist/core/examples/file-metadata.d.ts +1 -0
- package/dist/core/examples/files.d.ts +1 -0
- package/dist/core/examples/folders.d.ts +1 -0
- package/dist/core/examples/hidden-files.d.ts +1 -0
- package/dist/core/examples/icons.d.ts +1 -0
- package/dist/core/examples/permissions.d.ts +1 -0
- package/dist/types/items.d.ts +2 -0
- package/docs/builtin/paths.json +54 -0
- package/docs/cli/create.md +28 -0
- package/docs/cli/local-server.md +38 -0
- package/docs/cli/login.md +32 -0
- package/docs/cli/paths.json +30 -0
- package/docs/cli/publish.md +31 -0
- package/docs/cli/run.md +26 -0
- package/docs/cli/serve.md +43 -0
- package/docs/cli/swap.md +30 -0
- package/docs/client/paths.json +38 -0
- package/package.json +8 -10
- package/resources/AGENTS.md +39 -0
- package/src/built-in/AppManager/example.ts +86 -0
- package/src/built-in/CDEManager/example.ts +214 -0
- package/src/built-in/CDEManager/examples/FileEditing/example.ts +226 -0
- package/src/built-in/CDEManager/examples/FileMoves/example.ts +186 -0
- package/src/built-in/CDEManager/examples/FileOperations/example.ts +295 -0
- package/src/built-in/CDEManager/examples/FileTransfers/example.ts +210 -0
- package/src/built-in/CDEManager/examples/FolderManagement/example.ts +230 -0
- package/src/built-in/CDEManager/examples/MetadataSchema/example.ts +230 -0
- package/src/built-in/CDEManager/examples/MetadataViews/example.ts +166 -0
- package/src/built-in/CDEManager/examples/ProjectConfig/example.ts +177 -0
- package/src/built-in/FileList/example.ts +107 -0
- package/src/built-in/TabbedNavigation/example.ts +115 -0
- package/src/built-in/ViewportsManager/example.ts +106 -0
- package/src/cli/templates/{shared/app → app}/vite.config.js +42 -23
- package/src/cli/templates/{shared/cloud → cloud-component}/vite.config.js +46 -27
- package/src/cli/templates/shared/AGENTS.md +8 -30
- package/src/cli/templates/shared/CLAUDE.md +1 -1
- package/AGENTS.md +0 -86
- package/CONTEXT.md +0 -258
- package/dist/built-in/index.d.ts +0 -723
- package/dist/cli/commands/create-tests.d.ts +0 -3
- package/dist/cli/commands/serve-tests.d.ts +0 -3
- package/docs/access-backend-data.md +0 -19
- package/docs/app-architecture.md +0 -94
- package/docs/app-layout.md +0 -139
- package/docs/app-wiring.md +0 -123
- package/docs/bim-components/coding-conventions.md +0 -128
- package/docs/bim-components/element-collections.md +0 -69
- package/docs/bim-components/expose-events.md +0 -84
- package/docs/bim-components/library-examples.md +0 -28
- package/docs/bim-components/observable-collections.md +0 -83
- package/docs/bim-components/overview.md +0 -160
- package/docs/bim-components/per-frame-updates.md +0 -20
- package/docs/bim-components/save-and-restore-state.md +0 -21
- package/docs/bim-components/setup-and-cleanup.md +0 -64
- package/docs/bim-components/type-conventions.md +0 -49
- package/docs/bim-components/user-driven-object-creation.md +0 -56
- package/docs/cli-setup.md +0 -54
- package/docs/cloud-components.md +0 -74
- package/docs/connect-logic-to-ui.md +0 -113
- package/docs/previewing.md +0 -45
- package/docs/publishing.md +0 -35
- package/docs/scaffolding.md +0 -71
- package/docs/ui-components/async-actions.md +0 -18
- package/docs/ui-components/confirmation-dialog.md +0 -39
- package/docs/ui-components/data-table.md +0 -185
- package/docs/ui-components/display-text.md +0 -39
- package/docs/ui-components/inline-form.md +0 -44
- package/docs/ui-components/library-examples.md +0 -24
- package/docs/ui-components/overview.md +0 -194
- package/docs/ui-components/rendering-patterns.md +0 -129
- package/docs/ui-components/sections-layout.md +0 -123
- package/docs/update-grid-elements.md +0 -46
- package/docs/using-colors.md +0 -32
- package/docs/using-icons.md +0 -37
- package/src/cli/templates/bim/src/bim-components/CloudRunner/src/index.ts +0 -1
- package/src/cli/templates/bim/src/bim-components/CloudRunner/src/types.ts +0 -5
- package/src/cli/templates/bim/src/bim-components/index.ts +0 -1
- package/src/cli/templates/bim/src/globals.ts +0 -1
- package/src/cli/templates/bim/src/setups/index.ts +0 -3
- package/src/cli/templates/bim/src/ui-components/app-info-section/index.ts +0 -26
- package/src/cli/templates/bim/src/ui-components/app-info-section/src/index.ts +0 -1
- package/src/cli/templates/bim/src/ui-components/cloud-runner-section/index.ts +0 -37
- package/src/cli/templates/bim/src/ui-components/cloud-runner-section/src/index.ts +0 -1
- package/src/cli/templates/bim/src/ui-components/index.ts +0 -2
- package/src/cli/templates/bim-beta/CONTEXT.md +0 -241
- package/src/cli/templates/bim-beta/package.json +0 -25
- package/src/cli/templates/bim-beta/src/app.ts +0 -16
- package/src/cli/templates/bim-beta/src/bim-components/CloudRunner/index.ts +0 -91
- package/src/cli/templates/bim-beta/src/main.ts +0 -93
- package/src/cli/templates/bim-beta/src/setups/cloud-runner.ts +0 -13
- package/src/cli/templates/bim-beta/src/setups/ui-manager.ts +0 -27
- package/src/cli/templates/bim-beta/src/setups/viewports-manager.ts +0 -22
- package/src/cli/templates/bim-beta/src/ui-components/app-info-section/src/types.ts +0 -15
- package/src/cli/templates/bim-beta/src/ui-components/cloud-runner-section/src/types.ts +0 -14
- package/src/cli/templates/cloud/_thatopen +0 -5
- package/src/cli/templates/cloud/package.json +0 -22
- package/src/cli/templates/cloud-test/CONTEXT.md +0 -56
- package/src/cli/templates/cloud-test/src/main.ts +0 -565
- package/src/cli/templates/default/CONTEXT.md +0 -92
- package/src/cli/templates/default/package.json +0 -18
- package/src/cli/templates/default/src/main.ts +0 -62
- package/src/cli/templates/test/CONTEXT.md +0 -53
- package/src/cli/templates/test/package.json +0 -25
- package/src/cli/templates/test/src/main.ts +0 -955
- /package/src/cli/templates/{bim/CONTEXT.md → app/README.md} +0 -0
- /package/src/cli/templates/{shared/app → app}/index.html +0 -0
- /package/src/cli/templates/{bim → app}/package.json +0 -0
- /package/src/cli/templates/{bim → app}/src/app.ts +0 -0
- /package/src/cli/templates/{bim → app}/src/bim-components/CloudRunner/index.ts +0 -0
- /package/src/cli/templates/{bim-beta → app}/src/bim-components/CloudRunner/src/index.ts +0 -0
- /package/src/cli/templates/{bim-beta → app}/src/bim-components/CloudRunner/src/types.ts +0 -0
- /package/src/cli/templates/{bim-beta → app}/src/bim-components/index.ts +0 -0
- /package/src/cli/templates/{bim-beta → app}/src/globals.ts +0 -0
- /package/src/cli/templates/{bim → app}/src/main.ts +0 -0
- /package/src/cli/templates/{bim → app}/src/setups/cloud-runner.ts +0 -0
- /package/src/cli/templates/{bim-beta → app}/src/setups/index.ts +0 -0
- /package/src/cli/templates/{bim → app}/src/setups/ui-manager.ts +0 -0
- /package/src/cli/templates/{bim → app}/src/setups/viewports-manager.ts +0 -0
- /package/src/cli/templates/{bim-beta → app}/src/ui-components/app-info-section/index.ts +0 -0
- /package/src/cli/templates/{bim-beta → app}/src/ui-components/app-info-section/src/index.ts +0 -0
- /package/src/cli/templates/{bim → app}/src/ui-components/app-info-section/src/types.ts +0 -0
- /package/src/cli/templates/{bim-beta → app}/src/ui-components/cloud-runner-section/index.ts +0 -0
- /package/src/cli/templates/{bim-beta → app}/src/ui-components/cloud-runner-section/src/index.ts +0 -0
- /package/src/cli/templates/{bim → app}/src/ui-components/cloud-runner-section/src/types.ts +0 -0
- /package/src/cli/templates/{bim-beta → app}/src/ui-components/index.ts +0 -0
- /package/src/cli/templates/{shared/app → app}/tsconfig.json +0 -0
- /package/src/cli/templates/{cloud/CONTEXT.md → cloud-component/README.md} +0 -0
- /package/src/cli/templates/{cloud-test → cloud-component}/_thatopen +0 -0
- /package/src/cli/templates/{cloud → cloud-component}/declarations.json +0 -0
- /package/src/cli/templates/{cloud-test → cloud-component}/package.json +0 -0
- /package/src/cli/templates/{cloud → cloud-component}/src/main.ts +0 -0
- /package/src/cli/templates/{shared/cloud → cloud-component}/tsconfig.json +0 -0
package/README.md
CHANGED
|
@@ -1,285 +1,46 @@
|
|
|
1
1
|
# @thatopen/services
|
|
2
2
|
|
|
3
|
-
Client library and CLI for building BIM apps and cloud components on
|
|
3
|
+
Client library and CLI for building BIM apps and cloud components on [That Open Platform](https://platform.thatopen.com). Apps run inside the platform's browser environment; cloud components run server-side and can be triggered from any app.
|
|
4
4
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
7
|
-
###
|
|
7
|
+
### 1. Install the CLI
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
|
|
11
|
-
npm i @thatopen/services -g
|
|
10
|
+
npm install -g @thatopen/services@latest
|
|
12
11
|
```
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
### 2. Choose a project type
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
```
|
|
15
|
+
| Type | Template | Use when |
|
|
16
|
+
|------|----------|----------|
|
|
17
|
+
| **App** | `app` | You're building a BIM app that runs in the platform's browser UI |
|
|
18
|
+
| **Cloud component** | `cloud-component` | You're building server-side logic triggered by an app |
|
|
210
19
|
|
|
211
|
-
###
|
|
20
|
+
### 3. Scaffold
|
|
212
21
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
npm run build:lib # Library only
|
|
216
|
-
npm run build:cli # CLI only
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### Testing the CLI locally
|
|
22
|
+
See the full command reference here:
|
|
23
|
+
→ [`docs/cli/create.md`](https://raw.githubusercontent.com/ThatOpen/engine_services/main/docs/cli/create.md)
|
|
220
24
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
npm link
|
|
224
|
-
|
|
225
|
-
# Build CLI and scaffold a test app
|
|
226
|
-
npm run test:cli-build-app
|
|
25
|
+
To use beta engine libraries instead of the stable ones, see:
|
|
26
|
+
→ [`docs/cli/swap.md`](https://raw.githubusercontent.com/ThatOpen/engine_services/main/docs/cli/swap.md)
|
|
227
27
|
|
|
228
|
-
|
|
229
|
-
npm run test:cli-build-component
|
|
28
|
+
### 4. Next steps
|
|
230
29
|
|
|
231
|
-
|
|
232
|
-
npm run test:cli-run-component
|
|
233
|
-
```
|
|
30
|
+
Once scaffolded, open `AGENTS.md` in the scaffolded project root — it has everything needed to start building.
|
|
234
31
|
|
|
235
|
-
|
|
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
|
-
```
|
|
32
|
+
## What's in this repository
|
|
247
33
|
|
|
248
|
-
|
|
34
|
+
- **Library** — `EngineServicesClient` and `PlatformClient` for interacting with the That Open API (files, folders, apps, cloud components, executions, permissions).
|
|
35
|
+
- **CLI** — `thatopen` command for scaffolding and publishing.
|
|
36
|
+
- **Built-in component types** — TypeScript stubs for platform-hosted components.
|
|
249
37
|
|
|
250
|
-
|
|
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)
|
|
38
|
+
## Docs
|
|
254
39
|
|
|
255
|
-
|
|
40
|
+
Full reference for all CLI commands and flags:
|
|
41
|
+
→ [`docs/cli/paths.json`](https://raw.githubusercontent.com/ThatOpen/engine_services/main/docs/cli/paths.json)
|
|
256
42
|
|
|
257
|
-
|
|
43
|
+
## Contributing
|
|
258
44
|
|
|
259
|
-
|
|
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
|
-
```
|
|
45
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md) for setup, build commands, and publishing workflow.
|
|
284
46
|
|
|
285
|
-
Keep in mind the importance of semver — don't release a major for non-breaking changes.
|
package/dist/cli/lib/config.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export interface ThatOpenLocalConfig {
|
|
|
15
15
|
itemType?: ProjectType;
|
|
16
16
|
/** Path to an icon file (PNG, WebP, or ICO) uploaded on publish. */
|
|
17
17
|
iconPath?: string;
|
|
18
|
+
/** Whether this project uses beta engine libraries (@thatopen-platform/*-beta). */
|
|
19
|
+
beta?: boolean;
|
|
18
20
|
}
|
|
19
21
|
export declare function readLocalConfig(cwd?: string): ThatOpenLocalConfig | null;
|
|
20
22
|
export declare function writeLocalConfig(config: ThatOpenLocalConfig, cwd?: string): void;
|
package/dist/cli.js
CHANGED
|
@@ -7980,7 +7980,12 @@ const loginCommand = new Command2("login").description("Authenticate with the Th
|
|
|
7980
7980
|
);
|
|
7981
7981
|
}
|
|
7982
7982
|
});
|
|
7983
|
-
const
|
|
7983
|
+
const BETA_ALIASES = {
|
|
7984
|
+
"@thatopen/components": "@thatopen-platform/components-beta",
|
|
7985
|
+
"@thatopen/components-front": "@thatopen-platform/components-front-beta",
|
|
7986
|
+
"@thatopen/fragments": "@thatopen-platform/fragments-beta"
|
|
7987
|
+
};
|
|
7988
|
+
const TEMPLATES = ["app", "cloud-component"];
|
|
7984
7989
|
const libVersion = (() => {
|
|
7985
7990
|
try {
|
|
7986
7991
|
const pkg2 = JSON.parse(require$$3.readFileSync(require$$2.join(__dirname, "..", "package.json"), "utf-8"));
|
|
@@ -7990,13 +7995,13 @@ const libVersion = (() => {
|
|
|
7990
7995
|
}
|
|
7991
7996
|
})();
|
|
7992
7997
|
const templatesDir = require$$2.join(__dirname, "..", "src", "cli", "templates");
|
|
7993
|
-
const createCommand = new Command2("create").argument("<project-name>", 'Name of the project to create (use "." for current directory)').option("-t, --template <template>", `Template (${TEMPLATES.join(", ")})`, "
|
|
7998
|
+
const createCommand = new Command2("create").argument("<project-name>", 'Name of the project to create (use "." for current directory)').option("-t, --template <template>", `Template (${TEMPLATES.join(", ")})`, "app").option("--beta", "Use beta engine libraries (@thatopen-platform/*-beta)").description("Scaffold a new ThatOpen app or cloud component project").action(async (projectName, opts) => {
|
|
7994
7999
|
const template = opts.template;
|
|
7995
8000
|
if (!TEMPLATES.includes(template)) {
|
|
7996
8001
|
console.error(`Unknown template "${opts.template}". Available: ${TEMPLATES.join(", ")}`);
|
|
7997
8002
|
process.exit(1);
|
|
7998
8003
|
}
|
|
7999
|
-
const isCloud = template === "cloud
|
|
8004
|
+
const isCloud = template === "cloud-component";
|
|
8000
8005
|
const projectKind = isCloud ? "cloud component" : "app";
|
|
8001
8006
|
const useCurrentDir = projectName === ".";
|
|
8002
8007
|
const targetDir = useCurrentDir ? process.cwd() : require$$2.resolve(process.cwd(), projectName);
|
|
@@ -8005,44 +8010,43 @@ const createCommand = new Command2("create").argument("<project-name>", 'Name of
|
|
|
8005
8010
|
console.error(`Directory "${projectName}" already exists.`);
|
|
8006
8011
|
process.exit(1);
|
|
8007
8012
|
}
|
|
8008
|
-
console.log(`Creating ThatOpen ${projectKind} "${packageName}" (template: ${template})...`);
|
|
8013
|
+
console.log(`Creating ThatOpen ${projectKind} "${packageName}" (template: ${template}${opts.beta ? ", beta" : ""})...`);
|
|
8009
8014
|
if (!useCurrentDir) {
|
|
8010
8015
|
require$$3.mkdirSync(targetDir, { recursive: true });
|
|
8011
8016
|
}
|
|
8012
8017
|
require$$3.mkdirSync(require$$2.join(targetDir, "src"), { recursive: true });
|
|
8013
8018
|
const sharedDir = require$$2.join(templatesDir, "shared");
|
|
8014
|
-
const sharedVariantDir = require$$2.join(sharedDir, isCloud ? "cloud" : "app");
|
|
8015
8019
|
require$$3.copyFileSync(require$$2.join(sharedDir, "_gitignore"), require$$2.join(targetDir, ".gitignore"));
|
|
8016
8020
|
require$$3.copyFileSync(require$$2.join(sharedDir, "AGENTS.md"), require$$2.join(targetDir, "AGENTS.md"));
|
|
8017
8021
|
require$$3.copyFileSync(require$$2.join(sharedDir, "CLAUDE.md"), require$$2.join(targetDir, "CLAUDE.md"));
|
|
8018
|
-
require$$3.copyFileSync(require$$2.join(sharedVariantDir, "tsconfig.json"), require$$2.join(targetDir, "tsconfig.json"));
|
|
8019
|
-
require$$3.copyFileSync(require$$2.join(sharedVariantDir, "vite.config.js"), require$$2.join(targetDir, "vite.config.js"));
|
|
8020
|
-
if (!isCloud) {
|
|
8021
|
-
require$$3.copyFileSync(require$$2.join(sharedVariantDir, "index.html"), require$$2.join(targetDir, "index.html"));
|
|
8022
|
-
}
|
|
8023
8022
|
const templateDir = require$$2.join(templatesDir, template);
|
|
8024
8023
|
require$$3.cpSync(templateDir, targetDir, { recursive: true });
|
|
8025
8024
|
if (isCloud) {
|
|
8026
8025
|
require$$3.renameSync(require$$2.join(targetDir, "_thatopen"), require$$2.join(targetDir, ".thatopen"));
|
|
8027
8026
|
}
|
|
8028
8027
|
const pkgPath = require$$2.join(targetDir, "package.json");
|
|
8029
|
-
const
|
|
8030
|
-
require$$3.writeFileSync(pkgPath,
|
|
8031
|
-
|
|
8032
|
-
|
|
8033
|
-
|
|
8034
|
-
|
|
8035
|
-
|
|
8028
|
+
const pkgContent = require$$3.readFileSync(pkgPath, "utf-8").replace(/\{\{PROJECT_NAME\}\}/g, packageName).replace(/\{\{VERSION\}\}/g, libVersion).replace(/"@thatopen\/services": "file:[^"]*"/, `"@thatopen/services": "^${libVersion}"`);
|
|
8029
|
+
require$$3.writeFileSync(pkgPath, pkgContent);
|
|
8030
|
+
if (opts.beta) {
|
|
8031
|
+
const pkg2 = JSON.parse(require$$3.readFileSync(pkgPath, "utf-8"));
|
|
8032
|
+
for (const [stable, beta] of Object.entries(BETA_ALIASES)) {
|
|
8033
|
+
if (pkg2.dependencies?.[stable] !== void 0) {
|
|
8034
|
+
delete pkg2.dependencies[stable];
|
|
8035
|
+
pkg2.dependencies[beta] = "latest";
|
|
8036
|
+
}
|
|
8037
|
+
}
|
|
8038
|
+
require$$3.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2));
|
|
8039
|
+
updateLocalConfig({ beta: true }, targetDir);
|
|
8036
8040
|
}
|
|
8037
8041
|
console.log("");
|
|
8038
8042
|
console.log("Installing dependencies...");
|
|
8043
|
+
if (opts.beta) {
|
|
8044
|
+
console.log("(Beta packages are private — if this fails with 401/403, configure your beta npm token.)");
|
|
8045
|
+
}
|
|
8039
8046
|
try {
|
|
8040
8047
|
require$$1.execSync("npm install", { cwd: targetDir, stdio: "inherit" });
|
|
8041
8048
|
} catch {
|
|
8042
8049
|
console.error("Failed to install dependencies. Run `npm install` manually.");
|
|
8043
|
-
if (isBeta) {
|
|
8044
|
-
console.error("Beta packages are private — if this is an auth error, your beta token may not be configured.");
|
|
8045
|
-
}
|
|
8046
8050
|
}
|
|
8047
8051
|
console.log("");
|
|
8048
8052
|
console.log(useCurrentDir ? " Project ready!" : ` Created ./${projectName}`);
|
|
@@ -10719,6 +10723,7 @@ const serveCommand = new Command2("serve").description(
|
|
|
10719
10723
|
);
|
|
10720
10724
|
process.exit(1);
|
|
10721
10725
|
}
|
|
10726
|
+
const isBeta = readLocalConfig(cwd)?.beta === true;
|
|
10722
10727
|
const globalName = detectGlobalName(cwd);
|
|
10723
10728
|
const bundlePath = require$$2.join(cwd, "dist", "bundle.js");
|
|
10724
10729
|
const mapPath = require$$2.join(cwd, "dist", "bundle.js.map");
|
|
@@ -10746,6 +10751,7 @@ const serveCommand = new Command2("serve").description(
|
|
|
10746
10751
|
outfile: bundlePath,
|
|
10747
10752
|
sourcemap: true,
|
|
10748
10753
|
logLevel: "info",
|
|
10754
|
+
alias: isBeta ? BETA_ALIASES : void 0,
|
|
10749
10755
|
logOverride: {
|
|
10750
10756
|
// IIFE format leaves import.meta empty. The only consumer of import.meta
|
|
10751
10757
|
// in our ecosystem today is @thatopen/fragments' worker URL fallback,
|
|
@@ -10836,7 +10842,7 @@ const serveCommand = new Command2("serve").description(
|
|
|
10836
10842
|
res.end("Not found");
|
|
10837
10843
|
});
|
|
10838
10844
|
server.listen(port, () => {
|
|
10839
|
-
console.log(`Bundle server running at http://localhost:${port}`);
|
|
10845
|
+
console.log(`Bundle server running at http://localhost:${port}${isBeta ? " (beta mode)" : ""}`);
|
|
10840
10846
|
console.log("");
|
|
10841
10847
|
console.log(
|
|
10842
10848
|
"Open your project on the platform and click the debug button."
|
|
@@ -11254,8 +11260,11 @@ const localServerCommand = new Command2("local-server").description(
|
|
|
11254
11260
|
).option("--port <port>", "Port for the local server", "4001").option("--skip-build", "Skip the initial build step").action(async (opts) => {
|
|
11255
11261
|
const cwd = process.cwd();
|
|
11256
11262
|
const config = requireResolvedConfig(cwd);
|
|
11263
|
+
const isBeta = readLocalConfig(cwd)?.beta === true;
|
|
11257
11264
|
const port = parseInt(opts.port);
|
|
11258
11265
|
const bundlePath = require$$2.join(cwd, "dist", "bundle.js");
|
|
11266
|
+
const stableExternals = ["@thatopen/components", "@thatopen/fragments"];
|
|
11267
|
+
const externalPackages = isBeta ? stableExternals.map((p) => BETA_ALIASES[p] ?? p) : stableExternals;
|
|
11259
11268
|
let esbuild;
|
|
11260
11269
|
try {
|
|
11261
11270
|
esbuild = await import("esbuild");
|
|
@@ -11275,6 +11284,7 @@ const localServerCommand = new Command2("local-server").description(
|
|
|
11275
11284
|
footer: { js: "var main = ThatOpenComponent.main;" },
|
|
11276
11285
|
outfile: bundlePath,
|
|
11277
11286
|
logLevel: "info",
|
|
11287
|
+
alias: isBeta ? BETA_ALIASES : void 0,
|
|
11278
11288
|
logOverride: {
|
|
11279
11289
|
// Same upstream @nodable/entities duplicate `euro:` key noise
|
|
11280
11290
|
// silenced in the `serve` command. Cosmetic, no runtime impact.
|
|
@@ -11292,7 +11302,7 @@ const localServerCommand = new Command2("local-server").description(
|
|
|
11292
11302
|
},
|
|
11293
11303
|
external: [
|
|
11294
11304
|
"@thatopen/services",
|
|
11295
|
-
|
|
11305
|
+
...externalPackages,
|
|
11296
11306
|
"three",
|
|
11297
11307
|
"web-ifc",
|
|
11298
11308
|
"fs",
|
|
@@ -11417,7 +11427,7 @@ const localServerCommand = new Command2("local-server").description(
|
|
|
11417
11427
|
});
|
|
11418
11428
|
server.listen(port, () => {
|
|
11419
11429
|
console.log("");
|
|
11420
|
-
console.log(`[local-server] Running at http://localhost:${port}`);
|
|
11430
|
+
console.log(`[local-server] Running at http://localhost:${port}${isBeta ? " (beta mode)" : ""}`);
|
|
11421
11431
|
console.log("");
|
|
11422
11432
|
console.log("Usage with EngineServicesClient:");
|
|
11423
11433
|
console.log("");
|
|
@@ -11438,114 +11448,64 @@ const localServerCommand = new Command2("local-server").description(
|
|
|
11438
11448
|
process.exit(0);
|
|
11439
11449
|
});
|
|
11440
11450
|
});
|
|
11441
|
-
const
|
|
11442
|
-
|
|
11443
|
-
|
|
11444
|
-
|
|
11445
|
-
|
|
11446
|
-
|
|
11447
|
-
|
|
11448
|
-
)
|
|
11449
|
-
|
|
11450
|
-
)
|
|
11451
|
-
|
|
11452
|
-
|
|
11453
|
-
|
|
11454
|
-
|
|
11455
|
-
|
|
11456
|
-
|
|
11457
|
-
|
|
11458
|
-
|
|
11459
|
-
|
|
11460
|
-
|
|
11461
|
-
console.log(
|
|
11462
|
-
|
|
11463
|
-
|
|
11464
|
-
|
|
11465
|
-
|
|
11466
|
-
)
|
|
11467
|
-
|
|
11468
|
-
|
|
11451
|
+
const swapCommand = new Command2("swap").description("Toggle between stable public and beta engine libraries").option("--beta", "Switch to beta libraries").option("--stable", "Switch to stable public libraries").action(async (opts) => {
|
|
11452
|
+
const cwd = process.cwd();
|
|
11453
|
+
const pkgPath = require$$2.join(cwd, "package.json");
|
|
11454
|
+
if (!require$$3.existsSync(pkgPath)) {
|
|
11455
|
+
console.error("No package.json found. Run this from a ThatOpen project.");
|
|
11456
|
+
process.exit(1);
|
|
11457
|
+
}
|
|
11458
|
+
const currentlyBeta = readLocalConfig(cwd)?.beta === true;
|
|
11459
|
+
let targetBeta;
|
|
11460
|
+
if (opts.beta && opts.stable) {
|
|
11461
|
+
console.error("Cannot use --beta and --stable together.");
|
|
11462
|
+
process.exit(1);
|
|
11463
|
+
} else if (opts.beta) {
|
|
11464
|
+
targetBeta = true;
|
|
11465
|
+
} else if (opts.stable) {
|
|
11466
|
+
targetBeta = false;
|
|
11467
|
+
} else {
|
|
11468
|
+
targetBeta = !currentlyBeta;
|
|
11469
|
+
}
|
|
11470
|
+
if (targetBeta === currentlyBeta) {
|
|
11471
|
+
console.log(`Already using ${currentlyBeta ? "beta" : "stable"} libraries. Nothing to do.`);
|
|
11472
|
+
return;
|
|
11473
|
+
}
|
|
11474
|
+
const pkg2 = JSON.parse(require$$3.readFileSync(pkgPath, "utf-8"));
|
|
11475
|
+
if (targetBeta) {
|
|
11476
|
+
for (const [stable, beta] of Object.entries(BETA_ALIASES)) {
|
|
11477
|
+
if (pkg2.dependencies?.[stable] !== void 0) {
|
|
11478
|
+
delete pkg2.dependencies[stable];
|
|
11479
|
+
pkg2.dependencies[beta] = "latest";
|
|
11480
|
+
}
|
|
11469
11481
|
}
|
|
11470
|
-
|
|
11471
|
-
|
|
11472
|
-
|
|
11473
|
-
process.execPath,
|
|
11474
|
-
[bin, "create", opts.componentName, "-t", "cloud-test"],
|
|
11475
|
-
{ cwd: parentDir, stdio: "inherit" }
|
|
11482
|
+
} else {
|
|
11483
|
+
const cliPkg = JSON.parse(
|
|
11484
|
+
require$$3.readFileSync(require$$2.join(__dirname, "..", "package.json"), "utf-8")
|
|
11476
11485
|
);
|
|
11477
|
-
|
|
11478
|
-
|
|
11486
|
+
for (const [stable, beta] of Object.entries(BETA_ALIASES)) {
|
|
11487
|
+
if (pkg2.dependencies?.[beta] !== void 0) {
|
|
11488
|
+
delete pkg2.dependencies[beta];
|
|
11489
|
+
pkg2.dependencies[stable] = cliPkg.devDependencies?.[stable] ?? "latest";
|
|
11490
|
+
}
|
|
11479
11491
|
}
|
|
11480
|
-
|
|
11481
|
-
|
|
11482
|
-
|
|
11483
|
-
|
|
11484
|
-
|
|
11485
|
-
` 1. cd ${opts.componentName} && npm run run # Run the test component locally`
|
|
11486
|
-
);
|
|
11492
|
+
}
|
|
11493
|
+
require$$3.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2));
|
|
11494
|
+
updateLocalConfig({ beta: targetBeta }, cwd);
|
|
11495
|
+
console.log(`Switched to ${targetBeta ? "beta" : "stable"} libraries.`);
|
|
11496
|
+
if (targetBeta) {
|
|
11487
11497
|
console.log(
|
|
11488
|
-
|
|
11498
|
+
"Beta packages are private — make sure your beta npm token is configured."
|
|
11489
11499
|
);
|
|
11490
|
-
console.log("");
|
|
11491
11500
|
}
|
|
11492
|
-
);
|
|
11493
|
-
|
|
11494
|
-
|
|
11495
|
-
|
|
11496
|
-
|
|
11497
|
-
|
|
11498
|
-
"Name of the test component project",
|
|
11499
|
-
"test-component"
|
|
11500
|
-
).option("--app-port <port>", "Port for the app bundle server", "4000").option("--component-port <port>", "Port for the component local server", "4001").description(
|
|
11501
|
-
"Serve both the test app (thatopen serve) and the test component (thatopen local-server) in parallel"
|
|
11502
|
-
).action(
|
|
11503
|
-
async (directory, opts) => {
|
|
11504
|
-
const parentDir = require$$2.resolve(process.cwd(), directory);
|
|
11505
|
-
const bin = process.argv[1];
|
|
11506
|
-
const appDir = require$$2.resolve(parentDir, opts.appName);
|
|
11507
|
-
const componentDir = require$$2.resolve(parentDir, opts.componentName);
|
|
11508
|
-
console.log("Starting test suite servers...");
|
|
11509
|
-
console.log("");
|
|
11510
|
-
const children = [];
|
|
11511
|
-
function startProcess(label, cwd, args) {
|
|
11512
|
-
const child = require$$1.spawn(process.execPath, [bin, ...args], {
|
|
11513
|
-
cwd,
|
|
11514
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
11515
|
-
});
|
|
11516
|
-
const prefix = `[${label}]`;
|
|
11517
|
-
child.stdout.on("data", (data) => {
|
|
11518
|
-
for (const line of data.toString().split("\n")) {
|
|
11519
|
-
if (line) console.log(`${prefix} ${line}`);
|
|
11520
|
-
}
|
|
11521
|
-
});
|
|
11522
|
-
child.stderr.on("data", (data) => {
|
|
11523
|
-
for (const line of data.toString().split("\n")) {
|
|
11524
|
-
if (line) console.error(`${prefix} ${line}`);
|
|
11525
|
-
}
|
|
11526
|
-
});
|
|
11527
|
-
child.on("exit", (code) => {
|
|
11528
|
-
console.log(`${prefix} exited with code ${code}`);
|
|
11529
|
-
});
|
|
11530
|
-
children.push(child);
|
|
11531
|
-
}
|
|
11532
|
-
startProcess("component", componentDir, [
|
|
11533
|
-
"local-server",
|
|
11534
|
-
"--port",
|
|
11535
|
-
opts.componentPort
|
|
11536
|
-
]);
|
|
11537
|
-
startProcess("app", appDir, ["serve", "--port", opts.appPort]);
|
|
11538
|
-
console.log(`[component] ${componentDir} → http://localhost:${opts.componentPort}`);
|
|
11539
|
-
console.log(`[app] ${appDir} → http://localhost:${opts.appPort}`);
|
|
11540
|
-
console.log("");
|
|
11541
|
-
process.on("SIGINT", () => {
|
|
11542
|
-
for (const child of children) {
|
|
11543
|
-
child.kill("SIGINT");
|
|
11544
|
-
}
|
|
11545
|
-
setTimeout(() => process.exit(0), 500);
|
|
11546
|
-
});
|
|
11501
|
+
console.log("");
|
|
11502
|
+
console.log("Installing dependencies...");
|
|
11503
|
+
try {
|
|
11504
|
+
require$$1.execSync("npm install", { cwd, stdio: "inherit" });
|
|
11505
|
+
} catch {
|
|
11506
|
+
console.error("Failed to install dependencies. Run `npm install` manually.");
|
|
11547
11507
|
}
|
|
11548
|
-
);
|
|
11508
|
+
});
|
|
11549
11509
|
const pkg = JSON.parse(
|
|
11550
11510
|
require$$3.readFileSync(require$$2.join(__dirname, "..", "package.json"), "utf-8")
|
|
11551
11511
|
);
|
|
@@ -11572,6 +11532,5 @@ program.addCommand(publishCommand);
|
|
|
11572
11532
|
program.addCommand(serveCommand);
|
|
11573
11533
|
program.addCommand(runCommand);
|
|
11574
11534
|
program.addCommand(localServerCommand);
|
|
11575
|
-
program.addCommand(
|
|
11576
|
-
program.addCommand(serveTestsCommand);
|
|
11535
|
+
program.addCommand(swapCommand);
|
|
11577
11536
|
program.parse(process.argv);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|