@nextlyhq/adapter-drizzle 0.0.2-alpha.60 → 0.0.2-alpha.62

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.
@@ -1,9 +1,36 @@
1
1
  import { AnyRelations, SQL } from 'drizzle-orm';
2
+ import { T as TransactionContext, S as SelectOptions, W as WhereClause, U as UpdateOptions, D as DeleteOptions, e as UpsertOptions, f as TransactionOptions, g as DatabaseCapabilities, P as PoolStats, I as InsertOptions, a as Migration, d as MigrationResult } from './migration-BnT96HFp.js';
2
3
  import { S as SupportedDialect, a as SqlParam, T as TableResolver } from './core-CVO7WYDj.js';
3
- import { T as TransactionContext, e as TransactionOptions, D as DatabaseCapabilities, P as PoolStats, S as SelectOptions, I as InsertOptions, W as WhereClause, U as UpdateOptions, f as DeleteOptions, g as UpsertOptions, a as Migration, d as MigrationResult } from './migration-Bj84e15B.js';
4
4
  import { T as TableDefinition, C as CreateTableOptions, D as DropTableOptions, A as AlterTableOperation, a as AlterTableOptions } from './schema-BIQ0YQZ_.js';
5
5
  import { D as DatabaseErrorKind, a as DatabaseError } from './error-BrdknH2s.js';
6
6
 
7
+ /**
8
+ * Transaction CRUD forwarder helper for database adapters.
9
+ *
10
+ * @remarks
11
+ * Encapsulates the delegation pattern where a transaction context forwards its
12
+ * CRUD methods to the adapter's implementation while passing the transaction-bound
13
+ * Drizzle executor.
14
+ *
15
+ * @packageDocumentation
16
+ */
17
+
18
+ /**
19
+ * Interface representing an adapter that can execute CRUD operations with an optional executor.
20
+ */
21
+ interface TransactionCrudDelegator {
22
+ select<T = unknown>(table: string, options?: SelectOptions, executor?: unknown): Promise<T[]>;
23
+ selectOne<T = unknown>(table: string, options?: SelectOptions, executor?: unknown): Promise<T | null>;
24
+ update<T = unknown>(table: string, data: Record<string, unknown>, where: WhereClause, options?: UpdateOptions, executor?: unknown): Promise<T[]>;
25
+ updateCount(table: string, data: Record<string, unknown>, where: WhereClause, executor?: unknown): Promise<number>;
26
+ delete(table: string, where: WhereClause, options?: DeleteOptions, executor?: unknown): Promise<number>;
27
+ upsert<T = unknown>(table: string, data: Record<string, unknown>, options: UpsertOptions, executor?: unknown): Promise<T>;
28
+ }
29
+ /**
30
+ * Transaction context CRUD methods provided by the forwarder.
31
+ */
32
+ type TransactionCrudForwarders = Pick<TransactionContext, "select" | "selectOne" | "update" | "updateCount" | "delete" | "upsert" | "getDrizzle">;
33
+
7
34
  /**
8
35
  * Base database adapter abstract class.
9
36
  *
@@ -708,12 +735,35 @@ declare abstract class DrizzleAdapter {
708
735
  * @protected
709
736
  */
710
737
  protected createDatabaseError(kind: DatabaseErrorKind, message: string, cause?: Error): DatabaseError;
738
+ /**
739
+ * Helper to create transaction context CRUD forwarding methods.
740
+ *
741
+ * @param txDb - Thunk returning the transaction-bound Drizzle executor
742
+ * @returns Object providing forwarded CRUD and getDrizzle methods
743
+ *
744
+ * @protected
745
+ */
746
+ protected createTransactionForwarders(txDb: () => unknown): TransactionCrudForwarders;
747
+ /**
748
+ * Classify an error into a DatabaseError.
749
+ *
750
+ * @remarks
751
+ * Subclasses can override this method to add dialect-specific error code classification.
752
+ *
753
+ * @param error - Original error
754
+ * @param sql - SQL statement that caused the error (optional)
755
+ * @returns DatabaseError instance
756
+ *
757
+ * @protected
758
+ */
759
+ protected classifyError(error: unknown, sql?: string): DatabaseError;
711
760
  /**
712
761
  * Handle query errors and convert to DatabaseError.
713
762
  *
714
763
  * @remarks
715
764
  * Protected helper for consistent error handling across CRUD operations.
716
- * Subclasses can override to add dialect-specific error classification.
765
+ * Delegates to `classifyError` and attaches operation and table context if not present.
766
+ * Subclasses override `classifyError` to provide dialect-specific error code classification.
717
767
  *
718
768
  * @param error - Original error
719
769
  * @param operation - Operation that failed
@@ -725,4 +775,4 @@ declare abstract class DrizzleAdapter {
725
775
  protected handleQueryError(error: unknown, operation: string, table: string): DatabaseError;
726
776
  }
727
777
 
728
- export { DrizzleAdapter as D };
778
+ export { DrizzleAdapter as D, type TransactionCrudDelegator as T, type TransactionCrudForwarders as a };
@@ -1,9 +1,36 @@
1
1
  import { AnyRelations, SQL } from 'drizzle-orm';
2
+ import { T as TransactionContext, S as SelectOptions, W as WhereClause, U as UpdateOptions, D as DeleteOptions, e as UpsertOptions, f as TransactionOptions, g as DatabaseCapabilities, P as PoolStats, I as InsertOptions, a as Migration, d as MigrationResult } from './migration-DhMuYiIm.cjs';
2
3
  import { S as SupportedDialect, a as SqlParam, T as TableResolver } from './core-CVO7WYDj.cjs';
3
- import { T as TransactionContext, e as TransactionOptions, D as DatabaseCapabilities, P as PoolStats, S as SelectOptions, I as InsertOptions, W as WhereClause, U as UpdateOptions, f as DeleteOptions, g as UpsertOptions, a as Migration, d as MigrationResult } from './migration-BUc56kip.cjs';
4
4
  import { T as TableDefinition, C as CreateTableOptions, D as DropTableOptions, A as AlterTableOperation, a as AlterTableOptions } from './schema-BDn8WfSL.cjs';
5
5
  import { D as DatabaseErrorKind, a as DatabaseError } from './error-BrdknH2s.cjs';
6
6
 
7
+ /**
8
+ * Transaction CRUD forwarder helper for database adapters.
9
+ *
10
+ * @remarks
11
+ * Encapsulates the delegation pattern where a transaction context forwards its
12
+ * CRUD methods to the adapter's implementation while passing the transaction-bound
13
+ * Drizzle executor.
14
+ *
15
+ * @packageDocumentation
16
+ */
17
+
18
+ /**
19
+ * Interface representing an adapter that can execute CRUD operations with an optional executor.
20
+ */
21
+ interface TransactionCrudDelegator {
22
+ select<T = unknown>(table: string, options?: SelectOptions, executor?: unknown): Promise<T[]>;
23
+ selectOne<T = unknown>(table: string, options?: SelectOptions, executor?: unknown): Promise<T | null>;
24
+ update<T = unknown>(table: string, data: Record<string, unknown>, where: WhereClause, options?: UpdateOptions, executor?: unknown): Promise<T[]>;
25
+ updateCount(table: string, data: Record<string, unknown>, where: WhereClause, executor?: unknown): Promise<number>;
26
+ delete(table: string, where: WhereClause, options?: DeleteOptions, executor?: unknown): Promise<number>;
27
+ upsert<T = unknown>(table: string, data: Record<string, unknown>, options: UpsertOptions, executor?: unknown): Promise<T>;
28
+ }
29
+ /**
30
+ * Transaction context CRUD methods provided by the forwarder.
31
+ */
32
+ type TransactionCrudForwarders = Pick<TransactionContext, "select" | "selectOne" | "update" | "updateCount" | "delete" | "upsert" | "getDrizzle">;
33
+
7
34
  /**
8
35
  * Base database adapter abstract class.
9
36
  *
@@ -708,12 +735,35 @@ declare abstract class DrizzleAdapter {
708
735
  * @protected
709
736
  */
710
737
  protected createDatabaseError(kind: DatabaseErrorKind, message: string, cause?: Error): DatabaseError;
738
+ /**
739
+ * Helper to create transaction context CRUD forwarding methods.
740
+ *
741
+ * @param txDb - Thunk returning the transaction-bound Drizzle executor
742
+ * @returns Object providing forwarded CRUD and getDrizzle methods
743
+ *
744
+ * @protected
745
+ */
746
+ protected createTransactionForwarders(txDb: () => unknown): TransactionCrudForwarders;
747
+ /**
748
+ * Classify an error into a DatabaseError.
749
+ *
750
+ * @remarks
751
+ * Subclasses can override this method to add dialect-specific error code classification.
752
+ *
753
+ * @param error - Original error
754
+ * @param sql - SQL statement that caused the error (optional)
755
+ * @returns DatabaseError instance
756
+ *
757
+ * @protected
758
+ */
759
+ protected classifyError(error: unknown, sql?: string): DatabaseError;
711
760
  /**
712
761
  * Handle query errors and convert to DatabaseError.
713
762
  *
714
763
  * @remarks
715
764
  * Protected helper for consistent error handling across CRUD operations.
716
- * Subclasses can override to add dialect-specific error classification.
765
+ * Delegates to `classifyError` and attaches operation and table context if not present.
766
+ * Subclasses override `classifyError` to provide dialect-specific error code classification.
717
767
  *
718
768
  * @param error - Original error
719
769
  * @param operation - Operation that failed
@@ -725,4 +775,4 @@ declare abstract class DrizzleAdapter {
725
775
  protected handleQueryError(error: unknown, operation: string, table: string): DatabaseError;
726
776
  }
727
777
 
728
- export { DrizzleAdapter as D };
778
+ export { DrizzleAdapter as D, type TransactionCrudDelegator as T, type TransactionCrudForwarders as a };
package/dist/index.cjs CHANGED
@@ -3,6 +3,17 @@
3
3
  var drizzleOrm = require('drizzle-orm');
4
4
 
5
5
  // src/adapter.ts
6
+ function buildDrizzleOrderBy(columns, orderBy) {
7
+ if (!orderBy?.length) return [];
8
+ return orderBy.flatMap((spec) => {
9
+ const col = columns[spec.column];
10
+ if (!col) return [];
11
+ const direction = spec.direction === "desc" ? drizzleOrm.desc(col) : drizzleOrm.asc(col);
12
+ if (spec.nulls === void 0) return [direction];
13
+ const isNull2 = drizzleOrm.sql`${col} is null`;
14
+ return [spec.nulls === "last" ? drizzleOrm.asc(isNull2) : drizzleOrm.desc(isNull2), direction];
15
+ });
16
+ }
6
17
  function buildDrizzleWhere(table, where) {
7
18
  const columns = drizzleOrm.getColumns(table);
8
19
  return processWhereClause(columns, where);
@@ -38,13 +49,26 @@ function processWhereClause(columns, where) {
38
49
  parts.push(drizzleOrm.not(notCondition));
39
50
  }
40
51
  }
41
- if (parts.length === 0) return void 0;
52
+ if (parts.length === 0) {
53
+ if (namesABranch(where)) {
54
+ throw new Error(
55
+ `Where clause produced no condition: ${JSON.stringify(where)}. Every branch resolved to nothing, which would match every row. Pass {} to mean "no filter".`
56
+ );
57
+ }
58
+ return void 0;
59
+ }
42
60
  if (parts.length === 1) return parts[0];
43
61
  return drizzleOrm.and(...parts);
44
62
  }
45
63
  function isWhereCondition(item) {
46
64
  return "column" in item && "op" in item;
47
65
  }
66
+ function namesABranch(where) {
67
+ return Boolean(where.and?.length || where.or?.length || where.not);
68
+ }
69
+ function containsPattern(value) {
70
+ return `%${value.replace(/[!%_]/g, (character) => `!${character}`)}%`;
71
+ }
48
72
  function buildCondition(columns, cond) {
49
73
  const column = columns[cond.column];
50
74
  if (!column) {
@@ -83,12 +107,37 @@ function buildCondition(columns, cond) {
83
107
  case "NOT BETWEEN":
84
108
  return drizzleOrm.notBetween(col, cond.value, cond.valueTo);
85
109
  case "CONTAINS":
86
- return drizzleOrm.like(col, `%${String(cond.value)}%`);
110
+ return drizzleOrm.sql`${col} like ${containsPattern(String(cond.value))} escape '!'`;
87
111
  default:
88
112
  throw new Error(`Unsupported operator: ${cond.op}`);
89
113
  }
90
114
  }
91
115
 
116
+ // src/transaction-forwarders.ts
117
+ function createTransactionForwarders(delegator, txDb) {
118
+ return {
119
+ select: async (table, options) => {
120
+ return delegator.select(table, options, txDb());
121
+ },
122
+ selectOne: async (table, options) => {
123
+ return delegator.selectOne(table, options, txDb());
124
+ },
125
+ update: async (table, data, where, options) => {
126
+ return delegator.update(table, data, where, options, txDb());
127
+ },
128
+ updateCount: async (table, data, where) => {
129
+ return delegator.updateCount(table, data, where, txDb());
130
+ },
131
+ delete: async (table, where, options) => {
132
+ return delegator.delete(table, where, options, txDb());
133
+ },
134
+ upsert: async (table, data, options) => {
135
+ return delegator.upsert(table, data, options, txDb());
136
+ },
137
+ getDrizzle: () => txDb()
138
+ };
139
+ }
140
+
92
141
  // src/types/error.ts
93
142
  function isDatabaseError(error) {
94
143
  return typeof error === "object" && error !== null && "kind" in error && typeof error.kind === "string";
@@ -704,12 +753,10 @@ var DrizzleAdapter = class {
704
753
  }
705
754
  }
706
755
  if (options?.orderBy?.length) {
707
- const columns = drizzleOrm.getColumns(tableObj);
708
- const orderClauses = options.orderBy.map((o) => {
709
- const col = columns[o.column];
710
- if (!col) return void 0;
711
- return o.direction === "desc" ? drizzleOrm.desc(col) : drizzleOrm.asc(col);
712
- }).filter(Boolean);
756
+ const orderClauses = buildDrizzleOrderBy(
757
+ drizzleOrm.getColumns(tableObj),
758
+ options.orderBy
759
+ );
713
760
  if (orderClauses.length) {
714
761
  query = query.orderBy(...orderClauses);
715
762
  }
@@ -1305,11 +1352,11 @@ var DrizzleAdapter = class {
1305
1352
  */
1306
1353
  async tableExists(tableName, schema) {
1307
1354
  try {
1308
- let sql;
1355
+ let sql3;
1309
1356
  const params = [];
1310
1357
  switch (this.dialect) {
1311
1358
  case "postgresql":
1312
- sql = `
1359
+ sql3 = `
1313
1360
  SELECT EXISTS (
1314
1361
  SELECT FROM information_schema.tables
1315
1362
  WHERE table_schema = COALESCE($1, (
@@ -1323,7 +1370,7 @@ var DrizzleAdapter = class {
1323
1370
  params.push(schema ?? null, tableName);
1324
1371
  break;
1325
1372
  case "mysql":
1326
- sql = `
1373
+ sql3 = `
1327
1374
  SELECT COUNT(*) as count
1328
1375
  FROM information_schema.tables
1329
1376
  WHERE table_schema = DATABASE()
@@ -1332,7 +1379,7 @@ var DrizzleAdapter = class {
1332
1379
  params.push(tableName);
1333
1380
  break;
1334
1381
  case "sqlite":
1335
- sql = `
1382
+ sql3 = `
1336
1383
  SELECT COUNT(*) as count
1337
1384
  FROM sqlite_master
1338
1385
  WHERE type = 'table'
@@ -1348,7 +1395,7 @@ var DrizzleAdapter = class {
1348
1395
  );
1349
1396
  }
1350
1397
  const results = await this.executeQuery(
1351
- sql,
1398
+ sql3,
1352
1399
  params
1353
1400
  );
1354
1401
  if (results.length === 0) {
@@ -1380,11 +1427,11 @@ var DrizzleAdapter = class {
1380
1427
  */
1381
1428
  async listTables(schema) {
1382
1429
  try {
1383
- let sql;
1430
+ let sql3;
1384
1431
  const params = [];
1385
1432
  switch (this.dialect) {
1386
1433
  case "postgresql":
1387
- sql = `
1434
+ sql3 = `
1388
1435
  SELECT table_name
1389
1436
  FROM information_schema.tables
1390
1437
  WHERE table_schema = $1
@@ -1394,7 +1441,7 @@ var DrizzleAdapter = class {
1394
1441
  params.push(schema ?? "public");
1395
1442
  break;
1396
1443
  case "mysql":
1397
- sql = `
1444
+ sql3 = `
1398
1445
  SELECT table_name AS table_name
1399
1446
  FROM information_schema.tables
1400
1447
  WHERE table_schema = DATABASE()
@@ -1403,7 +1450,7 @@ var DrizzleAdapter = class {
1403
1450
  `;
1404
1451
  break;
1405
1452
  case "sqlite":
1406
- sql = `
1453
+ sql3 = `
1407
1454
  SELECT name as table_name
1408
1455
  FROM sqlite_master
1409
1456
  WHERE type = 'table'
@@ -1419,7 +1466,7 @@ var DrizzleAdapter = class {
1419
1466
  );
1420
1467
  }
1421
1468
  const results = await this.executeQuery(
1422
- sql,
1469
+ sql3,
1423
1470
  params
1424
1471
  );
1425
1472
  return results.map((row) => row.table_name);
@@ -1475,30 +1522,64 @@ var DrizzleAdapter = class {
1475
1522
  });
1476
1523
  }
1477
1524
  /**
1478
- * Handle query errors and convert to DatabaseError.
1525
+ * Helper to create transaction context CRUD forwarding methods.
1526
+ *
1527
+ * @param txDb - Thunk returning the transaction-bound Drizzle executor
1528
+ * @returns Object providing forwarded CRUD and getDrizzle methods
1529
+ *
1530
+ * @protected
1531
+ */
1532
+ createTransactionForwarders(txDb) {
1533
+ return createTransactionForwarders(this, txDb);
1534
+ }
1535
+ /**
1536
+ * Classify an error into a DatabaseError.
1479
1537
  *
1480
1538
  * @remarks
1481
- * Protected helper for consistent error handling across CRUD operations.
1482
- * Subclasses can override to add dialect-specific error classification.
1539
+ * Subclasses can override this method to add dialect-specific error code classification.
1483
1540
  *
1484
1541
  * @param error - Original error
1485
- * @param operation - Operation that failed
1486
- * @param table - Table name
1542
+ * @param sql - SQL statement that caused the error (optional)
1487
1543
  * @returns DatabaseError instance
1488
1544
  *
1489
1545
  * @protected
1490
1546
  */
1491
- handleQueryError(error, operation, table) {
1547
+ classifyError(error, sql3) {
1492
1548
  if (isDatabaseError(error)) {
1493
1549
  return error;
1494
1550
  }
1495
1551
  const errorMessage = error instanceof Error ? error.message : String(error);
1496
1552
  return this.createDatabaseError(
1497
1553
  "query",
1498
- `${operation} operation failed on table '${table}': ${errorMessage}`,
1554
+ sql3 ? `Query failed: ${errorMessage}` : errorMessage,
1499
1555
  error instanceof Error ? error : void 0
1500
1556
  );
1501
1557
  }
1558
+ /**
1559
+ * Handle query errors and convert to DatabaseError.
1560
+ *
1561
+ * @remarks
1562
+ * Protected helper for consistent error handling across CRUD operations.
1563
+ * Delegates to `classifyError` and attaches operation and table context if not present.
1564
+ * Subclasses override `classifyError` to provide dialect-specific error code classification.
1565
+ *
1566
+ * @param error - Original error
1567
+ * @param operation - Operation that failed
1568
+ * @param table - Table name
1569
+ * @returns DatabaseError instance
1570
+ *
1571
+ * @protected
1572
+ */
1573
+ handleQueryError(error, operation, table) {
1574
+ const dbError = this.classifyError(error);
1575
+ if (!dbError.message.includes(operation)) {
1576
+ dbError.message = `${operation} operation failed on table '${table}': ${dbError.message}`;
1577
+ }
1578
+ if (!dbError.table) {
1579
+ dbError.table = table;
1580
+ }
1581
+ return dbError;
1582
+ }
1502
1583
  };
1503
1584
  var ALLOWED_DEFAULT_SQL_EXPRESSIONS = /* @__PURE__ */ new Set([
1504
1585
  "current_timestamp",