@xcitedbs/client 0.1.0 → 0.2.5

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.txt ADDED
@@ -0,0 +1,274 @@
1
+ # XciteDB
2
+
3
+ > XciteDB is a versioned XML and JSON document database delivered as a Backend-as-a-Service (BaaS). It provides Git-like branching, commits, time-travel, and hierarchical document identifiers over a high-performance embedded LMDB engine, exposed through a REST + WebSocket API.
4
+
5
+ ## Important: Non-Standard Conventions
6
+
7
+ These are the most common sources of confusion for developers and AI assistants:
8
+
9
+ 1. **The default branch is the empty string `""`, not `"main"`.** When no `X-Branch` header is sent (or `context.branch` is omitted/empty in the SDK), 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.
10
+
11
+ 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 (like a filesystem). The server indexes this hierarchy natively.
12
+
13
+ 3. **Documents are XML or JSON, not arbitrary blobs.** XML documents are the primary document type, stored with structural shredding. JSON documents are a parallel store keyed by identifier string. Both are fully versioned.
14
+
15
+ 4. **Context (branch + date) travels as HTTP headers**, not URL path segments. Use `X-Branch` and `X-Date` headers (or the SDK `context` option) to select which branch and point-in-time you are reading/writing.
16
+
17
+ 5. **XML documents carry their identifier inside the XML** — specifically via a `db:identifier` attribute on the root element (e.g. `<chapter db:identifier="/book/ch1">...</chapter>`). When writing XML, the server extracts the identifier from the document body.
18
+
19
+ 6. **Authentication has two tiers.** Platform operators (site admins) log in via `/api/v1/platform/auth/*` and use `X-Project-Id` to select a tenant project. Application end-users log in via `/api/v1/app/auth/*` and are scoped to a single project. API keys bypass login for server-to-server use.
20
+
21
+ 7. **The query model is NOT SQL.** Listing/filtering documents uses query parameters on REST endpoints (`match`, `match_start`, `contains`, `regex`, `prefix`). Advanced analytics use **Unquery**, a JSON-defined declarative DSL posted to `POST /api/v1/unquery`.
22
+
23
+ 8. **Project vs tenant id.** In the SDK, prefer `context.project_id` (and `listMyProjects` / `switchProject`). Many JSON bodies and JWT claims still use the field name `tenant_id` for the same value — the client sends that wire name automatically.
24
+
25
+ ## JavaScript/TypeScript SDK (`@xcitedbs/client`)
26
+
27
+ Install: `npm install @xcitedbs/client`
28
+
29
+ ### Quick Start
30
+
31
+ ```typescript
32
+ import { XCiteDBClient } from '@xcitedbs/client';
33
+
34
+ const client = new XCiteDBClient({
35
+ baseUrl: 'http://localhost:8080',
36
+ apiKey: 'your-api-key',
37
+ // branch: '' means root timeline (the default); omit or use '' for default
38
+ context: { branch: '', date: '' },
39
+ });
40
+
41
+ // Health check (no auth required)
42
+ await client.health();
43
+
44
+ // List all branches
45
+ const branches = await client.listBranches();
46
+
47
+ // Query documents by identifier prefix
48
+ const docs = await client.queryDocuments({ match_start: '/manual/' });
49
+
50
+ // Read a single document by exact identifier
51
+ const xml = await client.queryByIdentifier('/manual/v1/intro', 'FirstMatch');
52
+
53
+ // Write an XML document (identifier is inside the XML body)
54
+ await client.writeXmlDocument(
55
+ '<chapter db:identifier="/manual/v1/intro"><title>Introduction</title></chapter>'
56
+ );
57
+
58
+ // Write a JSON document
59
+ await client.writeJsonDocument('app.settings', { theme: 'dark', locale: 'en' });
60
+
61
+ // Read a JSON document
62
+ const settings = await client.readJsonDocument('app.settings');
63
+
64
+ // Quick JSON CRUD aliases (same as writeJsonDocument / readJsonDocument / deleteJsonDocument / listJsonDocuments)
65
+ await client.put('app.prefs', { theme: 'dark' });
66
+ const prefs = await client.get<Record<string, unknown>>('app.prefs');
67
+ await client.remove('app.prefs');
68
+ const keys = await client.list(undefined, 50, 0);
69
+
70
+ // Branch helper: create branch, run work, commit, merge back (restores context)
71
+ await client.withBranch('feature-x', async (c) => {
72
+ await c.writeJsonDocument('app.settings', { theme: 'light' });
73
+ return 'ok';
74
+ }, { message: 'Light theme', autoMerge: true, fromBranch: '' });
75
+
76
+ // Create a branch, make changes, commit, merge
77
+ await client.createBranch('feature-x');
78
+ client.setContext({ branch: 'feature-x' });
79
+ await client.writeJsonDocument('app.settings', { theme: 'light' });
80
+ const commit = await client.createCommit('Switch to light theme');
81
+ await client.mergeBranch('', 'feature-x'); // merge into root (default) branch
82
+
83
+ // Attach JSON metadata to a document
84
+ await client.addMeta('/manual/v1/intro', { status: 'draft', owner: 'alice' });
85
+
86
+ // Acquire a cooperative lock
87
+ const lock = await client.acquireLock('/manual/v1/intro');
88
+ // ... edit ...
89
+ await client.releaseLock('/manual/v1/intro', lock.lock_id);
90
+
91
+ // Full-text search (requires Meilisearch or Elasticsearch backend)
92
+ const results = await client.search({ query: 'installation guide', limit: 20 });
93
+
94
+ // Subscribe to real-time changes via WebSocket
95
+ const sub = client.subscribe(
96
+ { pattern: '/manual/*', event_type: '*' },
97
+ (event) => console.log('Change:', event)
98
+ );
99
+ ```
100
+
101
+ ### Constructor Options
102
+
103
+ ```typescript
104
+ interface XCiteDBClientOptions {
105
+ baseUrl: string; // Server URL, e.g. 'http://localhost:8080'
106
+ apiKey?: string; // Project API key (secret or public)
107
+ accessToken?: string; // Platform JWT (from platformLogin)
108
+ appUserAccessToken?: string; // End-user JWT (from loginAppUser)
109
+ context?: {
110
+ branch?: string; // Branch name; '' = default/root timeline
111
+ date?: string; // Point-in-time (ISO-like or internal date key)
112
+ prefix?: string; // Optional identifier prefix filter
113
+ project_id?: string; // Preferred: project id for app-user public auth (`tenant_id` on wire)
114
+ tenant_id?: string; // Deprecated alias of project_id
115
+ };
116
+ platformConsole?: boolean; // true = use X-Project-Id header
117
+ projectId?: string; // Active project for platform console mode
118
+ }
119
+ ```
120
+
121
+ ### Key Methods Reference
122
+
123
+ **Health & Auth:**
124
+ - `health()` — Liveness check (no auth)
125
+ - `version()` — Server version info
126
+ - `platformLogin(email, password)` — Platform operator sign-in
127
+ - `loginAppUser(email, password)` — App end-user sign-in
128
+ - `setContext(ctx)` — Update branch/date context
129
+ - `setProjectId(id)` — Switch active project (platform console)
130
+
131
+ **XML Documents:**
132
+ - `writeXmlDocument(xml, options?)` — Store XML via JSON body (identifier inside XML). Deprecated alias: `writeDocumentJson`.
133
+ - `writeXML(xml)` — Store raw XML with `Content-Type: application/xml`
134
+ - `queryByIdentifier(id, flags?, filter?)` — Get document(s) by identifier
135
+ - `queryDocuments(query, flags?)` — List/filter documents
136
+ - `deleteDocument(identifier)` — Delete by identifier
137
+ - `listIdentifiers(query)` — List known identifiers with pagination
138
+ - `listIdentifierChildren(parentPath?)` — Navigate identifier hierarchy
139
+
140
+ **JSON Documents:**
141
+ - `writeJsonDocument(identifier, data)` — Store a JSON document
142
+ - `readJsonDocument(identifier)` — Read a JSON document (generic `readJsonDocument<T>()` supported)
143
+ - `deleteJsonDocument(identifier)` — Delete a JSON document
144
+ - `listJsonDocuments(match?, limit?, offset?)` — List JSON document keys
145
+ - **Quick JSON aliases:** `put`, `get`, `remove`, `list` — same as the four methods above
146
+
147
+ **Metadata (JSON on XML):**
148
+ - `addMeta(identifier, value, path?)` — Set metadata on a document
149
+ - `appendMeta(identifier, value, path?)` — Append to metadata
150
+ - `queryMeta(identifier, path?)` — Read metadata
151
+ - `clearMeta(query)` — Remove metadata
152
+
153
+ **Versioning:**
154
+ - `withBranch(name, fn, options?)` — Create branch, run callback on client, commit, merge back (optional `autoMerge: false`)
155
+ - `createBranch(name, fromBranch?, fromDate?)` — Create branch
156
+ - `listBranches()` — List all branches
157
+ - `mergeBranch(target, source, options?)` — Merge branches
158
+ - `deleteBranch(name)` — Delete branch
159
+ - `createCommit(message, author?)` — Commit current state
160
+ - `listCommits(options?)` — List commits
161
+ - `rollbackToCommit(commitId)` — Rollback to prior commit
162
+ - `cherryPick(commitId, message?)` — Cherry-pick a commit
163
+ - `diff(from, to, includeContent?)` — Diff between revisions
164
+ - `createTag(name, commitId, message?)` — Tag a commit
165
+ - `listTags()` / `deleteTag(name)` — Manage tags
166
+
167
+ **Locks:**
168
+ - `acquireLock(identifier, expires?)` — Acquire cooperative lock
169
+ - `releaseLock(identifier, lockId)` — Release lock
170
+ - `findLocks(identifier)` — Query active locks
171
+
172
+ **Search & Analytics:**
173
+ - `search(query)` — Full-text search
174
+ - `reindex()` — Rebuild search index
175
+ - `unquery(query, unqueryDoc)` — Execute Unquery DSL
176
+
177
+ **Security & Policies:**
178
+ - `createPolicy(id, policy)` / `listPolicies()` / `updatePolicy()` / `deletePolicy()` — ABAC policies
179
+ - `checkAccess(subject, identifier, action)` — Dry-run access check
180
+ - `getSecurityConfig()` / `updateSecurityConfig()` — Security settings
181
+
182
+ **Triggers:**
183
+ - `upsertTrigger(id, trigger)` / `listTriggers()` / `deleteTrigger(name)` — Automation triggers
184
+
185
+ **App Users (admin):**
186
+ - `listAppUsers()` / `createAppUser()` / `deleteAppUser()` — Manage end-user accounts
187
+ - `registerAppUser()` — Self-registration
188
+ - `getAppAuthConfig()` — Auth configuration
189
+
190
+ **WebSocket:**
191
+ - `subscribe(options, callback, onError?)` — Real-time document change notifications
192
+
193
+ ### Query Flags
194
+
195
+ When calling `queryByIdentifier` or `queryDocuments`, the `flags` parameter controls matching:
196
+ - `'FirstMatch'` — Return only the first matching document
197
+ - `'IncludeChildren'` — Include child identifiers in results
198
+ - `'NoChildren'` — Exclude children
199
+ - `'KeepIndexNodes'` — Include index/structural nodes
200
+
201
+ ### Errors
202
+
203
+ All API errors throw `XCiteDBError` with `.status` (HTTP code) and `.body` (parsed response). Common codes: `401` unauthenticated, `403` forbidden by policy, `404` not found, `409` conflict (lock), `422` validation, `423` project encrypted and locked, `429` rate limited.
204
+
205
+ ## Python SDK (`xcitedb`)
206
+
207
+ Install: `pip install xcitedb`
208
+
209
+ ```python
210
+ import asyncio
211
+ from xcitedb import XCiteDBClient, XCiteQuery, DatabaseContext, TextSearchQuery
212
+
213
+ async def main():
214
+ async with XCiteDBClient(
215
+ "http://localhost:8080",
216
+ api_key="your-key",
217
+ context=DatabaseContext(branch="", date=""),
218
+ ) as client:
219
+ print(await client.health())
220
+ ids = await client.query_documents(XCiteQuery(match_start="/manual/"))
221
+ print(ids)
222
+ await client.write_json_document("app.settings", {"theme": "dark"})
223
+ print(await client.read_json_document("app.settings"))
224
+ print(await client.search(TextSearchQuery(query="guide", limit=10)))
225
+ pair = await client.platform_login("admin@localhost", "password")
226
+ # await client.login_app_user("user@example.com", "secret", tenant_id="...")
227
+
228
+ asyncio.run(main())
229
+ ```
230
+
231
+ ## C++ SDK (`xcitedb`)
232
+
233
+ ```cpp
234
+ #include <xcitedb/xcitedb.hpp>
235
+
236
+ xcitedb::XCiteDBClientOptions opt;
237
+ opt.base_url = "http://127.0.0.1:8080";
238
+ opt.api_key = "your-key";
239
+ opt.context.branch = ""; // root timeline
240
+
241
+ xcitedb::XCiteDBClient client(opt);
242
+ auto health = client.health();
243
+ xcitedb::XCiteQuery q;
244
+ q.match_start = "/manual/";
245
+ auto ids = client.query_documents(q);
246
+ ```
247
+
248
+ ## Architecture Notes
249
+
250
+ - **Multi-tenant**: Each project is an isolated tenant with its own data, users, keys, and policies.
251
+ - **LMDB engine**: Data is memory-mapped; reads are microsecond-class on warm data.
252
+ - **Versioning**: Every write is versioned. Branches isolate work. Commits snapshot state. Time-travel reads any historical state via `X-Date`.
253
+ - **Two user tiers**: Platform operators manage infrastructure; App users are end-users of applications built on XciteDB.
254
+ - **Security policies (ABAC)**: Fine-grained allow/deny rules on actions, resources, roles, and branches.
255
+ - **WebSocket**: Real-time notifications for document changes at `/api/v1/ws`.
256
+
257
+ ## Documentation
258
+
259
+ - **OpenAPI 3.1:** Repository file `docs/openapi.yaml` (machine-readable route map and shared schemas).
260
+ - Full API reference is also available at your XciteDB server's `/docs` path. Key sections:
261
+ - Getting started — Base URL, headers, errors, pagination
262
+ - Documents — XML document CRUD, identifiers, hierarchy
263
+ - JSON documents — JSON document CRUD
264
+ - Metadata — JSON metadata on documents
265
+ - Search — Full-text search
266
+ - Unquery — Declarative query DSL
267
+ - Branches — Branch management
268
+ - Commits & tags — Version snapshots
269
+ - Locks — Cooperative editing locks
270
+ - Authentication — JWT, API keys, platform vs app users
271
+ - Security policies — ABAC access control
272
+ - Triggers — Automated webhooks on metadata changes
273
+ - App authentication — End-user registration, login, OAuth
274
+ - Project & API keys — Key management
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xcitedbs/client",
3
- "version": "0.1.0",
3
+ "version": "0.2.5",
4
4
  "description": "XCiteDB BaaS client SDK",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -37,7 +37,9 @@
37
37
  "typescript": "^5.0.0"
38
38
  },
39
39
  "files": [
40
- "dist"
40
+ "dist",
41
+ "llms.txt",
42
+ "llms-full.txt"
41
43
  ],
42
44
  "license": "MIT"
43
45
  }