@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 CHANGED
@@ -34,6 +34,19 @@ const docs = await client.queryByIdentifier('/test1', 'FirstMatch');
34
34
  await client.put('app.settings', { theme: 'dark' });
35
35
  ```
36
36
 
37
+ ### Full-text search (temporal)
38
+
39
+ `client.search()` accepts `TextSearchQuery` with optional **`at_date`** (point-in-time), **`date_from`** / **`date_to`** (range overlap), and **`mode`: `'fts'`** for pure keyword search. Omit temporal fields for the default “current” posting view. Hits may include **`valid_from`** / **`valid_to`** (7-character internal date keys returned by the server).
40
+
41
+ ```typescript
42
+ await client.search({
43
+ query: 'installation guide',
44
+ mode: 'fts',
45
+ at_date: '2024-06-01',
46
+ limit: 20,
47
+ });
48
+ ```
49
+
37
50
  ### WebSocket
38
51
 
39
52
  ```typescript
@@ -45,6 +58,15 @@ client.subscribe(
45
58
 
46
59
  With JWT in browsers, tokens are passed as `access_token` query parameter on the WebSocket URL. API keys can use `api_key` query parameter.
47
60
 
61
+ ## Test sessions (ephemeral and overlay)
62
+
63
+ Call **`POST /api/v1/test/sessions`** with your normal API key or Bearer (same project context as usual). Use **`XCiteDBClient.createTestSession({ baseUrl, apiKey, … })`** to get a client that sends **`X-Test-Session`** on requests.
64
+
65
+ - **Default:** isolated empty LMDB under the server’s `_test/<uuid>/` (writes never touch production).
66
+ - **Overlay:** pass **`overlay: true`** in **`createTestSession`** options (or **`POST`** body **`{"overlay":true}`**). The server layers a writable LMDB on top of the **current project’s on-disk data opened read-only** so you can debug against real data; changes still live only under `_test/<uuid>/`. Use project-scoped credentials or platform Bearer + **`X-Project-Id`** as when calling production APIs.
67
+
68
+ Tear down with **`destroyTestSession()`** (or **`DELETE /api/v1/test/sessions/current`** with the session header). See **`llms.txt`** / **`llms-full.txt`** in this package for full behavior, limits, and auth notes.
69
+
48
70
  ## Build
49
71
 
50
72
  ```bash
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { AccessCheckResult, AppAuthConfig, AppEmailConfig, AppEmailTemplates, AppUser, AppUserTokenPair, EmailTestResponse, ForgotPasswordResponse, SendVerificationResponse, BranchInfo, CommitRecord, DatabaseContext, DiffRef, DiffResult, Flags, ListIdentifierChildrenResult, ListIdentifiersResult, LockInfo, LogEntry, MergeResult, MetaValue, PlatformRegisterResult, PolicySubjectInput, UnqueryResult, UnqueryTemplate, PolicyUpdateResponse, RealtimeEvent, SecurityConfig, SecurityPolicy, StoredTriggerResponse, TriggerDefinition, StoredPolicyResponse, SubscriptionOptions, TagRecord, TextSearchQuery, TextSearchResult, ProjectSearchSettings, ProjectSearchSettingsUpdate, VectorIndexEstimate, RagQueryOptions, RagQueryResult, RagStreamEvent, OAuthProvidersResponse, ProjectInfo, PlatformRegistrationConfig, PlatformWorkspacesResponse, TokenPair, UserInfo, ApiKeyInfo, WriteDocumentOptions, CreateTestSessionOptions, XCiteDBClientOptions, XCiteDBJwtClaims, XCiteQuery, UserIsolationConfig } from './types';
1
+ import { AccessCheckResult, AppAuthConfig, AppEmailConfig, AppEmailTemplates, AppUser, AppUserTokenPair, EmailTestResponse, ForgotPasswordResponse, SendVerificationResponse, BranchInfo, BookmarkRecord, CheckpointRecord, CommitRecord, CompareRef, CompareResult, DatabaseContext, DiffRef, DiffResult, Flags, ListIdentifierChildrenResult, ListIdentifiersResult, LockInfo, LogEntry, MergeResult, PublishResult, WorkspaceInfo, MetaValue, PlatformRegisterResult, PolicySubjectInput, UnqueryResult, UnqueryTemplate, PolicyUpdateResponse, RealtimeEvent, SecurityConfig, SecurityPolicy, StoredTriggerResponse, TriggerDefinition, StoredPolicyResponse, SubscriptionOptions, TagRecord, TextSearchQuery, TextSearchResult, ProjectSearchSettings, ProjectSearchSettingsUpdate, ProjectDocConfResponse, PlatformDefaultDocConfResponse, VectorIndexEstimate, RagQueryOptions, RagQueryResult, RagStreamEvent, OAuthProvidersResponse, ProjectInfo, PlatformRegistrationConfig, PlatformWorkspacesResponse, TokenPair, UserInfo, ApiKeyInfo, WriteDocumentOptions, CreateTestSessionOptions, XCiteDBClientOptions, XCiteDBJwtClaims, XCiteQuery, UserIsolationConfig } from './types';
2
2
  import { WebSocketSubscription } from './websocket';
3
3
  export declare class XCiteDBClient {
4
4
  private baseUrl;
@@ -18,10 +18,13 @@ export declare class XCiteDBClient {
18
18
  private testRequireAuth?;
19
19
  private userIsolation?;
20
20
  private cachedAppUserId?;
21
+ private readonly requestTimeoutMs?;
21
22
  constructor(options: XCiteDBClientOptions);
22
23
  /**
23
- * Create an ephemeral isolated database: calls `POST /api/v1/test/sessions` with your API key or Bearer,
24
+ * Create an ephemeral test database: calls `POST /api/v1/test/sessions` with your API key or Bearer,
24
25
  * then returns a client that sends `X-Test-Session` (auth-free by default).
26
+ * With `opts.overlay === true`, the server stores overlay mode: reads merge the empty `_test/...` LMDB
27
+ * over the current project's production data (read-only base); writes stay under `_test/...` only.
25
28
  */
26
29
  static createTestSession(opts: CreateTestSessionOptions): Promise<XCiteDBClient>;
27
30
  /**
@@ -293,12 +296,34 @@ export declare class XCiteDBClient {
293
296
  * the server (namespace + shared paths). Does not send `X-Prefix`; identifiers in requests are rewritten.
294
297
  */
295
298
  enableUserIsolation(): Promise<UserIsolationConfig>;
299
+ createWorkspace(name: string, fromBranch?: string, fromDate?: string): Promise<void>;
300
+ /** @deprecated Use {@link createWorkspace}. */
296
301
  createBranch(name: string, fromBranch?: string, fromDate?: string): Promise<void>;
302
+ deleteWorkspace(name: string): Promise<void>;
303
+ /** @deprecated Use {@link deleteWorkspace}. */
297
304
  deleteBranch(name: string): Promise<void>;
305
+ deleteWorkspaceRevision(workspace: string, date: string): Promise<void>;
306
+ /** @deprecated Use {@link deleteWorkspaceRevision}. */
298
307
  deleteRevision(branch: string, date: string): Promise<void>;
308
+ listWorkspaces(): Promise<WorkspaceInfo[]>;
309
+ /** @deprecated Use {@link listWorkspaces}. */
299
310
  listBranches(): Promise<BranchInfo[]>;
311
+ getWorkspace(name: string): Promise<WorkspaceInfo>;
312
+ /** @deprecated Use {@link getWorkspace}. */
300
313
  getBranch(name: string): Promise<BranchInfo>;
314
+ createCheckpoint(message: string, author?: string): Promise<CheckpointRecord>;
315
+ /** @deprecated Use {@link createCheckpoint}. */
301
316
  createCommit(message: string, author?: string): Promise<CommitRecord>;
317
+ listCheckpoints(options?: {
318
+ branch?: string;
319
+ limit?: number;
320
+ offset?: number;
321
+ }): Promise<{
322
+ checkpoints: CheckpointRecord[];
323
+ total: number;
324
+ branch: string;
325
+ }>;
326
+ /** @deprecated Use {@link listCheckpoints}. */
302
327
  listCommits(options?: {
303
328
  branch?: string;
304
329
  limit?: number;
@@ -308,13 +333,33 @@ export declare class XCiteDBClient {
308
333
  total: number;
309
334
  branch: string;
310
335
  }>;
336
+ getCheckpoint(checkpointId: string): Promise<CheckpointRecord>;
337
+ /** @deprecated Use {@link getCheckpoint}. */
311
338
  getCommit(commitId: string): Promise<CommitRecord>;
339
+ revertToCheckpoint(checkpointId: string, _confirm?: boolean): Promise<{
340
+ rolled_back_checkpoints: string[];
341
+ rolled_back_commits?: string[];
342
+ current_tip: string;
343
+ }>;
344
+ /** @deprecated Use {@link revertToCheckpoint}. */
312
345
  rollbackToCommit(commitId: string, _confirm?: boolean): Promise<{
313
346
  rolled_back_commits: string[];
314
347
  current_tip: string;
315
348
  }>;
349
+ applyCheckpoint(checkpointId: string, message?: string, author?: string): Promise<CheckpointRecord>;
350
+ /** @deprecated Use {@link applyCheckpoint}. */
316
351
  cherryPick(commitId: string, message?: string, author?: string): Promise<CommitRecord>;
352
+ createBookmark(name: string, checkpointId: string, message?: string, author?: string): Promise<BookmarkRecord>;
353
+ /** @deprecated Use {@link createBookmark}. */
317
354
  createTag(name: string, commitId: string, message?: string, author?: string): Promise<TagRecord>;
355
+ listBookmarks(options?: {
356
+ limit?: number;
357
+ offset?: number;
358
+ }): Promise<{
359
+ bookmarks: BookmarkRecord[];
360
+ total: number;
361
+ }>;
362
+ /** @deprecated Use {@link listBookmarks}. */
318
363
  listTags(options?: {
319
364
  limit?: number;
320
365
  offset?: number;
@@ -322,23 +367,44 @@ export declare class XCiteDBClient {
322
367
  tags: TagRecord[];
323
368
  total: number;
324
369
  }>;
370
+ getBookmark(name: string): Promise<BookmarkRecord>;
371
+ /** @deprecated Use {@link getBookmark}. */
325
372
  getTag(name: string): Promise<TagRecord>;
373
+ deleteBookmark(name: string): Promise<void>;
374
+ /** @deprecated Use {@link deleteBookmark}. */
326
375
  deleteTag(name: string): Promise<void>;
376
+ compare(from: CompareRef, to: CompareRef, includeContent?: boolean): Promise<CompareResult>;
377
+ /** @deprecated Use {@link compare}. */
327
378
  diff(from: DiffRef, to: DiffRef, includeContent?: boolean): Promise<DiffResult>;
379
+ publishWorkspace(targetWorkspace: string, sourceWorkspace: string, options?: {
380
+ message?: string;
381
+ autoResolve?: 'none' | 'source' | 'target';
382
+ }): Promise<PublishResult>;
383
+ /** @deprecated Use {@link publishWorkspace}. */
328
384
  mergeBranch(targetBranch: string, sourceBranch: string, options?: {
329
385
  message?: string;
330
386
  autoResolve?: 'none' | 'source' | 'target';
331
387
  }): Promise<MergeResult>;
332
388
  /**
333
- * Create `branchName` from {@link options.fromBranch} (or current context branch), run `fn` scoped to that branch,
334
- * create a commit, then merge back into the parent branch unless {@link options.autoMerge} is `false`.
335
- * Restores previous {@link DatabaseContext} afterward.
389
+ * Create `workspaceName` from {@link options.fromBranch} (or current context), run `fn` scoped to that workspace,
390
+ * create a checkpoint, then publish back unless {@link options.autoMerge} is `false`.
336
391
  */
392
+ withWorkspace<T>(workspaceName: string, fn: (client: XCiteDBClient) => Promise<T>, options?: {
393
+ message?: string;
394
+ /** When true (default), publish `workspaceName` into the parent workspace after checkpoint. */
395
+ autoMerge?: boolean;
396
+ /** Workspace to fork from (default: current `context.branch` / `context.workspace`, or `""`). */
397
+ fromBranch?: string;
398
+ author?: string;
399
+ }): Promise<{
400
+ result: T;
401
+ checkpoint?: CheckpointRecord;
402
+ publish?: PublishResult;
403
+ }>;
404
+ /** @deprecated Use {@link withWorkspace}. */
337
405
  withBranch<T>(branchName: string, fn: (client: XCiteDBClient) => Promise<T>, options?: {
338
406
  message?: string;
339
- /** When true (default), merge `branchName` into the parent branch after commit. */
340
407
  autoMerge?: boolean;
341
- /** Branch to fork from (default: current `context.branch`, or `""`). */
342
408
  fromBranch?: string;
343
409
  author?: string;
344
410
  }): Promise<{
@@ -421,6 +487,18 @@ export declare class XCiteDBClient {
421
487
  getProjectSearchSettings(): Promise<ProjectSearchSettings>;
422
488
  /** Update project search settings (`PUT /api/v1/project/settings/search`). Returns the same shape as GET. */
423
489
  updateProjectSearchSettings(patch: ProjectSearchSettingsUpdate): Promise<ProjectSearchSettings>;
490
+ /** Per-project `document.conf` override (`GET /api/v1/project/settings/doc-conf`). */
491
+ getProjectDocConf(): Promise<ProjectDocConfResponse>;
492
+ /** Save or clear project `document.conf` (`PUT /api/v1/project/settings/doc-conf`). */
493
+ updateProjectDocConf(body: {
494
+ doc_conf_text: string;
495
+ } | {
496
+ clear: true;
497
+ }): Promise<ProjectDocConfResponse>;
498
+ /** Remove project override; server uses platform default (`DELETE /api/v1/project/settings/doc-conf`). */
499
+ deleteProjectDocConf(): Promise<ProjectDocConfResponse>;
500
+ /** Embedded platform default `document.conf` text (`GET /api/v1/platform/default-doc-conf`). */
501
+ getPlatformDefaultDocConf(): Promise<PlatformDefaultDocConfResponse>;
424
502
  /** Blocking full DB scan (admin; no calls to embedding API). Prefer {@link postVectorIndexEstimateSession} for UI. */
425
503
  getVectorIndexEstimate(): Promise<VectorIndexEstimate>;
426
504
  /** Start background estimate (202); cancel prior session for this tenant. */
package/dist/client.js CHANGED
@@ -18,6 +18,30 @@ function buildQuery(params) {
18
18
  const s = sp.toString();
19
19
  return s ? `?${s}` : '';
20
20
  }
21
+ function warnIfHttpOnTlsPort(baseUrl) {
22
+ try {
23
+ const u = new URL(baseUrl);
24
+ if (u.protocol !== 'http:')
25
+ return;
26
+ if (u.port === '443') {
27
+ if (typeof console !== 'undefined' && typeof console.warn === 'function') {
28
+ console.warn('[@xcitedbs/client] baseUrl uses http: on port 443; use https:// to avoid hangs or TLS errors.');
29
+ }
30
+ }
31
+ }
32
+ catch {
33
+ /* ignore invalid baseUrl */
34
+ }
35
+ }
36
+ /** Uses `AbortSignal.timeout` when the runtime supports it. */
37
+ function requestTimeoutSignal(ms) {
38
+ if (ms === undefined || ms <= 0)
39
+ return undefined;
40
+ const ctor = AbortSignal;
41
+ if (typeof ctor.timeout === 'function')
42
+ return ctor.timeout(ms);
43
+ return undefined;
44
+ }
21
45
  class XCiteDBClient {
22
46
  constructor(options) {
23
47
  this.baseUrl = options.baseUrl.replace(/\/+$/, '');
@@ -34,10 +58,14 @@ class XCiteDBClient {
34
58
  this.testSessionToken = options.testSessionToken;
35
59
  this.testRequireAuth = options.testRequireAuth === true;
36
60
  this.userIsolation = options.userIsolation;
61
+ this.requestTimeoutMs = options.requestTimeoutMs;
62
+ warnIfHttpOnTlsPort(this.baseUrl);
37
63
  }
38
64
  /**
39
- * Create an ephemeral isolated database: calls `POST /api/v1/test/sessions` with your API key or Bearer,
65
+ * Create an ephemeral test database: calls `POST /api/v1/test/sessions` with your API key or Bearer,
40
66
  * then returns a client that sends `X-Test-Session` (auth-free by default).
67
+ * With `opts.overlay === true`, the server stores overlay mode: reads merge the empty `_test/...` LMDB
68
+ * over the current project's production data (read-only base); writes stay under `_test/...` only.
41
69
  */
42
70
  static async createTestSession(opts) {
43
71
  const temp = new XCiteDBClient({
@@ -53,8 +81,9 @@ class XCiteDBClient {
53
81
  onAppUserTokensUpdated: opts.onAppUserTokensUpdated,
54
82
  onSessionInvalid: opts.onSessionInvalid,
55
83
  userIsolation: opts.userIsolation,
84
+ requestTimeoutMs: opts.requestTimeoutMs,
56
85
  });
57
- const data = await temp.request('POST', '/api/v1/test/sessions', undefined, undefined, { no401Retry: true });
86
+ const data = await temp.request('POST', '/api/v1/test/sessions', opts.overlay === true ? { overlay: true } : undefined, undefined, { no401Retry: true });
58
87
  return new XCiteDBClient({
59
88
  baseUrl: opts.baseUrl,
60
89
  apiKey: opts.testRequireAuth ? opts.apiKey : undefined,
@@ -70,6 +99,7 @@ class XCiteDBClient {
70
99
  testSessionToken: data.session_token,
71
100
  testRequireAuth: opts.testRequireAuth,
72
101
  userIsolation: opts.userIsolation,
102
+ requestTimeoutMs: opts.requestTimeoutMs,
73
103
  });
74
104
  }
75
105
  /**
@@ -345,7 +375,11 @@ class XCiteDBClient {
345
375
  this.projectId = projectId;
346
376
  }
347
377
  setContext(ctx) {
348
- this.defaultContext = { ...this.defaultContext, ...ctx };
378
+ const next = { ...this.defaultContext, ...ctx };
379
+ if (ctx.workspace !== undefined) {
380
+ next.branch = ctx.workspace;
381
+ }
382
+ this.defaultContext = next;
349
383
  }
350
384
  setTokens(access, refresh) {
351
385
  this.accessToken = access;
@@ -367,8 +401,9 @@ class XCiteDBClient {
367
401
  contextHeaders() {
368
402
  const h = {};
369
403
  const c = this.defaultContext;
370
- if (c.branch)
371
- h['X-Branch'] = c.branch;
404
+ const ws = c.workspace ?? c.branch;
405
+ if (ws)
406
+ h['X-Workspace'] = ws;
372
407
  if (c.date)
373
408
  h['X-Date'] = c.date;
374
409
  if (c.prefix)
@@ -439,6 +474,9 @@ class XCiteDBClient {
439
474
  init.body = JSON.stringify(body);
440
475
  }
441
476
  }
477
+ const sig = requestTimeoutSignal(this.requestTimeoutMs);
478
+ if (sig)
479
+ init.signal = sig;
442
480
  const res = await fetch(url, init);
443
481
  const text = await res.text();
444
482
  let data;
@@ -941,121 +979,202 @@ class XCiteDBClient {
941
979
  }
942
980
  return cfg;
943
981
  }
944
- async createBranch(name, fromBranch, fromDate) {
982
+ async createWorkspace(name, fromBranch, fromDate) {
945
983
  const body = { name };
946
984
  if (fromBranch)
947
985
  body.from_branch = fromBranch;
948
986
  if (fromDate)
949
987
  body.from_date = fromDate;
950
- await this.request('POST', '/api/v1/branches', body);
988
+ await this.request('POST', '/api/v1/workspaces', body);
951
989
  }
990
+ /** @deprecated Use {@link createWorkspace}. */
991
+ async createBranch(name, fromBranch, fromDate) {
992
+ return this.createWorkspace(name, fromBranch, fromDate);
993
+ }
994
+ async deleteWorkspace(name) {
995
+ await this.request('DELETE', `/api/v1/workspaces/${encodeURIComponent(name)}`);
996
+ }
997
+ /** @deprecated Use {@link deleteWorkspace}. */
952
998
  async deleteBranch(name) {
953
- await this.request('DELETE', `/api/v1/branches/${encodeURIComponent(name)}`);
999
+ return this.deleteWorkspace(name);
1000
+ }
1001
+ async deleteWorkspaceRevision(workspace, date) {
1002
+ await this.request('DELETE', `/api/v1/workspaces/${encodeURIComponent(workspace)}/revisions/${encodeURIComponent(date)}`);
954
1003
  }
1004
+ /** @deprecated Use {@link deleteWorkspaceRevision}. */
955
1005
  async deleteRevision(branch, date) {
956
- await this.request('DELETE', `/api/v1/branches/${encodeURIComponent(branch)}/revisions/${encodeURIComponent(date)}`);
1006
+ return this.deleteWorkspaceRevision(branch, date);
957
1007
  }
1008
+ async listWorkspaces() {
1009
+ const r = await this.request('GET', '/api/v1/workspaces');
1010
+ return r.workspaces ?? r.branches ?? [];
1011
+ }
1012
+ /** @deprecated Use {@link listWorkspaces}. */
958
1013
  async listBranches() {
959
- const r = await this.request('GET', '/api/v1/branches');
960
- return r.branches ?? [];
1014
+ return this.listWorkspaces();
1015
+ }
1016
+ async getWorkspace(name) {
1017
+ const r = await this.request('GET', `/api/v1/workspaces/${encodeURIComponent(name)}`);
1018
+ return (r.workspace ?? r.branch);
961
1019
  }
1020
+ /** @deprecated Use {@link getWorkspace}. */
962
1021
  async getBranch(name) {
963
- const r = await this.request('GET', `/api/v1/branches/${encodeURIComponent(name)}`);
964
- return r.branch;
1022
+ return this.getWorkspace(name);
965
1023
  }
966
- async createCommit(message, author) {
1024
+ async createCheckpoint(message, author) {
967
1025
  const body = { message };
968
1026
  if (author)
969
1027
  body.author = author;
970
- const r = await this.request('POST', '/api/v1/commits', body);
971
- return r.commit;
1028
+ const r = await this.request('POST', '/api/v1/checkpoints', body);
1029
+ return (r.checkpoint ?? r.commit);
972
1030
  }
973
- async listCommits(options) {
1031
+ /** @deprecated Use {@link createCheckpoint}. */
1032
+ async createCommit(message, author) {
1033
+ return this.createCheckpoint(message, author);
1034
+ }
1035
+ async listCheckpoints(options) {
974
1036
  const q = buildQuery({
975
1037
  branch: options?.branch,
976
1038
  limit: options?.limit,
977
1039
  offset: options?.offset,
978
1040
  });
979
- return this.request('GET', `/api/v1/commits${q}`);
1041
+ const r = await this.request('GET', `/api/v1/checkpoints${q}`);
1042
+ const list = r.checkpoints ?? r.commits ?? [];
1043
+ return { checkpoints: list, total: r.total, branch: r.branch };
1044
+ }
1045
+ /** @deprecated Use {@link listCheckpoints}. */
1046
+ async listCommits(options) {
1047
+ const r = await this.listCheckpoints(options);
1048
+ return { commits: r.checkpoints, total: r.total, branch: r.branch };
1049
+ }
1050
+ async getCheckpoint(checkpointId) {
1051
+ const r = await this.request('GET', `/api/v1/checkpoints/${encodeURIComponent(checkpointId)}`);
1052
+ return (r.checkpoint ?? r.commit);
980
1053
  }
1054
+ /** @deprecated Use {@link getCheckpoint}. */
981
1055
  async getCommit(commitId) {
982
- const r = await this.request('GET', `/api/v1/commits/${encodeURIComponent(commitId)}`);
983
- return r.commit;
1056
+ return this.getCheckpoint(commitId);
984
1057
  }
985
- async rollbackToCommit(commitId, _confirm) {
986
- return this.request('POST', `/api/v1/commits/${encodeURIComponent(commitId)}/rollback`, {
1058
+ async revertToCheckpoint(checkpointId, _confirm) {
1059
+ return this.request('POST', `/api/v1/checkpoints/${encodeURIComponent(checkpointId)}/revert`, {
987
1060
  confirm: true,
988
1061
  });
989
1062
  }
990
- async cherryPick(commitId, message, author) {
1063
+ /** @deprecated Use {@link revertToCheckpoint}. */
1064
+ async rollbackToCommit(commitId, _confirm) {
1065
+ const r = await this.revertToCheckpoint(commitId, _confirm);
1066
+ return {
1067
+ rolled_back_commits: r.rolled_back_commits ?? r.rolled_back_checkpoints,
1068
+ current_tip: r.current_tip,
1069
+ };
1070
+ }
1071
+ async applyCheckpoint(checkpointId, message, author) {
991
1072
  const body = {};
992
1073
  if (message)
993
1074
  body.message = message;
994
1075
  if (author)
995
1076
  body.author = author;
996
- const r = await this.request('POST', `/api/v1/commits/${encodeURIComponent(commitId)}/cherry-pick`, body);
997
- return r.commit;
1077
+ const r = await this.request('POST', `/api/v1/checkpoints/${encodeURIComponent(checkpointId)}/apply`, body);
1078
+ return (r.checkpoint ?? r.commit);
998
1079
  }
999
- async createTag(name, commitId, message, author) {
1000
- const body = { name, commit_id: commitId };
1080
+ /** @deprecated Use {@link applyCheckpoint}. */
1081
+ async cherryPick(commitId, message, author) {
1082
+ return this.applyCheckpoint(commitId, message, author);
1083
+ }
1084
+ async createBookmark(name, checkpointId, message, author) {
1085
+ const body = { name, checkpoint_id: checkpointId };
1001
1086
  if (message)
1002
1087
  body.message = message;
1003
1088
  if (author)
1004
1089
  body.author = author;
1005
- const r = await this.request('POST', '/api/v1/tags', body);
1006
- return r.tag;
1090
+ const r = await this.request('POST', '/api/v1/bookmarks', body);
1091
+ return (r.bookmark ?? r.tag);
1007
1092
  }
1008
- async listTags(options) {
1093
+ /** @deprecated Use {@link createBookmark}. */
1094
+ async createTag(name, commitId, message, author) {
1095
+ return this.createBookmark(name, commitId, message, author);
1096
+ }
1097
+ async listBookmarks(options) {
1009
1098
  const q = buildQuery({ limit: options?.limit, offset: options?.offset });
1010
- return this.request('GET', `/api/v1/tags${q}`);
1099
+ const r = await this.request('GET', `/api/v1/bookmarks${q}`);
1100
+ const list = r.bookmarks ?? r.tags ?? [];
1101
+ return { bookmarks: list, total: r.total };
1011
1102
  }
1103
+ /** @deprecated Use {@link listBookmarks}. */
1104
+ async listTags(options) {
1105
+ const r = await this.listBookmarks(options);
1106
+ return { tags: r.bookmarks, total: r.total };
1107
+ }
1108
+ async getBookmark(name) {
1109
+ const r = await this.request('GET', `/api/v1/bookmarks/${encodeURIComponent(name)}`);
1110
+ return (r.bookmark ?? r.tag);
1111
+ }
1112
+ /** @deprecated Use {@link getBookmark}. */
1012
1113
  async getTag(name) {
1013
- const r = await this.request('GET', `/api/v1/tags/${encodeURIComponent(name)}`);
1014
- return r.tag;
1114
+ return this.getBookmark(name);
1115
+ }
1116
+ async deleteBookmark(name) {
1117
+ await this.request('DELETE', `/api/v1/bookmarks/${encodeURIComponent(name)}`);
1015
1118
  }
1119
+ /** @deprecated Use {@link deleteBookmark}. */
1016
1120
  async deleteTag(name) {
1017
- await this.request('DELETE', `/api/v1/tags/${encodeURIComponent(name)}`);
1121
+ return this.deleteBookmark(name);
1018
1122
  }
1019
- async diff(from, to, includeContent) {
1020
- return this.request('POST', '/api/v1/diff', {
1123
+ async compare(from, to, includeContent) {
1124
+ return this.request('POST', '/api/v1/compare', {
1021
1125
  from,
1022
1126
  to,
1023
1127
  include_content: includeContent ?? false,
1024
1128
  });
1025
1129
  }
1026
- async mergeBranch(targetBranch, sourceBranch, options) {
1027
- const body = { source_branch: sourceBranch };
1130
+ /** @deprecated Use {@link compare}. */
1131
+ async diff(from, to, includeContent) {
1132
+ return this.compare(from, to, includeContent);
1133
+ }
1134
+ async publishWorkspace(targetWorkspace, sourceWorkspace, options) {
1135
+ const body = {
1136
+ source_workspace: sourceWorkspace,
1137
+ source_branch: sourceWorkspace,
1138
+ };
1028
1139
  if (options?.message)
1029
1140
  body.message = options.message;
1030
1141
  body.auto_resolve = options?.autoResolve ?? 'none';
1031
- return this.request('POST', `/api/v1/branches/${encodeURIComponent(targetBranch)}/merge`, body);
1142
+ return this.request('POST', `/api/v1/workspaces/${encodeURIComponent(targetWorkspace)}/publish`, body);
1143
+ }
1144
+ /** @deprecated Use {@link publishWorkspace}. */
1145
+ async mergeBranch(targetBranch, sourceBranch, options) {
1146
+ return this.publishWorkspace(targetBranch, sourceBranch, options);
1032
1147
  }
1033
1148
  /**
1034
- * Create `branchName` from {@link options.fromBranch} (or current context branch), run `fn` scoped to that branch,
1035
- * create a commit, then merge back into the parent branch unless {@link options.autoMerge} is `false`.
1036
- * Restores previous {@link DatabaseContext} afterward.
1149
+ * Create `workspaceName` from {@link options.fromBranch} (or current context), run `fn` scoped to that workspace,
1150
+ * create a checkpoint, then publish back unless {@link options.autoMerge} is `false`.
1037
1151
  */
1038
- async withBranch(branchName, fn, options) {
1152
+ async withWorkspace(workspaceName, fn, options) {
1039
1153
  const prev = { ...this.defaultContext };
1040
- const fromBranch = options?.fromBranch ?? prev.branch ?? '';
1041
- let commit;
1042
- let merge;
1154
+ const fromWs = options?.fromBranch ?? prev.branch ?? prev.workspace ?? '';
1155
+ let checkpoint;
1156
+ let publish;
1043
1157
  try {
1044
- await this.createBranch(branchName, fromBranch || undefined, prev.date || undefined);
1045
- this.setContext({ branch: branchName });
1158
+ await this.createWorkspace(workspaceName, fromWs || undefined, prev.date || undefined);
1159
+ this.setContext({ workspace: workspaceName, branch: workspaceName });
1046
1160
  const result = await fn(this);
1047
- commit = await this.createCommit(options?.message ?? `Branch ${branchName}`, options?.author);
1161
+ checkpoint = await this.createCheckpoint(options?.message ?? `Workspace ${workspaceName}`, options?.author);
1048
1162
  if (options?.autoMerge !== false) {
1049
- merge = await this.mergeBranch(fromBranch, branchName, {
1163
+ publish = await this.publishWorkspace(fromWs, workspaceName, {
1050
1164
  message: options?.message,
1051
1165
  });
1052
1166
  }
1053
- return { result, commit, merge };
1167
+ return { result, checkpoint, publish };
1054
1168
  }
1055
1169
  finally {
1056
1170
  this.setContext(prev);
1057
1171
  }
1058
1172
  }
1173
+ /** @deprecated Use {@link withWorkspace}. */
1174
+ async withBranch(branchName, fn, options) {
1175
+ const r = await this.withWorkspace(branchName, fn, options);
1176
+ return { result: r.result, commit: r.checkpoint, merge: r.publish };
1177
+ }
1059
1178
  /** Send raw XML body (`Content-Type: application/xml`). For JSON wrapper + options use `writeXmlDocument`. */
1060
1179
  async writeXML(xml, _options) {
1061
1180
  const payload = this.isoApplyXmlDbIdentifier(xml);
@@ -1324,12 +1443,18 @@ class XCiteDBClient {
1324
1443
  body.offset = q.offset;
1325
1444
  if (q.limit !== undefined)
1326
1445
  body.limit = q.limit;
1327
- if (q.mode)
1446
+ if (q.mode !== undefined)
1328
1447
  body.mode = q.mode;
1329
1448
  if (q.min_score !== undefined)
1330
1449
  body.min_score = q.min_score;
1331
1450
  if (q.semantic_weight !== undefined)
1332
1451
  body.semantic_weight = q.semantic_weight;
1452
+ if (q.at_date !== undefined && q.at_date !== '')
1453
+ body.at_date = q.at_date;
1454
+ if (q.date_from !== undefined && q.date_from !== '')
1455
+ body.date_from = q.date_from;
1456
+ if (q.date_to !== undefined && q.date_to !== '')
1457
+ body.date_to = q.date_to;
1333
1458
  const data = await this.request('POST', '/api/v1/search', body);
1334
1459
  const hits = [];
1335
1460
  if (Array.isArray(data.hits)) {
@@ -1350,6 +1475,12 @@ class XCiteDBClient {
1350
1475
  if (o.source === 'fts' || o.source === 'semantic' || o.source === 'both') {
1351
1476
  hit.source = o.source;
1352
1477
  }
1478
+ if (typeof o.valid_from === 'string' && o.valid_from.length > 0) {
1479
+ hit.valid_from = o.valid_from;
1480
+ }
1481
+ if (typeof o.valid_to === 'string' && o.valid_to.length > 0) {
1482
+ hit.valid_to = o.valid_to;
1483
+ }
1353
1484
  hits.push(hit);
1354
1485
  }
1355
1486
  }
@@ -1374,6 +1505,22 @@ class XCiteDBClient {
1374
1505
  async updateProjectSearchSettings(patch) {
1375
1506
  return this.request('PUT', '/api/v1/project/settings/search', patch);
1376
1507
  }
1508
+ /** Per-project `document.conf` override (`GET /api/v1/project/settings/doc-conf`). */
1509
+ async getProjectDocConf() {
1510
+ return this.request('GET', '/api/v1/project/settings/doc-conf');
1511
+ }
1512
+ /** Save or clear project `document.conf` (`PUT /api/v1/project/settings/doc-conf`). */
1513
+ async updateProjectDocConf(body) {
1514
+ return this.request('PUT', '/api/v1/project/settings/doc-conf', body);
1515
+ }
1516
+ /** Remove project override; server uses platform default (`DELETE /api/v1/project/settings/doc-conf`). */
1517
+ async deleteProjectDocConf() {
1518
+ return this.request('DELETE', '/api/v1/project/settings/doc-conf');
1519
+ }
1520
+ /** Embedded platform default `document.conf` text (`GET /api/v1/platform/default-doc-conf`). */
1521
+ async getPlatformDefaultDocConf() {
1522
+ return this.request('GET', '/api/v1/platform/default-doc-conf');
1523
+ }
1377
1524
  /** Blocking full DB scan (admin; no calls to embedding API). Prefer {@link postVectorIndexEstimateSession} for UI. */
1378
1525
  async getVectorIndexEstimate() {
1379
1526
  return this.request('GET', '/api/v1/project/settings/search/vector-index-estimate', undefined);
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { XCiteDBClient } from './client';
2
2
  export { WebSocketSubscription } from './websocket';
3
- export type { AccessCheckResult, ApiKeyInfo, AppAuthConfig, AppEmailConfig, AppEmailSmtpConfig, AppEmailTemplateEntry, AppEmailTemplates, AppEmailWebhookConfig, AppUser, AppUserTokenPair, EmailTestResponse, ForgotPasswordResponse, SendVerificationResponse, DatabaseContext, Flags, JsonDocumentData, IdentifierChildNode, ListIdentifierChildrenResult, ListIdentifiersResult, LockInfo, OAuthProviderInfo, OAuthProvidersResponse, OwnedTenantInfo, ProjectInfo, PlatformRegistrationConfig, PlatformWorkspaceOrg, PlatformWorkspacesResponse, ProjectSearchSettings, ProjectSearchSettingsUpdate, LogEntry, MetaValue, PlatformRegisterResult, PolicyUpdateResponse, PolicyConditions, PolicyIdentifierPattern, PolicyResources, PolicySubjectInput, PolicySubjects, RagQueryOptions, RagQueryResult, RagStreamEvent, RealtimeEvent, SearchIndexingProgress, SecurityConfig, SecurityPolicy, StoredPolicyResponse, StoredTriggerResponse, SubscriptionOptions, TextSearchHit, TextSearchQuery, TextSearchResult, TriggerDefinition, TokenPair, UserInfo, UserIsolationConfig, UserIsolationOptions, WriteDocumentOptions, CreateTestSessionOptions, XCiteDBClientOptions, XCiteDBJwtClaims, UnqueryResult, UnqueryTemplate, XCiteQuery, } from './types';
3
+ export type { AccessCheckResult, ApiKeyInfo, AppAuthConfig, AppEmailConfig, AppEmailSmtpConfig, AppEmailTemplateEntry, AppEmailTemplates, AppEmailWebhookConfig, AppUser, AppUserTokenPair, EmailTestResponse, ForgotPasswordResponse, SendVerificationResponse, BookmarkRecord, BranchInfo, BranchListItem, CheckpointRecord, CommitRecord, CompareEntry, CompareRef, CompareResult, DatabaseContext, DiffEntry, DiffRef, DiffResult, Flags, JsonDocumentData, IdentifierChildNode, ListIdentifierChildrenResult, ListIdentifiersResult, LockInfo, MergeConflict, MergeResult, OAuthProviderInfo, OAuthProvidersResponse, OwnedTenantInfo, ProjectInfo, PlatformRegistrationConfig, PlatformWorkspaceOrg, PlatformWorkspacesResponse, ProjectSearchSettings, ProjectSearchSettingsUpdate, ProjectDocConfResponse, PlatformDefaultDocConfResponse, LogEntry, MetaValue, PlatformRegisterResult, PolicyUpdateResponse, PublishConflict, PublishResult, PolicyConditions, PolicyIdentifierPattern, PolicyResources, PolicySubjectInput, PolicySubjects, RagQueryOptions, RagQueryResult, RagStreamEvent, RealtimeEvent, SearchIndexingProgress, SecurityConfig, SecurityPolicy, StoredPolicyResponse, StoredTriggerResponse, SubscriptionOptions, TagRecord, TextSearchHit, TextSearchQuery, TextSearchResult, TriggerDefinition, TokenPair, UserInfo, UserIsolationConfig, UserIsolationOptions, WorkspaceInfo, WriteDocumentOptions, CreateTestSessionOptions, XCiteDBClientOptions, XCiteDBJwtClaims, UnqueryResult, UnqueryTemplate, XCiteQuery, } from './types';
4
4
  export { XCiteDBError } from './types';