kysely 0.29.3 → 0.30.0-beta.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/README.md +1 -1
- package/dist/dialect/postgres/postgres-driver.js +5 -1
- package/dist/driver/driver.d.ts +2 -2
- package/dist/helpers/sqlite.d.ts +11 -4
- package/dist/helpers/sqlite.js +4 -1
- package/dist/migration/file-migration-provider.d.ts +2 -1
- package/dist/migration/index.d.ts +1 -0
- package/dist/migration/index.js +1 -0
- package/dist/migration/migration.d.ts +70 -0
- package/dist/migration/migration.js +21 -0
- package/dist/migration/migrator.d.ts +43 -11
- package/dist/migration/migrator.js +126 -91
- package/dist/plugin/camel-case/camel-case.d.ts +1 -1
- package/dist/query-compiler/default-query-compiler.js +4 -4
- package/dist/util/log.d.ts +1 -1
- package/dist/util/object-utils.d.ts +0 -1
- package/dist/util/object-utils.js +0 -3
- package/dist/util/type-utils.d.ts +1 -1
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[](https://stand-with-ukraine.pp.ua)
|
|
2
2
|
|
|
3
3
|
[](https://github.com/kysely-org/kysely/releases/latest)
|
|
4
|
-
[](https://socket.dev/npm/package/kysely/overview/0.30.0-beta.0)
|
|
5
5
|
[](https://github.com/kysely-org/kysely)
|
|
6
6
|
[](https://github.com/kysely-org/kysely/blob/master/LICENSE)
|
|
7
7
|
[](https://github.com/kysely-org/kysely/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc)
|
|
@@ -177,7 +177,11 @@ class PostgresConnection {
|
|
|
177
177
|
}
|
|
178
178
|
});
|
|
179
179
|
}
|
|
180
|
-
const controlClient = new Client({
|
|
180
|
+
const controlClient = new Client({
|
|
181
|
+
...poolOptions,
|
|
182
|
+
// `password` is not enumerable, so we have to explicitly set it after the spread.
|
|
183
|
+
password: 'password' in poolOptions ? poolOptions.password : undefined,
|
|
184
|
+
});
|
|
181
185
|
try {
|
|
182
186
|
await controlClient.connect();
|
|
183
187
|
// by the time we get the connection, another query might have been executed.
|
package/dist/driver/driver.d.ts
CHANGED
|
@@ -55,8 +55,8 @@ export interface TransactionSettings {
|
|
|
55
55
|
readonly accessMode?: AccessMode;
|
|
56
56
|
readonly isolationLevel?: IsolationLevel;
|
|
57
57
|
}
|
|
58
|
-
export declare const TRANSACTION_ACCESS_MODES: readonly [
|
|
58
|
+
export declare const TRANSACTION_ACCESS_MODES: readonly ['read only', 'read write'];
|
|
59
59
|
export type AccessMode = ArrayItemType<typeof TRANSACTION_ACCESS_MODES>;
|
|
60
|
-
export declare const TRANSACTION_ISOLATION_LEVELS: readonly [
|
|
60
|
+
export declare const TRANSACTION_ISOLATION_LEVELS: readonly ['read uncommitted', 'read committed', 'repeatable read', 'serializable', 'snapshot'];
|
|
61
61
|
export type IsolationLevel = ArrayItemType<typeof TRANSACTION_ISOLATION_LEVELS>;
|
|
62
62
|
export declare function validateTransactionSettings(settings: TransactionSettings): void;
|
package/dist/helpers/sqlite.d.ts
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import type { Expression } from '../expression/expression.js';
|
|
2
2
|
import type { SelectQueryBuilderExpression } from '../query-builder/select-query-builder-expression.js';
|
|
3
3
|
import type { RawBuilder } from '../raw-builder/raw-builder.js';
|
|
4
|
-
import type {
|
|
4
|
+
import type { KyselyTypeError } from '../util/type-error.js';
|
|
5
|
+
import type { IsNever, ShallowDehydrateObject, ShallowDehydrateValue, Simplify } from '../util/type-utils.js';
|
|
6
|
+
/**
|
|
7
|
+
* Used to check for `BLOB` column existence in result records.
|
|
8
|
+
*/
|
|
9
|
+
export type ExtractBlobs<O> = {
|
|
10
|
+
[K in keyof O]: O[K] extends Expression<infer V> ? Extract<V, Uint8Array> : Extract<O[K], Uint8Array>;
|
|
11
|
+
}[keyof O];
|
|
5
12
|
/**
|
|
6
13
|
* A SQLite helper for aggregating a subquery into a JSON array.
|
|
7
14
|
*
|
|
@@ -63,7 +70,7 @@ import type { ShallowDehydrateObject, ShallowDehydrateValue, Simplify } from '..
|
|
|
63
70
|
* from "person"
|
|
64
71
|
* ```
|
|
65
72
|
*/
|
|
66
|
-
export declare function jsonArrayFrom<O>(expr: SelectQueryBuilderExpression<O>): RawBuilder<Simplify<ShallowDehydrateObject<O>>[]>;
|
|
73
|
+
export declare function jsonArrayFrom<O>(expr: IsNever<ExtractBlobs<O>> extends true ? SelectQueryBuilderExpression<O> : KyselyTypeError<'SQLite does not support passing `BLOB` values to `json_object`. Cast to `TEXT`.'>): RawBuilder<Simplify<ShallowDehydrateObject<O>>[]>;
|
|
67
74
|
/**
|
|
68
75
|
* A SQLite helper for turning a subquery into a JSON object.
|
|
69
76
|
*
|
|
@@ -127,7 +134,7 @@ export declare function jsonArrayFrom<O>(expr: SelectQueryBuilderExpression<O>):
|
|
|
127
134
|
* from "person";
|
|
128
135
|
* ```
|
|
129
136
|
*/
|
|
130
|
-
export declare function jsonObjectFrom<O>(expr: SelectQueryBuilderExpression<O>): RawBuilder<Simplify<ShallowDehydrateObject<O>> | null>;
|
|
137
|
+
export declare function jsonObjectFrom<O>(expr: IsNever<ExtractBlobs<O>> extends true ? SelectQueryBuilderExpression<O> : KyselyTypeError<'SQLite does not support passing `BLOB` values to `json_object`. Cast to `TEXT`.'>): RawBuilder<Simplify<ShallowDehydrateObject<O>> | null>;
|
|
131
138
|
/**
|
|
132
139
|
* The SQLite `json_object` function.
|
|
133
140
|
*
|
|
@@ -184,6 +191,6 @@ export declare function jsonObjectFrom<O>(expr: SelectQueryBuilderExpression<O>)
|
|
|
184
191
|
* from "person"
|
|
185
192
|
* ```
|
|
186
193
|
*/
|
|
187
|
-
export declare function jsonBuildObject<O extends Record<string, Expression<unknown>>>(obj: O): RawBuilder<Simplify<{
|
|
194
|
+
export declare function jsonBuildObject<O extends Record<string, Expression<unknown>>>(obj: IsNever<ExtractBlobs<O>> extends true ? O : KyselyTypeError<'SQLite does not support passing `BLOB` values to `json_object`. Cast to `TEXT`.'>): RawBuilder<Simplify<{
|
|
188
195
|
[K in keyof O]: O[K] extends Expression<infer V> ? ShallowDehydrateValue<V> : never;
|
|
189
196
|
}>>;
|
package/dist/helpers/sqlite.js
CHANGED
|
@@ -188,7 +188,10 @@ export function jsonObjectFrom(expr) {
|
|
|
188
188
|
* ```
|
|
189
189
|
*/
|
|
190
190
|
export function jsonBuildObject(obj) {
|
|
191
|
-
return sql `json_object(${sql.join(Object.keys(obj).flatMap((k) => [
|
|
191
|
+
return sql `json_object(${sql.join(Object.keys(obj).flatMap((k) => [
|
|
192
|
+
sql.lit(k),
|
|
193
|
+
obj[k],
|
|
194
|
+
]))})`;
|
|
192
195
|
}
|
|
193
196
|
function getSqliteJsonObjectArgs(node, table) {
|
|
194
197
|
try {
|
package/dist/migration/index.js
CHANGED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { Kysely } from '../kysely.js';
|
|
2
|
+
/**
|
|
3
|
+
* The shape of a migration's module.
|
|
4
|
+
*/
|
|
5
|
+
export interface Migration {
|
|
6
|
+
/**
|
|
7
|
+
* Configuration object for this migration module.
|
|
8
|
+
*
|
|
9
|
+
* See {@link MigrationConfig}.
|
|
10
|
+
*/
|
|
11
|
+
config?: MigrationConfig;
|
|
12
|
+
/**
|
|
13
|
+
* The `down` method that reverts the changes made by it's sibling {@link Migration.up}
|
|
14
|
+
* method.
|
|
15
|
+
*/
|
|
16
|
+
down?(db: Kysely<any>): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* The `up` method that changes the database schema.
|
|
19
|
+
*
|
|
20
|
+
* See {@link Migration.down}.
|
|
21
|
+
*/
|
|
22
|
+
up(db: Kysely<any>): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Configuration for a single migration.
|
|
26
|
+
*/
|
|
27
|
+
export interface MigrationConfig {
|
|
28
|
+
/**
|
|
29
|
+
* Controls whether this migration runs inside its own transaction, when
|
|
30
|
+
* {@link MigrateOptions.transactionMode} is `'per-migration'` — the only
|
|
31
|
+
* mode that honors this property. Defaults to `true` in that mode: the
|
|
32
|
+
* migration runs in its own transaction unless this is set to `false`.
|
|
33
|
+
*
|
|
34
|
+
* In any other transaction mode, leaving this property out is the only
|
|
35
|
+
* valid state — providing a value, either one, results in an error: in
|
|
36
|
+
* `'per-run'` mode a single shared transaction cannot partially exclude a
|
|
37
|
+
* migration, and in `'none'` mode there are no transactions to configure.
|
|
38
|
+
* This is the one place an explicit `true` differs from the default —
|
|
39
|
+
* `true` asserts a requirement that non-`'per-migration'` modes refuse,
|
|
40
|
+
* while leaving the property out never errors.
|
|
41
|
+
*
|
|
42
|
+
* Setting `false` makes the migration run without a transaction. This is
|
|
43
|
+
* required for statements that cannot run inside a transaction, such as
|
|
44
|
+
* PostgreSQL's `CREATE INDEX CONCURRENTLY`. Note that without a
|
|
45
|
+
* transaction, a failure can leave the migration partially applied, and the
|
|
46
|
+
* migration table record is written separately after the migration
|
|
47
|
+
* completes. Prefer a single statement per non-transactional migration, and
|
|
48
|
+
* write it so it can be safely retried — for example, drop a
|
|
49
|
+
* possibly-leftover invalid index before creating it.
|
|
50
|
+
*/
|
|
51
|
+
readonly transaction?: boolean;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Helps define a single migration by taking over types duties and enforcing the contract.
|
|
55
|
+
*
|
|
56
|
+
* ### Examples
|
|
57
|
+
*
|
|
58
|
+
* ```ts
|
|
59
|
+
* import { defineMigration } from 'kysely/migration'
|
|
60
|
+
*
|
|
61
|
+
* export default defineMigration({
|
|
62
|
+
* async up(db) {
|
|
63
|
+
* // ...
|
|
64
|
+
* },
|
|
65
|
+
*
|
|
66
|
+
* config: { transaction: false },
|
|
67
|
+
* })
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare function defineMigration(migration: Migration): Migration;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/// <reference types="./migration.d.ts" />
|
|
2
|
+
/**
|
|
3
|
+
* Helps define a single migration by taking over types duties and enforcing the contract.
|
|
4
|
+
*
|
|
5
|
+
* ### Examples
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { defineMigration } from 'kysely/migration'
|
|
9
|
+
*
|
|
10
|
+
* export default defineMigration({
|
|
11
|
+
* async up(db) {
|
|
12
|
+
* // ...
|
|
13
|
+
* },
|
|
14
|
+
*
|
|
15
|
+
* config: { transaction: false },
|
|
16
|
+
* })
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export function defineMigration(migration) {
|
|
20
|
+
return migration;
|
|
21
|
+
}
|
|
@@ -1,19 +1,10 @@
|
|
|
1
1
|
import type { Kysely } from '../kysely.js';
|
|
2
|
+
import type { Migration } from './migration.js';
|
|
2
3
|
export declare const DEFAULT_MIGRATION_TABLE = "kysely_migration";
|
|
3
4
|
export declare const DEFAULT_MIGRATION_LOCK_TABLE = "kysely_migration_lock";
|
|
4
5
|
export declare const DEFAULT_ALLOW_UNORDERED_MIGRATIONS = false;
|
|
5
6
|
export declare const MIGRATION_LOCK_ID = "migration_lock";
|
|
6
7
|
export declare const NO_MIGRATIONS: NoMigrations;
|
|
7
|
-
export interface Migration {
|
|
8
|
-
up(db: Kysely<any>): Promise<void>;
|
|
9
|
-
/**
|
|
10
|
-
* An optional down method.
|
|
11
|
-
*
|
|
12
|
-
* If you don't provide a down method, the migration is skipped when
|
|
13
|
-
* migrating down.
|
|
14
|
-
*/
|
|
15
|
-
down?(db: Kysely<any>): Promise<void>;
|
|
16
|
-
}
|
|
17
8
|
/**
|
|
18
9
|
* A class for running migrations.
|
|
19
10
|
*
|
|
@@ -221,10 +212,51 @@ export interface MigrateOptions {
|
|
|
221
212
|
*
|
|
222
213
|
* Default is `false`.
|
|
223
214
|
*
|
|
224
|
-
*
|
|
215
|
+
* @deprecated Use {@link transactionMode} instead — `disableTransactions: true`
|
|
216
|
+
* is equivalent to `transactionMode: 'none'`. Setting both to contradicting
|
|
217
|
+
* values results in an error.
|
|
225
218
|
*/
|
|
226
219
|
readonly disableTransactions?: boolean;
|
|
220
|
+
/**
|
|
221
|
+
* Controls how migrations are wrapped in transactions, when the dialect
|
|
222
|
+
* supports transactional DDL ({@link DialectAdapter.supportsTransactionalDdl}).
|
|
223
|
+
*
|
|
224
|
+
* - `'per-run'` — the entire migration run is wrapped in a single transaction.
|
|
225
|
+
* Either every migration in the run is applied, or none are. Any migration
|
|
226
|
+
* with a per-migration `transaction` configuration ({@link MigrationConfig.transaction})
|
|
227
|
+
* results in an error, since a single shared transaction cannot partially
|
|
228
|
+
* exclude a migration. Requires transactional DDL — results in an error on
|
|
229
|
+
* dialects without it (e.g. MySQL).
|
|
230
|
+
*
|
|
231
|
+
* - `'per-migration'` — each migration runs in its own transaction, together
|
|
232
|
+
* with the insertion/deletion of its migration table record. A failure rolls
|
|
233
|
+
* back only the failing migration; previously completed migrations stay
|
|
234
|
+
* applied. Individual migrations can opt out of their transaction with
|
|
235
|
+
* `config: { transaction: false }` — required for statements that cannot
|
|
236
|
+
* run inside a transaction, such as PostgreSQL's `CREATE INDEX CONCURRENTLY`
|
|
237
|
+
* or `ALTER TYPE ... ADD VALUE` (pre-12). Requires transactional DDL —
|
|
238
|
+
* results in an error on dialects without it.
|
|
239
|
+
*
|
|
240
|
+
* - `'none'` — migrations run without any transactions. Any migration with a
|
|
241
|
+
* per-migration `transaction` configuration results in an error.
|
|
242
|
+
*
|
|
243
|
+
* When not provided, the current default is `'per-run'` on dialects that
|
|
244
|
+
* support transactional DDL and `'none'` on dialects that don't. This
|
|
245
|
+
* default might change to `'per-migration'` in a future version of Kysely —
|
|
246
|
+
* running multiple migrations without an explicit `transactionMode` logs a
|
|
247
|
+
* message about this. Provide an explicit `transactionMode` to make the
|
|
248
|
+
* migrator's behavior independent of the default.
|
|
249
|
+
*
|
|
250
|
+
* Note that transactions spanning multiple migrations (`'per-run'`) can make
|
|
251
|
+
* otherwise-valid migration sequences fail. For example, a new PostgreSQL enum
|
|
252
|
+
* value cannot be used in the same transaction that added it, so a migration
|
|
253
|
+
* that runs `ALTER TYPE ... ADD VALUE` followed by a migration that uses the
|
|
254
|
+
* new value works when the two run in separate transactions, but fails when
|
|
255
|
+
* both are pending in a single `'per-run'` mode run.
|
|
256
|
+
*/
|
|
257
|
+
readonly transactionMode?: MigratorTransactionMode;
|
|
227
258
|
}
|
|
259
|
+
export type MigratorTransactionMode = 'per-run' | 'per-migration' | 'none';
|
|
228
260
|
export interface MigratorProps extends MigrateOptions {
|
|
229
261
|
readonly db: Kysely<any>;
|
|
230
262
|
readonly provider: MigrationProvider;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/// <reference types="./migrator.d.ts" />
|
|
2
2
|
import { NoopPlugin } from '../plugin/noop-plugin.js';
|
|
3
3
|
import { WithSchemaPlugin } from '../plugin/with-schema/with-schema-plugin.js';
|
|
4
|
-
import {
|
|
4
|
+
import { logOnce } from '../util/log-once.js';
|
|
5
|
+
import { freeze, isObject } from '../util/object-utils.js';
|
|
5
6
|
export const DEFAULT_MIGRATION_TABLE = 'kysely_migration';
|
|
6
7
|
export const DEFAULT_MIGRATION_LOCK_TABLE = 'kysely_migration_lock';
|
|
7
8
|
export const DEFAULT_ALLOW_UNORDERED_MIGRATIONS = false;
|
|
@@ -403,6 +404,7 @@ export class Migrator {
|
|
|
403
404
|
lockRowId: MIGRATION_LOCK_ID,
|
|
404
405
|
lockTableSchema: this.#props.migrationTableSchema,
|
|
405
406
|
});
|
|
407
|
+
const transactionMode = this.#resolveTransactionMode(options, adapter);
|
|
406
408
|
const run = async (db) => {
|
|
407
409
|
const state = await this.#getState(db);
|
|
408
410
|
if (state.migrations.length === 0) {
|
|
@@ -412,13 +414,34 @@ export class Migrator {
|
|
|
412
414
|
if (step <= 0) {
|
|
413
415
|
return { results: [] };
|
|
414
416
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
+
const migrationsToRun = this.#getMigrationsToRun(state, direction, step);
|
|
418
|
+
const [orchestrator, runner] = direction === 'Down'
|
|
419
|
+
? [
|
|
420
|
+
this.#rollbackMigrations.bind(this),
|
|
421
|
+
this.#rollbackMigration.bind(this),
|
|
422
|
+
]
|
|
423
|
+
: [this.#applyMigrations.bind(this), this.#applyMigration.bind(this)];
|
|
424
|
+
if (transactionMode.value === 'per-migration') {
|
|
425
|
+
return await orchestrator(migrationsToRun, async (migration) => {
|
|
426
|
+
if (migration.config?.transaction === false) {
|
|
427
|
+
return await runner(db, migration);
|
|
428
|
+
}
|
|
429
|
+
await db.transaction().execute((trx) => runner(trx, migration));
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
const migrationWithTransactionConfig = migrationsToRun.find((migration) => migration.config?.transaction != null);
|
|
433
|
+
if (migrationWithTransactionConfig) {
|
|
434
|
+
const modeDescription = transactionMode.explicit
|
|
435
|
+
? `\`transactionMode\` is '${transactionMode.value}'`
|
|
436
|
+
: `\`transactionMode\` was not provided and defaults to '${transactionMode.value}'`;
|
|
437
|
+
throw new Error(`Migration "${migrationWithTransactionConfig.name}" has a \`transaction\` configuration but ${modeDescription}. Per-migration transaction configuration is only supported when \`transactionMode\` is 'per-migration'. Set \`transactionMode: 'per-migration'\` on the migrator or the migrate call to enable it.`);
|
|
417
438
|
}
|
|
418
|
-
|
|
419
|
-
|
|
439
|
+
if (!transactionMode.explicit &&
|
|
440
|
+
adapter.supportsTransactionalDdl &&
|
|
441
|
+
migrationsToRun.length > 1) {
|
|
442
|
+
logOnce("kysely:migrator: multiple migrations were run in a single transaction ('per-run'). This default might change in a future version of Kysely. Pass an explicit `transactionMode` to the migrator to pin the behavior and silence this message: 'per-run' to keep the current behavior, or 'per-migration' to run each migration in its own transaction.");
|
|
420
443
|
}
|
|
421
|
-
return
|
|
444
|
+
return await orchestrator(migrationsToRun, (migration) => runner(db, migration));
|
|
422
445
|
};
|
|
423
446
|
const runWithLock = async (db, cb) => {
|
|
424
447
|
try {
|
|
@@ -429,51 +452,92 @@ export class Migrator {
|
|
|
429
452
|
await adapter.releaseMigrationLock(db, lockOptions);
|
|
430
453
|
}
|
|
431
454
|
};
|
|
432
|
-
const disableTransactions = options?.disableTransactions ?? this.#props.disableTransactions;
|
|
433
455
|
if (this.#props.db.isTransaction) {
|
|
434
456
|
if (!adapter.supportsTransactionalDdl) {
|
|
435
457
|
throw new Error('Transactional DDL is not supported in this dialect. Passing a transaction to this migrator would result in failure or unexpected behavior.');
|
|
436
458
|
}
|
|
437
|
-
if (
|
|
438
|
-
throw new Error(
|
|
459
|
+
if (transactionMode.value !== 'per-run') {
|
|
460
|
+
throw new Error(`The transaction mode is '${transactionMode.value}' but the migrator was given a transaction. Passing a transaction to this migrator is only supported when \`transactionMode\` is 'per-run'.`);
|
|
439
461
|
}
|
|
440
462
|
return runWithLock(this.#props.db, run);
|
|
441
463
|
}
|
|
442
|
-
if (
|
|
464
|
+
if (transactionMode.value === 'per-run') {
|
|
443
465
|
return this.#props.db
|
|
444
466
|
.connection()
|
|
445
|
-
.execute((db) => runWithLock(db, (db) => db.transaction().execute(
|
|
467
|
+
.execute((db) => runWithLock(db, (db) => db.transaction().execute(run)));
|
|
446
468
|
}
|
|
447
469
|
return this.#props.db.connection().execute((db) => runWithLock(db, run));
|
|
448
470
|
}
|
|
471
|
+
#resolveTransactionMode(options, adapter) {
|
|
472
|
+
const resolveLevel = (options, source) => {
|
|
473
|
+
if (!options) {
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
const { disableTransactions, transactionMode } = options;
|
|
477
|
+
if (disableTransactions != null &&
|
|
478
|
+
transactionMode &&
|
|
479
|
+
(transactionMode === 'none') !== disableTransactions) {
|
|
480
|
+
throw new Error(`\`transactionMode\` is '${transactionMode}' but \`disableTransactions\` is ${disableTransactions} in the ${source}. These options contradict each other. Prefer \`transactionMode\` — \`disableTransactions\` is deprecated.`);
|
|
481
|
+
}
|
|
482
|
+
if (transactionMode) {
|
|
483
|
+
if (transactionMode !== 'none' && !adapter.supportsTransactionalDdl) {
|
|
484
|
+
throw new Error(`\`transactionMode\` is '${transactionMode}' but transactional DDL is not supported in this dialect. Migrations would fail or behave unexpectedly.`);
|
|
485
|
+
}
|
|
486
|
+
return { explicit: true, value: transactionMode };
|
|
487
|
+
}
|
|
488
|
+
if (disableTransactions == null) {
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
if (disableTransactions === true) {
|
|
492
|
+
return { explicit: true, value: 'none' };
|
|
493
|
+
}
|
|
494
|
+
return {
|
|
495
|
+
explicit: false,
|
|
496
|
+
value: adapter.supportsTransactionalDdl ? 'per-run' : 'none',
|
|
497
|
+
};
|
|
498
|
+
};
|
|
499
|
+
return (resolveLevel(options, 'migrate call options') ||
|
|
500
|
+
resolveLevel(this.#props, 'migrator properties') || {
|
|
501
|
+
explicit: false,
|
|
502
|
+
value: adapter.supportsTransactionalDdl ? 'per-run' : 'none',
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
#getMigrationsToRun(state, direction, step) {
|
|
506
|
+
if (direction === 'Down') {
|
|
507
|
+
return state.executedMigrations
|
|
508
|
+
.toReversed()
|
|
509
|
+
.slice(0, step)
|
|
510
|
+
.map((name) => {
|
|
511
|
+
return state.migrations.find((it) => it.name === name);
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
return state.pendingMigrations.slice(0, step);
|
|
515
|
+
}
|
|
449
516
|
async #getState(db) {
|
|
450
|
-
const migrations = await
|
|
451
|
-
|
|
517
|
+
const [migrations, executedMigrations] = await Promise.all([
|
|
518
|
+
this.#resolveMigrations(),
|
|
519
|
+
this.#getExecutedMigrations(db),
|
|
520
|
+
]);
|
|
452
521
|
this.#ensureNoMissingMigrations(migrations, executedMigrations);
|
|
453
522
|
if (!this.#allowUnorderedMigrations) {
|
|
454
523
|
this.#ensureMigrationsInOrder(migrations, executedMigrations);
|
|
455
524
|
}
|
|
456
525
|
const pendingMigrations = this.#getPendingMigrations(migrations, executedMigrations);
|
|
457
526
|
return freeze({
|
|
458
|
-
migrations,
|
|
459
527
|
executedMigrations,
|
|
460
|
-
lastMigration:
|
|
528
|
+
lastMigration: executedMigrations.at(-1),
|
|
529
|
+
migrations,
|
|
461
530
|
pendingMigrations,
|
|
462
531
|
});
|
|
463
532
|
}
|
|
464
533
|
#getPendingMigrations(migrations, executedMigrations) {
|
|
465
|
-
return migrations.filter((migration) =>
|
|
466
|
-
return !executedMigrations.includes(migration.name);
|
|
467
|
-
});
|
|
534
|
+
return migrations.filter((migration) => !executedMigrations.includes(migration.name));
|
|
468
535
|
}
|
|
469
536
|
async #resolveMigrations() {
|
|
470
537
|
const allMigrations = await this.#props.provider.getMigrations();
|
|
471
538
|
return Object.keys(allMigrations)
|
|
472
539
|
.sort()
|
|
473
|
-
.map((name) => ({
|
|
474
|
-
...allMigrations[name],
|
|
475
|
-
name,
|
|
476
|
-
}));
|
|
540
|
+
.map((name) => ({ ...allMigrations[name], name }));
|
|
477
541
|
}
|
|
478
542
|
async #getExecutedMigrations(db) {
|
|
479
543
|
const executedMigrations = await db
|
|
@@ -509,92 +573,63 @@ export class Migrator {
|
|
|
509
573
|
}
|
|
510
574
|
}
|
|
511
575
|
}
|
|
512
|
-
async #
|
|
513
|
-
const
|
|
514
|
-
|
|
515
|
-
.
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
});
|
|
519
|
-
const results = migrationsToRollback.map((migration) => {
|
|
520
|
-
return {
|
|
521
|
-
migrationName: migration.name,
|
|
522
|
-
direction: 'Down',
|
|
523
|
-
status: 'NotExecuted',
|
|
524
|
-
};
|
|
525
|
-
});
|
|
576
|
+
async #rollbackMigrations(migrationsToRollback, rollbacker) {
|
|
577
|
+
const results = migrationsToRollback.map((migration) => ({
|
|
578
|
+
direction: 'Down',
|
|
579
|
+
migrationName: migration.name,
|
|
580
|
+
status: 'NotExecuted',
|
|
581
|
+
}));
|
|
526
582
|
for (let i = 0; i < results.length; ++i) {
|
|
527
583
|
const migration = migrationsToRollback[i];
|
|
584
|
+
if (!migration.down) {
|
|
585
|
+
continue;
|
|
586
|
+
}
|
|
528
587
|
try {
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
await db
|
|
532
|
-
.withPlugin(this.#schemaPlugin)
|
|
533
|
-
.deleteFrom(this.#migrationTable)
|
|
534
|
-
.where('name', '=', migration.name)
|
|
535
|
-
.execute();
|
|
536
|
-
results[i] = {
|
|
537
|
-
migrationName: migration.name,
|
|
538
|
-
direction: 'Down',
|
|
539
|
-
status: 'Success',
|
|
540
|
-
};
|
|
541
|
-
}
|
|
588
|
+
await rollbacker(migration);
|
|
589
|
+
results[i].status = 'Success';
|
|
542
590
|
}
|
|
543
591
|
catch (error) {
|
|
544
|
-
results[i] =
|
|
545
|
-
|
|
546
|
-
direction: 'Down',
|
|
547
|
-
status: 'Error',
|
|
548
|
-
};
|
|
549
|
-
throw new MigrationResultSetError({
|
|
550
|
-
error,
|
|
551
|
-
results,
|
|
552
|
-
});
|
|
592
|
+
results[i].status = 'Error';
|
|
593
|
+
throw new MigrationResultSetError({ error, results });
|
|
553
594
|
}
|
|
554
595
|
}
|
|
555
596
|
return { results };
|
|
556
597
|
}
|
|
557
|
-
async #
|
|
558
|
-
const
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
status: 'NotExecuted',
|
|
564
|
-
};
|
|
565
|
-
});
|
|
598
|
+
async #applyMigrations(migrationsToRun, applier) {
|
|
599
|
+
const results = migrationsToRun.map((migration) => ({
|
|
600
|
+
direction: 'Up',
|
|
601
|
+
migrationName: migration.name,
|
|
602
|
+
status: 'NotExecuted',
|
|
603
|
+
}));
|
|
566
604
|
for (let i = 0; i < results.length; i++) {
|
|
567
|
-
const migration =
|
|
605
|
+
const migration = migrationsToRun[i];
|
|
568
606
|
try {
|
|
569
|
-
await migration
|
|
570
|
-
|
|
571
|
-
.withPlugin(this.#schemaPlugin)
|
|
572
|
-
.insertInto(this.#migrationTable)
|
|
573
|
-
.values({
|
|
574
|
-
name: migration.name,
|
|
575
|
-
timestamp: new Date().toISOString(),
|
|
576
|
-
})
|
|
577
|
-
.execute();
|
|
578
|
-
results[i] = {
|
|
579
|
-
migrationName: migration.name,
|
|
580
|
-
direction: 'Up',
|
|
581
|
-
status: 'Success',
|
|
582
|
-
};
|
|
607
|
+
await applier(migration);
|
|
608
|
+
results[i].status = 'Success';
|
|
583
609
|
}
|
|
584
610
|
catch (error) {
|
|
585
|
-
results[i] =
|
|
586
|
-
|
|
587
|
-
direction: 'Up',
|
|
588
|
-
status: 'Error',
|
|
589
|
-
};
|
|
590
|
-
throw new MigrationResultSetError({
|
|
591
|
-
error,
|
|
592
|
-
results,
|
|
593
|
-
});
|
|
611
|
+
results[i].status = 'Error';
|
|
612
|
+
throw new MigrationResultSetError({ error, results });
|
|
594
613
|
}
|
|
595
614
|
}
|
|
596
615
|
return { results };
|
|
597
616
|
}
|
|
617
|
+
async #applyMigration(db, migration) {
|
|
618
|
+
await migration.up(db);
|
|
619
|
+
await db
|
|
620
|
+
.withPlugin(this.#schemaPlugin)
|
|
621
|
+
.insertInto(this.#migrationTable)
|
|
622
|
+
.values({ name: migration.name, timestamp: new Date().toISOString() })
|
|
623
|
+
.execute();
|
|
624
|
+
}
|
|
625
|
+
async #rollbackMigration(db, migration) {
|
|
626
|
+
await migration.down(db);
|
|
627
|
+
await db
|
|
628
|
+
.withPlugin(this.#schemaPlugin)
|
|
629
|
+
.deleteFrom(this.#migrationTable)
|
|
630
|
+
.where('name', '=', migration.name)
|
|
631
|
+
.execute();
|
|
632
|
+
}
|
|
598
633
|
async #createIfNotExists(qb) {
|
|
599
634
|
if (this.#props.db.getExecutor().adapter.supportsCreateIfNotExists) {
|
|
600
635
|
qb = qb.ifNotExists();
|
|
@@ -3,9 +3,9 @@ export type StringMapper = (str: string) => string;
|
|
|
3
3
|
* Creates a function that transforms camel case strings to snake case.
|
|
4
4
|
*/
|
|
5
5
|
export declare function createSnakeCaseMapper({ upperCase, underscoreBeforeDigits, underscoreBetweenUppercaseLetters, }?: {
|
|
6
|
-
upperCase?: boolean | undefined;
|
|
7
6
|
underscoreBeforeDigits?: boolean | undefined;
|
|
8
7
|
underscoreBetweenUppercaseLetters?: boolean | undefined;
|
|
8
|
+
upperCase?: boolean | undefined;
|
|
9
9
|
}): StringMapper;
|
|
10
10
|
/**
|
|
11
11
|
* Creates a function that transforms snake case strings to camel case.
|
|
@@ -254,6 +254,10 @@ export class DefaultQueryCompiler extends OperationNodeVisitor {
|
|
|
254
254
|
this.append(' ');
|
|
255
255
|
this.visitNode(node.where);
|
|
256
256
|
}
|
|
257
|
+
if (node.returning) {
|
|
258
|
+
this.append(' ');
|
|
259
|
+
this.visitNode(node.returning);
|
|
260
|
+
}
|
|
257
261
|
if (node.orderBy) {
|
|
258
262
|
this.append(' ');
|
|
259
263
|
this.visitNode(node.orderBy);
|
|
@@ -262,10 +266,6 @@ export class DefaultQueryCompiler extends OperationNodeVisitor {
|
|
|
262
266
|
this.append(' ');
|
|
263
267
|
this.visitNode(node.limit);
|
|
264
268
|
}
|
|
265
|
-
if (node.returning) {
|
|
266
|
-
this.append(' ');
|
|
267
|
-
this.visitNode(node.returning);
|
|
268
|
-
}
|
|
269
269
|
if (wrapInParens) {
|
|
270
270
|
this.append(')');
|
|
271
271
|
}
|
package/dist/util/log.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CompiledQuery } from '../query-compiler/compiled-query.js';
|
|
2
2
|
import type { ArrayItemType } from './type-utils.js';
|
|
3
|
-
declare const logLevels: readonly [
|
|
3
|
+
declare const logLevels: readonly ['query', 'error'];
|
|
4
4
|
export declare const LOG_LEVELS: Readonly<typeof logLevels>;
|
|
5
5
|
export type LogLevel = ArrayItemType<typeof LOG_LEVELS>;
|
|
6
6
|
export interface QueryLogEvent {
|
|
@@ -14,7 +14,6 @@ export declare function isFunction(obj: unknown): obj is Function;
|
|
|
14
14
|
export declare function isObject(obj: unknown): obj is ShallowRecord<string, unknown>;
|
|
15
15
|
export declare function isArrayBufferOrView(obj: unknown): obj is ArrayBuffer | ArrayBufferView;
|
|
16
16
|
export declare function isPlainObject(obj: unknown): obj is Record<string, unknown>;
|
|
17
|
-
export declare function getLast<T>(arr: ArrayLike<T>): T | undefined;
|
|
18
17
|
export declare function freeze<T>(obj: T): Readonly<T>;
|
|
19
18
|
export declare function asArray<T>(arg: T | ReadonlyArray<T>): ReadonlyArray<T>;
|
|
20
19
|
export declare function asReadonlyArray<T>(arg: T | ReadonlyArray<T>): ReadonlyArray<T>;
|
|
@@ -119,7 +119,7 @@ export type IsAny<T> = 0 extends T & 1 ? true : false;
|
|
|
119
119
|
/**
|
|
120
120
|
* Evaluates to `true` if the types `T` and `U` are equal.
|
|
121
121
|
*/
|
|
122
|
-
export type Equals<T, U> = (<G>() => G extends T ? 1 : 2) extends <G>() => G extends U ? 1 : 2 ? true : false;
|
|
122
|
+
export type Equals<T, U> = (<G>() => G extends T ? 1 : 2) extends <G>() => (G extends U ? 1 : 2) ? true : false;
|
|
123
123
|
export type NarrowPartial<O, T> = T extends object ? DrainOuterGeneric<{
|
|
124
124
|
[K in keyof O & string]: K extends keyof T ? T[K] extends NotNull ? Exclude<O[K], null> : T[K] extends O[K] ? T[K] : T[K] extends object ? SimplifyDeep<O[K] & NarrowPartial<O[K], T[K]>> : KyselyTypeError<`$narrowType() call failed: passed type does not exist in '${K}'s type union`> : O[K];
|
|
125
125
|
}> : never;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kysely",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.0-beta.0",
|
|
4
4
|
"description": "Type safe SQL query builder",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -61,14 +61,13 @@
|
|
|
61
61
|
"Igal Klebanov <igalklebanov@gmail.com>"
|
|
62
62
|
],
|
|
63
63
|
"devDependencies": {
|
|
64
|
-
"@arethetypeswrong/cli": "0.18.
|
|
65
|
-
"@
|
|
66
|
-
"@electric-sql/pglite": "0.5.3",
|
|
64
|
+
"@arethetypeswrong/cli": "0.18.5",
|
|
65
|
+
"@electric-sql/pglite": "0.5.4",
|
|
67
66
|
"@types/better-sqlite3": "7.6.13",
|
|
68
67
|
"@types/chai": "5.2.3",
|
|
69
68
|
"@types/chai-as-promised": "8.0.2",
|
|
70
69
|
"@types/mocha": "10.0.10",
|
|
71
|
-
"@types/node": "26.1.
|
|
70
|
+
"@types/node": "26.1.1",
|
|
72
71
|
"@types/pg": "8.20.0",
|
|
73
72
|
"@types/pg-cursor": "2.7.2",
|
|
74
73
|
"@types/prototype-pollution-vulnerable-lodash.merge-dont-upgrade": "npm:@types/lodash.merge@4.6.1",
|
|
@@ -80,22 +79,23 @@
|
|
|
80
79
|
"esbuild": "0.28.1",
|
|
81
80
|
"jsr": "0.14.3",
|
|
82
81
|
"mocha": "11.7.6",
|
|
83
|
-
"mysql2": "3.
|
|
82
|
+
"mysql2": "3.23.0",
|
|
84
83
|
"pathe": "2.0.3",
|
|
85
84
|
"pg": "8.22.0",
|
|
86
85
|
"pg-cursor": "2.21.0",
|
|
87
86
|
"playwright": "1.61.1",
|
|
88
|
-
"prettier": "3.9.
|
|
87
|
+
"prettier": "3.9.5",
|
|
89
88
|
"prototype-pollution-vulnerable-lodash.merge-dont-upgrade": "npm:lodash.merge@4.6.1",
|
|
90
89
|
"remeda": "2.39.0",
|
|
91
90
|
"semver": "7.8.5",
|
|
92
91
|
"sinon": "22.0.0",
|
|
93
|
-
"std-env": "4.
|
|
94
|
-
"tarn": "3.1.
|
|
92
|
+
"std-env": "4.2.0",
|
|
93
|
+
"tarn": "3.1.2",
|
|
95
94
|
"tedious": "20.0.0",
|
|
96
95
|
"tsd": "0.33.0",
|
|
97
|
-
"tsx": "4.
|
|
98
|
-
"typescript": "
|
|
96
|
+
"tsx": "4.23.1",
|
|
97
|
+
"typescript": "7.0.2",
|
|
98
|
+
"typescript-6": "npm:typescript@6.0.3"
|
|
99
99
|
},
|
|
100
100
|
"scripts": {
|
|
101
101
|
"clean": "rm -rf dist & rm -rf test/node/dist & rm -rf test/browser/bundle.js",
|