@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.
Files changed (53) hide show
  1. package/AGENT.md +33 -0
  2. package/LICENSE +7 -0
  3. package/README.md +287 -0
  4. package/dist/backup/index.d.ts +119 -0
  5. package/dist/backup/index.d.ts.map +1 -0
  6. package/dist/backup/index.js +212 -0
  7. package/dist/backup/index.js.map +1 -0
  8. package/dist/backup/manifest.d.ts +51 -0
  9. package/dist/backup/manifest.d.ts.map +1 -0
  10. package/dist/chunks/duckdb-Djx8WKZE.js +924 -0
  11. package/dist/chunks/duckdb-Djx8WKZE.js.map +1 -0
  12. package/dist/chunks/index-DL-5nB7l.js +3468 -0
  13. package/dist/chunks/index-DL-5nB7l.js.map +1 -0
  14. package/dist/chunks/postgres-cli-Cr6bBZ3q.js +209 -0
  15. package/dist/chunks/postgres-cli-Cr6bBZ3q.js.map +1 -0
  16. package/dist/chunks/sqlite-DkCGjXmu.js +937 -0
  17. package/dist/chunks/sqlite-DkCGjXmu.js.map +1 -0
  18. package/dist/chunks/sqlite-native-B6q-0nLs.js +1129 -0
  19. package/dist/chunks/sqlite-native-B6q-0nLs.js.map +1 -0
  20. package/dist/cli/claude-context.d.ts +3 -0
  21. package/dist/cli/claude-context.d.ts.map +1 -0
  22. package/dist/cli/claude-context.js +21 -0
  23. package/dist/cli/claude-context.js.map +1 -0
  24. package/dist/doctor.d.ts +69 -0
  25. package/dist/doctor.d.ts.map +1 -0
  26. package/dist/duckdb.d.ts +9 -0
  27. package/dist/duckdb.d.ts.map +1 -0
  28. package/dist/index.d.ts +109 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +34 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/json.d.ts +30 -0
  33. package/dist/json.d.ts.map +1 -0
  34. package/dist/postgres-cli.d.ts +135 -0
  35. package/dist/postgres-cli.d.ts.map +1 -0
  36. package/dist/postgres.d.ts +77 -0
  37. package/dist/postgres.d.ts.map +1 -0
  38. package/dist/schema-manager.d.ts +86 -0
  39. package/dist/schema-manager.d.ts.map +1 -0
  40. package/dist/shared/alter-utils.d.ts +83 -0
  41. package/dist/shared/alter-utils.d.ts.map +1 -0
  42. package/dist/shared/duckdb-schema-utils.d.ts +86 -0
  43. package/dist/shared/duckdb-schema-utils.d.ts.map +1 -0
  44. package/dist/shared/types.d.ts +1016 -0
  45. package/dist/shared/types.d.ts.map +1 -0
  46. package/dist/shared/utils.d.ts +104 -0
  47. package/dist/shared/utils.d.ts.map +1 -0
  48. package/dist/sqlite-native.d.ts +4 -0
  49. package/dist/sqlite-native.d.ts.map +1 -0
  50. package/dist/sqlite.d.ts +54 -0
  51. package/dist/sqlite.d.ts.map +1 -0
  52. package/metadata.json +38 -0
  53. 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