turbine-orm 0.19.2 → 0.22.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 (53) hide show
  1. package/README.md +99 -18
  2. package/dist/adapters/cockroachdb.js +4 -9
  3. package/dist/cjs/adapters/cockroachdb.js +4 -9
  4. package/dist/cjs/cli/index.js +6 -3
  5. package/dist/cjs/cli/observe-ui.js +12 -2
  6. package/dist/cjs/cli/observe.js +6 -7
  7. package/dist/cjs/cli/studio.js +6 -7
  8. package/dist/cjs/client.js +44 -22
  9. package/dist/cjs/dialect.js +116 -0
  10. package/dist/cjs/errors.js +19 -1
  11. package/dist/cjs/generate.js +4 -0
  12. package/dist/cjs/index.js +3 -2
  13. package/dist/cjs/introspect.js +20 -0
  14. package/dist/cjs/mssql.js +1338 -0
  15. package/dist/cjs/mysql.js +1052 -0
  16. package/dist/cjs/powdb.js +851 -0
  17. package/dist/cjs/powql.js +903 -0
  18. package/dist/cjs/query/builder.js +293 -73
  19. package/dist/cjs/sqlite.js +849 -0
  20. package/dist/cjs/typed-sql.js +9 -7
  21. package/dist/cli/index.js +6 -3
  22. package/dist/cli/observe-ui.d.ts +1 -1
  23. package/dist/cli/observe-ui.js +12 -2
  24. package/dist/cli/observe.js +7 -8
  25. package/dist/cli/studio.js +7 -8
  26. package/dist/cli/ui.d.ts +1 -1
  27. package/dist/client.d.ts +23 -1
  28. package/dist/client.js +45 -23
  29. package/dist/dialect.d.ts +258 -1
  30. package/dist/dialect.js +83 -0
  31. package/dist/errors.d.ts +12 -0
  32. package/dist/errors.js +17 -0
  33. package/dist/generate.js +4 -0
  34. package/dist/index.d.ts +3 -3
  35. package/dist/index.js +1 -1
  36. package/dist/introspect.d.ts +18 -0
  37. package/dist/introspect.js +19 -0
  38. package/dist/mssql.d.ts +233 -0
  39. package/dist/mssql.js +1298 -0
  40. package/dist/mysql.d.ts +174 -0
  41. package/dist/mysql.js +1012 -0
  42. package/dist/powdb.d.ts +338 -0
  43. package/dist/powdb.js +802 -0
  44. package/dist/powql.d.ts +153 -0
  45. package/dist/powql.js +900 -0
  46. package/dist/query/builder.d.ts +105 -0
  47. package/dist/query/builder.js +294 -74
  48. package/dist/query/index.d.ts +1 -1
  49. package/dist/sqlite.d.ts +144 -0
  50. package/dist/sqlite.js +842 -0
  51. package/dist/typed-sql.d.ts +7 -5
  52. package/dist/typed-sql.js +9 -7
  53. package/package.json +45 -1
@@ -6,6 +6,39 @@
6
6
  * PostgreSQL-native by default, but query generation now depends on this
7
7
  * contract for the SQL primitives that vary across MySQL and SQLite.
8
8
  */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
9
42
  Object.defineProperty(exports, "__esModule", { value: true });
10
43
  exports.postgresDialect = void 0;
11
44
  const errors_js_1 = require("./errors.js");
@@ -13,11 +46,17 @@ const schema_js_1 = require("./schema.js");
13
46
  /** PostgreSQL implementation of the dialect contract. */
14
47
  exports.postgresDialect = {
15
48
  name: 'postgresql',
49
+ resultStrategy: 'returning',
16
50
  supportsReturning: true,
17
51
  supportsILike: true,
18
52
  jsonPathSupport: 'native',
19
53
  emptyJsonArrayLiteral: "'[]'::json",
20
54
  nullJsonLiteral: 'NULL',
55
+ aggSupportsInlineOrderBy: true,
56
+ supportsVector: true,
57
+ supportsListenNotify: true,
58
+ supportsRLS: true,
59
+ supportsAdvisoryLock: true,
21
60
  paramPlaceholder(index) {
22
61
  return `$${index}`;
23
62
  },
@@ -35,6 +74,9 @@ exports.postgresDialect = {
35
74
  const suffix = orderBy ? ` ${orderBy}` : '';
36
75
  return `COALESCE(json_agg(${jsonObjectExpr}${suffix}), ${this.emptyJsonArrayLiteral})`;
37
76
  },
77
+ wrapJsonSubresult(subquery, fallback) {
78
+ return `COALESCE((${subquery}), ${fallback})`;
79
+ },
38
80
  buildReturningClause(selection = '*') {
39
81
  return ` RETURNING ${selection}`;
40
82
  },
@@ -76,6 +118,15 @@ exports.postgresDialect = {
76
118
  typeToTypeScript(dialectType, nullable) {
77
119
  return (0, schema_js_1.pgTypeToTs)(dialectType, nullable);
78
120
  },
121
+ castAggregate(expr, target) {
122
+ return `${expr}::${target}`;
123
+ },
124
+ buildInClause(expr, paramRef, negated) {
125
+ return negated ? `${expr} != ALL(${paramRef})` : `${expr} = ANY(${paramRef})`;
126
+ },
127
+ inClauseParam(values) {
128
+ return values;
129
+ },
79
130
  arrayType(baseType) {
80
131
  return (0, schema_js_1.pgArrayType)(baseType);
81
132
  },
@@ -131,4 +182,69 @@ exports.postgresDialect = {
131
182
  buildMigrationDeleteApplied(table) {
132
183
  return `DELETE FROM ${table} WHERE name = ${this.paramPlaceholder(1)}`;
133
184
  },
185
+ beginStatement(isolationLevel) {
186
+ return isolationLevel ? `BEGIN ISOLATION LEVEL ${isolationLevel}` : 'BEGIN';
187
+ },
188
+ commitStatement() {
189
+ return 'COMMIT';
190
+ },
191
+ rollbackStatement() {
192
+ return 'ROLLBACK';
193
+ },
194
+ savepointStatement(name) {
195
+ return `SAVEPOINT ${name}`;
196
+ },
197
+ releaseSavepointStatement(name) {
198
+ return `RELEASE SAVEPOINT ${name}`;
199
+ },
200
+ rollbackToSavepointStatement(name) {
201
+ return `ROLLBACK TO SAVEPOINT ${name}`;
202
+ },
203
+ buildSetSessionConfig(name, value) {
204
+ // set_config(name, value, is_local=true) — the parameterizable,
205
+ // transaction-local equivalent of `SET LOCAL` (which rejects bind params).
206
+ return {
207
+ sql: `SELECT set_config(${this.paramPlaceholder(1)}, ${this.paramPlaceholder(2)}, true)`,
208
+ params: [name, value],
209
+ };
210
+ },
211
+ async *openStream(connection, sql, params, batchSize) {
212
+ // Cursors require a single connection inside a transaction. Identical SQL
213
+ // sequence to the historical inline implementation: BEGIN → DECLARE … NO
214
+ // SCROLL CURSOR FOR → FETCH n (loop) → CLOSE → COMMIT; ROLLBACK on error.
215
+ const cursorName = `turbine_cursor_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
216
+ const quotedCursor = this.quoteIdentifier(cursorName);
217
+ await connection.query(this.beginStatement());
218
+ try {
219
+ await connection.query(`DECLARE ${quotedCursor} NO SCROLL CURSOR FOR ${sql}`, params);
220
+ while (true) {
221
+ const batch = await connection.query(`FETCH ${batchSize} FROM ${quotedCursor}`);
222
+ if (batch.rows.length === 0)
223
+ break;
224
+ yield batch.rows;
225
+ if (batch.rows.length < batchSize)
226
+ break;
227
+ }
228
+ await connection.query(`CLOSE ${quotedCursor}`);
229
+ await connection.query(this.commitStatement());
230
+ }
231
+ catch (err) {
232
+ try {
233
+ await connection.query(this.rollbackStatement());
234
+ }
235
+ catch {
236
+ // Connection may already be broken — ignore rollback error.
237
+ }
238
+ throw err;
239
+ }
240
+ },
241
+ // Postgres introspection wraps the information_schema / pg_catalog reader in
242
+ // introspect.ts. A dynamic import keeps the static graph acyclic (introspect.ts
243
+ // imports postgresDialect) and calls the raw catalog reader (never the router).
244
+ introspector: {
245
+ async introspect(options) {
246
+ const { introspectPostgresCatalog } = await Promise.resolve().then(() => __importStar(require('./introspect.js')));
247
+ return introspectPostgresCatalog(options);
248
+ },
249
+ },
134
250
  };
@@ -6,7 +6,7 @@
6
6
  * All Turbine errors extend TurbineError which includes a `code` property.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.OptimisticLockError = exports.PipelineError = exports.ExclusionConstraintError = exports.CheckConstraintError = exports.SerializationFailureError = exports.DeadlockError = exports.NotNullViolationError = exports.ForeignKeyError = exports.UniqueConstraintError = exports.CircularRelationError = exports.MigrationError = exports.RelationError = exports.ConnectionError = exports.ValidationError = exports.TimeoutError = exports.NotFoundError = exports.TurbineError = exports.TurbineErrorCode = void 0;
9
+ exports.UnsupportedFeatureError = exports.OptimisticLockError = exports.PipelineError = exports.ExclusionConstraintError = exports.CheckConstraintError = exports.SerializationFailureError = exports.DeadlockError = exports.NotNullViolationError = exports.ForeignKeyError = exports.UniqueConstraintError = exports.CircularRelationError = exports.MigrationError = exports.RelationError = exports.ConnectionError = exports.ValidationError = exports.TimeoutError = exports.NotFoundError = exports.TurbineError = exports.TurbineErrorCode = void 0;
10
10
  exports.setErrorMessageMode = setErrorMessageMode;
11
11
  exports.getErrorMessageMode = getErrorMessageMode;
12
12
  exports.wrapPgError = wrapPgError;
@@ -28,6 +28,7 @@ exports.TurbineErrorCode = {
28
28
  PIPELINE: 'TURBINE_E014',
29
29
  OPTIMISTIC_LOCK: 'TURBINE_E015',
30
30
  EXCLUSION_VIOLATION: 'TURBINE_E016',
31
+ UNSUPPORTED_FEATURE: 'TURBINE_E017',
31
32
  };
32
33
  /** Base error class for all Turbine errors */
33
34
  class TurbineError extends Error {
@@ -458,6 +459,23 @@ class OptimisticLockError extends TurbineError {
458
459
  }
459
460
  }
460
461
  exports.OptimisticLockError = OptimisticLockError;
462
+ /**
463
+ * Thrown when a Postgres-only feature (pgvector distance ops, LISTEN/NOTIFY
464
+ * realtime, RLS session GUCs, advisory-lock migration locking, ...) is invoked
465
+ * on a dialect/engine whose capability flag reports it unsupported. Surfaces a
466
+ * clear `unsupported on <engine>` message instead of generating broken SQL.
467
+ */
468
+ class UnsupportedFeatureError extends TurbineError {
469
+ feature;
470
+ dialect;
471
+ constructor(feature, dialect, hint) {
472
+ super(exports.TurbineErrorCode.UNSUPPORTED_FEATURE, `[turbine] ${feature} is unsupported on "${dialect}".${hint ? ` ${hint}` : ''}`);
473
+ this.name = 'UnsupportedFeatureError';
474
+ this.feature = feature;
475
+ this.dialect = dialect;
476
+ }
477
+ }
478
+ exports.UnsupportedFeatureError = UnsupportedFeatureError;
461
479
  /**
462
480
  * Parse column names out of a pg `detail` string like:
463
481
  * "Key (email)=(foo@bar) already exists."
@@ -363,6 +363,10 @@ function generateMetadata(schema) {
363
363
  lines.push(' },');
364
364
  lines.push('};');
365
365
  lines.push('');
366
+ // Back-compat lowercase alias. `SCHEMA` is the canonical export, but docs and
367
+ // users frequently import `schema`; emit both so either name resolves.
368
+ lines.push('export const schema = SCHEMA;');
369
+ lines.push('');
366
370
  return lines.join('\n');
367
371
  }
368
372
  // ---------------------------------------------------------------------------
package/dist/cjs/index.js CHANGED
@@ -34,8 +34,8 @@
34
34
  * ```
35
35
  */
36
36
  Object.defineProperty(exports, "__esModule", { value: true });
37
- exports.column = exports.ColumnBuilder = exports.applyManyToManyRelations = exports.snakeToPascal = exports.snakeToCamel = exports.singularize = exports.pgTypeToTs = exports.pgArrayType = exports.normalizeKeyColumns = exports.isDateType = exports.camelToSnake = exports.validateChannel = exports.QueryInterface = exports.pipelineSupported = exports.executePipeline = exports.hasRelationFields = exports.executeNestedUpdate = exports.executeNestedCreate = exports.introspect = exports.generate = exports.wrapPgError = exports.ValidationError = exports.UniqueConstraintError = exports.TurbineErrorCode = exports.TurbineError = exports.TimeoutError = exports.setErrorMessageMode = exports.SerializationFailureError = exports.RelationError = exports.PipelineError = exports.OptimisticLockError = exports.NotNullViolationError = exports.NotFoundError = exports.MigrationError = exports.getErrorMessageMode = exports.ForeignKeyError = exports.ExclusionConstraintError = exports.DeadlockError = exports.ConnectionError = exports.CircularRelationError = exports.CheckConstraintError = exports.postgresDialect = exports.withRetry = exports.TurbineClient = exports.TransactionClient = exports.yugabytedb = exports.timescale = exports.postgresql = exports.cockroachdb = exports.alloydb = void 0;
38
- exports.TypedSqlQuery = exports.buildTypedSql = exports.turbineHttp = exports.schemaToSQLString = exports.schemaToSQL = exports.schemaPush = exports.schemaDiff = exports.table = exports.defineSchema = void 0;
37
+ exports.ColumnBuilder = exports.applyManyToManyRelations = exports.snakeToPascal = exports.snakeToCamel = exports.singularize = exports.pgTypeToTs = exports.pgArrayType = exports.normalizeKeyColumns = exports.isDateType = exports.camelToSnake = exports.validateChannel = exports.QueryInterface = exports.pipelineSupported = exports.executePipeline = exports.hasRelationFields = exports.executeNestedUpdate = exports.executeNestedCreate = exports.introspect = exports.generate = exports.wrapPgError = exports.ValidationError = exports.UnsupportedFeatureError = exports.UniqueConstraintError = exports.TurbineErrorCode = exports.TurbineError = exports.TimeoutError = exports.setErrorMessageMode = exports.SerializationFailureError = exports.RelationError = exports.PipelineError = exports.OptimisticLockError = exports.NotNullViolationError = exports.NotFoundError = exports.MigrationError = exports.getErrorMessageMode = exports.ForeignKeyError = exports.ExclusionConstraintError = exports.DeadlockError = exports.ConnectionError = exports.CircularRelationError = exports.CheckConstraintError = exports.postgresDialect = exports.withRetry = exports.TurbineClient = exports.TransactionClient = exports.yugabytedb = exports.timescale = exports.postgresql = exports.cockroachdb = exports.alloydb = void 0;
38
+ exports.TypedSqlQuery = exports.buildTypedSql = exports.turbineHttp = exports.schemaToSQLString = exports.schemaToSQL = exports.schemaPush = exports.schemaDiff = exports.table = exports.defineSchema = exports.column = void 0;
39
39
  var index_js_1 = require("./adapters/index.js");
40
40
  Object.defineProperty(exports, "alloydb", { enumerable: true, get: function () { return index_js_1.alloydb; } });
41
41
  Object.defineProperty(exports, "cockroachdb", { enumerable: true, get: function () { return index_js_1.cockroachdb; } });
@@ -70,6 +70,7 @@ Object.defineProperty(exports, "TimeoutError", { enumerable: true, get: function
70
70
  Object.defineProperty(exports, "TurbineError", { enumerable: true, get: function () { return errors_js_1.TurbineError; } });
71
71
  Object.defineProperty(exports, "TurbineErrorCode", { enumerable: true, get: function () { return errors_js_1.TurbineErrorCode; } });
72
72
  Object.defineProperty(exports, "UniqueConstraintError", { enumerable: true, get: function () { return errors_js_1.UniqueConstraintError; } });
73
+ Object.defineProperty(exports, "UnsupportedFeatureError", { enumerable: true, get: function () { return errors_js_1.UnsupportedFeatureError; } });
73
74
  Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return errors_js_1.ValidationError; } });
74
75
  Object.defineProperty(exports, "wrapPgError", { enumerable: true, get: function () { return errors_js_1.wrapPgError; } });
75
76
  // Code generation
@@ -13,6 +13,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.introspect = introspect;
16
+ exports.introspectPostgresCatalog = introspectPostgresCatalog;
16
17
  const pg_1 = __importDefault(require("pg"));
17
18
  const dialect_js_1 = require("./dialect.js");
18
19
  const schema_js_1 = require("./schema.js");
@@ -100,7 +101,26 @@ const SQL_ENUMS = `
100
101
  // ---------------------------------------------------------------------------
101
102
  // Main introspection function
102
103
  // ---------------------------------------------------------------------------
104
+ /**
105
+ * Introspect a database into {@link SchemaMetadata}, routing through the active
106
+ * dialect's {@link Dialect.introspector} so each engine can override the catalog
107
+ * SQL. PostgreSQL is driven by {@link introspectPostgresCatalog}.
108
+ */
103
109
  async function introspect(options) {
110
+ const dialect = options.dialect ?? dialect_js_1.postgresDialect;
111
+ const introspector = dialect.introspector;
112
+ if (introspector) {
113
+ return introspector.introspect(options);
114
+ }
115
+ // Dialects without an introspector fall back to the Postgres catalog reader.
116
+ return introspectPostgresCatalog(options);
117
+ }
118
+ /**
119
+ * PostgreSQL catalog introspector: reads information_schema + pg_catalog and
120
+ * produces {@link SchemaMetadata}. This is the implementation wrapped by
121
+ * `postgresDialect.introspector`; call {@link introspect} for dialect routing.
122
+ */
123
+ async function introspectPostgresCatalog(options) {
104
124
  const schema = options.schema ?? 'public';
105
125
  const dialect = dialect_js_1.postgresDialect;
106
126
  const pool = new pg_1.default.Pool({