ts-prorm-orm 1.2.2 → 2.0.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.
- package/CHANGELOG.md +209 -0
- package/README.md +32 -24
- package/dist/compliance/index.d.ts +2 -0
- package/dist/compliance/index.js +13 -1
- package/dist/connection-manager.js +13 -1
- package/dist/core/expressions.d.ts +58 -0
- package/dist/core/expressions.js +83 -0
- package/dist/core/hooks-manager.d.ts +179 -0
- package/dist/core/hooks-manager.js +291 -0
- package/dist/core/types.d.ts +235 -0
- package/dist/core/types.js +9 -0
- package/dist/decorators/index.d.ts +2 -0
- package/dist/decorators/index.js +11 -1
- package/dist/diagrams/chen-diagram.d.ts +15 -12
- package/dist/diagrams/chen-diagram.js +76 -85
- package/dist/diagrams/class-diagram.d.ts +9 -8
- package/dist/diagrams/class-diagram.js +60 -82
- package/dist/diagrams/core/index.d.ts +13 -0
- package/dist/diagrams/core/index.js +33 -0
- package/dist/diagrams/core/layout.d.ts +104 -0
- package/dist/diagrams/core/layout.js +223 -0
- package/dist/diagrams/{svg-dom.d.ts → core/svg.d.ts} +8 -20
- package/dist/diagrams/{svg-dom.js → core/svg.js} +21 -29
- package/dist/diagrams/core/theme.d.ts +84 -0
- package/dist/diagrams/core/theme.js +62 -0
- package/dist/diagrams/dependency-diagram.d.ts +15 -14
- package/dist/diagrams/dependency-diagram.js +71 -105
- package/dist/diagrams/er-diagram.d.ts +13 -26
- package/dist/diagrams/er-diagram.js +180 -259
- package/dist/diagrams/flow-diagram.d.ts +16 -11
- package/dist/diagrams/flow-diagram.js +96 -91
- package/dist/diagrams/gantt-diagram.d.ts +10 -5
- package/dist/diagrams/gantt-diagram.js +77 -103
- package/dist/diagrams/index-diagram.d.ts +10 -10
- package/dist/diagrams/index-diagram.js +106 -116
- package/dist/diagrams/index.d.ts +6 -9
- package/dist/diagrams/index.js +9 -24
- package/dist/diagrams/migration-diagram.d.ts +8 -4
- package/dist/diagrams/migration-diagram.js +189 -161
- package/dist/diagrams/model-diagram.d.ts +34 -34
- package/dist/diagrams/model-diagram.js +106 -485
- package/dist/diagrams/package-diagram.d.ts +9 -6
- package/dist/diagrams/package-diagram.js +64 -101
- package/dist/diagrams/relational-diagram.d.ts +12 -10
- package/dist/diagrams/relational-diagram.js +87 -114
- package/dist/diagrams/schemadoc-diagram.d.ts +8 -8
- package/dist/diagrams/schemadoc-diagram.js +71 -93
- package/dist/diagrams/sequence-diagram.d.ts +10 -10
- package/dist/diagrams/sequence-diagram.js +64 -89
- package/dist/diagrams/state-diagram.d.ts +10 -9
- package/dist/diagrams/state-diagram.js +69 -92
- package/dist/diagrams/tree-diagram.d.ts +11 -5
- package/dist/diagrams/tree-diagram.js +41 -65
- package/dist/dialects/clickhouse/index.js +15 -0
- package/dist/dialects/cockroachdb/index.d.ts +1 -1
- package/dist/dialects/cockroachdb/index.js +32 -63
- package/dist/dialects/db2/index.js +23 -8
- package/dist/dialects/dialect.d.ts +29 -5
- package/dist/dialects/duckdb/index.js +9 -2
- package/dist/dialects/hana/index.js +22 -5
- package/dist/dialects/lock-clause-helper.d.ts +167 -0
- package/dist/dialects/lock-clause-helper.js +316 -0
- package/dist/dialects/mariadb/index.d.ts +7 -4
- package/dist/dialects/mariadb/index.js +36 -60
- package/dist/dialects/mssql/index.js +34 -3
- package/dist/dialects/mysql/index.d.ts +1 -1
- package/dist/dialects/mysql/index.js +17 -45
- package/dist/dialects/oracle/index.d.ts +14 -3
- package/dist/dialects/oracle/index.js +66 -36
- package/dist/dialects/order-expression-helper.d.ts +72 -0
- package/dist/dialects/order-expression-helper.js +154 -0
- package/dist/dialects/partial-index.d.ts +52 -0
- package/dist/dialects/partial-index.js +251 -0
- package/dist/dialects/postgres/index.d.ts +1 -1
- package/dist/dialects/postgres/index.js +43 -68
- package/dist/dialects/redshift/index.js +9 -2
- package/dist/dialects/snowflake/index.js +17 -0
- package/dist/dialects/spanner/index.js +7 -2
- package/dist/dialects/sqlite/driver.d.ts +55 -0
- package/dist/dialects/sqlite/driver.js +102 -0
- package/dist/dialects/sqlite/index.d.ts +1 -1
- package/dist/dialects/sqlite/index.js +49 -27
- package/dist/graph/base-graph-dialect.d.ts +24 -3
- package/dist/graph/base-graph-dialect.js +43 -2
- package/dist/graph/dgraph/index.js +6 -0
- package/dist/graph/gremlin/index.d.ts +6 -0
- package/dist/graph/gremlin/index.js +12 -1
- package/dist/graph/index.d.ts +1 -1
- package/dist/graph/neo4j/index.d.ts +2 -0
- package/dist/graph/neo4j/index.js +6 -1
- package/dist/graph/types.d.ts +12 -1
- package/dist/index.d.ts +13 -4
- package/dist/index.js +54 -7
- package/dist/logging/index.d.ts +10 -0
- package/dist/logging/index.js +23 -0
- package/dist/logging/query-logging.d.ts +82 -0
- package/dist/logging/query-logging.js +102 -0
- package/dist/models/decorators.d.ts +39 -3
- package/dist/models/decorators.js +74 -0
- package/dist/models/eager-load.d.ts +99 -0
- package/dist/models/eager-load.js +348 -5
- package/dist/models/indexes.d.ts +3 -2
- package/dist/models/indexes.js +7 -1
- package/dist/models/model.js +69 -43
- package/dist/prorm.d.ts +175 -409
- package/dist/prorm.js +1142 -557
- package/dist/query-builders/order-limit-builder.js +12 -10
- package/dist/query-builders/sql-compiler.d.ts +10 -3
- package/dist/query-builders/sql-compiler.js +14 -43
- package/dist/query-interface.d.ts +2 -1
- package/dist/sql-constants.d.ts +44 -0
- package/dist/sql-constants.js +138 -1
- package/dist/types/index.d.ts +53 -17
- package/dist/types/index.js +10 -15
- package/dist/types/query-types.d.ts +26 -0
- package/dist/types/query-types.js +30 -0
- package/package.json +32 -5
- package/dist/decorators/belongs-to-many.js +0 -115
- package/dist/decorators/belongs-to.js +0 -115
- package/dist/decorators/has-many.js +0 -127
- package/dist/decorators/has-one.js +0 -116
- package/dist/diagrams/palette.d.ts +0 -138
- package/dist/diagrams/palette.js +0 -194
- package/dist/hooks/hooks-manager.d.ts +0 -189
- package/dist/hooks/hooks-manager.js +0 -350
- package/dist/hooks/index.d.ts +0 -8
- package/dist/hooks/index.js +0 -37
- /package/dist/{logging.d.ts → logging/logger.d.ts} +0 -0
- /package/dist/{logging.js → logging/logger.js} +0 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Runtime-appropriate SQLite driver.
|
|
4
|
+
*
|
|
5
|
+
* Node uses `better-sqlite3`, a native addon. Bun ships its own SQLite as the
|
|
6
|
+
* built-in `bun:sqlite`, which is faster there and needs no native build step —
|
|
7
|
+
* and under Bun the `better-sqlite3` addon may not be installable at all.
|
|
8
|
+
*
|
|
9
|
+
* The two APIs were designed to look alike, so the dialect can talk to either
|
|
10
|
+
* one unchanged. They differ in exactly one place: better-sqlite3 has
|
|
11
|
+
* `db.pragma()`, and bun:sqlite does not. This module adds it, so the dialect
|
|
12
|
+
* has a single shape to code against and no `if (isBun)` branches leak into the
|
|
13
|
+
* SQL layer.
|
|
14
|
+
*
|
|
15
|
+
* The driver is loaded lazily on first connect, so importing the ORM never
|
|
16
|
+
* dlopens a native binding or touches a `bun:` module on Node.
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.isBun = isBun;
|
|
20
|
+
exports.loadSqliteDriver = loadSqliteDriver;
|
|
21
|
+
exports.resetSqliteDriver = resetSqliteDriver;
|
|
22
|
+
/** True when running under Bun. */
|
|
23
|
+
function isBun() {
|
|
24
|
+
return typeof process !== 'undefined' && typeof process.versions?.bun === 'string';
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Give a bun:sqlite Database the `pragma()` method better-sqlite3 has.
|
|
28
|
+
*
|
|
29
|
+
* better-sqlite3's contract: `pragma('foreign_keys = ON')` sets and returns the
|
|
30
|
+
* resulting rows; `pragma('user_version', { simple: true })` returns the first
|
|
31
|
+
* column of the first row. `PRAGMA name = value` returns no rows, so a `simple`
|
|
32
|
+
* read of an assignment yields undefined in both drivers.
|
|
33
|
+
*/
|
|
34
|
+
function withPragma(db) {
|
|
35
|
+
const wrapped = db;
|
|
36
|
+
if (typeof db.pragma === 'function')
|
|
37
|
+
return wrapped;
|
|
38
|
+
wrapped.pragma = (source, options) => {
|
|
39
|
+
const rows = db.prepare(`PRAGMA ${source}`).all();
|
|
40
|
+
if (!options?.simple)
|
|
41
|
+
return rows;
|
|
42
|
+
const first = rows[0];
|
|
43
|
+
return first ? Object.values(first)[0] : undefined;
|
|
44
|
+
};
|
|
45
|
+
return wrapped;
|
|
46
|
+
}
|
|
47
|
+
let cached = null;
|
|
48
|
+
/**
|
|
49
|
+
* Resolve the SQLite driver for the current runtime.
|
|
50
|
+
*
|
|
51
|
+
* Under Bun this prefers `bun:sqlite` but falls back to `better-sqlite3` if it
|
|
52
|
+
* is installed and the built-in cannot be loaded, so an existing Bun project
|
|
53
|
+
* that already depends on better-sqlite3 keeps working.
|
|
54
|
+
*/
|
|
55
|
+
function loadSqliteDriver() {
|
|
56
|
+
if (cached)
|
|
57
|
+
return cached;
|
|
58
|
+
const attempts = [];
|
|
59
|
+
if (isBun()) {
|
|
60
|
+
attempts.push({
|
|
61
|
+
name: 'bun:sqlite',
|
|
62
|
+
load: () => {
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
64
|
+
const { Database } = require('bun:sqlite');
|
|
65
|
+
// bun:sqlite ignores better-sqlite3's `verbose`/`timeout`; pass through
|
|
66
|
+
// only what it understands so an unknown option can't throw.
|
|
67
|
+
return class BunDatabase {
|
|
68
|
+
constructor(filename, options) {
|
|
69
|
+
return withPragma(new Database(filename, {
|
|
70
|
+
readonly: options?.readonly ?? false,
|
|
71
|
+
create: !(options?.fileMustExist ?? false),
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
attempts.push({
|
|
79
|
+
name: 'better-sqlite3',
|
|
80
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
81
|
+
load: () => require('better-sqlite3'),
|
|
82
|
+
});
|
|
83
|
+
const failures = [];
|
|
84
|
+
for (const attempt of attempts) {
|
|
85
|
+
try {
|
|
86
|
+
cached = attempt.load();
|
|
87
|
+
return cached;
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
failures.push(`${attempt.name}: ${err instanceof Error ? err.message : String(err)}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
throw new Error('No SQLite driver could be loaded for the SQLite dialect. Tried ' +
|
|
94
|
+
attempts.map((a) => a.name).join(', ') +
|
|
95
|
+
'. On Node install better-sqlite3 (`npm install better-sqlite3`); on Bun the built-in ' +
|
|
96
|
+
'`bun:sqlite` is used and needs no install. Underlying errors — ' +
|
|
97
|
+
failures.join(' | '));
|
|
98
|
+
}
|
|
99
|
+
/** Test seam: forget the resolved driver. */
|
|
100
|
+
function resetSqliteDriver() {
|
|
101
|
+
cached = null;
|
|
102
|
+
}
|
|
@@ -6,27 +6,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.SQLiteTransaction = exports.SQLiteDialect = void 0;
|
|
7
7
|
exports.createSQLiteDialect = createSQLiteDialect;
|
|
8
8
|
const operators_1 = require("../../operators");
|
|
9
|
-
|
|
10
|
-
//
|
|
11
|
-
// better-sqlite3
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
try {
|
|
16
|
-
betterSqlite3Ctor = require('better-sqlite3');
|
|
17
|
-
}
|
|
18
|
-
catch (err) {
|
|
19
|
-
throw new Error("The 'better-sqlite3' package is required to use the SQLite dialect but could not be loaded. " +
|
|
20
|
-
'Install it with `npm install better-sqlite3`. Original error: ' +
|
|
21
|
-
(err instanceof Error ? err.message : String(err)));
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return betterSqlite3Ctor;
|
|
25
|
-
}
|
|
9
|
+
const partial_index_1 = require("../partial-index");
|
|
10
|
+
// The SQLite driver is resolved per runtime and loaded lazily on first connect:
|
|
11
|
+
// `better-sqlite3` on Node, the built-in `bun:sqlite` on Bun. See
|
|
12
|
+
// ./driver.ts — importing this ORM never dlopens a native binding, and no
|
|
13
|
+
// runtime branch leaks past that module.
|
|
14
|
+
const driver_1 = require("./driver");
|
|
26
15
|
const stream_1 = require("stream");
|
|
27
16
|
const prorm_1 = require("../../prorm");
|
|
28
17
|
const operators_2 = require("../../operators");
|
|
29
18
|
const sqlite_advanced_1 = require("../../sqlite-advanced");
|
|
19
|
+
const order_expression_helper_1 = require("../order-expression-helper");
|
|
30
20
|
/**
|
|
31
21
|
* SQLite dialect class that implements the Dialect interface
|
|
32
22
|
*/
|
|
@@ -54,7 +44,7 @@ class SQLiteDialect {
|
|
|
54
44
|
timeout: this.config.timeout || 5000,
|
|
55
45
|
verbose: this.config.verbose || undefined,
|
|
56
46
|
};
|
|
57
|
-
this.connection = new (
|
|
47
|
+
this.connection = new ((0, driver_1.loadSqliteDriver)())(this.config.storage, options);
|
|
58
48
|
this._isConnected = true;
|
|
59
49
|
// Enable foreign keys by default
|
|
60
50
|
this.connection.pragma('foreign_keys = ON');
|
|
@@ -160,8 +150,15 @@ class SQLiteDialect {
|
|
|
160
150
|
}
|
|
161
151
|
const sqlUpper = sql.trim().toUpperCase();
|
|
162
152
|
// EXPLAIN / EXPLAIN QUERY PLAN and WITH (CTE) statements also return rows.
|
|
153
|
+
//
|
|
154
|
+
// `PRAGMA name` is a query and returns a row; `PRAGMA name = value` is an
|
|
155
|
+
// assignment and returns nothing, and better-sqlite3 throws "This
|
|
156
|
+
// statement does not return data. Use run() instead" if you call .all()
|
|
157
|
+
// on it. Every PRAGMA was treated as a reader, so the assignment form -
|
|
158
|
+
// which is how disableForeignKeyChecks(), enableForeignKeyChecks() and
|
|
159
|
+
// setIsolationLevel() are implemented on SQLite - failed on every call.
|
|
163
160
|
const isSelect = sqlUpper.startsWith('SELECT') ||
|
|
164
|
-
sqlUpper.startsWith('PRAGMA') ||
|
|
161
|
+
(sqlUpper.startsWith('PRAGMA') && !sqlUpper.includes('=')) ||
|
|
165
162
|
sqlUpper.startsWith('EXPLAIN') ||
|
|
166
163
|
sqlUpper.startsWith('WITH');
|
|
167
164
|
const stmt = this.connection.prepare(sql);
|
|
@@ -706,6 +703,16 @@ class SQLiteDialect {
|
|
|
706
703
|
if (options?.initialAutoIncrement) {
|
|
707
704
|
console.warn(`SQLite: initialAutoIncrement option is not supported in CREATE TABLE`);
|
|
708
705
|
}
|
|
706
|
+
// Create the unique keys collected above.
|
|
707
|
+
//
|
|
708
|
+
// SQLite has no `ALTER TABLE ... ADD CONSTRAINT`, so a unique key that is
|
|
709
|
+
// not part of the CREATE TABLE text has to become a `CREATE UNIQUE INDEX`
|
|
710
|
+
// instead - which enforces exactly the same rule. This list was built and
|
|
711
|
+
// then never used, so `createTable(..., { uniqueKeys })` produced no SQL at
|
|
712
|
+
// all and the constraint the caller declared was never enforced.
|
|
713
|
+
for (const uk of uniqueKeysToCreate) {
|
|
714
|
+
await this.addIndex(tableName, uk.name, uk.fields, { unique: true });
|
|
715
|
+
}
|
|
709
716
|
// Create indexes after table creation
|
|
710
717
|
if (options?.indexes) {
|
|
711
718
|
for (const index of options.indexes) {
|
|
@@ -1849,10 +1856,16 @@ class SQLiteDialect {
|
|
|
1849
1856
|
else {
|
|
1850
1857
|
sql += ` (${fields.map((f) => this.escapeId(f)).join(', ')})`;
|
|
1851
1858
|
}
|
|
1852
|
-
// Add partial index WHERE clause (SQLite 3.8.0+)
|
|
1859
|
+
// Add partial index WHERE clause (SQLite 3.8.0+). The ordinary WHERE
|
|
1860
|
+
// builder is deliberately not used here: it emits bound placeholders, and
|
|
1861
|
+
// this DDL is executed without a value list, so SQLite rejected it with
|
|
1862
|
+
// "parameters prohibited in partial index WHERE clauses". The predicate is
|
|
1863
|
+
// compiled with its values inlined as escaped literals instead.
|
|
1853
1864
|
if (options?.where) {
|
|
1854
|
-
const
|
|
1855
|
-
|
|
1865
|
+
const predicate = (0, partial_index_1.buildPartialIndexPredicate)(options.where, this.name, this);
|
|
1866
|
+
if (predicate) {
|
|
1867
|
+
sql += ` WHERE ${predicate}`;
|
|
1868
|
+
}
|
|
1856
1869
|
}
|
|
1857
1870
|
await this.query(sql);
|
|
1858
1871
|
}
|
|
@@ -1892,9 +1905,12 @@ class SQLiteDialect {
|
|
|
1892
1905
|
if (indexDef.using) {
|
|
1893
1906
|
sql += ` USING ${indexDef.using}`;
|
|
1894
1907
|
}
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1908
|
+
// Partial index predicate - inlined literals, not placeholders. See addIndex.
|
|
1909
|
+
if (indexDef.where) {
|
|
1910
|
+
const predicate = (0, partial_index_1.buildPartialIndexPredicate)(indexDef.where, this.name, this);
|
|
1911
|
+
if (predicate) {
|
|
1912
|
+
sql += ` WHERE ${predicate}`;
|
|
1913
|
+
}
|
|
1898
1914
|
}
|
|
1899
1915
|
await this.query(sql);
|
|
1900
1916
|
}
|
|
@@ -2352,12 +2368,18 @@ class SQLiteDialect {
|
|
|
2352
2368
|
* Build an ORDER BY clause
|
|
2353
2369
|
*/
|
|
2354
2370
|
buildOrderClause(order, options) {
|
|
2355
|
-
const orderArray = order;
|
|
2356
|
-
if (
|
|
2371
|
+
const orderArray = (0, order_expression_helper_1.normalizeOrderItems)(order);
|
|
2372
|
+
if (orderArray.length === 0) {
|
|
2357
2373
|
return '';
|
|
2358
2374
|
}
|
|
2359
2375
|
const orderParts = [];
|
|
2360
2376
|
for (const item of orderArray) {
|
|
2377
|
+
// Order helpers: asc('name') / desc('name') / random()
|
|
2378
|
+
const orderExpr = (0, order_expression_helper_1.renderOrderExpressionItem)(this, item);
|
|
2379
|
+
if (orderExpr !== null) {
|
|
2380
|
+
orderParts.push(orderExpr);
|
|
2381
|
+
continue;
|
|
2382
|
+
}
|
|
2361
2383
|
if (Array.isArray(item)) {
|
|
2362
2384
|
const field = typeof item[0] === 'string' ? this.escapeId(item[0]) : item[0];
|
|
2363
2385
|
const direction = item[1] ? ` ${item[1]}` : '';
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
import { Readable } from 'stream';
|
|
26
26
|
import { BaseDialect, type ColumnDefinition, type ConstraintDefinition, type DropConstraintOptions, type DropIndexOptions, type DropSchemaOptions, type DropTableOptions, type DropViewOptions, type IndexDefinition, type IndexOptions, type InsertOptions, type TableDescription, type TableOptions, type UpdateOptions, type DeleteOptions, type SelectOptions, type UpsertQueryOptions, type ViewOptions, type BuildOptions } from '../dialects/dialect';
|
|
27
27
|
import type { DataType, Order, QueryOptions, QueryResult, StreamOptions, Transaction, TransactionOptions, WhereOptions, MaterializedViewOptions, RefreshOptions, DropMaterializedViewOptions, StoredProcedureOptions, DropStoredProcedureOptions, ExecuteStoredProcedureOptions, TriggerOptions, DropTriggerOptions, SequenceOptions, DropSequenceOptions, PolicyOptions, DropPolicyOptions, CreatePartitionOptions, AttachPartitionOptions, DetachPartitionOptions } from '../types';
|
|
28
|
-
import { ParamBag, type GraphConnectionOptions, type GraphPredicate, type GraphStatement, type GraphTraversalSpec, type GraphTraversalStep, type NodeMatchSpec, type NodeModelDefinition, type EdgeModelDefinition } from './types';
|
|
28
|
+
import { ParamBag, type GraphConnectionOptions, type GraphPredicate, type GraphStatement, type GraphTraversalSpec, type GraphTraversalStep, type GraphOrderTerm, type NodeMatchSpec, type NodeModelDefinition, type EdgeModelDefinition } from './types';
|
|
29
29
|
/** Context passed to {@link BaseGraphDialect.renderPredicate}. */
|
|
30
30
|
export interface WhereRenderContext {
|
|
31
31
|
/** Variable the predicate's properties are addressed through (e.g. `n`). */
|
|
@@ -110,8 +110,29 @@ export declare abstract class BaseGraphDialect extends BaseDialect {
|
|
|
110
110
|
protected run(stmt: GraphStatement, options?: QueryOptions): Promise<QueryResult>;
|
|
111
111
|
/** Positional param array for the SQL-shaped `{ sql, values }` contract. */
|
|
112
112
|
protected paramValues(stmt: GraphStatement): unknown[];
|
|
113
|
-
/**
|
|
114
|
-
|
|
113
|
+
/**
|
|
114
|
+
* The engine-native term that shuffles results, or `null` when this graph
|
|
115
|
+
* engine has no random ordering at all.
|
|
116
|
+
*
|
|
117
|
+
* Cypher has `rand()` and Gremlin has `order().by(shuffle)`; Dgraph DQL's
|
|
118
|
+
* `orderasc`/`orderdesc` only take a predicate, so it keeps the `null`
|
|
119
|
+
* default and {@link requireRandomOrderTerm} raises the typed capability
|
|
120
|
+
* error instead of emitting something that would silently not shuffle.
|
|
121
|
+
*/
|
|
122
|
+
protected randomOrderTerm(): string | null;
|
|
123
|
+
/** {@link randomOrderTerm}, raising `GraphCapabilityError` when unsupported. */
|
|
124
|
+
protected requireRandomOrderTerm(): string;
|
|
125
|
+
/**
|
|
126
|
+
* Tolerant `Order` -> `[field, dir][]` normalizer.
|
|
127
|
+
*
|
|
128
|
+
* Also understands the `asc()` / `desc()` / `random()` order helpers from
|
|
129
|
+
* `src/operators.ts`. They arrive as plain `OrderExpression` objects, so
|
|
130
|
+
* without an explicit branch they fell through the `$col`/`column` check
|
|
131
|
+
* below and were dropped silently — the helpers simply did nothing on
|
|
132
|
+
* every graph dialect. `random()` becomes a `'RANDOM'` term with no field,
|
|
133
|
+
* which each `compile*` translates (or refuses) in its own language.
|
|
134
|
+
*/
|
|
135
|
+
protected normalizeOrder(order?: Order): GraphOrderTerm[];
|
|
115
136
|
/** Map ORM `include` entries into graph traversal steps. */
|
|
116
137
|
protected mapIncludes(include?: any[]): GraphTraversalStep[];
|
|
117
138
|
buildWhereClause(where: WhereOptions, _options?: BuildOptions): {
|
|
@@ -28,6 +28,7 @@ exports.BaseGraphDialect = void 0;
|
|
|
28
28
|
const stream_1 = require("stream");
|
|
29
29
|
const dialect_1 = require("../dialects/dialect");
|
|
30
30
|
const types_1 = require("./types");
|
|
31
|
+
const operators_1 = require("../operators");
|
|
31
32
|
class BaseGraphDialect extends dialect_1.BaseDialect {
|
|
32
33
|
constructor(options = {}) {
|
|
33
34
|
super();
|
|
@@ -101,7 +102,36 @@ class BaseGraphDialect extends dialect_1.BaseDialect {
|
|
|
101
102
|
paramValues(stmt) {
|
|
102
103
|
return Object.values(stmt.params);
|
|
103
104
|
}
|
|
104
|
-
/**
|
|
105
|
+
/**
|
|
106
|
+
* The engine-native term that shuffles results, or `null` when this graph
|
|
107
|
+
* engine has no random ordering at all.
|
|
108
|
+
*
|
|
109
|
+
* Cypher has `rand()` and Gremlin has `order().by(shuffle)`; Dgraph DQL's
|
|
110
|
+
* `orderasc`/`orderdesc` only take a predicate, so it keeps the `null`
|
|
111
|
+
* default and {@link requireRandomOrderTerm} raises the typed capability
|
|
112
|
+
* error instead of emitting something that would silently not shuffle.
|
|
113
|
+
*/
|
|
114
|
+
randomOrderTerm() {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
/** {@link randomOrderTerm}, raising `GraphCapabilityError` when unsupported. */
|
|
118
|
+
requireRandomOrderTerm() {
|
|
119
|
+
const term = this.randomOrderTerm();
|
|
120
|
+
if (term === null) {
|
|
121
|
+
throw new types_1.GraphCapabilityError('random ordering', this.name);
|
|
122
|
+
}
|
|
123
|
+
return term;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Tolerant `Order` -> `[field, dir][]` normalizer.
|
|
127
|
+
*
|
|
128
|
+
* Also understands the `asc()` / `desc()` / `random()` order helpers from
|
|
129
|
+
* `src/operators.ts`. They arrive as plain `OrderExpression` objects, so
|
|
130
|
+
* without an explicit branch they fell through the `$col`/`column` check
|
|
131
|
+
* below and were dropped silently — the helpers simply did nothing on
|
|
132
|
+
* every graph dialect. `random()` becomes a `'RANDOM'` term with no field,
|
|
133
|
+
* which each `compile*` translates (or refuses) in its own language.
|
|
134
|
+
*/
|
|
105
135
|
normalizeOrder(order) {
|
|
106
136
|
if (!order)
|
|
107
137
|
return [];
|
|
@@ -111,6 +141,15 @@ class BaseGraphDialect extends dialect_1.BaseDialect {
|
|
|
111
141
|
if (typeof item === 'string') {
|
|
112
142
|
out.push([item, 'ASC']);
|
|
113
143
|
}
|
|
144
|
+
else if ((0, operators_1.isOrderExpression)(item)) {
|
|
145
|
+
const dir = String(item.direction || 'ASC').toUpperCase();
|
|
146
|
+
if (dir === 'RANDOM') {
|
|
147
|
+
out.push(['', 'RANDOM']);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
out.push([item.field, dir === 'DESC' ? 'DESC' : 'ASC']);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
114
153
|
else if (Array.isArray(item)) {
|
|
115
154
|
const rawField = item[0];
|
|
116
155
|
const field = String(rawField && rawField.$col ? rawField.$col : rawField);
|
|
@@ -159,7 +198,9 @@ class BaseGraphDialect extends dialect_1.BaseDialect {
|
|
|
159
198
|
}
|
|
160
199
|
buildOrderClause(order, _options) {
|
|
161
200
|
return this.normalizeOrder(order)
|
|
162
|
-
.map(([field, dir]) =>
|
|
201
|
+
.map(([field, dir]) => dir === 'RANDOM'
|
|
202
|
+
? this.requireRandomOrderTerm()
|
|
203
|
+
: `${this.defaultNodeVar}.${(0, types_1.safeIdent)(field)} ${dir}`)
|
|
163
204
|
.join(', ');
|
|
164
205
|
}
|
|
165
206
|
buildLimitOffset(limit, offset) {
|
|
@@ -404,6 +404,12 @@ class DgraphGraphDialect extends base_graph_dialect_1.BaseGraphDialect {
|
|
|
404
404
|
const filter = this.renderDql((0, types_2.normalizeWhere)(spec.where), params);
|
|
405
405
|
const funcArgs = [`func: type(${label})`];
|
|
406
406
|
const order = spec.order || [];
|
|
407
|
+
// DQL's `orderasc`/`orderdesc` only take a predicate name — Dgraph has no
|
|
408
|
+
// random ordering at all, so `random()` raises the typed capability error
|
|
409
|
+
// instead of quietly ordering by whatever else was asked for.
|
|
410
|
+
if (order.some(([, d]) => d === 'RANDOM')) {
|
|
411
|
+
this.requireRandomOrderTerm();
|
|
412
|
+
}
|
|
407
413
|
if (order.length) {
|
|
408
414
|
const [f, d] = order[0];
|
|
409
415
|
funcArgs.push(`${d === 'DESC' ? 'orderdesc' : 'orderasc'}: ${(0, types_2.safeIdent)(f)}`);
|
|
@@ -28,6 +28,12 @@ export declare class GremlinGraphDialect extends BaseGraphDialect {
|
|
|
28
28
|
readonly library = "gremlin";
|
|
29
29
|
private client;
|
|
30
30
|
constructor(options?: GraphConnectionOptions);
|
|
31
|
+
/**
|
|
32
|
+
* TinkerPop shuffles with `order().by(shuffle)` — `shuffle` is a
|
|
33
|
+
* comparator token, not a property name, so it is emitted as a bare
|
|
34
|
+
* `.by(shuffle)` step (never quoted like a property key).
|
|
35
|
+
*/
|
|
36
|
+
protected randomOrderTerm(): string;
|
|
31
37
|
protected get defaultNodeVar(): string;
|
|
32
38
|
connect(): Promise<void>;
|
|
33
39
|
disconnect(): Promise<void>;
|
|
@@ -36,6 +36,14 @@ class GremlinGraphDialect extends base_graph_dialect_1.BaseGraphDialect {
|
|
|
36
36
|
this.client = null;
|
|
37
37
|
this.dialectName = 'gremlin';
|
|
38
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* TinkerPop shuffles with `order().by(shuffle)` — `shuffle` is a
|
|
41
|
+
* comparator token, not a property name, so it is emitted as a bare
|
|
42
|
+
* `.by(shuffle)` step (never quoted like a property key).
|
|
43
|
+
*/
|
|
44
|
+
randomOrderTerm() {
|
|
45
|
+
return 'shuffle';
|
|
46
|
+
}
|
|
39
47
|
get defaultNodeVar() {
|
|
40
48
|
return 'it';
|
|
41
49
|
}
|
|
@@ -220,7 +228,10 @@ class GremlinGraphDialect extends base_graph_dialect_1.BaseGraphDialect {
|
|
|
220
228
|
if (order.length) {
|
|
221
229
|
text += '.order()';
|
|
222
230
|
for (const [f, d] of order) {
|
|
223
|
-
text +=
|
|
231
|
+
text +=
|
|
232
|
+
d === 'RANDOM'
|
|
233
|
+
? `.by(${this.requireRandomOrderTerm()})`
|
|
234
|
+
: `.by(${gremlinStr(f)}, ${d === 'DESC' ? 'desc' : 'asc'})`;
|
|
224
235
|
}
|
|
225
236
|
}
|
|
226
237
|
const offset = spec.offset !== undefined && spec.offset !== null ? Number(spec.offset) : 0;
|
package/dist/graph/index.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ export { Neo4jGraphDialect } from './neo4j';
|
|
|
28
28
|
export { GremlinGraphDialect } from './gremlin';
|
|
29
29
|
export { DgraphGraphDialect } from './dgraph';
|
|
30
30
|
export { GraphCapabilityError, ParamBag, normalizeWhere, deriveAssociationEdge, defaultEdgeLabel, safeIdent, } from './types';
|
|
31
|
-
export type { GraphConnectionOptions, GraphStatement, GraphPredicate, CanonOp, GraphAssociationType, GraphAssociationSpec, GraphPropertyDefinition, NodeModelDefinition, EdgeModelDefinition, GraphTraversalDirection, GraphTraversalStep, GraphTraversalSpec, NodeMatchSpec, } from './types';
|
|
31
|
+
export type { GraphConnectionOptions, GraphStatement, GraphPredicate, CanonOp, GraphAssociationType, GraphAssociationSpec, GraphPropertyDefinition, NodeModelDefinition, EdgeModelDefinition, GraphTraversalDirection, GraphTraversalStep, GraphTraversalSpec, GraphOrderDirection, GraphOrderTerm, NodeMatchSpec, } from './types';
|
|
32
32
|
/** The graph dialects keyed by the name they should register under. */
|
|
33
33
|
export declare const GRAPH_DIALECTS: {
|
|
34
34
|
readonly neo4j: typeof Neo4jGraphDialect;
|
|
@@ -22,6 +22,8 @@ export declare class Neo4jGraphDialect extends BaseGraphDialect {
|
|
|
22
22
|
private readonly txns;
|
|
23
23
|
constructor(options?: GraphConnectionOptions);
|
|
24
24
|
protected get defaultNodeVar(): string;
|
|
25
|
+
/** Cypher shuffles with the built-in `rand()` function. */
|
|
26
|
+
protected randomOrderTerm(): string;
|
|
25
27
|
connect(): Promise<void>;
|
|
26
28
|
disconnect(): Promise<void>;
|
|
27
29
|
private requireDriver;
|
|
@@ -44,6 +44,10 @@ class Neo4jGraphDialect extends base_graph_dialect_1.BaseGraphDialect {
|
|
|
44
44
|
get defaultNodeVar() {
|
|
45
45
|
return 'n';
|
|
46
46
|
}
|
|
47
|
+
/** Cypher shuffles with the built-in `rand()` function. */
|
|
48
|
+
randomOrderTerm() {
|
|
49
|
+
return 'rand()';
|
|
50
|
+
}
|
|
47
51
|
// -------------------------------------------------------------------
|
|
48
52
|
// Connection lifecycle
|
|
49
53
|
// -------------------------------------------------------------------
|
|
@@ -293,7 +297,8 @@ class Neo4jGraphDialect extends base_graph_dialect_1.BaseGraphDialect {
|
|
|
293
297
|
text += `\nRETURN ${distinct}${projection}${includeReturns.length ? ', ' + includeReturns.join(', ') : ''}`;
|
|
294
298
|
const order = spec.order || [];
|
|
295
299
|
if (order.length) {
|
|
296
|
-
|
|
300
|
+
const terms = order.map(([f, d]) => d === 'RANDOM' ? this.requireRandomOrderTerm() : `${v}.${(0, types_2.safeIdent)(f)} ${d}`);
|
|
301
|
+
text += `\nORDER BY ${terms.join(', ')}`;
|
|
297
302
|
}
|
|
298
303
|
if (spec.offset !== undefined && spec.offset !== null && String(spec.offset) !== '') {
|
|
299
304
|
text += `\nSKIP ${Number(spec.offset)}`;
|
package/dist/graph/types.d.ts
CHANGED
|
@@ -142,6 +142,17 @@ export interface GraphTraversalSpec {
|
|
|
142
142
|
targetWhere?: WhereOptions;
|
|
143
143
|
limit?: number;
|
|
144
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Direction of one normalized order term.
|
|
147
|
+
*
|
|
148
|
+
* `'RANDOM'` comes from the `random()` order helper (`src/operators.ts`) and
|
|
149
|
+
* carries no field — the engines that can shuffle express it as a whole term
|
|
150
|
+
* of their own (Cypher `rand()`, Gremlin `order().by(shuffle)`), and the ones
|
|
151
|
+
* that cannot raise a {@link GraphCapabilityError}.
|
|
152
|
+
*/
|
|
153
|
+
export type GraphOrderDirection = 'ASC' | 'DESC' | 'RANDOM';
|
|
154
|
+
/** One normalized order term: the property to sort on and its direction. */
|
|
155
|
+
export type GraphOrderTerm = [string, GraphOrderDirection];
|
|
145
156
|
/** Options for a node find/match. */
|
|
146
157
|
export interface NodeMatchSpec {
|
|
147
158
|
label: string;
|
|
@@ -150,7 +161,7 @@ export interface NodeMatchSpec {
|
|
|
150
161
|
include?: string[];
|
|
151
162
|
exclude?: string[];
|
|
152
163
|
};
|
|
153
|
-
order?:
|
|
164
|
+
order?: GraphOrderTerm[] | string[];
|
|
154
165
|
limit?: number | string;
|
|
155
166
|
offset?: number | string;
|
|
156
167
|
/** Associations to co-fetch as graph walks. */
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export { ConnectionManager, createConnectionManager, NamedConnectionOptions } fr
|
|
|
8
8
|
export { DataTypes, AbstractDataType } from './models/data-types';
|
|
9
9
|
export { CreationOptional, NonAttribute, ForeignKey, InferAttributes, InferCreationAttributes, PartialBy, RequiredBy, ModelStatic, ModelOptions, } from './models/typescript-types';
|
|
10
10
|
export { Model } from './models';
|
|
11
|
-
export { Table, Attribute, Column, AllowNull, PrimaryKey, AutoIncrement, NotNull, Default, Unique, Comment, getModelMetadata, getAttributeMetadata, getModelAttributes, clearMetadata, HasOneOptions, HasManyOptions, BelongsToOptions, BelongsToManyOptions, HasOne, HasMany, BelongsTo, BelongsToMany, } from './models/decorators';
|
|
11
|
+
export { Table, AbstractModel, isAbstractModel, getInheritedAttributeMetadata, Attribute, Column, AllowNull, PrimaryKey, AutoIncrement, NotNull, Default, Unique, Comment, getModelMetadata, getAttributeMetadata, getModelAttributes, clearMetadata, HasOneOptions, HasManyOptions, BelongsToOptions, BelongsToManyOptions, HasOne, HasMany, BelongsTo, BelongsToMany, } from './models/decorators';
|
|
12
12
|
export * from './compliance';
|
|
13
13
|
export * from './extensions';
|
|
14
14
|
export declare const STRING: ((...args: any[]) => import("./models").STRING) & {
|
|
@@ -163,7 +163,7 @@ export declare const GEOGRAPHY: ((...args: any[]) => import("./models").GEOGRAPH
|
|
|
163
163
|
};
|
|
164
164
|
export { Op } from './models/operators';
|
|
165
165
|
export type { Operator } from './models/operators';
|
|
166
|
-
export { Op as Operators, Operators as OpAliases, getOperatorString, operatorToWhereKey, where, and, or, not, eq, ne, gt, gte, lt, lte, like, notLike, iLike, notILike, startsWith, notStartsWith, endsWith, notEndsWith, substring, notSubstring, match, regexp, notRegexp, iRegexp, notIRegexp, in as in, inOp, notIn, between, notBetween, isNull, isNotNull, contains, overlap, asc, desc, random, isOrderExpression, } from './operators';
|
|
166
|
+
export { Op as Operators, Operators as OpAliases, getOperatorString, operatorToWhereKey, normalizeOperatorKeys, where, and, or, not, eq, ne, gt, gte, lt, lte, like, notLike, iLike, notILike, startsWith, notStartsWith, endsWith, notEndsWith, substring, notSubstring, match, regexp, notRegexp, iRegexp, notIRegexp, in as in, inOp, notIn, between, notBetween, isNull, isNotNull, contains, overlap, asc, desc, random, isOrderExpression, } from './operators';
|
|
167
167
|
export type { OperatorSymbol, WhereConditionOptions, OrderExpression } from './operators';
|
|
168
168
|
export * from './operators/index';
|
|
169
169
|
export { Transaction } from './types';
|
|
@@ -172,6 +172,8 @@ export { ReplicaManager } from './replica-manager';
|
|
|
172
172
|
export type { ReplicaStatus, ReplicaConnectionConfig, LagDetectionConfig, ReplicationOptions, RoutingStrategy, } from './replica-manager';
|
|
173
173
|
export { Dialect, BaseDialect, DialectRegistry } from './dialects/dialect';
|
|
174
174
|
export { BaseGraphDialect, Neo4jGraphDialect, GremlinGraphDialect, DgraphGraphDialect, GRAPH_DIALECTS, registerGraphDialects, } from './graph';
|
|
175
|
+
export { GraphCapabilityError, ParamBag, normalizeWhere, deriveAssociationEdge, defaultEdgeLabel, safeIdent, } from './graph';
|
|
176
|
+
export type { GraphConnectionOptions, GraphStatement, GraphPredicate, CanonOp, GraphAssociationType, GraphAssociationSpec, GraphPropertyDefinition, NodeModelDefinition, EdgeModelDefinition, GraphTraversalDirection, GraphTraversalStep, GraphTraversalSpec, NodeMatchSpec, WhereRenderContext, EdgeCreateSpec, NodeConstraintKind, DialectRegistryLike, } from './graph';
|
|
175
177
|
export type { DialectOptions, ColumnDefinition, TableOptions, DropTableOptions, TableDescription, IndexOptions, BuildOptions, InsertOptions, UpdateOptions as DialectUpdateOptions, DeleteOptions, SelectOptions, CTEOption, CreateExtensionOptions, DropExtensionOptions, ExtensionInfo, } from './dialects/dialect';
|
|
176
178
|
export { SQLiteDialect } from './dialects/sqlite';
|
|
177
179
|
export { OracleDialect, createOracleDialect } from './dialects/oracle';
|
|
@@ -210,11 +212,18 @@ export { UserManager, PRIVILEGE_LEVELS } from './user-management';
|
|
|
210
212
|
export type { PrivilegeType, PrivilegeScope, CreateUserOptions, AlterUserOptions, GrantOptions, RevokeOptions, RoleOptions, UserInfo, PrivilegeInfo, } from './user-management';
|
|
211
213
|
export { SQLiteAdvanced, createSQLiteAdvanced } from './sqlite-advanced';
|
|
212
214
|
export type { TriggerTiming, TriggerEvent, FTS5Tokenizer, GeneratedStorageType, ConflictAlgorithm, } from './sqlite-advanced';
|
|
213
|
-
export { SQL, MYSQL, MARIADB, POSTGRES, SQLITE, getConstantsForDialect, IsolationLevelEnum, IsolationLevelValue, } from './sql-constants';
|
|
214
|
-
export type { SQLConstants, MySQLConstants, PostgresConstants, SQLiteConstants, IsolationLevel, ForeignKeyChecks, UniqueKeyChecks, Autocommit, Cache, SqlMode, PragmaSettings, ConstraintDeferral, SearchPath, } from './sql-constants';
|
|
215
|
+
export { SQL, MYSQL, MARIADB, POSTGRES, SQLITE, getConstantsForDialect, getForeignKeyChecksSQL, UnsupportedForeignKeyChecksError, IsolationLevelEnum, IsolationLevelValue, } from './sql-constants';
|
|
216
|
+
export type { ForeignKeyChecksMode, SQLConstants, MySQLConstants, PostgresConstants, SQLiteConstants, IsolationLevel, ForeignKeyChecks, UniqueKeyChecks, Autocommit, Cache, SqlMode, PragmaSettings, ConstraintDeferral, SearchPath, } from './sql-constants';
|
|
215
217
|
export * from './nosql';
|
|
216
218
|
export { count, countDistinct, avg, min, max, stringAgg, arrayAgg, CaseBuilder, SimpleCaseBuilder, caseWhen, caseOf, dateTrunc, dateAdd, dateSub, dateDiff, currentDate, currentTimestamp, fullTextMatch, fullTextRank, jsonExtract, jsonKeys, jsonTypeOf, round, ceil, floor, power, sqrt, abs, sign, mod, greatest, least, concat, upper, lower, length, replace, lpad, rpad, split, WindowFunctionBuilder, rowNumber, rank, denseRank, percentRank, cumeDist, ntile, lag, lead, firstValue, lastValue, nthValue, sumOver, avgOver, countOver, minOver, maxOver, windowFn, NullsOrder, } from './query-builders/functions';
|
|
217
219
|
export { random as sqlRandom, truncate as sqlTruncate, substring as sqlSubstring, trim as sqlTrim, ltrim as sqlLtrim, rtrim as sqlRtrim, jsonContains as sqlJsonContains, jsonHasKey as sqlJsonHasKey, formatDate as sqlFormatDate, now as sqlNow, repeat as sqlRepeat, reverse as sqlReverse, sum as sqlSum, } from './query-builders/functions';
|
|
220
|
+
export { AbstractCacheManager, RedisClusterCache, createRedisClusterCache } from './cache';
|
|
221
|
+
export type { CacheBackend, L2CacheOptions, CacheKeyOptions, CacheStats, CacheBackendFactory, RedisClusterOptions, RedisClusterNodeConfig, } from './cache';
|
|
222
|
+
export type { CacheEntry as CacheManagerEntry, CacheManagerOptions as CacheManagerConfig, L1CacheOptions as CacheManagerL1Options, RedisClusterCacheOptions as RedisClusterCacheConfig, RedisClusterNode as RedisClusterCacheNode, } from './cache';
|
|
223
|
+
export { AuditLogger, setAuditLogger, getAuditLogger, addAuditHistoryToModel, addAuditHistoryToInstance, } from './audit';
|
|
224
|
+
export type { AuditLog, AuditLoggerOptions } from './audit';
|
|
225
|
+
export { convertPrismaSchema, parsePrismaSchema, resolveRelations } from './prisma-migrate';
|
|
226
|
+
export type { ConversionResult, PrismaSchema, PrismaModel, PrismaEnum, PrismaField, PrormRelation, } from './prisma-migrate';
|
|
218
227
|
import { Prorm } from './prorm';
|
|
219
228
|
import { Transaction } from './types';
|
|
220
229
|
declare const ORM: {
|