@thatopen/services 0.3.13 → 0.3.15

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.
@@ -2,7 +2,7 @@ import { Command } from 'commander';
2
2
 
3
3
  /**
4
4
  * `thatopen revit ...` — Revit collaboration commands. They drive the local
5
- * That Open Revit add-in (BT3): publish a shared central, join one, and sync.
5
+ * That Open Revit add-in (revit-flow): publish a shared central, join one, and sync.
6
6
  * Auth comes from `thatopen login` (~/.thatopen/config.json) and is forwarded to
7
7
  * the add-in, so the user never re-enters a token here.
8
8
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Talks to the local That Open Revit add-in (BT3). The add-in runs a
2
+ * Talks to the local That Open Revit add-in (revit-flow). The add-in runs a
3
3
  * 127.0.0.1 command listener and, on startup, writes its port + token to
4
4
  * %APPDATA%\ThatOpen\revit-addin.json so the CLI can discover it. Revit-specific
5
5
  * work (create central, create local, sync) happens inside the add-in; the CLI
package/dist/cli.js CHANGED
@@ -11701,7 +11701,7 @@ async function callAddin(cmd, body = {}) {
11701
11701
  method: "POST",
11702
11702
  headers: {
11703
11703
  "Content-Type": "application/json",
11704
- "X-Bt3-Token": info.token
11704
+ "X-RevitFlow-Token": info.token
11705
11705
  },
11706
11706
  body: JSON.stringify(body),
11707
11707
  signal: AbortSignal.timeout(6e5)
@@ -11799,6 +11799,22 @@ revitCommand.command("sync").description("Synchronize your local with the team (
11799
11799
  const r = await callAddin("sync");
11800
11800
  console.log(`Synced. v${r.verB} → v${r.verA}.`);
11801
11801
  });
11802
+ revitCommand.command("worksets").description("List the model worksets and who owns each").action(async () => {
11803
+ await connect();
11804
+ const r = await callAddin("worksets");
11805
+ console.log(JSON.stringify(r.worksets, null, 2));
11806
+ });
11807
+ revitCommand.command("take").description("Take ownership of a workset (only one person at a time — the team lock arbitrates)").requiredOption("--workset <name>", "The workset name to take").action(async (opts) => {
11808
+ await connect();
11809
+ const r = await callAddin("take", { workset: opts.workset });
11810
+ if (r.taken) console.log(`✓ Took workset "${r.workset}" (${r.result}). You can now edit its elements.`);
11811
+ else console.log(`✗ Could NOT take "${r.workset}" — it is held by "${r.deniedBy}". Ask them to release it (untake).`);
11812
+ });
11813
+ revitCommand.command("untake").description("Release a workset you own so teammates can take it").requiredOption("--workset <name>", "The workset name to release").action(async (opts) => {
11814
+ await connect();
11815
+ const r = await callAddin("untake", { workset: opts.workset });
11816
+ console.log(`Released workset "${r.released}".`);
11817
+ });
11802
11818
  const pkg = JSON.parse(
11803
11819
  require$$3.readFileSync(require$$2.join(__dirname, "..", "package.json"), "utf-8")
11804
11820
  );
@@ -81,7 +81,7 @@ Do **not** ask for the access token yet (that's Step 2).
81
81
 
82
82
  **(b) Revit is open but status still errors → the add‑in isn't installed. Install it:**
83
83
  - The add‑in files ship in **this same folder** as this guide (`install.ps1`,
84
- `Bt3Addin.dll`, `Bt3Core.dll`, `bt3.addin`). From this folder, run:
84
+ `RevitFlowAddin.dll`, `RevitFlowCore.dll`, `revitflow.addin`). From this folder, run:
85
85
  ```
86
86
  powershell -ExecutionPolicy Bypass -File install.ps1
87
87
  ```
@@ -178,6 +178,52 @@ Success: `Synced. vN → vM.` Repeat as often as they like; syncs are queued, n
178
178
 
179
179
  ---
180
180
 
181
+ ## Step 5 — Worksets (so two people don't edit the same thing)
182
+ Syncs never corrupt the central, but if **two people edit the SAME element** without
183
+ coordinating, the second one's sync is rejected and their local can get stuck. To avoid
184
+ that, claim the part of the model you're about to edit using **worksets** — the unit of
185
+ ownership. Typically one workset per area or per person (this central already has one per
186
+ floor/level).
187
+
188
+ **See the worksets and who owns each:**
189
+ ```
190
+ thatopen revit worksets
191
+ ```
192
+
193
+ **Claim a workset before editing it — two equivalent ways:**
194
+ - **Ribbon (easiest):** in Revit's **Add-Ins → That Open** panel, select any element that
195
+ belongs to the workset you want, then click **"Take workset"**.
196
+ - **CLI:**
197
+ ```
198
+ thatopen revit take --workset "<NAME>"
199
+ ```
200
+ Only **one person at a time** can own a workset. If someone else already holds it, you get
201
+ `✗ held by <user>` — coordinate or pick another. If two people click Take at the same
202
+ instant, the platform lock gives it to exactly one and denies the other (no corruption).
203
+
204
+ **⚠️ Ownership only protects you AFTER a sync round.** Taking a workset is instant for the
205
+ *claim* (nobody else can take it), but Revit only **blocks teammates' edits** once the
206
+ ownership reaches their copy: **you Sync (push your ownership), then each teammate Syncs
207
+ (pulls it).** So the reliable sequence is:
208
+ 1. `thatopen revit take --workset "<NAME>"` (or the Take workset button)
209
+ 2. `thatopen revit sync` ← you push the ownership
210
+ 3. teammates `thatopen revit sync` ← now Revit blocks them from editing your workset
211
+
212
+ Until teammates have synced, they could still auto-borrow an element in that workset by
213
+ editing it directly. After the round, they'll see it as owned by you and be blocked.
214
+
215
+ **Release when you're done** so teammates can take it:
216
+ - **Ribbon:** click **"Release worksets"** (frees everything you own).
217
+ - **CLI:** `thatopen revit untake --workset "<NAME>"`
218
+ Then `sync` so the release propagates.
219
+
220
+ > Note: simply editing an element makes you its **borrower** automatically (element-level);
221
+ > **taking a workset** makes you the **owner** (workset-level). Revit only blocks editing
222
+ > worksets owned by **someone else** — so the Take→Sync→Sync round above is what creates the
223
+ > protection.
224
+
225
+ ---
226
+
181
227
  ## Troubleshooting
182
228
  - **`thatopen login` fails with "Unauthorized"** → the token is invalid/expired, or it's
183
229
  for a different environment than `--api-url`. Ask the user to generate a fresh token in
@@ -196,6 +242,11 @@ Success: `Synced. vN → vM.` Repeat as often as they like; syncs are queued, n
196
242
  `--convert`.
197
243
  - **`join` says "Identify the central … with one of …"** → provide `--folder-id`, or
198
244
  `--path`, or both `--project` and `--doc`.
245
+ - **`take` returns `✗ held by <user>`** → someone else owns that workset. Ask them to
246
+ Release + sync, or claim a different workset. This is expected, not an error.
247
+ - **A teammate can still edit "my" workset** → ownership hasn't reached them yet. Make sure
248
+ **you synced after taking it, and they synced afterwards** (Step 5). Until both sync
249
+ rounds happen, Revit on their side doesn't know you own it.
199
250
 
200
251
  ## Rules recap (for the AI)
201
252
  - Ask for every value you don't have — never guess a project id, file path, or central name.
package/package.json CHANGED
@@ -1,95 +1,95 @@
1
- {
2
- "name": "@thatopen/services",
3
- "description": "Client library and CLI for building BIM apps and cloud components on the That Open Platform",
4
- "author": "That Open Company",
5
- "license": "MIT",
6
- "homepage": "https://github.com/ThatOpen/engine_services#readme",
7
- "bugs": {
8
- "url": "https://github.com/ThatOpen/engine_services/issues"
9
- },
10
- "repository": {
11
- "type": "git",
12
- "url": "git+https://github.com/ThatOpen/engine_services.git"
13
- },
14
- "publishConfig": {
15
- "access": "public"
16
- },
17
- "private": false,
18
- "version": "0.3.13",
19
- "main": "dist/index.cjs.js",
20
- "module": "dist/index.es.js",
21
- "types": "dist/index.d.ts",
22
- "bin": {
23
- "thatopen": "dist/cli.js"
24
- },
25
- "files": [
26
- "dist",
27
- "src/cli/templates",
28
- "src/built-in",
29
- "docs",
30
- "resources"
31
- ],
32
- "scripts": {
33
- "dev": "vite",
34
- "lint": "eslint src/",
35
- "build": "eslint src/ && tsc && vite build && vite build --config vite.config.cli.mts && node scripts/generate-cli-docs-paths.mjs && node scripts/generate-client-examples-paths.mjs",
36
- "build:lib": "tsc && vite build",
37
- "test": "vitest run",
38
- "test:watch": "vitest",
39
- "build:cli": "vite build --config vite.config.cli.mts",
40
- "preview": "vite preview",
41
- "test:ui": "vite --config test/vite.config.mts",
42
- "template:app": "cd src/cli/templates/app && npm install && cd ../../../.. && node scripts/generate-template-tsconfig.mjs",
43
- "template:app:dev": "cd src/cli/templates/app && npm run dev",
44
- "changeset": "changeset",
45
- "version": "changeset version",
46
- "prepublishOnly": "npm run build"
47
- },
48
- "devDependencies": {
49
- "@changesets/cli": "^2.27.7",
50
- "@thatopen/components": "~3.4.0",
51
- "@thatopen/components-front": "~3.4.0",
52
- "@thatopen/fragments": "~3.4.0",
53
- "@thatopen/ui": "~3.4.0",
54
- "@thatopen/ui-obc": "~3.4.0",
55
- "@types/node": "^20.12.12",
56
- "@types/three": "^0.182.0",
57
- "commander": "^14.0.3",
58
- "esbuild": "^0.27.3",
59
- "eslint": "9.x",
60
- "eslint-config-prettier": "^9.1.0",
61
- "eslint-plugin-prettier": "^5.1.3",
62
- "globals": "^15.3.0",
63
- "jszip": "^3.10.1",
64
- "prettier": "^3.2.5",
65
- "three": ">=0.182.0",
66
- "tsx": "^4.16.2",
67
- "typescript": "^5.2.2",
68
- "typescript-eslint": "^7.10.0",
69
- "vite": "^5.2.0",
70
- "vite-plugin-dts": "^3.9.1",
71
- "vite-plugin-eslint": "^1.8.1",
72
- "vitest": "^4.1.4"
73
- },
74
- "dependencies": {
75
- "dotenv": "^16.4.5",
76
- "socket.io": "^4.8.0",
77
- "socket.io-client": "^4.8.0"
78
- },
79
- "peerDependencies": {
80
- "@thatopen/components": "~3.4.0",
81
- "@thatopen/ui": "~3.4.0",
82
- "three": ">=0.182.0"
83
- },
84
- "peerDependenciesMeta": {
85
- "@thatopen/components": {
86
- "optional": true
87
- },
88
- "@thatopen/ui": {
89
- "optional": true
90
- },
91
- "three": {
92
- "optional": true
93
- }
94
- }
95
- }
1
+ {
2
+ "name": "@thatopen/services",
3
+ "description": "Client library and CLI for building BIM apps and cloud components on the That Open Platform",
4
+ "author": "That Open Company",
5
+ "license": "MIT",
6
+ "homepage": "https://github.com/ThatOpen/engine_services#readme",
7
+ "bugs": {
8
+ "url": "https://github.com/ThatOpen/engine_services/issues"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/ThatOpen/engine_services.git"
13
+ },
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
17
+ "private": false,
18
+ "version": "0.3.15",
19
+ "main": "dist/index.cjs.js",
20
+ "module": "dist/index.es.js",
21
+ "types": "dist/index.d.ts",
22
+ "bin": {
23
+ "thatopen": "dist/cli.js"
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "src/cli/templates",
28
+ "src/built-in",
29
+ "docs",
30
+ "resources"
31
+ ],
32
+ "scripts": {
33
+ "dev": "vite",
34
+ "lint": "eslint src/",
35
+ "build": "eslint src/ && tsc && vite build && vite build --config vite.config.cli.mts && node scripts/generate-cli-docs-paths.mjs && node scripts/generate-client-examples-paths.mjs",
36
+ "build:lib": "tsc && vite build",
37
+ "test": "vitest run",
38
+ "test:watch": "vitest",
39
+ "build:cli": "vite build --config vite.config.cli.mts",
40
+ "preview": "vite preview",
41
+ "test:ui": "vite --config test/vite.config.mts",
42
+ "template:app": "cd src/cli/templates/app && npm install && cd ../../../.. && node scripts/generate-template-tsconfig.mjs",
43
+ "template:app:dev": "cd src/cli/templates/app && npm run dev",
44
+ "changeset": "changeset",
45
+ "version": "changeset version",
46
+ "prepublishOnly": "npm run build"
47
+ },
48
+ "devDependencies": {
49
+ "@changesets/cli": "^2.27.7",
50
+ "@thatopen/components": "~3.4.0",
51
+ "@thatopen/components-front": "~3.4.0",
52
+ "@thatopen/fragments": "~3.4.0",
53
+ "@thatopen/ui": "~3.4.0",
54
+ "@thatopen/ui-obc": "~3.4.0",
55
+ "@types/node": "^20.12.12",
56
+ "@types/three": "^0.182.0",
57
+ "commander": "^14.0.3",
58
+ "esbuild": "^0.27.3",
59
+ "eslint": "9.x",
60
+ "eslint-config-prettier": "^9.1.0",
61
+ "eslint-plugin-prettier": "^5.1.3",
62
+ "globals": "^15.3.0",
63
+ "jszip": "^3.10.1",
64
+ "prettier": "^3.2.5",
65
+ "three": ">=0.182.0",
66
+ "tsx": "^4.16.2",
67
+ "typescript": "^5.2.2",
68
+ "typescript-eslint": "^7.10.0",
69
+ "vite": "^5.2.0",
70
+ "vite-plugin-dts": "^3.9.1",
71
+ "vite-plugin-eslint": "^1.8.1",
72
+ "vitest": "^4.1.4"
73
+ },
74
+ "dependencies": {
75
+ "dotenv": "^16.4.5",
76
+ "socket.io": "^4.8.0",
77
+ "socket.io-client": "^4.8.0"
78
+ },
79
+ "peerDependencies": {
80
+ "@thatopen/components": "~3.4.0",
81
+ "@thatopen/ui": "~3.4.0",
82
+ "three": ">=0.182.0"
83
+ },
84
+ "peerDependenciesMeta": {
85
+ "@thatopen/components": {
86
+ "optional": true
87
+ },
88
+ "@thatopen/ui": {
89
+ "optional": true
90
+ },
91
+ "three": {
92
+ "optional": true
93
+ }
94
+ }
95
+ }