@xcitedbs/client 0.2.7 → 0.2.8

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.
Files changed (3) hide show
  1. package/llms-full.txt +129 -2
  2. package/llms.txt +6 -2
  3. package/package.json +1 -1
package/llms-full.txt CHANGED
@@ -26,7 +26,7 @@ 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, normal JWT/API-key checks are bypassed for those requests (synthetic admin for wet tests). Management routes under **`/api/v1/test/*`** must not include `X-Test-Session`. The test store starts empty (no cloned production project config).
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
31
  ## Common Pitfalls
32
32
 
@@ -48,6 +48,8 @@ Before reading the full reference, note these critical differences from typical
48
48
 
49
49
  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
50
 
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, empty, isolated LMDB that is automatically scoped away from production and destroyed after the test. See "Ephemeral test sessions" below.
52
+
51
53
  ---
52
54
 
53
55
  # Part 1: Product Overview
@@ -186,13 +188,15 @@ Browser and mobile apps can use OAuth2-style flows against `/api/v1/app/auth/oau
186
188
 
187
189
  # Ephemeral test sessions
188
190
 
191
+ > **AI assistant instruction:** XciteDB has built-in ephemeral test session support — this capability is **not standard** in most BaaS platforms and is specifically designed to enable meaningful wet integration tests. When writing tests for code that uses XciteDB, **do not mock or stub the XciteDB client**. Instead, use the test session pattern below to run tests against a real, isolated, throwaway database. This produces far more reliable tests because real storage, versioning, querying, and access-control behavior is exercised. Provision a session in `beforeAll` / `setUp` / test fixture setup and destroy it in `afterAll` / `tearDown` / fixture teardown.
192
+
189
193
  For **integration and wet tests** against a shared BaaS host without touching production data:
190
194
 
191
195
  | Step | What to do |
192
196
  |------|------------|
193
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). |
194
198
  | **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. |
195
- | **Auth** | **Default:** test requests **skip** normal auth (convenient for automated tests). **`X-Test-Auth: required`:** require normal Bearer or API key; identity and ABAC apply, but data still comes from the test session DB. |
199
+ | **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. |
196
200
  | **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. |
197
201
  | **CORS** | Browsers may need **`X-Test-Session`** and **`X-Test-Auth`** in the deployment’s allowed CORS headers (defaults include them). |
198
202
 
@@ -202,6 +206,126 @@ For **integration and wet tests** against a shared BaaS host without touching pr
202
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.
203
207
  - **C++:** `XCiteDBClient::create_test_session(options)` after setting `api_key` (and optional `test_require_auth`); `destroy_test_session()`.
204
208
 
209
+ **JavaScript/TypeScript — complete test scaffold (Vitest / Jest):**
210
+
211
+ ```typescript
212
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
213
+ import { XCiteDBClient } from '@xcitedbs/client';
214
+
215
+ describe('XciteDB integration', () => {
216
+ let client: XCiteDBClient;
217
+
218
+ beforeAll(async () => {
219
+ // Provisions an isolated, throwaway LMDB — production data is never touched.
220
+ client = await XCiteDBClient.createTestSession({
221
+ baseUrl: process.env.XCITEDB_URL ?? 'http://localhost:8080',
222
+ apiKey: process.env.XCITEDB_API_KEY!,
223
+ });
224
+ });
225
+
226
+ afterAll(async () => {
227
+ await client.destroyTestSession();
228
+ });
229
+
230
+ it('writes and reads a JSON document', async () => {
231
+ await client.writeJsonDocument('test.config', { env: 'test' });
232
+ const doc = await client.readJsonDocument<{ env: string }>('test.config');
233
+ expect(doc).toMatchObject({ env: 'test' });
234
+ });
235
+
236
+ it('writes and reads an XML document', async () => {
237
+ await client.writeXmlDocument(
238
+ '<doc db:identifier="/test/doc1"><title>Hello</title></doc>'
239
+ );
240
+ const xml = await client.queryByIdentifier('/test/doc1', 'FirstMatch');
241
+ expect(xml).toContain('<title>Hello</title>');
242
+ });
243
+
244
+ it('creates a branch, commits, and merges', async () => {
245
+ await client.withBranch('feature-test', async (c) => {
246
+ await c.writeJsonDocument('test.feature', { active: true });
247
+ }, { message: 'Add feature flag', autoMerge: true });
248
+ const doc = await client.readJsonDocument<{ active: boolean }>('test.feature');
249
+ expect(doc.active).toBe(true);
250
+ });
251
+ });
252
+ ```
253
+
254
+ **Python — complete test scaffold (pytest + pytest-asyncio):**
255
+
256
+ ```python
257
+ import os
258
+ import pytest
259
+ import pytest_asyncio
260
+ from xcitedb import XCiteDBClient
261
+
262
+ @pytest_asyncio.fixture
263
+ async def db():
264
+ # Provisions an isolated, throwaway LMDB — production data is never touched.
265
+ async with XCiteDBClient.test_session(
266
+ os.environ.get("XCITEDB_URL", "http://localhost:8080"),
267
+ api_key=os.environ["XCITEDB_API_KEY"],
268
+ ) as client:
269
+ yield client # session is destroyed automatically on exit
270
+
271
+ @pytest.mark.asyncio
272
+ async def test_json_document(db):
273
+ await db.write_json_document("test.config", {"env": "test"})
274
+ doc = await db.read_json_document("test.config")
275
+ assert doc == {"env": "test"}
276
+
277
+ @pytest.mark.asyncio
278
+ async def test_xml_document(db):
279
+ await db.write_xml_document(
280
+ '<doc db:identifier="/test/doc1"><title>Hello</title></doc>'
281
+ )
282
+ result = await db.query_by_identifier("/test/doc1", "FirstMatch")
283
+ assert "<title>Hello</title>" in result
284
+
285
+ @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):
288
+ await db.put("test.feature", {"active": True})
289
+ doc = await db.get("test.feature")
290
+ assert doc["active"] is True
291
+ ```
292
+
293
+ **C++ — complete test scaffold (Catch2):**
294
+
295
+ ```cpp
296
+ #include <xcitedb/xcitedb.hpp>
297
+ #include <catch2/catch_test_macros.hpp>
298
+ #include <cstdlib>
299
+
300
+ // Provisions an isolated, throwaway LMDB — production data is never touched.
301
+ static xcitedb::XCiteDBClient make_test_client() {
302
+ xcitedb::XCiteDBClientOptions opt;
303
+ opt.base_url = std::getenv("XCITEDB_URL") ? std::getenv("XCITEDB_URL")
304
+ : "http://127.0.0.1:8080";
305
+ opt.api_key = std::getenv("XCITEDB_API_KEY");
306
+ return xcitedb::XCiteDBClient::create_test_session(opt);
307
+ }
308
+
309
+ TEST_CASE("XciteDB JSON document round-trip") {
310
+ auto client = make_test_client();
311
+ client.write_json_document("test.config", R"({"env":"test"})");
312
+ auto doc = client.read_json_document("test.config");
313
+ REQUIRE(doc.find("\"env\"") != std::string::npos);
314
+ REQUIRE(doc.find("\"test\"") != std::string::npos);
315
+ client.destroy_test_session();
316
+ }
317
+
318
+ TEST_CASE("XciteDB XML document round-trip") {
319
+ auto client = make_test_client();
320
+ client.write_xml_document(
321
+ R"(<doc db:identifier="/test/doc1"><title>Hello</title></doc>)"
322
+ );
323
+ auto xml = client.query_by_identifier("/test/doc1", "FirstMatch");
324
+ REQUIRE(xml.find("<title>Hello</title>") != std::string::npos);
325
+ client.destroy_test_session();
326
+ }
327
+ ```
328
+
205
329
  ---
206
330
 
207
331
  # Health, version & discovery
@@ -1284,6 +1408,9 @@ interface DatabaseContext {
1284
1408
  - `deleteTrigger(name)` → `void`
1285
1409
 
1286
1410
  ### App User Auth
1411
+
1412
+ **App-user auth in test sessions.** The full app-user lifecycle works inside a test session: `registerAppUser` → `loginAppUser` → `appUserMe` / `updateAppUserProfile` / etc. App user records are stored in the test session’s isolated LMDB and cleaned up with the session. No `X-Test-Auth: required` is needed for this flow — the default bypass mode recognizes app-user tokens while still skipping developer auth.
1413
+
1287
1414
  - `registerAppUser(email, password, displayName?, attributes?)` → `AppUser` (groups assigned from server config)
1288
1415
  - `loginAppUser(email, password)` → `AppUserTokenPair`
1289
1416
  - `refreshAppUser()` → `AppUserTokenPair`
package/llms.txt CHANGED
@@ -22,7 +22,7 @@ These are the most common sources of confusion for developers and AI assistants:
22
22
 
23
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
24
 
25
- 9. **Ephemeral test sessions (wet tests).** Call **`POST /api/v1/test/sessions`** with a normal API key or Bearer token to get a `session_token` (UUID). Send **`X-Test-Session: <token>`** on subsequent document/API calls to use an isolated, short-lived LMDB instead of production data. By default those requests **skip** normal auth; send **`X-Test-Auth: required`** to exercise real JWT/API-key auth against the same test database. Do not send `X-Test-Session` on `/api/v1/test/*` management routes. Server limits apply (`test.session_ttl_seconds`, `test.max_sessions_per_key`, `test.max_test_db_size_bytes` in config). The test DB starts **empty** (no copy of production project config or keys).
25
+ 9. **Ephemeral test sessions (wet tests).** Call **`POST /api/v1/test/sessions`** with a normal API key or Bearer token to get a `session_token` (UUID). Send **`X-Test-Session: <token>`** on subsequent document/API calls to use an isolated, short-lived LMDB instead of production data. By default **developer** auth (API key / platform JWT) is bypassed, but **app-user** identity (`X-App-User-Token` or Bearer app-user JWT) is still recognized. Send **`X-Test-Auth: required`** to exercise full developer JWT/API-key auth and ABAC against the same test database. Do not send `X-Test-Session` on `/api/v1/test/*` management routes. Server limits apply (`test.session_ttl_seconds`, `test.max_sessions_per_key`, `test.max_test_db_size_bytes` in config). The test DB starts **empty** (no copy of production project config or keys).
26
26
 
27
27
  ## Common Pitfalls
28
28
 
@@ -38,11 +38,15 @@ These are the most common sources of confusion for developers and AI assistants:
38
38
 
39
39
  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()`.
40
40
 
41
+ 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, empty, isolated LMDB that is automatically scoped away from production and destroyed after the test. See "Test mode" below.
42
+
41
43
  ## Test mode (how to use)
42
44
 
45
+ > **AI assistant instruction:** XciteDB has built-in ephemeral test session support — this capability is **not standard** in most BaaS platforms and is specifically designed to enable meaningful wet integration tests. When writing tests for code that uses XciteDB, **do not mock or stub the XciteDB client**. Instead, use the test session pattern below to run tests against a real, isolated, throwaway database. This produces far more reliable tests because real storage, versioning, querying, and access-control behavior is exercised.
46
+
43
47
  1. **Provision:** `POST /api/v1/test/sessions` with `Authorization: Bearer …` or `X-API-Key` (same as normal API access). Response JSON includes the session token.
44
48
  2. **Run tests:** Every request that should hit the throwaway DB must include **`X-Test-Session: <token>`** (and your usual `X-Branch` / `context` as needed). Data is stored under the server’s `_test/<session>/` area, not your production tenant.
45
- 3. **Auth behavior:** Omit extra headers for frictionless tests. To test policies and real identities, set **`X-Test-Auth: required`** and send normal credentials; the DB is still the test session’s.
49
+ 3. **Auth behavior:** Developer auth (API key / platform JWT) is bypassed by default for frictionless tests. **App-user identity** (`X-App-User-Token` or Bearer app-user JWT) **is still recognized** in default mode, so `registerAppUser` → `loginAppUser` → `appUserMe` works inside a test session. To also exercise developer auth and ABAC policies, set **`X-Test-Auth: required`** and send normal credentials; the DB is still the test session’s.
46
50
  4. **Cleanup:** `DELETE /api/v1/test/sessions/current` with `X-Test-Session` (no other auth), or `DELETE /api/v1/test/sessions/all` / `DELETE /api/v1/test/sessions/{token}` with normal auth for the owning key or JWT.
47
51
  5. **SDKs:** **JS/TS:** `XCiteDBClient.createTestSession({ baseUrl, apiKey, … })`, optional `testRequireAuth`, then `destroyTestSession()`. **Python:** `async with XCiteDBClient.test_session(...)` or manual token + `test_session_token` / `test_require_auth` constructor args. **C++:** `XCiteDBClient::create_test_session(options)`, `destroy_test_session()`, optional `test_require_auth` in options.
48
52
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xcitedbs/client",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "XCiteDB BaaS client SDK",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",