@xcitedbs/client 0.2.10 → 0.2.12
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 +22 -0
- package/dist/client.d.ts +85 -7
- package/dist/client.js +199 -52
- package/dist/index.d.ts +1 -1
- package/dist/types.d.ts +101 -28
- package/llms-full.txt +140 -103
- package/llms.txt +68 -47
- package/package.json +1 -1
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
|
|
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 (
|
|
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
|
|
|
@@ -26,7 +26,19 @@ Before reading the full reference, note these critical differences from typical
|
|
|
26
26
|
|
|
27
27
|
9. **OpenAPI:** See repository `docs/openapi.yaml` for a machine-readable route map.
|
|
28
28
|
|
|
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`.
|
|
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`. With a default body (omit or `{}`), the test LMDB starts **empty** (no cloned production project config).
|
|
30
|
+
|
|
31
|
+
11. **Overlay test sessions.** Same **`POST`**, with JSON **`{"overlay":true}`**, while authenticated for the **project to debug** (project-scoped API key, or platform Bearer + **`X-Project-Id`**). The session metadata records overlay mode; subsequent requests need only **`X-Test-Session`**. The server opens **`XCiteDB(_test/<uuid>/data, <production data path>)`**: production is used as a **read-only base**; reads merge overlay + base; **writes never modify production**. If the production data directory is missing, opening the session database fails. JS **`createTestSession({ …, overlay: true })`**, C++ **`test_session_overlay`** + **`create_test_session`**, MCP **`create_test_session`** tool **`overlay: true`**.
|
|
32
|
+
|
|
33
|
+
## Choosing the Right Versioning Approach
|
|
34
|
+
|
|
35
|
+
- **Write at a specific date:** Set `X-Date` / `context.date` and write — every dated write is a **temporal revision**; no workspace or checkpoint required.
|
|
36
|
+
- **Read as-of a date:** Set `X-Date` and read; the engine returns the revision at or before that instant.
|
|
37
|
+
- **Isolated editing (draft → publish):** Create a **workspace**, edit, then **publish** to the target timeline; optional **checkpoints** for named snapshots.
|
|
38
|
+
- **Audit trail:** Checkpoints carry messages and affected identifiers; **bookmarks** name a checkpoint.
|
|
39
|
+
- **Undo a batch:** **Revert** to a prior checkpoint on that workspace.
|
|
40
|
+
|
|
41
|
+
Legacy REST paths under `/api/v1/branches`, `/commits`, `/tags`, `/diff` remain **deprecated** aliases; prefer **`/api/v1/workspaces`**, **`/checkpoints`**, **`/bookmarks`**, **`/compare`**.
|
|
30
42
|
|
|
31
43
|
## Common Pitfalls
|
|
32
44
|
|
|
@@ -48,7 +60,7 @@ Before reading the full reference, note these critical differences from typical
|
|
|
48
60
|
|
|
49
61
|
6. **Self-registration uses server-configured default groups.** `registerAppUser()` assigns groups from the server's `auth.app_users.default_groups` config, not from the client request. To assign specific groups, use the admin endpoint `createAppUser()` instead, or update groups after registration via `updateAppUserGroups()`.
|
|
50
62
|
|
|
51
|
-
7. **Do not mock XciteDB in tests — use ephemeral test sessions instead.** Unlike most BaaS platforms, XciteDB has built-in support for isolated, throwaway database sessions specifically designed for wet integration tests. Mocking the client skips the actual storage, versioning, querying, and ABAC behavior, producing tests that don't catch real integration issues. Use `createTestSession()` / `test_session()` / `create_test_session()` (SDK helpers) or `POST /api/v1/test/sessions` directly to get a real
|
|
63
|
+
7. **Do not mock XciteDB in tests — use ephemeral test sessions instead.** Unlike most BaaS platforms, XciteDB has built-in support for isolated, throwaway database sessions specifically designed for wet integration tests. Mocking the client skips the actual storage, versioning, querying, and ABAC behavior, producing tests that don't catch real integration issues. Use `createTestSession()` / `test_session()` / `create_test_session()` (SDK helpers) or `POST /api/v1/test/sessions` directly to get a real LMDB under `_test/<uuid>/` (empty by default, or **overlay** on read-only production with **`{"overlay":true}`** / **`overlay: true`** / **`test_session_overlay`**). See "Ephemeral test sessions" below.
|
|
52
64
|
|
|
53
65
|
---
|
|
54
66
|
|
|
@@ -65,25 +77,25 @@ Before reading the full reference, note these critical differences from typical
|
|
|
65
77
|
### 1.1 What is XciteDB?
|
|
66
78
|
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
79
|
|
|
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,
|
|
80
|
+
**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
81
|
|
|
70
82
|
### 1.2 The Problem It Solves
|
|
71
83
|
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
84
|
|
|
73
|
-
XciteDB bridges this gap. It provides **
|
|
85
|
+
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
86
|
|
|
75
87
|
### 1.3 Target Workloads
|
|
76
88
|
XciteDB shines in domains requiring strict auditability, collaborative authoring, and complex document hierarchies:
|
|
77
89
|
- **Legal and Legislative Drafting:** Tracking amendments, clauses, and exact historical states of laws.
|
|
78
90
|
- **Structured Technical Documentation:** Managing manuals, specifications, and compliance documents where every change must be versioned and attributable.
|
|
79
|
-
- **Collaborative Content Management:** Systems requiring
|
|
91
|
+
- **Collaborative Content Management:** Systems requiring isolated workspaces, publish workflows, and cooperative locking to prevent editor conflicts.
|
|
80
92
|
- **Application State and Configuration:** Storing deeply structured JSON configuration, feature flags, or workflow state that benefits from versioning and path-level querying.
|
|
81
93
|
|
|
82
94
|
### 1.4 Unique Differentiators
|
|
83
|
-
- **First-Class XML & JSON:** Both formats are shredded, indexed by path, versioned,
|
|
95
|
+
- **First-Class XML & JSON:** Both formats are shredded, indexed by path, versioned, and fully queryable through the same engine.
|
|
84
96
|
- **Embedded LMDB Engine:** A memory-mapped, ACID-compliant storage core purpose-built for structured document workloads.
|
|
85
97
|
- **Bare-Metal Speed:** Reads hit memory-mapped pages with no network round-trip. Microsecond-class read latency on warm data.
|
|
86
|
-
- **
|
|
98
|
+
- **Document-centric versioning:** Temporal revisions (`X-Date`), workspaces, checkpoints, bookmarks, compare, publish, revert, and apply — plus time-travel reads.
|
|
87
99
|
- **Unquery DSL:** A purpose-built declarative query language for navigating, filtering, and aggregating data across both XML trees and JSON structures.
|
|
88
100
|
- **Native Office Ingestion:** Directly convert and ingest DOCX, ODF, RTF, and PDF formats into clean, versioned XML documents.
|
|
89
101
|
- **Transparent Tenant Routing:** Scale out horizontally using a coordinator/worker topology without breaking the client API contract.
|
|
@@ -106,10 +118,10 @@ XciteDB shines in domains requiring strict auditability, collaborative authoring
|
|
|
106
118
|
- **JSON Metadata on XML:** JSON metadata can be attached to any XML document or path.
|
|
107
119
|
- **Hierarchical Identifiers:** Both XML and JSON documents are addressed via logical, path-like strings. The engine natively indexes parent/child relationships.
|
|
108
120
|
|
|
109
|
-
### 2.3
|
|
110
|
-
- **
|
|
111
|
-
- **
|
|
112
|
-
- **Time
|
|
121
|
+
### 2.3 Document versioning model
|
|
122
|
+
- **Temporal revisions & workspaces:** Every write with `X-Date` records under that revision instant. **Workspaces** isolate draft edits from the root timeline.
|
|
123
|
+
- **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.
|
|
124
|
+
- **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
125
|
- **Cooperative Locking:** TTL locks prevent conflicting writes (HTTP 409 on conflict).
|
|
114
126
|
|
|
115
127
|
### 2.4 Unquery: Declarative Query DSL
|
|
@@ -142,7 +154,8 @@ Welcome to the **XciteDB HTTP API**. This reference describes REST endpoints und
|
|
|
142
154
|
|--------|------|-------------|
|
|
143
155
|
| `Authorization` | Usually required | `Bearer <JWT>` or `Bearer <api_key>` |
|
|
144
156
|
| `X-Project-Id` | Platform console / multi-project JWT | Selects the **tenant project** when the token is not already bound to one tenant |
|
|
145
|
-
| `X-
|
|
157
|
+
| `X-Workspace` | Optional | Active workspace name for document and versioning operations (preferred) |
|
|
158
|
+
| `X-Branch` | Optional | Deprecated alias of `X-Workspace` |
|
|
146
159
|
| `X-Date` | Optional | Point-in-time / revision context (ISO-like string as used by your deployment) |
|
|
147
160
|
| `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
161
|
|
|
@@ -194,7 +207,7 @@ For **integration and wet tests** against a shared BaaS host without touching pr
|
|
|
194
207
|
|
|
195
208
|
| Step | What to do |
|
|
196
209
|
|------|------------|
|
|
197
|
-
| **Create** | **`POST /api/v1/test/sessions`** with normal **`Authorization: Bearer …`** or **`X-API-Key`**. Response includes a **`session_token`** (UUID). Server enforces per-credential limits (`test.max_sessions_per_key`, `test.session_ttl_seconds`, `test.max_test_db_size_bytes` in server config). |
|
|
210
|
+
| **Create** | **`POST /api/v1/test/sessions`** with normal **`Authorization: Bearer …`** or **`X-API-Key`**. Response includes a **`session_token`** (UUID). Server enforces per-credential limits (`test.max_sessions_per_key`, `test.session_ttl_seconds`, `test.max_test_db_size_bytes` in server config). Optional JSON body **`{"overlay":true}`** provisions a **read-through production** session (writable delta only under `_test/<uuid>/`; production LMDB is read-only base). |
|
|
198
211
|
| **Use** | Send **`X-Test-Session: <session_token>`** on document and other data API requests. The server routes to a dedicated LMDB under its data root (`_test/<id>/`), not the caller’s production tenant. **`tenant_id` / `X-Project-Id` semantics do not select production** while the test header is present—the synthetic test tenant is implied. |
|
|
199
212
|
| **Auth** | **Default:** developer auth (API key / platform JWT) is **bypassed** with a synthetic admin identity. However, **app-user identity is still recognized**: if `X-App-User-Token` or a Bearer app-user JWT is present, the request runs as that app user (for routes like `/app/auth/me`). **`X-Test-Auth: required`:** all auth is validated normally; ABAC applies, but data still comes from the test session DB. |
|
|
200
213
|
| **Manage** | **`GET /api/v1/test/sessions`** — list sessions for the current credential. **`DELETE /api/v1/test/sessions/current`** — destroy the session named by **`X-Test-Session`** (no other auth). **`DELETE /api/v1/test/sessions/all`** — destroy all sessions for the credential. **`DELETE /api/v1/test/sessions/{token}`** — destroy one session if owned by the credential. Do **not** send **`X-Test-Session`** on these `/api/v1/test/*` routes. |
|
|
@@ -202,9 +215,9 @@ For **integration and wet tests** against a shared BaaS host without touching pr
|
|
|
202
215
|
|
|
203
216
|
**SDK usage (summary):**
|
|
204
217
|
|
|
205
|
-
- **JavaScript/TypeScript:** `XCiteDBClient.createTestSession({ baseUrl, apiKey, … })` returns a client configured with `testSessionToken`; optional `testRequireAuth: true` maps to `X-Test-Auth: required`. `destroyTestSession()` calls `DELETE …/test/sessions/current`.
|
|
206
|
-
- **Python:** `async with XCiteDBClient.test_session(base_url, api_key=…, …)` provisions and tears down; or pass `test_session_token` / `test_require_auth` to the constructor.
|
|
207
|
-
- **C++:** `XCiteDBClient::create_test_session(options)` after setting `api_key
|
|
218
|
+
- **JavaScript/TypeScript:** `XCiteDBClient.createTestSession({ baseUrl, apiKey, … })` returns a client configured with `testSessionToken`; optional **`overlay: true`** for overlay mode; optional `testRequireAuth: true` maps to `X-Test-Auth: required`. `destroyTestSession()` calls `DELETE …/test/sessions/current`.
|
|
219
|
+
- **Python:** `async with XCiteDBClient.test_session(base_url, api_key=…, …)` provisions and tears down; or pass `test_session_token` / `test_require_auth` to the constructor. For overlay until the helper accepts a flag, call **`POST /api/v1/test/sessions`** with JSON **`{"overlay":true}`** then construct the client with the returned token.
|
|
220
|
+
- **C++:** `XCiteDBClient::create_test_session(options)` after setting `api_key`, optional **`test_session_overlay = true`**, and optional `test_require_auth`; `destroy_test_session()`.
|
|
208
221
|
|
|
209
222
|
**JavaScript/TypeScript — complete test scaffold (Vitest / Jest):**
|
|
210
223
|
|
|
@@ -241,8 +254,8 @@ describe('XciteDB integration', () => {
|
|
|
241
254
|
expect(xml).toContain('<title>Hello</title>');
|
|
242
255
|
});
|
|
243
256
|
|
|
244
|
-
it('creates a
|
|
245
|
-
await client.
|
|
257
|
+
it('creates a workspace, checkpoints, and publishes', async () => {
|
|
258
|
+
await client.withWorkspace('feature-test', async (c) => {
|
|
246
259
|
await c.writeJsonDocument('test.feature', { active: true });
|
|
247
260
|
}, { message: 'Add feature flag', autoMerge: true });
|
|
248
261
|
const doc = await client.readJsonDocument<{ active: boolean }>('test.feature');
|
|
@@ -283,8 +296,8 @@ async def test_xml_document(db):
|
|
|
283
296
|
assert "<title>Hello</title>" in result
|
|
284
297
|
|
|
285
298
|
@pytest.mark.asyncio
|
|
286
|
-
async def
|
|
287
|
-
async with db.
|
|
299
|
+
async def test_workspace_and_publish(db):
|
|
300
|
+
async with db.with_workspace("feature-test", message="Add flag", auto_merge=True):
|
|
288
301
|
await db.put("test.feature", {"active": True})
|
|
289
302
|
doc = await db.get("test.feature")
|
|
290
303
|
assert doc["active"] is True
|
|
@@ -518,7 +531,7 @@ Can also use `"query"` instead of `"identifier"` to target multiple documents by
|
|
|
518
531
|
|
|
519
532
|
# Search
|
|
520
533
|
|
|
521
|
-
Full-text search uses embedded XciteFTS (
|
|
534
|
+
Full-text search uses **embedded XciteFTS** (LMDB index per project). **Semantic** and **hybrid** (FTS + vector) search are available when vector search is enabled in project settings. The JSON field **`mode`** selects behavior (`auto` picks the best option for the project, or set `fts`, `semantic`, or `hybrid` explicitly).
|
|
522
535
|
|
|
523
536
|
**Base path:** `/api/v1/search`
|
|
524
537
|
|
|
@@ -532,15 +545,26 @@ Full-text search uses embedded XciteFTS (enable per project in server settings).
|
|
|
532
545
|
"doc_types": ["xml", "json"],
|
|
533
546
|
"branch": "",
|
|
534
547
|
"limit": 20,
|
|
535
|
-
"offset": 0
|
|
548
|
+
"offset": 0,
|
|
549
|
+
"mode": "fts"
|
|
536
550
|
}
|
|
537
551
|
```
|
|
538
552
|
|
|
539
|
-
|
|
553
|
+
Optional fields (also on SDK `TextSearchQuery` and the MCP `search` tool): **`min_score`**, **`semantic_weight`** for semantic/hybrid.
|
|
554
|
+
|
|
555
|
+
**Temporal FTS** (posting intervals; applies to the FTS keyword index—use **`mode`: `"fts"`** for pure temporal keyword search, or hybrid where the FTS leg participates):
|
|
556
|
+
|
|
557
|
+
| Field | Meaning |
|
|
558
|
+
|-------|---------|
|
|
559
|
+
| **`at_date`** | Date string (e.g. ISO `YYYY-MM-DD` or `mm/dd/yyyy` as accepted by the server). A posting matches if it is valid at that instant: `start <= at_date < end` (internal 7-char keys after `date2key`). |
|
|
560
|
+
| **`date_from`**, **`date_to`** | Date strings defining a half-open range `[date_from, date_to)`. A posting matches if its `[start, end)` **overlaps** that range. Either bound may be omitted (open-ended). |
|
|
561
|
+
| *(none of the three)* | **Current-time** view: only postings whose interval is still “open” (end at the internal max sentinel) are included. |
|
|
562
|
+
|
|
563
|
+
**Response:** `{ hits: [...], total, query }`. Each hit has **`identifier`**, **`path`**, **`doc_type`**, **`branch`**, **`snippet`**, **`score`**, and optionally **`xcitepath`** (XML). Semantic/hybrid hits may include **`source`**: `fts` \| `semantic` \| `both`. When the server infers a temporal window for the matched term(s), hits may include **`valid_from`** and **`valid_to`** as **7-character internal date keys** (same alphabet as revision keys—not ISO). Omitted for full-range/unversioned postings or when not computed.
|
|
540
564
|
|
|
541
565
|
## Reindex
|
|
542
566
|
|
|
543
|
-
**`POST /api/v1/search/reindex`** — Rebuilds the search index.
|
|
567
|
+
**`POST /api/v1/search/reindex`** — Rebuilds the full-text search index.
|
|
544
568
|
|
|
545
569
|
---
|
|
546
570
|
|
|
@@ -680,100 +704,107 @@ Dry-run: **`POST /api/v1/security/check`** with `subject`, `identifier`, `action
|
|
|
680
704
|
|
|
681
705
|
---
|
|
682
706
|
|
|
683
|
-
#
|
|
707
|
+
# Workspaces (branches)
|
|
684
708
|
|
|
685
|
-
**
|
|
709
|
+
**Preferred base path:** `/api/v1/workspaces`
|
|
710
|
+
**Deprecated alias:** `/api/v1/branches` (same handlers)
|
|
686
711
|
|
|
687
|
-
**IMPORTANT: The default
|
|
712
|
+
**IMPORTANT: The default workspace is the empty string `""`.** When no workspace is specified, the server uses the root timeline.
|
|
688
713
|
|
|
689
|
-
## List
|
|
714
|
+
## List workspaces
|
|
690
715
|
|
|
691
|
-
**`GET /api/v1/
|
|
716
|
+
**`GET /api/v1/workspaces`** — Returns `{ workspaces: [...], branches: [...] }` where each item includes `name`, `from_branch`, `from_date`, `tip_checkpoint` (and `tip_commit` mirror).
|
|
692
717
|
|
|
693
|
-
## Create
|
|
718
|
+
## Create workspace
|
|
694
719
|
|
|
695
|
-
**`POST /api/v1/
|
|
720
|
+
**`POST /api/v1/workspaces`** — `{ "name": "feature-x", "from_branch": "", "from_date": "" }`
|
|
696
721
|
|
|
697
|
-
## Get
|
|
722
|
+
## Get workspace
|
|
698
723
|
|
|
699
|
-
**`GET /api/v1/
|
|
724
|
+
**`GET /api/v1/workspaces/{name}`** — Returns `{ workspace: {...}, branch: {...} }`.
|
|
700
725
|
|
|
701
|
-
## Delete
|
|
726
|
+
## Delete workspace
|
|
702
727
|
|
|
703
|
-
**`DELETE /api/v1/
|
|
728
|
+
**`DELETE /api/v1/workspaces/{name}`**
|
|
704
729
|
|
|
705
|
-
##
|
|
730
|
+
## Publish workspace
|
|
706
731
|
|
|
707
|
-
**`POST /api/v1/
|
|
732
|
+
**`POST /api/v1/workspaces/{target}/publish`**
|
|
708
733
|
|
|
709
734
|
```json
|
|
710
735
|
{
|
|
736
|
+
"source_workspace": "feature-x",
|
|
711
737
|
"source_branch": "feature-x",
|
|
712
|
-
"message": "
|
|
738
|
+
"message": "Publish feature",
|
|
713
739
|
"auto_resolve": "none"
|
|
714
740
|
}
|
|
715
741
|
```
|
|
716
742
|
|
|
717
743
|
`auto_resolve`: `"none"` | `"source"` | `"target"`.
|
|
718
744
|
|
|
719
|
-
Returns `{ status: "completed"|"conflicts", commit?, merged_identifiers?, conflicts? }
|
|
745
|
+
Returns `{ status: "completed"|"conflicts", checkpoint?, commit?, merged_identifiers?, conflicts? }` (`commit` mirrors `checkpoint`).
|
|
720
746
|
|
|
721
|
-
## Delete revision on
|
|
747
|
+
## Delete revision on workspace
|
|
722
748
|
|
|
723
|
-
**`DELETE /api/v1/
|
|
749
|
+
**`DELETE /api/v1/workspaces/{name}/revisions/{date}`** (human-readable date in path; legacy `/branches/...` path still works)
|
|
724
750
|
|
|
725
751
|
---
|
|
726
752
|
|
|
727
|
-
#
|
|
753
|
+
# Checkpoints, bookmarks & compare
|
|
728
754
|
|
|
729
|
-
## Create
|
|
755
|
+
## Create checkpoint
|
|
730
756
|
|
|
731
|
-
**`POST /api/v1/
|
|
757
|
+
**`POST /api/v1/checkpoints`** — `{ "message": "...", "author": "..." }`
|
|
758
|
+
(Deprecated: **`POST /api/v1/commits`**)
|
|
732
759
|
|
|
733
|
-
Returns `{
|
|
760
|
+
Returns `{ checkpoint: { id, checkpoint_id, branch, date, message, author, ... }, commit: <same> }`. Public JSON uses human-readable **`date`** (no `date_key`).
|
|
734
761
|
|
|
735
|
-
## List
|
|
762
|
+
## List checkpoints
|
|
736
763
|
|
|
737
|
-
**`GET /api/v1/
|
|
764
|
+
**`GET /api/v1/checkpoints?branch=...&limit=...&offset=...`** (query param name unchanged; means workspace)
|
|
765
|
+
Returns `{ checkpoints: [...], commits: [...], total, branch }` (mirrors).
|
|
738
766
|
|
|
739
|
-
|
|
767
|
+
## Get checkpoint
|
|
740
768
|
|
|
741
|
-
|
|
769
|
+
**`GET /api/v1/checkpoints/{id}`** — Returns `{ checkpoint, commit }`.
|
|
742
770
|
|
|
743
|
-
|
|
771
|
+
## Revert to checkpoint
|
|
744
772
|
|
|
745
|
-
|
|
773
|
+
**`POST /api/v1/checkpoints/{id}/revert`** — `{ "confirm": true }`
|
|
774
|
+
(Deprecated: **`.../rollback`**)
|
|
746
775
|
|
|
747
|
-
|
|
776
|
+
## Apply checkpoint
|
|
748
777
|
|
|
749
|
-
|
|
778
|
+
**`POST /api/v1/checkpoints/{id}/apply`** — `{ "message": "...", "author": "..." }`
|
|
779
|
+
(Deprecated: **`.../cherry-pick`**)
|
|
750
780
|
|
|
751
|
-
|
|
781
|
+
## Create bookmark
|
|
752
782
|
|
|
753
|
-
|
|
783
|
+
**`POST /api/v1/bookmarks`** — `{ "name": "v1.0", "checkpoint_id": "...", "commit_id": "...", "message": "..." }`
|
|
784
|
+
(Deprecated: **`POST /api/v1/tags`**)
|
|
754
785
|
|
|
755
|
-
|
|
786
|
+
## List bookmarks
|
|
756
787
|
|
|
757
|
-
|
|
788
|
+
**`GET /api/v1/bookmarks?limit=...&offset=...`** — Returns `{ bookmarks: [...], tags: [...], total }` (mirrors where applicable).
|
|
758
789
|
|
|
759
|
-
|
|
790
|
+
## Get / Delete bookmark
|
|
760
791
|
|
|
761
|
-
|
|
792
|
+
**`GET /api/v1/bookmarks/{name}`** / **`DELETE /api/v1/bookmarks/{name}`** (deprecated `/tags/...`)
|
|
762
793
|
|
|
763
|
-
|
|
794
|
+
## Compare
|
|
764
795
|
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
**`POST /api/v1/diff`**
|
|
796
|
+
**`POST /api/v1/compare`**
|
|
768
797
|
|
|
769
798
|
```json
|
|
770
799
|
{
|
|
771
|
-
"from": { "branch": "", "
|
|
800
|
+
"from": { "branch": "", "date": "2024-01-15T00:00:00" },
|
|
772
801
|
"to": { "branch": "feature-x" },
|
|
773
802
|
"include_content": true
|
|
774
803
|
}
|
|
775
804
|
```
|
|
776
805
|
|
|
806
|
+
(Deprecated: **`POST /api/v1/diff`**; `date_key` still accepted internally but prefer **`date`**.)
|
|
807
|
+
|
|
777
808
|
Returns `{ changes: [{ identifier, action: "added"|"modified"|"deleted", from_content?, to_content? }], total_changes }`.
|
|
778
809
|
|
|
779
810
|
---
|
|
@@ -1243,7 +1274,7 @@ import { XCiteDBClient } from '@xcitedbs/client';
|
|
|
1243
1274
|
const client = new XCiteDBClient({
|
|
1244
1275
|
baseUrl: 'http://localhost:8080',
|
|
1245
1276
|
apiKey: 'your-api-key',
|
|
1246
|
-
context: {
|
|
1277
|
+
context: { workspace: '', date: '' },
|
|
1247
1278
|
});
|
|
1248
1279
|
|
|
1249
1280
|
// Health check
|
|
@@ -1263,12 +1294,12 @@ await client.writeJsonDocument('app.settings', { theme: 'dark' });
|
|
|
1263
1294
|
// Read JSON document
|
|
1264
1295
|
const settings = await client.readJsonDocument('app.settings');
|
|
1265
1296
|
|
|
1266
|
-
//
|
|
1267
|
-
await client.
|
|
1268
|
-
client.setContext({
|
|
1297
|
+
// Workspace, edit, checkpoint, publish
|
|
1298
|
+
await client.createWorkspace('feature-x');
|
|
1299
|
+
client.setContext({ workspace: 'feature-x' });
|
|
1269
1300
|
await client.writeJsonDocument('app.settings', { theme: 'light' });
|
|
1270
|
-
await client.
|
|
1271
|
-
await client.
|
|
1301
|
+
await client.createCheckpoint('Switch to light theme');
|
|
1302
|
+
await client.publishWorkspace('', 'feature-x');
|
|
1272
1303
|
```
|
|
1273
1304
|
|
|
1274
1305
|
## Constructor Options
|
|
@@ -1289,7 +1320,8 @@ interface XCiteDBClientOptions {
|
|
|
1289
1320
|
}
|
|
1290
1321
|
|
|
1291
1322
|
interface DatabaseContext {
|
|
1292
|
-
|
|
1323
|
+
workspace?: string; // '' = default (root timeline); preferred
|
|
1324
|
+
branch?: string; // @deprecated alias of workspace
|
|
1293
1325
|
date?: string; // Point-in-time
|
|
1294
1326
|
prefix?: string; // Identifier prefix filter
|
|
1295
1327
|
unversioned?: boolean; // Sends X-Unversioned: true (flat writes; do not combine with date)
|
|
@@ -1357,30 +1389,34 @@ interface DatabaseContext {
|
|
|
1357
1389
|
- `queryMetaByQuery<T>(query, path?)` → `T`
|
|
1358
1390
|
- `clearMeta(query)` → `boolean`
|
|
1359
1391
|
|
|
1360
|
-
###
|
|
1361
|
-
- `
|
|
1362
|
-
- `
|
|
1363
|
-
- `
|
|
1364
|
-
- `
|
|
1365
|
-
- `
|
|
1366
|
-
- `deleteRevision(branch, date)` → `void`
|
|
1367
|
-
- `
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
- `
|
|
1372
|
-
- `
|
|
1373
|
-
- `
|
|
1374
|
-
- `
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
- `
|
|
1380
|
-
- `
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
- `
|
|
1392
|
+
### Workspaces & checkpoints
|
|
1393
|
+
- `withWorkspace(name, fn, options?)` → `{ result, checkpoint?, publish? }` — workspace, callback, checkpoint, publish back
|
|
1394
|
+
- `createWorkspace(name, fromBranch?, fromDate?)` → `void`
|
|
1395
|
+
- `listWorkspaces()` → `WorkspaceInfo[]`
|
|
1396
|
+
- `getWorkspace(name)` → `WorkspaceInfo`
|
|
1397
|
+
- `deleteWorkspace(name)` → `void`
|
|
1398
|
+
- `deleteRevision(branch, date)` → `void` (workspace name + human date)
|
|
1399
|
+
- `publishWorkspace(targetWorkspace, sourceWorkspace, options?)` → `PublishResult`
|
|
1400
|
+
- **Deprecated:** `withBranch`, `createBranch`, `listBranches`, `getBranch`, `deleteBranch`, `mergeBranch` (same HTTP behavior)
|
|
1401
|
+
|
|
1402
|
+
### Checkpoints
|
|
1403
|
+
- `createCheckpoint(message, author?)` → `CheckpointRecord`
|
|
1404
|
+
- `listCheckpoints(options?)` → `{ checkpoints, total, branch }` (wire JSON may also include `commits` mirror)
|
|
1405
|
+
- `getCheckpoint(checkpointId)` → `CheckpointRecord`
|
|
1406
|
+
- `revertToCheckpoint(checkpointId)` → `{ rolled_back_checkpoints, rolled_back_commits?, current_tip }`
|
|
1407
|
+
- `applyCheckpoint(checkpointId, message?, author?)` → `CheckpointRecord`
|
|
1408
|
+
- **Deprecated:** `createCommit`, `listCommits`, `getCommit`, `rollbackToCommit`, `cherryPick`
|
|
1409
|
+
|
|
1410
|
+
### Bookmarks
|
|
1411
|
+
- `createBookmark(name, checkpointId, message?, author?)` → `BookmarkRecord`
|
|
1412
|
+
- `listBookmarks(options?)` → `{ bookmarks, tags, total, limit?, offset? }`
|
|
1413
|
+
- `getBookmark(name)` → `BookmarkRecord`
|
|
1414
|
+
- `deleteBookmark(name)` → `void`
|
|
1415
|
+
- **Deprecated:** `createTag`, `listTags`, `getTag`, `deleteTag`
|
|
1416
|
+
|
|
1417
|
+
### Compare
|
|
1418
|
+
- `compare(from: CompareRef, to: CompareRef, includeContent?)` → `CompareResult`
|
|
1419
|
+
- **Deprecated:** `diff(from: DiffRef, …)` — alias of `compare`
|
|
1384
1420
|
|
|
1385
1421
|
### Locks
|
|
1386
1422
|
- `acquireLock(identifier, expires?)` → `LockInfo`
|
|
@@ -1388,7 +1424,7 @@ interface DatabaseContext {
|
|
|
1388
1424
|
- `findLocks(identifier)` → `LockInfo[]`
|
|
1389
1425
|
|
|
1390
1426
|
### Search
|
|
1391
|
-
- `search(query: TextSearchQuery)` → `TextSearchResult`
|
|
1427
|
+
- `search(query: TextSearchQuery)` → `TextSearchResult`. Query may include **`at_date`**, **`date_from`**, **`date_to`** (ISO-style or `mm/dd/yyyy` strings) for temporal FTS; set **`mode`: `"fts"`** for keyword-only temporal search. Hits may include **`valid_from`** / **`valid_to`** (7-char internal keys) when the server returns an inferred validity window.
|
|
1392
1428
|
- `reindex()` → `{ status, message }`
|
|
1393
1429
|
|
|
1394
1430
|
### Unquery
|
|
@@ -1513,7 +1549,7 @@ async def main():
|
|
|
1513
1549
|
async with XCiteDBClient(
|
|
1514
1550
|
"http://localhost:8080",
|
|
1515
1551
|
api_key="your-key",
|
|
1516
|
-
context=DatabaseContext(
|
|
1552
|
+
context=DatabaseContext(workspace="", date=""),
|
|
1517
1553
|
) as client:
|
|
1518
1554
|
print(await client.health())
|
|
1519
1555
|
print(await client.query_documents(XCiteQuery(match_start="/manual/")))
|
|
@@ -1521,15 +1557,16 @@ async def main():
|
|
|
1521
1557
|
print(await client.read_json_document("app.settings"))
|
|
1522
1558
|
print(await client.list_identifiers(XCiteQuery(match_start="/manual/")))
|
|
1523
1559
|
print(await client.search(TextSearchQuery(query="guide", limit=10)))
|
|
1560
|
+
# Temporal FTS: await client.search(TextSearchQuery(query="guide", mode="fts", at_date="2024-06-01"))
|
|
1524
1561
|
await client.platform_login("admin@localhost", "password")
|
|
1525
1562
|
# await client.login_app_user("user@example.com", "pw") # set context.project_id / tenant_id if needed
|
|
1526
|
-
async with client.
|
|
1563
|
+
async with client.with_workspace("feature-x", message="WIP", auto_merge=True):
|
|
1527
1564
|
await client.put("app.settings", {"theme": "light"})
|
|
1528
1565
|
|
|
1529
1566
|
asyncio.run(main())
|
|
1530
1567
|
```
|
|
1531
1568
|
|
|
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), `
|
|
1569
|
+
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
1570
|
|
|
1534
1571
|
---
|
|
1535
1572
|
|
|
@@ -1541,7 +1578,7 @@ Async client: `write_xml_document` / `write_document_json` (deprecated), `write_
|
|
|
1541
1578
|
xcitedb::XCiteDBClientOptions opt;
|
|
1542
1579
|
opt.base_url = "http://127.0.0.1:8080";
|
|
1543
1580
|
opt.api_key = "your-key";
|
|
1544
|
-
opt.context.
|
|
1581
|
+
opt.context.workspace = ""; // root timeline (`branch` is deprecated alias)
|
|
1545
1582
|
|
|
1546
1583
|
xcitedb::XCiteDBClient client(opt);
|
|
1547
1584
|
auto health = client.health();
|
|
@@ -1553,4 +1590,4 @@ auto ids = client.query_documents(q);
|
|
|
1553
1590
|
|
|
1554
1591
|
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
1592
|
|
|
1556
|
-
Includes optional `xcitevcs` CLI for command-line operations (
|
|
1593
|
+
Includes optional `xcitevcs` CLI for command-line operations (legacy branch/commit vocabulary on the wire, documents, search, import/export).
|