@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/README.md +2 -1
- package/dist/client.d.ts +47 -14
- package/dist/client.js +71 -16
- package/dist/index.d.ts +1 -1
- package/dist/types.d.ts +37 -5
- package/llms-full.txt +1181 -0
- package/llms.txt +274 -0
- package/package.json +4 -2
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.
|
|
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
|
}
|