uql-orm 0.53.0 → 0.55.0

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 (158) hide show
  1. package/README.md +2 -2
  2. package/dist/browser/uql-browser.min.js.map +2 -2
  3. package/dist/bunSql/bunSql.util.d.ts +3 -14
  4. package/dist/bunSql/bunSql.util.js +33 -56
  5. package/dist/bunSql/bunSqlQuerier.d.ts +3 -6
  6. package/dist/bunSql/bunSqlQuerier.js +7 -13
  7. package/dist/bunSql/bunSqlQuerierPool.d.ts +10 -5
  8. package/dist/bunSql/bunSqlQuerierPool.js +25 -10
  9. package/dist/cockroachdb/cockroachDialect.d.ts +2 -5
  10. package/dist/cockroachdb/cockroachDialect.js +2 -5
  11. package/dist/cockroachdb/crdbQuerierPool.d.ts +1 -3
  12. package/dist/cockroachdb/crdbQuerierPool.js +0 -4
  13. package/dist/cockroachdb/index.d.ts +0 -1
  14. package/dist/cockroachdb/index.js +0 -1
  15. package/dist/d1/d1SqliteDialect.d.ts +5 -0
  16. package/dist/d1/d1SqliteDialect.js +7 -0
  17. package/dist/dialect/abstractSqlDialect.d.ts +15 -9
  18. package/dist/dialect/abstractSqlDialect.js +47 -54
  19. package/dist/dialect/hydrateColumn.js +2 -2
  20. package/dist/dialect/mergeSqlDialect.d.ts +2 -2
  21. package/dist/dialect/mergeSqlDialect.js +0 -4
  22. package/dist/dialect/mysqlLikeSqlDialect.d.ts +0 -3
  23. package/dist/dialect/mysqlLikeSqlDialect.js +0 -3
  24. package/dist/dialect/pgLikeSqlDialect.d.ts +5 -0
  25. package/dist/dialect/pgLikeSqlDialect.js +12 -2
  26. package/dist/entity/decorator/members.d.ts +3 -10
  27. package/dist/entity/index.d.ts +1 -1
  28. package/dist/entity/index.js +1 -1
  29. package/dist/entity/metadata/definition.d.ts +3 -1
  30. package/dist/entity/metadata/definition.js +8 -4
  31. package/dist/libsql/index.d.ts +0 -1
  32. package/dist/libsql/index.js +0 -1
  33. package/dist/libsql/libsqlQuerierPool.d.ts +3 -5
  34. package/dist/libsql/libsqlQuerierPool.js +2 -5
  35. package/dist/maria/mariadbQuerier.d.ts +0 -3
  36. package/dist/maria/mariadbQuerier.js +6 -7
  37. package/dist/maria/mariadbQuerierPool.js +4 -7
  38. package/dist/migrate/builder/migrationBuilder.js +0 -4
  39. package/dist/migrate/ddl/index.d.ts +3 -3
  40. package/dist/migrate/ddl/index.js +3 -3
  41. package/dist/migrate/migrator.d.ts +3 -7
  42. package/dist/migrate/migrator.js +3 -7
  43. package/dist/migrate/schemaGenerator.d.ts +0 -13
  44. package/dist/migrate/schemaGenerator.js +0 -13
  45. package/dist/migrate/storage/databaseStorage.d.ts +2 -2
  46. package/dist/migrate/storage/databaseStorage.js +2 -2
  47. package/dist/mongo/index.d.ts +0 -1
  48. package/dist/mongo/index.js +0 -1
  49. package/dist/mongo/mongoDialect.d.ts +0 -1
  50. package/dist/mongo/mongoDialect.js +3 -14
  51. package/dist/mongo/mongodbQuerier.d.ts +3 -5
  52. package/dist/mongo/mongodbQuerier.js +23 -23
  53. package/dist/mongo/mongodbQuerierPool.d.ts +2 -2
  54. package/dist/mongo/mongodbQuerierPool.js +2 -2
  55. package/dist/mssql/mssqlDialect.d.ts +5 -5
  56. package/dist/mssql/mssqlDialect.js +11 -8
  57. package/dist/mssql/mssqlQuerier.d.ts +13 -6
  58. package/dist/mssql/mssqlQuerier.js +30 -75
  59. package/dist/mssql/mssqlQuerierPool.js +2 -0
  60. package/dist/mssql/mssqlWireTypes.d.ts +3 -4
  61. package/dist/mssql/mssqlWireTypes.js +5 -8
  62. package/dist/mysql/index.d.ts +0 -1
  63. package/dist/mysql/index.js +0 -1
  64. package/dist/mysql/mysql2Querier.d.ts +1 -4
  65. package/dist/mysql/mysql2Querier.js +0 -3
  66. package/dist/mysql/mysql2QuerierPool.d.ts +2 -2
  67. package/dist/mysql/mysql2QuerierPool.js +5 -3
  68. package/dist/neon/index.d.ts +0 -2
  69. package/dist/neon/index.js +0 -2
  70. package/dist/neon/neonQuerierPool.d.ts +2 -4
  71. package/dist/neon/neonQuerierPool.js +2 -6
  72. package/dist/pglite/index.d.ts +0 -1
  73. package/dist/pglite/index.js +0 -1
  74. package/dist/pglite/pgliteQuerier.d.ts +3 -3
  75. package/dist/pglite/pgliteQuerier.js +1 -1
  76. package/dist/pglite/pgliteQuerierPool.d.ts +7 -2
  77. package/dist/pglite/pgliteQuerierPool.js +16 -6
  78. package/dist/postgres/abstractPgQuerierPool.d.ts +8 -12
  79. package/dist/postgres/abstractPgQuerierPool.js +8 -6
  80. package/dist/postgres/index.d.ts +0 -1
  81. package/dist/postgres/index.js +0 -1
  82. package/dist/postgres/pgNumericTypes.d.ts +5 -5
  83. package/dist/postgres/pgNumericTypes.js +11 -7
  84. package/dist/postgres/pgQuerier.d.ts +22 -4
  85. package/dist/postgres/pgQuerier.js +29 -2
  86. package/dist/postgres/pgQuerierPool.d.ts +2 -4
  87. package/dist/postgres/pgQuerierPool.js +2 -6
  88. package/dist/postgres/postgresDialect.d.ts +5 -5
  89. package/dist/postgres/postgresDialect.js +5 -5
  90. package/dist/postgres/postgresWireDriverCapabilities.d.ts +2 -2
  91. package/dist/postgres/postgresWireDriverCapabilities.js +2 -2
  92. package/dist/querier/abstractPoolQuerier.d.ts +1 -1
  93. package/dist/querier/abstractPoolQuerier.js +1 -1
  94. package/dist/querier/abstractQuerier.d.ts +17 -22
  95. package/dist/querier/abstractQuerier.js +80 -57
  96. package/dist/querier/abstractSqlQuerier.d.ts +20 -13
  97. package/dist/querier/abstractSqlQuerier.js +96 -100
  98. package/dist/schema/schemaASTBuilder.js +7 -7
  99. package/dist/sqlite/hranaQuerier.d.ts +6 -8
  100. package/dist/sqlite/hranaQuerier.js +13 -30
  101. package/dist/sqlite/hranaQuerierPool.d.ts +3 -4
  102. package/dist/sqlite/hranaQuerierPool.js +2 -1
  103. package/dist/sqlite/localSqliteQuerierPool.d.ts +3 -3
  104. package/dist/sqlite/localSqliteQuerierPool.js +4 -2
  105. package/dist/sqlite/nodeSqliteAdapter.d.ts +0 -1
  106. package/dist/sqlite/nodeSqliteQuerierPool.js +0 -2
  107. package/dist/sqlite/sqlitePragmas.d.ts +12 -0
  108. package/dist/sqlite/sqlitePragmas.js +15 -0
  109. package/dist/sqlite/sqliteQuerierPool.d.ts +0 -5
  110. package/dist/sqlite/sqliteQuerierPool.js +2 -13
  111. package/dist/turso/index.d.ts +0 -1
  112. package/dist/turso/index.js +0 -1
  113. package/dist/turso/tursoLocalQuerier.d.ts +0 -1
  114. package/dist/turso/tursoLocalQuerierPool.js +2 -2
  115. package/dist/turso/tursoQuerierPool.d.ts +1 -3
  116. package/dist/turso/tursoQuerierPool.js +0 -4
  117. package/dist/type/dialect.d.ts +1 -1
  118. package/dist/type/entity.d.ts +6 -11
  119. package/dist/type/migration.d.ts +0 -3
  120. package/dist/type/query.d.ts +12 -12
  121. package/dist/type/query.js +0 -6
  122. package/dist/type/universalQuerier.d.ts +3 -3
  123. package/dist/util/dialect.util.d.ts +4 -3
  124. package/dist/util/dialect.util.js +2 -1
  125. package/dist/util/field.util.d.ts +4 -16
  126. package/dist/util/field.util.js +6 -19
  127. package/dist/util/fieldOption.util.d.ts +1 -4
  128. package/dist/util/fieldOption.util.js +0 -2
  129. package/dist/util/logger.d.ts +10 -11
  130. package/dist/util/logger.js +21 -11
  131. package/dist/util/raw.d.ts +3 -10
  132. package/dist/util/raw.js +3 -3
  133. package/dist/util/sql.util.js +2 -2
  134. package/dist/util/sqlLiteral.js +3 -8
  135. package/dist/util/string.util.js +2 -6
  136. package/dist/util/wideNumber.d.ts +14 -0
  137. package/dist/util/wideNumber.js +24 -0
  138. package/package.json +1 -1
  139. package/dist/cockroachdb/crdbQuerier.d.ts +0 -8
  140. package/dist/cockroachdb/crdbQuerier.js +0 -6
  141. package/dist/libsql/libsqlQuerier.d.ts +0 -10
  142. package/dist/libsql/libsqlQuerier.js +0 -10
  143. package/dist/mongo/mongodbNativeDialect.d.ts +0 -9
  144. package/dist/mongo/mongodbNativeDialect.js +0 -9
  145. package/dist/mysql/mysql2Dialect.d.ts +0 -9
  146. package/dist/mysql/mysql2Dialect.js +0 -9
  147. package/dist/neon/neonDialect.d.ts +0 -10
  148. package/dist/neon/neonDialect.js +0 -10
  149. package/dist/neon/neonQuerier.d.ts +0 -5
  150. package/dist/neon/neonQuerier.js +0 -3
  151. package/dist/pglite/pgliteDialect.d.ts +0 -14
  152. package/dist/pglite/pgliteDialect.js +0 -14
  153. package/dist/postgres/abstractPgQuerier.d.ts +0 -24
  154. package/dist/postgres/abstractPgQuerier.js +0 -32
  155. package/dist/postgres/pgDialect.d.ts +0 -10
  156. package/dist/postgres/pgDialect.js +0 -10
  157. package/dist/turso/tursoQuerier.d.ts +0 -10
  158. package/dist/turso/tursoQuerier.js +0 -10
@@ -8,9 +8,6 @@ import { decodeWireTypes } from './mssqlWireTypes.js';
8
8
  */
9
9
  export class MsSqlQuerier extends AbstractPoolQuerier {
10
10
  #transaction;
11
- constructor(connect, dialect, extra) {
12
- super(dialect, connect, extra);
13
- }
14
11
  /**
15
12
  * Values bind by name, `@p1` upward, matching {@link MsSqlDialect.placeholder}. `tedious` infers
16
13
  * a type from the JS value, which is why a `Date` and a `Uint8Array` reach it unconverted - the
@@ -26,9 +23,6 @@ export class MsSqlQuerier extends AbstractPoolQuerier {
26
23
  return decodeWireTypes(res.recordset, res.recordset?.columns);
27
24
  }
28
25
  async internalRun(query, values) {
29
- if (await this.#driveTransaction(query)) {
30
- return { changes: 0 };
31
- }
32
26
  const res = (await this.#request(values).query(query));
33
27
  return this.buildUpdateResult({
34
28
  // `rowsAffected` carries one entry per statement, and a `MERGE` upsert emits its `OUTPUT`
@@ -38,57 +32,24 @@ export class MsSqlQuerier extends AbstractPoolQuerier {
38
32
  });
39
33
  }
40
34
  /**
41
- * `tedious` streams by event, not by async iterator, so rows are handed over as they arrive rather
42
- * than collected first - buffering the whole result set would make this `all()` with extra steps.
43
- * The `query` promise is awaited at the end so its rejection surfaces rather than going unhandled.
35
+ * The driver's own stream over the request, which pauses the request while the loop is behind, so
36
+ * rows arrive only as fast as they are read. A failure the driver reports through the promise alone
37
+ * would leave the loop waiting for rows, so it ends the stream instead.
44
38
  */
45
39
  async *internalStream(query, values) {
46
40
  const request = this.#request(values);
47
- request.stream = true;
48
- let pending = [];
49
- let done = false;
50
- let failure;
51
- let wake;
52
- const arrived = () => {
53
- wake?.();
54
- wake = undefined;
55
- };
56
- request.on('row', (row) => {
57
- pending.push(row);
58
- arrived();
59
- });
60
- request.on('error', (err) => {
61
- failure ??= err;
62
- arrived();
63
- });
64
- request.on('done', () => {
65
- done = true;
66
- arrived();
67
- });
41
+ const rows = request.toReadableStream();
68
42
  const completed = request.query(query).catch((err) => {
69
- failure ??= err instanceof Error ? err : new Error(String(err));
70
- arrived();
43
+ rows.destroy(err instanceof Error ? err : new Error(String(err)));
71
44
  });
72
45
  try {
73
- while (true) {
74
- if (pending.length) {
75
- const batch = pending;
76
- pending = [];
77
- yield* batch;
78
- continue;
79
- }
80
- if (failure)
81
- throw failure;
82
- if (done)
83
- return;
84
- await new Promise((resolve) => {
85
- wake = resolve;
86
- });
46
+ for await (const row of rows) {
47
+ yield row;
87
48
  }
88
49
  }
89
50
  finally {
90
- // `completed` is awaited rather than left floating so a late rejection is handled; its own
91
- // `catch` has already recorded it, and the loop above is what raises one to the caller.
51
+ // The cancel reports itself as an error on the stream, and the loop that would hear it is gone.
52
+ rows.on('error', () => { });
92
53
  request.cancel();
93
54
  await completed;
94
55
  }
@@ -96,24 +57,23 @@ export class MsSqlQuerier extends AbstractPoolQuerier {
96
57
  /**
97
58
  * `mssql` owns its pool and hands out a `Request` per call, so a `BEGIN TRANSACTION` sent as text
98
59
  * would open one on a connection the next call may not be given. Its `Transaction` object is the
99
- * only thing that pins them together, so the three commands the dialect names are driven through
100
- * it here instead of being sent. Compared against the dialect's own strings rather than literals,
101
- * so renaming one cannot silently turn it back into text.
60
+ * only thing that pins them together, so the transaction is that object rather than statements, and
61
+ * the level goes to its `begin`: sent as a statement it would land on whichever connection served it.
102
62
  */
103
- async #driveTransaction(query) {
104
- const { beginTransactionCommand, commitTransactionCommand, rollbackTransactionCommand } = this.dialect;
105
- if (query.startsWith(beginTransactionCommand)) {
106
- this.#transaction = this.getConn().transaction();
107
- await this.#transaction.begin(isolationLevelOf(query.slice(beginTransactionCommand.length)));
108
- return true;
109
- }
110
- if (query !== commitTransactionCommand && query !== rollbackTransactionCommand) {
111
- return false;
112
- }
63
+ async internalBegin(opts) {
64
+ const transaction = this.getConn().transaction();
65
+ await transaction.begin(opts?.isolationLevel && ISOLATION_LEVEL[ISOLATION[opts.isolationLevel]]);
66
+ this.#transaction = transaction;
67
+ }
68
+ async internalCommit() {
69
+ const transaction = this.#transaction;
70
+ this.#transaction = undefined;
71
+ await transaction?.commit();
72
+ }
73
+ async internalRollback() {
113
74
  const transaction = this.#transaction;
114
75
  this.#transaction = undefined;
115
- await (query === commitTransactionCommand ? transaction?.commit() : transaction?.rollback());
116
- return true;
76
+ await transaction?.rollback();
117
77
  }
118
78
  /** The pool owns the socket; releasing a querier only drops this one's claim on it. */
119
79
  async releaseConn(_conn, _discard) {
@@ -123,15 +83,10 @@ export class MsSqlQuerier extends AbstractPoolQuerier {
123
83
  await transaction?.rollback().catch(() => undefined);
124
84
  }
125
85
  }
126
- /**
127
- * The driver constant for the level the dialect spelled into its `BEGIN`, so it applies to the
128
- * connection the transaction actually opens on. Undefined leaves the server's own default.
129
- */
130
- function isolationLevelOf(suffix) {
131
- const level = suffix
132
- .replace(/^\s*ISOLATION LEVEL\s*/i, '')
133
- .trim()
134
- .toUpperCase()
135
- .replaceAll(' ', '_');
136
- return level ? ISOLATION_LEVEL[level] : undefined;
137
- }
86
+ /** The driver's constant for each level UQL names; total, so a new level is a compile error here. */
87
+ const ISOLATION = {
88
+ 'read uncommitted': 'READ_UNCOMMITTED',
89
+ 'read committed': 'READ_COMMITTED',
90
+ 'repeatable read': 'REPEATABLE_READ',
91
+ serializable: 'SERIALIZABLE',
92
+ };
@@ -1,6 +1,7 @@
1
1
  import { ConnectionPool } from 'mssql';
2
2
  import { dialectOptionsFrom } from '../dialect/abstractDialect.js';
3
3
  import { AbstractSqlQuerierPool } from '../querier/index.js';
4
+ import { attachPoolErrorHandler } from '../util/index.js';
4
5
  import { MsSqlDialect } from './mssqlDialect.js';
5
6
  import { MsSqlQuerier } from './mssqlQuerier.js';
6
7
  export class MsSqlQuerierPool extends AbstractSqlQuerierPool {
@@ -9,6 +10,7 @@ export class MsSqlQuerierPool extends AbstractSqlQuerierPool {
9
10
  constructor(opts, extra) {
10
11
  super(new MsSqlDialect(dialectOptionsFrom(extra)), extra);
11
12
  this.pool = new ConnectionPool(opts);
13
+ attachPoolErrorHandler(this.pool, 'Idle SQL Server pool connection encountered an error', extra?.logger);
12
14
  }
13
15
  /**
14
16
  * `mssql` connects the pool as a whole rather than per checkout, so the promise is shared. A
@@ -14,10 +14,9 @@ type ColumnTypes = Record<string, {
14
14
  * reads, the ids an `OUTPUT` reports, raw SQL, counts, aggregates - where the ORM's own hydration
15
15
  * only ever sees entity reads.
16
16
  *
17
- * Exact to 2^53, which covers any generated id. A value past it keeps the string the driver gave,
18
- * because a number could no longer represent it: that is the one case where handing back the exact
19
- * text is more useful than handing back the type that was asked for. The lighter escape hatch for a
20
- * column that big is the declaration - `@Field({ type: String, columnType: 'bigint' })`.
17
+ * By the rule every driver here shares, `decodeWideNumber`: a number where one is exact, the driver's
18
+ * exact text past 2^53. The lighter escape hatch for a column that big is the declaration -
19
+ * `@Field({ type: String, columnType: 'bigint' })`.
21
20
  */
22
21
  export declare function decodeWireTypes<T>(rows: T[] | undefined, columns: ColumnTypes | undefined): T[];
23
22
  export {};
@@ -1,3 +1,4 @@
1
+ import { decodeWideNumber } from '../util/wideNumber.js';
1
2
  /**
2
3
  * Decode `BIGINT` as a JS number, leaving every other type to the driver.
3
4
  *
@@ -10,10 +11,9 @@
10
11
  * reads, the ids an `OUTPUT` reports, raw SQL, counts, aggregates - where the ORM's own hydration
11
12
  * only ever sees entity reads.
12
13
  *
13
- * Exact to 2^53, which covers any generated id. A value past it keeps the string the driver gave,
14
- * because a number could no longer represent it: that is the one case where handing back the exact
15
- * text is more useful than handing back the type that was asked for. The lighter escape hatch for a
16
- * column that big is the declaration - `@Field({ type: String, columnType: 'bigint' })`.
14
+ * By the rule every driver here shares, `decodeWideNumber`: a number where one is exact, the driver's
15
+ * exact text past 2^53. The lighter escape hatch for a column that big is the declaration -
16
+ * `@Field({ type: String, columnType: 'bigint' })`.
17
17
  */
18
18
  export function decodeWireTypes(rows, columns) {
19
19
  if (!rows?.length || !columns) {
@@ -29,10 +29,7 @@ export function decodeWireTypes(rows, columns) {
29
29
  for (const name of wide) {
30
30
  const value = decoded[name];
31
31
  if (typeof value === 'string') {
32
- const asNumber = Number(value);
33
- if (Number.isSafeInteger(asNumber)) {
34
- decoded[name] = asNumber;
35
- }
32
+ decoded[name] = decodeWideNumber(value);
36
33
  }
37
34
  }
38
35
  return decoded;
@@ -1,4 +1,3 @@
1
- export * from './mysql2Dialect.js';
2
1
  export * from './mysql2Querier.js';
3
2
  export * from './mysql2QuerierPool.js';
4
3
  export * from './mysqlDialect.js';
@@ -1,4 +1,3 @@
1
- export * from './mysql2Dialect.js';
2
1
  export * from './mysql2Querier.js';
3
2
  export * from './mysql2QuerierPool.js';
4
3
  export * from './mysqlDialect.js';
@@ -1,11 +1,8 @@
1
1
  import type { PoolConnection } from 'mysql2/promise';
2
2
  import { AbstractPoolQuerier } from '../querier/abstractPoolQuerier.js';
3
- import type { ExtraOptions } from '../type/index.js';
4
- import type { MySqlDialect } from './mysqlDialect.js';
5
3
  export declare class MySql2Querier extends AbstractPoolQuerier<PoolConnection> {
6
- constructor(connect: () => Promise<PoolConnection>, dialect: MySqlDialect, extra?: ExtraOptions);
7
4
  internalAll<T>(query: string, values?: unknown[]): Promise<T[]>;
8
- internalRun(query: string, values?: unknown[]): Promise<import("../type/query.js").QueryUpdateResult>;
5
+ internalRun(query: string, values?: unknown[]): Promise<import("../index.js").QueryUpdateResult>;
9
6
  internalStream<T>(query: string, values?: unknown[]): AsyncGenerator<Awaited<T>, void, unknown>;
10
7
  protected releaseConn(conn: PoolConnection, discard: boolean): Promise<void>;
11
8
  }
@@ -1,8 +1,5 @@
1
1
  import { AbstractPoolQuerier } from '../querier/abstractPoolQuerier.js';
2
2
  export class MySql2Querier extends AbstractPoolQuerier {
3
- constructor(connect, dialect, extra) {
4
- super(dialect, connect, extra);
5
- }
6
3
  async internalAll(query, values) {
7
4
  const [res] = await this.getConn().query(query, values);
8
5
  return res;
@@ -1,9 +1,9 @@
1
1
  import { type Pool, type PoolOptions } from 'mysql2/promise';
2
2
  import { AbstractSqlQuerierPool } from '../querier/index.js';
3
3
  import type { ExtraOptions } from '../type/index.js';
4
- import { MySql2Dialect } from './mysql2Dialect.js';
5
4
  import { MySql2Querier } from './mysql2Querier.js';
6
- export declare class MySql2QuerierPool extends AbstractSqlQuerierPool<MySql2Querier, MySql2Dialect> {
5
+ import { MySqlDialect } from './mysqlDialect.js';
6
+ export declare class MySql2QuerierPool extends AbstractSqlQuerierPool<MySql2Querier, MySqlDialect> {
7
7
  readonly pool: Pool;
8
8
  constructor(opts: PoolOptions, extra?: ExtraOptions);
9
9
  getQuerier(): Promise<MySql2Querier>;
@@ -1,13 +1,15 @@
1
1
  import { createPool } from 'mysql2/promise';
2
2
  import { dialectOptionsFrom } from '../dialect/abstractDialect.js';
3
3
  import { AbstractSqlQuerierPool } from '../querier/index.js';
4
- import { MySql2Dialect } from './mysql2Dialect.js';
5
4
  import { MySql2Querier } from './mysql2Querier.js';
5
+ import { MySqlDialect } from './mysqlDialect.js';
6
6
  export class MySql2QuerierPool extends AbstractSqlQuerierPool {
7
7
  pool;
8
8
  constructor(opts, extra) {
9
- super(new MySql2Dialect(dialectOptionsFrom(extra)), extra);
10
- this.pool = createPool(opts);
9
+ super(new MySqlDialect(dialectOptionsFrom(extra)), extra);
10
+ // A BIGINT past 2^53 as its exact text rather than a rounded number, the rule every driver here
11
+ // decodes by (`decodeWideNumber`); within that range it stays a number, and DECIMAL is untouched.
12
+ this.pool = createPool({ supportBigNumbers: true, ...opts });
11
13
  }
12
14
  async getQuerier() {
13
15
  return new MySql2Querier(() => this.pool.getConnection(), this.dialect, this.extra);
@@ -1,3 +1 @@
1
- export * from './neonDialect.js';
2
- export * from './neonQuerier.js';
3
1
  export * from './neonQuerierPool.js';
@@ -1,3 +1 @@
1
- export * from './neonDialect.js';
2
- export * from './neonQuerier.js';
3
1
  export * from './neonQuerierPool.js';
@@ -1,10 +1,8 @@
1
1
  import { Pool, type PoolClient, type PoolConfig } from '@neondatabase/serverless';
2
2
  import { AbstractPgQuerierPool } from '../postgres/abstractPgQuerierPool.js';
3
+ import { PostgresDialect } from '../postgres/postgresDialect.js';
3
4
  import type { ExtraOptions } from '../type/index.js';
4
- import { NeonDialect } from './neonDialect.js';
5
- import { NeonQuerier } from './neonQuerier.js';
6
- export declare class NeonQuerierPool extends AbstractPgQuerierPool<PoolClient, NeonQuerier, NeonDialect> {
5
+ export declare class NeonQuerierPool extends AbstractPgQuerierPool<PoolClient, PostgresDialect> {
7
6
  readonly pool: Pool;
8
7
  constructor(opts: PoolConfig, extra?: ExtraOptions);
9
- protected buildQuerier(connect: () => Promise<PoolClient>): NeonQuerier;
10
8
  }
@@ -2,14 +2,10 @@ import { Pool, types } from '@neondatabase/serverless';
2
2
  import { dialectOptionsFrom } from '../dialect/abstractDialect.js';
3
3
  import { AbstractPgQuerierPool } from '../postgres/abstractPgQuerierPool.js';
4
4
  import { numericTypes } from '../postgres/pgNumericTypes.js';
5
- import { NeonDialect } from './neonDialect.js';
6
- import { NeonQuerier } from './neonQuerier.js';
5
+ import { PostgresDialect } from '../postgres/postgresDialect.js';
7
6
  export class NeonQuerierPool extends AbstractPgQuerierPool {
8
7
  constructor(opts, extra) {
9
8
  // Neon's own `types`, not `pg`'s: this entry has to load on an edge runtime where `pg` is absent.
10
- super(new NeonDialect(dialectOptionsFrom(extra)), new Pool({ types: numericTypes(types), ...opts }), extra);
11
- }
12
- buildQuerier(connect) {
13
- return new NeonQuerier(connect, this.dialect, this.extra);
9
+ super(new PostgresDialect(dialectOptionsFrom(extra)), new Pool({ types: numericTypes(types), ...opts }), extra);
14
10
  }
15
11
  }
@@ -1,3 +1,2 @@
1
- export * from './pgliteDialect.js';
2
1
  export * from './pgliteQuerier.js';
3
2
  export * from './pgliteQuerierPool.js';
@@ -1,3 +1,2 @@
1
- export * from './pgliteDialect.js';
2
1
  export * from './pgliteQuerier.js';
3
2
  export * from './pgliteQuerierPool.js';
@@ -1,6 +1,6 @@
1
+ import type { PostgresDialect } from '../postgres/postgresDialect.js';
1
2
  import { AbstractSqlQuerier } from '../querier/index.js';
2
3
  import type { ExtraOptions } from '../type/index.js';
3
- import type { PgliteDialect } from './pgliteDialect.js';
4
4
  /**
5
5
  * Structural subset of the `@electric-sql/pglite` API actually used here, declared locally so this
6
6
  * package does not couple its published types to a pre-1.0 dependency.
@@ -20,7 +20,7 @@ export type PgliteDatabase = {
20
20
  /**
21
21
  * Querier for PGlite, Postgres compiled to WASM and run in this process.
22
22
  *
23
- * @remarks Extends {@link AbstractSqlQuerier} rather than `AbstractPgQuerier`, whose `internalStream`
23
+ * @remarks Extends {@link AbstractSqlQuerier} rather than `PgQuerier`, whose `internalStream`
24
24
  * hands a `pg-query-stream` object to `query()`, which PGlite's client has no equivalent of - so
25
25
  * streaming pages the rows in SQL instead. `BEGIN`/`COMMIT` are plain statements on the single
26
26
  * connection, leaving transactions to the base class.
@@ -28,7 +28,7 @@ export type PgliteDatabase = {
28
28
  export declare class PgliteQuerier extends AbstractSqlQuerier {
29
29
  readonly db: PgliteDatabase;
30
30
  readonly extra?: ExtraOptions | undefined;
31
- constructor(db: PgliteDatabase, dialect: PgliteDialect, extra?: ExtraOptions | undefined);
31
+ constructor(db: PgliteDatabase, dialect: PostgresDialect, extra?: ExtraOptions | undefined);
32
32
  internalAll<T>(query: string, values?: unknown[]): Promise<T[]>;
33
33
  internalRun(query: string, values?: unknown[]): Promise<import("../type/query.js").QueryUpdateResult>;
34
34
  /** Postgres compiled to WASM is still Postgres: `DECLARE`/`FETCH` streams what the client cannot. */
@@ -3,7 +3,7 @@ import { AbstractSqlQuerier } from '../querier/index.js';
3
3
  /**
4
4
  * Querier for PGlite, Postgres compiled to WASM and run in this process.
5
5
  *
6
- * @remarks Extends {@link AbstractSqlQuerier} rather than `AbstractPgQuerier`, whose `internalStream`
6
+ * @remarks Extends {@link AbstractSqlQuerier} rather than `PgQuerier`, whose `internalStream`
7
7
  * hands a `pg-query-stream` object to `query()`, which PGlite's client has no equivalent of - so
8
8
  * streaming pages the rows in SQL instead. `BEGIN`/`COMMIT` are plain statements on the single
9
9
  * connection, leaving transactions to the base class.
@@ -1,7 +1,7 @@
1
1
  import type { PGliteOptions } from '@electric-sql/pglite';
2
+ import { PostgresDialect } from '../postgres/postgresDialect.js';
2
3
  import { AbstractSharedHandleQuerierPool } from '../querier/abstractSharedHandleQuerierPool.js';
3
4
  import type { ExtraOptions } from '../type/index.js';
4
- import { PgliteDialect } from './pgliteDialect.js';
5
5
  import { type PgliteDatabase, PgliteQuerier } from './pgliteQuerier.js';
6
6
  /**
7
7
  * The driver's own options, minus the `dataDir` this pool takes as its first argument.
@@ -26,8 +26,13 @@ export type PglitePoolOptions = Omit<PGliteOptions, 'dataDir'>;
26
26
  * The cost is that PGlite cannot see the transaction, so it flushes to the filesystem after each
27
27
  * statement within one: pass `relaxedDurability: true` on a persistent `dataDir` to skip waiting on
28
28
  * those flushes.
29
+ *
30
+ * The dialect is plain `PostgresDialect`, `dialectName` included: PGlite *is* Postgres, so the
31
+ * introspector, schema generator and CLI resolve to Postgres's. Both driver capabilities hold as
32
+ * they are - PGlite serializes every built-in array type itself, and the `$n::jsonb` cast is what
33
+ * makes its `Describe` report JSONB and pick its JSON serializer; a bare `$n` binds `[object Object]`.
29
34
  */
30
- export declare class PgliteQuerierPool extends AbstractSharedHandleQuerierPool<PgliteDatabase, PgliteQuerier, PgliteDialect> {
35
+ export declare class PgliteQuerierPool extends AbstractSharedHandleQuerierPool<PgliteDatabase, PgliteQuerier, PostgresDialect> {
31
36
  readonly dataDir: string;
32
37
  readonly opts?: PglitePoolOptions | undefined;
33
38
  constructor(dataDir?: string, opts?: PglitePoolOptions | undefined, extra?: ExtraOptions);
@@ -1,6 +1,7 @@
1
1
  import { dialectOptionsFrom } from '../dialect/abstractDialect.js';
2
+ import { PostgresDialect } from '../postgres/postgresDialect.js';
2
3
  import { AbstractSharedHandleQuerierPool } from '../querier/abstractSharedHandleQuerierPool.js';
3
- import { PgliteDialect } from './pgliteDialect.js';
4
+ import { decodeWideNumber } from '../util/wideNumber.js';
4
5
  import { PgliteQuerier } from './pgliteQuerier.js';
5
6
  /**
6
7
  * Pool for PGlite, Postgres compiled to WASM and run in this process. No server, no container.
@@ -16,20 +17,29 @@ import { PgliteQuerier } from './pgliteQuerier.js';
16
17
  * The cost is that PGlite cannot see the transaction, so it flushes to the filesystem after each
17
18
  * statement within one: pass `relaxedDurability: true` on a persistent `dataDir` to skip waiting on
18
19
  * those flushes.
20
+ *
21
+ * The dialect is plain `PostgresDialect`, `dialectName` included: PGlite *is* Postgres, so the
22
+ * introspector, schema generator and CLI resolve to Postgres's. Both driver capabilities hold as
23
+ * they are - PGlite serializes every built-in array type itself, and the `$n::jsonb` cast is what
24
+ * makes its `Describe` report JSONB and pick its JSON serializer; a bare `$n` binds `[object Object]`.
19
25
  */
20
26
  export class PgliteQuerierPool extends AbstractSharedHandleQuerierPool {
21
27
  dataDir;
22
28
  opts;
23
29
  constructor(dataDir = 'memory://', opts, extra) {
24
- super(new PgliteDialect(dialectOptionsFrom(extra)), extra);
30
+ super(new PostgresDialect(dialectOptionsFrom(extra)), extra);
25
31
  this.dataDir = dataDir;
26
32
  this.opts = opts;
27
33
  }
28
34
  async openDb() {
29
- const { PGlite } = await import('@electric-sql/pglite');
30
- // The declared return type is what checks {@link PgliteDatabase} against the real driver, so no
31
- // cast is needed here or anywhere below it.
32
- return PGlite.create(this.dataDir, this.opts);
35
+ const { PGlite, types } = await import('@electric-sql/pglite');
36
+ // INT8 by the one wide-integer rule, where PGlite's own answers a `bigint` past 2^53; a caller's own
37
+ // `parsers` still win. The declared return type is what checks {@link PgliteDatabase} against the
38
+ // real driver, so no cast is needed here or anywhere below it.
39
+ return PGlite.create(this.dataDir, {
40
+ ...this.opts,
41
+ parsers: { [types.INT8]: decodeWideNumber, ...this.opts?.parsers },
42
+ });
33
43
  }
34
44
  buildQuerier(db) {
35
45
  return new PgliteQuerier(db, this.dialect, this.extra);
@@ -2,26 +2,22 @@ import type { AbstractSqlDialect } from '../dialect/index.js';
2
2
  import { AbstractSqlQuerierPool } from '../querier/index.js';
3
3
  import type { ExtraOptions } from '../type/index.js';
4
4
  import { type ErrorEmittingPool } from '../util/index.js';
5
- import type { AbstractPgQuerier, PgAnyClient } from './abstractPgQuerier.js';
5
+ import { type PgAnyClient, PgQuerier } from './pgQuerier.js';
6
6
  export interface PgAnyPool<C extends PgAnyClient> extends ErrorEmittingPool {
7
7
  connect: () => Promise<C>;
8
8
  end: () => Promise<void>;
9
9
  }
10
10
  /**
11
- * Shared base class for Postgres-compatible querier pools.
11
+ * Shared base class for Postgres-compatible querier pools. Each hands out a {@link PgQuerier} over its
12
+ * driver's client, so a subclass supplies only the dialect and the driver's pool.
12
13
  *
13
- * Wires the crash-preventing error handler here, once, so a new pg-compatible
14
- * pool subclass can't be added without it - the constructor takes the already
15
- * constructed pool and attaches the handler unconditionally.
14
+ * Wires the crash-preventing error handler here, once, so a new pg-compatible pool subclass can't be
15
+ * added without it - the constructor takes the already constructed pool and attaches the handler
16
+ * unconditionally.
16
17
  */
17
- export declare abstract class AbstractPgQuerierPool<C extends PgAnyClient, Q extends AbstractPgQuerier<C, D>, D extends AbstractSqlDialect> extends AbstractSqlQuerierPool<Q, D> {
18
+ export declare abstract class AbstractPgQuerierPool<C extends PgAnyClient, D extends AbstractSqlDialect> extends AbstractSqlQuerierPool<PgQuerier<C>, D> {
18
19
  readonly pool: PgAnyPool<C>;
19
20
  constructor(dialect: D, pool: PgAnyPool<C>, extra?: ExtraOptions);
20
- /**
21
- * Every pg-compatible pool acquires a client the same way, so only the querier class varies.
22
- * Subclasses name that instead of restating the lazy `connect` the querier expects.
23
- */
24
- protected abstract buildQuerier(connect: () => Promise<C>): Q;
25
- getQuerier(): Promise<Q>;
21
+ getQuerier(): Promise<PgQuerier<C>>;
26
22
  end(): Promise<void>;
27
23
  }
@@ -1,21 +1,23 @@
1
1
  import { AbstractSqlQuerierPool } from '../querier/index.js';
2
2
  import { attachPoolErrorHandler } from '../util/index.js';
3
+ import { PgQuerier } from './pgQuerier.js';
3
4
  /**
4
- * Shared base class for Postgres-compatible querier pools.
5
+ * Shared base class for Postgres-compatible querier pools. Each hands out a {@link PgQuerier} over its
6
+ * driver's client, so a subclass supplies only the dialect and the driver's pool.
5
7
  *
6
- * Wires the crash-preventing error handler here, once, so a new pg-compatible
7
- * pool subclass can't be added without it - the constructor takes the already
8
- * constructed pool and attaches the handler unconditionally.
8
+ * Wires the crash-preventing error handler here, once, so a new pg-compatible pool subclass can't be
9
+ * added without it - the constructor takes the already constructed pool and attaches the handler
10
+ * unconditionally.
9
11
  */
10
12
  export class AbstractPgQuerierPool extends AbstractSqlQuerierPool {
11
13
  pool;
12
14
  constructor(dialect, pool, extra) {
13
15
  super(dialect, extra);
14
16
  this.pool = pool;
15
- attachPoolErrorHandler(pool, 'Idle Postgres pool client encountered an error');
17
+ attachPoolErrorHandler(pool, 'Idle Postgres pool client encountered an error', extra?.logger);
16
18
  }
17
19
  async getQuerier() {
18
- return this.buildQuerier(() => this.pool.connect());
20
+ return new PgQuerier(() => this.pool.connect(), this.dialect, this.extra);
19
21
  }
20
22
  async end() {
21
23
  await this.pool.end();
@@ -1,4 +1,3 @@
1
- export * from './pgDialect.js';
2
1
  export * from './pgQuerier.js';
3
2
  export * from './pgQuerierPool.js';
4
3
  export * from './postgresDialect.js';
@@ -1,4 +1,3 @@
1
- export * from './pgDialect.js';
2
1
  export * from './pgQuerier.js';
3
2
  export * from './pgQuerierPool.js';
4
3
  export * from './postgresDialect.js';
@@ -10,7 +10,8 @@ type PgTypes = {
10
10
  getTypeParser(oid: number, format?: 'text' | 'binary'): (value: string) => unknown;
11
11
  };
12
12
  /**
13
- * Decode `INT8` and `FLOAT8` as JS numbers, leaving every other type to the driver.
13
+ * Decode `INT8` and `FLOAT8`, leaving every other type to the driver: an INT8 by `decodeWideNumber` - a
14
+ * number where one is exact, its exact text past 2^53 - and a FLOAT8 as the float64 it already is.
14
15
  *
15
16
  * uql owes this to the caller because uql picks the column: `type: Number` maps to BIGINT (see
16
17
  * `schema/canonicalType.ts`), so without it a field declared `number` read back as `'9'` - including
@@ -32,10 +33,9 @@ type PgTypes = {
32
33
  * `types.setTypeParser` calls in `neon/neonQuerier.test.ts` - and both made the suite pass on
33
34
  * behaviour the library never shipped. Do not reintroduce one.
34
35
  *
35
- * Exact to 2^53, which covers any auto-increment id. A caller who needs more passes their own
36
- * `types` in the pool options: it is spread after this one and therefore wins. For a decimal, the
37
- * lighter escape hatch is the declaration itself: `@Field({ type: String, columnType: 'decimal' })`
38
- * keeps the column DECIMAL while leaving the value as the exact text the driver returned.
36
+ * A caller's own `types` in the pool options are spread after this one and therefore win. For a
37
+ * decimal, the lighter escape hatch is the declaration itself: `@Field({ type: String, columnType:
38
+ * 'decimal' })` keeps the column DECIMAL while leaving the value as the exact text the driver returned.
39
39
  */
40
40
  export declare function numericTypes(types: PgTypes): CustomTypesConfig;
41
41
  export {};
@@ -1,5 +1,7 @@
1
+ import { decodeWideNumber } from '../util/wideNumber.js';
1
2
  /**
2
- * Decode `INT8` and `FLOAT8` as JS numbers, leaving every other type to the driver.
3
+ * Decode `INT8` and `FLOAT8`, leaving every other type to the driver: an INT8 by `decodeWideNumber` - a
4
+ * number where one is exact, its exact text past 2^53 - and a FLOAT8 as the float64 it already is.
3
5
  *
4
6
  * uql owes this to the caller because uql picks the column: `type: Number` maps to BIGINT (see
5
7
  * `schema/canonicalType.ts`), so without it a field declared `number` read back as `'9'` - including
@@ -21,15 +23,17 @@
21
23
  * `types.setTypeParser` calls in `neon/neonQuerier.test.ts` - and both made the suite pass on
22
24
  * behaviour the library never shipped. Do not reintroduce one.
23
25
  *
24
- * Exact to 2^53, which covers any auto-increment id. A caller who needs more passes their own
25
- * `types` in the pool options: it is spread after this one and therefore wins. For a decimal, the
26
- * lighter escape hatch is the declaration itself: `@Field({ type: String, columnType: 'decimal' })`
27
- * keeps the column DECIMAL while leaving the value as the exact text the driver returned.
26
+ * A caller's own `types` in the pool options are spread after this one and therefore win. For a
27
+ * decimal, the lighter escape hatch is the declaration itself: `@Field({ type: String, columnType:
28
+ * 'decimal' })` keeps the column DECIMAL while leaving the value as the exact text the driver returned.
28
29
  */
29
30
  export function numericTypes(types) {
30
31
  // Text only: in binary mode an INT8 arrives as an 8-byte Buffer, and `Number(buffer)` is `NaN`.
31
- const textNumeric = new Set([types.builtins['INT8'], types.builtins['FLOAT8']]);
32
+ const decoders = new Map([
33
+ [types.builtins['INT8'], decodeWideNumber],
34
+ [types.builtins['FLOAT8'], Number],
35
+ ]);
32
36
  return {
33
- getTypeParser: (oid, format) => format === 'text' && textNumeric.has(oid) ? Number : types.getTypeParser(oid, format),
37
+ getTypeParser: (oid, format) => (format === 'text' && decoders.get(oid)) || types.getTypeParser(oid, format),
34
38
  };
35
39
  }
@@ -1,5 +1,23 @@
1
- import type { PoolClient } from 'pg';
2
- import { AbstractPgQuerier } from './abstractPgQuerier.js';
3
- import type { PostgresDialect } from './postgresDialect.js';
4
- export declare class PgQuerier extends AbstractPgQuerier<PoolClient, PostgresDialect> {
1
+ import { AbstractPoolQuerier } from '../querier/abstractPoolQuerier.js';
2
+ import type { RawRow } from '../type/index.js';
3
+ export interface PgAnyClient {
4
+ query(text: string, values?: unknown[]): Promise<{
5
+ rows: RawRow[];
6
+ rowCount: number | null;
7
+ }>;
8
+ query(stream: object): AsyncIterable<RawRow> & {
9
+ destroy(): void;
10
+ };
11
+ /** Any truthy argument makes `pg-pool` evict the client instead of returning it to the idle list. */
12
+ release(discard?: boolean): void | Promise<void>;
13
+ }
14
+ /**
15
+ * Querier for every client with node-postgres' API: `pg` itself, for Postgres and CockroachDB, and
16
+ * Neon's serverless driver. Generic over the client alone - the dialect is whichever the pool built.
17
+ */
18
+ export declare class PgQuerier<C extends PgAnyClient = PgAnyClient> extends AbstractPoolQuerier<C> {
19
+ internalAll<T>(query: string, values?: unknown[]): Promise<T[]>;
20
+ internalRun(query: string, values?: unknown[]): Promise<import("../type/query.js").QueryUpdateResult>;
21
+ internalStream<T>(query: string, values?: unknown[]): AsyncGenerator<Awaited<T>, void, unknown>;
22
+ protected releaseConn(conn: C, discard: boolean): Promise<void>;
5
23
  }