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,1366 @@
|
|
|
1
|
+
interface RefersToRelationshipConfig {
|
|
2
|
+
type: "refersTo";
|
|
3
|
+
model: string;
|
|
4
|
+
relatedIdField: string;
|
|
5
|
+
}
|
|
6
|
+
interface HasManyRelationshipConfig {
|
|
7
|
+
type: "hasMany";
|
|
8
|
+
model: string;
|
|
9
|
+
relatedIdField: string;
|
|
10
|
+
orderByField?: string;
|
|
11
|
+
orderDirection?: "ASC" | "DESC";
|
|
12
|
+
}
|
|
13
|
+
interface HasManyThroughRelationshipConfig {
|
|
14
|
+
type: "hasManyThrough";
|
|
15
|
+
model: string;
|
|
16
|
+
joinModel: string;
|
|
17
|
+
joinModelLocalField: string;
|
|
18
|
+
joinModelRelatedField: string;
|
|
19
|
+
joinModelOrderByField?: string;
|
|
20
|
+
joinModelOrderDirection?: "ASC" | "DESC";
|
|
21
|
+
}
|
|
22
|
+
type RelationshipConfig = RefersToRelationshipConfig | HasManyRelationshipConfig | HasManyThroughRelationshipConfig;
|
|
23
|
+
|
|
24
|
+
type FieldType = "string" | "number" | "boolean" | "date" | "id" | "stringset";
|
|
25
|
+
interface FieldOptions {
|
|
26
|
+
type: FieldType;
|
|
27
|
+
indexed?: boolean;
|
|
28
|
+
required?: boolean;
|
|
29
|
+
unique?: boolean;
|
|
30
|
+
default?: any | (() => any);
|
|
31
|
+
autoAssign?: boolean;
|
|
32
|
+
maxLength?: number;
|
|
33
|
+
maxCount?: number;
|
|
34
|
+
}
|
|
35
|
+
interface UniqueConstraintConfig {
|
|
36
|
+
name: string;
|
|
37
|
+
fields: string[];
|
|
38
|
+
}
|
|
39
|
+
interface ModelOptions {
|
|
40
|
+
name: string;
|
|
41
|
+
uniqueConstraints?: UniqueConstraintConfig[];
|
|
42
|
+
relationships?: Record<string, RelationshipConfig>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface ITransactionalDatabaseOperations {
|
|
46
|
+
insert(modelName: string, data: any): Promise<void>;
|
|
47
|
+
delete(modelName: string, id: string): Promise<void>;
|
|
48
|
+
query<T extends Record<string, any>>(sql: string, params?: any[]): Promise<T[]>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Abstract class defining the interface for database engines.
|
|
52
|
+
* This allows for different database implementations (e.g., SQL.js, DuckDB) to be used interchangeably.
|
|
53
|
+
*/
|
|
54
|
+
declare abstract class DatabaseEngine {
|
|
55
|
+
/**
|
|
56
|
+
* Ensures that the database engine is fully initialized and ready for use.
|
|
57
|
+
* For WASM-based engines, this might involve loading the WASM module.
|
|
58
|
+
*/
|
|
59
|
+
abstract ensureReady(): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* Executes a SQL query against the database.
|
|
62
|
+
* @param sql The SQL query string.
|
|
63
|
+
* @param params Optional array of parameters for prepared statements.
|
|
64
|
+
* @returns A promise that resolves to an array of query results.
|
|
65
|
+
*/
|
|
66
|
+
abstract query(sql: string, params?: any[]): Promise<any[]>;
|
|
67
|
+
/**
|
|
68
|
+
* Retrieves the last error message from the database engine, if any.
|
|
69
|
+
* @returns The last error message as a string, or undefined if no error occurred.
|
|
70
|
+
*/
|
|
71
|
+
abstract getLastErrorMessage(): string | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* Retrieves the schema for a given table.
|
|
74
|
+
* This is useful for understanding table structure, field types, etc.
|
|
75
|
+
* The exact return type might vary based on the database engine.
|
|
76
|
+
* @param tableName The name of the table.
|
|
77
|
+
* @returns A promise that resolves to the table schema information.
|
|
78
|
+
*/
|
|
79
|
+
abstract getTableSchema(tableName: string): Promise<any>;
|
|
80
|
+
/**
|
|
81
|
+
* Destroys the database engine instance and releases any associated resources.
|
|
82
|
+
* This is crucial for cleanup, especially in testing environments or when the application is shutting down.
|
|
83
|
+
*/
|
|
84
|
+
abstract destroy(): Promise<void>;
|
|
85
|
+
createTable(_modelName: string, _schema: Map<string, any>, // Assuming 'any' for field options for now, can be refined
|
|
86
|
+
_options: ModelOptions): Promise<void>;
|
|
87
|
+
createStringSetJunctionTable(_modelName: string, _fieldName: string): Promise<void>;
|
|
88
|
+
insertStringSetValues(_modelName: string, _fieldName: string, _recordId: string, _values: string[]): Promise<void>;
|
|
89
|
+
removeStringSetValues(_modelName: string, _fieldName: string, _recordId: string, _values: string[]): Promise<void>;
|
|
90
|
+
insert(_modelName: string, _data: any): Promise<void>;
|
|
91
|
+
delete(_modelName: string, _id: string): Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Deletes all records for a specific document from the given model table.
|
|
94
|
+
* This is used when disconnecting a document to remove all its data.
|
|
95
|
+
* @param modelName The name of the model/table
|
|
96
|
+
* @param docId The document ID to filter by
|
|
97
|
+
*/
|
|
98
|
+
deleteByDocumentId(_modelName: string, _docId: string): Promise<void>;
|
|
99
|
+
getTableName(_modelName: string): string;
|
|
100
|
+
withTransaction<T>(_callback: (operations: ITransactionalDatabaseOperations) => Promise<T>): Promise<T>;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* JSON Schema DDL Generator
|
|
105
|
+
*
|
|
106
|
+
* Generates SQL DDL statements for the JSON schema approach where all records
|
|
107
|
+
* are stored in a single `records` table with a `_data` column.
|
|
108
|
+
*
|
|
109
|
+
* Internal columns use a `_` prefix convention:
|
|
110
|
+
* _id, _type, _data (records table)
|
|
111
|
+
* _record_id, _type (stringset_index table)
|
|
112
|
+
* _meta_doc_id, _meta_permission_hint (yjs mode metadata)
|
|
113
|
+
*
|
|
114
|
+
* This schema is used by both:
|
|
115
|
+
* - OPFS SQLite (browser, with _meta_doc_id for multi-document support)
|
|
116
|
+
* - Durable Objects SQLite (server, one DO per document, no _meta_doc_id needed)
|
|
117
|
+
*/
|
|
118
|
+
interface JsonSchemaOptions {
|
|
119
|
+
/**
|
|
120
|
+
* Whether to include the _meta_doc_id column.
|
|
121
|
+
* - true: For yjs mode where multiple documents share the same SQLite DB
|
|
122
|
+
* - false: For DO mode where each DO is a single document
|
|
123
|
+
*/
|
|
124
|
+
includeDocIdColumn: boolean;
|
|
125
|
+
}
|
|
126
|
+
declare class JsonSchemaDDL {
|
|
127
|
+
/**
|
|
128
|
+
* Generate CREATE TABLE statement for the records table
|
|
129
|
+
*/
|
|
130
|
+
static createRecordsTable(options: JsonSchemaOptions): string;
|
|
131
|
+
/**
|
|
132
|
+
* Generate CREATE TABLE statement for the stringset_index table
|
|
133
|
+
*/
|
|
134
|
+
static createStringSetIndexTable(options: JsonSchemaOptions): string;
|
|
135
|
+
/**
|
|
136
|
+
* Generate base indexes for the schema
|
|
137
|
+
*/
|
|
138
|
+
static createBaseIndexes(options: JsonSchemaOptions): string[];
|
|
139
|
+
/**
|
|
140
|
+
* Generate CREATE INDEX statement for a model field
|
|
141
|
+
* Uses json_extract for JSON schema
|
|
142
|
+
*/
|
|
143
|
+
static createFieldIndex(modelName: string, fieldName: string): string;
|
|
144
|
+
/**
|
|
145
|
+
* Generate DROP INDEX statement for a model field
|
|
146
|
+
*/
|
|
147
|
+
static dropFieldIndex(modelName: string, fieldName: string): string;
|
|
148
|
+
/**
|
|
149
|
+
* Generate CREATE TABLE statement for the _indexes table.
|
|
150
|
+
* Stores per-field index registrations (one row per index).
|
|
151
|
+
*/
|
|
152
|
+
static createIndexesTable(): string;
|
|
153
|
+
/**
|
|
154
|
+
* Generate CREATE TABLE statement for the _unique_constraints table.
|
|
155
|
+
* Stores composite (multi-field) unique constraints.
|
|
156
|
+
*/
|
|
157
|
+
static createUniqueConstraintsTable(): string;
|
|
158
|
+
/**
|
|
159
|
+
* Generate CREATE TABLE statement for the _model_fields table.
|
|
160
|
+
* Tracks field names and inferred types as records are written.
|
|
161
|
+
*/
|
|
162
|
+
static createModelFieldsTable(): string;
|
|
163
|
+
/**
|
|
164
|
+
* Generate all DDL statements needed to initialize the schema
|
|
165
|
+
*/
|
|
166
|
+
static getAllDDL(options: JsonSchemaOptions): string[];
|
|
167
|
+
/**
|
|
168
|
+
* Generate INSERT statement for a record
|
|
169
|
+
*/
|
|
170
|
+
static buildInsertSQL(options: JsonSchemaOptions): string;
|
|
171
|
+
/**
|
|
172
|
+
* Generate DELETE statement for a record by id and type
|
|
173
|
+
*/
|
|
174
|
+
static buildDeleteSQL(options: JsonSchemaOptions): string;
|
|
175
|
+
/**
|
|
176
|
+
* Generate DELETE statement for stringset values
|
|
177
|
+
*/
|
|
178
|
+
static buildDeleteStringSetSQL(): string;
|
|
179
|
+
/**
|
|
180
|
+
* Generate INSERT statement for stringset values
|
|
181
|
+
*/
|
|
182
|
+
static buildInsertStringSetSQL(options: JsonSchemaOptions): string;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* JSON Schema Engine Base Class
|
|
187
|
+
*
|
|
188
|
+
* Abstract base class for database engines that use the JSON schema approach.
|
|
189
|
+
* Provides common implementations for CRUD operations using the single `records`
|
|
190
|
+
* table with `data_json` column.
|
|
191
|
+
*
|
|
192
|
+
* Subclasses must implement:
|
|
193
|
+
* - execSql(sql, params): Execute SQL and return results
|
|
194
|
+
* - ensureReady(): Initialize the engine
|
|
195
|
+
* - destroy(): Clean up resources
|
|
196
|
+
*/
|
|
197
|
+
|
|
198
|
+
interface JsonSchemaEngineOptions extends JsonSchemaOptions {
|
|
199
|
+
}
|
|
200
|
+
declare abstract class JsonSchemaEngine extends DatabaseEngine {
|
|
201
|
+
protected schemaOptions: JsonSchemaEngineOptions;
|
|
202
|
+
initialized: boolean;
|
|
203
|
+
constructor(options: JsonSchemaEngineOptions);
|
|
204
|
+
/**
|
|
205
|
+
* Execute SQL and return results.
|
|
206
|
+
* Must be implemented by subclasses.
|
|
207
|
+
*/
|
|
208
|
+
abstract execSql(sql: string, params?: any[]): Promise<any[]>;
|
|
209
|
+
/**
|
|
210
|
+
* Execute SQL synchronously (optional, for environments that support it like DO).
|
|
211
|
+
* Returns undefined if not supported.
|
|
212
|
+
*/
|
|
213
|
+
execSqlSync?(sql: string, params?: any[]): any[];
|
|
214
|
+
/**
|
|
215
|
+
* Initialize the JSON schema tables.
|
|
216
|
+
* Should be called once during engine setup.
|
|
217
|
+
*/
|
|
218
|
+
initializeSchema(): Promise<void>;
|
|
219
|
+
/**
|
|
220
|
+
* Create table for a model.
|
|
221
|
+
* In JSON schema, this is a no-op since all models share the `records` table.
|
|
222
|
+
* However, we can create indexes for indexed fields.
|
|
223
|
+
*/
|
|
224
|
+
createTable(modelName: string, schema: Map<string, FieldOptions>, _options: ModelOptions): Promise<void>;
|
|
225
|
+
/**
|
|
226
|
+
* Create StringSet junction table.
|
|
227
|
+
* In JSON schema, this is a no-op since we use the shared stringset_index table.
|
|
228
|
+
*/
|
|
229
|
+
createStringSetJunctionTable(_modelName: string, _fieldName: string): Promise<void>;
|
|
230
|
+
/**
|
|
231
|
+
* Insert or update a record.
|
|
232
|
+
*/
|
|
233
|
+
insert(modelName: string, data: any): Promise<void>;
|
|
234
|
+
/**
|
|
235
|
+
* Delete a record by ID.
|
|
236
|
+
*/
|
|
237
|
+
delete(modelName: string, id: string): Promise<void>;
|
|
238
|
+
/**
|
|
239
|
+
* Delete all records for a specific document.
|
|
240
|
+
* Only applicable in yjs mode with doc ID column.
|
|
241
|
+
*/
|
|
242
|
+
deleteByDocumentId(modelName: string, docId: string): Promise<void>;
|
|
243
|
+
/**
|
|
244
|
+
* Insert StringSet values for a record.
|
|
245
|
+
*/
|
|
246
|
+
insertStringSetValues(modelName: string, fieldName: string, recordId: string, values: string[], docId?: string): Promise<void>;
|
|
247
|
+
/**
|
|
248
|
+
* Remove StringSet values for a record.
|
|
249
|
+
*/
|
|
250
|
+
removeStringSetValues(modelName: string, fieldName: string, recordId: string, values: string[]): Promise<void>;
|
|
251
|
+
/**
|
|
252
|
+
* Get table name for a model.
|
|
253
|
+
* In JSON schema, all models use the 'records' table.
|
|
254
|
+
*/
|
|
255
|
+
getTableName(_modelName: string): string;
|
|
256
|
+
/**
|
|
257
|
+
* Execute a query and return results.
|
|
258
|
+
*/
|
|
259
|
+
query(sql: string, params?: any[]): Promise<any[]>;
|
|
260
|
+
/**
|
|
261
|
+
* Get the table schema.
|
|
262
|
+
* Returns information about the records table structure.
|
|
263
|
+
*/
|
|
264
|
+
getTableSchema(_tableName: string): Promise<any>;
|
|
265
|
+
/**
|
|
266
|
+
* Get the last error message.
|
|
267
|
+
* Subclasses can override this if needed.
|
|
268
|
+
*/
|
|
269
|
+
getLastErrorMessage(): string | undefined;
|
|
270
|
+
/**
|
|
271
|
+
* Transaction support.
|
|
272
|
+
* Default implementation runs callback without actual transaction.
|
|
273
|
+
* Subclasses should override for proper transaction support.
|
|
274
|
+
*/
|
|
275
|
+
withTransaction<T>(callback: (operations: ITransactionalDatabaseOperations) => Promise<T>): Promise<T>;
|
|
276
|
+
/**
|
|
277
|
+
* Parse a record row from the database.
|
|
278
|
+
* Extracts fields from _data and merges with direct columns.
|
|
279
|
+
*/
|
|
280
|
+
protected parseRecordRow(row: any): Record<string, any>;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Cloudflare Durable Objects Type Definitions
|
|
285
|
+
*
|
|
286
|
+
* These types mirror the Cloudflare Workers runtime types for Durable Objects.
|
|
287
|
+
* They are provided here so js-bao can be built without requiring the
|
|
288
|
+
* @cloudflare/workers-types package as a dependency.
|
|
289
|
+
*
|
|
290
|
+
* When using js-bao in a Cloudflare Worker, you should install
|
|
291
|
+
* @cloudflare/workers-types for complete type coverage.
|
|
292
|
+
*/
|
|
293
|
+
/**
|
|
294
|
+
* SqlStorage interface - provides SQLite access in Durable Objects
|
|
295
|
+
*/
|
|
296
|
+
interface SqlStorage {
|
|
297
|
+
/**
|
|
298
|
+
* Execute a SQL query with optional parameter bindings.
|
|
299
|
+
* Returns a cursor for iterating over results.
|
|
300
|
+
*/
|
|
301
|
+
exec(query: string, ...bindings: any[]): SqlStorageCursor;
|
|
302
|
+
/**
|
|
303
|
+
* Get the current database size in bytes.
|
|
304
|
+
*/
|
|
305
|
+
readonly databaseSize: number;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* SqlStorageCursor - returned by sql.exec() for iterating results
|
|
309
|
+
*/
|
|
310
|
+
interface SqlStorageCursor extends Iterable<Record<string, any>> {
|
|
311
|
+
/**
|
|
312
|
+
* Get the next row from the cursor.
|
|
313
|
+
*/
|
|
314
|
+
next(): IteratorResult<Record<string, any>>;
|
|
315
|
+
/**
|
|
316
|
+
* Collect all remaining rows into an array.
|
|
317
|
+
*/
|
|
318
|
+
toArray(): Record<string, any>[];
|
|
319
|
+
/**
|
|
320
|
+
* Get exactly one row. Throws if zero or multiple rows.
|
|
321
|
+
*/
|
|
322
|
+
one(): Record<string, any>;
|
|
323
|
+
/**
|
|
324
|
+
* Return an iterator yielding arrays instead of objects.
|
|
325
|
+
*/
|
|
326
|
+
raw(): Iterator<any[]>;
|
|
327
|
+
/**
|
|
328
|
+
* Column names in result order.
|
|
329
|
+
*/
|
|
330
|
+
readonly columnNames: string[];
|
|
331
|
+
/**
|
|
332
|
+
* Number of rows read so far (affects billing).
|
|
333
|
+
*/
|
|
334
|
+
readonly rowsRead: number;
|
|
335
|
+
/**
|
|
336
|
+
* Number of rows written so far (affects billing).
|
|
337
|
+
*/
|
|
338
|
+
readonly rowsWritten: number;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* DurableObjectStorage interface
|
|
342
|
+
*/
|
|
343
|
+
interface DurableObjectStorage {
|
|
344
|
+
/**
|
|
345
|
+
* SQLite storage interface
|
|
346
|
+
*/
|
|
347
|
+
readonly sql: SqlStorage;
|
|
348
|
+
/**
|
|
349
|
+
* Execute a synchronous transaction with SQLite.
|
|
350
|
+
*/
|
|
351
|
+
transactionSync<T>(closure: () => T): T;
|
|
352
|
+
/**
|
|
353
|
+
* Execute an async transaction.
|
|
354
|
+
*/
|
|
355
|
+
transaction<T>(closure: (txn: DurableObjectTransaction) => Promise<T>): Promise<T>;
|
|
356
|
+
get<T = unknown>(key: string): Promise<T | undefined>;
|
|
357
|
+
get<T = unknown>(keys: string[]): Promise<Map<string, T>>;
|
|
358
|
+
put<T>(key: string, value: T): Promise<void>;
|
|
359
|
+
put<T>(entries: Record<string, T>): Promise<void>;
|
|
360
|
+
delete(key: string): Promise<boolean>;
|
|
361
|
+
delete(keys: string[]): Promise<number>;
|
|
362
|
+
deleteAll(): Promise<void>;
|
|
363
|
+
list<T = unknown>(options?: DurableObjectListOptions): Promise<Map<string, T>>;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* DurableObjectTransaction interface
|
|
367
|
+
*/
|
|
368
|
+
interface DurableObjectTransaction {
|
|
369
|
+
get<T = unknown>(key: string): Promise<T | undefined>;
|
|
370
|
+
get<T = unknown>(keys: string[]): Promise<Map<string, T>>;
|
|
371
|
+
put<T>(key: string, value: T): Promise<void>;
|
|
372
|
+
put<T>(entries: Record<string, T>): Promise<void>;
|
|
373
|
+
delete(key: string): Promise<boolean>;
|
|
374
|
+
delete(keys: string[]): Promise<number>;
|
|
375
|
+
rollback(): void;
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Options for storage.list()
|
|
379
|
+
*/
|
|
380
|
+
interface DurableObjectListOptions {
|
|
381
|
+
start?: string;
|
|
382
|
+
startAfter?: string;
|
|
383
|
+
end?: string;
|
|
384
|
+
prefix?: string;
|
|
385
|
+
reverse?: boolean;
|
|
386
|
+
limit?: number;
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* DurableObjectState - passed to DO constructor
|
|
390
|
+
*/
|
|
391
|
+
interface DurableObjectState {
|
|
392
|
+
/**
|
|
393
|
+
* The unique ID of this Durable Object instance.
|
|
394
|
+
*/
|
|
395
|
+
readonly id: DurableObjectId;
|
|
396
|
+
/**
|
|
397
|
+
* Storage interface for this Durable Object.
|
|
398
|
+
*/
|
|
399
|
+
readonly storage: DurableObjectStorage;
|
|
400
|
+
/**
|
|
401
|
+
* Wait until the output gate is open.
|
|
402
|
+
*/
|
|
403
|
+
waitUntil(promise: Promise<any>): void;
|
|
404
|
+
/**
|
|
405
|
+
* Block until storage operations complete.
|
|
406
|
+
*/
|
|
407
|
+
blockConcurrencyWhile<T>(callback: () => Promise<T>): Promise<T>;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* DurableObjectId - unique identifier for a DO instance
|
|
411
|
+
*/
|
|
412
|
+
interface DurableObjectId {
|
|
413
|
+
toString(): string;
|
|
414
|
+
equals(other: DurableObjectId): boolean;
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* DurableObjectNamespace - for accessing DO instances
|
|
418
|
+
*/
|
|
419
|
+
interface DurableObjectNamespace {
|
|
420
|
+
/**
|
|
421
|
+
* Get a DO ID from a name string.
|
|
422
|
+
*/
|
|
423
|
+
idFromName(name: string): DurableObjectId;
|
|
424
|
+
/**
|
|
425
|
+
* Get a DO ID from a hex string.
|
|
426
|
+
*/
|
|
427
|
+
idFromString(hexId: string): DurableObjectId;
|
|
428
|
+
/**
|
|
429
|
+
* Generate a new unique DO ID.
|
|
430
|
+
*/
|
|
431
|
+
newUniqueId(): DurableObjectId;
|
|
432
|
+
/**
|
|
433
|
+
* Get a stub for accessing a DO instance.
|
|
434
|
+
*/
|
|
435
|
+
get(id: DurableObjectId): DurableObjectStub;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* DurableObjectStub - proxy for calling DO methods
|
|
439
|
+
*/
|
|
440
|
+
interface DurableObjectStub {
|
|
441
|
+
/**
|
|
442
|
+
* The ID of this Durable Object.
|
|
443
|
+
*/
|
|
444
|
+
readonly id: DurableObjectId;
|
|
445
|
+
/**
|
|
446
|
+
* The name of this Durable Object (if created via idFromName).
|
|
447
|
+
*/
|
|
448
|
+
readonly name?: string;
|
|
449
|
+
/**
|
|
450
|
+
* Send a fetch request to this Durable Object.
|
|
451
|
+
*/
|
|
452
|
+
fetch(request: Request | string, init?: RequestInit): Promise<Response>;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Durable Object Engine
|
|
457
|
+
*
|
|
458
|
+
* Database engine implementation that runs inside a Cloudflare Durable Object.
|
|
459
|
+
* Uses the DO's embedded SQLite database via ctx.storage.sql.
|
|
460
|
+
*
|
|
461
|
+
* Key characteristics:
|
|
462
|
+
* - Synchronous SQL execution (DO SQLite is sync)
|
|
463
|
+
* - No doc ID column needed (one DO = one document)
|
|
464
|
+
* - Uses JSON schema (records + stringset_index tables)
|
|
465
|
+
* - Schemaless: any model/field can be saved and queried without registration
|
|
466
|
+
* - Indexes are additive: register/drop individual field indexes independently
|
|
467
|
+
*/
|
|
468
|
+
|
|
469
|
+
interface DurableObjectEngineOptions {
|
|
470
|
+
/**
|
|
471
|
+
* The SqlStorage interface from ctx.storage.sql
|
|
472
|
+
*/
|
|
473
|
+
sql: SqlStorage;
|
|
474
|
+
/**
|
|
475
|
+
* The full storage interface for transaction support
|
|
476
|
+
*/
|
|
477
|
+
storage: DurableObjectStorage;
|
|
478
|
+
}
|
|
479
|
+
/** Row shape from the _indexes table */
|
|
480
|
+
interface IndexEntry {
|
|
481
|
+
model_name: string;
|
|
482
|
+
field_name: string;
|
|
483
|
+
field_type: string;
|
|
484
|
+
is_unique: number;
|
|
485
|
+
created_at: string;
|
|
486
|
+
}
|
|
487
|
+
/** Row shape from the _unique_constraints table */
|
|
488
|
+
interface UniqueConstraintEntry {
|
|
489
|
+
model_name: string;
|
|
490
|
+
constraint_name: string;
|
|
491
|
+
fields: string[];
|
|
492
|
+
created_at: string;
|
|
493
|
+
}
|
|
494
|
+
/** Row shape from the _model_fields table */
|
|
495
|
+
interface ModelFieldInfo {
|
|
496
|
+
model_name: string;
|
|
497
|
+
field_name: string;
|
|
498
|
+
inferred_type: string;
|
|
499
|
+
first_seen_at: string;
|
|
500
|
+
}
|
|
501
|
+
declare class DurableObjectEngine extends JsonSchemaEngine {
|
|
502
|
+
private sql;
|
|
503
|
+
private storage;
|
|
504
|
+
constructor(options: DurableObjectEngineOptions);
|
|
505
|
+
/**
|
|
506
|
+
* Initialize the engine — creates tables and restores persisted indexes.
|
|
507
|
+
*/
|
|
508
|
+
ensureReady(): Promise<void>;
|
|
509
|
+
/**
|
|
510
|
+
* Handle schema migrations for existing databases.
|
|
511
|
+
* Adds columns/tables that were added in later versions.
|
|
512
|
+
*/
|
|
513
|
+
private _migrateSchema;
|
|
514
|
+
/**
|
|
515
|
+
* Load indexes from the _indexes table and re-ensure they exist.
|
|
516
|
+
*/
|
|
517
|
+
private loadPersistedIndexes;
|
|
518
|
+
/**
|
|
519
|
+
* Register an index on a model field.
|
|
520
|
+
* Idempotent — re-registering the same index is a no-op.
|
|
521
|
+
*/
|
|
522
|
+
registerIndex(modelName: string, fieldName: string, fieldType: string, unique?: boolean): void;
|
|
523
|
+
/**
|
|
524
|
+
* Drop an index on a model field.
|
|
525
|
+
* Idempotent — dropping a non-existent index is a no-op.
|
|
526
|
+
*/
|
|
527
|
+
dropIndex(modelName: string, fieldName: string): void;
|
|
528
|
+
/**
|
|
529
|
+
* List all registered indexes, optionally filtered by model.
|
|
530
|
+
*/
|
|
531
|
+
listIndexes(modelName?: string): IndexEntry[];
|
|
532
|
+
/**
|
|
533
|
+
* Get unique single-field indexes for a model.
|
|
534
|
+
*/
|
|
535
|
+
getUniqueIndexes(modelName: string): IndexEntry[];
|
|
536
|
+
/**
|
|
537
|
+
* Register a composite unique constraint.
|
|
538
|
+
* Idempotent — re-registering the same constraint is a no-op.
|
|
539
|
+
*/
|
|
540
|
+
registerUniqueConstraint(modelName: string, constraintName: string, fields: string[]): void;
|
|
541
|
+
/**
|
|
542
|
+
* Drop a composite unique constraint.
|
|
543
|
+
* Idempotent — dropping a non-existent constraint is a no-op.
|
|
544
|
+
*/
|
|
545
|
+
dropUniqueConstraint(modelName: string, constraintName: string): void;
|
|
546
|
+
/**
|
|
547
|
+
* List composite unique constraints, optionally filtered by model.
|
|
548
|
+
*/
|
|
549
|
+
listUniqueConstraints(modelName?: string): UniqueConstraintEntry[];
|
|
550
|
+
/**
|
|
551
|
+
* Check all unique constraints for a model before saving.
|
|
552
|
+
* Returns null if no violation, or an error message string if violated.
|
|
553
|
+
*/
|
|
554
|
+
checkUniqueConstraints(modelName: string, id: string, data: Record<string, any>): string | null;
|
|
555
|
+
/**
|
|
556
|
+
* Check if a record exists (used by hooks to determine isNew).
|
|
557
|
+
*/
|
|
558
|
+
recordExists(modelName: string, id: string): boolean;
|
|
559
|
+
/**
|
|
560
|
+
* Execute SQL asynchronously.
|
|
561
|
+
* Wraps the synchronous DO SQLite API.
|
|
562
|
+
*/
|
|
563
|
+
execSql(sql: string, params?: any[]): Promise<any[]>;
|
|
564
|
+
/**
|
|
565
|
+
* Execute SQL synchronously.
|
|
566
|
+
* This is the native mode for DO SQLite.
|
|
567
|
+
*/
|
|
568
|
+
execSqlSync(sql: string, params?: any[]): any[];
|
|
569
|
+
/**
|
|
570
|
+
* Transaction support using DO's transactionSync.
|
|
571
|
+
*/
|
|
572
|
+
withTransaction<T>(callback: (operations: ITransactionalDatabaseOperations) => Promise<T>): Promise<T>;
|
|
573
|
+
/**
|
|
574
|
+
* Run operations within a synchronous transaction.
|
|
575
|
+
*/
|
|
576
|
+
transactionSync<T>(callback: () => T): T;
|
|
577
|
+
/**
|
|
578
|
+
* Clean up resources.
|
|
579
|
+
*/
|
|
580
|
+
destroy(): Promise<void>;
|
|
581
|
+
/**
|
|
582
|
+
* Insert a record with StringSet support.
|
|
583
|
+
*/
|
|
584
|
+
insertWithStringSets(modelName: string, data: any, stringSets: Record<string, string[]>): Promise<void>;
|
|
585
|
+
/**
|
|
586
|
+
* Add values to StringSet fields without replacing the entire set.
|
|
587
|
+
* Also updates the arrays stored in data_json.
|
|
588
|
+
*/
|
|
589
|
+
addToStringSets(modelName: string, id: string, sets: Record<string, string[]>): void;
|
|
590
|
+
/**
|
|
591
|
+
* Non-transactional core of addToStringSets.
|
|
592
|
+
* Call this from an outer transaction (e.g. batch) to avoid nested transactions.
|
|
593
|
+
* @internal
|
|
594
|
+
*/
|
|
595
|
+
addToStringSetsRaw(modelName: string, id: string, sets: Record<string, string[]>): void;
|
|
596
|
+
/**
|
|
597
|
+
* Remove values from StringSet fields without replacing the entire set.
|
|
598
|
+
* Also updates the arrays stored in data_json.
|
|
599
|
+
*/
|
|
600
|
+
removeFromStringSets(modelName: string, id: string, sets: Record<string, string[]>): void;
|
|
601
|
+
/**
|
|
602
|
+
* Non-transactional core of removeFromStringSets.
|
|
603
|
+
* Call this from an outer transaction (e.g. batch) to avoid nested transactions.
|
|
604
|
+
* @internal
|
|
605
|
+
*/
|
|
606
|
+
removeFromStringSetsRaw(modelName: string, id: string, sets: Record<string, string[]>): void;
|
|
607
|
+
/**
|
|
608
|
+
* Sync stringset_index state back into data_json arrays for the given fields.
|
|
609
|
+
* @internal
|
|
610
|
+
*/
|
|
611
|
+
private _syncStringSetsToJson;
|
|
612
|
+
/**
|
|
613
|
+
* Patch a record: merge provided fields into existing data_json.
|
|
614
|
+
* Only the specified fields are updated; all other fields are preserved.
|
|
615
|
+
* If stringSets are provided, those StringSet fields are fully replaced.
|
|
616
|
+
* Returns false if the record does not exist.
|
|
617
|
+
*/
|
|
618
|
+
patchRecord(modelName: string, id: string, fields: Record<string, any>, stringSets?: Record<string, string[]>): boolean;
|
|
619
|
+
/**
|
|
620
|
+
* Non-transactional core of patchRecord.
|
|
621
|
+
* Call this from an outer transaction (e.g. batch) to avoid nested transactions.
|
|
622
|
+
* @internal
|
|
623
|
+
*/
|
|
624
|
+
patchRecordRaw(modelName: string, id: string, fields: Record<string, any>, stringSets?: Record<string, string[]>): boolean;
|
|
625
|
+
/**
|
|
626
|
+
* Atomically increment/decrement numeric fields on a record.
|
|
627
|
+
* Each key in `fields` is a field name and its value is the delta.
|
|
628
|
+
* Missing fields are initialised to 0 before adding the delta.
|
|
629
|
+
* Returns the new values, or null if the record doesn't exist.
|
|
630
|
+
*/
|
|
631
|
+
incrementFields(modelName: string, id: string, fields: Record<string, number>): Record<string, number> | null;
|
|
632
|
+
/**
|
|
633
|
+
* Non-transactional core of incrementFields.
|
|
634
|
+
* Call this from an outer transaction (e.g. batch) to avoid nested transactions.
|
|
635
|
+
* @internal
|
|
636
|
+
*/
|
|
637
|
+
incrementFieldsRaw(modelName: string, id: string, fields: Record<string, number>): Record<string, number> | null;
|
|
638
|
+
/**
|
|
639
|
+
* Delete a record and its StringSet values atomically.
|
|
640
|
+
*/
|
|
641
|
+
deleteWithStringSets(modelName: string, id: string): Promise<void>;
|
|
642
|
+
/**
|
|
643
|
+
* Track field names and inferred types for a model based on written data.
|
|
644
|
+
* Uses INSERT OR IGNORE so the first-seen type wins.
|
|
645
|
+
*/
|
|
646
|
+
trackModelFields(modelName: string, data: Record<string, any>): void;
|
|
647
|
+
/**
|
|
648
|
+
* Get tracked fields for a model, or all models if no name given.
|
|
649
|
+
*/
|
|
650
|
+
getModelFields(modelName?: string): ModelFieldInfo[];
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
interface ComparisonOperators<T = any> {
|
|
654
|
+
$eq?: T;
|
|
655
|
+
$ne?: T;
|
|
656
|
+
$gt?: T;
|
|
657
|
+
$gte?: T;
|
|
658
|
+
$lt?: T;
|
|
659
|
+
$lte?: T;
|
|
660
|
+
$in?: T[];
|
|
661
|
+
$nin?: T[];
|
|
662
|
+
}
|
|
663
|
+
interface StringSetOperators {
|
|
664
|
+
/**
|
|
665
|
+
* Exact membership: StringSet contains this specific string
|
|
666
|
+
*/
|
|
667
|
+
$contains?: string;
|
|
668
|
+
$all?: string[];
|
|
669
|
+
$size?: number | ComparisonOperators<number>;
|
|
670
|
+
}
|
|
671
|
+
interface SubstringOperators {
|
|
672
|
+
/** Prefix match */
|
|
673
|
+
$startsWith?: string;
|
|
674
|
+
/** Suffix match */
|
|
675
|
+
$endsWith?: string;
|
|
676
|
+
/** Substring anywhere */
|
|
677
|
+
$containsText?: string;
|
|
678
|
+
}
|
|
679
|
+
interface ExistenceOperators {
|
|
680
|
+
$exists?: boolean;
|
|
681
|
+
}
|
|
682
|
+
type FieldOperators<T = any> = ComparisonOperators<T> & ExistenceOperators & StringSetOperators & SubstringOperators;
|
|
683
|
+
interface LogicalOperators {
|
|
684
|
+
$and?: DocumentFilter[];
|
|
685
|
+
$or?: DocumentFilter[];
|
|
686
|
+
}
|
|
687
|
+
type DocumentFilter = {
|
|
688
|
+
[field: string]: any | FieldOperators<any>;
|
|
689
|
+
} & LogicalOperators;
|
|
690
|
+
type SortDirection = 1 | -1;
|
|
691
|
+
type SortSpec = {
|
|
692
|
+
[field: string]: SortDirection;
|
|
693
|
+
};
|
|
694
|
+
type ProjectionSpec = {
|
|
695
|
+
[field: string]: 1 | 0;
|
|
696
|
+
};
|
|
697
|
+
interface IncludeSpec {
|
|
698
|
+
model: string;
|
|
699
|
+
type: "refersTo" | "hasMany" | "refersToMany";
|
|
700
|
+
sourceField?: string;
|
|
701
|
+
foreignKey?: string;
|
|
702
|
+
localField?: string;
|
|
703
|
+
as?: string;
|
|
704
|
+
projection?: ProjectionSpec;
|
|
705
|
+
limit?: number;
|
|
706
|
+
sort?: SortSpec;
|
|
707
|
+
filter?: DocumentFilter;
|
|
708
|
+
include?: IncludeSpec[];
|
|
709
|
+
}
|
|
710
|
+
interface QueryOptions {
|
|
711
|
+
sort?: SortSpec;
|
|
712
|
+
projection?: ProjectionSpec;
|
|
713
|
+
documents?: string | string[];
|
|
714
|
+
limit?: number;
|
|
715
|
+
uniqueStartKey?: string;
|
|
716
|
+
direction?: 1 | -1;
|
|
717
|
+
include?: IncludeSpec[];
|
|
718
|
+
}
|
|
719
|
+
interface TranslatedQuery {
|
|
720
|
+
sql: string;
|
|
721
|
+
params: any[];
|
|
722
|
+
sortFields: string[];
|
|
723
|
+
sortDirections?: (1 | -1)[];
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* JSON Query Translator
|
|
728
|
+
*
|
|
729
|
+
* Translates document-style queries to SQL for the JSON schema approach.
|
|
730
|
+
* All records are in a single `records` table with fields stored in `_data`.
|
|
731
|
+
*
|
|
732
|
+
* Key differences from DocumentQueryTranslator:
|
|
733
|
+
* - Uses json_extract(_data, '$.field') instead of direct column access
|
|
734
|
+
* - Uses shared stringset_index table instead of per-model junction tables
|
|
735
|
+
* - Adds _type = ? filter to all queries
|
|
736
|
+
* - Optionally handles _meta_doc_id for yjs mode
|
|
737
|
+
*/
|
|
738
|
+
|
|
739
|
+
interface JsonQueryTranslatorOptions {
|
|
740
|
+
/**
|
|
741
|
+
* Whether to include document scoping (_meta_doc_id) in queries.
|
|
742
|
+
* - true: For yjs mode where multiple documents share the same SQLite DB
|
|
743
|
+
* - false: For DO mode where each DO is a single document
|
|
744
|
+
*/
|
|
745
|
+
includeDocId: boolean;
|
|
746
|
+
}
|
|
747
|
+
declare class JsonQueryTranslator {
|
|
748
|
+
private modelName;
|
|
749
|
+
private schema?;
|
|
750
|
+
private options;
|
|
751
|
+
private fieldSqlCache;
|
|
752
|
+
constructor(modelName: string, schema?: Map<string, FieldOptions>, options?: JsonQueryTranslatorOptions);
|
|
753
|
+
/**
|
|
754
|
+
* Get SQL expression for a field.
|
|
755
|
+
* System fields (id, type) map to internal columns (_id, _type);
|
|
756
|
+
* others use json_extract(_data, ...).
|
|
757
|
+
* When no schema is provided, any field is accepted (schemaless mode).
|
|
758
|
+
*/
|
|
759
|
+
getFieldSql(fieldName: string): string;
|
|
760
|
+
/**
|
|
761
|
+
* Translate document filter and options to SQL for find operations
|
|
762
|
+
*/
|
|
763
|
+
translateFind(filter: DocumentFilter, options?: QueryOptions): TranslatedQuery;
|
|
764
|
+
/**
|
|
765
|
+
* Translate document filter to SQL for count operations
|
|
766
|
+
*/
|
|
767
|
+
translateCount(filter: DocumentFilter, options?: Pick<QueryOptions, "documents">): {
|
|
768
|
+
sql: string;
|
|
769
|
+
params: any[];
|
|
770
|
+
};
|
|
771
|
+
/**
|
|
772
|
+
* Translate document filter to SQL WHERE clause.
|
|
773
|
+
* Returns the conditions and params without the type = ? prefix.
|
|
774
|
+
*/
|
|
775
|
+
translateFilter(filter: DocumentFilter): {
|
|
776
|
+
sql: string;
|
|
777
|
+
params: any[];
|
|
778
|
+
};
|
|
779
|
+
/**
|
|
780
|
+
* Translate logical operators ($and, $or)
|
|
781
|
+
*/
|
|
782
|
+
private translateLogicalOperator;
|
|
783
|
+
/**
|
|
784
|
+
* Translate field condition to SQL
|
|
785
|
+
*/
|
|
786
|
+
private translateFieldCondition;
|
|
787
|
+
/**
|
|
788
|
+
* Translate field operators to SQL
|
|
789
|
+
*/
|
|
790
|
+
private translateFieldOperators;
|
|
791
|
+
/**
|
|
792
|
+
* Translate individual operator to SQL
|
|
793
|
+
*/
|
|
794
|
+
private translateOperator;
|
|
795
|
+
/**
|
|
796
|
+
* Build SELECT clause based on projection
|
|
797
|
+
* For JSON schema, we need to extract fields from data_json
|
|
798
|
+
*/
|
|
799
|
+
private buildSelectClause;
|
|
800
|
+
/**
|
|
801
|
+
* Build LIMIT clause
|
|
802
|
+
*/
|
|
803
|
+
private buildLimitClause;
|
|
804
|
+
/**
|
|
805
|
+
* Build pagination WHERE clause from cursor
|
|
806
|
+
*/
|
|
807
|
+
private buildPaginationClause;
|
|
808
|
+
/**
|
|
809
|
+
* Validate projection fields — skipped in schemaless mode
|
|
810
|
+
*/
|
|
811
|
+
private validateProjection;
|
|
812
|
+
/**
|
|
813
|
+
* Validate operator is supported for field type
|
|
814
|
+
*/
|
|
815
|
+
private validateOperatorForType;
|
|
816
|
+
/**
|
|
817
|
+
* Validate field value matches expected type
|
|
818
|
+
*/
|
|
819
|
+
private validateFieldValue;
|
|
820
|
+
/**
|
|
821
|
+
* Validate array values for $in/$nin operators
|
|
822
|
+
*/
|
|
823
|
+
private validateArrayValues;
|
|
824
|
+
/**
|
|
825
|
+
* Check if value is a primitive (not an object with operators)
|
|
826
|
+
*/
|
|
827
|
+
private isPrimitiveValue;
|
|
828
|
+
/**
|
|
829
|
+
* Get the type of a value for validation
|
|
830
|
+
*/
|
|
831
|
+
private getValueType;
|
|
832
|
+
/**
|
|
833
|
+
* Check if value type is compatible with field type
|
|
834
|
+
*/
|
|
835
|
+
private isTypeCompatible;
|
|
836
|
+
/**
|
|
837
|
+
* Convert value for SQLite compatibility
|
|
838
|
+
*/
|
|
839
|
+
private convertValueForSQLite;
|
|
840
|
+
private normalizeDocumentIds;
|
|
841
|
+
private buildDocumentClause;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
/**
|
|
845
|
+
* Aggregation types shared between Yjs and DO backends.
|
|
846
|
+
*/
|
|
847
|
+
|
|
848
|
+
/**
|
|
849
|
+
* Describes a StringSet membership check in a groupBy clause.
|
|
850
|
+
* Groups records by whether they have a specific value in a StringSet field.
|
|
851
|
+
*/
|
|
852
|
+
interface StringSetMembership {
|
|
853
|
+
field: string;
|
|
854
|
+
contains: string;
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* A groupBy field can be a plain field name or a StringSet membership check.
|
|
858
|
+
*/
|
|
859
|
+
type GroupByField = string | StringSetMembership;
|
|
860
|
+
/**
|
|
861
|
+
* An aggregation operation (count, sum, avg, min, max).
|
|
862
|
+
*/
|
|
863
|
+
interface AggregationOperation {
|
|
864
|
+
type: "count" | "sum" | "avg" | "min" | "max";
|
|
865
|
+
/** Required for sum, avg, min, max; not used for count */
|
|
866
|
+
field?: string;
|
|
867
|
+
}
|
|
868
|
+
/**
|
|
869
|
+
* Options for an aggregation query.
|
|
870
|
+
*/
|
|
871
|
+
interface AggregationOptions {
|
|
872
|
+
groupBy: GroupByField[];
|
|
873
|
+
operations: AggregationOperation[];
|
|
874
|
+
filter?: DocumentFilter;
|
|
875
|
+
limit?: number;
|
|
876
|
+
sort?: {
|
|
877
|
+
/** Can be operation result field like 'count', 'sum_fieldName', etc. */
|
|
878
|
+
field: string;
|
|
879
|
+
/** 1 for ascending, -1 for descending */
|
|
880
|
+
direction: 1 | -1;
|
|
881
|
+
};
|
|
882
|
+
}
|
|
883
|
+
/**
|
|
884
|
+
* Result of an aggregation query — nested object keyed by group values.
|
|
885
|
+
*/
|
|
886
|
+
type AggregationResult = Record<string, any> | Record<string, any>[];
|
|
887
|
+
|
|
888
|
+
/**
|
|
889
|
+
* Hook type definitions for Durable Object access control.
|
|
890
|
+
*
|
|
891
|
+
* Hooks run server-side inside the DO before CRUD operations.
|
|
892
|
+
* They can allow/deny operations and inject query filters.
|
|
893
|
+
*/
|
|
894
|
+
|
|
895
|
+
/** Context passed to all hooks */
|
|
896
|
+
interface HookContext {
|
|
897
|
+
/** The model (type discriminator) being operated on */
|
|
898
|
+
modelName: string;
|
|
899
|
+
/** The document ID (derived from the DO instance) */
|
|
900
|
+
docId: string;
|
|
901
|
+
/** The raw request (for reading headers, auth tokens, etc.) */
|
|
902
|
+
request: Request;
|
|
903
|
+
/** The DO's SQLite engine (for direct queries, e.g. lookup functions) */
|
|
904
|
+
engine: any;
|
|
905
|
+
}
|
|
906
|
+
/** Context for beforeSave hooks */
|
|
907
|
+
interface BeforeSaveContext extends HookContext {
|
|
908
|
+
/** Record ID being saved */
|
|
909
|
+
id: string;
|
|
910
|
+
/** Data being saved */
|
|
911
|
+
data: Record<string, any>;
|
|
912
|
+
/** StringSet values being saved (if any) */
|
|
913
|
+
stringSets?: Record<string, string[]>;
|
|
914
|
+
/** Whether this is a new record (true) or an update (false) */
|
|
915
|
+
isNew: boolean;
|
|
916
|
+
}
|
|
917
|
+
/** Context for beforeDelete hooks */
|
|
918
|
+
interface BeforeDeleteContext extends HookContext {
|
|
919
|
+
/** Record ID being deleted */
|
|
920
|
+
id: string;
|
|
921
|
+
/** The existing record being deleted (parsed from data_json) */
|
|
922
|
+
record: Record<string, any> | null;
|
|
923
|
+
}
|
|
924
|
+
/** Context for beforeQuery hooks */
|
|
925
|
+
interface BeforeQueryContext extends HookContext {
|
|
926
|
+
/** The filter being applied */
|
|
927
|
+
filter: DocumentFilter;
|
|
928
|
+
/** Query options (sort, limit, etc.) */
|
|
929
|
+
options?: QueryOptions;
|
|
930
|
+
}
|
|
931
|
+
/** Context for afterQuery hooks */
|
|
932
|
+
interface AfterQueryContext extends HookContext {
|
|
933
|
+
/** The query results to filter */
|
|
934
|
+
results: Record<string, any>[];
|
|
935
|
+
}
|
|
936
|
+
/** Result from beforeSave/beforeDelete hooks */
|
|
937
|
+
interface HookResult {
|
|
938
|
+
allow: boolean;
|
|
939
|
+
/** Reason for denial (returned to client as error message) */
|
|
940
|
+
reason?: string;
|
|
941
|
+
}
|
|
942
|
+
/** Result from beforeQuery hooks — can inject additional filters */
|
|
943
|
+
interface BeforeQueryResult extends HookResult {
|
|
944
|
+
/** Additional filter merged into the query via $and */
|
|
945
|
+
injectFilter?: DocumentFilter;
|
|
946
|
+
}
|
|
947
|
+
/** Result from afterQuery hooks — returns filtered results */
|
|
948
|
+
interface AfterQueryResult {
|
|
949
|
+
/** The filtered results to return */
|
|
950
|
+
results: Record<string, any>[];
|
|
951
|
+
}
|
|
952
|
+
/** Hook definitions for createDatabaseDO */
|
|
953
|
+
interface DatabaseDOHooks {
|
|
954
|
+
beforeSave?: (ctx: BeforeSaveContext) => Promise<HookResult>;
|
|
955
|
+
beforeDelete?: (ctx: BeforeDeleteContext) => Promise<HookResult>;
|
|
956
|
+
beforeQuery?: (ctx: BeforeQueryContext) => Promise<BeforeQueryResult>;
|
|
957
|
+
afterQuery?: (ctx: AfterQueryContext) => Promise<AfterQueryResult>;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
/**
|
|
961
|
+
* Database Durable Object Factory
|
|
962
|
+
*
|
|
963
|
+
* Creates a Durable Object class that serves as a schemaless database store.
|
|
964
|
+
* Each DO instance has its own SQLite database.
|
|
965
|
+
*
|
|
966
|
+
* Usage:
|
|
967
|
+
* ```typescript
|
|
968
|
+
* import { createDatabaseDO } from 'js-bao/cloudflare/do';
|
|
969
|
+
*
|
|
970
|
+
* export const MyDatabaseDO = createDatabaseDO({
|
|
971
|
+
* hooks: {
|
|
972
|
+
* beforeSave: async (ctx) => {
|
|
973
|
+
* // Access control logic
|
|
974
|
+
* return { allow: true };
|
|
975
|
+
* },
|
|
976
|
+
* },
|
|
977
|
+
* });
|
|
978
|
+
* ```
|
|
979
|
+
*/
|
|
980
|
+
|
|
981
|
+
interface DatabaseDOConfig {
|
|
982
|
+
/**
|
|
983
|
+
* Hooks for access control. All hooks are async.
|
|
984
|
+
*/
|
|
985
|
+
hooks?: DatabaseDOHooks;
|
|
986
|
+
}
|
|
987
|
+
/**
|
|
988
|
+
* @deprecated Use DatabaseDOConfig instead
|
|
989
|
+
*/
|
|
990
|
+
type DocumentDOConfig = DatabaseDOConfig;
|
|
991
|
+
/**
|
|
992
|
+
* Request body types for RPC endpoints
|
|
993
|
+
*/
|
|
994
|
+
interface QueryRequest {
|
|
995
|
+
modelName: string;
|
|
996
|
+
filter: DocumentFilter;
|
|
997
|
+
options?: QueryOptions;
|
|
998
|
+
}
|
|
999
|
+
interface SaveRequest {
|
|
1000
|
+
modelName: string;
|
|
1001
|
+
id: string;
|
|
1002
|
+
data: Record<string, any>;
|
|
1003
|
+
stringSets?: Record<string, string[]>;
|
|
1004
|
+
ifNotExists?: boolean;
|
|
1005
|
+
condition?: DocumentFilter;
|
|
1006
|
+
}
|
|
1007
|
+
interface DeleteRequest {
|
|
1008
|
+
modelName: string;
|
|
1009
|
+
id: string;
|
|
1010
|
+
condition?: DocumentFilter;
|
|
1011
|
+
}
|
|
1012
|
+
interface CountRequest {
|
|
1013
|
+
modelName: string;
|
|
1014
|
+
filter: DocumentFilter;
|
|
1015
|
+
}
|
|
1016
|
+
interface RegisterIndexRequest {
|
|
1017
|
+
modelName: string;
|
|
1018
|
+
fieldName: string;
|
|
1019
|
+
fieldType: string;
|
|
1020
|
+
unique?: boolean;
|
|
1021
|
+
}
|
|
1022
|
+
interface DropIndexRequest {
|
|
1023
|
+
modelName: string;
|
|
1024
|
+
fieldName: string;
|
|
1025
|
+
}
|
|
1026
|
+
interface RegisterUniqueConstraintRequest {
|
|
1027
|
+
modelName: string;
|
|
1028
|
+
constraintName: string;
|
|
1029
|
+
fields: string[];
|
|
1030
|
+
}
|
|
1031
|
+
interface DropUniqueConstraintRequest {
|
|
1032
|
+
modelName: string;
|
|
1033
|
+
constraintName: string;
|
|
1034
|
+
}
|
|
1035
|
+
/**
|
|
1036
|
+
* Response types
|
|
1037
|
+
*/
|
|
1038
|
+
interface QueryResponse {
|
|
1039
|
+
data: Record<string, any>[];
|
|
1040
|
+
hasMore?: boolean;
|
|
1041
|
+
nextCursor?: string;
|
|
1042
|
+
prevCursor?: string;
|
|
1043
|
+
}
|
|
1044
|
+
interface SaveResponse {
|
|
1045
|
+
success: boolean;
|
|
1046
|
+
id: string;
|
|
1047
|
+
}
|
|
1048
|
+
interface DeleteResponse {
|
|
1049
|
+
success: boolean;
|
|
1050
|
+
}
|
|
1051
|
+
interface CountResponse {
|
|
1052
|
+
count: number;
|
|
1053
|
+
}
|
|
1054
|
+
interface ErrorResponse {
|
|
1055
|
+
error: string;
|
|
1056
|
+
code?: string;
|
|
1057
|
+
}
|
|
1058
|
+
interface RegisterIndexResponse {
|
|
1059
|
+
success: boolean;
|
|
1060
|
+
modelName: string;
|
|
1061
|
+
fieldName: string;
|
|
1062
|
+
}
|
|
1063
|
+
interface DropIndexResponse {
|
|
1064
|
+
success: boolean;
|
|
1065
|
+
modelName: string;
|
|
1066
|
+
fieldName: string;
|
|
1067
|
+
}
|
|
1068
|
+
interface IndexListResponse {
|
|
1069
|
+
indexes: IndexEntry[];
|
|
1070
|
+
}
|
|
1071
|
+
interface RegisterUniqueConstraintResponse {
|
|
1072
|
+
success: boolean;
|
|
1073
|
+
modelName: string;
|
|
1074
|
+
constraintName: string;
|
|
1075
|
+
}
|
|
1076
|
+
interface DropUniqueConstraintResponse {
|
|
1077
|
+
success: boolean;
|
|
1078
|
+
modelName: string;
|
|
1079
|
+
constraintName: string;
|
|
1080
|
+
}
|
|
1081
|
+
interface UniqueConstraintListResponse {
|
|
1082
|
+
constraints: UniqueConstraintEntry[];
|
|
1083
|
+
}
|
|
1084
|
+
interface AggregateRequest {
|
|
1085
|
+
modelName: string;
|
|
1086
|
+
options: AggregationOptions;
|
|
1087
|
+
}
|
|
1088
|
+
interface AggregateResponse {
|
|
1089
|
+
result: AggregationResult;
|
|
1090
|
+
}
|
|
1091
|
+
interface SyncIndexesRequest {
|
|
1092
|
+
models: Array<{
|
|
1093
|
+
modelName: string;
|
|
1094
|
+
indexes: Array<{
|
|
1095
|
+
fieldName: string;
|
|
1096
|
+
fieldType: string;
|
|
1097
|
+
unique: boolean;
|
|
1098
|
+
}>;
|
|
1099
|
+
uniqueConstraints: Array<{
|
|
1100
|
+
name: string;
|
|
1101
|
+
fields: string[];
|
|
1102
|
+
}>;
|
|
1103
|
+
}>;
|
|
1104
|
+
}
|
|
1105
|
+
interface SyncIndexesResponse {
|
|
1106
|
+
registered: number;
|
|
1107
|
+
}
|
|
1108
|
+
interface PatchRequest {
|
|
1109
|
+
modelName: string;
|
|
1110
|
+
id: string;
|
|
1111
|
+
data: Record<string, any>;
|
|
1112
|
+
stringSets?: Record<string, string[]>;
|
|
1113
|
+
condition?: DocumentFilter;
|
|
1114
|
+
}
|
|
1115
|
+
interface PatchResponse {
|
|
1116
|
+
success: boolean;
|
|
1117
|
+
id: string;
|
|
1118
|
+
}
|
|
1119
|
+
interface BatchOperation {
|
|
1120
|
+
op: "save" | "patch" | "delete" | "increment" | "addToSet" | "removeFromSet";
|
|
1121
|
+
modelName: string;
|
|
1122
|
+
id: string;
|
|
1123
|
+
data?: Record<string, any>;
|
|
1124
|
+
stringSets?: Record<string, string[]>;
|
|
1125
|
+
fields?: Record<string, number>;
|
|
1126
|
+
ifNotExists?: boolean;
|
|
1127
|
+
condition?: DocumentFilter;
|
|
1128
|
+
}
|
|
1129
|
+
interface BatchRequest {
|
|
1130
|
+
operations: BatchOperation[];
|
|
1131
|
+
}
|
|
1132
|
+
interface BatchOperationResult {
|
|
1133
|
+
success: boolean;
|
|
1134
|
+
id: string;
|
|
1135
|
+
error?: string;
|
|
1136
|
+
values?: Record<string, number>;
|
|
1137
|
+
}
|
|
1138
|
+
interface BatchResponse {
|
|
1139
|
+
results: BatchOperationResult[];
|
|
1140
|
+
}
|
|
1141
|
+
interface IncrementRequest {
|
|
1142
|
+
modelName: string;
|
|
1143
|
+
id: string;
|
|
1144
|
+
fields: Record<string, number>;
|
|
1145
|
+
condition?: DocumentFilter;
|
|
1146
|
+
}
|
|
1147
|
+
interface IncrementResponse {
|
|
1148
|
+
success: boolean;
|
|
1149
|
+
id: string;
|
|
1150
|
+
values: Record<string, number>;
|
|
1151
|
+
}
|
|
1152
|
+
interface StringSetUpdateRequest {
|
|
1153
|
+
modelName: string;
|
|
1154
|
+
id: string;
|
|
1155
|
+
sets: Record<string, string[]>;
|
|
1156
|
+
condition?: DocumentFilter;
|
|
1157
|
+
}
|
|
1158
|
+
interface StringSetUpdateResponse {
|
|
1159
|
+
success: boolean;
|
|
1160
|
+
}
|
|
1161
|
+
/**
|
|
1162
|
+
* Create a Durable Object class for schemaless database storage.
|
|
1163
|
+
*
|
|
1164
|
+
* The returned class can be exported and used in wrangler.toml:
|
|
1165
|
+
* ```toml
|
|
1166
|
+
* [durable_objects]
|
|
1167
|
+
* bindings = [
|
|
1168
|
+
* { name = "DATABASE_DO", class_name = "MyDatabaseDO" }
|
|
1169
|
+
* ]
|
|
1170
|
+
* ```
|
|
1171
|
+
*/
|
|
1172
|
+
declare function createDatabaseDO(config?: DatabaseDOConfig): {
|
|
1173
|
+
new (state: DurableObjectState, _env: unknown): {
|
|
1174
|
+
/** @internal */
|
|
1175
|
+
_doState: DurableObjectState;
|
|
1176
|
+
/** @internal */
|
|
1177
|
+
_engine: DurableObjectEngine;
|
|
1178
|
+
/** @internal */
|
|
1179
|
+
_initialized: boolean;
|
|
1180
|
+
/** @internal — cache for $contains misuse check: "model:field" keys known to be in data_json */
|
|
1181
|
+
_containsMisuseCache: Set<string>;
|
|
1182
|
+
get state(): DurableObjectState;
|
|
1183
|
+
get engine(): DurableObjectEngine;
|
|
1184
|
+
/** @internal */
|
|
1185
|
+
_ensureInitialized(): Promise<void>;
|
|
1186
|
+
fetch(request: Request): Promise<Response>;
|
|
1187
|
+
/** @internal */
|
|
1188
|
+
_handleQuery(request: Request, docId: string): Promise<Response>;
|
|
1189
|
+
/** @internal — Check for reserved field names in record data */
|
|
1190
|
+
_checkReservedFields(data: Record<string, any>): string | null;
|
|
1191
|
+
/** @internal */
|
|
1192
|
+
_handleSave(request: Request, docId: string): Promise<Response>;
|
|
1193
|
+
/** @internal — Partial update: merge provided fields into existing record */
|
|
1194
|
+
_handlePatch(request: Request, docId: string): Promise<Response>;
|
|
1195
|
+
/** @internal */
|
|
1196
|
+
_handleDelete(request: Request, docId: string): Promise<Response>;
|
|
1197
|
+
/** @internal — Execute multiple save/patch/delete operations in a single transaction */
|
|
1198
|
+
_handleBatch(request: Request, docId: string): Promise<Response>;
|
|
1199
|
+
/** @internal */
|
|
1200
|
+
_handleCount(request: Request, docId: string): Promise<Response>;
|
|
1201
|
+
/** @internal — Atomically increment/decrement numeric fields */
|
|
1202
|
+
_handleIncrement(request: Request, _docId: string): Promise<Response>;
|
|
1203
|
+
/** @internal — Atomically add values to StringSet fields */
|
|
1204
|
+
_handleStringSetAdd(request: Request, _docId: string): Promise<Response>;
|
|
1205
|
+
/** @internal — Atomically remove values from StringSet fields */
|
|
1206
|
+
_handleStringSetRemove(request: Request, _docId: string): Promise<Response>;
|
|
1207
|
+
_handleAggregate(request: Request, docId: string): Promise<Response>;
|
|
1208
|
+
/** @internal — Build SQL for StringSet facet aggregation */
|
|
1209
|
+
_buildStringSetFacetSql(modelName: string, facetField: string, aggOptions: AggregationOptions, filter: DocumentFilter, translator: JsonQueryTranslator): {
|
|
1210
|
+
sql: string;
|
|
1211
|
+
params: any[];
|
|
1212
|
+
};
|
|
1213
|
+
/** @internal — Build SQL for regular field aggregation */
|
|
1214
|
+
_buildRegularAggregationSql(modelName: string, regularGroupBy: string[], stringSetMemberships: Array<{
|
|
1215
|
+
field: string;
|
|
1216
|
+
contains: string;
|
|
1217
|
+
}>, aggOptions: AggregationOptions, filter: DocumentFilter, translator: JsonQueryTranslator): {
|
|
1218
|
+
sql: string;
|
|
1219
|
+
params: any[];
|
|
1220
|
+
aliasMap: Array<{
|
|
1221
|
+
alias: string;
|
|
1222
|
+
field: string;
|
|
1223
|
+
contains: string;
|
|
1224
|
+
}>;
|
|
1225
|
+
};
|
|
1226
|
+
/** @internal — Extract operation value(s) from a row. Flattens single-op results. */
|
|
1227
|
+
_extractOpValue(row: any, operations: AggregationOptions["operations"]): any;
|
|
1228
|
+
/** @internal — Process raw aggregation rows into nested result */
|
|
1229
|
+
_processAggregationResults(results: any[], aggOptions: AggregationOptions, aliasMap: Array<{
|
|
1230
|
+
alias: string;
|
|
1231
|
+
field: string;
|
|
1232
|
+
contains: string;
|
|
1233
|
+
}>, stringSetFacetField: string | null): AggregationResult;
|
|
1234
|
+
/** @internal */
|
|
1235
|
+
/** @internal — Batch sync: compare desired indexes against _indexes table, register missing */
|
|
1236
|
+
_handleIndexesSync(request: Request): Promise<Response>;
|
|
1237
|
+
/** @internal */
|
|
1238
|
+
_handleIndexRegister(request: Request): Promise<Response>;
|
|
1239
|
+
/** @internal */
|
|
1240
|
+
_handleIndexDrop(request: Request): Promise<Response>;
|
|
1241
|
+
/** @internal */
|
|
1242
|
+
_handleIndexList(request: Request): Response;
|
|
1243
|
+
/** @internal */
|
|
1244
|
+
_handleUniqueConstraintRegister(request: Request): Promise<Response>;
|
|
1245
|
+
/** @internal */
|
|
1246
|
+
_handleUniqueConstraintDrop(request: Request): Promise<Response>;
|
|
1247
|
+
/** @internal */
|
|
1248
|
+
_handleUniqueConstraintList(request: Request): Response;
|
|
1249
|
+
/** @internal */
|
|
1250
|
+
/**
|
|
1251
|
+
* Extract field names that use $contains from a filter tree.
|
|
1252
|
+
* @internal
|
|
1253
|
+
*/
|
|
1254
|
+
_findContainsFields(filter: DocumentFilter): string[];
|
|
1255
|
+
/**
|
|
1256
|
+
* Check for $contains misuse with caching.
|
|
1257
|
+
* Returns an error Response if misuse is detected, or null if OK.
|
|
1258
|
+
* @internal
|
|
1259
|
+
*/
|
|
1260
|
+
_checkContainsMisuse(modelName: string, filter: DocumentFilter): Response | null;
|
|
1261
|
+
/**
|
|
1262
|
+
* Check a write condition against the current state of a record.
|
|
1263
|
+
* Returns true if the condition is met (record exists and matches the filter).
|
|
1264
|
+
* Returns false if the record doesn't exist or doesn't match.
|
|
1265
|
+
* @internal
|
|
1266
|
+
*/
|
|
1267
|
+
_checkCondition(modelName: string, id: string, condition: DocumentFilter): boolean;
|
|
1268
|
+
_handleHealth(): Response;
|
|
1269
|
+
/** @internal — Return tracked field names and types for a model */
|
|
1270
|
+
_handleDescribe(request: Request): Response;
|
|
1271
|
+
/** @internal — List all known model names from records and _model_fields */
|
|
1272
|
+
_handleModelList(): Response;
|
|
1273
|
+
/** @internal */
|
|
1274
|
+
_errorResponse(message: string, status: number): Response;
|
|
1275
|
+
/** @internal */
|
|
1276
|
+
_parseRow(row: Record<string, any>): Record<string, any>;
|
|
1277
|
+
/** @internal — Validate an IncludeSpec, returning an error message or null */
|
|
1278
|
+
_validateIncludeSpec(spec: IncludeSpec): string | null;
|
|
1279
|
+
/** @internal — Resolve all includes for a set of records */
|
|
1280
|
+
_resolveIncludes(records: Record<string, any>[], includes: IncludeSpec[], depth: number, _parentModelName?: string): Record<string, any>[];
|
|
1281
|
+
/** @internal — Resolve a refersTo include (parent FK → single related record) */
|
|
1282
|
+
_resolveRefersTo(records: Record<string, any>[], spec: IncludeSpec, resultKey: string): void;
|
|
1283
|
+
/** @internal — Resolve a refersToMany include (parent StringSet field → array of related records) */
|
|
1284
|
+
_resolveRefersToMany(records: Record<string, any>[], spec: IncludeSpec, resultKey: string): void;
|
|
1285
|
+
/** @internal — Resolve a hasMany include (target FK → array of related records) */
|
|
1286
|
+
_resolveHasMany(records: Record<string, any>[], spec: IncludeSpec, resultKey: string): void;
|
|
1287
|
+
/** @internal — Simple hasMany without per-parent limit */
|
|
1288
|
+
_resolveHasManySimple(spec: IncludeSpec, parentValues: any[]): Record<string, any>[];
|
|
1289
|
+
/** @internal — hasMany with per-parent limit using ROW_NUMBER() */
|
|
1290
|
+
_resolveHasManyWithLimit(spec: IncludeSpec, parentValues: any[]): Record<string, any>[];
|
|
1291
|
+
/**
|
|
1292
|
+
* @internal — Execute IN queries in chunks to stay under Cloudflare DO's
|
|
1293
|
+
* 100 bound parameter limit per SQL statement.
|
|
1294
|
+
*/
|
|
1295
|
+
_chunkedIn(model: string, field: string, values: any[], extraFilter?: DocumentFilter, extraOptions?: {
|
|
1296
|
+
sort?: SortSpec;
|
|
1297
|
+
projection?: ProjectionSpec;
|
|
1298
|
+
}): Record<string, any>[];
|
|
1299
|
+
/** @internal — Apply projection to a single record */
|
|
1300
|
+
_applyProjection(record: Record<string, any>, projection: ProjectionSpec): Record<string, any>;
|
|
1301
|
+
};
|
|
1302
|
+
};
|
|
1303
|
+
/**
|
|
1304
|
+
* @deprecated Use createDatabaseDO instead
|
|
1305
|
+
*/
|
|
1306
|
+
declare const createDocumentDO: typeof createDatabaseDO;
|
|
1307
|
+
|
|
1308
|
+
/**
|
|
1309
|
+
* Cloudflare Worker Router Template
|
|
1310
|
+
*
|
|
1311
|
+
* This file provides a template for routing requests to Document Durable Objects.
|
|
1312
|
+
* Copy and customize this for your worker implementation.
|
|
1313
|
+
*
|
|
1314
|
+
* Usage:
|
|
1315
|
+
* 1. Copy this file to your worker project
|
|
1316
|
+
* 2. Import your models and create the DO class
|
|
1317
|
+
* 3. Configure wrangler.toml with the DO binding
|
|
1318
|
+
* 4. Deploy with `wrangler deploy`
|
|
1319
|
+
*
|
|
1320
|
+
* Example wrangler.toml:
|
|
1321
|
+
* ```toml
|
|
1322
|
+
* name = "my-worker"
|
|
1323
|
+
* main = "src/index.ts"
|
|
1324
|
+
* compatibility_date = "2024-01-01"
|
|
1325
|
+
*
|
|
1326
|
+
* [[durable_objects.bindings]]
|
|
1327
|
+
* name = "DOCUMENT_DO"
|
|
1328
|
+
* class_name = "DocumentDO"
|
|
1329
|
+
*
|
|
1330
|
+
* [[migrations]]
|
|
1331
|
+
* tag = "v1"
|
|
1332
|
+
* new_sqlite_classes = ["DocumentDO"]
|
|
1333
|
+
* ```
|
|
1334
|
+
*/
|
|
1335
|
+
|
|
1336
|
+
/**
|
|
1337
|
+
* Environment interface - customize for your worker
|
|
1338
|
+
*/
|
|
1339
|
+
interface Env {
|
|
1340
|
+
/**
|
|
1341
|
+
* The Durable Object namespace binding
|
|
1342
|
+
*/
|
|
1343
|
+
DOCUMENT_DO: DurableObjectNamespace;
|
|
1344
|
+
}
|
|
1345
|
+
/**
|
|
1346
|
+
* Create the worker export
|
|
1347
|
+
*
|
|
1348
|
+
* Example usage in your worker:
|
|
1349
|
+
* ```typescript
|
|
1350
|
+
* import { createDocumentDO } from 'js-bao/cloudflare/do';
|
|
1351
|
+
* import { Statement } from './models';
|
|
1352
|
+
*
|
|
1353
|
+
* // Create the DO class
|
|
1354
|
+
* export const DocumentDO = createDocumentDO({ models: [Statement] });
|
|
1355
|
+
*
|
|
1356
|
+
* // Export the worker
|
|
1357
|
+
* export default {
|
|
1358
|
+
* async fetch(request: Request, env: Env): Promise<Response> {
|
|
1359
|
+
* return handleRequest(request, env);
|
|
1360
|
+
* }
|
|
1361
|
+
* };
|
|
1362
|
+
* ```
|
|
1363
|
+
*/
|
|
1364
|
+
declare function handleRequest(request: Request, env: Env): Promise<Response>;
|
|
1365
|
+
|
|
1366
|
+
export { type AfterQueryContext, type AfterQueryResult, type AggregateRequest, type AggregateResponse, type AggregationOperation, type AggregationOptions, type AggregationResult, type BatchOperation, type BatchOperationResult, type BatchRequest, type BatchResponse, type BeforeDeleteContext, type BeforeQueryContext, type BeforeQueryResult, type BeforeSaveContext, type CountRequest, type CountResponse, type DatabaseDOConfig, type DatabaseDOHooks, type DeleteRequest, type DeleteResponse, type DocumentDOConfig, type DropIndexRequest, type DropIndexResponse, type DropUniqueConstraintRequest, type DropUniqueConstraintResponse, DurableObjectEngine, type DurableObjectEngineOptions, type DurableObjectId, type DurableObjectNamespace, type DurableObjectState, type DurableObjectStorage, type DurableObjectStub, type Env, type ErrorResponse, type GroupByField, type HookContext, type HookResult, type IncrementRequest, type IncrementResponse, type IndexEntry, type IndexListResponse, JsonQueryTranslator, type JsonQueryTranslatorOptions, JsonSchemaDDL, type JsonSchemaOptions, type PatchRequest, type PatchResponse, type QueryRequest, type QueryResponse, type RegisterIndexRequest, type RegisterIndexResponse, type RegisterUniqueConstraintRequest, type RegisterUniqueConstraintResponse, type SaveRequest, type SaveResponse, type SqlStorage, type SqlStorageCursor, type StringSetMembership, type StringSetUpdateRequest, type StringSetUpdateResponse, type SyncIndexesRequest, type SyncIndexesResponse, type UniqueConstraintEntry, type UniqueConstraintListResponse, createDatabaseDO, createDocumentDO, handleRequest };
|