@thatopen/services 0.8.0 → 0.9.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.
- package/README.md +62 -62
- package/dist/built-in/index.d.ts +66 -41
- package/dist/cli.js +31 -12
- package/dist/core/client.d.ts +6 -0
- package/dist/core/platform-client.d.ts +139 -0
- package/dist/core/platform-client.live.test.d.ts +1 -0
- package/dist/core/platform-client.notifications.test.d.ts +1 -0
- package/dist/index.cjs.js +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +635 -445
- package/dist/types/notifications.d.ts +54 -0
- package/dist/vite-env.d.ts +1 -1
- package/docs/cli/create.md +29 -29
- package/docs/cli/local-server.md +38 -38
- package/docs/cli/login.md +32 -32
- package/docs/cli/publish.md +31 -31
- package/docs/cli/run.md +26 -26
- package/docs/cli/serve.md +43 -43
- package/docs/cli/swap.md +30 -30
- package/package.json +1 -1
- package/src/built-in/CDEManager/example.ts +214 -214
- package/src/built-in/CDEManager/examples/FileEditing/example.ts +226 -226
- package/src/built-in/CDEManager/examples/FileMoves/example.ts +186 -186
- package/src/built-in/CDEManager/examples/FileOperations/example.ts +295 -295
- package/src/built-in/CDEManager/examples/FileTransfers/example.ts +210 -210
- package/src/built-in/CDEManager/examples/FolderManagement/example.ts +230 -230
- package/src/built-in/CDEManager/examples/MetadataSchema/example.ts +230 -230
- package/src/built-in/CDEManager/examples/MetadataViews/example.ts +166 -166
- package/src/built-in/CDEManager/examples/ProjectConfig/example.ts +177 -177
- package/src/built-in/UIManager/src/app/example.ts +97 -97
- package/src/built-in/UIManager/src/app/examples/AppState/example.ts +140 -140
- package/src/built-in/UIManager/src/app/examples/Banner/example.ts +159 -159
- package/src/built-in/UIManager/src/app/examples/Contexts/example.ts +123 -123
- package/src/built-in/UIManager/src/app/examples/FileDrop/example.ts +124 -124
- package/src/built-in/UIManager/src/app/examples/FloatingLayout/example.ts +90 -90
- package/src/built-in/UIManager/src/app/examples/Modal/example.ts +163 -163
- package/src/built-in/UIManager/src/app/examples/Notifications/example.ts +133 -133
- package/src/built-in/UIManager/src/app/examples/ProjectFileStorage/example.ts +150 -150
- package/src/built-in/UIManager/src/app/examples/Sidebar/example.ts +102 -102
- package/src/built-in/UIManager/src/clashes-panel/example.ts +183 -183
- package/src/built-in/UIManager/src/git-history-panel/example.ts +70 -70
- package/src/built-in/UIManager/src/models-list/example.ts +122 -122
- package/src/built-in/UIManager/src/topics-panel/example.ts +170 -170
- package/src/built-in/index.ts +66 -41
- package/src/cli/templates/app/index.html +35 -35
- package/src/cli/templates/app/package.json +32 -32
- package/src/cli/templates/app/src/bim-components/CloudRunner/index.ts +95 -95
- package/src/cli/templates/app/src/bim-components/CloudRunner/src/index.ts +1 -1
- package/src/cli/templates/app/src/bim-components/CloudRunner/src/types.ts +5 -5
- package/src/cli/templates/app/src/bim-components/index.ts +1 -1
- package/src/cli/templates/app/src/globals.ts +1 -1
- package/src/cli/templates/app/src/ui-components/app-info-section/index.ts +26 -26
- package/src/cli/templates/app/src/ui-components/app-info-section/src/index.ts +1 -1
- package/src/cli/templates/app/src/ui-components/app-info-section/src/types.ts +15 -15
- package/src/cli/templates/app/src/ui-components/cloud-runner-section/index.ts +37 -37
- package/src/cli/templates/app/src/ui-components/cloud-runner-section/src/index.ts +1 -1
- package/src/cli/templates/app/src/ui-components/cloud-runner-section/src/types.ts +14 -14
- package/src/cli/templates/app/src/ui-components/index.ts +2 -2
- package/src/cli/templates/app/tsconfig.json +16 -16
- package/src/cli/templates/app/vite.config.js +57 -57
- package/src/cli/templates/cloud-component/README.md +205 -205
- package/src/cli/templates/cloud-component/_thatopen +5 -5
- package/src/cli/templates/cloud-component/declarations.json +4 -4
- package/src/cli/templates/cloud-component/package.json +21 -21
- package/src/cli/templates/cloud-component/src/main.ts +70 -70
- package/src/cli/templates/cloud-component/tsconfig.json +16 -16
- package/src/cli/templates/cloud-component/vite.config.js +46 -46
- package/src/cli/templates/shared/AGENTS.md +8 -8
- package/src/cli/templates/shared/CLAUDE.md +1 -1
- package/src/cli/templates/shared/_gitignore +5 -5
package/README.md
CHANGED
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
# @thatopen/services
|
|
2
|
-
|
|
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
|
-
|
|
5
|
-
> **Using an AI assistant?** Point it at this single file and it can take you from nothing to a running app:
|
|
6
|
-
> → [`docs/ai-quickstart.md`](https://raw.githubusercontent.com/ThatOpen/engine_services/main/docs/ai-quickstart.md)
|
|
7
|
-
|
|
8
|
-
## Quick Start
|
|
9
|
-
|
|
10
|
-
### 1. Install the CLI
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
npm install -g @thatopen/services@latest
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
### 2. Choose a project type
|
|
17
|
-
|
|
18
|
-
| Type | Template | Use when |
|
|
19
|
-
|------|----------|----------|
|
|
20
|
-
| **App** | `app` | You're building a BIM app that runs in the platform's browser UI |
|
|
21
|
-
| **Cloud component** | `cloud-component` | You're building server-side logic triggered by an app |
|
|
22
|
-
|
|
23
|
-
### 3. Scaffold
|
|
24
|
-
|
|
25
|
-
See the full command reference here:
|
|
26
|
-
→ [`docs/cli/create.md`](https://raw.githubusercontent.com/ThatOpen/engine_services/main/docs/cli/create.md)
|
|
27
|
-
|
|
28
|
-
To use beta engine libraries instead of the stable ones, see:
|
|
29
|
-
→ [`docs/cli/swap.md`](https://raw.githubusercontent.com/ThatOpen/engine_services/main/docs/cli/swap.md)
|
|
30
|
-
|
|
31
|
-
### 4. Next steps
|
|
32
|
-
|
|
33
|
-
Once scaffolded, open `AGENTS.md` in the scaffolded project root — it has everything needed to start building.
|
|
34
|
-
|
|
35
|
-
## Beta engine libraries (Founding Members)
|
|
36
|
-
|
|
37
|
-
Founding Members get early access to the private beta engine libraries (`@thatopen-platform/*-beta`). The CLI configures access automatically — no npm account or manual token needed.
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
thatopen login --token <your-token> # API token from the dashboard → Data → API Tokens
|
|
41
|
-
thatopen create my-app --beta # new project on the beta libraries
|
|
42
|
-
# or, in an existing project:
|
|
43
|
-
thatopen swap --beta # toggle the current project to beta
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
On `--beta`, the CLI fetches your read-only beta npm credentials and writes them to the project's `.npmrc`, so `npm install` resolves the private packages. The `.npmrc` is gitignored — it carries a credential, so don't commit or share it. Access is tied to your membership; non-Founding accounts get a clear message and the project is still created.
|
|
47
|
-
|
|
48
|
-
## What's in this repository
|
|
49
|
-
|
|
50
|
-
- **Library** — `EngineServicesClient` and `PlatformClient` for interacting with the That Open API (files, folders, apps, cloud components, executions, permissions).
|
|
51
|
-
- **CLI** — `thatopen` command for scaffolding and publishing.
|
|
52
|
-
- **Built-in component types** — TypeScript stubs for platform-hosted components.
|
|
53
|
-
|
|
54
|
-
## Docs
|
|
55
|
-
|
|
56
|
-
Full reference for all CLI commands and flags:
|
|
57
|
-
→ [`docs/cli/paths.json`](https://raw.githubusercontent.com/ThatOpen/engine_services/main/docs/cli/paths.json)
|
|
58
|
-
|
|
59
|
-
## Contributing
|
|
60
|
-
|
|
61
|
-
See [CONTRIBUTING.md](./CONTRIBUTING.md) for setup, build commands, and publishing workflow.
|
|
62
|
-
|
|
1
|
+
# @thatopen/services
|
|
2
|
+
|
|
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
|
+
|
|
5
|
+
> **Using an AI assistant?** Point it at this single file and it can take you from nothing to a running app:
|
|
6
|
+
> → [`docs/ai-quickstart.md`](https://raw.githubusercontent.com/ThatOpen/engine_services/main/docs/ai-quickstart.md)
|
|
7
|
+
|
|
8
|
+
## Quick Start
|
|
9
|
+
|
|
10
|
+
### 1. Install the CLI
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install -g @thatopen/services@latest
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### 2. Choose a project type
|
|
17
|
+
|
|
18
|
+
| Type | Template | Use when |
|
|
19
|
+
|------|----------|----------|
|
|
20
|
+
| **App** | `app` | You're building a BIM app that runs in the platform's browser UI |
|
|
21
|
+
| **Cloud component** | `cloud-component` | You're building server-side logic triggered by an app |
|
|
22
|
+
|
|
23
|
+
### 3. Scaffold
|
|
24
|
+
|
|
25
|
+
See the full command reference here:
|
|
26
|
+
→ [`docs/cli/create.md`](https://raw.githubusercontent.com/ThatOpen/engine_services/main/docs/cli/create.md)
|
|
27
|
+
|
|
28
|
+
To use beta engine libraries instead of the stable ones, see:
|
|
29
|
+
→ [`docs/cli/swap.md`](https://raw.githubusercontent.com/ThatOpen/engine_services/main/docs/cli/swap.md)
|
|
30
|
+
|
|
31
|
+
### 4. Next steps
|
|
32
|
+
|
|
33
|
+
Once scaffolded, open `AGENTS.md` in the scaffolded project root — it has everything needed to start building.
|
|
34
|
+
|
|
35
|
+
## Beta engine libraries (Founding Members)
|
|
36
|
+
|
|
37
|
+
Founding Members get early access to the private beta engine libraries (`@thatopen-platform/*-beta`). The CLI configures access automatically — no npm account or manual token needed.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
thatopen login --token <your-token> # API token from the dashboard → Data → API Tokens
|
|
41
|
+
thatopen create my-app --beta # new project on the beta libraries
|
|
42
|
+
# or, in an existing project:
|
|
43
|
+
thatopen swap --beta # toggle the current project to beta
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
On `--beta`, the CLI fetches your read-only beta npm credentials and writes them to the project's `.npmrc`, so `npm install` resolves the private packages. The `.npmrc` is gitignored — it carries a credential, so don't commit or share it. Access is tied to your membership; non-Founding accounts get a clear message and the project is still created.
|
|
47
|
+
|
|
48
|
+
## What's in this repository
|
|
49
|
+
|
|
50
|
+
- **Library** — `EngineServicesClient` and `PlatformClient` for interacting with the That Open API (files, folders, apps, cloud components, executions, permissions).
|
|
51
|
+
- **CLI** — `thatopen` command for scaffolding and publishing.
|
|
52
|
+
- **Built-in component types** — TypeScript stubs for platform-hosted components.
|
|
53
|
+
|
|
54
|
+
## Docs
|
|
55
|
+
|
|
56
|
+
Full reference for all CLI commands and flags:
|
|
57
|
+
→ [`docs/cli/paths.json`](https://raw.githubusercontent.com/ThatOpen/engine_services/main/docs/cli/paths.json)
|
|
58
|
+
|
|
59
|
+
## Contributing
|
|
60
|
+
|
|
61
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md) for setup, build commands, and publishing workflow.
|
|
62
|
+
|
package/dist/built-in/index.d.ts
CHANGED
|
@@ -1133,7 +1133,7 @@ export type ContextMode = "default" | "hidden";
|
|
|
1133
1133
|
/** The three kinds of change a commit can carry. */
|
|
1134
1134
|
export type ChangeKind = "create" | "update" | "delete";
|
|
1135
1135
|
/**
|
|
1136
|
-
* Stable id for a commit across models
|
|
1136
|
+
* Stable id for a commit across models — which is now just its guid.
|
|
1137
1137
|
*
|
|
1138
1138
|
* It used to have to be `${model}:${id}`, because the id was a per-model version number and every
|
|
1139
1139
|
* model had a commit 3. A guid needs no help being unique, and that is exactly what it was for.
|
|
@@ -1146,25 +1146,25 @@ export declare const commitKey: (c: {
|
|
|
1146
1146
|
}) => string;
|
|
1147
1147
|
/** How the commit is shown in 3D: review colours, or the model as it ended up. */
|
|
1148
1148
|
export type HighlightMode = "colored" | "plain";
|
|
1149
|
-
/** Dominant change type of a commit: delete
|
|
1149
|
+
/** Dominant change type of a commit: delete → create → update. */
|
|
1150
1150
|
export declare function dominantChange(commit: RevitFlowCommit): DominantChange;
|
|
1151
1151
|
/**
|
|
1152
|
-
* GitHistoryManager
|
|
1152
|
+
* GitHistoryManager — headless engine for the revit-flow git-history built-in.
|
|
1153
1153
|
*
|
|
1154
|
-
* Owns ALL viewer mutation for the change outlines. It does NOT load the model
|
|
1154
|
+
* Owns ALL viewer mutation for the change outlines. It does NOT load the model —
|
|
1155
1155
|
* the user opens a model from the Project Files panel, and this manager reacts to
|
|
1156
1156
|
* that load: it reads the model's hidden `revitflow_history.json` (if any) and
|
|
1157
1157
|
* publishes the commit list. Showing a commit outlines its changed elements
|
|
1158
|
-
* (create
|
|
1159
|
-
* `OBF.Outliner` groups
|
|
1158
|
+
* (create → green, update → blue, delete → red) via three independently-colored
|
|
1159
|
+
* `OBF.Outliner` groups — a cheap post-process outline that never recolors the
|
|
1160
1160
|
* fragment geometry. The Lit panel (`top-git-history`) is intent-only: it calls
|
|
1161
1161
|
* these methods and subscribes to the events below.
|
|
1162
1162
|
*
|
|
1163
1163
|
* Data model, per loaded model (fileId == modelId), all HIDDEN children of it:
|
|
1164
|
-
* - revitflow_history.json
|
|
1164
|
+
* - revitflow_history.json — { model, commits: [{ id, parent, author, source,
|
|
1165
1165
|
* timestamp, changes:[{type,uniqueId}], counts }] }. The first commit is the
|
|
1166
1166
|
* INITIAL full-model capture (its geometry == the visible baseline file).
|
|
1167
|
-
* - revitflow_frag_<N>.frag
|
|
1167
|
+
* - revitflow_frag_<N>.frag — delta fragments for commit N (its created+modified
|
|
1168
1168
|
* geometry), loaded on demand so created elements can be colored.
|
|
1169
1169
|
*/
|
|
1170
1170
|
declare class _GitHistoryManager extends OBC.Component {
|
|
@@ -1177,15 +1177,40 @@ declare class _GitHistoryManager extends OBC.Component {
|
|
|
1177
1177
|
readonly onError: OBC.Event<string>;
|
|
1178
1178
|
/** The GUID currently selected in the 3D view (null when the selection is cleared). */
|
|
1179
1179
|
readonly onSelectedGuidChanged: OBC.Event<string | null>;
|
|
1180
|
+
/** A source icon was added or replaced. */
|
|
1181
|
+
readonly onSourceIconsChanged: OBC.Event<void>;
|
|
1182
|
+
/**
|
|
1183
|
+
* Which mark to draw on a commit, by the application that wrote it.
|
|
1184
|
+
*
|
|
1185
|
+
* Every commit already says who made it, in `source`. The panel used to draw the Revit logo on
|
|
1186
|
+
* all of them regardless, which was true while Revit was the only thing that could write one and
|
|
1187
|
+
* became a lie the moment anything else did: a commit from another tool would claim to be a
|
|
1188
|
+
* Revit commit, on the one part of the row whose whole job is to say where a change came from.
|
|
1189
|
+
*
|
|
1190
|
+
* The format is deliberately open about who writes history, so the icons have to be too. This is
|
|
1191
|
+
* the registry. Only `revit` is built in; an application adds its own:
|
|
1192
|
+
*
|
|
1193
|
+
* const history = components.get(GitHistoryManager);
|
|
1194
|
+
* history.setSourceIcon("rhino", "https://…/rhino.svg"); // a URL, or a data: URI
|
|
1195
|
+
* history.setSourceIcon("tekla", "<svg viewBox='0 0 24 24'>…</svg>"); // or the markup
|
|
1196
|
+
*
|
|
1197
|
+
* A source with no icon gets a neutral one rather than somebody else's.
|
|
1198
|
+
*/
|
|
1199
|
+
readonly sourceIcons: Map<string, string>;
|
|
1200
|
+
/**
|
|
1201
|
+
* @param source the commit's own `source` value, matched case-insensitively.
|
|
1202
|
+
* @param icon a URL, a `data:` URI, or inline `<svg>` markup.
|
|
1203
|
+
*/
|
|
1204
|
+
setSourceIcon(source: string, icon: string): void;
|
|
1180
1205
|
world?: OBC.World;
|
|
1181
1206
|
/**
|
|
1182
1207
|
* What happens to elements that are NOT part of the selected commit:
|
|
1183
|
-
* "default"
|
|
1184
|
-
* "hidden"
|
|
1208
|
+
* "default" — left as they are (the change outlines sit on the full model)
|
|
1209
|
+
* "hidden" — hidden entirely, isolating the commit's elements
|
|
1185
1210
|
*
|
|
1186
1211
|
* A dimmed ("ghost") middle ground was dropped: the fragments x-ray writes depth
|
|
1187
1212
|
* from the pixels its screen door keeps, so dimmed geometry still occluded the very
|
|
1188
|
-
* elements under review
|
|
1213
|
+
* elements under review — worse the denser the model in front. Fixing that properly
|
|
1189
1214
|
* belongs in the renderer, not here, so this offers the two states that are exact.
|
|
1190
1215
|
*/
|
|
1191
1216
|
contextMode: ContextMode;
|
|
@@ -1203,18 +1228,18 @@ declare class _GitHistoryManager extends OBC.Component {
|
|
|
1203
1228
|
prefetchRadius: number;
|
|
1204
1229
|
/**
|
|
1205
1230
|
* How a commit is presented in 3D:
|
|
1206
|
-
* "colored"
|
|
1207
|
-
* "plain"
|
|
1231
|
+
* "colored" — outline created/edited/deleted in their colours (the review lens)
|
|
1232
|
+
* "plain" — no outlines: the model simply as it stood AFTER the commit, so the
|
|
1208
1233
|
* deleted elements are hidden rather than painted red
|
|
1209
1234
|
*/
|
|
1210
1235
|
highlightMode: HighlightMode;
|
|
1211
|
-
/** @deprecated kept so older callers still compile
|
|
1236
|
+
/** @deprecated kept so older callers still compile — maps onto contextMode. */
|
|
1212
1237
|
get isolateChanges(): boolean;
|
|
1213
|
-
/** Green
|
|
1238
|
+
/** Green — created elements. */
|
|
1214
1239
|
readonly COLOR_CREATED = "#22c55e";
|
|
1215
|
-
/** Golden yellow
|
|
1240
|
+
/** Golden yellow — modified elements. */
|
|
1216
1241
|
readonly COLOR_MODIFIED = "#e3b341";
|
|
1217
|
-
/** Red
|
|
1242
|
+
/** Red — deleted elements. */
|
|
1218
1243
|
readonly COLOR_DELETED = "#ef4444";
|
|
1219
1244
|
readonly GROUP_CREATED = "revitflow-created";
|
|
1220
1245
|
readonly GROUP_MODIFIED = "revitflow-modified";
|
|
@@ -1223,7 +1248,7 @@ declare class _GitHistoryManager extends OBC.Component {
|
|
|
1223
1248
|
private _projectId?;
|
|
1224
1249
|
/**
|
|
1225
1250
|
* One entry per loaded revit-flow model. Commit ids are per-model version numbers, so
|
|
1226
|
-
* they collide across models
|
|
1251
|
+
* they collide across models — every commit is tagged with its modelId and a commit is
|
|
1227
1252
|
* addressed by {@link commitKey}, never by id alone.
|
|
1228
1253
|
*/
|
|
1229
1254
|
private _models;
|
|
@@ -1295,7 +1320,7 @@ declare class _GitHistoryManager extends OBC.Component {
|
|
|
1295
1320
|
init(client: PlatformClient): Promise<void>;
|
|
1296
1321
|
/**
|
|
1297
1322
|
* Follow the viewer's selection so the element view tracks whatever the user clicks in
|
|
1298
|
-
* 3D
|
|
1323
|
+
* 3D — no "trace this" button to press. The Highlighter's events appear asynchronously
|
|
1299
1324
|
* (they're registered when the viewer sets it up), so retry briefly until they exist.
|
|
1300
1325
|
*/
|
|
1301
1326
|
private _watchSelection;
|
|
@@ -1304,7 +1329,7 @@ declare class _GitHistoryManager extends OBC.Component {
|
|
|
1304
1329
|
/**
|
|
1305
1330
|
* Probe a loaded model for a sibling visible `revitflow_history.json` in its
|
|
1306
1331
|
* folder. If present, adopt it as the active model and publish its commits.
|
|
1307
|
-
* Silent for non-revit models and for our own delta frags
|
|
1332
|
+
* Silent for non-revit models and for our own delta frags — only genuine
|
|
1308
1333
|
* fetch/parse failures raise onError.
|
|
1309
1334
|
*/
|
|
1310
1335
|
private _probeModel;
|
|
@@ -1339,7 +1364,7 @@ declare class _GitHistoryManager extends OBC.Component {
|
|
|
1339
1364
|
* Show the model as it stood AT `commit`: the visible baseline is the model at its
|
|
1340
1365
|
* INITIAL commit, and everything created later lives in per-commit delta .frags loaded
|
|
1341
1366
|
* as separate models. Those deltas stay loaded (the prefetch window keeps neighbours
|
|
1342
|
-
* warm), so stepping BACK has to hide the ones from later commits
|
|
1367
|
+
* warm), so stepping BACK has to hide the ones from later commits — otherwise a wall
|
|
1343
1368
|
* added in commit 3 was still sitting there while you were looking at commit 2.
|
|
1344
1369
|
* Only touches deltas of the commit's own model; other models keep their own state.
|
|
1345
1370
|
*/
|
|
@@ -1379,7 +1404,7 @@ declare class _GitHistoryManager extends OBC.Component {
|
|
|
1379
1404
|
selectedGuids(): Promise<string[]>;
|
|
1380
1405
|
selectedGuid(): Promise<string | null>;
|
|
1381
1406
|
/**
|
|
1382
|
-
* Select every element the commit touched, in the viewer's own selection
|
|
1407
|
+
* Select every element the commit touched, in the viewer's own selection — so the
|
|
1383
1408
|
* usual tools (properties, isolate, zoom) work on it like any hand-made selection.
|
|
1384
1409
|
* Honours the current type filter, so "only deletions" selects only those.
|
|
1385
1410
|
* @returns how many elements ended up selected.
|
|
@@ -1393,11 +1418,11 @@ declare class _GitHistoryManager extends OBC.Component {
|
|
|
1393
1418
|
private _outliner;
|
|
1394
1419
|
/**
|
|
1395
1420
|
* Create the three independently-colored outline groups once. The viewer
|
|
1396
|
-
* owns the Outliner's DEFAULT group (selection)
|
|
1421
|
+
* owns the Outliner's DEFAULT group (selection) — we only add our own named
|
|
1397
1422
|
* groups and never touch "default".
|
|
1398
1423
|
*/
|
|
1399
1424
|
private _ensureGroups;
|
|
1400
|
-
/** Clear our three outline groups only
|
|
1425
|
+
/** Clear our three outline groups only — leaves the viewer's default group. */
|
|
1401
1426
|
private _clearOutlines;
|
|
1402
1427
|
/**
|
|
1403
1428
|
* Resolve each change bucket's GUIDs to localIds across every loaded model
|
|
@@ -1411,7 +1436,7 @@ declare class _GitHistoryManager extends OBC.Component {
|
|
|
1411
1436
|
private _dropSuperseded;
|
|
1412
1437
|
/**
|
|
1413
1438
|
* Hide (or restore) the elements a commit deleted. Tracked separately from the context
|
|
1414
|
-
* modes so switching Colored
|
|
1439
|
+
* modes so switching Colored↔Plain doesn't disturb ghosting or the rest of the model.
|
|
1415
1440
|
*/
|
|
1416
1441
|
private _applyDeletedVisibility;
|
|
1417
1442
|
/**
|
|
@@ -1420,14 +1445,14 @@ declare class _GitHistoryManager extends OBC.Component {
|
|
|
1420
1445
|
* THE BUG THIS EXISTS FOR. The baseline .frag holds the whole model as of the first
|
|
1421
1446
|
* commit, and every later commit ships a delta .frag with the geometry it created AND
|
|
1422
1447
|
* the geometry it modified. Both stay in the scene. For a CREATED element that is
|
|
1423
|
-
* right
|
|
1448
|
+
* right — it exists in exactly one place. For a MODIFIED one it is not: the element is
|
|
1424
1449
|
* in the baseline at its old shape and in the delta at its new one, and the viewer drew
|
|
1425
1450
|
* both. Measured 2026-08-05 on a wall whose height Quim raised: the new wall stood
|
|
1426
1451
|
* proud of the old one, with the coincident faces z-fighting into a dotted band.
|
|
1427
1452
|
*
|
|
1428
1453
|
* The rule is the obvious one once stated: for any element, only the newest VISIBLE
|
|
1429
1454
|
* source may draw it. Deltas are walked newest-first, each guid is claimed by the first
|
|
1430
|
-
* source that has it, and every older copy
|
|
1455
|
+
* source that has it, and every older copy — in an older delta or in the baseline — is
|
|
1431
1456
|
* hidden. Deltas newer than the commit being shown are already hidden wholesale by
|
|
1432
1457
|
* `_applyFutureVisibility`, so they never get to claim anything.
|
|
1433
1458
|
*
|
|
@@ -1445,13 +1470,13 @@ declare class _GitHistoryManager extends OBC.Component {
|
|
|
1445
1470
|
* load that commit's delta, which is the last place its geometry existed.
|
|
1446
1471
|
*/
|
|
1447
1472
|
private _ensureDeletedGeometry;
|
|
1448
|
-
/** GUIDs
|
|
1473
|
+
/** GUIDs → { modelId: Set<localId> } across the given models. */
|
|
1449
1474
|
private _buildMap;
|
|
1450
1475
|
private _mergeMaps;
|
|
1451
1476
|
/**
|
|
1452
1477
|
* Dim ("ghost") or hide every element that is NOT part of the shown commit, per the
|
|
1453
1478
|
* chosen context mode. Best-effort per model: a model that doesn't support the call is
|
|
1454
|
-
* simply left alone
|
|
1479
|
+
* simply left alone — the outlines still convey the change.
|
|
1455
1480
|
*/
|
|
1456
1481
|
private _applyContext;
|
|
1457
1482
|
/** Undo whatever the context mode did: drop the ghost overlay and restore visibility. */
|
|
@@ -1469,42 +1494,42 @@ declare class _GitHistoryManager extends OBC.Component {
|
|
|
1469
1494
|
private _firstWorld;
|
|
1470
1495
|
}
|
|
1471
1496
|
/**
|
|
1472
|
-
* GitHistoryManager
|
|
1497
|
+
* GitHistoryManager — headless engine for the revit-flow git-history built-in.
|
|
1473
1498
|
*
|
|
1474
|
-
* Owns ALL viewer mutation for the change outlines. It does NOT load the model
|
|
1499
|
+
* Owns ALL viewer mutation for the change outlines. It does NOT load the model —
|
|
1475
1500
|
* the user opens a model from the Project Files panel, and this manager reacts to
|
|
1476
1501
|
* that load: it reads the model's hidden `revitflow_history.json` (if any) and
|
|
1477
1502
|
* publishes the commit list. Showing a commit outlines its changed elements
|
|
1478
|
-
* (create
|
|
1479
|
-
* `OBF.Outliner` groups
|
|
1503
|
+
* (create → green, update → blue, delete → red) via three independently-colored
|
|
1504
|
+
* `OBF.Outliner` groups — a cheap post-process outline that never recolors the
|
|
1480
1505
|
* fragment geometry. The Lit panel (`top-git-history`) is intent-only: it calls
|
|
1481
1506
|
* these methods and subscribes to the events below.
|
|
1482
1507
|
*
|
|
1483
1508
|
* Data model, per loaded model (fileId == modelId), all HIDDEN children of it:
|
|
1484
|
-
* - revitflow_history.json
|
|
1509
|
+
* - revitflow_history.json — { model, commits: [{ id, parent, author, source,
|
|
1485
1510
|
* timestamp, changes:[{type,uniqueId}], counts }] }. The first commit is the
|
|
1486
1511
|
* INITIAL full-model capture (its geometry == the visible baseline file).
|
|
1487
|
-
* - revitflow_frag_<N>.frag
|
|
1512
|
+
* - revitflow_frag_<N>.frag — delta fragments for commit N (its created+modified
|
|
1488
1513
|
* geometry), loaded on demand so created elements can be colored.
|
|
1489
1514
|
*/
|
|
1490
1515
|
export type GitHistoryManager = InstanceType<typeof _GitHistoryManager>;
|
|
1491
1516
|
/**
|
|
1492
|
-
* GitHistoryManager
|
|
1517
|
+
* GitHistoryManager — headless engine for the revit-flow git-history built-in.
|
|
1493
1518
|
*
|
|
1494
|
-
* Owns ALL viewer mutation for the change outlines. It does NOT load the model
|
|
1519
|
+
* Owns ALL viewer mutation for the change outlines. It does NOT load the model —
|
|
1495
1520
|
* the user opens a model from the Project Files panel, and this manager reacts to
|
|
1496
1521
|
* that load: it reads the model's hidden `revitflow_history.json` (if any) and
|
|
1497
1522
|
* publishes the commit list. Showing a commit outlines its changed elements
|
|
1498
|
-
* (create
|
|
1499
|
-
* `OBF.Outliner` groups
|
|
1523
|
+
* (create → green, update → blue, delete → red) via three independently-colored
|
|
1524
|
+
* `OBF.Outliner` groups — a cheap post-process outline that never recolors the
|
|
1500
1525
|
* fragment geometry. The Lit panel (`top-git-history`) is intent-only: it calls
|
|
1501
1526
|
* these methods and subscribes to the events below.
|
|
1502
1527
|
*
|
|
1503
1528
|
* Data model, per loaded model (fileId == modelId), all HIDDEN children of it:
|
|
1504
|
-
* - revitflow_history.json
|
|
1529
|
+
* - revitflow_history.json — { model, commits: [{ id, parent, author, source,
|
|
1505
1530
|
* timestamp, changes:[{type,uniqueId}], counts }] }. The first commit is the
|
|
1506
1531
|
* INITIAL full-model capture (its geometry == the visible baseline file).
|
|
1507
|
-
* - revitflow_frag_<N>.frag
|
|
1532
|
+
* - revitflow_frag_<N>.frag — delta fragments for commit N (its created+modified
|
|
1508
1533
|
* geometry), loaded on demand so created elements can be colored.
|
|
1509
1534
|
*/
|
|
1510
1535
|
export declare const GitHistoryManager: typeof _GitHistoryManager & {
|
package/dist/cli.js
CHANGED
|
@@ -4205,8 +4205,8 @@ class BaseXHR extends Polling {
|
|
|
4205
4205
|
/**
|
|
4206
4206
|
* Sends data.
|
|
4207
4207
|
*
|
|
4208
|
-
* @param {String} data to send.
|
|
4209
|
-
* @param {Function} called upon flush.
|
|
4208
|
+
* @param {String} data - data to send.
|
|
4209
|
+
* @param {Function} fn - called upon flush.
|
|
4210
4210
|
* @private
|
|
4211
4211
|
*/
|
|
4212
4212
|
doWrite(data, fn) {
|
|
@@ -4959,7 +4959,7 @@ class SocketWithoutUpgrade extends Emitter {
|
|
|
4959
4959
|
/**
|
|
4960
4960
|
* Sends a packet.
|
|
4961
4961
|
*
|
|
4962
|
-
* @param {String} type
|
|
4962
|
+
* @param {String} type - packet type.
|
|
4963
4963
|
* @param {String} data.
|
|
4964
4964
|
* @param {Object} options.
|
|
4965
4965
|
* @param {Function} fn - callback function.
|
|
@@ -5194,11 +5194,12 @@ class SocketWithUpgrade extends SocketWithoutUpgrade {
|
|
|
5194
5194
|
}
|
|
5195
5195
|
let Socket$1 = class Socket extends SocketWithUpgrade {
|
|
5196
5196
|
constructor(uri, opts = {}) {
|
|
5197
|
-
const
|
|
5197
|
+
const isOptionsOnly = typeof uri === "object";
|
|
5198
|
+
const o = isOptionsOnly ? { ...uri } : { ...opts };
|
|
5198
5199
|
if (!o.transports || o.transports && typeof o.transports[0] === "string") {
|
|
5199
5200
|
o.transports = (o.transports || ["polling", "websocket", "webtransport"]).map((transportName) => transports[transportName]).filter((t) => !!t);
|
|
5200
5201
|
}
|
|
5201
|
-
super(uri, o);
|
|
5202
|
+
super(isOptionsOnly ? o : uri, o);
|
|
5202
5203
|
}
|
|
5203
5204
|
};
|
|
5204
5205
|
function url(uri, path2 = "", loc) {
|
|
@@ -5419,12 +5420,13 @@ class Encoder {
|
|
|
5419
5420
|
class Decoder extends Emitter {
|
|
5420
5421
|
/**
|
|
5421
5422
|
* Decoder constructor
|
|
5422
|
-
*
|
|
5423
|
-
* @param {function} reviver - custom reviver to pass down to JSON.stringify
|
|
5424
5423
|
*/
|
|
5425
|
-
constructor(
|
|
5424
|
+
constructor(opts) {
|
|
5426
5425
|
super();
|
|
5427
|
-
this.
|
|
5426
|
+
this.opts = Object.assign({
|
|
5427
|
+
reviver: void 0,
|
|
5428
|
+
maxAttachments: 10
|
|
5429
|
+
}, typeof opts === "function" ? { reviver: opts } : opts);
|
|
5428
5430
|
}
|
|
5429
5431
|
/**
|
|
5430
5432
|
* Decodes an encoded packet string into packet JSON.
|
|
@@ -5484,7 +5486,13 @@ class Decoder extends Emitter {
|
|
|
5484
5486
|
if (buf != Number(buf) || str.charAt(i) !== "-") {
|
|
5485
5487
|
throw new Error("Illegal attachments");
|
|
5486
5488
|
}
|
|
5487
|
-
|
|
5489
|
+
const n = Number(buf);
|
|
5490
|
+
if (!isInteger(n) || n < 0) {
|
|
5491
|
+
throw new Error("Illegal attachments");
|
|
5492
|
+
} else if (n > this.opts.maxAttachments) {
|
|
5493
|
+
throw new Error("too many attachments");
|
|
5494
|
+
}
|
|
5495
|
+
p.attachments = n;
|
|
5488
5496
|
}
|
|
5489
5497
|
if ("/" === str.charAt(i + 1)) {
|
|
5490
5498
|
const start = i + 1;
|
|
@@ -5525,7 +5533,7 @@ class Decoder extends Emitter {
|
|
|
5525
5533
|
}
|
|
5526
5534
|
tryParse(str) {
|
|
5527
5535
|
try {
|
|
5528
|
-
return JSON.parse(str, this.reviver);
|
|
5536
|
+
return JSON.parse(str, this.opts.reviver);
|
|
5529
5537
|
} catch (e) {
|
|
5530
5538
|
return false;
|
|
5531
5539
|
}
|
|
@@ -5587,6 +5595,9 @@ class BinaryReconstructor {
|
|
|
5587
5595
|
this.buffers = [];
|
|
5588
5596
|
}
|
|
5589
5597
|
}
|
|
5598
|
+
const isInteger = Number.isInteger || function(value2) {
|
|
5599
|
+
return typeof value2 === "number" && isFinite(value2) && Math.floor(value2) === value2;
|
|
5600
|
+
};
|
|
5590
5601
|
function isObject(value2) {
|
|
5591
5602
|
return Object.prototype.toString.call(value2) === "[object Object]";
|
|
5592
5603
|
}
|
|
@@ -6942,6 +6953,14 @@ class EngineServicesClient {
|
|
|
6942
6953
|
* the new token is picked up on every request — expired tokens no
|
|
6943
6954
|
* longer stick around.
|
|
6944
6955
|
*/
|
|
6956
|
+
/**
|
|
6957
|
+
* Socket origin without namespace or query, for gateways other than the
|
|
6958
|
+
* execution one. `wsUrl` already carries a token that may be stale when a
|
|
6959
|
+
* provider is in play, so callers append their own.
|
|
6960
|
+
*/
|
|
6961
|
+
get socketOrigin() {
|
|
6962
|
+
return this.wsUrl.split("?")[0];
|
|
6963
|
+
}
|
|
6945
6964
|
async resolveAccessToken() {
|
|
6946
6965
|
return this.accessToken;
|
|
6947
6966
|
}
|
|
@@ -8226,7 +8245,7 @@ Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/js
|
|
|
8226
8245
|
JSZip uses the library pako released under the MIT license :
|
|
8227
8246
|
https://github.com/nodeca/pako/blob/main/LICENSE
|
|
8228
8247
|
*/
|
|
8229
|
-
(function(module2, exports
|
|
8248
|
+
(function(module2, exports) {
|
|
8230
8249
|
!function(e) {
|
|
8231
8250
|
module2.exports = e();
|
|
8232
8251
|
}(function() {
|
package/dist/core/client.d.ts
CHANGED
|
@@ -207,6 +207,12 @@ export declare class EngineServicesClient {
|
|
|
207
207
|
* the new token is picked up on every request — expired tokens no
|
|
208
208
|
* longer stick around.
|
|
209
209
|
*/
|
|
210
|
+
/**
|
|
211
|
+
* Socket origin without namespace or query, for gateways other than the
|
|
212
|
+
* execution one. `wsUrl` already carries a token that may be stale when a
|
|
213
|
+
* provider is in play, so callers append their own.
|
|
214
|
+
*/
|
|
215
|
+
protected get socketOrigin(): string;
|
|
210
216
|
protected resolveAccessToken(): Promise<string>;
|
|
211
217
|
/**
|
|
212
218
|
* Protected extension hook for subclasses (e.g. `PlatformClient`) that
|
|
@@ -1,6 +1,33 @@
|
|
|
1
1
|
import { EngineServicesClient, EngineServicesClientProps } from './client';
|
|
2
2
|
import { Project, ProjectData } from '../types/projects';
|
|
3
|
+
import { MarkNotificationsReadResultDto, NotificationPageDto, NotificationSubscriptionView } from '../types/notifications';
|
|
3
4
|
|
|
5
|
+
/**
|
|
6
|
+
* What arrived on the socket. One callback for all three because a bell
|
|
7
|
+
* reacts the same way to each: refresh the badge, and the list if open.
|
|
8
|
+
*
|
|
9
|
+
* `allRead` is one event for the whole sweep rather than one per
|
|
10
|
+
* notification, so do not expect an id on it.
|
|
11
|
+
*/
|
|
12
|
+
export type LiveNotificationEvent = {
|
|
13
|
+
type: 'created';
|
|
14
|
+
id: string;
|
|
15
|
+
} | {
|
|
16
|
+
type: 'read';
|
|
17
|
+
id: string;
|
|
18
|
+
} | {
|
|
19
|
+
type: 'allRead';
|
|
20
|
+
batch: number;
|
|
21
|
+
};
|
|
22
|
+
/** Per-automation opt-in. `failures` skips started events entirely. */
|
|
23
|
+
export type NotificationSubscriptionFilterInput = 'all' | 'failures';
|
|
24
|
+
export interface NotificationSubscriptionInput {
|
|
25
|
+
filter?: NotificationSubscriptionFilterInput;
|
|
26
|
+
/** Overrides the account-level channel setting for this automation only. */
|
|
27
|
+
channels?: {
|
|
28
|
+
email?: boolean;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
4
31
|
/** Scope by which a permission was granted (or `'none'` if denied). */
|
|
5
32
|
export type PermissionScope = 'global' | 'project' | 'entity' | 'none';
|
|
6
33
|
/** Result of a single permission check. */
|
|
@@ -110,4 +137,116 @@ export declare class PlatformClient extends EngineServicesClient {
|
|
|
110
137
|
* single round-trip; results come back in the same order as `checks`.
|
|
111
138
|
*/
|
|
112
139
|
checkPermissionBatch(checks: PermissionCheckEntry[]): Promise<PermissionCheckResult[]>;
|
|
140
|
+
/**
|
|
141
|
+
* Lists the signed-in user's notifications, newest first.
|
|
142
|
+
*
|
|
143
|
+
* Scoped to whoever the bearer token belongs to — an app cannot read
|
|
144
|
+
* anyone else's. Muted notifications are included: muting silences the
|
|
145
|
+
* badge and the delivery channels, it does not hide the record.
|
|
146
|
+
*
|
|
147
|
+
* Paginate by passing the previous response's `nextCursor` back in; it is
|
|
148
|
+
* opaque, so do not build one by hand. A null `nextCursor` means the last
|
|
149
|
+
* page.
|
|
150
|
+
*
|
|
151
|
+
* @example Walk every page:
|
|
152
|
+
* ```ts
|
|
153
|
+
* let cursor: string | undefined;
|
|
154
|
+
* do {
|
|
155
|
+
* const page = await client.getNotifications({ cursor });
|
|
156
|
+
* render(page.items);
|
|
157
|
+
* cursor = page.nextCursor ?? undefined;
|
|
158
|
+
* } while (cursor);
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
getNotifications(params?: {
|
|
162
|
+
cursor?: string;
|
|
163
|
+
limit?: number;
|
|
164
|
+
}): Promise<NotificationPageDto>;
|
|
165
|
+
/**
|
|
166
|
+
* Number of unread notifications, excluding muted ones. This is the bell
|
|
167
|
+
* badge count, so it is cheap to poll.
|
|
168
|
+
*/
|
|
169
|
+
getUnreadNotificationCount(): Promise<number>;
|
|
170
|
+
/**
|
|
171
|
+
* Marks specific notifications as read. Ids the caller does not own are
|
|
172
|
+
* ignored rather than rejected, so `updated` can be lower than the number
|
|
173
|
+
* passed in.
|
|
174
|
+
*/
|
|
175
|
+
markNotificationsRead(notificationIds: string[]): Promise<MarkNotificationsReadResultDto>;
|
|
176
|
+
/** Marks every unread notification as read in one call. */
|
|
177
|
+
markAllNotificationsRead(): Promise<MarkNotificationsReadResultDto>;
|
|
178
|
+
/**
|
|
179
|
+
* The automations this user has subscribed to. Nobody is subscribed by
|
|
180
|
+
* default, so an empty list is the normal state.
|
|
181
|
+
*/
|
|
182
|
+
getNotificationSubscriptions(): Promise<NotificationSubscriptionView[]>;
|
|
183
|
+
/**
|
|
184
|
+
* Removes this user's subscription to one automation.
|
|
185
|
+
*
|
|
186
|
+
* Unlike subscribing, which happens through the project routes, this works
|
|
187
|
+
* for any automation the user is subscribed to and keeps working after the
|
|
188
|
+
* automation itself is gone — opting out must never be the thing that
|
|
189
|
+
* fails.
|
|
190
|
+
*/
|
|
191
|
+
unsubscribeFromAutomation(hookId: string): Promise<{
|
|
192
|
+
unsubscribed: boolean;
|
|
193
|
+
}>;
|
|
194
|
+
/**
|
|
195
|
+
* Subscribes the signed-in user to one project automation's runs.
|
|
196
|
+
*
|
|
197
|
+
* Nobody is subscribed by default, so this is what makes an automation
|
|
198
|
+
* produce notifications for this user at all. Subscribing again is
|
|
199
|
+
* harmless: it updates the existing subscription rather than duplicating.
|
|
200
|
+
*
|
|
201
|
+
* Read-level access to the project is enough. Someone who can see an
|
|
202
|
+
* automation can follow it without being able to change it.
|
|
203
|
+
*
|
|
204
|
+
* @example Follow only the failures, and email me about them:
|
|
205
|
+
* ```ts
|
|
206
|
+
* await client.subscribeToAutomation(projectId, hookId, {
|
|
207
|
+
* filter: 'failures',
|
|
208
|
+
* channels: { email: true },
|
|
209
|
+
* });
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
subscribeToAutomation(projectId: string, hookId: string, input?: NotificationSubscriptionInput): Promise<{
|
|
213
|
+
subscribed: true;
|
|
214
|
+
}>;
|
|
215
|
+
/**
|
|
216
|
+
* Changes an existing subscription. Only the fields passed are touched, so
|
|
217
|
+
* sending `channels` alone leaves the filter as it was.
|
|
218
|
+
*
|
|
219
|
+
* Throws if the user is not subscribed; use {@link subscribeToAutomation}
|
|
220
|
+
* to create one.
|
|
221
|
+
*/
|
|
222
|
+
updateAutomationSubscription(projectId: string, hookId: string, changes: NotificationSubscriptionInput): Promise<{
|
|
223
|
+
updated: true;
|
|
224
|
+
}>;
|
|
225
|
+
/**
|
|
226
|
+
* Listens for this user's notifications in real time.
|
|
227
|
+
*
|
|
228
|
+
* Unlike {@link EngineServicesClient.onExecutionProgress}, which follows one
|
|
229
|
+
* execution and closes when it ends, this stays connected for the session:
|
|
230
|
+
* the server puts the socket in a room for the signed-in account and pushes
|
|
231
|
+
* anything addressed to them.
|
|
232
|
+
*
|
|
233
|
+
* The events carry ids rather than the notifications themselves, so treat
|
|
234
|
+
* them as a signal to refresh. That keeps a burst cheap and means the
|
|
235
|
+
* server is never the source of a stale render.
|
|
236
|
+
*
|
|
237
|
+
* Requires a user JWT. An API access token is rejected by the gateway,
|
|
238
|
+
* because it identifies a token rather than a person.
|
|
239
|
+
*
|
|
240
|
+
* @returns a function that disconnects. Call it on unmount.
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* ```ts
|
|
244
|
+
* const stop = await client.onNotification((event) => {
|
|
245
|
+
* if (event.type === 'created') refreshBell();
|
|
246
|
+
* });
|
|
247
|
+
* // later
|
|
248
|
+
* stop();
|
|
249
|
+
* ```
|
|
250
|
+
*/
|
|
251
|
+
onNotification(onEvent: (event: LiveNotificationEvent) => void): Promise<() => void>;
|
|
113
252
|
}
|