js-bao 0.2.11 → 0.2.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +174 -0
- package/dist/BaseModel-5YQCROYE.js +17 -0
- package/dist/BaseModel-5YQCROYE.js.map +1 -0
- package/dist/BaseModel-FCNWDJBH.js +17 -0
- package/dist/BaseModel-FCNWDJBH.js.map +1 -0
- package/dist/BrowserDatabaseFactory-PXOTK2DQ.js +119 -0
- package/dist/BrowserDatabaseFactory-PXOTK2DQ.js.map +1 -0
- package/dist/BrowserDatabaseFactory-WD4VX2VZ.js +119 -0
- package/dist/BrowserDatabaseFactory-WD4VX2VZ.js.map +1 -0
- package/dist/IncludeResolver-RCKQGNPZ.js +385 -0
- package/dist/IncludeResolver-RCKQGNPZ.js.map +1 -0
- package/dist/IncludeResolver-WGSQDMS7.js +385 -0
- package/dist/IncludeResolver-WGSQDMS7.js.map +1 -0
- package/dist/NodeDatabaseFactory-J4Z36UF3.js +165 -0
- package/dist/NodeDatabaseFactory-J4Z36UF3.js.map +1 -0
- package/dist/NodeDatabaseFactory-QIEKAXBM.js +10 -0
- package/dist/NodeDatabaseFactory-QIEKAXBM.js.map +1 -0
- package/dist/NodeSqliteEngine-HJSAYE4E.js +383 -0
- package/dist/NodeSqliteEngine-HJSAYE4E.js.map +1 -0
- package/dist/NodeSqliteEngine-I5SLWLME.js +383 -0
- package/dist/NodeSqliteEngine-I5SLWLME.js.map +1 -0
- package/dist/browser.cjs +3779 -3370
- package/dist/browser.d.cts +18 -1
- package/dist/browser.d.ts +18 -1
- package/dist/browser.js +3750 -3341
- package/dist/chunk-3PZWHUZO.js +4153 -0
- package/dist/chunk-3PZWHUZO.js.map +1 -0
- package/dist/chunk-53MS4MN7.js +373 -0
- package/dist/chunk-53MS4MN7.js.map +1 -0
- package/dist/chunk-65G2P4GL.js +709 -0
- package/dist/chunk-65G2P4GL.js.map +1 -0
- package/dist/chunk-6UX3YSCW.js +4151 -0
- package/dist/chunk-6UX3YSCW.js.map +1 -0
- package/dist/chunk-DANSD6BE.js +709 -0
- package/dist/chunk-DANSD6BE.js.map +1 -0
- package/dist/chunk-DF3JEQXA.js +373 -0
- package/dist/chunk-DF3JEQXA.js.map +1 -0
- package/dist/chunk-GO3APTPX.js +61 -0
- package/dist/chunk-GO3APTPX.js.map +1 -0
- package/dist/chunk-ID4U6IQC.js +53 -0
- package/dist/chunk-ID4U6IQC.js.map +1 -0
- package/dist/chunk-RQVS3LVL.js +165 -0
- package/dist/chunk-RQVS3LVL.js.map +1 -0
- package/dist/client.cjs +837 -0
- package/dist/client.d.cts +1101 -0
- package/dist/client.d.ts +1101 -0
- package/dist/client.js +806 -0
- package/dist/cloudflare-do.cjs +3637 -0
- package/dist/cloudflare-do.d.cts +1366 -0
- package/dist/cloudflare-do.d.ts +1366 -0
- package/dist/cloudflare-do.js +3614 -0
- package/dist/cloudflare.cjs +1048 -0
- package/dist/cloudflare.d.cts +1381 -0
- package/dist/cloudflare.d.ts +1381 -0
- package/dist/cloudflare.js +1017 -0
- package/dist/codegen.cjs +260 -19
- package/dist/environment-TOTQICSE.js +17 -0
- package/dist/environment-TOTQICSE.js.map +1 -0
- package/dist/index.cjs +1905 -1492
- package/dist/index.d.cts +19 -2
- package/dist/index.d.ts +19 -2
- package/dist/index.js +1870 -1457
- package/dist/node.cjs +4779 -4366
- package/dist/node.d.cts +18 -1
- package/dist/node.d.ts +18 -1
- package/dist/node.js +4758 -4345
- package/package.json +42 -13
|
@@ -0,0 +1,1101 @@
|
|
|
1
|
+
import * as Y from 'yjs';
|
|
2
|
+
|
|
3
|
+
interface RefersToRelationshipConfig {
|
|
4
|
+
type: "refersTo";
|
|
5
|
+
model: string;
|
|
6
|
+
relatedIdField: string;
|
|
7
|
+
}
|
|
8
|
+
interface HasManyRelationshipConfig {
|
|
9
|
+
type: "hasMany";
|
|
10
|
+
model: string;
|
|
11
|
+
relatedIdField: string;
|
|
12
|
+
orderByField?: string;
|
|
13
|
+
orderDirection?: "ASC" | "DESC";
|
|
14
|
+
}
|
|
15
|
+
interface HasManyThroughRelationshipConfig {
|
|
16
|
+
type: "hasManyThrough";
|
|
17
|
+
model: string;
|
|
18
|
+
joinModel: string;
|
|
19
|
+
joinModelLocalField: string;
|
|
20
|
+
joinModelRelatedField: string;
|
|
21
|
+
joinModelOrderByField?: string;
|
|
22
|
+
joinModelOrderDirection?: "ASC" | "DESC";
|
|
23
|
+
}
|
|
24
|
+
type RelationshipConfig = RefersToRelationshipConfig | HasManyRelationshipConfig | HasManyThroughRelationshipConfig;
|
|
25
|
+
|
|
26
|
+
type FieldType = "string" | "number" | "boolean" | "date" | "id" | "stringset";
|
|
27
|
+
interface FieldOptions {
|
|
28
|
+
type: FieldType;
|
|
29
|
+
indexed?: boolean;
|
|
30
|
+
required?: boolean;
|
|
31
|
+
unique?: boolean;
|
|
32
|
+
default?: any | (() => any);
|
|
33
|
+
autoAssign?: boolean;
|
|
34
|
+
maxLength?: number;
|
|
35
|
+
maxCount?: number;
|
|
36
|
+
}
|
|
37
|
+
interface UniqueConstraintConfig {
|
|
38
|
+
name: string;
|
|
39
|
+
fields: string[];
|
|
40
|
+
}
|
|
41
|
+
interface ModelOptions {
|
|
42
|
+
name: string;
|
|
43
|
+
uniqueConstraints?: UniqueConstraintConfig[];
|
|
44
|
+
relationships?: Record<string, RelationshipConfig>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface ITransactionalDatabaseOperations {
|
|
48
|
+
insert(modelName: string, data: any): Promise<void>;
|
|
49
|
+
delete(modelName: string, id: string): Promise<void>;
|
|
50
|
+
query<T extends Record<string, any>>(sql: string, params?: any[]): Promise<T[]>;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Abstract class defining the interface for database engines.
|
|
54
|
+
* This allows for different database implementations (e.g., SQL.js, DuckDB) to be used interchangeably.
|
|
55
|
+
*/
|
|
56
|
+
declare abstract class DatabaseEngine {
|
|
57
|
+
/**
|
|
58
|
+
* Ensures that the database engine is fully initialized and ready for use.
|
|
59
|
+
* For WASM-based engines, this might involve loading the WASM module.
|
|
60
|
+
*/
|
|
61
|
+
abstract ensureReady(): Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Executes a SQL query against the database.
|
|
64
|
+
* @param sql The SQL query string.
|
|
65
|
+
* @param params Optional array of parameters for prepared statements.
|
|
66
|
+
* @returns A promise that resolves to an array of query results.
|
|
67
|
+
*/
|
|
68
|
+
abstract query(sql: string, params?: any[]): Promise<any[]>;
|
|
69
|
+
/**
|
|
70
|
+
* Retrieves the last error message from the database engine, if any.
|
|
71
|
+
* @returns The last error message as a string, or undefined if no error occurred.
|
|
72
|
+
*/
|
|
73
|
+
abstract getLastErrorMessage(): string | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* Retrieves the schema for a given table.
|
|
76
|
+
* This is useful for understanding table structure, field types, etc.
|
|
77
|
+
* The exact return type might vary based on the database engine.
|
|
78
|
+
* @param tableName The name of the table.
|
|
79
|
+
* @returns A promise that resolves to the table schema information.
|
|
80
|
+
*/
|
|
81
|
+
abstract getTableSchema(tableName: string): Promise<any>;
|
|
82
|
+
/**
|
|
83
|
+
* Destroys the database engine instance and releases any associated resources.
|
|
84
|
+
* This is crucial for cleanup, especially in testing environments or when the application is shutting down.
|
|
85
|
+
*/
|
|
86
|
+
abstract destroy(): Promise<void>;
|
|
87
|
+
createTable(_modelName: string, _schema: Map<string, any>, // Assuming 'any' for field options for now, can be refined
|
|
88
|
+
_options: ModelOptions): Promise<void>;
|
|
89
|
+
createStringSetJunctionTable(_modelName: string, _fieldName: string): Promise<void>;
|
|
90
|
+
insertStringSetValues(_modelName: string, _fieldName: string, _recordId: string, _values: string[]): Promise<void>;
|
|
91
|
+
removeStringSetValues(_modelName: string, _fieldName: string, _recordId: string, _values: string[]): Promise<void>;
|
|
92
|
+
insert(_modelName: string, _data: any): Promise<void>;
|
|
93
|
+
delete(_modelName: string, _id: string): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Deletes all records for a specific document from the given model table.
|
|
96
|
+
* This is used when disconnecting a document to remove all its data.
|
|
97
|
+
* @param modelName The name of the model/table
|
|
98
|
+
* @param docId The document ID to filter by
|
|
99
|
+
*/
|
|
100
|
+
deleteByDocumentId(_modelName: string, _docId: string): Promise<void>;
|
|
101
|
+
getTableName(_modelName: string): string;
|
|
102
|
+
withTransaction<T>(_callback: (operations: ITransactionalDatabaseOperations) => Promise<T>): Promise<T>;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
interface StringSetChangeTracker {
|
|
106
|
+
markStringSetChange(fieldName: string, operation: "add" | "remove" | "clear", value?: string): void;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
type DocumentPermissionHint = "read" | "read-write";
|
|
110
|
+
interface SaveOptions$1 {
|
|
111
|
+
targetDocument?: string;
|
|
112
|
+
forceWrite?: boolean;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
interface ComparisonOperators<T = any> {
|
|
116
|
+
$eq?: T;
|
|
117
|
+
$ne?: T;
|
|
118
|
+
$gt?: T;
|
|
119
|
+
$gte?: T;
|
|
120
|
+
$lt?: T;
|
|
121
|
+
$lte?: T;
|
|
122
|
+
$in?: T[];
|
|
123
|
+
$nin?: T[];
|
|
124
|
+
}
|
|
125
|
+
interface StringSetOperators {
|
|
126
|
+
/**
|
|
127
|
+
* Exact membership: StringSet contains this specific string
|
|
128
|
+
*/
|
|
129
|
+
$contains?: string;
|
|
130
|
+
$all?: string[];
|
|
131
|
+
$size?: number | ComparisonOperators<number>;
|
|
132
|
+
}
|
|
133
|
+
interface SubstringOperators {
|
|
134
|
+
/** Prefix match */
|
|
135
|
+
$startsWith?: string;
|
|
136
|
+
/** Suffix match */
|
|
137
|
+
$endsWith?: string;
|
|
138
|
+
/** Substring anywhere */
|
|
139
|
+
$containsText?: string;
|
|
140
|
+
}
|
|
141
|
+
interface ExistenceOperators {
|
|
142
|
+
$exists?: boolean;
|
|
143
|
+
}
|
|
144
|
+
type FieldOperators<T = any> = ComparisonOperators<T> & ExistenceOperators & StringSetOperators & SubstringOperators;
|
|
145
|
+
interface LogicalOperators {
|
|
146
|
+
$and?: DocumentFilter[];
|
|
147
|
+
$or?: DocumentFilter[];
|
|
148
|
+
}
|
|
149
|
+
type DocumentFilter = {
|
|
150
|
+
[field: string]: any | FieldOperators<any>;
|
|
151
|
+
} & LogicalOperators;
|
|
152
|
+
type SortDirection = 1 | -1;
|
|
153
|
+
type SortSpec = {
|
|
154
|
+
[field: string]: SortDirection;
|
|
155
|
+
};
|
|
156
|
+
type ProjectionSpec = {
|
|
157
|
+
[field: string]: 1 | 0;
|
|
158
|
+
};
|
|
159
|
+
interface IncludeSpec {
|
|
160
|
+
model: string;
|
|
161
|
+
type: "refersTo" | "hasMany" | "refersToMany";
|
|
162
|
+
sourceField?: string;
|
|
163
|
+
foreignKey?: string;
|
|
164
|
+
localField?: string;
|
|
165
|
+
as?: string;
|
|
166
|
+
projection?: ProjectionSpec;
|
|
167
|
+
limit?: number;
|
|
168
|
+
sort?: SortSpec;
|
|
169
|
+
filter?: DocumentFilter;
|
|
170
|
+
include?: IncludeSpec[];
|
|
171
|
+
}
|
|
172
|
+
interface QueryOptions {
|
|
173
|
+
sort?: SortSpec;
|
|
174
|
+
projection?: ProjectionSpec;
|
|
175
|
+
documents?: string | string[];
|
|
176
|
+
limit?: number;
|
|
177
|
+
uniqueStartKey?: string;
|
|
178
|
+
direction?: 1 | -1;
|
|
179
|
+
include?: IncludeSpec[];
|
|
180
|
+
}
|
|
181
|
+
interface PaginatedResult<T> {
|
|
182
|
+
data: T[];
|
|
183
|
+
nextCursor?: string;
|
|
184
|
+
prevCursor?: string;
|
|
185
|
+
hasMore: boolean;
|
|
186
|
+
}
|
|
187
|
+
interface TranslatedQuery {
|
|
188
|
+
sql: string;
|
|
189
|
+
params: any[];
|
|
190
|
+
sortFields: string[];
|
|
191
|
+
sortDirections?: (1 | -1)[];
|
|
192
|
+
}
|
|
193
|
+
type ProjectedResult<T, P extends ProjectionSpec> = {
|
|
194
|
+
[K in keyof P]: K extends keyof T ? T[K] : never;
|
|
195
|
+
};
|
|
196
|
+
type QueryResult<T, P extends ProjectionSpec | undefined> = P extends ProjectionSpec ? ProjectedResult<T, P> : T;
|
|
197
|
+
|
|
198
|
+
declare class DocumentQueryTranslator {
|
|
199
|
+
private modelName;
|
|
200
|
+
private schema;
|
|
201
|
+
private tableName;
|
|
202
|
+
private quotedTableName;
|
|
203
|
+
private fieldSqlCache;
|
|
204
|
+
constructor(modelName: string, schema: Map<string, FieldOptions>);
|
|
205
|
+
private getQuotedField;
|
|
206
|
+
/**
|
|
207
|
+
* Translate document filter and options to SQL for find operations
|
|
208
|
+
*/
|
|
209
|
+
translateFind(filter: DocumentFilter, options?: QueryOptions): TranslatedQuery;
|
|
210
|
+
/**
|
|
211
|
+
* Translate document filter to SQL for count operations
|
|
212
|
+
*/
|
|
213
|
+
translateCount(filter: DocumentFilter, options?: Pick<QueryOptions, "documents">): {
|
|
214
|
+
sql: string;
|
|
215
|
+
params: any[];
|
|
216
|
+
};
|
|
217
|
+
/**
|
|
218
|
+
* Translate document filter to SQL WHERE clause
|
|
219
|
+
*/
|
|
220
|
+
translateFilter(filter: DocumentFilter): {
|
|
221
|
+
sql: string;
|
|
222
|
+
params: any[];
|
|
223
|
+
};
|
|
224
|
+
/**
|
|
225
|
+
* Translate logical operators ($and, $or)
|
|
226
|
+
*/
|
|
227
|
+
private translateLogicalOperator;
|
|
228
|
+
/**
|
|
229
|
+
* Translate field condition to SQL
|
|
230
|
+
*/
|
|
231
|
+
private translateFieldCondition;
|
|
232
|
+
/**
|
|
233
|
+
* Translate field operators to SQL
|
|
234
|
+
*/
|
|
235
|
+
private translateFieldOperators;
|
|
236
|
+
/**
|
|
237
|
+
* Translate individual operator to SQL
|
|
238
|
+
*/
|
|
239
|
+
private translateOperator;
|
|
240
|
+
/**
|
|
241
|
+
* Build SELECT clause based on projection
|
|
242
|
+
*/
|
|
243
|
+
private buildSelectClause;
|
|
244
|
+
/**
|
|
245
|
+
* Build LIMIT clause
|
|
246
|
+
*/
|
|
247
|
+
private buildLimitClause;
|
|
248
|
+
/**
|
|
249
|
+
* Build pagination WHERE clause from cursor
|
|
250
|
+
*/
|
|
251
|
+
private buildPaginationClause;
|
|
252
|
+
/**
|
|
253
|
+
* Validate that field exists in schema
|
|
254
|
+
*/
|
|
255
|
+
private validateField;
|
|
256
|
+
/**
|
|
257
|
+
* Validate projection fields
|
|
258
|
+
*/
|
|
259
|
+
private validateProjection;
|
|
260
|
+
/**
|
|
261
|
+
* Validate operator is supported for field type
|
|
262
|
+
*/
|
|
263
|
+
private validateOperatorForType;
|
|
264
|
+
/**
|
|
265
|
+
* Validate field value matches expected type
|
|
266
|
+
*/
|
|
267
|
+
private validateFieldValue;
|
|
268
|
+
/**
|
|
269
|
+
* Validate array values for $in/$nin operators
|
|
270
|
+
*/
|
|
271
|
+
private validateArrayValues;
|
|
272
|
+
/**
|
|
273
|
+
* Check if value is a primitive (not an object with operators)
|
|
274
|
+
*/
|
|
275
|
+
private isPrimitiveValue;
|
|
276
|
+
/**
|
|
277
|
+
* Get the type of a value for validation
|
|
278
|
+
*/
|
|
279
|
+
private getValueType;
|
|
280
|
+
/**
|
|
281
|
+
* Check if value type is compatible with field type
|
|
282
|
+
*/
|
|
283
|
+
private isTypeCompatible;
|
|
284
|
+
/**
|
|
285
|
+
* Convert value for SQLite compatibility
|
|
286
|
+
*/
|
|
287
|
+
private convertValueForSQLite;
|
|
288
|
+
private normalizeDocumentIds;
|
|
289
|
+
private buildDocumentClause;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
interface StringSetMembership$1 {
|
|
293
|
+
field: string;
|
|
294
|
+
contains: string;
|
|
295
|
+
}
|
|
296
|
+
type GroupByField$1 = string | StringSetMembership$1;
|
|
297
|
+
interface AggregationOperation$1 {
|
|
298
|
+
type: "count" | "sum" | "avg" | "min" | "max";
|
|
299
|
+
field?: string;
|
|
300
|
+
}
|
|
301
|
+
interface AggregationOptions$1 {
|
|
302
|
+
groupBy: GroupByField$1[];
|
|
303
|
+
operations: AggregationOperation$1[];
|
|
304
|
+
filter?: DocumentFilter;
|
|
305
|
+
limit?: number;
|
|
306
|
+
sort?: {
|
|
307
|
+
field: string;
|
|
308
|
+
direction: 1 | -1;
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
type AggregationResult$1 = Record<string, any> | Record<string, any>[];
|
|
312
|
+
interface AggregationAliasDebugInfo {
|
|
313
|
+
field: string;
|
|
314
|
+
contains: string;
|
|
315
|
+
originalAlias: string;
|
|
316
|
+
}
|
|
317
|
+
interface AggregationAliasDetail extends AggregationAliasDebugInfo {
|
|
318
|
+
alias: string;
|
|
319
|
+
membershipKey: string;
|
|
320
|
+
}
|
|
321
|
+
interface AggregationQueryPlan {
|
|
322
|
+
sql: string;
|
|
323
|
+
params: any[];
|
|
324
|
+
aliasMetadata?: AggregationAliasDetail[];
|
|
325
|
+
}
|
|
326
|
+
declare enum LogLevel {
|
|
327
|
+
SILENT = 0,
|
|
328
|
+
ERROR = 1,
|
|
329
|
+
WARN = 2,
|
|
330
|
+
INFO = 3,
|
|
331
|
+
DEBUG = 4,
|
|
332
|
+
VERBOSE = 5
|
|
333
|
+
}
|
|
334
|
+
declare class BaseModel implements StringSetChangeTracker {
|
|
335
|
+
static modelName?: string;
|
|
336
|
+
private static listenersMap;
|
|
337
|
+
private static modelNameToDefaultDocId;
|
|
338
|
+
private static globalDefaultDocId;
|
|
339
|
+
private static defaultDocChangedListeners;
|
|
340
|
+
private static modelDocMappingChangedListeners;
|
|
341
|
+
private static readonly DEFAULT_LEGACY_DOC_ID;
|
|
342
|
+
protected static dbInstance: DatabaseEngine | null;
|
|
343
|
+
protected static connectedDocuments: Map<string, {
|
|
344
|
+
yDoc: Y.Doc;
|
|
345
|
+
permissionHint: DocumentPermissionHint;
|
|
346
|
+
}>;
|
|
347
|
+
protected static documentYMaps: Map<string, Y.Map<any>>;
|
|
348
|
+
private _localChanges;
|
|
349
|
+
private _isDirty;
|
|
350
|
+
private _isLoadingFromYjs;
|
|
351
|
+
private _stringSetFields;
|
|
352
|
+
private _metaDocId;
|
|
353
|
+
private _metaPermissionHint;
|
|
354
|
+
/**
|
|
355
|
+
* Returns the document id this instance is associated with, or null if not resolved yet.
|
|
356
|
+
*/
|
|
357
|
+
getDocumentId(): string | null;
|
|
358
|
+
id: string;
|
|
359
|
+
type: string;
|
|
360
|
+
static setLogLevel(level: LogLevel): void;
|
|
361
|
+
static getLogLevel(): LogLevel;
|
|
362
|
+
static setModelDefaultDocumentId(modelName: string, docId: string): void;
|
|
363
|
+
static removeModelDefaultDocumentId(modelName: string): void;
|
|
364
|
+
static clearModelDefaultDocumentIds(): void;
|
|
365
|
+
static setGlobalDefaultDocumentId(docId: string): void;
|
|
366
|
+
static clearGlobalDefaultDocumentId(): void;
|
|
367
|
+
static getModelDefaultDocumentMapping(): Record<string, string>;
|
|
368
|
+
static getDocumentIdForModel(modelName: string): string | undefined;
|
|
369
|
+
static getGlobalDefaultDocumentId(): string | undefined;
|
|
370
|
+
static onDefaultDocChanged(listener: (payload: {
|
|
371
|
+
previous?: string;
|
|
372
|
+
current?: string;
|
|
373
|
+
}) => void): () => void;
|
|
374
|
+
static onModelDocMappingChanged(listener: (payload: {
|
|
375
|
+
modelName: string;
|
|
376
|
+
previous?: string;
|
|
377
|
+
current?: string;
|
|
378
|
+
}) => void): () => void;
|
|
379
|
+
static _clearMappingsForDocId(docId: string): void;
|
|
380
|
+
private static attachFieldAccessorsSet;
|
|
381
|
+
static attachFieldAccessors(modelClass: typeof BaseModel, fields: Map<string, FieldOptions>): void;
|
|
382
|
+
constructor(data?: Partial<any>);
|
|
383
|
+
private ensureLocalChanges;
|
|
384
|
+
private hasLocalChange;
|
|
385
|
+
private getFromYjs;
|
|
386
|
+
private getValue;
|
|
387
|
+
private setValue;
|
|
388
|
+
get isDirty(): boolean;
|
|
389
|
+
get hasUnsavedChanges(): boolean;
|
|
390
|
+
private clearLocalChanges;
|
|
391
|
+
discardChanges(): void;
|
|
392
|
+
protected validateFieldValue(fieldKey: string, value: any): void;
|
|
393
|
+
protected validateBeforeSave(): void;
|
|
394
|
+
getChangedFields(): string[];
|
|
395
|
+
getOriginalValue(fieldKey: string): any;
|
|
396
|
+
getCurrentValue(fieldKey: string): any;
|
|
397
|
+
hasFieldChanged(fieldKey: string): boolean;
|
|
398
|
+
markStringSetChange(fieldName: string, operation: "add" | "remove" | "clear", value?: string): void;
|
|
399
|
+
private getStringSetCurrentValues;
|
|
400
|
+
private getStringSetFromYjs;
|
|
401
|
+
private getOrCreateStringSet;
|
|
402
|
+
static initialize(_yDoc: Y.Doc, _db: DatabaseEngine): Promise<void>;
|
|
403
|
+
static initializeForDocument(yDoc: Y.Doc, db: DatabaseEngine, docId: string, permissionHint: DocumentPermissionHint): Promise<void>;
|
|
404
|
+
static cleanupDocumentData(docId: string): Promise<void>;
|
|
405
|
+
static subscribe(callback: () => void): () => void;
|
|
406
|
+
protected static notifyListeners(): void;
|
|
407
|
+
/**
|
|
408
|
+
* Legacy migration method - no longer needed in the new multidoc architecture.
|
|
409
|
+
* Data migration is now handled during document initialization.
|
|
410
|
+
*/
|
|
411
|
+
static migrateToNestedYMaps(): Promise<void>;
|
|
412
|
+
/**
|
|
413
|
+
* Utility to diff current instance data against YJS nested map data
|
|
414
|
+
* Returns object with added, modified, and removed fields
|
|
415
|
+
*/
|
|
416
|
+
protected _diffWithYjsData(): {
|
|
417
|
+
added: Record<string, any>;
|
|
418
|
+
modified: Record<string, any>;
|
|
419
|
+
removed: string[];
|
|
420
|
+
};
|
|
421
|
+
/**
|
|
422
|
+
* Deep equality check for comparing field values
|
|
423
|
+
*/
|
|
424
|
+
protected _deepEqual(a: any, b: any): boolean;
|
|
425
|
+
protected static _buildKeyFromValues(fields: string[], keyValues: any[], modelName: string, constraintName: string): string | null;
|
|
426
|
+
protected _buildUniqueKey(fields: string[], data: Record<string, any>, modelName: string, constraintName: string): string | null;
|
|
427
|
+
save(options?: SaveOptions$1): Promise<void>;
|
|
428
|
+
delete(): Promise<void>;
|
|
429
|
+
protected getCurrentJSState(): Record<string, any>;
|
|
430
|
+
protected toJSON(): Record<string, any>;
|
|
431
|
+
static find<T extends BaseModel>(this: new (...args: any[]) => T, id: string): Promise<T | null>;
|
|
432
|
+
/**
|
|
433
|
+
* Document-style query API - returns paginated results
|
|
434
|
+
*/
|
|
435
|
+
static query<T extends BaseModel, P extends ProjectionSpec | undefined = undefined>(this: new (...args: any[]) => T, filter?: DocumentFilter, options?: QueryOptions & {
|
|
436
|
+
projection?: P;
|
|
437
|
+
}): Promise<PaginatedResult<QueryResult<T, P>>>;
|
|
438
|
+
/**
|
|
439
|
+
* Main aggregation API - performs grouping, faceting, and statistical operations
|
|
440
|
+
* @param options Aggregation configuration with groupBy, operations, filter, limit, and sort
|
|
441
|
+
* @returns Nested object structure with aggregation results
|
|
442
|
+
*
|
|
443
|
+
* @example
|
|
444
|
+
* // Simple facet count
|
|
445
|
+
* const tagCounts = await Model.aggregate({
|
|
446
|
+
* groupBy: ['tags'],
|
|
447
|
+
* operations: [{ type: 'count' }]
|
|
448
|
+
* });
|
|
449
|
+
* // Result: { red: 15, blue: 8, green: 12 }
|
|
450
|
+
*
|
|
451
|
+
* @example
|
|
452
|
+
* // Multi-dimensional grouping with multiple operations
|
|
453
|
+
* const categoryStats = await Model.aggregate({
|
|
454
|
+
* groupBy: ['category', 'status'],
|
|
455
|
+
* operations: [
|
|
456
|
+
* { type: 'count' },
|
|
457
|
+
* { type: 'sum', field: 'amount' },
|
|
458
|
+
* { type: 'avg', field: 'score' }
|
|
459
|
+
* ],
|
|
460
|
+
* filter: { active: true },
|
|
461
|
+
* sort: { field: 'count', direction: 'desc' },
|
|
462
|
+
* limit: 10
|
|
463
|
+
* });
|
|
464
|
+
*
|
|
465
|
+
* @example
|
|
466
|
+
* // StringSet membership grouping
|
|
467
|
+
* const urgentCounts = await Model.aggregate({
|
|
468
|
+
* groupBy: [{ field: 'tags', contains: 'urgent' }],
|
|
469
|
+
* operations: [{ type: 'count' }]
|
|
470
|
+
* });
|
|
471
|
+
* // Result: { true: 5, false: 23 }
|
|
472
|
+
*/
|
|
473
|
+
static aggregate<T extends BaseModel>(this: new (...args: any[]) => T, options: AggregationOptions$1): Promise<AggregationResult$1>;
|
|
474
|
+
/**
|
|
475
|
+
* Build SQL query for structured aggregation
|
|
476
|
+
*/
|
|
477
|
+
protected static buildAggregationQuery(options: AggregationOptions$1, schema: any, modelName: string): AggregationQueryPlan;
|
|
478
|
+
/**
|
|
479
|
+
* Get the proper database table name (should match database engine naming)
|
|
480
|
+
*/
|
|
481
|
+
protected static getDatabaseTableName(modelName: string): string;
|
|
482
|
+
/**
|
|
483
|
+
* Get the proper database junction table name for StringSet fields
|
|
484
|
+
*/
|
|
485
|
+
protected static getDatabaseJunctionTableName(modelName: string, fieldName: string): string;
|
|
486
|
+
private static buildMembershipKey;
|
|
487
|
+
/**
|
|
488
|
+
* Build query for StringSet facet counts
|
|
489
|
+
*/
|
|
490
|
+
protected static buildStringSetFacetQuery(stringSetFields: string[], options: AggregationOptions$1, translator: DocumentQueryTranslator, modelName: string): AggregationQueryPlan;
|
|
491
|
+
/**
|
|
492
|
+
* Build query for regular field aggregation
|
|
493
|
+
*/
|
|
494
|
+
protected static buildRegularAggregationQuery(regularGroupBy: string[], stringSetMemberships: StringSetMembership$1[], options: AggregationOptions$1, translator: DocumentQueryTranslator, modelName: string): AggregationQueryPlan;
|
|
495
|
+
/**
|
|
496
|
+
* Process aggregation results into nested structure
|
|
497
|
+
*/
|
|
498
|
+
protected static processAggregationResults(results: any[], options: AggregationOptions$1, aliasMetadata?: AggregationAliasDetail[]): AggregationResult$1;
|
|
499
|
+
/**
|
|
500
|
+
* Document-style query API - returns single result or null
|
|
501
|
+
*/
|
|
502
|
+
static queryOne<T extends BaseModel, P extends ProjectionSpec | undefined = undefined>(this: new (...args: any[]) => T, filter?: DocumentFilter, options?: Omit<QueryOptions, "limit" | "uniqueStartKey" | "direction"> & {
|
|
503
|
+
projection?: P;
|
|
504
|
+
}): Promise<QueryResult<T, P> | null>;
|
|
505
|
+
/**
|
|
506
|
+
* Document-style count API
|
|
507
|
+
*/
|
|
508
|
+
static count(this: new (...args: any[]) => any, filter?: DocumentFilter, options?: Pick<QueryOptions, "documents">): Promise<number>;
|
|
509
|
+
static findAll<T extends BaseModel>(this: new (...args: any[]) => T): Promise<T[]>;
|
|
510
|
+
static findByUnique<T extends BaseModel>(this: typeof BaseModel & (new (...args: any[]) => T), constraintName: string, value: any | any[]): Promise<T | null>;
|
|
511
|
+
static upsertByUnique<T extends BaseModel>(this: typeof BaseModel & (new (...args: any[]) => T), constraintName: string, uniqueLookupValue: any | any[], dataToUpsert: Partial<Omit<InstanceType<new (...args: any[]) => T>, keyof BaseModel | "toJSON">> & {
|
|
512
|
+
id?: string;
|
|
513
|
+
}, options?: {
|
|
514
|
+
objectMustExist?: boolean;
|
|
515
|
+
objectMustNotExist?: boolean;
|
|
516
|
+
targetDocument?: string;
|
|
517
|
+
}): Promise<T>;
|
|
518
|
+
/**
|
|
519
|
+
* Execute a callback with automatic transaction handling for all modified models
|
|
520
|
+
*/
|
|
521
|
+
static withTransaction<T>(callback: () => Promise<T> | T): Promise<T>;
|
|
522
|
+
/**
|
|
523
|
+
* Sets up deep observation on a nested YMap to sync field-level changes to the database
|
|
524
|
+
*/
|
|
525
|
+
protected static setupNestedYMapObserver(recordId: string, recordYMap: Y.Map<any>): void;
|
|
526
|
+
/**
|
|
527
|
+
* Sets up deep observation on a nested YMap for a specific document to sync field-level changes to the database
|
|
528
|
+
*/
|
|
529
|
+
protected static setupNestedYMapObserverForDocument(recordId: string, recordYMap: Y.Map<any>, docId: string, permissionHint: DocumentPermissionHint): void;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* Durable Object Engine
|
|
534
|
+
*
|
|
535
|
+
* Database engine implementation that runs inside a Cloudflare Durable Object.
|
|
536
|
+
* Uses the DO's embedded SQLite database via ctx.storage.sql.
|
|
537
|
+
*
|
|
538
|
+
* Key characteristics:
|
|
539
|
+
* - Synchronous SQL execution (DO SQLite is sync)
|
|
540
|
+
* - No doc ID column needed (one DO = one document)
|
|
541
|
+
* - Uses JSON schema (records + stringset_index tables)
|
|
542
|
+
* - Schemaless: any model/field can be saved and queried without registration
|
|
543
|
+
* - Indexes are additive: register/drop individual field indexes independently
|
|
544
|
+
*/
|
|
545
|
+
|
|
546
|
+
/** Row shape from the _indexes table */
|
|
547
|
+
interface IndexEntry {
|
|
548
|
+
model_name: string;
|
|
549
|
+
field_name: string;
|
|
550
|
+
field_type: string;
|
|
551
|
+
is_unique: number;
|
|
552
|
+
created_at: string;
|
|
553
|
+
}
|
|
554
|
+
/** Row shape from the _unique_constraints table */
|
|
555
|
+
interface UniqueConstraintEntry {
|
|
556
|
+
model_name: string;
|
|
557
|
+
constraint_name: string;
|
|
558
|
+
fields: string[];
|
|
559
|
+
created_at: string;
|
|
560
|
+
}
|
|
561
|
+
/** Row shape from the _model_fields table */
|
|
562
|
+
interface ModelFieldInfo {
|
|
563
|
+
model_name: string;
|
|
564
|
+
field_name: string;
|
|
565
|
+
inferred_type: string;
|
|
566
|
+
first_seen_at: string;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* Aggregation types shared between Yjs and DO backends.
|
|
571
|
+
*/
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* Describes a StringSet membership check in a groupBy clause.
|
|
575
|
+
* Groups records by whether they have a specific value in a StringSet field.
|
|
576
|
+
*/
|
|
577
|
+
interface StringSetMembership {
|
|
578
|
+
field: string;
|
|
579
|
+
contains: string;
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* A groupBy field can be a plain field name or a StringSet membership check.
|
|
583
|
+
*/
|
|
584
|
+
type GroupByField = string | StringSetMembership;
|
|
585
|
+
/**
|
|
586
|
+
* An aggregation operation (count, sum, avg, min, max).
|
|
587
|
+
*/
|
|
588
|
+
interface AggregationOperation {
|
|
589
|
+
type: "count" | "sum" | "avg" | "min" | "max";
|
|
590
|
+
/** Required for sum, avg, min, max; not used for count */
|
|
591
|
+
field?: string;
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Options for an aggregation query.
|
|
595
|
+
*/
|
|
596
|
+
interface AggregationOptions {
|
|
597
|
+
groupBy: GroupByField[];
|
|
598
|
+
operations: AggregationOperation[];
|
|
599
|
+
filter?: DocumentFilter;
|
|
600
|
+
limit?: number;
|
|
601
|
+
sort?: {
|
|
602
|
+
/** Can be operation result field like 'count', 'sum_fieldName', etc. */
|
|
603
|
+
field: string;
|
|
604
|
+
/** 1 for ascending, -1 for descending */
|
|
605
|
+
direction: 1 | -1;
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Result of an aggregation query — nested object keyed by group values.
|
|
610
|
+
*/
|
|
611
|
+
type AggregationResult = Record<string, any> | Record<string, any>[];
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* Database Durable Object Factory
|
|
615
|
+
*
|
|
616
|
+
* Creates a Durable Object class that serves as a schemaless database store.
|
|
617
|
+
* Each DO instance has its own SQLite database.
|
|
618
|
+
*
|
|
619
|
+
* Usage:
|
|
620
|
+
* ```typescript
|
|
621
|
+
* import { createDatabaseDO } from 'js-bao/cloudflare/do';
|
|
622
|
+
*
|
|
623
|
+
* export const MyDatabaseDO = createDatabaseDO({
|
|
624
|
+
* hooks: {
|
|
625
|
+
* beforeSave: async (ctx) => {
|
|
626
|
+
* // Access control logic
|
|
627
|
+
* return { allow: true };
|
|
628
|
+
* },
|
|
629
|
+
* },
|
|
630
|
+
* });
|
|
631
|
+
* ```
|
|
632
|
+
*/
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Request body types for RPC endpoints
|
|
636
|
+
*/
|
|
637
|
+
interface QueryRequest {
|
|
638
|
+
modelName: string;
|
|
639
|
+
filter: DocumentFilter;
|
|
640
|
+
options?: QueryOptions;
|
|
641
|
+
}
|
|
642
|
+
interface SaveRequest {
|
|
643
|
+
modelName: string;
|
|
644
|
+
id: string;
|
|
645
|
+
data: Record<string, any>;
|
|
646
|
+
stringSets?: Record<string, string[]>;
|
|
647
|
+
ifNotExists?: boolean;
|
|
648
|
+
condition?: DocumentFilter;
|
|
649
|
+
}
|
|
650
|
+
interface DeleteRequest {
|
|
651
|
+
modelName: string;
|
|
652
|
+
id: string;
|
|
653
|
+
condition?: DocumentFilter;
|
|
654
|
+
}
|
|
655
|
+
interface CountRequest {
|
|
656
|
+
modelName: string;
|
|
657
|
+
filter: DocumentFilter;
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Response types
|
|
661
|
+
*/
|
|
662
|
+
interface QueryResponse {
|
|
663
|
+
data: Record<string, any>[];
|
|
664
|
+
hasMore?: boolean;
|
|
665
|
+
nextCursor?: string;
|
|
666
|
+
prevCursor?: string;
|
|
667
|
+
}
|
|
668
|
+
interface SaveResponse {
|
|
669
|
+
success: boolean;
|
|
670
|
+
id: string;
|
|
671
|
+
}
|
|
672
|
+
interface DeleteResponse {
|
|
673
|
+
success: boolean;
|
|
674
|
+
}
|
|
675
|
+
interface CountResponse {
|
|
676
|
+
count: number;
|
|
677
|
+
}
|
|
678
|
+
interface ErrorResponse {
|
|
679
|
+
error: string;
|
|
680
|
+
code?: string;
|
|
681
|
+
}
|
|
682
|
+
interface AggregateRequest {
|
|
683
|
+
modelName: string;
|
|
684
|
+
options: AggregationOptions;
|
|
685
|
+
}
|
|
686
|
+
interface AggregateResponse {
|
|
687
|
+
result: AggregationResult;
|
|
688
|
+
}
|
|
689
|
+
interface SyncIndexesRequest {
|
|
690
|
+
models: Array<{
|
|
691
|
+
modelName: string;
|
|
692
|
+
indexes: Array<{
|
|
693
|
+
fieldName: string;
|
|
694
|
+
fieldType: string;
|
|
695
|
+
unique: boolean;
|
|
696
|
+
}>;
|
|
697
|
+
uniqueConstraints: Array<{
|
|
698
|
+
name: string;
|
|
699
|
+
fields: string[];
|
|
700
|
+
}>;
|
|
701
|
+
}>;
|
|
702
|
+
}
|
|
703
|
+
interface SyncIndexesResponse {
|
|
704
|
+
registered: number;
|
|
705
|
+
}
|
|
706
|
+
interface PatchRequest {
|
|
707
|
+
modelName: string;
|
|
708
|
+
id: string;
|
|
709
|
+
data: Record<string, any>;
|
|
710
|
+
stringSets?: Record<string, string[]>;
|
|
711
|
+
condition?: DocumentFilter;
|
|
712
|
+
}
|
|
713
|
+
interface PatchResponse {
|
|
714
|
+
success: boolean;
|
|
715
|
+
id: string;
|
|
716
|
+
}
|
|
717
|
+
interface BatchOperation {
|
|
718
|
+
op: "save" | "patch" | "delete" | "increment" | "addToSet" | "removeFromSet";
|
|
719
|
+
modelName: string;
|
|
720
|
+
id: string;
|
|
721
|
+
data?: Record<string, any>;
|
|
722
|
+
stringSets?: Record<string, string[]>;
|
|
723
|
+
fields?: Record<string, number>;
|
|
724
|
+
ifNotExists?: boolean;
|
|
725
|
+
condition?: DocumentFilter;
|
|
726
|
+
}
|
|
727
|
+
interface BatchRequest {
|
|
728
|
+
operations: BatchOperation[];
|
|
729
|
+
}
|
|
730
|
+
interface BatchOperationResult {
|
|
731
|
+
success: boolean;
|
|
732
|
+
id: string;
|
|
733
|
+
error?: string;
|
|
734
|
+
values?: Record<string, number>;
|
|
735
|
+
}
|
|
736
|
+
interface BatchResponse {
|
|
737
|
+
results: BatchOperationResult[];
|
|
738
|
+
}
|
|
739
|
+
interface IncrementRequest {
|
|
740
|
+
modelName: string;
|
|
741
|
+
id: string;
|
|
742
|
+
fields: Record<string, number>;
|
|
743
|
+
condition?: DocumentFilter;
|
|
744
|
+
}
|
|
745
|
+
interface IncrementResponse {
|
|
746
|
+
success: boolean;
|
|
747
|
+
id: string;
|
|
748
|
+
values: Record<string, number>;
|
|
749
|
+
}
|
|
750
|
+
interface StringSetUpdateRequest {
|
|
751
|
+
modelName: string;
|
|
752
|
+
id: string;
|
|
753
|
+
sets: Record<string, string[]>;
|
|
754
|
+
condition?: DocumentFilter;
|
|
755
|
+
}
|
|
756
|
+
interface StringSetUpdateResponse {
|
|
757
|
+
success: boolean;
|
|
758
|
+
}
|
|
759
|
+
interface DescribeResponse {
|
|
760
|
+
modelName: string;
|
|
761
|
+
fields: ModelFieldInfo[];
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* Durable Object Client Engine
|
|
766
|
+
*
|
|
767
|
+
* Client-side engine that proxies database operations to a Cloudflare
|
|
768
|
+
* Durable Object via HTTP fetch calls.
|
|
769
|
+
*
|
|
770
|
+
* This engine runs in the browser or Node.js and communicates with
|
|
771
|
+
* the DO-based backend.
|
|
772
|
+
*/
|
|
773
|
+
|
|
774
|
+
interface DOClientEngineConfig {
|
|
775
|
+
/**
|
|
776
|
+
* Base URL of the Cloudflare Worker
|
|
777
|
+
* e.g., "https://my-worker.my-subdomain.workers.dev"
|
|
778
|
+
*/
|
|
779
|
+
endpoint: string;
|
|
780
|
+
/**
|
|
781
|
+
* Optional custom fetch function (useful for testing)
|
|
782
|
+
*/
|
|
783
|
+
fetch?: typeof fetch;
|
|
784
|
+
/**
|
|
785
|
+
* Optional authorization header value
|
|
786
|
+
*/
|
|
787
|
+
authorization?: string;
|
|
788
|
+
/**
|
|
789
|
+
* Request timeout in milliseconds (default: 30000)
|
|
790
|
+
*/
|
|
791
|
+
timeout?: number;
|
|
792
|
+
}
|
|
793
|
+
declare class DOClientEngine extends DatabaseEngine {
|
|
794
|
+
private endpoint;
|
|
795
|
+
private customFetch;
|
|
796
|
+
private authorization?;
|
|
797
|
+
private timeout;
|
|
798
|
+
private currentDocId;
|
|
799
|
+
constructor(config: DOClientEngineConfig);
|
|
800
|
+
/**
|
|
801
|
+
* Set the current document ID for subsequent operations.
|
|
802
|
+
*/
|
|
803
|
+
setCurrentDocument(docId: string): void;
|
|
804
|
+
/**
|
|
805
|
+
* Get the current document ID.
|
|
806
|
+
*/
|
|
807
|
+
getCurrentDocument(): string | null;
|
|
808
|
+
/**
|
|
809
|
+
* Build the URL for a DO endpoint.
|
|
810
|
+
*/
|
|
811
|
+
private buildUrl;
|
|
812
|
+
/**
|
|
813
|
+
* Make a fetch request to the DO.
|
|
814
|
+
*/
|
|
815
|
+
private doFetch;
|
|
816
|
+
/**
|
|
817
|
+
* Query records from the DO.
|
|
818
|
+
*/
|
|
819
|
+
queryModel(modelName: string, filter?: DocumentFilter, options?: QueryOptions): Promise<PaginatedResult<Record<string, any>>>;
|
|
820
|
+
/**
|
|
821
|
+
* Save a record to the DO.
|
|
822
|
+
*/
|
|
823
|
+
saveModel(modelName: string, id: string, data: Record<string, any>, stringSets?: Record<string, string[]>, options?: {
|
|
824
|
+
ifNotExists?: boolean;
|
|
825
|
+
condition?: DocumentFilter;
|
|
826
|
+
}): Promise<string>;
|
|
827
|
+
/**
|
|
828
|
+
* Patch (partial update) a record in the DO.
|
|
829
|
+
* Only the provided fields are updated; existing fields are preserved.
|
|
830
|
+
*/
|
|
831
|
+
patchModel(modelName: string, id: string, data: Record<string, any>, stringSets?: Record<string, string[]>, options?: {
|
|
832
|
+
condition?: DocumentFilter;
|
|
833
|
+
}): Promise<string>;
|
|
834
|
+
/**
|
|
835
|
+
* Delete a record from the DO.
|
|
836
|
+
*/
|
|
837
|
+
deleteModel(modelName: string, id: string, options?: {
|
|
838
|
+
condition?: DocumentFilter;
|
|
839
|
+
}): Promise<boolean>;
|
|
840
|
+
/**
|
|
841
|
+
* Count records matching a filter.
|
|
842
|
+
*/
|
|
843
|
+
countModel(modelName: string, filter?: DocumentFilter): Promise<number>;
|
|
844
|
+
/**
|
|
845
|
+
* Aggregate records with groupBy and operations (count, sum, avg, min, max).
|
|
846
|
+
*/
|
|
847
|
+
aggregateModel(modelName: string, options: AggregationOptions): Promise<AggregationResult>;
|
|
848
|
+
/**
|
|
849
|
+
* Atomically add values to StringSet fields on a record.
|
|
850
|
+
*/
|
|
851
|
+
addToStringSet(modelName: string, id: string, sets: Record<string, string[]>, options?: {
|
|
852
|
+
condition?: DocumentFilter;
|
|
853
|
+
}): Promise<void>;
|
|
854
|
+
/**
|
|
855
|
+
* Atomically remove values from StringSet fields on a record.
|
|
856
|
+
*/
|
|
857
|
+
removeFromStringSet(modelName: string, id: string, sets: Record<string, string[]>, options?: {
|
|
858
|
+
condition?: DocumentFilter;
|
|
859
|
+
}): Promise<void>;
|
|
860
|
+
/**
|
|
861
|
+
* Atomically increment/decrement numeric fields on a record.
|
|
862
|
+
* Returns the new values after the increment.
|
|
863
|
+
*/
|
|
864
|
+
incrementFields(modelName: string, id: string, fields: Record<string, number>, options?: {
|
|
865
|
+
condition?: DocumentFilter;
|
|
866
|
+
}): Promise<Record<string, number>>;
|
|
867
|
+
/**
|
|
868
|
+
* Execute multiple save/patch/delete operations in a single request.
|
|
869
|
+
* All operations run in a single transaction on the server.
|
|
870
|
+
*/
|
|
871
|
+
batchWrite(operations: BatchOperation[]): Promise<BatchOperationResult[]>;
|
|
872
|
+
/**
|
|
873
|
+
* Check if the DO is healthy.
|
|
874
|
+
*/
|
|
875
|
+
healthCheck(): Promise<{
|
|
876
|
+
status: string;
|
|
877
|
+
}>;
|
|
878
|
+
/**
|
|
879
|
+
* Batch sync indexes: send all desired indexes in one request.
|
|
880
|
+
* The DO compares against its _indexes table and registers only what's missing.
|
|
881
|
+
* Returns the number of indexes/constraints newly registered.
|
|
882
|
+
*/
|
|
883
|
+
syncIndexesBatch(request: SyncIndexesRequest): Promise<number>;
|
|
884
|
+
/**
|
|
885
|
+
* Register an index on a model field.
|
|
886
|
+
* Creates a SQLite index on json_extract(data_json, '$.fieldName').
|
|
887
|
+
* Set unique=true to enforce uniqueness on this field.
|
|
888
|
+
*/
|
|
889
|
+
registerIndex(modelName: string, fieldName: string, fieldType?: string, unique?: boolean): Promise<void>;
|
|
890
|
+
/**
|
|
891
|
+
* Drop an index from a model field.
|
|
892
|
+
*/
|
|
893
|
+
dropIndex(modelName: string, fieldName: string): Promise<void>;
|
|
894
|
+
/**
|
|
895
|
+
* List indexes, optionally filtered by model name.
|
|
896
|
+
*/
|
|
897
|
+
listIndexes(modelName?: string): Promise<IndexEntry[]>;
|
|
898
|
+
/**
|
|
899
|
+
* Describe tracked fields for a model.
|
|
900
|
+
*/
|
|
901
|
+
describe(modelName: string): Promise<ModelFieldInfo[]>;
|
|
902
|
+
/**
|
|
903
|
+
* Register a composite unique constraint across multiple fields.
|
|
904
|
+
*/
|
|
905
|
+
registerUniqueConstraint(modelName: string, constraintName: string, fields: string[]): Promise<void>;
|
|
906
|
+
/**
|
|
907
|
+
* Drop a composite unique constraint.
|
|
908
|
+
*/
|
|
909
|
+
dropUniqueConstraint(modelName: string, constraintName: string): Promise<void>;
|
|
910
|
+
/**
|
|
911
|
+
* List composite unique constraints, optionally filtered by model name.
|
|
912
|
+
*/
|
|
913
|
+
listUniqueConstraints(modelName?: string): Promise<UniqueConstraintEntry[]>;
|
|
914
|
+
/**
|
|
915
|
+
* Ensure the engine is ready.
|
|
916
|
+
* For DOClient, this verifies connectivity.
|
|
917
|
+
*/
|
|
918
|
+
ensureReady(): Promise<void>;
|
|
919
|
+
/**
|
|
920
|
+
* Execute raw SQL.
|
|
921
|
+
* Not supported in DO client mode - use queryModel instead.
|
|
922
|
+
*/
|
|
923
|
+
query(_sql: string, _params?: any[]): Promise<any[]>;
|
|
924
|
+
/**
|
|
925
|
+
* Get last error message.
|
|
926
|
+
*/
|
|
927
|
+
getLastErrorMessage(): string | undefined;
|
|
928
|
+
/**
|
|
929
|
+
* Get table schema.
|
|
930
|
+
* Not directly supported - schema is managed by the DO.
|
|
931
|
+
*/
|
|
932
|
+
getTableSchema(_tableName: string): Promise<any>;
|
|
933
|
+
/**
|
|
934
|
+
* Destroy the engine.
|
|
935
|
+
* Nothing to clean up for the client.
|
|
936
|
+
*/
|
|
937
|
+
destroy(): Promise<void>;
|
|
938
|
+
/**
|
|
939
|
+
* Create table.
|
|
940
|
+
* No-op in DO client mode - schema is managed by the DO.
|
|
941
|
+
*/
|
|
942
|
+
createTable(_modelName: string, _schema: Map<string, FieldOptions>, _options: ModelOptions): Promise<void>;
|
|
943
|
+
/**
|
|
944
|
+
* Create StringSet junction table.
|
|
945
|
+
* No-op in DO client mode.
|
|
946
|
+
*/
|
|
947
|
+
createStringSetJunctionTable(_modelName: string, _fieldName: string): Promise<void>;
|
|
948
|
+
/**
|
|
949
|
+
* Insert a record.
|
|
950
|
+
* Delegates to saveModel.
|
|
951
|
+
*/
|
|
952
|
+
insert(modelName: string, data: any): Promise<void>;
|
|
953
|
+
/**
|
|
954
|
+
* Delete a record.
|
|
955
|
+
* Delegates to deleteModel.
|
|
956
|
+
*/
|
|
957
|
+
delete(modelName: string, id: string): Promise<void>;
|
|
958
|
+
/**
|
|
959
|
+
* Get table name.
|
|
960
|
+
* All models use 'records' in JSON schema.
|
|
961
|
+
*/
|
|
962
|
+
getTableName(_modelName: string): string;
|
|
963
|
+
/**
|
|
964
|
+
* Transaction support.
|
|
965
|
+
* DO client doesn't support client-side transactions.
|
|
966
|
+
* Operations are atomic on the DO side.
|
|
967
|
+
*/
|
|
968
|
+
withTransaction<T>(callback: (operations: ITransactionalDatabaseOperations) => Promise<T>): Promise<T>;
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
/**
|
|
972
|
+
* Durable Object Mode Initialization
|
|
973
|
+
*
|
|
974
|
+
* Alternative initialization for js-bao that uses Cloudflare Durable Objects
|
|
975
|
+
* instead of yjs for document storage.
|
|
976
|
+
*
|
|
977
|
+
* Key differences from yjs mode:
|
|
978
|
+
* - No yjs dependency
|
|
979
|
+
* - Server-authoritative (DO is source of truth)
|
|
980
|
+
* - HTTP-based communication with DO backend
|
|
981
|
+
* - One DO per document
|
|
982
|
+
* - Schemaless: any field can be saved/queried without registration
|
|
983
|
+
* - Only indexes need explicit registration for performance
|
|
984
|
+
*/
|
|
985
|
+
|
|
986
|
+
/**
|
|
987
|
+
* A model can be identified by either a BaseModel subclass or a plain string name.
|
|
988
|
+
* Use a string when you don't have a model class (e.g., schemaless / CSV import).
|
|
989
|
+
*/
|
|
990
|
+
type ModelIdentifier = typeof BaseModel | string;
|
|
991
|
+
/**
|
|
992
|
+
* Configuration for connectDoDb
|
|
993
|
+
*/
|
|
994
|
+
interface ConnectDoDbOptions {
|
|
995
|
+
/** Base URL of the Cloudflare Worker */
|
|
996
|
+
endpoint: string;
|
|
997
|
+
/** Document ID to connect to */
|
|
998
|
+
id: string;
|
|
999
|
+
/** Model classes to create pre-bound accessors for */
|
|
1000
|
+
models?: (typeof BaseModel)[];
|
|
1001
|
+
/** Optional authorization header value */
|
|
1002
|
+
authorization?: string;
|
|
1003
|
+
/** Optional custom fetch function (for testing) */
|
|
1004
|
+
fetch?: typeof fetch;
|
|
1005
|
+
/** Request timeout in milliseconds (default: 30000) */
|
|
1006
|
+
timeout?: number;
|
|
1007
|
+
}
|
|
1008
|
+
/**
|
|
1009
|
+
* Pre-bound model accessor — all methods are scoped to a specific model.
|
|
1010
|
+
*/
|
|
1011
|
+
interface SaveOptions {
|
|
1012
|
+
stringSets?: Record<string, string[]>;
|
|
1013
|
+
ifNotExists?: boolean;
|
|
1014
|
+
condition?: DocumentFilter;
|
|
1015
|
+
}
|
|
1016
|
+
interface PatchOptions {
|
|
1017
|
+
stringSets?: Record<string, string[]>;
|
|
1018
|
+
condition?: DocumentFilter;
|
|
1019
|
+
}
|
|
1020
|
+
interface WriteCondition {
|
|
1021
|
+
condition?: DocumentFilter;
|
|
1022
|
+
}
|
|
1023
|
+
interface ModelAccessor {
|
|
1024
|
+
query<T extends Record<string, any> = Record<string, any>>(filter?: DocumentFilter, options?: QueryOptions): Promise<PaginatedResult<T>>;
|
|
1025
|
+
find<T extends Record<string, any> = Record<string, any>>(id: string): Promise<T | null>;
|
|
1026
|
+
save(data: Record<string, any>, options?: SaveOptions | Record<string, string[]>): Promise<string>;
|
|
1027
|
+
patch(id: string, data: Record<string, any>, options?: PatchOptions | Record<string, string[]>): Promise<string>;
|
|
1028
|
+
delete(id: string, options?: WriteCondition): Promise<boolean>;
|
|
1029
|
+
count(filter?: DocumentFilter): Promise<number>;
|
|
1030
|
+
aggregate(options: AggregationOptions): Promise<AggregationResult>;
|
|
1031
|
+
increment(id: string, fields: Record<string, number>, options?: WriteCondition): Promise<Record<string, number>>;
|
|
1032
|
+
addToSet(id: string, sets: Record<string, string[]>, options?: WriteCondition): Promise<void>;
|
|
1033
|
+
removeFromSet(id: string, sets: Record<string, string[]>, options?: WriteCondition): Promise<void>;
|
|
1034
|
+
}
|
|
1035
|
+
/**
|
|
1036
|
+
* Result of connectDoDb — provides both ad-hoc and pre-bound model access.
|
|
1037
|
+
*
|
|
1038
|
+
* Ad-hoc: `db.query(User, filter)` — works with any model class.
|
|
1039
|
+
* Pre-bound: `db.User.query(filter)` — only for models passed in `models` array.
|
|
1040
|
+
*/
|
|
1041
|
+
interface DoDb {
|
|
1042
|
+
/** The underlying DO client engine */
|
|
1043
|
+
readonly engine: DOClientEngine;
|
|
1044
|
+
/** The connected document ID */
|
|
1045
|
+
readonly docId: string;
|
|
1046
|
+
query<T extends Record<string, any> = Record<string, any>>(model: ModelIdentifier, filter?: DocumentFilter, options?: QueryOptions): Promise<PaginatedResult<T>>;
|
|
1047
|
+
find<T extends Record<string, any> = Record<string, any>>(model: ModelIdentifier, id: string): Promise<T | null>;
|
|
1048
|
+
save(model: ModelIdentifier, data: Record<string, any>, options?: SaveOptions | Record<string, string[]>): Promise<string>;
|
|
1049
|
+
patch(model: ModelIdentifier, id: string, data: Record<string, any>, options?: PatchOptions | Record<string, string[]>): Promise<string>;
|
|
1050
|
+
delete(model: ModelIdentifier, id: string, options?: WriteCondition): Promise<boolean>;
|
|
1051
|
+
count(model: ModelIdentifier, filter?: DocumentFilter): Promise<number>;
|
|
1052
|
+
aggregate(model: ModelIdentifier, options: AggregationOptions): Promise<AggregationResult>;
|
|
1053
|
+
increment(model: ModelIdentifier, id: string, fields: Record<string, number>, options?: WriteCondition): Promise<Record<string, number>>;
|
|
1054
|
+
addToSet(model: ModelIdentifier, id: string, sets: Record<string, string[]>, options?: WriteCondition): Promise<void>;
|
|
1055
|
+
removeFromSet(model: ModelIdentifier, id: string, sets: Record<string, string[]>, options?: WriteCondition): Promise<void>;
|
|
1056
|
+
batch(operations: BatchOperation[]): Promise<BatchOperationResult[]>;
|
|
1057
|
+
describe(modelName: string): Promise<ModelFieldInfo[]>;
|
|
1058
|
+
registerIndex(modelName: string, fieldName: string, fieldType?: string, unique?: boolean): Promise<void>;
|
|
1059
|
+
dropIndex(modelName: string, fieldName: string): Promise<void>;
|
|
1060
|
+
listIndexes(modelName?: string): Promise<IndexEntry[]>;
|
|
1061
|
+
registerUniqueConstraint(modelName: string, constraintName: string, fields: string[]): Promise<void>;
|
|
1062
|
+
dropUniqueConstraint(modelName: string, constraintName: string): Promise<void>;
|
|
1063
|
+
listUniqueConstraints(modelName?: string): Promise<UniqueConstraintEntry[]>;
|
|
1064
|
+
syncIndexes(modelClass: typeof BaseModel): Promise<number>;
|
|
1065
|
+
/**
|
|
1066
|
+
* Sync indexes for all models passed in the `models` array at init.
|
|
1067
|
+
* Returns total number of indexes/constraints newly registered.
|
|
1068
|
+
*/
|
|
1069
|
+
syncAllIndexes(): Promise<number>;
|
|
1070
|
+
[modelName: string]: any;
|
|
1071
|
+
}
|
|
1072
|
+
/**
|
|
1073
|
+
* Connect to a Durable Object document database.
|
|
1074
|
+
*
|
|
1075
|
+
* Combines initialization and document connection into a single call.
|
|
1076
|
+
* Returns an object with both ad-hoc and pre-bound model access.
|
|
1077
|
+
*
|
|
1078
|
+
* Usage:
|
|
1079
|
+
* ```typescript
|
|
1080
|
+
* import { connectDoDb } from 'js-bao/cloudflare';
|
|
1081
|
+
* import { User, Post } from './models';
|
|
1082
|
+
*
|
|
1083
|
+
* const db = connectDoDb({
|
|
1084
|
+
* endpoint: 'https://my-worker.workers.dev',
|
|
1085
|
+
* id: 'my-document',
|
|
1086
|
+
* models: [User, Post],
|
|
1087
|
+
* });
|
|
1088
|
+
*
|
|
1089
|
+
* // Pre-bound model access (models registered at init)
|
|
1090
|
+
* await db.User.save({ id: 'u-1', name: 'Alice' });
|
|
1091
|
+
* const users = await db.User.query({ name: 'Alice' });
|
|
1092
|
+
* const user = await db.User.find('u-1');
|
|
1093
|
+
*
|
|
1094
|
+
* // Ad-hoc model access (any model class)
|
|
1095
|
+
* await db.save(User, { id: 'u-2', name: 'Bob' });
|
|
1096
|
+
* const results = await db.query(User, { name: 'Bob' });
|
|
1097
|
+
* ```
|
|
1098
|
+
*/
|
|
1099
|
+
declare function connectDoDb(options: ConnectDoDbOptions): DoDb;
|
|
1100
|
+
|
|
1101
|
+
export { type AggregateRequest, type AggregateResponse, type AggregationOperation, type AggregationOptions, type AggregationResult, type BatchOperation, type BatchOperationResult, type BatchRequest, type BatchResponse, type ConnectDoDbOptions, type CountRequest, type CountResponse, DOClientEngine, type DOClientEngineConfig, type DeleteRequest, type DeleteResponse, type DescribeResponse, type DoDb, type DocumentFilter, type ErrorResponse, type GroupByField, type IncrementRequest, type IncrementResponse, type IndexEntry, type ModelAccessor, type ModelFieldInfo, type ModelIdentifier, type PaginatedResult, type PatchOptions, type PatchRequest, type PatchResponse, type ProjectionSpec, type QueryOptions, type QueryRequest, type QueryResponse, type SaveOptions, type SaveRequest, type SaveResponse, type SortSpec, type StringSetMembership, type StringSetUpdateRequest, type StringSetUpdateResponse, type SyncIndexesRequest, type SyncIndexesResponse, type UniqueConstraintEntry, type WriteCondition, connectDoDb };
|