@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/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
- export { D as DrizzleAdapter, T as TransactionCrudDelegator, a as TransactionCrudForwarders } from './adapter-BeMxQXZs.cjs';
1
+ export { D as DrizzleAdapter, T as TransactionCrudDelegator, a as TransactionCrudForwarders } from './adapter-C6ENLDau.cjs';
2
2
  export { T as TableResolver } from './core-CVO7WYDj.cjs';
3
3
  import 'drizzle-orm';
4
- import './migration-DhMuYiIm.cjs';
4
+ import './migration-B6AmjCQ1.cjs';
5
5
  import './schema-BDn8WfSL.cjs';
6
6
  import './error-BrdknH2s.cjs';
7
7
 
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- export { D as DrizzleAdapter, T as TransactionCrudDelegator, a as TransactionCrudForwarders } from './adapter-BRvxUZrS.js';
1
+ export { D as DrizzleAdapter, T as TransactionCrudDelegator, a as TransactionCrudForwarders } from './adapter-D4GM1VAZ.js';
2
2
  export { T as TableResolver } from './core-CVO7WYDj.js';
3
3
  import 'drizzle-orm';
4
- import './migration-BnT96HFp.js';
4
+ import './migration-R06fsTrz.js';
5
5
  import './schema-BIQ0YQZ_.js';
6
6
  import './error-BrdknH2s.js';
7
7
 
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { getColumns, desc, asc, sql, and, or, not, notBetween, between, isNotNull, isNull, notInArray, inArray, ilike, like, lte, gte, lt, gt, ne, eq } from 'drizzle-orm';
1
+ import { getColumns, count, desc, asc, sql, and, or, not, notBetween, between, isNotNull, isNull, notInArray, inArray, ilike, like, lte, gte, lt, gt, ne, eq } from 'drizzle-orm';
2
2
 
3
3
  // src/adapter.ts
4
4
  function buildDrizzleOrderBy(columns, orderBy) {
@@ -567,6 +567,23 @@ var DrizzleAdapter = class {
567
567
  if (names == null || names === "*" || !tableObj || typeof tableObj !== "object") {
568
568
  return void 0;
569
569
  }
570
+ const { projection } = this.resolveColumns(tableObj, names);
571
+ return Object.keys(projection).length ? projection : void 0;
572
+ }
573
+ /**
574
+ * The requested column names split into what this table has and what it does not.
575
+ *
576
+ * One resolution, reported both ways, because two callers need different halves
577
+ * of the same answer: a projection drops what it cannot find, while a distinct
578
+ * count has to REFUSE it. Resolving twice would let the two disagree about what
579
+ * "found" means — the SQL-name alias below is exactly the kind of detail a
580
+ * second implementation gets wrong — and the count would then reject a column
581
+ * the projection happily uses.
582
+ *
583
+ * Both spellings resolve: a caller may name the Drizzle property or the SQL
584
+ * column, and either maps to the same projection key.
585
+ */
586
+ resolveColumns(tableObj, names) {
570
587
  const cols = getColumns(tableObj);
571
588
  const byAnyName = {};
572
589
  for (const [jsName, col] of Object.entries(cols)) {
@@ -575,11 +592,13 @@ var DrizzleAdapter = class {
575
592
  if (typeof sqlName === "string") byAnyName[sqlName] = { jsName, col };
576
593
  }
577
594
  const projection = {};
595
+ const unresolved = [];
578
596
  for (const name of names) {
579
597
  const hit = byAnyName[name];
580
598
  if (hit) projection[hit.jsName] = hit.col;
599
+ else unresolved.push(name);
581
600
  }
582
- return Object.keys(projection).length ? projection : void 0;
601
+ return { projection, unresolved };
583
602
  }
584
603
  // ============================================================
585
604
  // Connection Status (Default implementations, can override)
@@ -806,6 +825,93 @@ var DrizzleAdapter = class {
806
825
  * });
807
826
  * ```
808
827
  */
828
+ /** The registered table object, or a refusal naming what is missing. */
829
+ requireTableObject(table) {
830
+ const tableObj = this.getTableObject(table);
831
+ if (tableObj) return tableObj;
832
+ throw this.createDatabaseError(
833
+ "query",
834
+ `Table "${table}" not found in schema registry. Ensure setTableResolver() has been called during boot.`,
835
+ void 0
836
+ );
837
+ }
838
+ /**
839
+ * The columns a distinct count groups by, or `undefined` for a row count.
840
+ *
841
+ * 🔴 EVERY named column must resolve, not merely one of them. A `distinctOn`
842
+ * naming no column this table has would fall through to a row count, and one
843
+ * naming a valid column beside a misspelled or since-removed column would
844
+ * count distinct over a NARROWER key than the caller asked for. Both answer a
845
+ * different question than the one asked, silently; the second is the worse of
846
+ * the two, because a subset key groups more rows together and so UNDERCOUNTS,
847
+ * which reads as a plausible number rather than as a fault. Refused here,
848
+ * where the mistake was made, rather than surfacing as a wrong figure.
849
+ */
850
+ countProjection(tableObj, table, options) {
851
+ const distinctOn = options?.distinctOn;
852
+ if (!distinctOn?.length) return void 0;
853
+ const { projection, unresolved } = this.resolveColumns(
854
+ tableObj,
855
+ distinctOn
856
+ );
857
+ if (unresolved.length > 0) {
858
+ throw this.createDatabaseError(
859
+ "query",
860
+ `distinctOn names ${unresolved.length === 1 ? "a column" : "columns"} that do not exist on "${table}": ${unresolved.join(", ")}`,
861
+ void 0
862
+ );
863
+ }
864
+ return projection;
865
+ }
866
+ /**
867
+ * `COUNT(*)` over a `SELECT DISTINCT` subquery.
868
+ *
869
+ * Its own function because it is a genuinely different query from the plain
870
+ * count rather than a variation on one, and because building both inline made
871
+ * the public method a chain of decisions the complexity gate objected to
872
+ * before a reader would have.
873
+ */
874
+ async countDistinctRows(db, tableObj, projection, where) {
875
+ const inner = db.selectDistinct(projection).from(tableObj).$dynamic();
876
+ const distinctRows = where ? inner.where(where) : inner;
877
+ const [row] = await db.select({ value: count() }).from(distinctRows.as("nextly_distinct"));
878
+ return Number(row?.value ?? 0);
879
+ }
880
+ /** `COUNT(*)` over the table itself. */
881
+ async countAllRows(db, tableObj, where) {
882
+ const base = db.select({ value: count() }).from(tableObj).$dynamic();
883
+ const [row] = await (where ? base.where(where) : base);
884
+ return Number(row?.value ?? 0);
885
+ }
886
+ /**
887
+ * How many rows match, or how many DISTINCT combinations of some columns do.
888
+ *
889
+ * The data layer had no count at all: collection totals go through
890
+ * `countEntries`, an access-controlled path built for collection tables, and
891
+ * nothing could count a system table. A caller wanting one selected the rows
892
+ * and measured the array, which transfers every row to learn a number and
893
+ * cannot be bounded without making the number wrong.
894
+ *
895
+ * 🔴 `distinctOn` compiles to `COUNT(*)` over a `SELECT DISTINCT` SUBQUERY,
896
+ * never to `COUNT(DISTINCT a, b)`. The inline form is not portable and fails
897
+ * in the direction that is hardest to notice -- MySQL accepts it, PostgreSQL
898
+ * needs a row constructor, and SQLite rejects it outright with "wrong number
899
+ * of arguments to function count()" -- so a query written against one engine
900
+ * is a syntax error on another. The subquery is the single form all three
901
+ * accept, and building it here rather than at each call site is what keeps
902
+ * the answer identical per dialect.
903
+ */
904
+ async count(table, options, executor) {
905
+ const tableObj = this.requireTableObject(table);
906
+ try {
907
+ const db = executor ?? this.getDrizzle();
908
+ const where = options?.where ? buildDrizzleWhere(tableObj, options.where) : void 0;
909
+ const projection = this.countProjection(tableObj, table, options);
910
+ return projection ? await this.countDistinctRows(db, tableObj, projection, where) : await this.countAllRows(db, tableObj, where);
911
+ } catch (error) {
912
+ throw this.handleQueryError(error, "count", table);
913
+ }
914
+ }
809
915
  async selectOne(table, options, executor) {
810
916
  const results = await this.select(
811
917
  table,