@mdxui/terminal 2.0.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 +571 -0
- package/dist/ansi-css-Sk5mWtdK.d.ts +119 -0
- package/dist/ansi-css-V6JIHGsM.d.ts +119 -0
- package/dist/ansi-css-_3eSEU9d.d.ts +119 -0
- package/dist/chunk-3EFDH7PK.js +5235 -0
- package/dist/chunk-3RG5ZIWI.js +10 -0
- package/dist/chunk-3X5IR6WE.js +884 -0
- package/dist/chunk-4FV5ZDCE.js +5236 -0
- package/dist/chunk-4OVMSF2J.js +243 -0
- package/dist/chunk-63FEETIS.js +4048 -0
- package/dist/chunk-B43KP7XJ.js +884 -0
- package/dist/chunk-BMTJXWUV.js +655 -0
- package/dist/chunk-C3SVH4N7.js +882 -0
- package/dist/chunk-EVWR7Y47.js +874 -0
- package/dist/chunk-F6A5VWUC.js +1285 -0
- package/dist/chunk-FD7KW7GE.js +882 -0
- package/dist/chunk-GBQ6UD6I.js +655 -0
- package/dist/chunk-GMDD3M6U.js +5227 -0
- package/dist/chunk-JBHRXOXM.js +1058 -0
- package/dist/chunk-JFOO3EYO.js +1182 -0
- package/dist/chunk-JQ5H3WXL.js +1291 -0
- package/dist/chunk-JQD5NASE.js +234 -0
- package/dist/chunk-KRHJP5R7.js +592 -0
- package/dist/chunk-KWF6WVJE.js +962 -0
- package/dist/chunk-LHYQVN3H.js +1038 -0
- package/dist/chunk-M3TLQLGC.js +1032 -0
- package/dist/chunk-MVW4Q5OP.js +240 -0
- package/dist/chunk-NXCZSWLU.js +1294 -0
- package/dist/chunk-O25TNRO6.js +607 -0
- package/dist/chunk-PNECDA2I.js +884 -0
- package/dist/chunk-QIHWRLJR.js +962 -0
- package/dist/chunk-QW5YMQ7K.js +882 -0
- package/dist/chunk-R5U7XKVJ.js +16 -0
- package/dist/chunk-RP2MVQLR.js +962 -0
- package/dist/chunk-TP6RXGXA.js +1087 -0
- package/dist/chunk-TQQSTITZ.js +655 -0
- package/dist/chunk-X24GWXQV.js +1281 -0
- package/dist/components/index.d.ts +802 -0
- package/dist/components/index.js +149 -0
- package/dist/data/index.d.ts +2554 -0
- package/dist/data/index.js +51 -0
- package/dist/forms/index.d.ts +1596 -0
- package/dist/forms/index.js +464 -0
- package/dist/index-CQRFZntR.d.ts +867 -0
- package/dist/index.d.ts +579 -0
- package/dist/index.js +786 -0
- package/dist/interactive-D0JkWosD.d.ts +217 -0
- package/dist/keyboard/index.d.ts +2 -0
- package/dist/keyboard/index.js +43 -0
- package/dist/renderers/index.d.ts +546 -0
- package/dist/renderers/index.js +2157 -0
- package/dist/storybook/index.d.ts +396 -0
- package/dist/storybook/index.js +641 -0
- package/dist/theme/index.d.ts +1339 -0
- package/dist/theme/index.js +123 -0
- package/dist/types-Bxu5PAgA.d.ts +710 -0
- package/dist/types-CIlop5Ji.d.ts +701 -0
- package/dist/types-Ca8p_p5X.d.ts +710 -0
- package/package.json +90 -0
- package/src/__tests__/components/data/card.test.ts +458 -0
- package/src/__tests__/components/data/list.test.ts +473 -0
- package/src/__tests__/components/data/metrics.test.ts +541 -0
- package/src/__tests__/components/data/table.test.ts +448 -0
- package/src/__tests__/components/input/field.test.ts +555 -0
- package/src/__tests__/components/input/form.test.ts +870 -0
- package/src/__tests__/components/input/search.test.ts +1238 -0
- package/src/__tests__/components/input/select.test.ts +658 -0
- package/src/__tests__/components/navigation/breadcrumb.test.ts +923 -0
- package/src/__tests__/components/navigation/command-palette.test.ts +1095 -0
- package/src/__tests__/components/navigation/sidebar.test.ts +1018 -0
- package/src/__tests__/components/navigation/tabs.test.ts +995 -0
- package/src/__tests__/components.test.tsx +1197 -0
- package/src/__tests__/core/compiler.test.ts +986 -0
- package/src/__tests__/core/parser.test.ts +785 -0
- package/src/__tests__/core/tier-switcher.test.ts +1103 -0
- package/src/__tests__/core/types.test.ts +1398 -0
- package/src/__tests__/data/collections.test.ts +1337 -0
- package/src/__tests__/data/db.test.ts +1265 -0
- package/src/__tests__/data/reactive.test.ts +1010 -0
- package/src/__tests__/data/sync.test.ts +1614 -0
- package/src/__tests__/errors.test.ts +660 -0
- package/src/__tests__/forms/integration.test.ts +444 -0
- package/src/__tests__/integration.test.ts +905 -0
- package/src/__tests__/keyboard.test.ts +1791 -0
- package/src/__tests__/renderer.test.ts +489 -0
- package/src/__tests__/renderers/ansi-css.test.ts +948 -0
- package/src/__tests__/renderers/ansi.test.ts +1366 -0
- package/src/__tests__/renderers/ascii.test.ts +1360 -0
- package/src/__tests__/renderers/interactive.test.ts +2353 -0
- package/src/__tests__/renderers/markdown.test.ts +1483 -0
- package/src/__tests__/renderers/text.test.ts +1369 -0
- package/src/__tests__/renderers/unicode.test.ts +1307 -0
- package/src/__tests__/theme.test.ts +639 -0
- package/src/__tests__/utils/assertions.ts +685 -0
- package/src/__tests__/utils/index.ts +115 -0
- package/src/__tests__/utils/test-renderer.ts +381 -0
- package/src/__tests__/utils/utils.test.ts +560 -0
- package/src/components/containers/card.ts +56 -0
- package/src/components/containers/dialog.ts +53 -0
- package/src/components/containers/index.ts +9 -0
- package/src/components/containers/panel.ts +59 -0
- package/src/components/feedback/badge.ts +40 -0
- package/src/components/feedback/index.ts +8 -0
- package/src/components/feedback/spinner.ts +23 -0
- package/src/components/helpers.ts +81 -0
- package/src/components/index.ts +153 -0
- package/src/components/layout/breadcrumb.ts +31 -0
- package/src/components/layout/index.ts +10 -0
- package/src/components/layout/list.ts +29 -0
- package/src/components/layout/sidebar.ts +79 -0
- package/src/components/layout/table.ts +62 -0
- package/src/components/primitives/box.ts +95 -0
- package/src/components/primitives/button.ts +54 -0
- package/src/components/primitives/index.ts +11 -0
- package/src/components/primitives/input.ts +88 -0
- package/src/components/primitives/select.ts +97 -0
- package/src/components/primitives/text.ts +60 -0
- package/src/components/render.ts +155 -0
- package/src/components/templates/app.ts +43 -0
- package/src/components/templates/index.ts +8 -0
- package/src/components/templates/site.ts +54 -0
- package/src/components/types.ts +777 -0
- package/src/core/compiler.ts +718 -0
- package/src/core/parser.ts +127 -0
- package/src/core/tier-switcher.ts +607 -0
- package/src/core/types.ts +672 -0
- package/src/data/collection.ts +316 -0
- package/src/data/collections.ts +50 -0
- package/src/data/context.tsx +174 -0
- package/src/data/db.ts +127 -0
- package/src/data/hooks.ts +532 -0
- package/src/data/index.ts +138 -0
- package/src/data/reactive.ts +1225 -0
- package/src/data/saas-collections.ts +375 -0
- package/src/data/sync.ts +1213 -0
- package/src/data/types.ts +660 -0
- package/src/forms/converters.ts +512 -0
- package/src/forms/index.ts +133 -0
- package/src/forms/schemas.ts +403 -0
- package/src/forms/types.ts +476 -0
- package/src/index.ts +542 -0
- package/src/keyboard/focus.ts +748 -0
- package/src/keyboard/index.ts +96 -0
- package/src/keyboard/integration.ts +371 -0
- package/src/keyboard/manager.ts +377 -0
- package/src/keyboard/presets.ts +90 -0
- package/src/renderers/ansi-css.ts +576 -0
- package/src/renderers/ansi.ts +802 -0
- package/src/renderers/ascii.ts +680 -0
- package/src/renderers/breadcrumb.ts +480 -0
- package/src/renderers/command-palette.ts +802 -0
- package/src/renderers/components/field.ts +210 -0
- package/src/renderers/components/form.ts +327 -0
- package/src/renderers/components/index.ts +21 -0
- package/src/renderers/components/search.ts +449 -0
- package/src/renderers/components/select.ts +222 -0
- package/src/renderers/index.ts +101 -0
- package/src/renderers/interactive/component-handlers.ts +622 -0
- package/src/renderers/interactive/cursor-manager.ts +147 -0
- package/src/renderers/interactive/focus-manager.ts +279 -0
- package/src/renderers/interactive/index.ts +661 -0
- package/src/renderers/interactive/input-handler.ts +164 -0
- package/src/renderers/interactive/keyboard-handler.ts +212 -0
- package/src/renderers/interactive/mouse-handler.ts +167 -0
- package/src/renderers/interactive/state-manager.ts +109 -0
- package/src/renderers/interactive/types.ts +338 -0
- package/src/renderers/interactive-string.ts +299 -0
- package/src/renderers/interactive.ts +59 -0
- package/src/renderers/markdown.ts +950 -0
- package/src/renderers/sidebar.ts +549 -0
- package/src/renderers/tabs.ts +682 -0
- package/src/renderers/text.ts +791 -0
- package/src/renderers/unicode.ts +917 -0
- package/src/renderers/utils.ts +942 -0
- package/src/router/adapters.ts +383 -0
- package/src/router/types.ts +140 -0
- package/src/router/utils.ts +452 -0
- package/src/schemas.ts +205 -0
- package/src/storybook/index.ts +91 -0
- package/src/storybook/interactive-decorator.tsx +659 -0
- package/src/storybook/keyboard-simulator.ts +501 -0
- package/src/theme/ansi-codes.ts +80 -0
- package/src/theme/box-drawing.ts +132 -0
- package/src/theme/color-convert.ts +254 -0
- package/src/theme/color-support.ts +321 -0
- package/src/theme/index.ts +134 -0
- package/src/theme/strip-ansi.ts +50 -0
- package/src/theme/tailwind-map.ts +469 -0
- package/src/theme/text-styles.ts +206 -0
- package/src/theme/theme-system.ts +568 -0
- package/src/types.ts +103 -0
|
@@ -0,0 +1,660 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @mdxui/terminal Data Layer Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for the TanStack DB-like integration.
|
|
5
|
+
* Provides a type-safe, reactive in-memory database with Zod validation,
|
|
6
|
+
* filtering, sorting, pagination, and optimistic updates.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { ZodSchema, ZodRawShape, z } from 'zod'
|
|
10
|
+
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Query Filter Types
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Comparison operators for filtering database queries
|
|
17
|
+
*
|
|
18
|
+
* @template T - The type of the field being compared
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* // Using comparison operators in a where clause
|
|
23
|
+
* {
|
|
24
|
+
* $eq: 5, // Equal to 5
|
|
25
|
+
* $ne: 10, // Not equal to 10
|
|
26
|
+
* $gt: 3, // Greater than 3
|
|
27
|
+
* $gte: 3, // Greater than or equal to 3
|
|
28
|
+
* $lt: 100, // Less than 100
|
|
29
|
+
* $lte: 100, // Less than or equal to 100
|
|
30
|
+
* $in: [1, 2, 3], // In array [1, 2, 3]
|
|
31
|
+
* $nin: [1, 2, 3], // Not in array [1, 2, 3]
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export interface ComparisonOperators<T> {
|
|
36
|
+
/** Equality match */
|
|
37
|
+
$eq?: T
|
|
38
|
+
/** Not equal to */
|
|
39
|
+
$ne?: T
|
|
40
|
+
/** Greater than */
|
|
41
|
+
$gt?: T
|
|
42
|
+
/** Greater than or equal to */
|
|
43
|
+
$gte?: T
|
|
44
|
+
/** Less than */
|
|
45
|
+
$lt?: T
|
|
46
|
+
/** Less than or equal to */
|
|
47
|
+
$lte?: T
|
|
48
|
+
/** Value is in array */
|
|
49
|
+
$in?: T[]
|
|
50
|
+
/** Value is not in array */
|
|
51
|
+
$nin?: T[]
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Field filter - either a direct value for equality or comparison operators
|
|
56
|
+
*
|
|
57
|
+
* @template T - The type of the field
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* // Direct equality
|
|
62
|
+
* type Filter = FieldFilter<number> // number
|
|
63
|
+
* const filter: Filter = 5
|
|
64
|
+
*
|
|
65
|
+
* // With operators
|
|
66
|
+
* const filter: Filter = { $gt: 5 }
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export type FieldFilter<T> = T | ComparisonOperators<T>
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Where clause for filtering - supports equality, comparison operators, and $or
|
|
73
|
+
*
|
|
74
|
+
* @template T - The document type being queried
|
|
75
|
+
*
|
|
76
|
+
* @remarks
|
|
77
|
+
* - Uses AND logic for multiple field conditions
|
|
78
|
+
* - `$or` is an array of alternative conditions (OR logic)
|
|
79
|
+
* - Can combine $or with other fields (fields AND ($or[...]))
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* // Simple equality
|
|
84
|
+
* const where: WhereClause<User> = { role: 'admin' }
|
|
85
|
+
*
|
|
86
|
+
* // With comparison operators
|
|
87
|
+
* const where: WhereClause<User> = { age: { $gte: 18 } }
|
|
88
|
+
*
|
|
89
|
+
* // Multiple conditions (AND)
|
|
90
|
+
* const where: WhereClause<User> = {
|
|
91
|
+
* role: 'admin',
|
|
92
|
+
* age: { $gte: 18 }
|
|
93
|
+
* }
|
|
94
|
+
*
|
|
95
|
+
* // OR conditions
|
|
96
|
+
* const where: WhereClause<User> = {
|
|
97
|
+
* $or: [
|
|
98
|
+
* { role: 'admin' },
|
|
99
|
+
* { role: 'moderator' }
|
|
100
|
+
* ]
|
|
101
|
+
* }
|
|
102
|
+
*
|
|
103
|
+
* // Combined AND/OR
|
|
104
|
+
* const where: WhereClause<User> = {
|
|
105
|
+
* status: 'active',
|
|
106
|
+
* $or: [
|
|
107
|
+
* { role: 'admin' },
|
|
108
|
+
* { role: 'moderator' }
|
|
109
|
+
* ]
|
|
110
|
+
* }
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export type WhereClause<T> = {
|
|
114
|
+
[K in keyof T]?: FieldFilter<T[K]>
|
|
115
|
+
} & {
|
|
116
|
+
$or?: Array<WhereClause<T>>
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Sort direction for ordering results
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```typescript
|
|
124
|
+
* type Direction = OrderDirection
|
|
125
|
+
* const ascending: Direction = 'asc'
|
|
126
|
+
* const descending: Direction = 'desc'
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
export type OrderDirection = 'asc' | 'desc'
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Order by clause for sorting results
|
|
133
|
+
*
|
|
134
|
+
* @template T - The document type being sorted
|
|
135
|
+
*
|
|
136
|
+
* @remarks
|
|
137
|
+
* Maps field names to sort directions (asc/desc)
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```typescript
|
|
141
|
+
* // Sort by age ascending
|
|
142
|
+
* const orderBy: OrderByClause<User> = { age: 'asc' }
|
|
143
|
+
*
|
|
144
|
+
* // Sort by multiple fields
|
|
145
|
+
* const orderByArray: OrderByClause<User>[] = [
|
|
146
|
+
* { role: 'asc' },
|
|
147
|
+
* { age: 'desc' }
|
|
148
|
+
* ]
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
export type OrderByClause<T> = {
|
|
152
|
+
[K in keyof T]?: OrderDirection
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ============================================================================
|
|
156
|
+
// Collection Types
|
|
157
|
+
// ============================================================================
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Configuration for creating a collection
|
|
161
|
+
*
|
|
162
|
+
* @template T - The Zod schema shape for the collection
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* ```typescript
|
|
166
|
+
* const config: CollectionConfig<typeof UserSchema.shape> = {
|
|
167
|
+
* name: 'users',
|
|
168
|
+
* schema: UserSchema,
|
|
169
|
+
* primaryKey: 'id',
|
|
170
|
+
* indexes: ['email', 'role']
|
|
171
|
+
* }
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
export interface CollectionConfig<T extends ZodRawShape> {
|
|
175
|
+
/** Collection name - used to reference in queries */
|
|
176
|
+
name: string
|
|
177
|
+
/** Zod schema for automatic validation on insert/update */
|
|
178
|
+
schema: ZodSchema<z.infer<z.ZodObject<T>>>
|
|
179
|
+
/** Primary key field (defaults to 'id'). Used for duplicate detection */
|
|
180
|
+
primaryKey?: keyof z.infer<z.ZodObject<T>>
|
|
181
|
+
/** Fields to index for faster queries (metadata only, used for optimization hints) */
|
|
182
|
+
indexes?: Array<keyof z.infer<z.ZodObject<T>>>
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* A typed in-memory collection with CRUD operations, filtering, sorting, and reactive subscriptions
|
|
187
|
+
*
|
|
188
|
+
* @template T - The document type stored in this collection
|
|
189
|
+
*
|
|
190
|
+
* @remarks
|
|
191
|
+
* - All documents are validated against the schema on insert/update
|
|
192
|
+
* - Provides reactive subscriptions for real-time updates
|
|
193
|
+
* - Supports filtering with where clauses and comparison operators
|
|
194
|
+
* - Supports sorting with orderBy and multiple sort fields
|
|
195
|
+
* - Supports pagination with limit and offset
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```typescript
|
|
199
|
+
* const collection = createCollection<User>({
|
|
200
|
+
* name: 'users',
|
|
201
|
+
* schema: UserSchema
|
|
202
|
+
* })
|
|
203
|
+
*
|
|
204
|
+
* // CRUD operations
|
|
205
|
+
* const user = await collection.insert({ id: '1', name: 'Alice', ... })
|
|
206
|
+
* const updated = await collection.update({ id: '1' }, { name: 'Alicia' })
|
|
207
|
+
* const found = await collection.findOne({ id: '1' })
|
|
208
|
+
* const all = await collection.findMany()
|
|
209
|
+
* await collection.delete({ id: '1' })
|
|
210
|
+
*
|
|
211
|
+
* // Subscribe to changes
|
|
212
|
+
* const unsubscribe = collection.subscribe((data) => {
|
|
213
|
+
* console.log('Collection changed:', data)
|
|
214
|
+
* })
|
|
215
|
+
* ```
|
|
216
|
+
*/
|
|
217
|
+
export interface Collection<T> {
|
|
218
|
+
/** Collection name - used to reference in queries */
|
|
219
|
+
name: string
|
|
220
|
+
/** Zod schema for validation */
|
|
221
|
+
schema: ZodSchema<T>
|
|
222
|
+
/** Primary key field name */
|
|
223
|
+
primaryKey: string
|
|
224
|
+
/** Indexed field names */
|
|
225
|
+
indexes: string[]
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Insert a new document into the collection
|
|
229
|
+
*
|
|
230
|
+
* @param data - Document to insert (must match schema)
|
|
231
|
+
* @returns The validated document
|
|
232
|
+
* @throws If document fails schema validation or primary key already exists
|
|
233
|
+
*/
|
|
234
|
+
insert(data: T): Promise<T>
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Update one or more documents matching the filter
|
|
238
|
+
*
|
|
239
|
+
* @param filter - Documents matching this filter will be updated
|
|
240
|
+
* @param data - Partial updates to apply (merged with existing data)
|
|
241
|
+
* @returns Array of updated documents
|
|
242
|
+
* @throws If updated documents fail schema validation
|
|
243
|
+
*/
|
|
244
|
+
update(filter: Partial<T>, data: Partial<T>): Promise<T[]>
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Delete one or more documents matching the filter
|
|
248
|
+
*
|
|
249
|
+
* @param filter - Documents matching this filter will be deleted
|
|
250
|
+
* @returns void
|
|
251
|
+
*/
|
|
252
|
+
delete(filter: Partial<T>): Promise<void>
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Find a single document matching the filter
|
|
256
|
+
*
|
|
257
|
+
* @param filter - Equality filter conditions
|
|
258
|
+
* @returns First matching document or null if not found
|
|
259
|
+
*/
|
|
260
|
+
findOne(filter: Partial<T>): Promise<T | null>
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Find multiple documents with optional filtering, sorting, and pagination
|
|
264
|
+
*
|
|
265
|
+
* @param options - Query options (where, orderBy, limit, offset)
|
|
266
|
+
* @returns Array of matching documents
|
|
267
|
+
*
|
|
268
|
+
* @example
|
|
269
|
+
* ```typescript
|
|
270
|
+
* // Get all
|
|
271
|
+
* const all = await collection.findMany()
|
|
272
|
+
*
|
|
273
|
+
* // With filter
|
|
274
|
+
* const admins = await collection.findMany({
|
|
275
|
+
* where: { role: 'admin' }
|
|
276
|
+
* })
|
|
277
|
+
*
|
|
278
|
+
* // With sorting and pagination
|
|
279
|
+
* const page = await collection.findMany({
|
|
280
|
+
* where: { status: 'active' },
|
|
281
|
+
* orderBy: { createdAt: 'desc' },
|
|
282
|
+
* limit: 20,
|
|
283
|
+
* offset: 0
|
|
284
|
+
* })
|
|
285
|
+
* ```
|
|
286
|
+
*/
|
|
287
|
+
findMany(options?: FindManyOptions<T>): Promise<T[]>
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Subscribe to collection changes
|
|
291
|
+
*
|
|
292
|
+
* @param callback - Called whenever data changes with current full collection state
|
|
293
|
+
* @returns Unsubscribe function to remove listener
|
|
294
|
+
*
|
|
295
|
+
* @example
|
|
296
|
+
* ```typescript
|
|
297
|
+
* const unsubscribe = collection.subscribe((data) => {
|
|
298
|
+
* console.log('Collection now contains:', data)
|
|
299
|
+
* })
|
|
300
|
+
*
|
|
301
|
+
* // Later: stop listening
|
|
302
|
+
* unsubscribe()
|
|
303
|
+
* ```
|
|
304
|
+
*/
|
|
305
|
+
subscribe(callback: (data: T[]) => void): () => void
|
|
306
|
+
|
|
307
|
+
/** Internal: notify all subscribers of changes */
|
|
308
|
+
_notify(): void
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// ============================================================================
|
|
312
|
+
// Database Types
|
|
313
|
+
// ============================================================================
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Sync adapter interface for remote synchronization
|
|
317
|
+
*
|
|
318
|
+
* @remarks
|
|
319
|
+
* Implement this interface to add custom sync behavior (WebSockets, server polling, etc.)
|
|
320
|
+
* The database automatically calls these methods when mutations occur (if optimistic mode enabled)
|
|
321
|
+
*
|
|
322
|
+
* @example
|
|
323
|
+
* ```typescript
|
|
324
|
+
* const syncAdapter: SyncAdapter = {
|
|
325
|
+
* async push(changes) {
|
|
326
|
+
* // Send to server
|
|
327
|
+
* await fetch('/api/sync', { method: 'POST', body: JSON.stringify(changes) })
|
|
328
|
+
* },
|
|
329
|
+
* async pull() {
|
|
330
|
+
* // Get from server
|
|
331
|
+
* const res = await fetch('/api/sync')
|
|
332
|
+
* return res.json()
|
|
333
|
+
* },
|
|
334
|
+
* subscribe(callback) {
|
|
335
|
+
* // Listen for remote changes
|
|
336
|
+
* const ws = new WebSocket('wss://...')
|
|
337
|
+
* ws.onmessage = (e) => callback(e.data)
|
|
338
|
+
* return () => ws.close()
|
|
339
|
+
* }
|
|
340
|
+
* }
|
|
341
|
+
* ```
|
|
342
|
+
*/
|
|
343
|
+
export interface SyncAdapter {
|
|
344
|
+
/**
|
|
345
|
+
* Push local changes to remote
|
|
346
|
+
*
|
|
347
|
+
* @param changes - Array of change objects to send to remote
|
|
348
|
+
* @throws Error if push fails - mutation will be rolled back if optimistic
|
|
349
|
+
*/
|
|
350
|
+
push(changes: unknown[]): Promise<void>
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Pull remote changes
|
|
354
|
+
*
|
|
355
|
+
* @returns Array of changes from remote
|
|
356
|
+
*/
|
|
357
|
+
pull(): Promise<unknown[]>
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Subscribe to remote changes
|
|
361
|
+
*
|
|
362
|
+
* @param callback - Called with remote changes
|
|
363
|
+
* @returns Unsubscribe function
|
|
364
|
+
*/
|
|
365
|
+
subscribe(callback: (changes: unknown[]) => void): () => void
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Database configuration for creating a DB instance
|
|
370
|
+
*
|
|
371
|
+
* @example
|
|
372
|
+
* ```typescript
|
|
373
|
+
* const config: DBConfig = {
|
|
374
|
+
* collections: [usersCollection, todosCollection],
|
|
375
|
+
* sync: customSyncAdapter
|
|
376
|
+
* }
|
|
377
|
+
* ```
|
|
378
|
+
*/
|
|
379
|
+
export interface DBConfig {
|
|
380
|
+
/** Collections to register in the database */
|
|
381
|
+
collections?: Collection<any>[]
|
|
382
|
+
/** Optional sync adapter for remote synchronization */
|
|
383
|
+
sync?: SyncAdapter
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Database instance - main entry point for accessing collections and syncing
|
|
388
|
+
*
|
|
389
|
+
* @remarks
|
|
390
|
+
* - Collections are accessed by name via `db.collections[name]`
|
|
391
|
+
* - Provides centralized management of all collections
|
|
392
|
+
* - Optional sync adapter for remote data synchronization
|
|
393
|
+
*
|
|
394
|
+
* @example
|
|
395
|
+
* ```typescript
|
|
396
|
+
* const db = createDB({
|
|
397
|
+
* collections: [usersCollection, todosCollection],
|
|
398
|
+
* sync: syncAdapter
|
|
399
|
+
* })
|
|
400
|
+
*
|
|
401
|
+
* // Access collections
|
|
402
|
+
* const users = await db.collections.users.findMany()
|
|
403
|
+
*
|
|
404
|
+
* // Clear all data
|
|
405
|
+
* await db.clear()
|
|
406
|
+
*
|
|
407
|
+
* // Close resources
|
|
408
|
+
* db.close()
|
|
409
|
+
* ```
|
|
410
|
+
*/
|
|
411
|
+
export interface DB {
|
|
412
|
+
/** Registered collections by name - access with `db.collections[collectionName]` */
|
|
413
|
+
collections: Record<string, Collection<any>>
|
|
414
|
+
/** Optional sync adapter if configured */
|
|
415
|
+
sync?: SyncAdapter
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Close the database connection and clean up resources
|
|
419
|
+
*/
|
|
420
|
+
close(): void
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Clear all data from all collections
|
|
424
|
+
*
|
|
425
|
+
* @returns Promise that resolves when all data is cleared
|
|
426
|
+
*/
|
|
427
|
+
clear(): Promise<void>
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// ============================================================================
|
|
431
|
+
// Hook Types
|
|
432
|
+
// ============================================================================
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Options for collection.findMany() - internal collection query
|
|
436
|
+
*
|
|
437
|
+
* @template T - The document type
|
|
438
|
+
*
|
|
439
|
+
* @remarks
|
|
440
|
+
* Unlike `QueryOptions`, this doesn't include `from` since it's called on a collection directly
|
|
441
|
+
*
|
|
442
|
+
* @example
|
|
443
|
+
* ```typescript
|
|
444
|
+
* const options: FindManyOptions<User> = {
|
|
445
|
+
* where: { role: 'admin' },
|
|
446
|
+
* orderBy: { name: 'asc' },
|
|
447
|
+
* limit: 10,
|
|
448
|
+
* offset: 0
|
|
449
|
+
* }
|
|
450
|
+
* const users = await collection.findMany(options)
|
|
451
|
+
* ```
|
|
452
|
+
*/
|
|
453
|
+
export interface FindManyOptions<T> {
|
|
454
|
+
/** Filter conditions using WhereClause syntax */
|
|
455
|
+
where?: WhereClause<T>
|
|
456
|
+
/** Sort order - single field or array of fields with directions */
|
|
457
|
+
orderBy?: OrderByClause<T> | OrderByClause<T>[]
|
|
458
|
+
/** Maximum number of results to return */
|
|
459
|
+
limit?: number
|
|
460
|
+
/** Number of results to skip (for pagination) */
|
|
461
|
+
offset?: number
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Options for useQuery hook - React hook query interface
|
|
466
|
+
*
|
|
467
|
+
* @template T - The document type being queried
|
|
468
|
+
*
|
|
469
|
+
* @remarks
|
|
470
|
+
* Extends `FindManyOptions` with `from` to specify which collection to query.
|
|
471
|
+
* Called within a `DBProvider` context.
|
|
472
|
+
*
|
|
473
|
+
* @example
|
|
474
|
+
* ```typescript
|
|
475
|
+
* const { data, isLoading, error } = useQuery<User>({
|
|
476
|
+
* from: 'users',
|
|
477
|
+
* where: { role: 'admin', age: { $gte: 18 } },
|
|
478
|
+
* orderBy: { name: 'asc' },
|
|
479
|
+
* limit: 20
|
|
480
|
+
* })
|
|
481
|
+
* ```
|
|
482
|
+
*/
|
|
483
|
+
export interface QueryOptions<T> extends FindManyOptions<T> {
|
|
484
|
+
/** Collection name to query from */
|
|
485
|
+
from: string
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* Result of useQuery hook - reactive query state and refetch control
|
|
490
|
+
*
|
|
491
|
+
* @template T - The document type
|
|
492
|
+
*
|
|
493
|
+
* @remarks
|
|
494
|
+
* - `data` starts as undefined while loading
|
|
495
|
+
* - `isLoading` is true until first query completes
|
|
496
|
+
* - Automatically updates when collection changes (reactive)
|
|
497
|
+
* - Subscribe callbacks automatically re-apply filters and sorting
|
|
498
|
+
*
|
|
499
|
+
* @example
|
|
500
|
+
* ```typescript
|
|
501
|
+
* const { data, isLoading, error, refetch } = useQuery<User>({
|
|
502
|
+
* from: 'users'
|
|
503
|
+
* })
|
|
504
|
+
*
|
|
505
|
+
* if (isLoading) return <Spinner />
|
|
506
|
+
* if (error) return <Error message={error.message} />
|
|
507
|
+
*
|
|
508
|
+
* return (
|
|
509
|
+
* <div>
|
|
510
|
+
* {data?.map(user => (
|
|
511
|
+
* <UserCard key={user.id} user={user} />
|
|
512
|
+
* ))}
|
|
513
|
+
* <button onClick={refetch}>Refresh</button>
|
|
514
|
+
* </div>
|
|
515
|
+
* )
|
|
516
|
+
* ```
|
|
517
|
+
*/
|
|
518
|
+
export interface QueryResult<T> {
|
|
519
|
+
/** Query results - undefined while loading, array when loaded */
|
|
520
|
+
data: T[] | undefined
|
|
521
|
+
/** True while initial query is executing */
|
|
522
|
+
isLoading: boolean
|
|
523
|
+
/** Error object if query failed, undefined if successful */
|
|
524
|
+
error: Error | undefined
|
|
525
|
+
/** Function to manually refetch the query */
|
|
526
|
+
refetch: () => void
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Type of mutation operation
|
|
531
|
+
*
|
|
532
|
+
* @example
|
|
533
|
+
* ```typescript
|
|
534
|
+
* type Op = MutationOperation
|
|
535
|
+
* const operation: Op = 'insert'
|
|
536
|
+
* ```
|
|
537
|
+
*/
|
|
538
|
+
export type MutationOperation = 'insert' | 'update' | 'delete'
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Options for useMutation hook
|
|
542
|
+
*
|
|
543
|
+
* @remarks
|
|
544
|
+
* - `insert`: Creates new document
|
|
545
|
+
* - `update`: Updates existing documents matching filter
|
|
546
|
+
* - `delete`: Removes documents matching filter
|
|
547
|
+
* - `optimistic`: If true, updates UI immediately before server confirmation
|
|
548
|
+
* (on error, automatically rolls back)
|
|
549
|
+
*
|
|
550
|
+
* @example
|
|
551
|
+
* ```typescript
|
|
552
|
+
* const { mutate, isPending, error } = useMutation({
|
|
553
|
+
* collection: 'users',
|
|
554
|
+
* operation: 'insert',
|
|
555
|
+
* optimistic: true
|
|
556
|
+
* })
|
|
557
|
+
* ```
|
|
558
|
+
*/
|
|
559
|
+
export interface MutationOptions {
|
|
560
|
+
/** Collection name to mutate */
|
|
561
|
+
collection: string
|
|
562
|
+
/** Type of operation: insert, update, or delete */
|
|
563
|
+
operation: MutationOperation
|
|
564
|
+
/** Enable optimistic updates (show change immediately, rollback on error) */
|
|
565
|
+
optimistic?: boolean
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Data format for update mutations
|
|
570
|
+
*
|
|
571
|
+
* @template T - The document type
|
|
572
|
+
*
|
|
573
|
+
* @example
|
|
574
|
+
* ```typescript
|
|
575
|
+
* const updateData: UpdateMutationData<User> = {
|
|
576
|
+
* where: { id: '1' },
|
|
577
|
+
* data: { name: 'Updated Name' }
|
|
578
|
+
* }
|
|
579
|
+
* ```
|
|
580
|
+
*/
|
|
581
|
+
export interface UpdateMutationData<T> {
|
|
582
|
+
/** Filter to select which documents to update */
|
|
583
|
+
where: Partial<T>
|
|
584
|
+
/** Partial updates to apply to matching documents */
|
|
585
|
+
data: Partial<T>
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* Data format for delete mutations
|
|
590
|
+
*
|
|
591
|
+
* @template T - The document type (generic for flexibility)
|
|
592
|
+
*
|
|
593
|
+
* @example
|
|
594
|
+
* ```typescript
|
|
595
|
+
* const deleteData: DeleteMutationData<User> = {
|
|
596
|
+
* id: 'user-123'
|
|
597
|
+
* }
|
|
598
|
+
* ```
|
|
599
|
+
*/
|
|
600
|
+
export interface DeleteMutationData<T> {
|
|
601
|
+
/** ID of document to delete */
|
|
602
|
+
id: string
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* Result of useMutation hook - mutation execution and state control
|
|
607
|
+
*
|
|
608
|
+
* @template T - The document type
|
|
609
|
+
*
|
|
610
|
+
* @remarks
|
|
611
|
+
* - Call `mutate()` with data to execute the operation
|
|
612
|
+
* - `isPending` is true while mutation is executing
|
|
613
|
+
* - On error, `error` contains the Error object
|
|
614
|
+
* - Use `reset()` to clear error state after handling
|
|
615
|
+
* - For optimistic updates, local UI updates immediately
|
|
616
|
+
* (automatic rollback if sync fails)
|
|
617
|
+
*
|
|
618
|
+
* @example
|
|
619
|
+
* ```typescript
|
|
620
|
+
* const { mutate, isPending, error, reset } = useMutation<User>({
|
|
621
|
+
* collection: 'users',
|
|
622
|
+
* operation: 'insert'
|
|
623
|
+
* })
|
|
624
|
+
*
|
|
625
|
+
* const handleCreate = async () => {
|
|
626
|
+
* try {
|
|
627
|
+
* await mutate({
|
|
628
|
+
* id: '2',
|
|
629
|
+
* name: 'Bob',
|
|
630
|
+
* email: 'bob@example.com',
|
|
631
|
+
* role: 'user'
|
|
632
|
+
* })
|
|
633
|
+
* } catch (err) {
|
|
634
|
+
* console.error('Failed:', err)
|
|
635
|
+
* }
|
|
636
|
+
* }
|
|
637
|
+
*
|
|
638
|
+
* return (
|
|
639
|
+
* <form onSubmit={handleCreate}>
|
|
640
|
+
* <button disabled={isPending}>
|
|
641
|
+
* {isPending ? 'Creating...' : 'Create'}
|
|
642
|
+
* </button>
|
|
643
|
+
* {error && <Error message={error.message} onDismiss={reset} />}
|
|
644
|
+
* </form>
|
|
645
|
+
* )
|
|
646
|
+
* ```
|
|
647
|
+
*/
|
|
648
|
+
export interface MutationResult<T> {
|
|
649
|
+
/**
|
|
650
|
+
* Execute the mutation with data
|
|
651
|
+
* Data format depends on operation: T for insert, UpdateMutationData<T> for update, DeleteMutationData<T> for delete
|
|
652
|
+
*/
|
|
653
|
+
mutate: (data: T | UpdateMutationData<T> | DeleteMutationData<T>) => Promise<void>
|
|
654
|
+
/** True while mutation is being executed */
|
|
655
|
+
isPending: boolean
|
|
656
|
+
/** Error object if mutation failed, undefined if successful */
|
|
657
|
+
error: Error | undefined
|
|
658
|
+
/** Reset mutation state (clears error and pending flags) */
|
|
659
|
+
reset: () => void
|
|
660
|
+
}
|