@onyx.dev/onyx-database 0.1.4

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.
@@ -0,0 +1,1176 @@
1
+ /**
2
+ * Supported operators for building query criteria.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * const criteria = { field: 'age', operator: 'GREATER_THAN', value: 21 };
7
+ * ```
8
+ */
9
+ type QueryCriteriaOperator = 'EQUAL' | 'NOT_EQUAL' | 'IN' | 'NOT_IN' | 'GREATER_THAN' | 'GREATER_THAN_EQUAL' | 'LESS_THAN' | 'LESS_THAN_EQUAL' | 'MATCHES' | 'NOT_MATCHES' | 'BETWEEN' | 'LIKE' | 'NOT_LIKE' | 'CONTAINS' | 'CONTAINS_IGNORE_CASE' | 'NOT_CONTAINS' | 'NOT_CONTAINS_IGNORE_CASE' | 'STARTS_WITH' | 'NOT_STARTS_WITH' | 'IS_NULL' | 'NOT_NULL';
10
+ /** Logical operator used to join conditions in a query. */
11
+ type LogicalOperator = 'AND' | 'OR';
12
+ /**
13
+ * Sorting instruction for query results.
14
+ *
15
+ * @property field - Field name to order by.
16
+ * @property order - Sort direction.
17
+ * @example
18
+ * ```ts
19
+ * const sort: Sort = { field: 'name', order: 'ASC' };
20
+ * ```
21
+ */
22
+ interface Sort {
23
+ field: string;
24
+ order: 'ASC' | 'DESC';
25
+ }
26
+ /** Actions emitted by real-time data streams. */
27
+ type StreamAction = 'CREATE' | 'UPDATE' | 'DELETE' | 'QUERY_RESPONSE' | 'KEEP_ALIVE';
28
+ /**
29
+ * Basic document representation used by the SDK.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * const doc: OnyxDocument = { documentId: '1', content: 'hello' };
34
+ * ```
35
+ */
36
+ interface OnyxDocument {
37
+ /** Unique document identifier. */
38
+ documentId?: string;
39
+ /** Path within the Onyx database. */
40
+ path?: string;
41
+ /** Creation timestamp. */
42
+ created?: Date;
43
+ /** Last update timestamp. */
44
+ updated?: Date;
45
+ /** MIME type of the content. */
46
+ mimeType?: string;
47
+ /** Raw document content. */
48
+ content?: string;
49
+ }
50
+ /** Minimal fetch typing to avoid DOM lib dependency */
51
+ interface FetchResponse {
52
+ /** Whether the request succeeded (status in the range 200–299). */
53
+ ok: boolean;
54
+ /** HTTP status code. */
55
+ status: number;
56
+ /** HTTP status text. */
57
+ statusText: string;
58
+ /** Response headers getter. */
59
+ headers: {
60
+ get(name: string): string | null;
61
+ };
62
+ /** Reads the body as text. */
63
+ text(): Promise<string>;
64
+ /** Raw body for streams; left as unknown to avoid DOM typings */
65
+ body?: unknown;
66
+ }
67
+ /**
68
+ * Fetch implementation signature used by the SDK.
69
+ *
70
+ * @param url - Resource URL.
71
+ * @param init - Optional init parameters.
72
+ * @example
73
+ * ```ts
74
+ * const res = await fetchImpl('https://api.onyx.dev');
75
+ * ```
76
+ */
77
+ type FetchImpl = (url: string, init?: {
78
+ method?: string;
79
+ headers?: Record<string, string>;
80
+ body?: string;
81
+ }) => Promise<FetchResponse>;
82
+
83
+ /**
84
+ * Represents a single field comparison in a query.
85
+ *
86
+ * @property field - Field name to evaluate.
87
+ * @property operator - Comparison operator.
88
+ * @property value - Value to compare against.
89
+ * @example
90
+ * ```ts
91
+ * const criteria: QueryCriteria = { field: 'age', operator: 'GREATER_THAN', value: 18 };
92
+ * ```
93
+ */
94
+ interface QueryCriteria {
95
+ field: string;
96
+ operator: QueryCriteriaOperator;
97
+ value?: unknown;
98
+ }
99
+ /**
100
+ * Recursive condition structure used to express complex WHERE clauses.
101
+ *
102
+ * @example
103
+ * ```ts
104
+ * const condition: QueryCondition = {
105
+ * conditionType: 'CompoundCondition',
106
+ * operator: 'AND',
107
+ * conditions: [
108
+ * { conditionType: 'SingleCondition', criteria: { field: 'age', operator: 'GREATER_THAN', value: 18 } },
109
+ * { conditionType: 'SingleCondition', criteria: { field: 'status', operator: 'EQUAL', value: 'ACTIVE' } }
110
+ * ]
111
+ * };
112
+ * ```
113
+ */
114
+ type QueryCondition = {
115
+ conditionType: 'SingleCondition';
116
+ criteria: QueryCriteria;
117
+ } | {
118
+ conditionType: 'CompoundCondition';
119
+ operator: LogicalOperator;
120
+ conditions: QueryCondition[];
121
+ };
122
+ /**
123
+ * Wire format for select queries sent to the server.
124
+ *
125
+ * @example
126
+ * ```ts
127
+ * const query: SelectQuery = {
128
+ * type: 'SelectQuery',
129
+ * fields: ['id', 'name'],
130
+ * limit: 10
131
+ * };
132
+ * ```
133
+ */
134
+ interface SelectQuery {
135
+ type: 'SelectQuery';
136
+ fields?: string[] | null;
137
+ conditions?: QueryCondition | null;
138
+ sort?: Sort[] | null;
139
+ limit?: number | null;
140
+ distinct?: boolean | null;
141
+ groupBy?: string[] | null;
142
+ partition?: string | null;
143
+ resolvers?: string[] | null;
144
+ }
145
+ /**
146
+ * Wire format for update queries sent to the server.
147
+ *
148
+ * @example
149
+ * ```ts
150
+ * const update: UpdateQuery = {
151
+ * type: 'UpdateQuery',
152
+ * updates: { name: 'New Name' }
153
+ * };
154
+ * ```
155
+ */
156
+ interface UpdateQuery {
157
+ type: 'UpdateQuery';
158
+ conditions?: QueryCondition | null;
159
+ updates: Record<string, unknown>;
160
+ sort?: Sort[] | null;
161
+ limit?: number | null;
162
+ partition?: string | null;
163
+ }
164
+ /**
165
+ * A single page of query results.
166
+ *
167
+ * @example
168
+ * ```ts
169
+ * const page: QueryPage<User> = { records: users, nextPage: token };
170
+ * ```
171
+ */
172
+ interface QueryPage<T> {
173
+ /** Records in the current page. */
174
+ records: T[];
175
+ /** Token for the next page or null if none. */
176
+ nextPage?: string | null;
177
+ }
178
+
179
+ /**
180
+ * Array-like container for paginated query results. Provides helper methods
181
+ * to traverse and aggregate records across pages.
182
+ *
183
+ * @example
184
+ * ```ts
185
+ * const results = new QueryResults(users, nextToken, fetchNext);
186
+ * const firstUser = results.first();
187
+ * ```
188
+ */
189
+ type QueryResultsPromise<T> = Promise<QueryResults<T>> & {
190
+ [K in keyof QueryResults<T> as QueryResults<T>[K] extends (...args: any[]) => any ? K : never]: QueryResults<T>[K] extends (...args: infer P) => infer R ? (...args: P) => Promise<Awaited<R>> : never;
191
+ };
192
+ declare class QueryResults<T> extends Array<T> {
193
+ /** Token for the next page of results or null. */
194
+ nextPage: string | null;
195
+ private readonly fetcher?;
196
+ /**
197
+ * @param records - Records in the current page.
198
+ * @param nextPage - Token representing the next page.
199
+ * @param fetcher - Function used to fetch the next page when needed.
200
+ * @example
201
+ * ```ts
202
+ * const results = new QueryResults(users, token, t => fetchMore(t));
203
+ * ```
204
+ */
205
+ constructor(records: T[], nextPage: string | null, fetcher?: (token: string) => Promise<QueryResults<T>>);
206
+ /**
207
+ * Returns the first record in the result set.
208
+ * @throws Error if the result set is empty.
209
+ * @example
210
+ * ```ts
211
+ * const user = results.first();
212
+ * ```
213
+ */
214
+ first(): T;
215
+ /**
216
+ * Returns the first record or `null` if the result set is empty.
217
+ * @example
218
+ * ```ts
219
+ * const user = results.firstOrNull();
220
+ * ```
221
+ */
222
+ firstOrNull(): T | null;
223
+ /**
224
+ * Checks whether the current page has no records.
225
+ * @example
226
+ * ```ts
227
+ * if (results.isEmpty()) console.log('no data');
228
+ * ```
229
+ */
230
+ isEmpty(): boolean;
231
+ /**
232
+ * Number of records on the current page.
233
+ * @example
234
+ * ```ts
235
+ * console.log(results.size());
236
+ * ```
237
+ */
238
+ size(): number;
239
+ /**
240
+ * Iterates over each record on the current page only.
241
+ * @param action - Function to invoke for each record.
242
+ * @example
243
+ * ```ts
244
+ * results.forEachOnPage(u => console.log(u.id));
245
+ * ```
246
+ */
247
+ forEachOnPage(action: (item: T) => void): void;
248
+ /**
249
+ * Iterates over every record across all pages sequentially.
250
+ * @param action - Function executed for each record. Returning `false`
251
+ * stops iteration early.
252
+ * @example
253
+ * ```ts
254
+ * await results.forEachAll(u => {
255
+ * if (u.disabled) return false;
256
+ * });
257
+ * ```
258
+ */
259
+ forEachAll(action: (item: T) => boolean | void | Promise<boolean | void>): Promise<void>;
260
+ /**
261
+ * Iterates page by page across the result set.
262
+ * @param action - Function invoked with each page of records. Returning
263
+ * `false` stops iteration.
264
+ * @example
265
+ * ```ts
266
+ * await results.forEachPage(page => {
267
+ * console.log(page.length);
268
+ * });
269
+ * ```
270
+ */
271
+ forEachPage(action: (records: T[]) => boolean | void | Promise<boolean | void>): Promise<void>;
272
+ /**
273
+ * Collects all records from every page into a single array.
274
+ * @returns All records.
275
+ * @example
276
+ * ```ts
277
+ * const allUsers = await results.getAllRecords();
278
+ * ```
279
+ */
280
+ getAllRecords(): Promise<T[]>;
281
+ /**
282
+ * Filters all records using the provided predicate.
283
+ * @param predicate - Function used to test each record.
284
+ * @example
285
+ * ```ts
286
+ * const enabled = await results.filterAll(u => u.enabled);
287
+ * ```
288
+ */
289
+ filterAll(predicate: (record: T) => boolean): Promise<T[]>;
290
+ /**
291
+ * Maps all records using the provided transform.
292
+ * @param transform - Mapping function.
293
+ * @example
294
+ * ```ts
295
+ * const names = await results.mapAll(u => u.name);
296
+ * ```
297
+ */
298
+ mapAll<R>(transform: (record: T) => R): Promise<R[]>;
299
+ /**
300
+ * Extracts values for a field across all records.
301
+ * @param field - Name of the field to pluck.
302
+ * @example
303
+ * ```ts
304
+ * const ids = await results.values('id');
305
+ * ```
306
+ */
307
+ values<K extends keyof T>(field: K): Promise<Array<T[K]>>;
308
+ /**
309
+ * Maximum value produced by the selector across all records.
310
+ * @param selector - Function extracting a numeric value.
311
+ * @example
312
+ * ```ts
313
+ * const maxAge = await results.maxOfDouble(u => u.age);
314
+ * ```
315
+ */
316
+ maxOfDouble(selector: (record: T) => number): Promise<number>;
317
+ /**
318
+ * Minimum value produced by the selector across all records.
319
+ * @param selector - Function extracting a numeric value.
320
+ * @example
321
+ * ```ts
322
+ * const minAge = await results.minOfDouble(u => u.age);
323
+ * ```
324
+ */
325
+ minOfDouble(selector: (record: T) => number): Promise<number>;
326
+ /**
327
+ * Sum of values produced by the selector across all records.
328
+ * @param selector - Function extracting a numeric value.
329
+ * @example
330
+ * ```ts
331
+ * const total = await results.sumOfDouble(u => u.score);
332
+ * ```
333
+ */
334
+ sumOfDouble(selector: (record: T) => number): Promise<number>;
335
+ /**
336
+ * Maximum float value from the selector.
337
+ * @param selector - Function extracting a numeric value.
338
+ */
339
+ maxOfFloat(selector: (record: T) => number): Promise<number>;
340
+ /**
341
+ * Minimum float value from the selector.
342
+ * @param selector - Function extracting a numeric value.
343
+ */
344
+ minOfFloat(selector: (record: T) => number): Promise<number>;
345
+ /**
346
+ * Sum of float values from the selector.
347
+ * @param selector - Function extracting a numeric value.
348
+ */
349
+ sumOfFloat(selector: (record: T) => number): Promise<number>;
350
+ /**
351
+ * Maximum integer value from the selector.
352
+ * @param selector - Function extracting a numeric value.
353
+ */
354
+ maxOfInt(selector: (record: T) => number): Promise<number>;
355
+ /**
356
+ * Minimum integer value from the selector.
357
+ * @param selector - Function extracting a numeric value.
358
+ */
359
+ minOfInt(selector: (record: T) => number): Promise<number>;
360
+ /**
361
+ * Sum of integer values from the selector.
362
+ * @param selector - Function extracting a numeric value.
363
+ */
364
+ sumOfInt(selector: (record: T) => number): Promise<number>;
365
+ /**
366
+ * Maximum long value from the selector.
367
+ * @param selector - Function extracting a numeric value.
368
+ */
369
+ maxOfLong(selector: (record: T) => number): Promise<number>;
370
+ /**
371
+ * Minimum long value from the selector.
372
+ * @param selector - Function extracting a numeric value.
373
+ */
374
+ minOfLong(selector: (record: T) => number): Promise<number>;
375
+ /**
376
+ * Sum of long values from the selector.
377
+ * @param selector - Function extracting a numeric value.
378
+ */
379
+ sumOfLong(selector: (record: T) => number): Promise<number>;
380
+ /**
381
+ * Sum of bigint values from the selector.
382
+ * @param selector - Function extracting a bigint value.
383
+ * @example
384
+ * ```ts
385
+ * const total = await results.sumOfBigInt(u => u.balance);
386
+ * ```
387
+ */
388
+ sumOfBigInt(selector: (record: T) => bigint): Promise<bigint>;
389
+ /**
390
+ * Executes an action for each page in parallel.
391
+ * @param action - Function executed for each record concurrently.
392
+ * @example
393
+ * ```ts
394
+ * await results.forEachPageParallel(async u => sendEmail(u));
395
+ * ```
396
+ */
397
+ forEachPageParallel(action: (item: T) => void | Promise<void>): Promise<void>;
398
+ }
399
+
400
+ /**
401
+ * Builder used to compose query conditions.
402
+ */
403
+ interface IConditionBuilder {
404
+ /**
405
+ * Combines the current condition with another using `AND`.
406
+ * @param condition - Additional condition or builder.
407
+ * @example
408
+ * ```ts
409
+ * cb.and({ field: 'age', operator: 'GREATER_THAN', value: 18 });
410
+ * ```
411
+ */
412
+ and(condition: IConditionBuilder | QueryCriteria): IConditionBuilder;
413
+ /**
414
+ * Combines the current condition with another using `OR`.
415
+ * @param condition - Additional condition or builder.
416
+ * @example
417
+ * ```ts
418
+ * cb.or({ field: 'status', operator: 'EQUAL', value: 'ACTIVE' });
419
+ * ```
420
+ */
421
+ or(condition: IConditionBuilder | QueryCriteria): IConditionBuilder;
422
+ /**
423
+ * Materializes the composed condition into a `QueryCondition` object.
424
+ * @example
425
+ * ```ts
426
+ * const cond = cb.toCondition();
427
+ * ```
428
+ */
429
+ toCondition(): QueryCondition;
430
+ }
431
+ /**
432
+ * Fluent query builder for constructing and executing select/update/delete operations.
433
+ */
434
+ interface IQueryBuilder<T = unknown> {
435
+ /**
436
+ * Sets the table to query.
437
+ * @example
438
+ * ```ts
439
+ * const users = await db.from('User').list();
440
+ * ```
441
+ */
442
+ from(table: string): IQueryBuilder<T>;
443
+ /**
444
+ * Selects a subset of fields to return.
445
+ * @example
446
+ * ```ts
447
+ * const emails = await db.from('User').selectFields('email').list();
448
+ * ```
449
+ */
450
+ selectFields(...fields: Array<string | string[]>): IQueryBuilder<T>;
451
+ /**
452
+ * Resolves related values by name.
453
+ * @example
454
+ * ```ts
455
+ * const users = await db
456
+ * .from('User')
457
+ * .resolve('profile', 'roles')
458
+ * .list();
459
+ * ```
460
+ */
461
+ resolve(...values: Array<string | string[]>): IQueryBuilder<T>;
462
+ /**
463
+ * Adds a filter condition.
464
+ * @example
465
+ * ```ts
466
+ * const active = await db.from('User').where(eq('status', 'active')).list();
467
+ * ```
468
+ */
469
+ where(condition: IConditionBuilder | QueryCriteria): IQueryBuilder<T>;
470
+ /**
471
+ * Adds an additional filter with `AND`.
472
+ * @example
473
+ * ```ts
474
+ * qb.where(eq('status', 'active')).and(eq('role', 'admin'));
475
+ * ```
476
+ */
477
+ and(condition: IConditionBuilder | QueryCriteria): IQueryBuilder<T>;
478
+ /**
479
+ * Adds an additional filter with `OR`.
480
+ * @example
481
+ * ```ts
482
+ * qb.where(eq('status', 'active')).or(eq('status', 'invited'));
483
+ * ```
484
+ */
485
+ or(condition: IConditionBuilder | QueryCriteria): IQueryBuilder<T>;
486
+ /**
487
+ * Orders results by the provided fields.
488
+ * @example
489
+ * ```ts
490
+ * const users = await db.from('User').orderBy(asc('createdAt')).list();
491
+ * ```
492
+ */
493
+ orderBy(...sorts: Sort[]): IQueryBuilder<T>;
494
+ /**
495
+ * Groups results by the provided fields.
496
+ * @example
497
+ * ```ts
498
+ * const stats = await db.from('User').groupBy('status').list();
499
+ * ```
500
+ */
501
+ groupBy(...fields: string[]): IQueryBuilder<T>;
502
+ /**
503
+ * Ensures only distinct records are returned.
504
+ * @example
505
+ * ```ts
506
+ * const roles = await db.from('User').selectFields('role').distinct().list();
507
+ * ```
508
+ */
509
+ distinct(): IQueryBuilder<T>;
510
+ /**
511
+ * Limits the number of records returned.
512
+ * @example
513
+ * ```ts
514
+ * const few = await db.from('User').limit(5).list();
515
+ * ```
516
+ */
517
+ limit(n: number): IQueryBuilder<T>;
518
+ /**
519
+ * Restricts the query to a specific partition.
520
+ * @example
521
+ * ```ts
522
+ * const tenantUsers = await db.from('User').inPartition('tenantA').list();
523
+ * ```
524
+ */
525
+ inPartition(partition: string): IQueryBuilder<T>;
526
+ /** Sets the page size for subsequent `list` or `page` calls. */
527
+ pageSize(n: number): IQueryBuilder<T>;
528
+ /**
529
+ * Continues a paged query using a next-page token.
530
+ * @example
531
+ * ```ts
532
+ * const page2 = await db.from('User').nextPage(token).list();
533
+ * ```
534
+ */
535
+ nextPage(token: string): IQueryBuilder<T>;
536
+ /**
537
+ * Counts matching records.
538
+ * @example
539
+ * ```ts
540
+ * const total = await db.from('User').count();
541
+ * ```
542
+ */
543
+ count(): Promise<number>;
544
+ /**
545
+ * Lists records with optional pagination.
546
+ * @example
547
+ * ```ts
548
+ * const users = await db.from('User').list({ pageSize: 10 });
549
+ * ```
550
+ */
551
+ list(options?: {
552
+ pageSize?: number;
553
+ nextPage?: string;
554
+ }): QueryResultsPromise<T>;
555
+ /**
556
+ * Retrieves the first record or null.
557
+ * @example
558
+ * ```ts
559
+ * const user = await db.from('User').firstOrNull();
560
+ * ```
561
+ */
562
+ firstOrNull(): Promise<T | null>;
563
+ /**
564
+ * Retrieves exactly one record or null.
565
+ * @example
566
+ * ```ts
567
+ * const user = await db
568
+ * .from('User')
569
+ * .where(eq('email', 'a@b.com'))
570
+ * .one();
571
+ * ```
572
+ */
573
+ one(): Promise<T | null>;
574
+ /**
575
+ * Retrieves a single page of records with optional next token.
576
+ * @example
577
+ * ```ts
578
+ * const { records, nextPage } = await db.from('User').page({ pageSize: 25 });
579
+ * ```
580
+ */
581
+ page(options?: {
582
+ pageSize?: number;
583
+ nextPage?: string;
584
+ }): Promise<{
585
+ records: T[];
586
+ nextPage?: string | null;
587
+ }>;
588
+ /**
589
+ * Sets field updates for an update query.
590
+ * @example
591
+ * ```ts
592
+ * await db
593
+ * .from('User')
594
+ * .where(eq('id', 'u1'))
595
+ * .setUpdates({ status: 'active' })
596
+ * .update();
597
+ * ```
598
+ */
599
+ setUpdates(updates: Partial<T>): IQueryBuilder<T>;
600
+ /**
601
+ * Executes an update operation.
602
+ * @example
603
+ * ```ts
604
+ * await db.from('User').where(eq('id', 'u1')).setUpdates({ status: 'active' }).update();
605
+ * ```
606
+ */
607
+ update(): Promise<unknown>;
608
+ /**
609
+ * Executes a delete operation.
610
+ * @example
611
+ * ```ts
612
+ * await db.from('User').where(eq('status', 'inactive')).delete();
613
+ * ```
614
+ */
615
+ delete(): Promise<unknown>;
616
+ /**
617
+ * Registers a listener for added items on a stream.
618
+ * @example
619
+ * ```ts
620
+ * db.from('User').onItemAdded(u => console.log('added', u));
621
+ * ```
622
+ */
623
+ onItemAdded(listener: (entity: T) => void): IQueryBuilder<T>;
624
+ /**
625
+ * Registers a listener for updated items on a stream.
626
+ * @example
627
+ * ```ts
628
+ * db.from('User').onItemUpdated(u => console.log('updated', u));
629
+ * ```
630
+ */
631
+ onItemUpdated(listener: (entity: T) => void): IQueryBuilder<T>;
632
+ /**
633
+ * Registers a listener for deleted items on a stream.
634
+ * @example
635
+ * ```ts
636
+ * db.from('User').onItemDeleted(u => console.log('deleted', u));
637
+ * ```
638
+ */
639
+ onItemDeleted(listener: (entity: T) => void): IQueryBuilder<T>;
640
+ /**
641
+ * Registers a listener for any stream item with its action.
642
+ * @example
643
+ * ```ts
644
+ * db.from('User').onItem((u, action) => console.log(action, u));
645
+ * ```
646
+ */
647
+ onItem(listener: (entity: T | null, action: StreamAction) => void): IQueryBuilder<T>;
648
+ /**
649
+ * Starts a stream including query results.
650
+ * @example
651
+ * ```ts
652
+ * const { cancel } = await db.from('User').stream();
653
+ * ```
654
+ */
655
+ stream(includeQueryResults?: boolean, keepAlive?: boolean): Promise<{
656
+ cancel: () => void;
657
+ }>;
658
+ /**
659
+ * Starts a stream emitting only events.
660
+ * @example
661
+ * ```ts
662
+ * const { cancel } = await db.from('User').streamEventsOnly();
663
+ * ```
664
+ */
665
+ streamEventsOnly(keepAlive?: boolean): Promise<{
666
+ cancel: () => void;
667
+ }>;
668
+ /**
669
+ * Starts a stream that returns events alongside query results.
670
+ * @example
671
+ * ```ts
672
+ * const { cancel } = await db.from('User').streamWithQueryResults();
673
+ * ```
674
+ */
675
+ streamWithQueryResults(keepAlive?: boolean): Promise<{
676
+ cancel: () => void;
677
+ }>;
678
+ }
679
+
680
+ /** Builder for save operations. */
681
+ interface ISaveBuilder<T = unknown> {
682
+ /**
683
+ * Cascades specified relationships when saving.
684
+ * @example
685
+ * ```ts
686
+ * await db.save('User').cascade('role').one(user);
687
+ * ```
688
+ */
689
+ cascade(...relationships: Array<string | string[]>): ISaveBuilder<T>;
690
+ /**
691
+ * Persists a single entity.
692
+ * @example
693
+ * ```ts
694
+ * await db.save('User').one({ id: 'u1' });
695
+ * ```
696
+ */
697
+ one(entity: Partial<T>): Promise<unknown>;
698
+ /**
699
+ * Persists multiple entities.
700
+ * @example
701
+ * ```ts
702
+ * await db.save('User').many([{ id: 'u1' }, { id: 'u2' }]);
703
+ * ```
704
+ */
705
+ many(entities: Array<Partial<T>>): Promise<unknown>;
706
+ }
707
+ /** Builder for cascading save/delete operations across multiple tables. */
708
+ interface ICascadeBuilder<Schema = Record<string, unknown>> {
709
+ /**
710
+ * Specifies relationships to cascade through.
711
+ * @example
712
+ * ```ts
713
+ * const builder = db.cascade('permissions');
714
+ * ```
715
+ */
716
+ cascade(...relationships: Array<string | string[]>): ICascadeBuilder<Schema>;
717
+ /**
718
+ * Saves one or many entities for a given table.
719
+ * @example
720
+ * ```ts
721
+ * await db.cascade('permissions').save('Role', role);
722
+ * ```
723
+ */
724
+ save<Table extends keyof Schema & string>(table: Table, entityOrEntities: Partial<Schema[Table]> | Array<Partial<Schema[Table]>>): Promise<unknown>;
725
+ /**
726
+ * Deletes an entity by primary key.
727
+ * @example
728
+ * ```ts
729
+ * await db.cascade('permissions').delete('Role', 'admin');
730
+ * ```
731
+ */
732
+ delete<Table extends keyof Schema & string>(table: Table, primaryKey: string): Promise<Schema[Table]>;
733
+ }
734
+ /** Builder for describing cascade relationship metadata. */
735
+ interface ICascadeRelationshipBuilder {
736
+ /**
737
+ * Names the relationship graph.
738
+ * @example
739
+ * ```ts
740
+ * builder.graph('permissions');
741
+ * ```
742
+ */
743
+ graph(name: string): ICascadeRelationshipBuilder;
744
+ /**
745
+ * Sets the graph type.
746
+ * @example
747
+ * ```ts
748
+ * builder.graphType('Permission');
749
+ * ```
750
+ */
751
+ graphType(type: string): ICascadeRelationshipBuilder;
752
+ /**
753
+ * Field on the target entity.
754
+ * @example
755
+ * ```ts
756
+ * builder.targetField('roleId');
757
+ * ```
758
+ */
759
+ targetField(field: string): ICascadeRelationshipBuilder;
760
+ /**
761
+ * Field on the source entity.
762
+ * @example
763
+ * ```ts
764
+ * const rel = builder.sourceField('id');
765
+ * ```
766
+ */
767
+ sourceField(field: string): string;
768
+ }
769
+
770
+ interface OnyxConfig {
771
+ baseUrl?: string;
772
+ databaseId?: string;
773
+ apiKey?: string;
774
+ apiSecret?: string;
775
+ fetch?: FetchImpl;
776
+ /**
777
+ * Default partition for queries, `findById`, and deletes when removing by
778
+ * primary key. Saves rely on the entity's partition field instead.
779
+ */
780
+ partition?: string;
781
+ /**
782
+ * When true, log HTTP requests and bodies to the console.
783
+ */
784
+ requestLoggingEnabled?: boolean;
785
+ /**
786
+ * When true, log HTTP responses and bodies to the console.
787
+ */
788
+ responseLoggingEnabled?: boolean;
789
+ /**
790
+ * Milliseconds to cache resolved credentials; defaults to 5 minutes.
791
+ */
792
+ ttl?: number;
793
+ }
794
+ interface IOnyxDatabase<Schema = Record<string, unknown>> {
795
+ /**
796
+ * Begin a query against a table.
797
+ *
798
+ * @example
799
+ * ```ts
800
+ * const maybeUser = await db
801
+ * .from('User')
802
+ * .where(eq('email', 'a@b.com'))
803
+ * .firstOrNull(); // or .one()
804
+ * ```
805
+ *
806
+ * @example
807
+ * ```ts
808
+ * const users = await db
809
+ * .select('id', 'email')
810
+ * .from('User')
811
+ * .list();
812
+ * ```
813
+ *
814
+ * @param table Table name to query.
815
+ */
816
+ from<Table extends keyof Schema & string>(table: Table): IQueryBuilder<Schema[Table]>;
817
+ /**
818
+ * Select specific fields for a query.
819
+ *
820
+ * @example
821
+ * ```ts
822
+ * const users = await db
823
+ * .select('id', 'name')
824
+ * .from('User')
825
+ * .list();
826
+ * ```
827
+ *
828
+ * @param fields Field names to project; omit to select all.
829
+ */
830
+ select(...fields: string[]): IQueryBuilder<Record<string, unknown>>;
831
+ /**
832
+ * Include related records in the next save or delete.
833
+ *
834
+ * @example
835
+ * ```ts
836
+ * // Save a role and its permissions
837
+ * await db
838
+ * .cascade('permissions:Permission(roleId, id)')
839
+ * .save('Role', role);
840
+ *
841
+ * // Delete a role and all of its permissions via resolver
842
+ * await db
843
+ * .cascade('permissions')
844
+ * .delete('Role', 'admin');
845
+ * ```
846
+ *
847
+ * @param relationships Cascade relationship strings using
848
+ * `graph:Type(targetField, sourceField)` syntax when saving.
849
+ * When deleting, pass resolver attribute names only.
850
+ */
851
+ cascade(...relationships: Array<string | string[]>): ICascadeBuilder<Schema>;
852
+ /**
853
+ * Build cascade relationship strings programmatically.
854
+ *
855
+ * @example
856
+ * ```ts
857
+ * const rel = db
858
+ * .cascadeBuilder()
859
+ * .graph('permissions')
860
+ * .graphType('Permission')
861
+ * .targetField('roleId')
862
+ * .sourceField('id');
863
+ * await db.cascade(rel).save('Role', role);
864
+ * ```
865
+ *
866
+ * @returns Builder that emits strings like
867
+ * `graphName:TypeName(targetField, sourceField)`.
868
+ */
869
+ cascadeBuilder(): ICascadeRelationshipBuilder;
870
+ /**
871
+ * Start a save builder for inserting or updating entities.
872
+ *
873
+ * @example
874
+ * ```ts
875
+ * await db
876
+ * .save('User')
877
+ * .cascade('role:Role(userId, id)')
878
+ * .one({
879
+ * id: 'u1',
880
+ * email: 'a@b.com',
881
+ * role: { id: 'admin', userId: 'u1' }
882
+ * });
883
+ * ```
884
+ *
885
+ * @param table Table to save into.
886
+ */
887
+ save<Table extends keyof Schema & string>(table: Table): ISaveBuilder<Schema[Table]>;
888
+ /**
889
+ * Save one or many entities immediately.
890
+ *
891
+ * @example
892
+ * ```ts
893
+ * await db.save(
894
+ * 'Role',
895
+ * [{ id: 'admin', permissions: [{ id: 'perm1', roleId: 'admin' }] }],
896
+ * { relationships: ['permissions:Permission(roleId, id)'] }
897
+ * );
898
+ * ```
899
+ *
900
+ * The `relationships` option accepts cascade strings in the form
901
+ * `graphName:TypeName(targetField, sourceField)` describing how child records relate to the
902
+ * parent. Use {@link cascadeBuilder} to construct them safely.
903
+ *
904
+ * @param table Table to save into.
905
+ * @param entityOrEntities Object or array of objects to persist.
906
+ * @param options Optional settings for the save operation.
907
+ * @param options.relationships Cascade relationships to include.
908
+ */
909
+ save<Table extends keyof Schema & string>(table: Table, entityOrEntities: Partial<Schema[Table]> | Array<Partial<Schema[Table]>>, options?: {
910
+ relationships?: string[];
911
+ }): Promise<unknown>;
912
+ /**
913
+ * Save many entities in configurable batches.
914
+ *
915
+ * @example
916
+ * ```ts
917
+ * await db.batchSave('User', users, 500);
918
+ * ```
919
+ *
920
+ * @param table Table to save into.
921
+ * @param entities Array of entities to persist.
922
+ * @param batchSize Number of entities per batch; defaults to 1000.
923
+ */
924
+ batchSave<Table extends keyof Schema & string>(table: Table, entities: Array<Partial<Schema[Table]>>, batchSize?: number, options?: {
925
+ relationships?: string[];
926
+ }): Promise<void>;
927
+ /**
928
+ * Retrieve an entity by its primary key.
929
+ *
930
+ * @example
931
+ * ```ts
932
+ * const user = await db.findById('User', 'user_1', {
933
+ * partition: 'tenantA',
934
+ * resolvers: ['profile']
935
+ * });
936
+ * ```
937
+ *
938
+ * @param table Table to search.
939
+ * @param primaryKey Primary key value.
940
+ * @param options Optional partition and resolver settings.
941
+ */
942
+ findById<Table extends keyof Schema & string, T = Schema[Table]>(table: Table, primaryKey: string, options?: {
943
+ partition?: string;
944
+ resolvers?: string[];
945
+ }): Promise<T | null>;
946
+ /**
947
+ * Delete an entity by primary key.
948
+ *
949
+ * @example
950
+ * ```ts
951
+ * const deleted = await db.delete('Role', 'admin', {
952
+ * relationships: ['permissions']
953
+ * });
954
+ * ```
955
+ *
956
+ * @param table Table containing the entity.
957
+ * @param primaryKey Primary key value.
958
+ * @param options Optional partition and cascade relationships.
959
+ */
960
+ delete<Table extends keyof Schema & string, T = Schema[Table]>(table: Table, primaryKey: string, options?: {
961
+ partition?: string;
962
+ relationships?: string[];
963
+ }): Promise<T>;
964
+ /**
965
+ * Store a document (file blob) for later retrieval.
966
+ *
967
+ * @example
968
+ * ```ts
969
+ * const id = await db.saveDocument({
970
+ * path: '/docs/note.txt',
971
+ * mimeType: 'text/plain',
972
+ * content: 'hello world'
973
+ * });
974
+ * ```
975
+ */
976
+ saveDocument(doc: OnyxDocument): Promise<unknown>;
977
+ /**
978
+ * Fetch a previously saved document.
979
+ *
980
+ * @example
981
+ * ```ts
982
+ * const doc = await db.getDocument('doc123', { width: 640, height: 480 });
983
+ * ```
984
+ *
985
+ * @param documentId ID of the document to fetch.
986
+ * @param options Optional image resize settings.
987
+ */
988
+ getDocument(documentId: string, options?: {
989
+ width?: number;
990
+ height?: number;
991
+ }): Promise<unknown>;
992
+ /**
993
+ * Remove a stored document permanently.
994
+ *
995
+ * @example
996
+ * ```ts
997
+ * await db.deleteDocument('doc123');
998
+ * ```
999
+ *
1000
+ * @param documentId ID of the document to delete.
1001
+ */
1002
+ deleteDocument(documentId: string): Promise<unknown>;
1003
+ /**
1004
+ * Cancels active streams; safe to call multiple times.
1005
+ * @example
1006
+ * ```ts
1007
+ * const stream = await db.from('User').stream();
1008
+ * stream.cancel();
1009
+ * db.close();
1010
+ * ```
1011
+ */
1012
+ close(): void;
1013
+ }
1014
+ interface OnyxFacade {
1015
+ /**
1016
+ * Initialize a database client.
1017
+ *
1018
+ * @example
1019
+ * ```ts
1020
+ * const db = onyx.init({
1021
+ * baseUrl: 'https://api.onyx.dev',
1022
+ * databaseId: 'my-db',
1023
+ * apiKey: 'key',
1024
+ * apiSecret: 'secret'
1025
+ * });
1026
+ * ```
1027
+ *
1028
+ * @param config Connection settings and optional custom fetch.
1029
+ * @remarks
1030
+ * Each `db` instance resolves configuration once and holds a single internal
1031
+ * HTTP client. Requests leverage Node's built-in `fetch`, which reuses and
1032
+ * pools connections for keep-alive, so additional connection caching or
1033
+ * pooling is rarely necessary.
1034
+ */
1035
+ init<Schema = Record<string, unknown>>(config?: OnyxConfig): IOnyxDatabase<Schema>;
1036
+ /**
1037
+ * Clear cached configuration so the next {@link init} call re-resolves
1038
+ * credentials immediately.
1039
+ */
1040
+ clearCacheConfig(): void;
1041
+ }
1042
+
1043
+ /** -------------------------
1044
+ * Facade export
1045
+ * --------------------------*/
1046
+ declare const onyx: OnyxFacade;
1047
+
1048
+ declare const asc: (field: string) => Sort;
1049
+ declare const desc: (field: string) => Sort;
1050
+
1051
+ /** Builder for combining query conditions with logical operators. */
1052
+ declare class ConditionBuilderImpl implements IConditionBuilder {
1053
+ private condition;
1054
+ /**
1055
+ * Initialize with an optional starting criteria.
1056
+ *
1057
+ * @param criteria Initial query criteria to seed the builder.
1058
+ * @example
1059
+ * ```ts
1060
+ * const builder = new ConditionBuilderImpl({ field: 'id', operator: 'eq', value: '1' });
1061
+ * ```
1062
+ */
1063
+ constructor(criteria?: QueryCriteria | null);
1064
+ /**
1065
+ * Add a criteria combined with AND.
1066
+ *
1067
+ * @param condition Another builder or raw criteria to AND.
1068
+ * @example
1069
+ * ```ts
1070
+ * builder.and({ field: 'name', operator: 'eq', value: 'Ada' });
1071
+ * ```
1072
+ */
1073
+ and(condition: IConditionBuilder | QueryCriteria): IConditionBuilder;
1074
+ /**
1075
+ * Add a criteria combined with OR.
1076
+ *
1077
+ * @param condition Another builder or raw criteria to OR.
1078
+ * @example
1079
+ * ```ts
1080
+ * builder.or({ field: 'status', operator: 'eq', value: 'active' });
1081
+ * ```
1082
+ */
1083
+ or(condition: IConditionBuilder | QueryCriteria): IConditionBuilder;
1084
+ /**
1085
+ * Produce the composed QueryCondition.
1086
+ *
1087
+ * @example
1088
+ * ```ts
1089
+ * const condition = builder.toCondition();
1090
+ * ```
1091
+ */
1092
+ toCondition(): QueryCondition;
1093
+ /**
1094
+ * Wrap raw criteria into a single condition object.
1095
+ *
1096
+ * @param criteria Criteria to wrap.
1097
+ * @example
1098
+ * ```ts
1099
+ * builder['single']({ field: 'id', operator: 'eq', value: '1' });
1100
+ * ```
1101
+ */
1102
+ private single;
1103
+ /**
1104
+ * Create a compound condition using the provided operator.
1105
+ *
1106
+ * @param operator Logical operator to apply.
1107
+ * @param conditions Child conditions to combine.
1108
+ * @example
1109
+ * ```ts
1110
+ * builder['compound']('AND', [condA, condB]);
1111
+ * ```
1112
+ */
1113
+ private compound;
1114
+ /**
1115
+ * Merge the next condition into the existing tree using the operator.
1116
+ *
1117
+ * @param operator Logical operator for the merge.
1118
+ * @param next Condition to merge into the tree.
1119
+ * @example
1120
+ * ```ts
1121
+ * builder['addCompound']('AND', someCondition);
1122
+ * ```
1123
+ */
1124
+ private addCompound;
1125
+ /**
1126
+ * Normalize input into a QueryCondition instance.
1127
+ *
1128
+ * @param condition Builder or raw criteria to normalize.
1129
+ * @example
1130
+ * ```ts
1131
+ * const qc = builder['prepare']({ field: 'id', operator: 'eq', value: '1' });
1132
+ * ```
1133
+ */
1134
+ private prepare;
1135
+ }
1136
+
1137
+ declare const eq: (field: string, value: unknown) => ConditionBuilderImpl;
1138
+ declare const neq: (field: string, value: unknown) => ConditionBuilderImpl;
1139
+ declare const inOp: (field: string, values: unknown[] | string) => ConditionBuilderImpl;
1140
+ declare const notIn: (field: string, values: unknown[]) => ConditionBuilderImpl;
1141
+ declare const between: (field: string, lower: unknown, upper: unknown) => ConditionBuilderImpl;
1142
+ declare const gt: (field: string, value: unknown) => ConditionBuilderImpl;
1143
+ declare const gte: (field: string, value: unknown) => ConditionBuilderImpl;
1144
+ declare const lt: (field: string, value: unknown) => ConditionBuilderImpl;
1145
+ declare const lte: (field: string, value: unknown) => ConditionBuilderImpl;
1146
+ declare const matches: (field: string, regex: string) => ConditionBuilderImpl;
1147
+ declare const notMatches: (field: string, regex: string) => ConditionBuilderImpl;
1148
+ declare const like: (field: string, pattern: string) => ConditionBuilderImpl;
1149
+ declare const notLike: (field: string, pattern: string) => ConditionBuilderImpl;
1150
+ declare const contains: (field: string, value: unknown) => ConditionBuilderImpl;
1151
+ declare const containsIgnoreCase: (field: string, value: unknown) => ConditionBuilderImpl;
1152
+ declare const notContains: (field: string, value: unknown) => ConditionBuilderImpl;
1153
+ declare const notContainsIgnoreCase: (field: string, value: unknown) => ConditionBuilderImpl;
1154
+ declare const startsWith: (field: string, prefix: string) => ConditionBuilderImpl;
1155
+ declare const notStartsWith: (field: string, prefix: string) => ConditionBuilderImpl;
1156
+ declare const isNull: (field: string) => ConditionBuilderImpl;
1157
+ declare const notNull: (field: string) => ConditionBuilderImpl;
1158
+
1159
+ declare const avg: (attribute: string) => string;
1160
+ declare const sum: (attribute: string) => string;
1161
+ declare const count: (attribute: string) => string;
1162
+ declare const min: (attribute: string) => string;
1163
+ declare const max: (attribute: string) => string;
1164
+ declare const std: (attribute: string) => string;
1165
+ declare const variance: (attribute: string) => string;
1166
+ declare const median: (attribute: string) => string;
1167
+ declare const upper: (attribute: string) => string;
1168
+ declare const lower: (attribute: string) => string;
1169
+ declare const substring: (attribute: string, from: number, length: number) => string;
1170
+ declare const replace: (attribute: string, pattern: string, repl: string) => string;
1171
+ declare const percentile: (attribute: string, p: number) => string;
1172
+
1173
+ declare const sdkName = "@onyx.dev/onyx-database";
1174
+ declare const sdkVersion = "0.1.0";
1175
+
1176
+ export { type FetchImpl, type FetchResponse, type ICascadeBuilder, type ICascadeRelationshipBuilder, type IConditionBuilder, type IOnyxDatabase, type IQueryBuilder, type ISaveBuilder, type LogicalOperator, type OnyxConfig, type OnyxDocument, type OnyxFacade, type QueryCondition, type QueryCriteria, type QueryCriteriaOperator, type QueryPage, QueryResults, type QueryResultsPromise, type SelectQuery, type Sort, type StreamAction, type UpdateQuery, asc, avg, between, contains, containsIgnoreCase, count, desc, eq, gt, gte, inOp, isNull, like, lower, lt, lte, matches, max, median, min, neq, notContains, notContainsIgnoreCase, notIn, notLike, notMatches, notNull, notStartsWith, onyx, percentile, replace, sdkName, sdkVersion, startsWith, std, substring, sum, upper, variance };