@xcitedbs/client 0.2.9 → 0.2.11

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/llms-full.txt CHANGED
@@ -8,13 +8,13 @@
8
8
 
9
9
  Before reading the full reference, note these critical differences from typical databases:
10
10
 
11
- 1. **The default branch is the empty string `""`, not `"main"`.** When no `X-Branch` header is sent (or `context.branch` is omitted/empty), the server operates on the root timeline. A branch named `"main"` may exist as a user-created branch, but it is not required or special.
11
+ 1. **The default workspace is the empty string `""`, not `"main"`.** When no `X-Workspace` header is sent (or `context.workspace` / `context.branch` is omitted/empty), the server operates on the root timeline. `X-Branch` is a supported alias of `X-Workspace`. A workspace named `"main"` may exist as user-created metadata, but it is not required or special.
12
12
 
13
13
  2. **Identifiers are hierarchical, path-like strings** — e.g. `/us/bills/hr1`, `/manual/v2/chapter3`. They are NOT auto-generated UUIDs. The leading `/` is part of the identifier. Parent/child relationships are derived from the path structure.
14
14
 
15
15
  3. **Documents are XML or JSON, not arbitrary blobs.** XML documents are the primary document type. JSON documents are a parallel store. Both are fully versioned.
16
16
 
17
- 4. **Context (branch + date) travels as HTTP headers** (`X-Branch`, `X-Date`, and optionally `X-Unversioned` for explicit flat writes), not URL path segments.
17
+ 4. **Context (workspace + date) travels as HTTP headers** (`X-Workspace` preferred, `X-Branch` alias, `X-Date`, and optionally `X-Unversioned` for explicit flat writes), not URL path segments.
18
18
 
19
19
  5. **XML documents carry their identifier inside the XML** via a `db:identifier` attribute on the root element.
20
20
 
@@ -28,6 +28,16 @@ Before reading the full reference, note these critical differences from typical
28
28
 
29
29
  10. **Ephemeral test sessions.** `POST /api/v1/test/sessions` (authenticated) returns a UUID **`session_token`**. Clients send **`X-Test-Session: <token>`** on API calls to use an isolated, TTL- and quota-limited LMDB instead of production project data. Unless **`X-Test-Auth: required`** is set, **developer** JWT/API-key checks are bypassed (synthetic admin for wet tests), but **app-user** identity via **`X-App-User-Token`** or Bearer app-user JWT is still recognized. Management routes under **`/api/v1/test/*`** must not include `X-Test-Session`. The test store starts empty (no cloned production project config).
30
30
 
31
+ ## Choosing the Right Versioning Approach
32
+
33
+ - **Write at a specific date:** Set `X-Date` / `context.date` and write — every dated write is a **temporal revision**; no workspace or checkpoint required.
34
+ - **Read as-of a date:** Set `X-Date` and read; the engine returns the revision at or before that instant.
35
+ - **Isolated editing (draft → publish):** Create a **workspace**, edit, then **publish** to the target timeline; optional **checkpoints** for named snapshots.
36
+ - **Audit trail:** Checkpoints carry messages and affected identifiers; **bookmarks** name a checkpoint.
37
+ - **Undo a batch:** **Revert** to a prior checkpoint on that workspace.
38
+
39
+ Legacy REST paths under `/api/v1/branches`, `/commits`, `/tags`, `/diff` remain **deprecated** aliases; prefer **`/api/v1/workspaces`**, **`/checkpoints`**, **`/bookmarks`**, **`/compare`**.
40
+
31
41
  ## Common Pitfalls
32
42
 
33
43
  1. **`baseUrl` must be origin-only (no `/api` or `/api/v1` path).** The SDK prepends `/api/v1/…` to every request. If `baseUrl` is `https://host/api/v1`, requests hit `/api/v1/api/v1/…` which typically returns **405 Not Allowed** from the reverse proxy. Use only the scheme + host + optional port: `https://host` or `http://localhost:8080`.
@@ -65,25 +75,25 @@ Before reading the full reference, note these critical differences from typical
65
75
  ### 1.1 What is XciteDB?
66
76
  XciteDB is an enterprise-grade **Backend-as-a-Service (BaaS)** built on top of a highly optimized **embedded LMDB** database engine. Powered by a high-performance C++17 HTTP/WebSocket API, XciteDB exposes a multi-tenant, secure platform for managing complex, versioned, structured documents.
67
77
 
68
- **Both XML and JSON are first-class citizens.** XciteDB can operate as a pure **XML document store**, a pure **JSON document database**, or any combination of the two — including the common pattern of **XML documents enriched with structured JSON metadata**. In every mode, data is deeply shredded into its structural components (elements, attributes, objects, fields, array items), versioned, branched, indexed by path, and fully queryable through the same Unquery analytics engine.
78
+ **Both XML and JSON are first-class citizens.** XciteDB can operate as a pure **XML document store**, a pure **JSON document database**, or any combination of the two — including the common pattern of **XML documents enriched with structured JSON metadata**. In every mode, data is deeply shredded into its structural components (elements, attributes, objects, fields, array items), versioned, indexed by path, and fully queryable through the same Unquery analytics engine — with **temporal revisions**, **workspaces**, and **checkpoints** when you need collaborative workflow.
69
79
 
70
80
  ### 1.2 The Problem It Solves
71
81
  Standard relational databases and generic NoSQL stores struggle with highly structured, hierarchical, and deeply versioned content. Building collaborative authoring tools, legislative drafting systems, or complex content management platforms usually requires bolting a Git-like versioning layer and document-aware parsers onto an ill-fitting database.
72
82
 
73
- XciteDB bridges this gap. It provides **Git-like versioning for structured XML and JSON data** out of the box, delivered as a modern, API-first cloud platform with multi-tenancy, Attribute-Based Access Control (ABAC), and S3-compatible backups.
83
+ XciteDB bridges this gap. It provides **temporal versioning plus optional workspaces and checkpoints** for structured XML and JSON data out of the box, delivered as a modern, API-first cloud platform with multi-tenancy, Attribute-Based Access Control (ABAC), and S3-compatible backups.
74
84
 
75
85
  ### 1.3 Target Workloads
76
86
  XciteDB shines in domains requiring strict auditability, collaborative authoring, and complex document hierarchies:
77
87
  - **Legal and Legislative Drafting:** Tracking amendments, clauses, and exact historical states of laws.
78
88
  - **Structured Technical Documentation:** Managing manuals, specifications, and compliance documents where every change must be versioned and attributable.
79
- - **Collaborative Content Management:** Systems requiring branching, merging, and cooperative locking to prevent editor conflicts.
89
+ - **Collaborative Content Management:** Systems requiring isolated workspaces, publish workflows, and cooperative locking to prevent editor conflicts.
80
90
  - **Application State and Configuration:** Storing deeply structured JSON configuration, feature flags, or workflow state that benefits from versioning and path-level querying.
81
91
 
82
92
  ### 1.4 Unique Differentiators
83
- - **First-Class XML & JSON:** Both formats are shredded, indexed by path, versioned, branched, and fully queryable through the same engine.
93
+ - **First-Class XML & JSON:** Both formats are shredded, indexed by path, versioned, and fully queryable through the same engine.
84
94
  - **Embedded LMDB Engine:** A memory-mapped, ACID-compliant storage core purpose-built for structured document workloads.
85
95
  - **Bare-Metal Speed:** Reads hit memory-mapped pages with no network round-trip. Microsecond-class read latency on warm data.
86
- - **"Git for Data" Versioning:** Branches, commits, tags, diffs, and time-travel are first-class database primitives.
96
+ - **Document-centric versioning:** Temporal revisions (`X-Date`), workspaces, checkpoints, bookmarks, compare, publish, revert, and apply — plus time-travel reads.
87
97
  - **Unquery DSL:** A purpose-built declarative query language for navigating, filtering, and aggregating data across both XML trees and JSON structures.
88
98
  - **Native Office Ingestion:** Directly convert and ingest DOCX, ODF, RTF, and PDF formats into clean, versioned XML documents.
89
99
  - **Transparent Tenant Routing:** Scale out horizontally using a coordinator/worker topology without breaking the client API contract.
@@ -106,10 +116,10 @@ XciteDB shines in domains requiring strict auditability, collaborative authoring
106
116
  - **JSON Metadata on XML:** JSON metadata can be attached to any XML document or path.
107
117
  - **Hierarchical Identifiers:** Both XML and JSON documents are addressed via logical, path-like strings. The engine natively indexes parent/child relationships.
108
118
 
109
- ### 2.3 Git-Like Document Versioning
110
- - **Branches & Commits:** Isolate collaborative edits into branches. Create atomic commits with descriptive messages.
111
- - **Merge & Cherry-Pick:** Merge branches or cherry-pick specific commits.
112
- - **Time Travel:** Read historical state at any point in time using the `X-Date` header. For **writes**, `X-Unversioned: true` explicitly requests flat (unversioned) storage; it conflicts with `X-Date` (**400**).
119
+ ### 2.3 Document versioning model
120
+ - **Temporal revisions & workspaces:** Every write with `X-Date` records under that revision instant. **Workspaces** isolate draft edits from the root timeline.
121
+ - **Checkpoints, publish, apply, revert:** Optional named snapshots (**checkpoints**); **publish** merges a workspace into a target; **apply** brings another checkpoint’s changes; **revert** rolls the workspace back to a checkpoint.
122
+ - **Time travel:** Read historical state at any point in time using the `X-Date` header. For **writes**, `X-Unversioned: true` explicitly requests flat (unversioned) storage; it conflicts with `X-Date` (**400**).
113
123
  - **Cooperative Locking:** TTL locks prevent conflicting writes (HTTP 409 on conflict).
114
124
 
115
125
  ### 2.4 Unquery: Declarative Query DSL
@@ -142,7 +152,8 @@ Welcome to the **XciteDB HTTP API**. This reference describes REST endpoints und
142
152
  |--------|------|-------------|
143
153
  | `Authorization` | Usually required | `Bearer <JWT>` or `Bearer <api_key>` |
144
154
  | `X-Project-Id` | Platform console / multi-project JWT | Selects the **tenant project** when the token is not already bound to one tenant |
145
- | `X-Branch` | Optional | Active branch name for document and versioning operations |
155
+ | `X-Workspace` | Optional | Active workspace name for document and versioning operations (preferred) |
156
+ | `X-Branch` | Optional | Deprecated alias of `X-Workspace` |
146
157
  | `X-Date` | Optional | Point-in-time / revision context (ISO-like string as used by your deployment) |
147
158
  | `X-Unversioned` | Optional | When `true` or `1`, **writes** use flat LMDB keys (no date revision). Must not be combined with `X-Date` (**400**). Omitting `X-Date` remains valid (implicit unversioned). |
148
159
 
@@ -241,8 +252,8 @@ describe('XciteDB integration', () => {
241
252
  expect(xml).toContain('<title>Hello</title>');
242
253
  });
243
254
 
244
- it('creates a branch, commits, and merges', async () => {
245
- await client.withBranch('feature-test', async (c) => {
255
+ it('creates a workspace, checkpoints, and publishes', async () => {
256
+ await client.withWorkspace('feature-test', async (c) => {
246
257
  await c.writeJsonDocument('test.feature', { active: true });
247
258
  }, { message: 'Add feature flag', autoMerge: true });
248
259
  const doc = await client.readJsonDocument<{ active: boolean }>('test.feature');
@@ -283,8 +294,8 @@ async def test_xml_document(db):
283
294
  assert "<title>Hello</title>" in result
284
295
 
285
296
  @pytest.mark.asyncio
286
- async def test_branch_and_merge(db):
287
- async with db.with_branch("feature-test", message="Add flag", auto_merge=True):
297
+ async def test_workspace_and_publish(db):
298
+ async with db.with_workspace("feature-test", message="Add flag", auto_merge=True):
288
299
  await db.put("test.feature", {"active": True})
289
300
  doc = await db.get("test.feature")
290
301
  assert doc["active"] is True
@@ -680,100 +691,107 @@ Dry-run: **`POST /api/v1/security/check`** with `subject`, `identifier`, `action
680
691
 
681
692
  ---
682
693
 
683
- # Branches
694
+ # Workspaces (branches)
684
695
 
685
- **Base path:** `/api/v1/branches`
696
+ **Preferred base path:** `/api/v1/workspaces`
697
+ **Deprecated alias:** `/api/v1/branches` (same handlers)
686
698
 
687
- **IMPORTANT: The default branch is the empty string `""`.** When no branch is specified, the server uses the root timeline.
699
+ **IMPORTANT: The default workspace is the empty string `""`.** When no workspace is specified, the server uses the root timeline.
688
700
 
689
- ## List branches
701
+ ## List workspaces
690
702
 
691
- **`GET /api/v1/branches`** — Returns `{ branches: [{ name, from_branch, from_date, from_date_key, tip_commit }] }`.
703
+ **`GET /api/v1/workspaces`** — Returns `{ workspaces: [...], branches: [...] }` where each item includes `name`, `from_branch`, `from_date`, `tip_checkpoint` (and `tip_commit` mirror).
692
704
 
693
- ## Create branch
705
+ ## Create workspace
694
706
 
695
- **`POST /api/v1/branches`** — `{ "name": "feature-x", "from_branch": "", "from_date": "" }`
707
+ **`POST /api/v1/workspaces`** — `{ "name": "feature-x", "from_branch": "", "from_date": "" }`
696
708
 
697
- ## Get branch
709
+ ## Get workspace
698
710
 
699
- **`GET /api/v1/branches/{name}`** — Returns `{ branch: {...} }`.
711
+ **`GET /api/v1/workspaces/{name}`** — Returns `{ workspace: {...}, branch: {...} }`.
700
712
 
701
- ## Delete branch
713
+ ## Delete workspace
702
714
 
703
- **`DELETE /api/v1/branches/{name}`**
715
+ **`DELETE /api/v1/workspaces/{name}`**
704
716
 
705
- ## Merge branch
717
+ ## Publish workspace
706
718
 
707
- **`POST /api/v1/branches/{target}/merge`**
719
+ **`POST /api/v1/workspaces/{target}/publish`**
708
720
 
709
721
  ```json
710
722
  {
723
+ "source_workspace": "feature-x",
711
724
  "source_branch": "feature-x",
712
- "message": "Merge feature",
725
+ "message": "Publish feature",
713
726
  "auto_resolve": "none"
714
727
  }
715
728
  ```
716
729
 
717
730
  `auto_resolve`: `"none"` | `"source"` | `"target"`.
718
731
 
719
- Returns `{ status: "completed"|"conflicts", commit?, merged_identifiers?, conflicts? }`.
732
+ Returns `{ status: "completed"|"conflicts", checkpoint?, commit?, merged_identifiers?, conflicts? }` (`commit` mirrors `checkpoint`).
720
733
 
721
- ## Delete revision on branch
734
+ ## Delete revision on workspace
722
735
 
723
- **`DELETE /api/v1/branches/{name}/revisions/{date}`**
736
+ **`DELETE /api/v1/workspaces/{name}/revisions/{date}`** (human-readable date in path; legacy `/branches/...` path still works)
724
737
 
725
738
  ---
726
739
 
727
- # Commits, tags & diff
740
+ # Checkpoints, bookmarks & compare
728
741
 
729
- ## Create commit
742
+ ## Create checkpoint
730
743
 
731
- **`POST /api/v1/commits`** — `{ "message": "...", "author": "..." }`
744
+ **`POST /api/v1/checkpoints`** — `{ "message": "...", "author": "..." }`
745
+ (Deprecated: **`POST /api/v1/commits`**)
732
746
 
733
- Returns `{ commit: { id, branch, date_key, message, author, ... } }`.
747
+ Returns `{ checkpoint: { id, checkpoint_id, branch, date, message, author, ... }, commit: <same> }`. Public JSON uses human-readable **`date`** (no `date_key`).
734
748
 
735
- ## List commits
749
+ ## List checkpoints
736
750
 
737
- **`GET /api/v1/commits?branch=...&limit=...&offset=...`**
751
+ **`GET /api/v1/checkpoints?branch=...&limit=...&offset=...`** (query param name unchanged; means workspace)
752
+ Returns `{ checkpoints: [...], commits: [...], total, branch }` (mirrors).
738
753
 
739
- Returns `{ commits: [...], total, branch }`.
754
+ ## Get checkpoint
740
755
 
741
- ## Get commit
756
+ **`GET /api/v1/checkpoints/{id}`** — Returns `{ checkpoint, commit }`.
742
757
 
743
- **`GET /api/v1/commits/{id}`** Returns `{ commit: {...} }`.
758
+ ## Revert to checkpoint
744
759
 
745
- ## Rollback to commit
760
+ **`POST /api/v1/checkpoints/{id}/revert`** `{ "confirm": true }`
761
+ (Deprecated: **`.../rollback`**)
746
762
 
747
- **`POST /api/v1/commits/{id}/rollback`** — `{ "confirm": true }`
763
+ ## Apply checkpoint
748
764
 
749
- ## Cherry-pick commit
765
+ **`POST /api/v1/checkpoints/{id}/apply`** — `{ "message": "...", "author": "..." }`
766
+ (Deprecated: **`.../cherry-pick`**)
750
767
 
751
- **`POST /api/v1/commits/{id}/cherry-pick`** — `{ "message": "...", "author": "..." }`
768
+ ## Create bookmark
752
769
 
753
- ## Create tag
770
+ **`POST /api/v1/bookmarks`** — `{ "name": "v1.0", "checkpoint_id": "...", "commit_id": "...", "message": "..." }`
771
+ (Deprecated: **`POST /api/v1/tags`**)
754
772
 
755
- **`POST /api/v1/tags`** — `{ "name": "v1.0", "commit_id": "...", "message": "..." }`
773
+ ## List bookmarks
756
774
 
757
- ## List tags
775
+ **`GET /api/v1/bookmarks?limit=...&offset=...`** — Returns `{ bookmarks: [...], tags: [...], total }` (mirrors where applicable).
758
776
 
759
- **`GET /api/v1/tags?limit=...&offset=...`** Returns `{ tags: [...], total }`.
777
+ ## Get / Delete bookmark
760
778
 
761
- ## Get / Delete tag
779
+ **`GET /api/v1/bookmarks/{name}`** / **`DELETE /api/v1/bookmarks/{name}`** (deprecated `/tags/...`)
762
780
 
763
- **`GET /api/v1/tags/{name}`** / **`DELETE /api/v1/tags/{name}`**
781
+ ## Compare
764
782
 
765
- ## Diff
766
-
767
- **`POST /api/v1/diff`**
783
+ **`POST /api/v1/compare`**
768
784
 
769
785
  ```json
770
786
  {
771
- "from": { "branch": "", "date_key": "..." },
787
+ "from": { "branch": "", "date": "2024-01-15T00:00:00" },
772
788
  "to": { "branch": "feature-x" },
773
789
  "include_content": true
774
790
  }
775
791
  ```
776
792
 
793
+ (Deprecated: **`POST /api/v1/diff`**; `date_key` still accepted internally but prefer **`date`**.)
794
+
777
795
  Returns `{ changes: [{ identifier, action: "added"|"modified"|"deleted", from_content?, to_content? }], total_changes }`.
778
796
 
779
797
  ---
@@ -1243,7 +1261,7 @@ import { XCiteDBClient } from '@xcitedbs/client';
1243
1261
  const client = new XCiteDBClient({
1244
1262
  baseUrl: 'http://localhost:8080',
1245
1263
  apiKey: 'your-api-key',
1246
- context: { branch: '', date: '' },
1264
+ context: { workspace: '', date: '' },
1247
1265
  });
1248
1266
 
1249
1267
  // Health check
@@ -1263,12 +1281,12 @@ await client.writeJsonDocument('app.settings', { theme: 'dark' });
1263
1281
  // Read JSON document
1264
1282
  const settings = await client.readJsonDocument('app.settings');
1265
1283
 
1266
- // Branch, edit, commit, merge
1267
- await client.createBranch('feature-x');
1268
- client.setContext({ branch: 'feature-x' });
1284
+ // Workspace, edit, checkpoint, publish
1285
+ await client.createWorkspace('feature-x');
1286
+ client.setContext({ workspace: 'feature-x' });
1269
1287
  await client.writeJsonDocument('app.settings', { theme: 'light' });
1270
- await client.createCommit('Switch to light theme');
1271
- await client.mergeBranch('', 'feature-x');
1288
+ await client.createCheckpoint('Switch to light theme');
1289
+ await client.publishWorkspace('', 'feature-x');
1272
1290
  ```
1273
1291
 
1274
1292
  ## Constructor Options
@@ -1289,7 +1307,8 @@ interface XCiteDBClientOptions {
1289
1307
  }
1290
1308
 
1291
1309
  interface DatabaseContext {
1292
- branch?: string; // '' = default (root timeline)
1310
+ workspace?: string; // '' = default (root timeline); preferred
1311
+ branch?: string; // @deprecated alias of workspace
1293
1312
  date?: string; // Point-in-time
1294
1313
  prefix?: string; // Identifier prefix filter
1295
1314
  unversioned?: boolean; // Sends X-Unversioned: true (flat writes; do not combine with date)
@@ -1357,30 +1376,34 @@ interface DatabaseContext {
1357
1376
  - `queryMetaByQuery<T>(query, path?)` → `T`
1358
1377
  - `clearMeta(query)` → `boolean`
1359
1378
 
1360
- ### Branches
1361
- - `withBranch(name, fn, options?)` → `{ result, commit?, merge? }` — branch, callback, commit, merge back
1362
- - `createBranch(name, fromBranch?, fromDate?)` → `void`
1363
- - `listBranches()` → `BranchInfo[]`
1364
- - `getBranch(name)` → `BranchInfo`
1365
- - `deleteBranch(name)` → `void`
1366
- - `deleteRevision(branch, date)` → `void`
1367
- - `mergeBranch(targetBranch, sourceBranch, options?)` → `MergeResult`
1368
-
1369
- ### Commits
1370
- - `createCommit(message, author?)` → `CommitRecord`
1371
- - `listCommits(options?)` → `{ commits, total, branch }`
1372
- - `getCommit(commitId)` → `CommitRecord`
1373
- - `rollbackToCommit(commitId)` → `{ rolled_back_commits, current_tip }`
1374
- - `cherryPick(commitId, message?, author?)` → `CommitRecord`
1375
-
1376
- ### Tags
1377
- - `createTag(name, commitId, message?, author?)` → `TagRecord`
1378
- - `listTags(options?)` → `{ tags, total }`
1379
- - `getTag(name)` → `TagRecord`
1380
- - `deleteTag(name)` → `void`
1381
-
1382
- ### Diff
1383
- - `diff(from: DiffRef, to: DiffRef, includeContent?)` `DiffResult`
1379
+ ### Workspaces & checkpoints
1380
+ - `withWorkspace(name, fn, options?)` → `{ result, checkpoint?, publish? }` — workspace, callback, checkpoint, publish back
1381
+ - `createWorkspace(name, fromBranch?, fromDate?)` → `void`
1382
+ - `listWorkspaces()` → `WorkspaceInfo[]`
1383
+ - `getWorkspace(name)` → `WorkspaceInfo`
1384
+ - `deleteWorkspace(name)` → `void`
1385
+ - `deleteRevision(branch, date)` → `void` (workspace name + human date)
1386
+ - `publishWorkspace(targetWorkspace, sourceWorkspace, options?)` → `PublishResult`
1387
+ - **Deprecated:** `withBranch`, `createBranch`, `listBranches`, `getBranch`, `deleteBranch`, `mergeBranch` (same HTTP behavior)
1388
+
1389
+ ### Checkpoints
1390
+ - `createCheckpoint(message, author?)` → `CheckpointRecord`
1391
+ - `listCheckpoints(options?)` → `{ checkpoints, total, branch }` (wire JSON may also include `commits` mirror)
1392
+ - `getCheckpoint(checkpointId)` → `CheckpointRecord`
1393
+ - `revertToCheckpoint(checkpointId)` → `{ rolled_back_checkpoints, rolled_back_commits?, current_tip }`
1394
+ - `applyCheckpoint(checkpointId, message?, author?)` → `CheckpointRecord`
1395
+ - **Deprecated:** `createCommit`, `listCommits`, `getCommit`, `rollbackToCommit`, `cherryPick`
1396
+
1397
+ ### Bookmarks
1398
+ - `createBookmark(name, checkpointId, message?, author?)` → `BookmarkRecord`
1399
+ - `listBookmarks(options?)` → `{ bookmarks, tags, total, limit?, offset? }`
1400
+ - `getBookmark(name)` → `BookmarkRecord`
1401
+ - `deleteBookmark(name)` → `void`
1402
+ - **Deprecated:** `createTag`, `listTags`, `getTag`, `deleteTag`
1403
+
1404
+ ### Compare
1405
+ - `compare(from: CompareRef, to: CompareRef, includeContent?)` → `CompareResult`
1406
+ - **Deprecated:** `diff(from: DiffRef, …)` — alias of `compare`
1384
1407
 
1385
1408
  ### Locks
1386
1409
  - `acquireLock(identifier, expires?)` → `LockInfo`
@@ -1513,7 +1536,7 @@ async def main():
1513
1536
  async with XCiteDBClient(
1514
1537
  "http://localhost:8080",
1515
1538
  api_key="your-key",
1516
- context=DatabaseContext(branch="", date=""),
1539
+ context=DatabaseContext(workspace="", date=""),
1517
1540
  ) as client:
1518
1541
  print(await client.health())
1519
1542
  print(await client.query_documents(XCiteQuery(match_start="/manual/")))
@@ -1523,13 +1546,13 @@ async def main():
1523
1546
  print(await client.search(TextSearchQuery(query="guide", limit=10)))
1524
1547
  await client.platform_login("admin@localhost", "password")
1525
1548
  # await client.login_app_user("user@example.com", "pw") # set context.project_id / tenant_id if needed
1526
- async with client.with_branch("feature-x", message="WIP", auto_merge=True):
1549
+ async with client.with_workspace("feature-x", message="WIP", auto_merge=True):
1527
1550
  await client.put("app.settings", {"theme": "light"})
1528
1551
 
1529
1552
  asyncio.run(main())
1530
1553
  ```
1531
1554
 
1532
- Async client: `write_xml_document` / `write_document_json` (deprecated), `write_json_document`, `read_json_document`, `list_json_documents`, `list_identifiers`, `search`, `reindex`, `platform_login` / `login` (deprecated), `login_app_user`, `refresh_app_user`, `logout_app_user`, `register_app_user`, `put` / `get` / `remove` / `list_documents` (JSON aliases), `with_branch` (async context manager).
1555
+ Async client: `write_xml_document` / `write_document_json` (deprecated), `write_json_document`, `read_json_document`, `list_json_documents`, `list_identifiers`, `search`, `reindex`, `platform_login` / `login` (deprecated), `login_app_user`, `refresh_app_user`, `logout_app_user`, `register_app_user`, `put` / `get` / `remove` / `list_documents` (JSON aliases), `with_workspace` (async context manager; `with_branch` deprecated alias).
1533
1556
 
1534
1557
  ---
1535
1558
 
@@ -1541,7 +1564,7 @@ Async client: `write_xml_document` / `write_document_json` (deprecated), `write_
1541
1564
  xcitedb::XCiteDBClientOptions opt;
1542
1565
  opt.base_url = "http://127.0.0.1:8080";
1543
1566
  opt.api_key = "your-key";
1544
- opt.context.branch = ""; // root timeline
1567
+ opt.context.workspace = ""; // root timeline (`branch` is deprecated alias)
1545
1568
 
1546
1569
  xcitedb::XCiteDBClient client(opt);
1547
1570
  auto health = client.health();
@@ -1553,4 +1576,4 @@ auto ids = client.query_documents(q);
1553
1576
 
1554
1577
  Synchronous (blocking) HTTP client. Methods mirror the JavaScript SDK with C++ naming (`write_xml_document`, deprecated `write_document_json`). Errors throw `xcitedb::XCiteDBError` with `.status()` and `.body()`.
1555
1578
 
1556
- Includes optional `xcitevcs` CLI for command-line operations (branches, commits, documents, search, import/export).
1579
+ Includes optional `xcitevcs` CLI for command-line operations (legacy branch/commit vocabulary on the wire, documents, search, import/export).