@xcitedbs/client 0.1.0
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 +53 -0
- package/dist/client.d.ts +211 -0
- package/dist/client.js +894 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +9 -0
- package/dist/types.d.ts +421 -0
- package/dist/types.js +12 -0
- package/dist/websocket.d.ts +27 -0
- package/dist/websocket.js +93 -0
- package/package.json +43 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { XCiteDBClient } from './client';
|
|
2
|
+
export { WebSocketSubscription } from './websocket';
|
|
3
|
+
export type { AccessCheckResult, ApiKeyInfo, AppAuthConfig, AppEmailConfig, AppEmailSmtpConfig, AppEmailTemplateEntry, AppEmailTemplates, AppEmailWebhookConfig, AppUser, AppUserTokenPair, EmailTestResponse, ForgotPasswordResponse, SendVerificationResponse, DatabaseContext, Flags, IdentifierChildNode, ListIdentifierChildrenResult, ListIdentifiersResult, LockInfo, OAuthProviderInfo, OAuthProvidersResponse, OwnedTenantInfo, PlatformRegistrationConfig, PlatformWorkspaceOrg, PlatformWorkspacesResponse, LogEntry, PolicyUpdateResponse, PolicyConditions, PolicyIdentifierPattern, PolicyResources, PolicySubjectInput, PolicySubjects, RealtimeEvent, SecurityConfig, SecurityPolicy, StoredPolicyResponse, StoredTriggerResponse, SubscriptionOptions, TextSearchHit, TextSearchQuery, TextSearchResult, TriggerDefinition, TokenPair, UserInfo, WriteDocumentOptions, XCiteDBClientOptions, XCiteQuery, } from './types';
|
|
4
|
+
export { XCiteDBError } from './types';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.XCiteDBError = exports.WebSocketSubscription = exports.XCiteDBClient = void 0;
|
|
4
|
+
var client_1 = require("./client");
|
|
5
|
+
Object.defineProperty(exports, "XCiteDBClient", { enumerable: true, get: function () { return client_1.XCiteDBClient; } });
|
|
6
|
+
var websocket_1 = require("./websocket");
|
|
7
|
+
Object.defineProperty(exports, "WebSocketSubscription", { enumerable: true, get: function () { return websocket_1.WebSocketSubscription; } });
|
|
8
|
+
var types_1 = require("./types");
|
|
9
|
+
Object.defineProperty(exports, "XCiteDBError", { enumerable: true, get: function () { return types_1.XCiteDBError; } });
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
/** Query filters for XCiteDB document APIs */
|
|
2
|
+
export interface XCiteQuery {
|
|
3
|
+
match?: string;
|
|
4
|
+
match_start?: string;
|
|
5
|
+
match_end?: string;
|
|
6
|
+
contains?: string | string[];
|
|
7
|
+
regex?: string;
|
|
8
|
+
/** Restrict to documents that have all of these JSON meta paths (AND). */
|
|
9
|
+
required_meta_paths?: string[];
|
|
10
|
+
/** Restrict to documents that have (or had) indexed meta (meta_path_docs sentinel). */
|
|
11
|
+
filter_any_meta?: boolean;
|
|
12
|
+
/** Max rows to return (server default 500, max 10000). */
|
|
13
|
+
limit?: number;
|
|
14
|
+
/** Skip this many rows (for pagination). */
|
|
15
|
+
offset?: number;
|
|
16
|
+
}
|
|
17
|
+
/** Full-text search (`POST /api/v1/search`) */
|
|
18
|
+
export interface TextSearchQuery {
|
|
19
|
+
query: string;
|
|
20
|
+
doc_types?: ('xml' | 'json')[];
|
|
21
|
+
branch?: string;
|
|
22
|
+
offset?: number;
|
|
23
|
+
limit?: number;
|
|
24
|
+
}
|
|
25
|
+
export interface TextSearchHit {
|
|
26
|
+
identifier: string;
|
|
27
|
+
/** Canonical db:xcitepath for XML hits; omitted or empty for JSON. */
|
|
28
|
+
xcitepath?: string;
|
|
29
|
+
path: string;
|
|
30
|
+
doc_type: 'xml' | 'json';
|
|
31
|
+
branch: string;
|
|
32
|
+
snippet: string;
|
|
33
|
+
score: number;
|
|
34
|
+
}
|
|
35
|
+
export interface TextSearchResult {
|
|
36
|
+
hits: TextSearchHit[];
|
|
37
|
+
total: number;
|
|
38
|
+
query: string;
|
|
39
|
+
}
|
|
40
|
+
/** Response from `GET /api/v1/documents/identifiers` */
|
|
41
|
+
export interface ListIdentifiersResult {
|
|
42
|
+
identifiers: string[];
|
|
43
|
+
total: number;
|
|
44
|
+
offset: number;
|
|
45
|
+
limit: number;
|
|
46
|
+
}
|
|
47
|
+
/** One row from `GET /api/v1/documents/identifier-children` */
|
|
48
|
+
export interface IdentifierChildNode {
|
|
49
|
+
segment: string;
|
|
50
|
+
full_path: string;
|
|
51
|
+
is_identifier: boolean;
|
|
52
|
+
has_children: boolean;
|
|
53
|
+
}
|
|
54
|
+
/** Response from `GET /api/v1/documents/identifier-children` */
|
|
55
|
+
export interface ListIdentifierChildrenResult {
|
|
56
|
+
parent_path: string;
|
|
57
|
+
/** True when `parent_path` is non-empty and names an existing identifier (for “(this path)” in the tree). */
|
|
58
|
+
parent_is_identifier: boolean;
|
|
59
|
+
hierarchy_index_available: boolean;
|
|
60
|
+
children: IdentifierChildNode[];
|
|
61
|
+
}
|
|
62
|
+
export interface LogEntry {
|
|
63
|
+
identifier: string;
|
|
64
|
+
branch: string;
|
|
65
|
+
date: string;
|
|
66
|
+
action: string;
|
|
67
|
+
}
|
|
68
|
+
export interface LockInfo {
|
|
69
|
+
lock_id: string;
|
|
70
|
+
identifier: string;
|
|
71
|
+
time: number;
|
|
72
|
+
expiration: number;
|
|
73
|
+
branch: string;
|
|
74
|
+
}
|
|
75
|
+
export interface TokenPair {
|
|
76
|
+
access_token: string;
|
|
77
|
+
refresh_token: string;
|
|
78
|
+
expires_in: number;
|
|
79
|
+
}
|
|
80
|
+
/** Projects from `GET /api/v1/platform/auth/workspaces` (mapped for compatibility). */
|
|
81
|
+
export interface OwnedTenantInfo {
|
|
82
|
+
tenant_id: string;
|
|
83
|
+
org_id?: string;
|
|
84
|
+
name: string;
|
|
85
|
+
status: string;
|
|
86
|
+
created_at: string;
|
|
87
|
+
updated_at?: string;
|
|
88
|
+
config?: unknown;
|
|
89
|
+
owner_user_id?: string;
|
|
90
|
+
}
|
|
91
|
+
export interface UserInfo {
|
|
92
|
+
user_id: string;
|
|
93
|
+
username: string;
|
|
94
|
+
tenant_id: string;
|
|
95
|
+
role: string;
|
|
96
|
+
email?: string;
|
|
97
|
+
org_id?: string;
|
|
98
|
+
org_role?: string;
|
|
99
|
+
auth_user_type?: string;
|
|
100
|
+
/** Present for `/api/v1/platform/auth/me` (console / platform JWT). */
|
|
101
|
+
display_name?: string;
|
|
102
|
+
groups?: string[];
|
|
103
|
+
status?: string;
|
|
104
|
+
current_project_id?: string;
|
|
105
|
+
}
|
|
106
|
+
/** `GET /api/v1/platform/auth/registration-config` */
|
|
107
|
+
export interface PlatformRegistrationConfig {
|
|
108
|
+
registration_policy: string;
|
|
109
|
+
organization_mode: string;
|
|
110
|
+
require_email_verification: boolean;
|
|
111
|
+
}
|
|
112
|
+
/** `GET /api/v1/platform/auth/workspaces` */
|
|
113
|
+
export interface PlatformWorkspaceOrg {
|
|
114
|
+
org_id: string;
|
|
115
|
+
name: string;
|
|
116
|
+
slug: string;
|
|
117
|
+
}
|
|
118
|
+
export interface PlatformWorkspacesResponse {
|
|
119
|
+
orgs: PlatformWorkspaceOrg[];
|
|
120
|
+
projects: OwnedTenantInfo[];
|
|
121
|
+
}
|
|
122
|
+
/** One row from `GET /api/v1/project/keys` (secret is never returned). */
|
|
123
|
+
export interface ApiKeyInfo {
|
|
124
|
+
key_id: string;
|
|
125
|
+
name: string;
|
|
126
|
+
prefix: string;
|
|
127
|
+
expires_at: number;
|
|
128
|
+
/** `secret` = server-side full access; `public` = client-safe, restricted. */
|
|
129
|
+
key_type?: 'secret' | 'public';
|
|
130
|
+
}
|
|
131
|
+
export type Flags = 'None' | 'FirstMatch' | 'IncludeChildren' | 'NoChildren' | 'KeepIndexNodes' | 'PrevIfDeleted' | string;
|
|
132
|
+
export interface DatabaseContext {
|
|
133
|
+
branch?: string;
|
|
134
|
+
date?: string;
|
|
135
|
+
prefix?: string;
|
|
136
|
+
/** Project/tenant id; sent as `tenant_id` in app-user public auth bodies when no developer token is used. */
|
|
137
|
+
tenant_id?: string;
|
|
138
|
+
}
|
|
139
|
+
export interface WriteDocumentOptions {
|
|
140
|
+
is_top?: boolean;
|
|
141
|
+
compare_attributes?: boolean;
|
|
142
|
+
}
|
|
143
|
+
export interface SubscriptionOptions {
|
|
144
|
+
pattern: string;
|
|
145
|
+
event_type?: string;
|
|
146
|
+
}
|
|
147
|
+
export interface RealtimeEvent {
|
|
148
|
+
event: string;
|
|
149
|
+
identifier?: string;
|
|
150
|
+
branch?: string;
|
|
151
|
+
date?: string;
|
|
152
|
+
timestamp?: number;
|
|
153
|
+
tenant_id?: string;
|
|
154
|
+
}
|
|
155
|
+
export interface XCiteDBClientOptions {
|
|
156
|
+
baseUrl: string;
|
|
157
|
+
apiKey?: string;
|
|
158
|
+
accessToken?: string;
|
|
159
|
+
/** Optional end-user JWT; combined with developer `accessToken`/`apiKey` as `X-App-User-Token`, or alone as `Authorization` Bearer. */
|
|
160
|
+
appUserAccessToken?: string;
|
|
161
|
+
appUserRefreshToken?: string;
|
|
162
|
+
context?: DatabaseContext;
|
|
163
|
+
/** When true, sends `X-Project-Id` for console requests; developer JWTs are always platform tokens. */
|
|
164
|
+
platformConsole?: boolean;
|
|
165
|
+
/** Active project id for platform console requests (`X-Project-Id` header). */
|
|
166
|
+
projectId?: string;
|
|
167
|
+
/** Persist developer session tokens after refresh (e.g. localStorage). */
|
|
168
|
+
onSessionTokensUpdated?: (pair: TokenPair) => void;
|
|
169
|
+
/** Persist app-user tokens after refresh. */
|
|
170
|
+
onAppUserTokensUpdated?: (pair: AppUserTokenPair) => void;
|
|
171
|
+
/**
|
|
172
|
+
* Called when a request returns 401 and refresh (if any) could not recover the session.
|
|
173
|
+
* Use to clear stored credentials and redirect to sign-in. Not invoked for login/register-style paths.
|
|
174
|
+
*/
|
|
175
|
+
onSessionInvalid?: () => void;
|
|
176
|
+
}
|
|
177
|
+
/** Application user (tenant-scoped), distinct from developer users. */
|
|
178
|
+
export interface AppUser {
|
|
179
|
+
user_id: string;
|
|
180
|
+
email: string;
|
|
181
|
+
display_name: string;
|
|
182
|
+
groups: string[];
|
|
183
|
+
attributes: Record<string, unknown>;
|
|
184
|
+
status: 'active' | 'disabled' | 'pending_verification';
|
|
185
|
+
created_at: number;
|
|
186
|
+
updated_at: number;
|
|
187
|
+
}
|
|
188
|
+
export interface AppUserTokenPair {
|
|
189
|
+
access_token: string;
|
|
190
|
+
refresh_token: string;
|
|
191
|
+
expires_in: number;
|
|
192
|
+
user?: AppUser;
|
|
193
|
+
}
|
|
194
|
+
/** `GET /api/v1/app/auth/oauth/providers` */
|
|
195
|
+
export interface OAuthProviderInfo {
|
|
196
|
+
id: string;
|
|
197
|
+
display_name: string;
|
|
198
|
+
}
|
|
199
|
+
export interface OAuthProvidersResponse {
|
|
200
|
+
providers: OAuthProviderInfo[];
|
|
201
|
+
}
|
|
202
|
+
/** Read-only effective `auth.app_users` (GET /api/v1/app/auth/config). */
|
|
203
|
+
export interface AppAuthConfig {
|
|
204
|
+
enabled: boolean;
|
|
205
|
+
registration_enabled: boolean;
|
|
206
|
+
default_groups: string[];
|
|
207
|
+
require_email_verification: boolean;
|
|
208
|
+
min_password_length: number;
|
|
209
|
+
max_login_attempts: number;
|
|
210
|
+
lockout_duration_seconds: number;
|
|
211
|
+
access_token_expiry_seconds: number;
|
|
212
|
+
refresh_token_expiry_seconds: number;
|
|
213
|
+
reset_token_expiry_seconds: number;
|
|
214
|
+
verification_token_expiry_seconds: number;
|
|
215
|
+
jwt_algorithm: string;
|
|
216
|
+
public_base_url: string;
|
|
217
|
+
}
|
|
218
|
+
export interface AppEmailSmtpConfig {
|
|
219
|
+
host: string;
|
|
220
|
+
port: number;
|
|
221
|
+
username: string;
|
|
222
|
+
/** Masked as `***` on GET when set; send `***` or empty on PUT to keep previous. */
|
|
223
|
+
password: string;
|
|
224
|
+
encryption: string;
|
|
225
|
+
}
|
|
226
|
+
export interface AppEmailWebhookConfig {
|
|
227
|
+
url: string;
|
|
228
|
+
secret: string;
|
|
229
|
+
headers: Record<string, string>;
|
|
230
|
+
}
|
|
231
|
+
/** Effective per-tenant email delivery (merged with server config). */
|
|
232
|
+
export interface AppEmailConfig {
|
|
233
|
+
delivery_mode: 'none' | 'smtp' | 'webhook' | string;
|
|
234
|
+
from_email: string;
|
|
235
|
+
from_name: string;
|
|
236
|
+
app_name: string;
|
|
237
|
+
base_url: string;
|
|
238
|
+
reset_path: string;
|
|
239
|
+
verify_path: string;
|
|
240
|
+
smtp: AppEmailSmtpConfig;
|
|
241
|
+
webhook: AppEmailWebhookConfig;
|
|
242
|
+
}
|
|
243
|
+
export interface AppEmailTemplateEntry {
|
|
244
|
+
subject: string;
|
|
245
|
+
html: string;
|
|
246
|
+
text: string;
|
|
247
|
+
}
|
|
248
|
+
export interface AppEmailTemplates {
|
|
249
|
+
password_reset?: AppEmailTemplateEntry;
|
|
250
|
+
email_verification?: AppEmailTemplateEntry;
|
|
251
|
+
}
|
|
252
|
+
export interface ForgotPasswordResponse {
|
|
253
|
+
delivery: string;
|
|
254
|
+
reset_token?: string;
|
|
255
|
+
mail_error?: string;
|
|
256
|
+
}
|
|
257
|
+
export interface SendVerificationResponse {
|
|
258
|
+
delivery: string;
|
|
259
|
+
verification_token?: string;
|
|
260
|
+
mail_error?: string;
|
|
261
|
+
}
|
|
262
|
+
export interface EmailTestResponse {
|
|
263
|
+
delivery: string;
|
|
264
|
+
ok: boolean;
|
|
265
|
+
message?: string;
|
|
266
|
+
error?: string;
|
|
267
|
+
}
|
|
268
|
+
export interface PolicySubjects {
|
|
269
|
+
type?: 'app_user' | 'developer' | 'member' | 'any';
|
|
270
|
+
user_ids?: string[];
|
|
271
|
+
groups?: string[];
|
|
272
|
+
not_groups?: string[];
|
|
273
|
+
}
|
|
274
|
+
export interface PolicyIdentifierPattern {
|
|
275
|
+
exact?: string;
|
|
276
|
+
match_start?: string;
|
|
277
|
+
match_end?: string;
|
|
278
|
+
contains?: string;
|
|
279
|
+
regex?: string;
|
|
280
|
+
}
|
|
281
|
+
export interface PolicyResources {
|
|
282
|
+
identifiers?: PolicyIdentifierPattern[];
|
|
283
|
+
meta_paths?: string[];
|
|
284
|
+
xml_paths?: string[];
|
|
285
|
+
}
|
|
286
|
+
export interface PolicyConditions {
|
|
287
|
+
branches?: string[];
|
|
288
|
+
}
|
|
289
|
+
export interface SecurityPolicy {
|
|
290
|
+
description?: string;
|
|
291
|
+
effect: 'allow' | 'deny';
|
|
292
|
+
priority: number;
|
|
293
|
+
subjects: PolicySubjects;
|
|
294
|
+
resources: PolicyResources;
|
|
295
|
+
actions: string[];
|
|
296
|
+
conditions?: PolicyConditions;
|
|
297
|
+
}
|
|
298
|
+
/** Subject payload for `checkAccess` dry-run. */
|
|
299
|
+
export interface PolicySubjectInput {
|
|
300
|
+
type?: 'app_user' | 'developer' | 'member' | 'any';
|
|
301
|
+
user_id?: string;
|
|
302
|
+
email?: string;
|
|
303
|
+
groups?: string[];
|
|
304
|
+
role?: string;
|
|
305
|
+
username?: string;
|
|
306
|
+
}
|
|
307
|
+
export interface SecurityConfig {
|
|
308
|
+
default_effect: 'allow' | 'deny';
|
|
309
|
+
app_user_default_effect: 'allow' | 'deny';
|
|
310
|
+
developer_bypass: boolean;
|
|
311
|
+
/** Preferred name; server may only return `developer_bypass`. */
|
|
312
|
+
member_bypass?: boolean;
|
|
313
|
+
/** Present on GET /api/v1/security/config; server-derived, not stored on PUT. */
|
|
314
|
+
xml_paths_enforced?: boolean;
|
|
315
|
+
xml_paths_pattern_style?: string;
|
|
316
|
+
xml_paths_limitations?: string[];
|
|
317
|
+
}
|
|
318
|
+
export interface AccessCheckResult {
|
|
319
|
+
effect: 'allow' | 'deny';
|
|
320
|
+
matched_policy_id?: string;
|
|
321
|
+
}
|
|
322
|
+
export interface StoredPolicyResponse {
|
|
323
|
+
policy_id: string;
|
|
324
|
+
policy: SecurityPolicy;
|
|
325
|
+
warnings?: string[];
|
|
326
|
+
}
|
|
327
|
+
/** Response from PUT /api/v1/security/policies/{id} */
|
|
328
|
+
export interface PolicyUpdateResponse {
|
|
329
|
+
message: string;
|
|
330
|
+
policy_id: string;
|
|
331
|
+
policy: SecurityPolicy;
|
|
332
|
+
warnings?: string[];
|
|
333
|
+
}
|
|
334
|
+
/** Stored trigger document under /_xcitedb/triggers (server-defined shape). */
|
|
335
|
+
export type TriggerDefinition = Record<string, unknown>;
|
|
336
|
+
export interface StoredTriggerResponse {
|
|
337
|
+
trigger_id: string;
|
|
338
|
+
trigger: TriggerDefinition;
|
|
339
|
+
}
|
|
340
|
+
/** Version control / commit metadata (git-like layer). */
|
|
341
|
+
export interface CommitRecord {
|
|
342
|
+
id: string;
|
|
343
|
+
branch: string;
|
|
344
|
+
/** Internal LMDB date key for this commit snapshot. */
|
|
345
|
+
date_key: string;
|
|
346
|
+
date_human?: string;
|
|
347
|
+
/** Alias for human-readable date (same as date_human when present). */
|
|
348
|
+
date?: string;
|
|
349
|
+
message: string;
|
|
350
|
+
author: string;
|
|
351
|
+
parent_id: string | null;
|
|
352
|
+
merge_source?: {
|
|
353
|
+
branch: string;
|
|
354
|
+
commit_id: string;
|
|
355
|
+
};
|
|
356
|
+
cherry_picked_from?: string;
|
|
357
|
+
affected_identifiers: string[];
|
|
358
|
+
status: 'active' | 'rolled_back';
|
|
359
|
+
created_at: number;
|
|
360
|
+
}
|
|
361
|
+
/** Branch row from GET /api/v1/branches (also exposed as BranchListItem). */
|
|
362
|
+
export interface BranchInfo {
|
|
363
|
+
name: string;
|
|
364
|
+
from_branch: string;
|
|
365
|
+
from_date: string;
|
|
366
|
+
/** Internal LMDB fork date key when present. */
|
|
367
|
+
from_date_key?: string;
|
|
368
|
+
tip_commit?: CommitRecord;
|
|
369
|
+
}
|
|
370
|
+
export type BranchListItem = BranchInfo;
|
|
371
|
+
export interface TagRecord {
|
|
372
|
+
name: string;
|
|
373
|
+
commit_id: string;
|
|
374
|
+
branch: string;
|
|
375
|
+
date_key: string;
|
|
376
|
+
message?: string;
|
|
377
|
+
author?: string;
|
|
378
|
+
created_at: number;
|
|
379
|
+
}
|
|
380
|
+
export interface DiffEntry {
|
|
381
|
+
identifier: string;
|
|
382
|
+
action: 'added' | 'modified' | 'deleted';
|
|
383
|
+
from_content?: string;
|
|
384
|
+
to_content?: string;
|
|
385
|
+
}
|
|
386
|
+
export interface DiffRef {
|
|
387
|
+
branch?: string;
|
|
388
|
+
/** Internal date key (preferred for exact revision). */
|
|
389
|
+
date_key?: string;
|
|
390
|
+
commit_id?: string;
|
|
391
|
+
}
|
|
392
|
+
export interface DiffResult {
|
|
393
|
+
changes: DiffEntry[];
|
|
394
|
+
from: {
|
|
395
|
+
branch?: string;
|
|
396
|
+
date_key?: string;
|
|
397
|
+
};
|
|
398
|
+
to: {
|
|
399
|
+
branch?: string;
|
|
400
|
+
date_key?: string;
|
|
401
|
+
};
|
|
402
|
+
total_changes: number;
|
|
403
|
+
}
|
|
404
|
+
export interface MergeConflict {
|
|
405
|
+
identifier: string;
|
|
406
|
+
source_action: string;
|
|
407
|
+
target_action: string;
|
|
408
|
+
}
|
|
409
|
+
export interface MergeResult {
|
|
410
|
+
status: 'completed' | 'conflicts';
|
|
411
|
+
commit?: CommitRecord;
|
|
412
|
+
merged_identifiers?: string[];
|
|
413
|
+
conflicts?: MergeConflict[];
|
|
414
|
+
auto_mergeable?: string[];
|
|
415
|
+
message?: string;
|
|
416
|
+
}
|
|
417
|
+
export declare class XCiteDBError extends Error {
|
|
418
|
+
readonly status: number;
|
|
419
|
+
readonly body?: unknown | undefined;
|
|
420
|
+
constructor(message: string, status: number, body?: unknown | undefined);
|
|
421
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.XCiteDBError = void 0;
|
|
4
|
+
class XCiteDBError extends Error {
|
|
5
|
+
constructor(message, status, body) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.status = status;
|
|
8
|
+
this.body = body;
|
|
9
|
+
this.name = 'XCiteDBError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.XCiteDBError = XCiteDBError;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { RealtimeEvent, SubscriptionOptions } from './types';
|
|
2
|
+
export type MessageHandler = (event: RealtimeEvent) => void;
|
|
3
|
+
export type ErrorHandler = (error: Error) => void;
|
|
4
|
+
/**
|
|
5
|
+
* Browser / Node 21+ WebSocket client for `/api/v1/ws`.
|
|
6
|
+
* Pass `access_token` or `X-API-Key` via headers map (used as query params for browser WebSocket).
|
|
7
|
+
*/
|
|
8
|
+
export declare class WebSocketSubscription {
|
|
9
|
+
private ws;
|
|
10
|
+
private readonly baseWsUrl;
|
|
11
|
+
private readonly headerParams;
|
|
12
|
+
private messageHandler?;
|
|
13
|
+
private errorHandler?;
|
|
14
|
+
private reconnectMs;
|
|
15
|
+
private shouldReconnect;
|
|
16
|
+
private subs;
|
|
17
|
+
constructor(baseWsUrl: string, headers: Record<string, string>);
|
|
18
|
+
private buildUrl;
|
|
19
|
+
connect(): void;
|
|
20
|
+
private sendSubscribe;
|
|
21
|
+
subscribePattern(options: SubscriptionOptions): void;
|
|
22
|
+
unsubscribePattern(pattern: string): void;
|
|
23
|
+
ping(): void;
|
|
24
|
+
onMessage(cb: MessageHandler): void;
|
|
25
|
+
onError(cb: ErrorHandler): void;
|
|
26
|
+
close(): void;
|
|
27
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WebSocketSubscription = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Browser / Node 21+ WebSocket client for `/api/v1/ws`.
|
|
6
|
+
* Pass `access_token` or `X-API-Key` via headers map (used as query params for browser WebSocket).
|
|
7
|
+
*/
|
|
8
|
+
class WebSocketSubscription {
|
|
9
|
+
constructor(baseWsUrl, headers) {
|
|
10
|
+
this.ws = null;
|
|
11
|
+
this.reconnectMs = 1000;
|
|
12
|
+
this.shouldReconnect = false;
|
|
13
|
+
this.subs = [];
|
|
14
|
+
this.baseWsUrl = baseWsUrl.replace(/\/+$/, '');
|
|
15
|
+
this.headerParams = { ...headers };
|
|
16
|
+
}
|
|
17
|
+
buildUrl() {
|
|
18
|
+
const u = new URL('/api/v1/ws', `${this.baseWsUrl}/`);
|
|
19
|
+
const token = this.headerParams['Authorization']?.replace(/^Bearer\s+/i, '');
|
|
20
|
+
if (token)
|
|
21
|
+
u.searchParams.set('access_token', token);
|
|
22
|
+
const apiKey = this.headerParams['X-API-Key'];
|
|
23
|
+
if (apiKey)
|
|
24
|
+
u.searchParams.set('api_key', apiKey);
|
|
25
|
+
const tenant = this.headerParams['tenant_id'];
|
|
26
|
+
if (tenant)
|
|
27
|
+
u.searchParams.set('tenant_id', tenant);
|
|
28
|
+
return u.toString();
|
|
29
|
+
}
|
|
30
|
+
connect() {
|
|
31
|
+
this.shouldReconnect = true;
|
|
32
|
+
const url = this.buildUrl();
|
|
33
|
+
this.ws = new WebSocket(url);
|
|
34
|
+
this.ws.onopen = () => {
|
|
35
|
+
for (const s of this.subs) {
|
|
36
|
+
this.sendSubscribe(s);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
this.ws.onmessage = (ev) => {
|
|
40
|
+
try {
|
|
41
|
+
const data = JSON.parse(String(ev.data));
|
|
42
|
+
this.messageHandler?.(data);
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
this.errorHandler?.(e instanceof Error ? e : new Error(String(e)));
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
this.ws.onerror = () => {
|
|
49
|
+
this.errorHandler?.(new Error('WebSocket error'));
|
|
50
|
+
};
|
|
51
|
+
this.ws.onclose = () => {
|
|
52
|
+
if (this.shouldReconnect) {
|
|
53
|
+
setTimeout(() => this.connect(), this.reconnectMs);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
sendSubscribe(opt) {
|
|
58
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN)
|
|
59
|
+
return;
|
|
60
|
+
this.ws.send(JSON.stringify({
|
|
61
|
+
action: 'subscribe',
|
|
62
|
+
pattern: opt.pattern,
|
|
63
|
+
event_type: opt.event_type ?? '*',
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
subscribePattern(options) {
|
|
67
|
+
this.subs.push(options);
|
|
68
|
+
this.sendSubscribe(options);
|
|
69
|
+
}
|
|
70
|
+
unsubscribePattern(pattern) {
|
|
71
|
+
this.subs = this.subs.filter((s) => s.pattern !== pattern);
|
|
72
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN)
|
|
73
|
+
return;
|
|
74
|
+
this.ws.send(JSON.stringify({ action: 'unsubscribe', pattern }));
|
|
75
|
+
}
|
|
76
|
+
ping() {
|
|
77
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN)
|
|
78
|
+
return;
|
|
79
|
+
this.ws.send(JSON.stringify({ action: 'ping' }));
|
|
80
|
+
}
|
|
81
|
+
onMessage(cb) {
|
|
82
|
+
this.messageHandler = cb;
|
|
83
|
+
}
|
|
84
|
+
onError(cb) {
|
|
85
|
+
this.errorHandler = cb;
|
|
86
|
+
}
|
|
87
|
+
close() {
|
|
88
|
+
this.shouldReconnect = false;
|
|
89
|
+
this.ws?.close();
|
|
90
|
+
this.ws = null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
exports.WebSocketSubscription = WebSocketSubscription;
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xcitedbs/client",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "XCiteDB BaaS client SDK",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"prepublishOnly": "npm run build",
|
|
10
|
+
"test": "node --test dist/**/*.test.js 2>/dev/null || echo 'No tests'"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"xcitedb",
|
|
14
|
+
"database",
|
|
15
|
+
"baas",
|
|
16
|
+
"client",
|
|
17
|
+
"api",
|
|
18
|
+
"websocket"
|
|
19
|
+
],
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/xcite-db/XciteDB-server.git",
|
|
23
|
+
"directory": "sdks/javascript"
|
|
24
|
+
},
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/xcite-db/XciteDB-server/issues"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://github.com/xcite-db/XciteDB-server/tree/main/sdks/javascript#readme",
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18"
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"typescript": "^5.0.0"
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist"
|
|
41
|
+
],
|
|
42
|
+
"license": "MIT"
|
|
43
|
+
}
|