turbine-orm 0.10.0 → 0.11.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/dist/cjs/client.js +1 -0
- package/dist/cjs/dialect.js +57 -0
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/query/builder.js +111 -95
- package/dist/cjs/query/index.js +3 -1
- package/dist/client.d.ts +3 -0
- package/dist/client.js +1 -0
- package/dist/dialect.d.ts +61 -0
- package/dist/dialect.js +55 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/query/builder.d.ts +9 -1
- package/dist/query/builder.js +112 -96
- package/dist/query/index.d.ts +2 -0
- package/dist/query/index.js +1 -0
- package/package.json +3 -3
package/dist/cjs/query/index.js
CHANGED
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
* former monolithic `import { … } from './query.js'`.
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.QueryInterface = exports.sqlToPreparedName = exports.quoteIdent = exports.OPERATOR_KEYS = exports.LRUCache = exports.fnv1a64Hex = exports.escSingleQuote = exports.escapeLike = exports.buildCorrelation = void 0;
|
|
10
|
+
exports.QueryInterface = exports.sqlToPreparedName = exports.quoteIdent = exports.OPERATOR_KEYS = exports.LRUCache = exports.fnv1a64Hex = exports.escSingleQuote = exports.escapeLike = exports.buildCorrelation = exports.postgresDialect = void 0;
|
|
11
|
+
var dialect_js_1 = require("../dialect.js");
|
|
12
|
+
Object.defineProperty(exports, "postgresDialect", { enumerable: true, get: function () { return dialect_js_1.postgresDialect; } });
|
|
11
13
|
var utils_js_1 = require("./utils.js");
|
|
12
14
|
Object.defineProperty(exports, "buildCorrelation", { enumerable: true, get: function () { return utils_js_1.buildCorrelation; } });
|
|
13
15
|
Object.defineProperty(exports, "escapeLike", { enumerable: true, get: function () { return utils_js_1.escapeLike; } });
|
package/dist/client.d.ts
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
24
|
import pg from 'pg';
|
|
25
|
+
import type { Dialect } from './dialect.js';
|
|
25
26
|
import { type ErrorMessageMode } from './errors.js';
|
|
26
27
|
import { type PipelineOptions, type PipelineResults } from './pipeline.js';
|
|
27
28
|
import { type DeferredQuery, QueryInterface, type QueryInterfaceOptions } from './query/index.js';
|
|
@@ -142,6 +143,8 @@ export interface TurbineConfig {
|
|
|
142
143
|
* Default: `true`. Set to `false` as a nuclear kill switch.
|
|
143
144
|
*/
|
|
144
145
|
sqlCache?: boolean;
|
|
146
|
+
/** SQL dialect implementation. Defaults to PostgreSQL. Internal Phase-1 seam for dialect packages. */
|
|
147
|
+
dialect?: Dialect;
|
|
145
148
|
}
|
|
146
149
|
/** Parameters passed to middleware functions */
|
|
147
150
|
export interface MiddlewareParams {
|
package/dist/client.js
CHANGED
|
@@ -197,6 +197,7 @@ export class TurbineClient {
|
|
|
197
197
|
warnOnUnlimited: config.warnOnUnlimited,
|
|
198
198
|
preparedStatements: envDisablePrepared ? false : (config.preparedStatements ?? !config.pool),
|
|
199
199
|
sqlCache: config.sqlCache ?? true,
|
|
200
|
+
dialect: config.dialect,
|
|
200
201
|
};
|
|
201
202
|
// Apply NotFoundError message redaction mode (default: safe — values are
|
|
202
203
|
// stripped from messages to avoid leaking PII into error logs).
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* turbine-orm — SQL dialect contract
|
|
3
|
+
*
|
|
4
|
+
* Phase-1 seam for future database packages. The current package remains
|
|
5
|
+
* PostgreSQL-native by default, but query generation now depends on this
|
|
6
|
+
* contract for the SQL primitives that vary across MySQL and SQLite.
|
|
7
|
+
*/
|
|
8
|
+
import type { SchemaMetadata } from './schema.js';
|
|
9
|
+
export type DialectName = 'postgresql' | 'mysql' | 'sqlite' | (string & {});
|
|
10
|
+
export interface Dialect {
|
|
11
|
+
/** Dialect identifier. */
|
|
12
|
+
readonly name: DialectName;
|
|
13
|
+
/** Parameter placeholder for the Nth value, using a 1-indexed public count. */
|
|
14
|
+
paramPlaceholder(index: number): string;
|
|
15
|
+
/** Quote a SQL identifier (table, column, cursor, alias). */
|
|
16
|
+
quoteIdentifier(name: string): string;
|
|
17
|
+
/** Escape a string literal body for SQL single-quoted strings. */
|
|
18
|
+
escapeStringLiteral(value: string): string;
|
|
19
|
+
/** Empty JSON array literal used as a fallback for to-many relations. */
|
|
20
|
+
readonly emptyJsonArrayLiteral: string;
|
|
21
|
+
/** JSON null literal/fallback for to-one relations. */
|
|
22
|
+
readonly nullJsonLiteral: string;
|
|
23
|
+
/** Build a JSON object expression from output keys and SQL expressions. */
|
|
24
|
+
buildJsonObject(pairs: [key: string, expr: string][]): string;
|
|
25
|
+
/** Build a JSON array aggregation expression with a dialect-specific empty-array fallback. */
|
|
26
|
+
buildJsonArrayAgg(jsonObjectExpr: string, orderBy?: string): string;
|
|
27
|
+
/** Whether INSERT/UPDATE/DELETE support RETURNING rows. */
|
|
28
|
+
readonly supportsReturning: boolean;
|
|
29
|
+
/** Whether native ILIKE is supported. */
|
|
30
|
+
readonly supportsILike: boolean;
|
|
31
|
+
/** Build a case-insensitive LIKE equivalent. */
|
|
32
|
+
buildInsensitiveLike(column: string, paramRef: string): string;
|
|
33
|
+
/** JSON operator support level for this dialect. */
|
|
34
|
+
readonly jsonPathSupport: 'native' | 'function' | 'limited';
|
|
35
|
+
/** Build a JSON containment check. */
|
|
36
|
+
buildJsonContains(column: string, paramRef: string): string;
|
|
37
|
+
/** Build a JSON path text extraction expression. */
|
|
38
|
+
buildJsonPathExtract(column: string, pathParamRef: string): string;
|
|
39
|
+
/** Build a correlation clause across single or composite keys. */
|
|
40
|
+
buildCorrelation(leftRef: string, leftColumns: string | string[], rightRef: string, rightColumns: string | string[]): string;
|
|
41
|
+
/** Type mapping hook for code generation. */
|
|
42
|
+
typeToTypeScript(dialectType: string, nullable: boolean): string;
|
|
43
|
+
/** Optional array-cast hook for bulk insert implementations. */
|
|
44
|
+
arrayType?(baseType: string): string;
|
|
45
|
+
}
|
|
46
|
+
export interface DialectIntrospector {
|
|
47
|
+
introspect(options: IntrospectOptions): Promise<SchemaMetadata>;
|
|
48
|
+
}
|
|
49
|
+
export interface IntrospectOptions {
|
|
50
|
+
connectionString: string;
|
|
51
|
+
schema?: string;
|
|
52
|
+
include?: string[];
|
|
53
|
+
exclude?: string[];
|
|
54
|
+
}
|
|
55
|
+
export interface DialectMigrator {
|
|
56
|
+
acquireLock(lockId: number): Promise<boolean>;
|
|
57
|
+
releaseLock(lockId: number): Promise<void>;
|
|
58
|
+
}
|
|
59
|
+
/** PostgreSQL implementation of the dialect contract. */
|
|
60
|
+
export declare const postgresDialect: Dialect;
|
|
61
|
+
//# sourceMappingURL=dialect.d.ts.map
|
package/dist/dialect.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* turbine-orm — SQL dialect contract
|
|
3
|
+
*
|
|
4
|
+
* Phase-1 seam for future database packages. The current package remains
|
|
5
|
+
* PostgreSQL-native by default, but query generation now depends on this
|
|
6
|
+
* contract for the SQL primitives that vary across MySQL and SQLite.
|
|
7
|
+
*/
|
|
8
|
+
/** PostgreSQL implementation of the dialect contract. */
|
|
9
|
+
export const postgresDialect = {
|
|
10
|
+
name: 'postgresql',
|
|
11
|
+
supportsReturning: true,
|
|
12
|
+
supportsILike: true,
|
|
13
|
+
jsonPathSupport: 'native',
|
|
14
|
+
emptyJsonArrayLiteral: "'[]'::json",
|
|
15
|
+
nullJsonLiteral: 'NULL',
|
|
16
|
+
paramPlaceholder(index) {
|
|
17
|
+
return `$${index}`;
|
|
18
|
+
},
|
|
19
|
+
quoteIdentifier(name) {
|
|
20
|
+
return `"${name.replace(/"/g, '""')}"`;
|
|
21
|
+
},
|
|
22
|
+
escapeStringLiteral(value) {
|
|
23
|
+
return value.replace(/'/g, "''");
|
|
24
|
+
},
|
|
25
|
+
buildJsonObject(pairs) {
|
|
26
|
+
const args = pairs.map(([key, expr]) => `'${this.escapeStringLiteral(key)}', ${expr}`);
|
|
27
|
+
return `json_build_object(${args.join(', ')})`;
|
|
28
|
+
},
|
|
29
|
+
buildJsonArrayAgg(jsonObjectExpr, orderBy) {
|
|
30
|
+
const suffix = orderBy ? ` ${orderBy}` : '';
|
|
31
|
+
return `COALESCE(json_agg(${jsonObjectExpr}${suffix}), ${this.emptyJsonArrayLiteral})`;
|
|
32
|
+
},
|
|
33
|
+
buildInsensitiveLike(column, paramRef) {
|
|
34
|
+
return `${column} ILIKE ${paramRef}`;
|
|
35
|
+
},
|
|
36
|
+
buildJsonContains(column, paramRef) {
|
|
37
|
+
return `${column} @> ${paramRef}::jsonb`;
|
|
38
|
+
},
|
|
39
|
+
buildJsonPathExtract(column, pathParamRef) {
|
|
40
|
+
return `${column} #>> ${pathParamRef}::text[]`;
|
|
41
|
+
},
|
|
42
|
+
buildCorrelation(leftRef, leftColumns, rightRef, rightColumns) {
|
|
43
|
+
const leftCols = Array.isArray(leftColumns) ? leftColumns : [leftColumns];
|
|
44
|
+
const rightCols = Array.isArray(rightColumns) ? rightColumns : [rightColumns];
|
|
45
|
+
return leftCols
|
|
46
|
+
.map((col, i) => `${leftRef}.${this.quoteIdentifier(col)} = ${rightRef}.${this.quoteIdentifier(rightCols[i])}`)
|
|
47
|
+
.join(' AND ');
|
|
48
|
+
},
|
|
49
|
+
typeToTypeScript(_dialectType, _nullable) {
|
|
50
|
+
// Existing PostgreSQL type mapping remains in schema.ts/generate.ts for now.
|
|
51
|
+
// This hook is the package boundary MySQL/SQLite implementations will fill.
|
|
52
|
+
return 'unknown';
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=dialect.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -35,6 +35,8 @@
|
|
|
35
35
|
export type { DatabaseAdapter, IntrospectionOverrides } from './adapters/index.js';
|
|
36
36
|
export { alloydb, cockroachdb, postgresql, timescale, yugabytedb } from './adapters/index.js';
|
|
37
37
|
export { type Middleware, type MiddlewareNext, type MiddlewareParams, type PgCompatPool, type PgCompatPoolClient, type PgCompatQueryResult, TransactionClient, type TransactionOptions, TurbineClient, type TurbineConfig, } from './client.js';
|
|
38
|
+
export type { Dialect, DialectIntrospector, DialectMigrator, DialectName, IntrospectOptions as DialectIntrospectOptions, } from './dialect.js';
|
|
39
|
+
export { postgresDialect } from './dialect.js';
|
|
38
40
|
export { CheckConstraintError, CircularRelationError, ConnectionError, DeadlockError, type ErrorMessageMode, ForeignKeyError, getErrorMessageMode, MigrationError, NotFoundError, NotNullViolationError, PipelineError, type PipelineResultSlot, RelationError, SerializationFailureError, setErrorMessageMode, TimeoutError, TurbineError, TurbineErrorCode, UniqueConstraintError, ValidationError, wrapPgError, } from './errors.js';
|
|
39
41
|
export { type GenerateOptions, generate } from './generate.js';
|
|
40
42
|
export { type IntrospectOptions, introspect } from './introspect.js';
|
package/dist/index.js
CHANGED
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
export { alloydb, cockroachdb, postgresql, timescale, yugabytedb } from './adapters/index.js';
|
|
36
36
|
// Client
|
|
37
37
|
export { TransactionClient, TurbineClient, } from './client.js';
|
|
38
|
+
export { postgresDialect } from './dialect.js';
|
|
38
39
|
// Error types
|
|
39
40
|
export { CheckConstraintError, CircularRelationError, ConnectionError, DeadlockError, ForeignKeyError, getErrorMessageMode, MigrationError, NotFoundError, NotNullViolationError, PipelineError, RelationError, SerializationFailureError, setErrorMessageMode, TimeoutError, TurbineError, TurbineErrorCode, UniqueConstraintError, ValidationError, wrapPgError, } from './errors.js';
|
|
40
41
|
// Code generation
|
package/dist/query/builder.d.ts
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* metadata — nothing is hardcoded.
|
|
12
12
|
*/
|
|
13
13
|
import type pg from 'pg';
|
|
14
|
+
import type { Dialect } from '../dialect.js';
|
|
14
15
|
import type { SchemaMetadata } from '../schema.js';
|
|
15
16
|
import type { AggregateArgs, AggregateResult, CountArgs, CreateArgs, CreateManyArgs, DeleteArgs, DeleteManyArgs, FindManyArgs, FindManyStreamArgs, FindUniqueArgs, GroupByArgs, TypedWithClause, UpdateArgs, UpdateManyArgs, UpsertArgs, WithClause, WithResult } from './types.js';
|
|
16
17
|
export interface DeferredQuery<T> {
|
|
@@ -64,6 +65,8 @@ export interface QueryInterfaceOptions {
|
|
|
64
65
|
* Default: `true`. Set to `false` as a nuclear kill switch.
|
|
65
66
|
*/
|
|
66
67
|
sqlCache?: boolean;
|
|
68
|
+
/** SQL dialect implementation. Defaults to PostgreSQL. */
|
|
69
|
+
dialect?: Dialect;
|
|
67
70
|
}
|
|
68
71
|
export declare class QueryInterface<T extends object, R extends object = {}> {
|
|
69
72
|
private readonly pool;
|
|
@@ -77,6 +80,7 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
|
|
|
77
80
|
private readonly warnOnUnlimited;
|
|
78
81
|
private readonly preparedStatementsEnabled;
|
|
79
82
|
private readonly sqlCacheEnabled;
|
|
83
|
+
private readonly dialect;
|
|
80
84
|
/**
|
|
81
85
|
* Tracks tables that have already triggered an unlimited-query warning so
|
|
82
86
|
* the user is not spammed once per row. Per-instance state — each
|
|
@@ -95,6 +99,10 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
|
|
|
95
99
|
/** Tracks tables that have already triggered a deep-with warning (one-time) */
|
|
96
100
|
private readonly deepWithWarned;
|
|
97
101
|
constructor(pool: pg.Pool, table: string, schema: SchemaMetadata, middlewares?: MiddlewareFn[], options?: QueryInterfaceOptions);
|
|
102
|
+
/** Quote an identifier through the active SQL dialect. */
|
|
103
|
+
private q;
|
|
104
|
+
/** Return the active dialect's placeholder for a 1-indexed parameter position. */
|
|
105
|
+
private p;
|
|
98
106
|
/**
|
|
99
107
|
* Return cache hit/miss statistics for this QueryInterface instance.
|
|
100
108
|
* Useful for monitoring and benchmarking.
|
|
@@ -433,7 +441,7 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
|
|
|
433
441
|
* 8. **Parameter threading:** All user-supplied values (where filters, limit) are
|
|
434
442
|
* pushed to the shared `params` array with `$N` placeholders. No string
|
|
435
443
|
* interpolation of user data ever occurs -- all identifiers go through
|
|
436
|
-
* `
|
|
444
|
+
* `this.q()` and all values are parameterized.
|
|
437
445
|
*
|
|
438
446
|
* ### Example output (hasMany with nested relation)
|
|
439
447
|
* ```sql
|