@nextlyhq/adapter-drizzle 0.0.2-alpha.62 → 0.0.2-alpha.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -1
- package/dist/{adapter-BeMxQXZs.d.cts → adapter-C6ENLDau.d.cts} +63 -1
- package/dist/{adapter-BRvxUZrS.d.ts → adapter-D4GM1VAZ.d.ts} +63 -1
- package/dist/index.cjs +107 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +108 -2
- package/dist/index.mjs.map +1 -1
- package/dist/{migration-DhMuYiIm.d.cts → migration-B6AmjCQ1.d.cts} +25 -1
- package/dist/{migration-BnT96HFp.d.ts → migration-R06fsTrz.d.ts} +25 -1
- package/dist/migrations.d.cts +3 -3
- package/dist/migrations.d.ts +3 -3
- package/dist/types/index.d.cts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -2,7 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
Internal Drizzle ORM utilities for Nextly's database adapters.
|
|
4
4
|
|
|
5
|
-
>
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://www.npmjs.com/package/@nextlyhq/adapter-drizzle"><img alt="npm" src="https://img.shields.io/npm/v/@nextlyhq%2Fadapter-drizzle?style=flat-square&label=npm&color=cb3837" /></a>
|
|
7
|
+
<a href="https://github.com/nextlyhq/nextly/blob/main/LICENSE.md"><img alt="License" src="https://img.shields.io/github/license/nextlyhq/nextly?style=flat-square&color=blue" /></a>
|
|
8
|
+
<a href="https://nextlyhq.com/docs"><img alt="Status" src="https://img.shields.io/badge/status-alpha-orange?style=flat-square" /></a>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
> [!IMPORTANT]
|
|
12
|
+
> Nextly is in alpha. APIs may change before 1.0. Pin exact versions in production.
|
|
13
|
+
|
|
14
|
+
This package is part of Nextly's internals. It is installed automatically as a dependency of [`nextly`](../nextly). Choose [`@nextlyhq/adapter-postgres`](../adapter-postgres), [`@nextlyhq/adapter-mysql`](../adapter-mysql), or [`@nextlyhq/adapter-sqlite`](../adapter-sqlite) for your project.
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
You do not install this directly. It arrives as a dependency of [`nextly`](../nextly)
|
|
19
|
+
and of each database adapter. Install the adapter for your database instead:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pnpm add @nextlyhq/adapter-postgres pg
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Related packages
|
|
26
|
+
|
|
27
|
+
- [`@nextlyhq/adapter-postgres`](../adapter-postgres) — recommended for production
|
|
28
|
+
- [`@nextlyhq/adapter-mysql`](../adapter-mysql)
|
|
29
|
+
- [`@nextlyhq/adapter-sqlite`](../adapter-sqlite) — local demos
|
|
6
30
|
|
|
7
31
|
## License
|
|
8
32
|
|
|
@@ -1,5 +1,5 @@
|
|
|
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-
|
|
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, C as CountOptions, I as InsertOptions, a as Migration, d as MigrationResult } from './migration-B6AmjCQ1.cjs';
|
|
3
3
|
import { S as SupportedDialect, a as SqlParam, T as TableResolver } from './core-CVO7WYDj.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';
|
|
@@ -320,6 +320,23 @@ declare abstract class DrizzleAdapter {
|
|
|
320
320
|
* for `"*"` or when nothing resolves, so callers fall back to all columns.
|
|
321
321
|
*/
|
|
322
322
|
protected buildColumnProjection(tableObj: unknown, names: string[] | "*" | undefined): Record<string, unknown> | undefined;
|
|
323
|
+
/**
|
|
324
|
+
* The requested column names split into what this table has and what it does not.
|
|
325
|
+
*
|
|
326
|
+
* One resolution, reported both ways, because two callers need different halves
|
|
327
|
+
* of the same answer: a projection drops what it cannot find, while a distinct
|
|
328
|
+
* count has to REFUSE it. Resolving twice would let the two disagree about what
|
|
329
|
+
* "found" means — the SQL-name alias below is exactly the kind of detail a
|
|
330
|
+
* second implementation gets wrong — and the count would then reject a column
|
|
331
|
+
* the projection happily uses.
|
|
332
|
+
*
|
|
333
|
+
* Both spellings resolve: a caller may name the Drizzle property or the SQL
|
|
334
|
+
* column, and either maps to the same projection key.
|
|
335
|
+
*/
|
|
336
|
+
protected resolveColumns(tableObj: unknown, names: readonly string[]): {
|
|
337
|
+
projection: Record<string, unknown>;
|
|
338
|
+
unresolved: string[];
|
|
339
|
+
};
|
|
323
340
|
/**
|
|
324
341
|
* Check if the adapter is currently connected.
|
|
325
342
|
*
|
|
@@ -453,6 +470,51 @@ declare abstract class DrizzleAdapter {
|
|
|
453
470
|
* });
|
|
454
471
|
* ```
|
|
455
472
|
*/
|
|
473
|
+
/** The registered table object, or a refusal naming what is missing. */
|
|
474
|
+
private requireTableObject;
|
|
475
|
+
/**
|
|
476
|
+
* The columns a distinct count groups by, or `undefined` for a row count.
|
|
477
|
+
*
|
|
478
|
+
* 🔴 EVERY named column must resolve, not merely one of them. A `distinctOn`
|
|
479
|
+
* naming no column this table has would fall through to a row count, and one
|
|
480
|
+
* naming a valid column beside a misspelled or since-removed column would
|
|
481
|
+
* count distinct over a NARROWER key than the caller asked for. Both answer a
|
|
482
|
+
* different question than the one asked, silently; the second is the worse of
|
|
483
|
+
* the two, because a subset key groups more rows together and so UNDERCOUNTS,
|
|
484
|
+
* which reads as a plausible number rather than as a fault. Refused here,
|
|
485
|
+
* where the mistake was made, rather than surfacing as a wrong figure.
|
|
486
|
+
*/
|
|
487
|
+
private countProjection;
|
|
488
|
+
/**
|
|
489
|
+
* `COUNT(*)` over a `SELECT DISTINCT` subquery.
|
|
490
|
+
*
|
|
491
|
+
* Its own function because it is a genuinely different query from the plain
|
|
492
|
+
* count rather than a variation on one, and because building both inline made
|
|
493
|
+
* the public method a chain of decisions the complexity gate objected to
|
|
494
|
+
* before a reader would have.
|
|
495
|
+
*/
|
|
496
|
+
private countDistinctRows;
|
|
497
|
+
/** `COUNT(*)` over the table itself. */
|
|
498
|
+
private countAllRows;
|
|
499
|
+
/**
|
|
500
|
+
* How many rows match, or how many DISTINCT combinations of some columns do.
|
|
501
|
+
*
|
|
502
|
+
* The data layer had no count at all: collection totals go through
|
|
503
|
+
* `countEntries`, an access-controlled path built for collection tables, and
|
|
504
|
+
* nothing could count a system table. A caller wanting one selected the rows
|
|
505
|
+
* and measured the array, which transfers every row to learn a number and
|
|
506
|
+
* cannot be bounded without making the number wrong.
|
|
507
|
+
*
|
|
508
|
+
* 🔴 `distinctOn` compiles to `COUNT(*)` over a `SELECT DISTINCT` SUBQUERY,
|
|
509
|
+
* never to `COUNT(DISTINCT a, b)`. The inline form is not portable and fails
|
|
510
|
+
* in the direction that is hardest to notice -- MySQL accepts it, PostgreSQL
|
|
511
|
+
* needs a row constructor, and SQLite rejects it outright with "wrong number
|
|
512
|
+
* of arguments to function count()" -- so a query written against one engine
|
|
513
|
+
* is a syntax error on another. The subquery is the single form all three
|
|
514
|
+
* accept, and building it here rather than at each call site is what keeps
|
|
515
|
+
* the answer identical per dialect.
|
|
516
|
+
*/
|
|
517
|
+
count(table: string, options?: CountOptions, executor?: unknown): Promise<number>;
|
|
456
518
|
selectOne<T = unknown>(table: string, options?: SelectOptions, executor?: unknown): Promise<T | null>;
|
|
457
519
|
/**
|
|
458
520
|
* Insert a single record into a table.
|
|
@@ -1,5 +1,5 @@
|
|
|
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-
|
|
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, C as CountOptions, I as InsertOptions, a as Migration, d as MigrationResult } from './migration-R06fsTrz.js';
|
|
3
3
|
import { S as SupportedDialect, a as SqlParam, T as TableResolver } from './core-CVO7WYDj.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';
|
|
@@ -320,6 +320,23 @@ declare abstract class DrizzleAdapter {
|
|
|
320
320
|
* for `"*"` or when nothing resolves, so callers fall back to all columns.
|
|
321
321
|
*/
|
|
322
322
|
protected buildColumnProjection(tableObj: unknown, names: string[] | "*" | undefined): Record<string, unknown> | undefined;
|
|
323
|
+
/**
|
|
324
|
+
* The requested column names split into what this table has and what it does not.
|
|
325
|
+
*
|
|
326
|
+
* One resolution, reported both ways, because two callers need different halves
|
|
327
|
+
* of the same answer: a projection drops what it cannot find, while a distinct
|
|
328
|
+
* count has to REFUSE it. Resolving twice would let the two disagree about what
|
|
329
|
+
* "found" means — the SQL-name alias below is exactly the kind of detail a
|
|
330
|
+
* second implementation gets wrong — and the count would then reject a column
|
|
331
|
+
* the projection happily uses.
|
|
332
|
+
*
|
|
333
|
+
* Both spellings resolve: a caller may name the Drizzle property or the SQL
|
|
334
|
+
* column, and either maps to the same projection key.
|
|
335
|
+
*/
|
|
336
|
+
protected resolveColumns(tableObj: unknown, names: readonly string[]): {
|
|
337
|
+
projection: Record<string, unknown>;
|
|
338
|
+
unresolved: string[];
|
|
339
|
+
};
|
|
323
340
|
/**
|
|
324
341
|
* Check if the adapter is currently connected.
|
|
325
342
|
*
|
|
@@ -453,6 +470,51 @@ declare abstract class DrizzleAdapter {
|
|
|
453
470
|
* });
|
|
454
471
|
* ```
|
|
455
472
|
*/
|
|
473
|
+
/** The registered table object, or a refusal naming what is missing. */
|
|
474
|
+
private requireTableObject;
|
|
475
|
+
/**
|
|
476
|
+
* The columns a distinct count groups by, or `undefined` for a row count.
|
|
477
|
+
*
|
|
478
|
+
* 🔴 EVERY named column must resolve, not merely one of them. A `distinctOn`
|
|
479
|
+
* naming no column this table has would fall through to a row count, and one
|
|
480
|
+
* naming a valid column beside a misspelled or since-removed column would
|
|
481
|
+
* count distinct over a NARROWER key than the caller asked for. Both answer a
|
|
482
|
+
* different question than the one asked, silently; the second is the worse of
|
|
483
|
+
* the two, because a subset key groups more rows together and so UNDERCOUNTS,
|
|
484
|
+
* which reads as a plausible number rather than as a fault. Refused here,
|
|
485
|
+
* where the mistake was made, rather than surfacing as a wrong figure.
|
|
486
|
+
*/
|
|
487
|
+
private countProjection;
|
|
488
|
+
/**
|
|
489
|
+
* `COUNT(*)` over a `SELECT DISTINCT` subquery.
|
|
490
|
+
*
|
|
491
|
+
* Its own function because it is a genuinely different query from the plain
|
|
492
|
+
* count rather than a variation on one, and because building both inline made
|
|
493
|
+
* the public method a chain of decisions the complexity gate objected to
|
|
494
|
+
* before a reader would have.
|
|
495
|
+
*/
|
|
496
|
+
private countDistinctRows;
|
|
497
|
+
/** `COUNT(*)` over the table itself. */
|
|
498
|
+
private countAllRows;
|
|
499
|
+
/**
|
|
500
|
+
* How many rows match, or how many DISTINCT combinations of some columns do.
|
|
501
|
+
*
|
|
502
|
+
* The data layer had no count at all: collection totals go through
|
|
503
|
+
* `countEntries`, an access-controlled path built for collection tables, and
|
|
504
|
+
* nothing could count a system table. A caller wanting one selected the rows
|
|
505
|
+
* and measured the array, which transfers every row to learn a number and
|
|
506
|
+
* cannot be bounded without making the number wrong.
|
|
507
|
+
*
|
|
508
|
+
* 🔴 `distinctOn` compiles to `COUNT(*)` over a `SELECT DISTINCT` SUBQUERY,
|
|
509
|
+
* never to `COUNT(DISTINCT a, b)`. The inline form is not portable and fails
|
|
510
|
+
* in the direction that is hardest to notice -- MySQL accepts it, PostgreSQL
|
|
511
|
+
* needs a row constructor, and SQLite rejects it outright with "wrong number
|
|
512
|
+
* of arguments to function count()" -- so a query written against one engine
|
|
513
|
+
* is a syntax error on another. The subquery is the single form all three
|
|
514
|
+
* accept, and building it here rather than at each call site is what keeps
|
|
515
|
+
* the answer identical per dialect.
|
|
516
|
+
*/
|
|
517
|
+
count(table: string, options?: CountOptions, executor?: unknown): Promise<number>;
|
|
456
518
|
selectOne<T = unknown>(table: string, options?: SelectOptions, executor?: unknown): Promise<T | null>;
|
|
457
519
|
/**
|
|
458
520
|
* Insert a single record into a table.
|
package/dist/index.cjs
CHANGED
|
@@ -569,6 +569,23 @@ var DrizzleAdapter = class {
|
|
|
569
569
|
if (names == null || names === "*" || !tableObj || typeof tableObj !== "object") {
|
|
570
570
|
return void 0;
|
|
571
571
|
}
|
|
572
|
+
const { projection } = this.resolveColumns(tableObj, names);
|
|
573
|
+
return Object.keys(projection).length ? projection : void 0;
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* The requested column names split into what this table has and what it does not.
|
|
577
|
+
*
|
|
578
|
+
* One resolution, reported both ways, because two callers need different halves
|
|
579
|
+
* of the same answer: a projection drops what it cannot find, while a distinct
|
|
580
|
+
* count has to REFUSE it. Resolving twice would let the two disagree about what
|
|
581
|
+
* "found" means — the SQL-name alias below is exactly the kind of detail a
|
|
582
|
+
* second implementation gets wrong — and the count would then reject a column
|
|
583
|
+
* the projection happily uses.
|
|
584
|
+
*
|
|
585
|
+
* Both spellings resolve: a caller may name the Drizzle property or the SQL
|
|
586
|
+
* column, and either maps to the same projection key.
|
|
587
|
+
*/
|
|
588
|
+
resolveColumns(tableObj, names) {
|
|
572
589
|
const cols = drizzleOrm.getColumns(tableObj);
|
|
573
590
|
const byAnyName = {};
|
|
574
591
|
for (const [jsName, col] of Object.entries(cols)) {
|
|
@@ -577,11 +594,13 @@ var DrizzleAdapter = class {
|
|
|
577
594
|
if (typeof sqlName === "string") byAnyName[sqlName] = { jsName, col };
|
|
578
595
|
}
|
|
579
596
|
const projection = {};
|
|
597
|
+
const unresolved = [];
|
|
580
598
|
for (const name of names) {
|
|
581
599
|
const hit = byAnyName[name];
|
|
582
600
|
if (hit) projection[hit.jsName] = hit.col;
|
|
601
|
+
else unresolved.push(name);
|
|
583
602
|
}
|
|
584
|
-
return
|
|
603
|
+
return { projection, unresolved };
|
|
585
604
|
}
|
|
586
605
|
// ============================================================
|
|
587
606
|
// Connection Status (Default implementations, can override)
|
|
@@ -808,6 +827,93 @@ var DrizzleAdapter = class {
|
|
|
808
827
|
* });
|
|
809
828
|
* ```
|
|
810
829
|
*/
|
|
830
|
+
/** The registered table object, or a refusal naming what is missing. */
|
|
831
|
+
requireTableObject(table) {
|
|
832
|
+
const tableObj = this.getTableObject(table);
|
|
833
|
+
if (tableObj) return tableObj;
|
|
834
|
+
throw this.createDatabaseError(
|
|
835
|
+
"query",
|
|
836
|
+
`Table "${table}" not found in schema registry. Ensure setTableResolver() has been called during boot.`,
|
|
837
|
+
void 0
|
|
838
|
+
);
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* The columns a distinct count groups by, or `undefined` for a row count.
|
|
842
|
+
*
|
|
843
|
+
* 🔴 EVERY named column must resolve, not merely one of them. A `distinctOn`
|
|
844
|
+
* naming no column this table has would fall through to a row count, and one
|
|
845
|
+
* naming a valid column beside a misspelled or since-removed column would
|
|
846
|
+
* count distinct over a NARROWER key than the caller asked for. Both answer a
|
|
847
|
+
* different question than the one asked, silently; the second is the worse of
|
|
848
|
+
* the two, because a subset key groups more rows together and so UNDERCOUNTS,
|
|
849
|
+
* which reads as a plausible number rather than as a fault. Refused here,
|
|
850
|
+
* where the mistake was made, rather than surfacing as a wrong figure.
|
|
851
|
+
*/
|
|
852
|
+
countProjection(tableObj, table, options) {
|
|
853
|
+
const distinctOn = options?.distinctOn;
|
|
854
|
+
if (!distinctOn?.length) return void 0;
|
|
855
|
+
const { projection, unresolved } = this.resolveColumns(
|
|
856
|
+
tableObj,
|
|
857
|
+
distinctOn
|
|
858
|
+
);
|
|
859
|
+
if (unresolved.length > 0) {
|
|
860
|
+
throw this.createDatabaseError(
|
|
861
|
+
"query",
|
|
862
|
+
`distinctOn names ${unresolved.length === 1 ? "a column" : "columns"} that do not exist on "${table}": ${unresolved.join(", ")}`,
|
|
863
|
+
void 0
|
|
864
|
+
);
|
|
865
|
+
}
|
|
866
|
+
return projection;
|
|
867
|
+
}
|
|
868
|
+
/**
|
|
869
|
+
* `COUNT(*)` over a `SELECT DISTINCT` subquery.
|
|
870
|
+
*
|
|
871
|
+
* Its own function because it is a genuinely different query from the plain
|
|
872
|
+
* count rather than a variation on one, and because building both inline made
|
|
873
|
+
* the public method a chain of decisions the complexity gate objected to
|
|
874
|
+
* before a reader would have.
|
|
875
|
+
*/
|
|
876
|
+
async countDistinctRows(db, tableObj, projection, where) {
|
|
877
|
+
const inner = db.selectDistinct(projection).from(tableObj).$dynamic();
|
|
878
|
+
const distinctRows = where ? inner.where(where) : inner;
|
|
879
|
+
const [row] = await db.select({ value: drizzleOrm.count() }).from(distinctRows.as("nextly_distinct"));
|
|
880
|
+
return Number(row?.value ?? 0);
|
|
881
|
+
}
|
|
882
|
+
/** `COUNT(*)` over the table itself. */
|
|
883
|
+
async countAllRows(db, tableObj, where) {
|
|
884
|
+
const base = db.select({ value: drizzleOrm.count() }).from(tableObj).$dynamic();
|
|
885
|
+
const [row] = await (where ? base.where(where) : base);
|
|
886
|
+
return Number(row?.value ?? 0);
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* How many rows match, or how many DISTINCT combinations of some columns do.
|
|
890
|
+
*
|
|
891
|
+
* The data layer had no count at all: collection totals go through
|
|
892
|
+
* `countEntries`, an access-controlled path built for collection tables, and
|
|
893
|
+
* nothing could count a system table. A caller wanting one selected the rows
|
|
894
|
+
* and measured the array, which transfers every row to learn a number and
|
|
895
|
+
* cannot be bounded without making the number wrong.
|
|
896
|
+
*
|
|
897
|
+
* 🔴 `distinctOn` compiles to `COUNT(*)` over a `SELECT DISTINCT` SUBQUERY,
|
|
898
|
+
* never to `COUNT(DISTINCT a, b)`. The inline form is not portable and fails
|
|
899
|
+
* in the direction that is hardest to notice -- MySQL accepts it, PostgreSQL
|
|
900
|
+
* needs a row constructor, and SQLite rejects it outright with "wrong number
|
|
901
|
+
* of arguments to function count()" -- so a query written against one engine
|
|
902
|
+
* is a syntax error on another. The subquery is the single form all three
|
|
903
|
+
* accept, and building it here rather than at each call site is what keeps
|
|
904
|
+
* the answer identical per dialect.
|
|
905
|
+
*/
|
|
906
|
+
async count(table, options, executor) {
|
|
907
|
+
const tableObj = this.requireTableObject(table);
|
|
908
|
+
try {
|
|
909
|
+
const db = executor ?? this.getDrizzle();
|
|
910
|
+
const where = options?.where ? buildDrizzleWhere(tableObj, options.where) : void 0;
|
|
911
|
+
const projection = this.countProjection(tableObj, table, options);
|
|
912
|
+
return projection ? await this.countDistinctRows(db, tableObj, projection, where) : await this.countAllRows(db, tableObj, where);
|
|
913
|
+
} catch (error) {
|
|
914
|
+
throw this.handleQueryError(error, "count", table);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
811
917
|
async selectOne(table, options, executor) {
|
|
812
918
|
const results = await this.select(
|
|
813
919
|
table,
|