@happyvertical/sql 0.74.8
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/AGENT.md +33 -0
- package/LICENSE +7 -0
- package/README.md +287 -0
- package/dist/backup/index.d.ts +119 -0
- package/dist/backup/index.d.ts.map +1 -0
- package/dist/backup/index.js +212 -0
- package/dist/backup/index.js.map +1 -0
- package/dist/backup/manifest.d.ts +51 -0
- package/dist/backup/manifest.d.ts.map +1 -0
- package/dist/chunks/duckdb-Djx8WKZE.js +924 -0
- package/dist/chunks/duckdb-Djx8WKZE.js.map +1 -0
- package/dist/chunks/index-DL-5nB7l.js +3468 -0
- package/dist/chunks/index-DL-5nB7l.js.map +1 -0
- package/dist/chunks/postgres-cli-Cr6bBZ3q.js +209 -0
- package/dist/chunks/postgres-cli-Cr6bBZ3q.js.map +1 -0
- package/dist/chunks/sqlite-DkCGjXmu.js +937 -0
- package/dist/chunks/sqlite-DkCGjXmu.js.map +1 -0
- package/dist/chunks/sqlite-native-B6q-0nLs.js +1129 -0
- package/dist/chunks/sqlite-native-B6q-0nLs.js.map +1 -0
- package/dist/cli/claude-context.d.ts +3 -0
- package/dist/cli/claude-context.d.ts.map +1 -0
- package/dist/cli/claude-context.js +21 -0
- package/dist/cli/claude-context.js.map +1 -0
- package/dist/doctor.d.ts +69 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/duckdb.d.ts +9 -0
- package/dist/duckdb.d.ts.map +1 -0
- package/dist/index.d.ts +109 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/json.d.ts +30 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/postgres-cli.d.ts +135 -0
- package/dist/postgres-cli.d.ts.map +1 -0
- package/dist/postgres.d.ts +77 -0
- package/dist/postgres.d.ts.map +1 -0
- package/dist/schema-manager.d.ts +86 -0
- package/dist/schema-manager.d.ts.map +1 -0
- package/dist/shared/alter-utils.d.ts +83 -0
- package/dist/shared/alter-utils.d.ts.map +1 -0
- package/dist/shared/duckdb-schema-utils.d.ts +86 -0
- package/dist/shared/duckdb-schema-utils.d.ts.map +1 -0
- package/dist/shared/types.d.ts +1016 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/utils.d.ts +104 -0
- package/dist/shared/utils.d.ts.map +1 -0
- package/dist/sqlite-native.d.ts +4 -0
- package/dist/sqlite-native.d.ts.map +1 -0
- package/dist/sqlite.d.ts +54 -0
- package/dist/sqlite.d.ts.map +1 -0
- package/metadata.json +38 -0
- package/package.json +84 -0
|
@@ -0,0 +1,1016 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WHERE clause input for database queries
|
|
3
|
+
*
|
|
4
|
+
* Supports two formats:
|
|
5
|
+
* 1. Object format (AND-only): `{ status: 'active', 'price >': 100 }`
|
|
6
|
+
* - All conditions are AND-joined
|
|
7
|
+
*
|
|
8
|
+
* 2. 2D array format (OR/AND compound logic): `[[cond1, cond2], [cond3, cond4]]`
|
|
9
|
+
* - Inner arrays are AND-joined: `(cond1 AND cond2)`
|
|
10
|
+
* - Outer array is OR-joined: `(cond1 AND cond2) OR (cond3 AND cond4)`
|
|
11
|
+
*
|
|
12
|
+
* @example Object format (backward compatible)
|
|
13
|
+
* ```typescript
|
|
14
|
+
* // WHERE status = 'active' AND price > 100
|
|
15
|
+
* const where = { status: 'active', 'price >': 100 };
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @example 2D array format for OR/AND compound logic
|
|
19
|
+
* ```typescript
|
|
20
|
+
* // WHERE (status = 'active' AND price > 100) OR (status = 'pending' AND priority = 'high')
|
|
21
|
+
* const where = [
|
|
22
|
+
* [{ status: 'active' }, { 'price >': 100 }],
|
|
23
|
+
* [{ status: 'pending' }, { priority: 'high' }]
|
|
24
|
+
* ];
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export type WhereClause = Record<string, any> | Record<string, any>[][];
|
|
28
|
+
/**
|
|
29
|
+
* Common database connection options
|
|
30
|
+
*/
|
|
31
|
+
export interface DatabaseOptions {
|
|
32
|
+
/**
|
|
33
|
+
* Database connection URL
|
|
34
|
+
*/
|
|
35
|
+
url?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Authentication token for the database connection
|
|
38
|
+
*/
|
|
39
|
+
authToken?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* DuckDB-specific connection options
|
|
43
|
+
*/
|
|
44
|
+
export interface DuckDBOptions extends DatabaseOptions {
|
|
45
|
+
/**
|
|
46
|
+
* Database type identifier
|
|
47
|
+
*/
|
|
48
|
+
type?: 'duckdb';
|
|
49
|
+
/**
|
|
50
|
+
* Path to directory containing JSON files to auto-register as tables
|
|
51
|
+
* @default './data'
|
|
52
|
+
*/
|
|
53
|
+
dataDir?: string;
|
|
54
|
+
/**
|
|
55
|
+
* Automatically register JSON files in dataDir as queryable tables
|
|
56
|
+
* @default true
|
|
57
|
+
*/
|
|
58
|
+
autoRegisterJSON?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Strategy for writing data back to JSON files
|
|
61
|
+
* - 'immediate': Write changes to JSON files immediately
|
|
62
|
+
* - 'manual': Require explicit export calls
|
|
63
|
+
* - 'none': Read-only mode, no writes to JSON files
|
|
64
|
+
* @default 'none'
|
|
65
|
+
*/
|
|
66
|
+
writeStrategy?: 'immediate' | 'manual' | 'none';
|
|
67
|
+
/**
|
|
68
|
+
* Whether to use a persistent DuckDB file for caching/indexes
|
|
69
|
+
* If true, uses url or defaults to ':memory:'
|
|
70
|
+
* @default false
|
|
71
|
+
*/
|
|
72
|
+
persistent?: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Explicit schema definitions for tables
|
|
75
|
+
* When provided, these schemas will be used for table creation
|
|
76
|
+
*/
|
|
77
|
+
schemas?: SchemasOption;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* JSON database adapter options (DuckDB-backed)
|
|
81
|
+
*
|
|
82
|
+
* Uses DuckDB's in-memory engine to query JSON files directly.
|
|
83
|
+
* No WAL files or persistent database files are created.
|
|
84
|
+
*/
|
|
85
|
+
export interface JSONOptions {
|
|
86
|
+
/**
|
|
87
|
+
* Database type identifier
|
|
88
|
+
*/
|
|
89
|
+
type: 'json';
|
|
90
|
+
/**
|
|
91
|
+
* Path to directory containing JSON files (required)
|
|
92
|
+
* JSON files in this directory will be loaded as queryable tables
|
|
93
|
+
*/
|
|
94
|
+
url: string;
|
|
95
|
+
/**
|
|
96
|
+
* Automatically load all JSON files in dataDir as tables
|
|
97
|
+
* @default true
|
|
98
|
+
*/
|
|
99
|
+
autoRegister?: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Strategy for writing changes back to JSON files
|
|
102
|
+
* - 'immediate': Auto-save after every insert/update (default)
|
|
103
|
+
* - 'manual': Require explicit exportTable() calls
|
|
104
|
+
* - 'none': Read-only mode, throws error on writes
|
|
105
|
+
* @default 'immediate'
|
|
106
|
+
*/
|
|
107
|
+
writeStrategy?: 'immediate' | 'manual' | 'none';
|
|
108
|
+
/**
|
|
109
|
+
* Explicit schema definitions for tables
|
|
110
|
+
*
|
|
111
|
+
* When provided, these schemas will be used instead of auto-detection.
|
|
112
|
+
* This allows frameworks to provide explicit schemas via dependency injection.
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```typescript
|
|
116
|
+
* const db = await getDatabase({
|
|
117
|
+
* type: 'json',
|
|
118
|
+
* url: './data',
|
|
119
|
+
* schemas: {
|
|
120
|
+
* users: {
|
|
121
|
+
* tableName: 'users',
|
|
122
|
+
* ddl: 'CREATE TABLE users (id TEXT PRIMARY KEY, name TEXT)',
|
|
123
|
+
* indexes: ['CREATE INDEX idx_users_name ON users(name)']
|
|
124
|
+
* }
|
|
125
|
+
* }
|
|
126
|
+
* });
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
schemas?: SchemasOption;
|
|
130
|
+
/**
|
|
131
|
+
* Unique identifier for in-memory DuckDB instances to enable connection sharing
|
|
132
|
+
* When multiple getDatabase() calls use the same dbid, they receive
|
|
133
|
+
* the same database connection instance.
|
|
134
|
+
*
|
|
135
|
+
* Auto-generated if not provided, enabling connection sharing by default.
|
|
136
|
+
* This solves the issue where multiple collections create separate in-memory
|
|
137
|
+
* databases that can't see each other's tables.
|
|
138
|
+
*/
|
|
139
|
+
dbid?: string;
|
|
140
|
+
/**
|
|
141
|
+
* Eagerly load all JSON files as tables at connection time
|
|
142
|
+
*
|
|
143
|
+
* When true (default), creates tables with inferred schemas for all JSON files
|
|
144
|
+
* in the data directory, even those without explicit schemas or .schema.sql files.
|
|
145
|
+
* This enables cross-table queries (JOINs, NOT EXISTS subqueries) before
|
|
146
|
+
* syncSchema() is called.
|
|
147
|
+
*
|
|
148
|
+
* Note: Inferred schemas don't include UNIQUE constraints. UPSERT operations
|
|
149
|
+
* require syncSchema() to be called first to establish proper constraints.
|
|
150
|
+
* When syncSchema() is called, tables with inferred schemas are dropped and
|
|
151
|
+
* recreated with the proper schema.
|
|
152
|
+
*
|
|
153
|
+
* @default true
|
|
154
|
+
*/
|
|
155
|
+
eagerLoadTables?: boolean;
|
|
156
|
+
/**
|
|
157
|
+
* Force a fresh database connection, bypassing the connection cache
|
|
158
|
+
*
|
|
159
|
+
* When true, clears any cached connection for this URL before creating a new one.
|
|
160
|
+
* Useful when you need to reload the database from disk after external changes.
|
|
161
|
+
*
|
|
162
|
+
* @default false
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* // Initial connection - cached
|
|
166
|
+
* const db1 = await getDatabase({ type: 'json', url: './data' });
|
|
167
|
+
*
|
|
168
|
+
* // External process adds JSON files...
|
|
169
|
+
*
|
|
170
|
+
* // Force reload from disk
|
|
171
|
+
* const db2 = await getDatabase({
|
|
172
|
+
* type: 'json',
|
|
173
|
+
* url: './data',
|
|
174
|
+
* clearCache: true
|
|
175
|
+
* });
|
|
176
|
+
*/
|
|
177
|
+
clearCache?: boolean;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Result of a database operation that modifies data
|
|
181
|
+
*/
|
|
182
|
+
export interface QueryResult {
|
|
183
|
+
/**
|
|
184
|
+
* Type of operation performed (e.g., "insert", "update", "delete")
|
|
185
|
+
*/
|
|
186
|
+
operation: string;
|
|
187
|
+
/**
|
|
188
|
+
* Number of rows affected by the operation
|
|
189
|
+
*/
|
|
190
|
+
affected: number;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Options for upsert operations.
|
|
194
|
+
*/
|
|
195
|
+
export interface UpsertOptions {
|
|
196
|
+
/**
|
|
197
|
+
* Preserve database-native NULL-distinct conflict behavior.
|
|
198
|
+
*
|
|
199
|
+
* By default, upsert treats NULL values in conflict columns as matching
|
|
200
|
+
* existing NULL values. Set this to true to opt out and use the underlying
|
|
201
|
+
* database's native ON CONFLICT behavior where NULLs are distinct.
|
|
202
|
+
*/
|
|
203
|
+
nullsDistinct?: boolean;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Schema definition that can be provided to database adapters
|
|
207
|
+
*
|
|
208
|
+
* Allows frameworks like SMRT to provide explicit schemas instead of
|
|
209
|
+
* relying on auto-detection or circular dependencies.
|
|
210
|
+
*
|
|
211
|
+
* This is a simpler, DDL-based alternative to SchemaDefinition which is
|
|
212
|
+
* used for structured JSON manifests.
|
|
213
|
+
*/
|
|
214
|
+
export interface SchemaProvider {
|
|
215
|
+
/**
|
|
216
|
+
* Table name in snake_case plural form
|
|
217
|
+
*/
|
|
218
|
+
tableName: string;
|
|
219
|
+
/**
|
|
220
|
+
* DDL statement(s) to create the table
|
|
221
|
+
* Can be a single CREATE TABLE statement or multiple statements
|
|
222
|
+
*/
|
|
223
|
+
ddl: string;
|
|
224
|
+
/**
|
|
225
|
+
* Index creation statements (optional)
|
|
226
|
+
* Each string should be a complete CREATE INDEX statement
|
|
227
|
+
*/
|
|
228
|
+
indexes?: string[];
|
|
229
|
+
/**
|
|
230
|
+
* Trigger creation statements (optional, adapter-specific support)
|
|
231
|
+
* Each string should be a complete CREATE TRIGGER statement
|
|
232
|
+
*/
|
|
233
|
+
triggers?: string[];
|
|
234
|
+
/**
|
|
235
|
+
* Schema version for migration tracking (optional)
|
|
236
|
+
*/
|
|
237
|
+
version?: string;
|
|
238
|
+
/**
|
|
239
|
+
* Field metadata (optional, for advanced use cases)
|
|
240
|
+
* Can be used by frameworks for runtime type information and validation
|
|
241
|
+
*/
|
|
242
|
+
fields?: Map<string, any>;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Schema definitions for getDatabase(), either eagerly built or lazy.
|
|
246
|
+
*
|
|
247
|
+
* Callers can pass schemas as a lazy function so that building the schema
|
|
248
|
+
* map (potentially 200+ objects from ObjectRegistry) is deferred until an
|
|
249
|
+
* adapter actually needs it. Adapters that manage tables via migrations
|
|
250
|
+
* (Postgres, SQLite) never call the function, making the cost zero.
|
|
251
|
+
*
|
|
252
|
+
* @example Lazy — only resolved by JSON/DuckDB adapters
|
|
253
|
+
* ```typescript
|
|
254
|
+
* await getDatabase({
|
|
255
|
+
* type: 'postgres',
|
|
256
|
+
* url: '...',
|
|
257
|
+
* schemas: () => ObjectRegistry.getAllSchemas(), // never called
|
|
258
|
+
* });
|
|
259
|
+
* ```
|
|
260
|
+
*
|
|
261
|
+
* @example Eager — built upfront (fine for JSON/DuckDB)
|
|
262
|
+
* ```typescript
|
|
263
|
+
* await getDatabase({
|
|
264
|
+
* type: 'json',
|
|
265
|
+
* url: './data',
|
|
266
|
+
* schemas: { users: { tableName: 'users', ddl: '...' } },
|
|
267
|
+
* });
|
|
268
|
+
* ```
|
|
269
|
+
*/
|
|
270
|
+
export type SchemasOption = Record<string, SchemaProvider> | (() => Record<string, SchemaProvider>);
|
|
271
|
+
/**
|
|
272
|
+
* Resolves a SchemasOption to its concrete value.
|
|
273
|
+
*
|
|
274
|
+
* Adapters that need schemas (JSON, DuckDB) call this to unwrap the
|
|
275
|
+
* lazy function. Adapters that don't (Postgres, SQLite) simply ignore
|
|
276
|
+
* the `schemas` option without calling this.
|
|
277
|
+
*/
|
|
278
|
+
export declare function resolveSchemas(schemas: SchemasOption | undefined): Record<string, SchemaProvider> | undefined;
|
|
279
|
+
/**
|
|
280
|
+
* Schema manifest structure for JSON-based schema management
|
|
281
|
+
*/
|
|
282
|
+
export interface SchemaManifest {
|
|
283
|
+
version: string;
|
|
284
|
+
timestamp: number;
|
|
285
|
+
packageName: string;
|
|
286
|
+
schemas: Record<string, SchemaDefinition>;
|
|
287
|
+
dependencies: string[];
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Schema definition for individual tables
|
|
291
|
+
*/
|
|
292
|
+
export interface SchemaDefinition {
|
|
293
|
+
tableName: string;
|
|
294
|
+
columns: Record<string, ColumnDefinition>;
|
|
295
|
+
indexes: IndexDefinition[];
|
|
296
|
+
triggers: TriggerDefinition[];
|
|
297
|
+
foreignKeys: ForeignKeyDefinition[];
|
|
298
|
+
dependencies: string[];
|
|
299
|
+
version: string;
|
|
300
|
+
packageName: string;
|
|
301
|
+
baseClass?: string;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Column definition structure
|
|
305
|
+
*/
|
|
306
|
+
export interface ColumnDefinition {
|
|
307
|
+
type: string;
|
|
308
|
+
primaryKey?: boolean;
|
|
309
|
+
unique?: boolean;
|
|
310
|
+
notNull?: boolean;
|
|
311
|
+
defaultValue?: any;
|
|
312
|
+
check?: string;
|
|
313
|
+
foreignKey?: {
|
|
314
|
+
table: string;
|
|
315
|
+
column: string;
|
|
316
|
+
onDelete?: string;
|
|
317
|
+
onUpdate?: string;
|
|
318
|
+
};
|
|
319
|
+
description?: string;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Column definition with name for ALTER TABLE operations
|
|
323
|
+
*/
|
|
324
|
+
export interface ColumnDefinitionWithName extends ColumnDefinition {
|
|
325
|
+
name: string;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Index definition structure
|
|
329
|
+
*/
|
|
330
|
+
export interface IndexDefinition {
|
|
331
|
+
name: string;
|
|
332
|
+
columns: string[];
|
|
333
|
+
unique?: boolean;
|
|
334
|
+
where?: string;
|
|
335
|
+
description?: string;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Trigger definition structure
|
|
339
|
+
*/
|
|
340
|
+
export interface TriggerDefinition {
|
|
341
|
+
name: string;
|
|
342
|
+
when: string;
|
|
343
|
+
event: string;
|
|
344
|
+
table: string;
|
|
345
|
+
condition?: string;
|
|
346
|
+
body: string;
|
|
347
|
+
description?: string;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Foreign key constraint definition
|
|
351
|
+
*/
|
|
352
|
+
export interface ForeignKeyDefinition {
|
|
353
|
+
column: string;
|
|
354
|
+
referencesTable: string;
|
|
355
|
+
referencesColumn: string;
|
|
356
|
+
onDelete?: string;
|
|
357
|
+
onUpdate?: string;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Options for schema initialization and management
|
|
361
|
+
*/
|
|
362
|
+
export interface SchemaInitializationOptions {
|
|
363
|
+
/** Schema manifest containing table definitions */
|
|
364
|
+
manifest?: SchemaManifest;
|
|
365
|
+
/** Raw SQL DDL schema string (legacy support) */
|
|
366
|
+
schema?: string;
|
|
367
|
+
/** Schema overrides for extending base schemas */
|
|
368
|
+
overrides?: Record<string, SchemaDefinition>;
|
|
369
|
+
/** Force recreation of tables */
|
|
370
|
+
force?: boolean;
|
|
371
|
+
/** Enable debug logging */
|
|
372
|
+
debug?: boolean;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Table schema information returned by getTableSchema()
|
|
376
|
+
*/
|
|
377
|
+
export interface TableSchemaInfo {
|
|
378
|
+
/** Table name */
|
|
379
|
+
tableName: string;
|
|
380
|
+
/** Columns in the table */
|
|
381
|
+
columns: Record<string, ColumnDefinition>;
|
|
382
|
+
/** Indexes on the table */
|
|
383
|
+
indexes: IndexDefinition[];
|
|
384
|
+
/** Foreign key constraints */
|
|
385
|
+
foreignKeys: ForeignKeyDefinition[];
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Options for vector similarity search
|
|
389
|
+
*/
|
|
390
|
+
export interface VectorSearchOptions {
|
|
391
|
+
/** Maximum number of results to return */
|
|
392
|
+
limit?: number;
|
|
393
|
+
/** Distance metric for similarity comparison @default 'cosine' */
|
|
394
|
+
metric?: 'cosine' | 'l2' | 'ip';
|
|
395
|
+
/**
|
|
396
|
+
* Additional SQL WHERE clause.
|
|
397
|
+
* Use $2, $3, etc. for parameter placeholders ($1 is reserved for the query vector).
|
|
398
|
+
* @example `category = $2`
|
|
399
|
+
*/
|
|
400
|
+
where?: string;
|
|
401
|
+
/** Parameters for the WHERE clause, bound to $2, $3, etc. */
|
|
402
|
+
params?: any[];
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Result of a vector similarity search
|
|
406
|
+
*/
|
|
407
|
+
export interface VectorSearchResult {
|
|
408
|
+
/** Row primary key */
|
|
409
|
+
id: string;
|
|
410
|
+
/**
|
|
411
|
+
* Distance from query vector (lower = more similar).
|
|
412
|
+
* Range varies by metric: cosine [0, 2], L2 [0, Infinity), ip (-Infinity, Infinity).
|
|
413
|
+
*/
|
|
414
|
+
distance: number;
|
|
415
|
+
/** Additional columns from the row */
|
|
416
|
+
[key: string]: any;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Options for creating a vector index
|
|
420
|
+
*/
|
|
421
|
+
export interface VectorIndexOptions {
|
|
422
|
+
/** Number of dimensions (informational only, dimensions are set via ensureColumn) */
|
|
423
|
+
dimensions?: number;
|
|
424
|
+
/** Distance metric @default 'cosine' */
|
|
425
|
+
metric?: 'cosine' | 'l2' | 'ip';
|
|
426
|
+
/** Index type @default 'hnsw' */
|
|
427
|
+
type?: 'hnsw' | 'ivfflat';
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Vector operations capability for database adapters
|
|
431
|
+
*
|
|
432
|
+
* Provides native vector similarity search, storage, and indexing.
|
|
433
|
+
* Implemented by PostgreSQL via pgvector and optionally by SQLite via
|
|
434
|
+
* sqlite-vector.
|
|
435
|
+
*/
|
|
436
|
+
export interface VectorCapabilities {
|
|
437
|
+
/**
|
|
438
|
+
* Search for similar vectors
|
|
439
|
+
*
|
|
440
|
+
* @param table - Table containing vector column
|
|
441
|
+
* @param column - Name of the vector column
|
|
442
|
+
* @param embedding - Query vector
|
|
443
|
+
* @param options - Search options
|
|
444
|
+
* @returns Ranked results by similarity
|
|
445
|
+
*/
|
|
446
|
+
search(table: string, column: string, embedding: number[], options?: VectorSearchOptions): Promise<VectorSearchResult[]>;
|
|
447
|
+
/**
|
|
448
|
+
* Ensure a vector column exists on a table
|
|
449
|
+
*
|
|
450
|
+
* @param table - Table name
|
|
451
|
+
* @param column - Column name
|
|
452
|
+
* @param dimensions - Number of vector dimensions
|
|
453
|
+
*/
|
|
454
|
+
ensureColumn(table: string, column: string, dimensions: number): Promise<void>;
|
|
455
|
+
/**
|
|
456
|
+
* Ensure a vector index exists on a column
|
|
457
|
+
*
|
|
458
|
+
* @param table - Table name
|
|
459
|
+
* @param column - Column name
|
|
460
|
+
* @param options - Index options
|
|
461
|
+
*/
|
|
462
|
+
ensureIndex(table: string, column: string, options?: VectorIndexOptions): Promise<void>;
|
|
463
|
+
/**
|
|
464
|
+
* Store or update a vector in a specific row
|
|
465
|
+
*
|
|
466
|
+
* @param table - Table name
|
|
467
|
+
* @param where - Conditions to identify the row
|
|
468
|
+
* @param column - Vector column name
|
|
469
|
+
* @param embedding - Vector data
|
|
470
|
+
*/
|
|
471
|
+
upsertVector(table: string, where: Record<string, any>, column: string, embedding: number[]): Promise<void>;
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* SQLite notification delivered by optional notification capabilities.
|
|
475
|
+
*/
|
|
476
|
+
export interface DatabaseNotification {
|
|
477
|
+
id: number;
|
|
478
|
+
channel: string;
|
|
479
|
+
payload: any;
|
|
480
|
+
createdAt?: number | string | Date | null;
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Options for notification listeners.
|
|
484
|
+
*/
|
|
485
|
+
export interface NotificationListenOptions {
|
|
486
|
+
/**
|
|
487
|
+
* Fallback poll interval in milliseconds when the native watcher does not
|
|
488
|
+
* receive an update signal.
|
|
489
|
+
*/
|
|
490
|
+
fallbackPollMs?: number | null;
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Options for waiting on the next database update.
|
|
494
|
+
*/
|
|
495
|
+
export interface NotificationWaitOptions {
|
|
496
|
+
/**
|
|
497
|
+
* Maximum time to wait in milliseconds. When omitted, waits indefinitely.
|
|
498
|
+
*/
|
|
499
|
+
timeoutMs?: number;
|
|
500
|
+
/**
|
|
501
|
+
* Optional abort signal to cancel the wait.
|
|
502
|
+
*/
|
|
503
|
+
signal?: AbortSignal;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Options for pruning persisted notification rows.
|
|
507
|
+
*/
|
|
508
|
+
export interface NotificationPruneOptions {
|
|
509
|
+
/** Delete notifications older than this many seconds. */
|
|
510
|
+
olderThanS?: number | null;
|
|
511
|
+
/** Keep at most this many most-recent notifications. */
|
|
512
|
+
maxKeep?: number | null;
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Optional notification/pub-sub capabilities for database adapters.
|
|
516
|
+
*/
|
|
517
|
+
export interface NotificationCapabilities {
|
|
518
|
+
notify(channel: string, payload: any): Promise<number>;
|
|
519
|
+
listen(channel: string, options?: NotificationListenOptions): AsyncIterable<DatabaseNotification>;
|
|
520
|
+
waitForUpdate(options?: NotificationWaitOptions): Promise<boolean>;
|
|
521
|
+
prune(options?: NotificationPruneOptions): Promise<number>;
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Options for SQLite native notification support.
|
|
525
|
+
*/
|
|
526
|
+
export interface SqliteNotificationCapabilityOptions {
|
|
527
|
+
watcherBackend?: 'polling' | 'kernel' | 'shm';
|
|
528
|
+
maxReaders?: number;
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Options for SQLite native vector support.
|
|
532
|
+
*/
|
|
533
|
+
export interface SqliteVectorCapabilityOptions {
|
|
534
|
+
preload?: boolean;
|
|
535
|
+
quantization?: 'turbo4' | 'turbo3' | 'turbo2' | 'uint8' | 'int8' | '1bit';
|
|
536
|
+
maxMemory?: string;
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Optional SQLite-only native capabilities.
|
|
540
|
+
*/
|
|
541
|
+
export interface SqliteCapabilitiesOptions {
|
|
542
|
+
notifications?: boolean | SqliteNotificationCapabilityOptions;
|
|
543
|
+
vector?: boolean | SqliteVectorCapabilityOptions;
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Common interface for database adapters
|
|
547
|
+
* Provides a unified API for different database backends
|
|
548
|
+
*/
|
|
549
|
+
export interface DatabaseInterface {
|
|
550
|
+
/**
|
|
551
|
+
* Database location identifier
|
|
552
|
+
* For file-based databases: file path
|
|
553
|
+
* For directory-based databases (JSON/DuckDB with JSON): directory path
|
|
554
|
+
* For in-memory databases: ':memory:'
|
|
555
|
+
* For remote databases: connection URL
|
|
556
|
+
*/
|
|
557
|
+
url: string;
|
|
558
|
+
/**
|
|
559
|
+
* Underlying database client instance
|
|
560
|
+
*/
|
|
561
|
+
client: any;
|
|
562
|
+
/**
|
|
563
|
+
* Inserts one or more records into a table
|
|
564
|
+
*
|
|
565
|
+
* @param table - Table name
|
|
566
|
+
* @param data - Single record or array of records to insert
|
|
567
|
+
* @returns Promise resolving to operation result
|
|
568
|
+
*/
|
|
569
|
+
insert: (table: string, data: Record<string, any> | Record<string, any>[]) => Promise<QueryResult>;
|
|
570
|
+
/**
|
|
571
|
+
* Retrieves a single record matching the where criteria
|
|
572
|
+
*
|
|
573
|
+
* @param table - Table name
|
|
574
|
+
* @param where - Criteria to match records (object for AND-only, 2D array for OR/AND)
|
|
575
|
+
* @returns Promise resolving to matching record or null if not found
|
|
576
|
+
*/
|
|
577
|
+
get: (table: string, where: WhereClause) => Promise<Record<string, any> | null>;
|
|
578
|
+
/**
|
|
579
|
+
* Retrieves multiple records matching the where criteria
|
|
580
|
+
*
|
|
581
|
+
* @param table - Table name
|
|
582
|
+
* @param where - Criteria to match records (object for AND-only, 2D array for OR/AND)
|
|
583
|
+
* @returns Promise resolving to array of matching records
|
|
584
|
+
*/
|
|
585
|
+
list: (table: string, where: WhereClause) => Promise<Record<string, any>[]>;
|
|
586
|
+
/**
|
|
587
|
+
* Updates records matching the where criteria
|
|
588
|
+
*
|
|
589
|
+
* @param table - Table name
|
|
590
|
+
* @param where - Criteria to match records to update (object for AND-only, 2D array for OR/AND)
|
|
591
|
+
* @param data - New data to set
|
|
592
|
+
* @returns Promise resolving to operation result
|
|
593
|
+
*/
|
|
594
|
+
update: (table: string, where: WhereClause, data: Record<string, any>) => Promise<QueryResult>;
|
|
595
|
+
/**
|
|
596
|
+
* Inserts a record or updates it if it already exists (UPSERT)
|
|
597
|
+
* Uses database-specific ON CONFLICT / ON DUPLICATE KEY syntax
|
|
598
|
+
*
|
|
599
|
+
* @param table - Table name
|
|
600
|
+
* @param conflictColumns - Columns that define the uniqueness constraint
|
|
601
|
+
* @param data - Data to insert or update
|
|
602
|
+
* @returns Promise resolving to operation result
|
|
603
|
+
*
|
|
604
|
+
* @example
|
|
605
|
+
* ```typescript
|
|
606
|
+
* // Upsert a user by email
|
|
607
|
+
* await db.upsert('users', ['email'], {
|
|
608
|
+
* email: 'user@example.com',
|
|
609
|
+
* name: 'John Doe',
|
|
610
|
+
* updated_at: new Date().toISOString()
|
|
611
|
+
* });
|
|
612
|
+
*
|
|
613
|
+
* // Upsert with composite key
|
|
614
|
+
* await db.upsert('settings', ['user_id', 'key'], {
|
|
615
|
+
* user_id: '123',
|
|
616
|
+
* key: 'theme',
|
|
617
|
+
* value: 'dark'
|
|
618
|
+
* });
|
|
619
|
+
* ```
|
|
620
|
+
*/
|
|
621
|
+
upsert: (table: string, conflictColumns: string[], data: Record<string, any>, options?: UpsertOptions) => Promise<QueryResult>;
|
|
622
|
+
/**
|
|
623
|
+
* Gets a record matching the where criteria or inserts it if not found
|
|
624
|
+
*
|
|
625
|
+
* @param table - Table name
|
|
626
|
+
* @param where - Criteria to match existing record (object for AND-only, 2D array for OR/AND)
|
|
627
|
+
* @param data - Data to insert if no record found
|
|
628
|
+
* @returns Promise resolving to the record (either retrieved or newly inserted)
|
|
629
|
+
*/
|
|
630
|
+
getOrInsert: (table: string, where: WhereClause, data: Record<string, any>) => Promise<Record<string, any>>;
|
|
631
|
+
/**
|
|
632
|
+
* Deletes records from a table matching the where criteria
|
|
633
|
+
*
|
|
634
|
+
* @param table - Table name
|
|
635
|
+
* @param where - Criteria to match records for deletion (object for AND-only, 2D array for OR/AND)
|
|
636
|
+
* @returns Promise resolving to operation result with count of deleted rows
|
|
637
|
+
*
|
|
638
|
+
* @example
|
|
639
|
+
* ```typescript
|
|
640
|
+
* // Delete by ID
|
|
641
|
+
* await db.delete('products', { id: 'prod-123' });
|
|
642
|
+
*
|
|
643
|
+
* // Delete by criteria
|
|
644
|
+
* await db.delete('orders', { status: 'cancelled' });
|
|
645
|
+
*
|
|
646
|
+
* // Delete with multiple conditions
|
|
647
|
+
* await db.delete('sessions', {
|
|
648
|
+
* user_id: 'user-123',
|
|
649
|
+
* expired: true
|
|
650
|
+
* });
|
|
651
|
+
* ```
|
|
652
|
+
*/
|
|
653
|
+
delete: (table: string, where: WhereClause) => Promise<QueryResult>;
|
|
654
|
+
/**
|
|
655
|
+
* Counts records in a table matching the where criteria
|
|
656
|
+
*
|
|
657
|
+
* @param table - Table name
|
|
658
|
+
* @param where - Criteria to match records (optional, counts all if omitted; object for AND-only, 2D array for OR/AND)
|
|
659
|
+
* @returns Promise resolving to count of matching records
|
|
660
|
+
*
|
|
661
|
+
* @example
|
|
662
|
+
* ```typescript
|
|
663
|
+
* // Count all records
|
|
664
|
+
* const total = await db.count('products');
|
|
665
|
+
*
|
|
666
|
+
* // Count with single condition
|
|
667
|
+
* const activeCount = await db.count('products', { active: true });
|
|
668
|
+
*
|
|
669
|
+
* // Count with multiple conditions
|
|
670
|
+
* const filteredCount = await db.count('orders', {
|
|
671
|
+
* status: 'pending',
|
|
672
|
+
* priority: 'high'
|
|
673
|
+
* });
|
|
674
|
+
* ```
|
|
675
|
+
*/
|
|
676
|
+
count: (table: string, where?: WhereClause) => Promise<number>;
|
|
677
|
+
/**
|
|
678
|
+
* Creates a table-specific interface for simplified table operations
|
|
679
|
+
*
|
|
680
|
+
* @param table - Table name
|
|
681
|
+
* @returns TableInterface for the specified table
|
|
682
|
+
*/
|
|
683
|
+
table: (table: string) => TableInterface;
|
|
684
|
+
/**
|
|
685
|
+
* Checks if a table exists in the database
|
|
686
|
+
*
|
|
687
|
+
* @param table - Table name
|
|
688
|
+
* @returns Promise resolving to boolean indicating existence
|
|
689
|
+
*/
|
|
690
|
+
tableExists: (table: string) => Promise<boolean>;
|
|
691
|
+
/**
|
|
692
|
+
* Whether this adapter requires schema existence checks at runtime.
|
|
693
|
+
*
|
|
694
|
+
* Set to `true` on adapters where tables may not exist yet and need
|
|
695
|
+
* to be verified before use (e.g. JSON/DuckDB with auto-created tables).
|
|
696
|
+
*
|
|
697
|
+
* When absent or `false`, frameworks skip `tableExists()` calls during
|
|
698
|
+
* collection initialization — tables are assumed to exist because
|
|
699
|
+
* schema is managed by migrations (e.g. `smrt db:migrate`).
|
|
700
|
+
*
|
|
701
|
+
* - Postgres adapter: not set (migration-managed)
|
|
702
|
+
* - SQLite adapter: not set (migration-managed)
|
|
703
|
+
* - JSON/DuckDB adapter: `true` (tables may be auto-created)
|
|
704
|
+
*/
|
|
705
|
+
requiresSchemaCheck?: boolean;
|
|
706
|
+
/**
|
|
707
|
+
* Executes a SQL query using template literals and returns multiple rows
|
|
708
|
+
*
|
|
709
|
+
* @param strings - Template strings
|
|
710
|
+
* @param vars - Variables to interpolate into the query
|
|
711
|
+
* @returns Promise resolving to array of result records
|
|
712
|
+
*/
|
|
713
|
+
many: (strings: TemplateStringsArray, ...vars: any[]) => Promise<Record<string, any>[]>;
|
|
714
|
+
/**
|
|
715
|
+
* Executes a SQL query using template literals and returns a single row
|
|
716
|
+
*
|
|
717
|
+
* @param strings - Template strings
|
|
718
|
+
* @param vars - Variables to interpolate into the query
|
|
719
|
+
* @returns Promise resolving to a single result record or null
|
|
720
|
+
*/
|
|
721
|
+
single: (strings: TemplateStringsArray, ...vars: any[]) => Promise<Record<string, any> | null>;
|
|
722
|
+
/**
|
|
723
|
+
* Executes a SQL query using template literals and returns a single value
|
|
724
|
+
*
|
|
725
|
+
* @param strings - Template strings
|
|
726
|
+
* @param vars - Variables to interpolate into the query
|
|
727
|
+
* @returns Promise resolving to a single value (first column of first row)
|
|
728
|
+
*/
|
|
729
|
+
pluck: (strings: TemplateStringsArray, ...vars: any[]) => Promise<any>;
|
|
730
|
+
/**
|
|
731
|
+
* Executes a SQL query using template literals without returning results
|
|
732
|
+
*
|
|
733
|
+
* @param strings - Template strings
|
|
734
|
+
* @param vars - Variables to interpolate into the query
|
|
735
|
+
* @returns Promise that resolves when the query completes
|
|
736
|
+
*/
|
|
737
|
+
execute: (strings: TemplateStringsArray, ...vars: any[]) => Promise<void>;
|
|
738
|
+
/**
|
|
739
|
+
* Alias for many() - Executes a SQL query and returns multiple rows
|
|
740
|
+
*/
|
|
741
|
+
oo: (strings: TemplateStringsArray, ...vars: any[]) => Promise<Record<string, any>[]>;
|
|
742
|
+
/**
|
|
743
|
+
* Alias for single() - Executes a SQL query and returns a single row
|
|
744
|
+
*/
|
|
745
|
+
oO: (strings: TemplateStringsArray, ...vars: any[]) => Promise<Record<string, any> | null>;
|
|
746
|
+
/**
|
|
747
|
+
* Alias for pluck() - Executes a SQL query and returns a single value
|
|
748
|
+
*/
|
|
749
|
+
ox: (strings: TemplateStringsArray, ...vars: any[]) => Promise<any>;
|
|
750
|
+
/**
|
|
751
|
+
* Alias for execute() - Executes a SQL query without returning results
|
|
752
|
+
*/
|
|
753
|
+
xx: (strings: TemplateStringsArray, ...vars: any[]) => Promise<void>;
|
|
754
|
+
/**
|
|
755
|
+
* Executes a raw SQL query with parameterized values
|
|
756
|
+
*
|
|
757
|
+
* Raw queries use the adapter's native placeholder syntax.
|
|
758
|
+
* Parameters may be passed as rest arguments or as one values array.
|
|
759
|
+
* For adapter-specific array parameter caveats, see the package docs.
|
|
760
|
+
*
|
|
761
|
+
* @param str - SQL query string
|
|
762
|
+
* @param vars - Variables to use as parameters
|
|
763
|
+
* @returns Promise resolving to query result with rows and count
|
|
764
|
+
*/
|
|
765
|
+
query: (str: string, ...vars: any[]) => Promise<{
|
|
766
|
+
rows: Record<string, any>[];
|
|
767
|
+
rowCount: number;
|
|
768
|
+
}>;
|
|
769
|
+
/**
|
|
770
|
+
* Synchronizes database schema with provided SQL DDL
|
|
771
|
+
* Creates tables if they don't exist and adds missing columns
|
|
772
|
+
*
|
|
773
|
+
* @param schema - SQL schema definition with CREATE TABLE statements
|
|
774
|
+
* @returns Promise that resolves when schema is synchronized
|
|
775
|
+
*/
|
|
776
|
+
syncSchema?: (schema: string) => Promise<void>;
|
|
777
|
+
/**
|
|
778
|
+
* Initialize database schemas from JSON manifest
|
|
779
|
+
* Supports dependency resolution and schema overrides
|
|
780
|
+
*
|
|
781
|
+
* @param options - Schema initialization options
|
|
782
|
+
* @returns Promise that resolves when schemas are initialized
|
|
783
|
+
*/
|
|
784
|
+
initializeSchemas?: (options: SchemaInitializationOptions) => Promise<void>;
|
|
785
|
+
/**
|
|
786
|
+
* Executes a callback within a database transaction
|
|
787
|
+
* Automatically commits on success or rolls back on error
|
|
788
|
+
*
|
|
789
|
+
* @param callback - Function to execute within transaction
|
|
790
|
+
* @returns Promise resolving to callback result
|
|
791
|
+
*/
|
|
792
|
+
transaction?: <T>(callback: (tx: DatabaseInterface) => Promise<T>) => Promise<T>;
|
|
793
|
+
/**
|
|
794
|
+
* Begins a new transaction and returns a handle for manual control
|
|
795
|
+
*
|
|
796
|
+
* Unlike transaction(), this gives you explicit control over commit/rollback.
|
|
797
|
+
* Ideal for test isolation where you want to rollback after each test.
|
|
798
|
+
*
|
|
799
|
+
* @returns Promise resolving to a TransactionHandle
|
|
800
|
+
*
|
|
801
|
+
* @example Test isolation pattern
|
|
802
|
+
* ```typescript
|
|
803
|
+
* let tx: TransactionHandle;
|
|
804
|
+
*
|
|
805
|
+
* beforeEach(async () => {
|
|
806
|
+
* tx = await db.beginTransaction();
|
|
807
|
+
* });
|
|
808
|
+
*
|
|
809
|
+
* afterEach(async () => {
|
|
810
|
+
* await tx.rollback(); // Discard all test changes
|
|
811
|
+
* });
|
|
812
|
+
*
|
|
813
|
+
* it('creates user', async () => {
|
|
814
|
+
* await tx.insert('users', { id: '1', name: 'Test' });
|
|
815
|
+
* const user = await tx.get('users', { id: '1' });
|
|
816
|
+
* expect(user).toBeDefined();
|
|
817
|
+
* // Changes rolled back in afterEach
|
|
818
|
+
* });
|
|
819
|
+
* ```
|
|
820
|
+
*/
|
|
821
|
+
beginTransaction?: () => Promise<TransactionHandle>;
|
|
822
|
+
/**
|
|
823
|
+
* Acquire a pinned single-connection session.
|
|
824
|
+
*
|
|
825
|
+
* Returns a {@link SessionHandle} whose queries all run on one underlying
|
|
826
|
+
* connection, enabling session-scoped state (e.g. PostgreSQL session advisory
|
|
827
|
+
* locks) that the pooled top-level {@link query} cannot hold reliably. The
|
|
828
|
+
* caller must {@link SessionHandle.release} it.
|
|
829
|
+
*
|
|
830
|
+
* Only meaningful for engines with session-scoped state, so it is currently
|
|
831
|
+
* implemented for PostgreSQL only; check for the method before calling
|
|
832
|
+
* (`if (db.acquireSession)`). Single-connection engines (SQLite, DuckDB) have
|
|
833
|
+
* no session-scoped locks to hold, so they leave it undefined.
|
|
834
|
+
*
|
|
835
|
+
* @returns Promise resolving to a SessionHandle
|
|
836
|
+
*
|
|
837
|
+
* @example Hold a Postgres session advisory lock
|
|
838
|
+
* ```typescript
|
|
839
|
+
* const session = await db.acquireSession();
|
|
840
|
+
* try {
|
|
841
|
+
* await session.query('SELECT pg_advisory_lock($1)', 42);
|
|
842
|
+
* // ... lock is held for the life of this session ...
|
|
843
|
+
* } finally {
|
|
844
|
+
* await session.release(); // frees the lock and drops the connection
|
|
845
|
+
* }
|
|
846
|
+
* ```
|
|
847
|
+
*/
|
|
848
|
+
acquireSession?: () => Promise<SessionHandle>;
|
|
849
|
+
/**
|
|
850
|
+
* Retrieves the schema information for a table
|
|
851
|
+
*
|
|
852
|
+
* @param table - Table name
|
|
853
|
+
* @returns Promise resolving to table schema info or null if table doesn't exist
|
|
854
|
+
*/
|
|
855
|
+
getTableSchema?: (table: string) => Promise<TableSchemaInfo | null>;
|
|
856
|
+
/**
|
|
857
|
+
* Vector operations for native similarity search
|
|
858
|
+
*
|
|
859
|
+
* When available, enables database-level vector operations (e.g., pgvector).
|
|
860
|
+
* Consumers should check for this capability rather than checking the database type.
|
|
861
|
+
*/
|
|
862
|
+
vector?: VectorCapabilities;
|
|
863
|
+
/**
|
|
864
|
+
* Optional notification/pub-sub operations.
|
|
865
|
+
*/
|
|
866
|
+
notifications?: NotificationCapabilities;
|
|
867
|
+
/**
|
|
868
|
+
* Close the database adapter and release native resources when supported.
|
|
869
|
+
*/
|
|
870
|
+
close?: () => Promise<void>;
|
|
871
|
+
/**
|
|
872
|
+
* ALTER TABLE operations for schema evolution
|
|
873
|
+
*/
|
|
874
|
+
alterTable?: {
|
|
875
|
+
/**
|
|
876
|
+
* Adds a new column to an existing table
|
|
877
|
+
*
|
|
878
|
+
* @param table - Table name
|
|
879
|
+
* @param column - Column definition with name
|
|
880
|
+
* @returns Promise that resolves when column is added
|
|
881
|
+
*/
|
|
882
|
+
addColumn: (table: string, column: ColumnDefinitionWithName) => Promise<void>;
|
|
883
|
+
/**
|
|
884
|
+
* Adds a new index to an existing table
|
|
885
|
+
*
|
|
886
|
+
* @param table - Table name
|
|
887
|
+
* @param index - Index definition
|
|
888
|
+
* @returns Promise that resolves when index is created
|
|
889
|
+
*/
|
|
890
|
+
addIndex: (table: string, index: IndexDefinition) => Promise<void>;
|
|
891
|
+
};
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* Transaction handle for manual transaction control
|
|
895
|
+
*
|
|
896
|
+
* Extends DatabaseInterface with commit() and rollback() methods.
|
|
897
|
+
* Use beginTransaction() to obtain a handle, then explicitly
|
|
898
|
+
* commit or rollback when done.
|
|
899
|
+
*
|
|
900
|
+
* @example Test isolation with rollback
|
|
901
|
+
* ```typescript
|
|
902
|
+
* const tx = await db.beginTransaction();
|
|
903
|
+
* try {
|
|
904
|
+
* // All operations happen in the transaction
|
|
905
|
+
* await tx.insert('users', { id: '1', name: 'Test' });
|
|
906
|
+
* const user = await tx.get('users', { id: '1' });
|
|
907
|
+
*
|
|
908
|
+
* // Rollback discards all changes (useful for test isolation)
|
|
909
|
+
* await tx.rollback();
|
|
910
|
+
* } catch (error) {
|
|
911
|
+
* await tx.rollback();
|
|
912
|
+
* throw error;
|
|
913
|
+
* }
|
|
914
|
+
* ```
|
|
915
|
+
*
|
|
916
|
+
* @example Manual commit
|
|
917
|
+
* ```typescript
|
|
918
|
+
* const tx = await db.beginTransaction();
|
|
919
|
+
* try {
|
|
920
|
+
* await tx.insert('orders', { id: '1', total: 100 });
|
|
921
|
+
* await tx.insert('order_items', { order_id: '1', product: 'Widget' });
|
|
922
|
+
* await tx.commit(); // Persist changes
|
|
923
|
+
* } catch (error) {
|
|
924
|
+
* await tx.rollback();
|
|
925
|
+
* throw error;
|
|
926
|
+
* }
|
|
927
|
+
* ```
|
|
928
|
+
*/
|
|
929
|
+
export interface TransactionHandle extends DatabaseInterface {
|
|
930
|
+
/**
|
|
931
|
+
* Commits the transaction, persisting all changes
|
|
932
|
+
*
|
|
933
|
+
* After commit, the transaction handle should not be used.
|
|
934
|
+
*/
|
|
935
|
+
commit: () => Promise<void>;
|
|
936
|
+
/**
|
|
937
|
+
* Rolls back the transaction, discarding all changes
|
|
938
|
+
*
|
|
939
|
+
* After rollback, the transaction handle should not be used.
|
|
940
|
+
* This is the key method for test isolation - rollback after each test.
|
|
941
|
+
*/
|
|
942
|
+
rollback: () => Promise<void>;
|
|
943
|
+
/**
|
|
944
|
+
* Whether the transaction is still active (not committed or rolled back)
|
|
945
|
+
*/
|
|
946
|
+
isActive: () => boolean;
|
|
947
|
+
}
|
|
948
|
+
/**
|
|
949
|
+
* Pinned single-connection session handle.
|
|
950
|
+
*
|
|
951
|
+
* Obtained via {@link DatabaseInterface.acquireSession}. Unlike the pooled
|
|
952
|
+
* top-level `query` (which may run each statement on a different connection),
|
|
953
|
+
* every call on a session handle runs on the *same* underlying connection for
|
|
954
|
+
* the handle's lifetime. This is required for session-scoped state such as
|
|
955
|
+
* PostgreSQL session advisory locks (`pg_advisory_lock`), which must be
|
|
956
|
+
* acquired, observed, and released on one connection — and which release
|
|
957
|
+
* automatically if the connection drops (e.g. the process dies).
|
|
958
|
+
*
|
|
959
|
+
* A session holds one connection out of the pool (default max 20) for its
|
|
960
|
+
* entire lifetime, so it is meant to be held one-per-process, not per-operation.
|
|
961
|
+
* Always {@link SessionHandle.release} the handle when done, and release it
|
|
962
|
+
* *before* calling `db.client.end()` — a pinned connection keeps `pool.end()`
|
|
963
|
+
* from resolving.
|
|
964
|
+
*/
|
|
965
|
+
export interface SessionHandle {
|
|
966
|
+
/**
|
|
967
|
+
* Execute a raw query on this session's pinned connection.
|
|
968
|
+
* Same placeholder/return contract as {@link DatabaseInterface.query}.
|
|
969
|
+
* Throws if the session has been released or its connection was lost.
|
|
970
|
+
*/
|
|
971
|
+
query: (sql: string, ...vars: any[]) => Promise<{
|
|
972
|
+
rows: Record<string, any>[];
|
|
973
|
+
rowCount: number;
|
|
974
|
+
}>;
|
|
975
|
+
/**
|
|
976
|
+
* Whether the session is still usable — not released and its connection has
|
|
977
|
+
* not errored/dropped. A long-lived lock holder can poll this without
|
|
978
|
+
* issuing a query.
|
|
979
|
+
*/
|
|
980
|
+
isActive: () => boolean;
|
|
981
|
+
/**
|
|
982
|
+
* Release the session. Idempotent. After release the handle must not be used.
|
|
983
|
+
* Best-effort frees session-scoped locks, then drops the underlying
|
|
984
|
+
* connection (it is NOT returned to the pool) so the database releases any
|
|
985
|
+
* remaining session state — returning it to the pool would leak that state
|
|
986
|
+
* onto a later, unrelated checkout.
|
|
987
|
+
*/
|
|
988
|
+
release: () => Promise<void>;
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* Simplified interface for table-specific operations
|
|
992
|
+
*/
|
|
993
|
+
export interface TableInterface {
|
|
994
|
+
/**
|
|
995
|
+
* Inserts one or more records into the table
|
|
996
|
+
*
|
|
997
|
+
* @param data - Single record or array of records to insert
|
|
998
|
+
* @returns Promise resolving to operation result
|
|
999
|
+
*/
|
|
1000
|
+
insert: (data: Record<string, any> | Record<string, any>[]) => Promise<QueryResult>;
|
|
1001
|
+
/**
|
|
1002
|
+
* Retrieves a single record from the table matching the where criteria
|
|
1003
|
+
*
|
|
1004
|
+
* @param where - Criteria to match records (object for AND-only, 2D array for OR/AND)
|
|
1005
|
+
* @returns Promise resolving to matching record or null if not found
|
|
1006
|
+
*/
|
|
1007
|
+
get: (where: WhereClause) => Promise<Record<string, any> | null>;
|
|
1008
|
+
/**
|
|
1009
|
+
* Retrieves multiple records from the table matching the where criteria
|
|
1010
|
+
*
|
|
1011
|
+
* @param where - Criteria to match records (object for AND-only, 2D array for OR/AND)
|
|
1012
|
+
* @returns Promise resolving to array of matching records
|
|
1013
|
+
*/
|
|
1014
|
+
list: (where: WhereClause) => Promise<Record<string, any>[]>;
|
|
1015
|
+
}
|
|
1016
|
+
//# sourceMappingURL=types.d.ts.map
|