uql-orm 0.65.1 → 0.67.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 (193) hide show
  1. package/dist/browser/querier/httpQuerier.js +1 -8
  2. package/dist/browser/uql-browser.min.js.map +5 -5
  3. package/dist/bunSql/bunSql.util.d.ts +2 -6
  4. package/dist/bunSql/bunSql.util.js +2 -6
  5. package/dist/bunSql/bunSqlQuerier.d.ts +2 -5
  6. package/dist/bunSql/bunSqlQuerier.js +2 -5
  7. package/dist/cockroachdb/cockroachDialect.d.ts +4 -13
  8. package/dist/cockroachdb/cockroachDialect.js +4 -13
  9. package/dist/context/context.browser.js +2 -10
  10. package/dist/context/context.d.ts +4 -17
  11. package/dist/context/context.js +4 -17
  12. package/dist/dialect/abstractDialect.d.ts +4 -19
  13. package/dist/dialect/abstractDialect.js +2 -20
  14. package/dist/dialect/abstractSqlDialect.d.ts +47 -212
  15. package/dist/dialect/abstractSqlDialect.js +68 -222
  16. package/dist/dialect/aliases.d.ts +2 -12
  17. package/dist/dialect/aliases.js +4 -12
  18. package/dist/dialect/hydrateColumn.d.ts +2 -6
  19. package/dist/dialect/hydrateColumn.js +3 -13
  20. package/dist/dialect/jsonArrayElemMatchUtils.d.ts +1 -7
  21. package/dist/dialect/jsonArrayElemMatchUtils.js +1 -7
  22. package/dist/dialect/jsonSql.d.ts +6 -27
  23. package/dist/dialect/jsonSql.js +6 -27
  24. package/dist/dialect/mergeSqlDialect.d.ts +4 -22
  25. package/dist/dialect/mergeSqlDialect.js +4 -22
  26. package/dist/dialect/mysqlLikeSqlDialect.d.ts +11 -37
  27. package/dist/dialect/mysqlLikeSqlDialect.js +35 -51
  28. package/dist/dialect/pgLikeSqlDialect.d.ts +8 -22
  29. package/dist/dialect/pgLikeSqlDialect.js +36 -39
  30. package/dist/dialect/queryContext.d.ts +4 -22
  31. package/dist/dialect/queryContext.js +4 -22
  32. package/dist/dialect/queryJoins.d.ts +3 -12
  33. package/dist/dialect/queryJoins.js +3 -12
  34. package/dist/dialect/vectorCast.d.ts +2 -12
  35. package/dist/dialect/vectorCast.js +3 -19
  36. package/dist/dialect/vectorSqlDialect.d.ts +8 -38
  37. package/dist/dialect/vectorSqlDialect.js +7 -38
  38. package/dist/entity/decorator/bag.d.ts +6 -19
  39. package/dist/entity/decorator/bag.js +6 -22
  40. package/dist/entity/decorator/entity.d.ts +5 -10
  41. package/dist/entity/decorator/entity.js +2 -7
  42. package/dist/entity/decorator/members.d.ts +10 -31
  43. package/dist/entity/decorator/members.js +3 -12
  44. package/dist/entity/metadata/definition.d.ts +5 -21
  45. package/dist/entity/metadata/definition.js +69 -91
  46. package/dist/http/handler.d.ts +2 -14
  47. package/dist/index.d.ts +3 -1
  48. package/dist/index.js +3 -1
  49. package/dist/libsql/libsqlDialect.d.ts +1 -8
  50. package/dist/libsql/libsqlDialect.js +1 -8
  51. package/dist/maria/mariaDialect.d.ts +3 -5
  52. package/dist/maria/mariaDialect.js +5 -5
  53. package/dist/maria/mariadbQuerier.js +2 -2
  54. package/dist/maria/mariadbQuerierPool.js +1 -6
  55. package/dist/migrate/builder/migrationBuilder.js +3 -19
  56. package/dist/migrate/builder/splitSqlStatements.d.ts +1 -14
  57. package/dist/migrate/builder/splitSqlStatements.js +2 -22
  58. package/dist/migrate/builder/types.d.ts +2 -15
  59. package/dist/migrate/cli-config.js +2 -11
  60. package/dist/migrate/cli.js +2 -7
  61. package/dist/migrate/codegen/entityCodeGenerator.d.ts +0 -15
  62. package/dist/migrate/codegen/entityCodeGenerator.js +15 -44
  63. package/dist/migrate/codegen/fieldOptionsSource.d.ts +1 -8
  64. package/dist/migrate/codegen/fieldOptionsSource.js +3 -22
  65. package/dist/migrate/ddl/indexDdl.d.ts +2 -5
  66. package/dist/migrate/ddl/indexDdl.js +2 -5
  67. package/dist/migrate/ddl/pgIndexDdl.d.ts +3 -13
  68. package/dist/migrate/ddl/pgIndexDdl.js +3 -13
  69. package/dist/migrate/generator/definitionToNode.d.ts +2 -9
  70. package/dist/migrate/generator/definitionToNode.js +3 -17
  71. package/dist/migrate/generator/indexNodeToSchema.d.ts +2 -3
  72. package/dist/migrate/generator/indexNodeToSchema.js +2 -3
  73. package/dist/migrate/generator/mongoCommand.d.ts +1 -8
  74. package/dist/migrate/generator/mongoSchemaGenerator.d.ts +1 -8
  75. package/dist/migrate/generator/mongoSchemaGenerator.js +1 -8
  76. package/dist/migrate/introspection/abstractSqlSchemaIntrospector.d.ts +6 -26
  77. package/dist/migrate/introspection/abstractSqlSchemaIntrospector.js +9 -41
  78. package/dist/migrate/introspection/baseSqlIntrospector.js +0 -1
  79. package/dist/migrate/introspection/mongoIntrospector.d.ts +3 -1
  80. package/dist/migrate/introspection/mongoIntrospector.js +48 -46
  81. package/dist/migrate/introspection/mssqlIntrospector.d.ts +4 -4
  82. package/dist/migrate/introspection/mssqlIntrospector.js +18 -27
  83. package/dist/migrate/introspection/mysqlIntrospector.d.ts +7 -2
  84. package/dist/migrate/introspection/mysqlIntrospector.js +16 -14
  85. package/dist/migrate/introspection/postgresIntrospector.d.ts +24 -9
  86. package/dist/migrate/introspection/postgresIntrospector.js +68 -59
  87. package/dist/migrate/introspection/sqliteIntrospector.d.ts +1 -1
  88. package/dist/migrate/introspection/sqliteIntrospector.js +8 -10
  89. package/dist/migrate/migrator.d.ts +9 -53
  90. package/dist/migrate/migrator.js +32 -65
  91. package/dist/migrate/schemaGenerator.d.ts +20 -66
  92. package/dist/migrate/schemaGenerator.js +32 -93
  93. package/dist/mongo/mongoDialect.d.ts +21 -53
  94. package/dist/mongo/mongoDialect.js +25 -70
  95. package/dist/mongo/mongodbQuerier.d.ts +5 -8
  96. package/dist/mongo/mongodbQuerier.js +31 -65
  97. package/dist/mssql/mssqlDialect.d.ts +8 -34
  98. package/dist/mssql/mssqlDialect.js +37 -51
  99. package/dist/mssql/mssqlQuerier.d.ts +37 -4
  100. package/dist/mssql/mssqlQuerier.js +2 -2
  101. package/dist/mssql/mssqlWireTypes.d.ts +2 -14
  102. package/dist/mssql/mssqlWireTypes.js +2 -14
  103. package/dist/nestjs/uqlModule.js +2 -7
  104. package/dist/pglite/pgliteQuerier.d.ts +1 -9
  105. package/dist/pglite/pgliteQuerierPool.d.ts +4 -26
  106. package/dist/pglite/pgliteQuerierPool.js +3 -18
  107. package/dist/postgres/abstractPgQuerierPool.d.ts +1 -8
  108. package/dist/postgres/abstractPgQuerierPool.js +1 -8
  109. package/dist/postgres/pgNumericTypes.d.ts +3 -26
  110. package/dist/postgres/pgNumericTypes.js +3 -26
  111. package/dist/postgres/postgresDialect.d.ts +4 -10
  112. package/dist/postgres/postgresDialect.js +4 -10
  113. package/dist/querier/abstractQuerier.d.ts +35 -103
  114. package/dist/querier/abstractQuerier.js +105 -201
  115. package/dist/querier/abstractSharedHandleQuerierPool.d.ts +3 -17
  116. package/dist/querier/abstractSharedHandleQuerierPool.js +3 -17
  117. package/dist/querier/abstractSqlQuerier.d.ts +15 -36
  118. package/dist/querier/abstractSqlQuerier.js +49 -131
  119. package/dist/schema/canonicalType.d.ts +3 -21
  120. package/dist/schema/canonicalType.js +22 -67
  121. package/dist/schema/dependencyGraph.d.ts +2 -8
  122. package/dist/schema/dependencyGraph.js +2 -32
  123. package/dist/schema/index.d.ts +1 -25
  124. package/dist/schema/index.js +0 -26
  125. package/dist/schema/indexColumns.d.ts +1 -8
  126. package/dist/schema/indexColumns.js +1 -8
  127. package/dist/schema/indexDifferences.d.ts +7 -40
  128. package/dist/schema/indexDifferences.js +6 -31
  129. package/dist/schema/schemaAST.d.ts +8 -175
  130. package/dist/schema/schemaAST.js +13 -365
  131. package/dist/schema/schemaASTBuilder.d.ts +2 -24
  132. package/dist/schema/schemaASTBuilder.js +6 -41
  133. package/dist/schema/schemaASTDiffer.d.ts +6 -46
  134. package/dist/schema/schemaASTDiffer.js +8 -56
  135. package/dist/schema/types.d.ts +5 -61
  136. package/dist/schema/types.js +3 -6
  137. package/dist/sqlite/abstractSqliteQuerier.d.ts +1 -8
  138. package/dist/sqlite/localSqliteQuerierPool.d.ts +1 -7
  139. package/dist/sqlite/localSqliteQuerierPool.js +1 -7
  140. package/dist/sqlite/nodeSqliteQuerierPool.d.ts +2 -7
  141. package/dist/sqlite/nodeSqliteQuerierPool.js +2 -7
  142. package/dist/sqlite/sqliteDialect.d.ts +5 -20
  143. package/dist/sqlite/sqliteDialect.js +29 -35
  144. package/dist/turso/tursoDialect.d.ts +4 -6
  145. package/dist/turso/tursoDialect.js +4 -6
  146. package/dist/turso/tursoLocalQuerierPool.d.ts +1 -7
  147. package/dist/turso/tursoLocalQuerierPool.js +1 -7
  148. package/dist/turso/tursoQuerierPool.d.ts +2 -6
  149. package/dist/turso/tursoQuerierPool.js +2 -6
  150. package/dist/turso/tursoSessionQuerier.d.ts +1 -7
  151. package/dist/turso/tursoSessionQuerier.js +1 -7
  152. package/dist/type/dialect.d.ts +42 -94
  153. package/dist/type/dialect.js +3 -13
  154. package/dist/type/entity.d.ts +189 -551
  155. package/dist/type/entity.js +26 -9
  156. package/dist/type/logger.d.ts +2 -14
  157. package/dist/type/migration.d.ts +9 -38
  158. package/dist/type/querier.d.ts +9 -28
  159. package/dist/type/querierPool.d.ts +4 -26
  160. package/dist/type/query.d.ts +28 -78
  161. package/dist/type/query.js +2 -7
  162. package/dist/type/queryAggregate.d.ts +18 -98
  163. package/dist/type/queryRaw.d.ts +1 -8
  164. package/dist/type/queryRaw.js +1 -8
  165. package/dist/type/queryWhere.d.ts +13 -61
  166. package/dist/type/universalQuerier.d.ts +18 -105
  167. package/dist/type/utility.d.ts +12 -24
  168. package/dist/type/vector.d.ts +8 -38
  169. package/dist/type/vector.js +1 -1
  170. package/dist/type/wire.d.ts +2 -5
  171. package/dist/util/dialect.util.d.ts +9 -27
  172. package/dist/util/dialect.util.js +10 -27
  173. package/dist/util/field.util.d.ts +5 -37
  174. package/dist/util/field.util.js +7 -50
  175. package/dist/util/fieldOption.util.d.ts +7 -15
  176. package/dist/util/fieldOption.util.js +1 -1
  177. package/dist/util/filters.util.d.ts +2 -5
  178. package/dist/util/filters.util.js +2 -5
  179. package/dist/util/logger.d.ts +2 -6
  180. package/dist/util/logger.js +2 -6
  181. package/dist/util/object.util.d.ts +2 -6
  182. package/dist/util/object.util.js +1 -5
  183. package/dist/util/raw.d.ts +3 -23
  184. package/dist/util/relationQuery.util.d.ts +3 -14
  185. package/dist/util/relationQuery.util.js +3 -14
  186. package/dist/util/rowKey.util.d.ts +2 -10
  187. package/dist/util/rowKey.util.js +2 -10
  188. package/dist/util/sql.util.d.ts +6 -37
  189. package/dist/util/sql.util.js +13 -73
  190. package/dist/util/sqlLiteral.d.ts +2 -13
  191. package/dist/util/sqlLiteral.js +8 -13
  192. package/dist/util/string.util.js +0 -2
  193. package/package.json +4 -4
@@ -10,34 +10,39 @@ import { parseQueryLock } from '../type/index.js';
10
10
  import { isAutoIncrement } from '../util/field.util.js';
11
11
  import { assertNonNegativeInteger } from '../util/index.js';
12
12
  import { escapeSingleQuotes } from '../util/sqlLiteral.js';
13
- /**
14
- * Microsoft SQL Server 2017 and up - the floor `STRING_AGG` sets, every other construct here being
15
- * 2016 or older.
16
- *
17
- * Identifiers are `"`-quoted rather than bracketed: `escapeIdChar` is one character that doubles to
18
- * escape itself, `"` is the ANSI spelling, and `tedious` enables `QUOTED_IDENTIFIER` by default.
19
- * Brackets would buy nothing and cost the shared dialect spec, which reads that one character.
20
- */
13
+ /** What SQL Server has. */
14
+ const MSSQL_FEATURES = {
15
+ // Neither object takes an `IF NOT EXISTS`; both need a `sys` catalogue lookup around them, which
16
+ // the generator does not emit.
17
+ ifNotExists: false,
18
+ indexIfNotExists: false,
19
+ schemas: true,
20
+ dropTableCascade: false,
21
+ foreignKeyAlter: true,
22
+ primaryKeyAlter: true,
23
+ generatedColumnAdd: true,
24
+ // Extended properties are out-of-band metadata with their own procedures, not comments.
25
+ commentSyntax: 'none',
26
+ vectorIndexRequiresNotNull: false,
27
+ vectorSupportsLength: true,
28
+ supportsTimestamptz: false,
29
+ stringSizing: 'varchar',
30
+ supportsUnsigned: false,
31
+ serverSideCursors: false,
32
+ rowLocks: true,
33
+ rowLockWithWindow: true,
34
+ rowLockOf: true,
35
+ orderedUpsertReturning: false,
36
+ orderedJsonAggregates: true,
37
+ partialJsonContainment: false,
38
+ typedJsonElements: false,
39
+ narrowVectorTypes: false,
40
+ vectorTuningNeedsTransaction: false,
41
+ serialDeclaresPrimaryKey: false,
42
+ };
43
+ /** Microsoft SQL Server 2017 and up. Identifiers are `"`-quoted, the ANSI spelling `tedious` enables. */
21
44
  export class MsSqlDialect extends MergeSqlDialect {
22
- featureDefaults = {
23
- // Neither object takes an `IF NOT EXISTS`; both need a `sys` catalogue lookup around them, which
24
- // the generator does not emit.
25
- ifNotExists: false,
26
- indexIfNotExists: false,
27
- schemas: true,
28
- dropTableCascade: false,
29
- foreignKeyAlter: true,
30
- primaryKeyAlter: true,
31
- generatedColumnAdd: true,
32
- // Extended properties are out-of-band metadata with their own procedures, not comments.
33
- commentSyntax: 'none',
34
- vectorIndexRequiresNotNull: false,
35
- vectorSupportsLength: true,
36
- supportsTimestamptz: false,
37
- stringSizing: 'varchar',
38
- supportsUnsigned: false,
39
- serverSideCursors: false,
40
- };
45
+ features = MSSQL_FEATURES;
41
46
  dialectName = 'mssql';
42
47
  /** `OPENJSON`'s own output columns, which every JSON operator below reads through. */
43
48
  #elem = {
@@ -61,8 +66,6 @@ export class MsSqlDialect extends MergeSqlDialect {
61
66
  maxBindValues = 2100;
62
67
  /** `OUTPUT` has no trailing form: it sits between the column list and `VALUES`. */
63
68
  returningPosition = 'after-target';
64
- /** Microsoft documents no row order for a `MERGE ... OUTPUT`. */
65
- upsertReturningOrdered = false;
66
69
  insertIdSource = 'returning';
67
70
  /** Holds the update key lock across the insert; without it two concurrent upserts of one key race. */
68
71
  mergeTargetHint = ' WITH (HOLDLOCK)';
@@ -86,12 +89,8 @@ export class MsSqlDialect extends MergeSqlDialect {
86
89
  super.pager(ctx, opts, sorted);
87
90
  }
88
91
  /**
89
- * `SET IDENTITY_INSERT` around the insert, where the payload states a key the engine would
90
- * otherwise generate: writing one is refused outright ("cannot insert explicit value for identity
91
- * column ... when IDENTITY_INSERT is set to OFF") rather than ignored.
92
- *
93
- * Emitted only for that case, because the setting is per-session and only one table may hold it at
94
- * a time, so it is turned back off in the same batch it was turned on.
92
+ * `SET IDENTITY_INSERT` around an insert that states a key the engine would generate, which it otherwise
93
+ * refuses; turned off in the same batch, since one table per session may hold it.
95
94
  */
96
95
  insert(ctx, entity, payload, opts) {
97
96
  const table = this.identityInsertTarget(entity, payload);
@@ -115,13 +114,7 @@ export class MsSqlDialect extends MergeSqlDialect {
115
114
  const stated = records.some((record) => record[idKey] !== undefined);
116
115
  return stated ? this.escapedTableName(meta) : undefined;
117
116
  }
118
- /**
119
- * A `DECIMAL` read back as the exact text it was written as, where the entity declared the field a
120
- * `String`. `tedious` decodes the type to a JS number before anything here can see it, so the
121
- * digits past 2^53 are gone at the wire unless the column is converted before it crosses - the same
122
- * reason MariaDB reads a vector column through `VEC_ToText`. 41 characters covers `DECIMAL(38, s)`
123
- * with room for the sign and the point.
124
- */
117
+ /** A `DECIMAL` declared `String`, converted before it crosses the wire, where `tedious` would round it. */
125
118
  selectFieldExpr(escapedColumn, field) {
126
119
  const exactDecimal = field.type === String && fieldOptionsToCanonical(field).category === 'decimal';
127
120
  return exactDecimal ? `CONVERT(NVARCHAR(41), ${escapedColumn})` : escapedColumn;
@@ -261,13 +254,8 @@ export class MsSqlDialect extends MergeSqlDialect {
261
254
  return this.getJsonPathScalarExpr(escapedColumn, jsonPathStr);
262
255
  }
263
256
  /**
264
- * A value being *compared* against a JSON path, which reads back as the text `JSON_VALUE` yields:
265
- * `'true'` for a boolean, `'12'` for a number. So only a boolean needs re-spelling; a number or a
266
- * string already binds as the text it will be compared with.
267
- *
268
- * There is no "parse this text as JSON" cast to bind through the way `CAST(? AS JSON)` and
269
- * `json(?)` serve the other families - `JSON_QUERY` marks text as JSON but answers NULL for a
270
- * scalar - which is why reading and writing need the two different binders here.
257
+ * A value compared against a JSON path, which reads back as text, so only a boolean needs spelling as
258
+ * `'true'`; SQL Server has no cast that parses text as JSON.
271
259
  */
272
260
  jsonScalarParam(ctx, value) {
273
261
  return (this.#jsonCompound(ctx, value) ?? this.addValue(ctx, typeof value === 'boolean' ? JSON.stringify(value) : value));
@@ -298,8 +286,6 @@ export class MsSqlDialect extends MergeSqlDialect {
298
286
  }
299
287
  return `JSON_QUERY(${this.addValue(ctx, JSON.stringify(value))})`;
300
288
  }
301
- /** An exploded element compares as text here, so `$elemMatch` always expands per field. */
302
- jsonContainmentIsPartial = false;
303
289
  jsonElemFrom(jsonField, _fields, alias) {
304
290
  return `OPENJSON(${jsonField}) ${alias}`;
305
291
  }
@@ -1,12 +1,44 @@
1
- import type { ConnectionPool } from 'mssql';
2
1
  import { AbstractPoolQuerier } from '../querier/abstractPoolQuerier.js';
3
- import type { QueryUpdateResult, TransactionOptions } from '../type/index.js';
2
+ import type { QueryUpdateResult, RawRow, TransactionOptions } from '../type/index.js';
3
+ /** What `tedious` hands back for one statement, whichever shape it took. */
4
+ type MsSqlResult = {
5
+ recordset?: RawRow[] & {
6
+ columns?: Record<string, {
7
+ type: unknown;
8
+ }>;
9
+ };
10
+ rowsAffected: number[];
11
+ };
12
+ /** The part of the `Readable` a request streams into that a querier drives. */
13
+ type MsSqlRowStream = AsyncIterable<unknown> & {
14
+ destroy(error: Error): unknown;
15
+ on(event: 'error', listener: (error: Error) => void): unknown;
16
+ };
17
+ /** The part of an `mssql` `Request` a querier drives. */
18
+ type MsSqlRequest = {
19
+ input(name: string, value: unknown): unknown;
20
+ query(command: string): Promise<MsSqlResult>;
21
+ toReadableStream(): MsSqlRowStream;
22
+ cancel(): unknown;
23
+ };
24
+ /** The part of an `mssql` `Transaction` a querier drives. */
25
+ type MsSqlTransaction = {
26
+ begin(isolationLevel?: number): Promise<unknown>;
27
+ commit(): Promise<unknown>;
28
+ rollback(): Promise<unknown>;
29
+ request(): MsSqlRequest;
30
+ };
31
+ /** The part of an `mssql` `ConnectionPool` a querier drives. */
32
+ export type MsSqlConnection = {
33
+ request(): MsSqlRequest;
34
+ transaction(): MsSqlTransaction;
35
+ };
4
36
  /**
5
37
  * A connection is a `ConnectionPool` handle here rather than a checked-out socket: `mssql` owns its
6
38
  * own pool and hands out `Request`s, so what UQL holds is the pool plus, once a transaction opens,
7
39
  * the `Transaction` every later request has to be bound to.
8
40
  */
9
- export declare class MsSqlQuerier extends AbstractPoolQuerier<ConnectionPool> {
41
+ export declare class MsSqlQuerier extends AbstractPoolQuerier<MsSqlConnection> {
10
42
  #private;
11
43
  internalAll<T>(query: string, values?: unknown[]): Promise<T[]>;
12
44
  internalRun(query: string, values?: unknown[]): Promise<QueryUpdateResult>;
@@ -26,5 +58,6 @@ export declare class MsSqlQuerier extends AbstractPoolQuerier<ConnectionPool> {
26
58
  protected internalCommit(): Promise<void>;
27
59
  protected internalRollback(): Promise<void>;
28
60
  /** The pool owns the socket; releasing a querier only drops this one's claim on it. */
29
- protected releaseConn(_conn: ConnectionPool, _discard: boolean): Promise<void>;
61
+ protected releaseConn(_conn: MsSqlConnection, _discard: boolean): Promise<void>;
30
62
  }
63
+ export {};
@@ -19,11 +19,11 @@ export class MsSqlQuerier extends AbstractPoolQuerier {
19
19
  return request;
20
20
  }
21
21
  async internalAll(query, values) {
22
- const res = (await this.#request(values).query(query));
22
+ const res = await this.#request(values).query(query);
23
23
  return decodeWireTypes(res.recordset, res.recordset?.columns);
24
24
  }
25
25
  async internalRun(query, values) {
26
- const res = (await this.#request(values).query(query));
26
+ const res = await this.#request(values).query(query);
27
27
  return this.buildUpdateResult({
28
28
  // `rowsAffected` carries one entry per statement, and a `MERGE` upsert emits its `OUTPUT`
29
29
  // alongside the write, so the counts are summed rather than read at [0].
@@ -3,20 +3,8 @@ type ColumnTypes = Record<string, {
3
3
  readonly type: unknown;
4
4
  }>;
5
5
  /**
6
- * Decode `BIGINT` as a JS number, leaving every other type to the driver.
7
- *
8
- * uql owes this to the caller because uql picks the column: `type: Number` maps to BIGINT (see
9
- * `schema/canonicalType.ts`), and `tedious` hands that back as a string to protect the digits past
10
- * 2^53 - so without this a field declared `number` reads back as `'9'`, including every generated
11
- * primary key on every entity.
12
- *
13
- * At the wire, for the reason `pgNumericTypes` gives: everything crosses it exactly once - entity
14
- * reads, the ids an `OUTPUT` reports, raw SQL, counts, aggregates - where the ORM's own hydration
15
- * only ever sees entity reads.
16
- *
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' })`.
6
+ * Decodes `BIGINT`, which `tedious` returns as text, by `decodeWideNumber`: `type: Number` maps to
7
+ * BIGINT, so otherwise every generated key reads back as a string. At the wire, which every result crosses.
20
8
  */
21
9
  export declare function decodeWireTypes<T>(rows: T[] | undefined, columns: ColumnTypes | undefined): T[];
22
10
  export {};
@@ -1,19 +1,7 @@
1
1
  import { decodeWideNumber } from '../util/wideNumber.js';
2
2
  /**
3
- * Decode `BIGINT` as a JS number, leaving every other type to the driver.
4
- *
5
- * uql owes this to the caller because uql picks the column: `type: Number` maps to BIGINT (see
6
- * `schema/canonicalType.ts`), and `tedious` hands that back as a string to protect the digits past
7
- * 2^53 - so without this a field declared `number` reads back as `'9'`, including every generated
8
- * primary key on every entity.
9
- *
10
- * At the wire, for the reason `pgNumericTypes` gives: everything crosses it exactly once - entity
11
- * reads, the ids an `OUTPUT` reports, raw SQL, counts, aggregates - where the ORM's own hydration
12
- * only ever sees entity reads.
13
- *
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' })`.
3
+ * Decodes `BIGINT`, which `tedious` returns as text, by `decodeWideNumber`: `type: Number` maps to
4
+ * BIGINT, so otherwise every generated key reads back as a string. At the wire, which every result crosses.
17
5
  */
18
6
  export function decodeWireTypes(rows, columns) {
19
7
  if (!rows?.length || !columns) {
@@ -43,13 +43,8 @@ import { UqlContextInterceptor } from './uqlContextInterceptor.js';
43
43
  */
44
44
  export const UQL_QUERIER_POOL = Symbol('UQL_QUERIER_POOL');
45
45
  /**
46
- * Ends the pool when Nest shuts down.
47
- *
48
- * @remarks A provider rather than a hook on the module class, and built through `useFactory` with an
49
- * `inject` list rather than constructor injection: Nest injects constructor parameters with a parameter
50
- * decorator, and the TC39 decorator spec has none, so `@Inject()` cannot appear in a file compiled
51
- * against it. Nest runs lifecycle hooks on providers too, so this keeps the pool that *this* module was
52
- * configured with instead of reaching for the global default.
46
+ * Ends the pool this module was configured with when Nest shuts down: a provider built by `useFactory`,
47
+ * since TC39 decorators have no parameter decorator for `@Inject()`.
53
48
  */
54
49
  class UqlPoolLifecycle {
55
50
  pool;
@@ -1,15 +1,7 @@
1
1
  import type { PostgresDialect } from '../postgres/postgresDialect.js';
2
2
  import { AbstractSqlQuerier } from '../querier/index.js';
3
3
  import type { ExtraOptions } from '../type/index.js';
4
- /**
5
- * Structural subset of the `@electric-sql/pglite` API actually used here, declared locally so this
6
- * package does not couple its published types to a pre-1.0 dependency.
7
- *
8
- * @remarks This is what uql *consumes* from the driver, so it is two methods and stating them costs
9
- * nothing. `PglitePoolOptions` is the opposite case and imports PGlite's own type: those options are
10
- * the caller's input to the driver, so restating them would mean re-deriving its whole option surface
11
- * and then casting at the `PGlite.create` call.
12
- */
4
+ /** The two methods uql uses of `@electric-sql/pglite`, stated so its published types do not depend on a pre-1.0 package. */
13
5
  export type PgliteDatabase = {
14
6
  query<T>(query: string, params?: unknown[]): Promise<{
15
7
  rows: T[];
@@ -3,34 +3,12 @@ import { PostgresDialect } from '../postgres/postgresDialect.js';
3
3
  import { AbstractSharedHandleQuerierPool } from '../querier/abstractSharedHandleQuerierPool.js';
4
4
  import type { ExtraOptions } from '../type/index.js';
5
5
  import { type PgliteDatabase, PgliteQuerier } from './pgliteQuerier.js';
6
- /**
7
- * The driver's own options, minus the `dataDir` this pool takes as its first argument.
8
- *
9
- * @remarks Imported rather than restated so extensions and the filesystem hooks keep their real types:
10
- * `extensions: { vector }` from `@electric-sql/pglite-pgvector` is how a vector column becomes usable,
11
- * mirroring `LocalSqlitePoolOptions.extensions` for `sqlite-vec`. Type-only, like the `pg` imports in
12
- * `abstractPgQuerierPool.ts`, so nothing here reaches a runtime without the peer installed.
13
- */
6
+ /** PGlite's own options but `dataDir`, the pool's first argument; `extensions: { vector }` enables pgvector. Type-only. */
14
7
  export type PglitePoolOptions = Omit<PGliteOptions, 'dataDir'>;
15
8
  /**
16
- * Pool for PGlite, Postgres compiled to WASM and run in this process. No server, no container.
17
- *
18
- * PGlite is single connection, so the shared-handle lifecycle is {@link AbstractSharedHandleQuerierPool}'s.
19
- * Where PGlite differs from the two SQLite-family pools there is that it does not refuse a second
20
- * `BEGIN`: a querier that opens a transaction while another already has one silently joins it, and that
21
- * one's `ROLLBACK` then discards both queriers' writes. Nothing reports it, so a unit of work that needs
22
- * a transaction of its own needs its own pool, and therefore its own database.
23
- *
24
- * @remarks Transactions are plain `BEGIN`/`COMMIT` statements rather than `db.transaction()`, whose
25
- * callback holds PGlite's transaction mutex and would block every other querier's reads until commit.
26
- * The cost is that PGlite cannot see the transaction, so it flushes to the filesystem after each
27
- * statement within one: pass `relaxedDurability: true` on a persistent `dataDir` to skip waiting on
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]`.
9
+ * A pool for PGlite, Postgres in WASM in this process, on one connection. A second `BEGIN` silently joins
10
+ * the open transaction, so a unit of work needing its own needs its own pool. Transactions are plain
11
+ * statements, so pass `relaxedDurability` on a persistent `dataDir` to skip a flush per statement.
34
12
  */
35
13
  export declare class PgliteQuerierPool extends AbstractSharedHandleQuerierPool<PgliteDatabase, PgliteQuerier, PostgresDialect> {
36
14
  readonly dataDir: string;
@@ -4,24 +4,9 @@ import { AbstractSharedHandleQuerierPool } from '../querier/abstractSharedHandle
4
4
  import { decodeWideNumber } from '../util/wideNumber.js';
5
5
  import { PgliteQuerier } from './pgliteQuerier.js';
6
6
  /**
7
- * Pool for PGlite, Postgres compiled to WASM and run in this process. No server, no container.
8
- *
9
- * PGlite is single connection, so the shared-handle lifecycle is {@link AbstractSharedHandleQuerierPool}'s.
10
- * Where PGlite differs from the two SQLite-family pools there is that it does not refuse a second
11
- * `BEGIN`: a querier that opens a transaction while another already has one silently joins it, and that
12
- * one's `ROLLBACK` then discards both queriers' writes. Nothing reports it, so a unit of work that needs
13
- * a transaction of its own needs its own pool, and therefore its own database.
14
- *
15
- * @remarks Transactions are plain `BEGIN`/`COMMIT` statements rather than `db.transaction()`, whose
16
- * callback holds PGlite's transaction mutex and would block every other querier's reads until commit.
17
- * The cost is that PGlite cannot see the transaction, so it flushes to the filesystem after each
18
- * statement within one: pass `relaxedDurability: true` on a persistent `dataDir` to skip waiting on
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]`.
7
+ * A pool for PGlite, Postgres in WASM in this process, on one connection. A second `BEGIN` silently joins
8
+ * the open transaction, so a unit of work needing its own needs its own pool. Transactions are plain
9
+ * statements, so pass `relaxedDurability` on a persistent `dataDir` to skip a flush per statement.
25
10
  */
26
11
  export class PgliteQuerierPool extends AbstractSharedHandleQuerierPool {
27
12
  dataDir;
@@ -7,14 +7,7 @@ export interface PgAnyPool<C extends PgAnyClient> extends ErrorEmittingPool {
7
7
  connect: () => Promise<C>;
8
8
  end: () => Promise<void>;
9
9
  }
10
- /**
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.
13
- *
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.
17
- */
10
+ /** A Postgres-wire pool of {@link PgQuerier}s, attaching the error handler that keeps a dropped connection from crashing the process. */
18
11
  export declare abstract class AbstractPgQuerierPool<C extends PgAnyClient, D extends AbstractSqlDialect> extends AbstractSqlQuerierPool<PgQuerier<C>, D> {
19
12
  readonly pool: PgAnyPool<C>;
20
13
  constructor(dialect: D, pool: PgAnyPool<C>, extra?: ExtraOptions);
@@ -1,14 +1,7 @@
1
1
  import { AbstractSqlQuerierPool } from '../querier/index.js';
2
2
  import { attachPoolErrorHandler } from '../util/index.js';
3
3
  import { PgQuerier } from './pgQuerier.js';
4
- /**
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.
7
- *
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.
11
- */
4
+ /** A Postgres-wire pool of {@link PgQuerier}s, attaching the error handler that keeps a dropped connection from crashing the process. */
12
5
  export class AbstractPgQuerierPool extends AbstractSqlQuerierPool {
13
6
  pool;
14
7
  constructor(dialect, pool, extra) {
@@ -10,32 +10,9 @@ type PgTypes = {
10
10
  getTypeParser(oid: number, format?: 'text' | 'binary'): (value: string) => unknown;
11
11
  };
12
12
  /**
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.
15
- *
16
- * uql owes this to the caller because uql picks the column: `type: Number` maps to BIGINT (see
17
- * `schema/canonicalType.ts`), so without it a field declared `number` read back as `'9'` - including
18
- * every auto-increment primary key, on every entity. `FLOAT8` is a float64, which is exactly what a
19
- * JS number is, so decoding it loses nothing at all.
20
- *
21
- * At the driver because everything crosses the wire decoder exactly once - entity reads, `RETURNING
22
- * id`, raw SQL, counts, aggregates - while the ORM's hydration only ever sees entity reads. Which
23
- * types belong here and which need the entity's declaration is settled in `hydratableFields`.
24
- *
25
- * `NUMERIC` is deliberately absent, and decoded in hydration instead: `type: BigInt` also maps to
26
- * BIGINT, so a blanket decode here is already as far as a driver can go without the declaration. That
27
- * split also covers mysql2, which returns DECIMAL as text and has no equivalent hook.
28
- *
29
- * Per pool, never global, which is the whole reason this takes `types` as an argument. TypeORM does
30
- * the same job by assigning `postgres.defaults.parseInt8`, a module-wide flag every pool in the
31
- * process then shares; MikroORM passes a per-pool `TypeOverrides`, as here. Two globals of exactly
32
- * that shape have already been deleted from this repo - `test/pgTypeParsers.util.ts` and the
33
- * `types.setTypeParser` calls in `neon/neonQuerier.test.ts` - and both made the suite pass on
34
- * behaviour the library never shipped. Do not reintroduce one.
35
- *
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.
13
+ * Decodes `INT8` by `decodeWideNumber` and `FLOAT8` as the float64 it is, since `type: Number` maps to
14
+ * BIGINT. At the wire, which every result crosses; `NUMERIC` is left to hydration, which knows the field.
15
+ * Per pool, never a global parser, and a caller's own `types` win.
39
16
  */
40
17
  export declare function numericTypes(types: PgTypes): CustomTypesConfig;
41
18
  export {};
@@ -1,31 +1,8 @@
1
1
  import { decodeWideNumber } from '../util/wideNumber.js';
2
2
  /**
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.
5
- *
6
- * uql owes this to the caller because uql picks the column: `type: Number` maps to BIGINT (see
7
- * `schema/canonicalType.ts`), so without it a field declared `number` read back as `'9'` - including
8
- * every auto-increment primary key, on every entity. `FLOAT8` is a float64, which is exactly what a
9
- * JS number is, so decoding it loses nothing at all.
10
- *
11
- * At the driver because everything crosses the wire decoder exactly once - entity reads, `RETURNING
12
- * id`, raw SQL, counts, aggregates - while the ORM's hydration only ever sees entity reads. Which
13
- * types belong here and which need the entity's declaration is settled in `hydratableFields`.
14
- *
15
- * `NUMERIC` is deliberately absent, and decoded in hydration instead: `type: BigInt` also maps to
16
- * BIGINT, so a blanket decode here is already as far as a driver can go without the declaration. That
17
- * split also covers mysql2, which returns DECIMAL as text and has no equivalent hook.
18
- *
19
- * Per pool, never global, which is the whole reason this takes `types` as an argument. TypeORM does
20
- * the same job by assigning `postgres.defaults.parseInt8`, a module-wide flag every pool in the
21
- * process then shares; MikroORM passes a per-pool `TypeOverrides`, as here. Two globals of exactly
22
- * that shape have already been deleted from this repo - `test/pgTypeParsers.util.ts` and the
23
- * `types.setTypeParser` calls in `neon/neonQuerier.test.ts` - and both made the suite pass on
24
- * behaviour the library never shipped. Do not reintroduce one.
25
- *
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.
3
+ * Decodes `INT8` by `decodeWideNumber` and `FLOAT8` as the float64 it is, since `type: Number` maps to
4
+ * BIGINT. At the wire, which every result crosses; `NUMERIC` is left to hydration, which knows the field.
5
+ * Per pool, never a global parser, and a caller's own `types` win.
29
6
  */
30
7
  export function numericTypes(types) {
31
8
  // Text only: in binary mode an INT8 arrives as an 8-byte Buffer, and `Number(buffer)` is `NaN`.
@@ -1,17 +1,11 @@
1
1
  import { PgLikeSqlDialect } from '../dialect/pgLikeSqlDialect.js';
2
- import type { QueryConflictPaths, QueryContext, SqlDialectName, Type } from '../type/index.js';
3
- /**
4
- * PostgreSQL dialect, the same class under every Postgres driver - `pg`, Neon, PGlite, `bun:sql` -
5
- * where a driver that binds differently passes `driverCapabilities` rather than subclassing it.
6
- * Shared Postgres-wire AST/quoting/JSONB/full-text-search/vector-search logic (including BIGINT
7
- * IDENTITY PKs) lives in {@link PgLikeSqlDialect}; this class adds what's Postgres-only: the `vector`
8
- * extension requirement, pgvector's index syntax, and `xmax`-based upsert `created` detection.
9
- */
2
+ import type { QueryConflictPaths, QueryContext, SqlDialectFeatures, SqlDialectName, Type } from '../type/index.js';
3
+ /** PostgreSQL, under every driver: `pg`, Neon, PGlite, `bun:sql`. Adds pgvector and the `xmax` upsert `created`. */
10
4
  export declare class PostgresDialect extends PgLikeSqlDialect {
11
5
  readonly dialectName: SqlDialectName;
12
6
  readonly vectorExtension: string | undefined;
13
- /** pgvector is the only engine with `halfvec` and `sparsevec`; every other maps them onto `vector`. */
14
- protected readonly hasNarrowVectorTypes = true;
7
+ /** pgvector is the only engine with `halfvec` and `sparsevec`. */
8
+ readonly features: SqlDialectFeatures;
15
9
  upsert<E>(ctx: QueryContext, entity: Type<E>, conflictPaths: QueryConflictPaths<E>, payload: E | E[]): void;
16
10
  /**
17
11
  * `to_regclass` rather than a `::regclass` cast: it answers `NULL` for a table that does not exist
@@ -1,18 +1,12 @@
1
1
  import { COUNT_ALIAS } from '../dialect/aliases.js';
2
- import { PgLikeSqlDialect } from '../dialect/pgLikeSqlDialect.js';
2
+ import { PG_FEATURES, PgLikeSqlDialect } from '../dialect/pgLikeSqlDialect.js';
3
3
  import { getMeta } from '../entity/index.js';
4
- /**
5
- * PostgreSQL dialect, the same class under every Postgres driver - `pg`, Neon, PGlite, `bun:sql` -
6
- * where a driver that binds differently passes `driverCapabilities` rather than subclassing it.
7
- * Shared Postgres-wire AST/quoting/JSONB/full-text-search/vector-search logic (including BIGINT
8
- * IDENTITY PKs) lives in {@link PgLikeSqlDialect}; this class adds what's Postgres-only: the `vector`
9
- * extension requirement, pgvector's index syntax, and `xmax`-based upsert `created` detection.
10
- */
4
+ /** PostgreSQL, under every driver: `pg`, Neon, PGlite, `bun:sql`. Adds pgvector and the `xmax` upsert `created`. */
11
5
  export class PostgresDialect extends PgLikeSqlDialect {
12
6
  dialectName = 'postgres';
13
7
  vectorExtension = 'vector';
14
- /** pgvector is the only engine with `halfvec` and `sparsevec`; every other maps them onto `vector`. */
15
- hasNarrowVectorTypes = true;
8
+ /** pgvector is the only engine with `halfvec` and `sparsevec`. */
9
+ features = { ...PG_FEATURES, narrowVectorTypes: true };
16
10
  upsert(ctx, entity, conflictPaths, payload) {
17
11
  // The xmax system column is 0 for a newly inserted row and non-zero for an updated one (MVCC).
18
12
  super.upsert(ctx, entity, conflictPaths, payload, `(xmax = 0) AS ${this.escapeId('_created')}`);