@geekmidas/testkit 0.4.0 → 0.6.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/Factory-BFVnMMCC.mjs.map +1 -1
- package/dist/Factory-BhjUOBWN.cjs.map +1 -1
- package/dist/{Factory-c16c27Y6.d.cts → Factory-Bx0AJXZB.d.cts} +3 -2
- package/dist/Factory-Bx0AJXZB.d.cts.map +1 -0
- package/dist/{Factory-BcGJjLc8.d.mts → Factory-SFupxRC2.d.mts} +2 -1
- package/dist/Factory-SFupxRC2.d.mts.map +1 -0
- package/dist/Factory.d.cts +2 -2
- package/dist/Factory.d.mts +1 -1
- package/dist/KyselyFactory-BFqVIn_0.cjs.map +1 -1
- package/dist/KyselyFactory-DMswpwji.mjs.map +1 -1
- package/dist/{KyselyFactory-uZ45h7YU.d.cts → KyselyFactory-KLeKH43i.d.cts} +4 -3
- package/dist/KyselyFactory-KLeKH43i.d.cts.map +1 -0
- package/dist/{KyselyFactory-Cj-EultY.d.mts → KyselyFactory-vAxYodck.d.mts} +3 -2
- package/dist/KyselyFactory-vAxYodck.d.mts.map +1 -0
- package/dist/KyselyFactory.d.cts +3 -3
- package/dist/KyselyFactory.d.mts +2 -2
- package/dist/{ObjectionFactory-DL4qkuF1.d.mts → ObjectionFactory-BWjB49-i.d.mts} +3 -2
- package/dist/ObjectionFactory-BWjB49-i.d.mts.map +1 -0
- package/dist/ObjectionFactory-BeFBYcan.cjs.map +1 -1
- package/dist/ObjectionFactory-QCJ7u0Ql.mjs.map +1 -1
- package/dist/{ObjectionFactory-CdhzKs4f.d.cts → ObjectionFactory-aMGvAKt9.d.cts} +4 -3
- package/dist/ObjectionFactory-aMGvAKt9.d.cts.map +1 -0
- package/dist/ObjectionFactory.d.cts +3 -3
- package/dist/ObjectionFactory.d.mts +2 -2
- package/dist/{PostgresKyselyMigrator-upT-hmrz.mjs → PostgresKyselyMigrator-6sE1KOni.mjs} +2 -2
- package/dist/PostgresKyselyMigrator-6sE1KOni.mjs.map +1 -0
- package/dist/{PostgresKyselyMigrator-CIx3AFSR.d.mts → PostgresKyselyMigrator-CBltSOq5.d.cts} +3 -2
- package/dist/PostgresKyselyMigrator-CBltSOq5.d.cts.map +1 -0
- package/dist/{PostgresKyselyMigrator-CfytARcA.cjs → PostgresKyselyMigrator-D6IbPq8t.cjs} +2 -2
- package/dist/PostgresKyselyMigrator-D6IbPq8t.cjs.map +1 -0
- package/dist/{PostgresKyselyMigrator-CQ3aUoy_.d.cts → PostgresKyselyMigrator-DrVWncqd.d.mts} +3 -2
- package/dist/PostgresKyselyMigrator-DrVWncqd.d.mts.map +1 -0
- package/dist/PostgresKyselyMigrator.cjs +2 -2
- package/dist/PostgresKyselyMigrator.d.cts +2 -2
- package/dist/PostgresKyselyMigrator.d.mts +2 -2
- package/dist/PostgresKyselyMigrator.mjs +2 -2
- package/dist/{PostgresMigrator-DbuJGAVy.mjs → PostgresMigrator-BjjenqSd.mjs} +2 -2
- package/dist/PostgresMigrator-BjjenqSd.mjs.map +1 -0
- package/dist/{PostgresMigrator-D5UkK1_K.d.cts → PostgresMigrator-Bres0U6E.d.cts} +2 -1
- package/dist/PostgresMigrator-Bres0U6E.d.cts.map +1 -0
- package/dist/{PostgresMigrator-DFcNdCvD.cjs → PostgresMigrator-D6dQn0x2.cjs} +2 -2
- package/dist/PostgresMigrator-D6dQn0x2.cjs.map +1 -0
- package/dist/{PostgresMigrator-DQaRxoaY.d.mts → PostgresMigrator-S-YYosAC.d.mts} +2 -1
- package/dist/PostgresMigrator-S-YYosAC.d.mts.map +1 -0
- package/dist/PostgresMigrator.cjs +1 -1
- package/dist/PostgresMigrator.d.cts +1 -1
- package/dist/PostgresMigrator.d.mts +1 -1
- package/dist/PostgresMigrator.mjs +1 -1
- package/dist/{PostgresObjectionMigrator-CZHHcCOv.d.cts → PostgresObjectionMigrator-CPfBAP7r.d.cts} +3 -2
- package/dist/PostgresObjectionMigrator-CPfBAP7r.d.cts.map +1 -0
- package/dist/{PostgresObjectionMigrator-BG6ymgnt.cjs → PostgresObjectionMigrator-DK8ODIHQ.cjs} +2 -2
- package/dist/PostgresObjectionMigrator-DK8ODIHQ.cjs.map +1 -0
- package/dist/{PostgresObjectionMigrator-D_hCcrQu.d.mts → PostgresObjectionMigrator-DVEqB5tp.d.mts} +3 -2
- package/dist/PostgresObjectionMigrator-DVEqB5tp.d.mts.map +1 -0
- package/dist/{PostgresObjectionMigrator-DPj2pOpX.mjs → PostgresObjectionMigrator-D_QxXbIN.mjs} +2 -2
- package/dist/PostgresObjectionMigrator-D_QxXbIN.mjs.map +1 -0
- package/dist/PostgresObjectionMigrator.cjs +2 -2
- package/dist/PostgresObjectionMigrator.d.cts +2 -2
- package/dist/PostgresObjectionMigrator.d.mts +2 -2
- package/dist/PostgresObjectionMigrator.mjs +2 -2
- package/dist/{VitestKyselyTransactionIsolator-D3EZZhjZ.d.cts → VitestKyselyTransactionIsolator-CduJlHoT.d.cts} +4 -3
- package/dist/VitestKyselyTransactionIsolator-CduJlHoT.d.cts.map +1 -0
- package/dist/{VitestKyselyTransactionIsolator-Dxlp1u0f.d.mts → VitestKyselyTransactionIsolator-Cswnnj0k.d.mts} +4 -3
- package/dist/VitestKyselyTransactionIsolator-Cswnnj0k.d.mts.map +1 -0
- package/dist/{VitestKyselyTransactionIsolator-EvDLk5zg.cjs → VitestKyselyTransactionIsolator-D7RRXOBa.cjs} +2 -2
- package/dist/VitestKyselyTransactionIsolator-D7RRXOBa.cjs.map +1 -0
- package/dist/{VitestKyselyTransactionIsolator-CNURW8y6.mjs → VitestKyselyTransactionIsolator-DceyIqr4.mjs} +2 -2
- package/dist/VitestKyselyTransactionIsolator-DceyIqr4.mjs.map +1 -0
- package/dist/VitestKyselyTransactionIsolator.cjs +1 -1
- package/dist/VitestKyselyTransactionIsolator.d.cts +2 -2
- package/dist/VitestKyselyTransactionIsolator.d.mts +2 -2
- package/dist/VitestKyselyTransactionIsolator.mjs +1 -1
- package/dist/{VitestObjectionTransactionIsolator-1TpsPqfG.d.cts → VitestObjectionTransactionIsolator-BXoR6xdG.d.cts} +4 -3
- package/dist/VitestObjectionTransactionIsolator-BXoR6xdG.d.cts.map +1 -0
- package/dist/{VitestObjectionTransactionIsolator-CM5KTAFA.cjs → VitestObjectionTransactionIsolator-CdLRrzNf.cjs} +2 -2
- package/dist/VitestObjectionTransactionIsolator-CdLRrzNf.cjs.map +1 -0
- package/dist/{VitestObjectionTransactionIsolator-jQFaCz0u.mjs → VitestObjectionTransactionIsolator-OF2osYY5.mjs} +2 -2
- package/dist/VitestObjectionTransactionIsolator-OF2osYY5.mjs.map +1 -0
- package/dist/{VitestObjectionTransactionIsolator-i9jIgU8Q.d.mts → VitestObjectionTransactionIsolator-x6hY5j4u.d.mts} +4 -3
- package/dist/VitestObjectionTransactionIsolator-x6hY5j4u.d.mts.map +1 -0
- package/dist/VitestObjectionTransactionIsolator.cjs +1 -1
- package/dist/VitestObjectionTransactionIsolator.d.cts +2 -2
- package/dist/VitestObjectionTransactionIsolator.d.mts +2 -2
- package/dist/VitestObjectionTransactionIsolator.mjs +1 -1
- package/dist/{VitestTransactionIsolator-BvR19bYn.d.mts → VitestTransactionIsolator-BNWJqh9f.d.mts} +3 -2
- package/dist/VitestTransactionIsolator-BNWJqh9f.d.mts.map +1 -0
- package/dist/VitestTransactionIsolator-CMfJXZP8.cjs.map +1 -1
- package/dist/{VitestTransactionIsolator-CwQaxZLP.d.cts → VitestTransactionIsolator-CSroc7Df.d.cts} +3 -2
- package/dist/VitestTransactionIsolator-CSroc7Df.d.cts.map +1 -0
- package/dist/VitestTransactionIsolator-DQ7tLqgV.mjs.map +1 -1
- package/dist/VitestTransactionIsolator.d.cts +1 -1
- package/dist/VitestTransactionIsolator.d.mts +1 -1
- package/dist/aws.cjs.map +1 -1
- package/dist/aws.d.cts +2 -0
- package/dist/aws.d.cts.map +1 -0
- package/dist/aws.d.mts +2 -0
- package/dist/aws.d.mts.map +1 -0
- package/dist/aws.mjs.map +1 -1
- package/dist/benchmark.cjs.map +1 -1
- package/dist/benchmark.d.cts +1 -0
- package/dist/benchmark.d.cts.map +1 -0
- package/dist/benchmark.d.mts +1 -0
- package/dist/benchmark.d.mts.map +1 -0
- package/dist/benchmark.mjs.map +1 -1
- package/dist/better-auth.cjs +29 -30
- package/dist/better-auth.cjs.map +1 -1
- package/dist/better-auth.d.cts +2 -2
- package/dist/better-auth.d.cts.map +1 -0
- package/dist/better-auth.d.mts.map +1 -0
- package/dist/better-auth.mjs +29 -30
- package/dist/better-auth.mjs.map +1 -1
- package/dist/directory-B-Ozljzk.mjs.map +1 -1
- package/dist/directory-BVC8g7cX.cjs.map +1 -1
- package/dist/{directory-BXavAeJZ.d.mts → directory-CVrfTq1I.d.mts} +2 -1
- package/dist/directory-CVrfTq1I.d.mts.map +1 -0
- package/dist/directory-Cys9g76X.d.cts +13 -0
- package/dist/directory-Cys9g76X.d.cts.map +1 -0
- package/dist/faker-B14IEMIN.cjs.map +1 -1
- package/dist/faker-BGKYFoCT.mjs.map +1 -1
- package/dist/{faker-DvxiCtxc.d.cts → faker-BSH1EMtg.d.cts} +3 -3
- package/dist/faker-BSH1EMtg.d.cts.map +1 -0
- package/dist/faker-DHh7xs4u.d.mts.map +1 -0
- package/dist/faker.d.cts +1 -1
- package/dist/helpers.cjs.map +1 -1
- package/dist/helpers.d.cts +1 -0
- package/dist/helpers.d.cts.map +1 -0
- package/dist/helpers.d.mts +1 -0
- package/dist/helpers.d.mts.map +1 -0
- package/dist/helpers.mjs.map +1 -1
- package/dist/kysely.cjs +3 -3
- package/dist/kysely.cjs.map +1 -1
- package/dist/kysely.d.cts +8 -7
- package/dist/kysely.d.cts.map +1 -0
- package/dist/kysely.d.mts +7 -6
- package/dist/kysely.d.mts.map +1 -0
- package/dist/kysely.mjs +3 -3
- package/dist/kysely.mjs.map +1 -1
- package/dist/logger.cjs.map +1 -1
- package/dist/logger.d.cts +1 -0
- package/dist/logger.d.cts.map +1 -0
- package/dist/logger.d.mts +1 -0
- package/dist/logger.d.mts.map +1 -0
- package/dist/logger.mjs.map +1 -1
- package/dist/objection.cjs +3 -3
- package/dist/objection.cjs.map +1 -1
- package/dist/objection.d.cts +8 -7
- package/dist/objection.d.cts.map +1 -0
- package/dist/objection.d.mts +7 -6
- package/dist/objection.d.mts.map +1 -0
- package/dist/objection.mjs +3 -3
- package/dist/objection.mjs.map +1 -1
- package/dist/os/directory.d.cts +1 -1
- package/dist/os/directory.d.mts +1 -1
- package/dist/os/index.d.cts +1 -1
- package/dist/os/index.d.mts +1 -1
- package/dist/timer.cjs.map +1 -1
- package/dist/timer.d.cts +2 -0
- package/dist/timer.d.cts.map +1 -0
- package/dist/timer.d.mts +2 -0
- package/dist/timer.d.mts.map +1 -0
- package/dist/timer.mjs.map +1 -1
- package/package.json +5 -5
- package/src/Factory.ts +72 -72
- package/src/KyselyFactory.ts +330 -330
- package/src/ObjectionFactory.ts +354 -355
- package/src/PostgresKyselyMigrator.ts +37 -37
- package/src/PostgresMigrator.ts +107 -107
- package/src/PostgresObjectionMigrator.ts +91 -91
- package/src/VitestKyselyTransactionIsolator.ts +27 -27
- package/src/VitestObjectionTransactionIsolator.ts +39 -39
- package/src/VitestTransactionIsolator.ts +196 -195
- package/src/__tests__/Factory.spec.ts +163 -155
- package/src/__tests__/KyselyFactory.spec.ts +443 -439
- package/src/__tests__/ObjectionFactory.spec.ts +563 -557
- package/src/__tests__/PostgresKyselyMigrator.spec.ts +641 -641
- package/src/__tests__/PostgresMigrator.spec.ts +341 -341
- package/src/__tests__/PostgresObjectionMigrator.spec.ts +578 -578
- package/src/__tests__/VitestObjectionTransactionIsolator.spec.ts +114 -114
- package/src/__tests__/benchmark.spec.ts +140 -0
- package/src/__tests__/better-auth.spec.ts +15 -15
- package/src/__tests__/faker.spec.ts +226 -137
- package/src/__tests__/integration.spec.ts +597 -597
- package/src/__tests__/utilities.spec.ts +211 -0
- package/src/aws.ts +104 -104
- package/src/benchmark.ts +12 -12
- package/src/better-auth.ts +286 -301
- package/src/faker.ts +153 -153
- package/src/helpers.ts +6 -6
- package/src/kysely.ts +33 -33
- package/src/logger.ts +10 -10
- package/src/objection.ts +31 -31
- package/src/os/directory.ts +11 -10
- package/src/timer.ts +1 -1
- package/test/globalSetup.ts +45 -45
- package/test/helpers.ts +189 -189
- package/test/migrations/1749664623372_user.ts +13 -13
- package/tsconfig.json +9 -0
- package/vitest.config.ts +4 -4
- package/dist/PostgresKyselyMigrator-CfytARcA.cjs.map +0 -1
- package/dist/PostgresKyselyMigrator-upT-hmrz.mjs.map +0 -1
- package/dist/PostgresMigrator-DFcNdCvD.cjs.map +0 -1
- package/dist/PostgresMigrator-DbuJGAVy.mjs.map +0 -1
- package/dist/PostgresObjectionMigrator-BG6ymgnt.cjs.map +0 -1
- package/dist/PostgresObjectionMigrator-DPj2pOpX.mjs.map +0 -1
- package/dist/VitestKyselyTransactionIsolator-CNURW8y6.mjs.map +0 -1
- package/dist/VitestKyselyTransactionIsolator-EvDLk5zg.cjs.map +0 -1
- package/dist/VitestObjectionTransactionIsolator-CM5KTAFA.cjs.map +0 -1
- package/dist/VitestObjectionTransactionIsolator-jQFaCz0u.mjs.map +0 -1
- package/dist/directory-Mi7tdOuD.d.cts +0 -12
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { Kysely, type MigrationProvider, PostgresDialect, sql } from 'kysely';
|
|
2
2
|
import { Client, Pool } from 'pg';
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
afterAll,
|
|
5
|
+
afterEach,
|
|
6
|
+
beforeAll,
|
|
7
|
+
beforeEach,
|
|
8
|
+
describe,
|
|
9
|
+
expect,
|
|
10
|
+
it,
|
|
11
|
+
vi,
|
|
12
12
|
} from 'vitest';
|
|
13
13
|
import { createTestDatabase } from '../../test/helpers';
|
|
14
14
|
import { PostgresKyselyMigrator } from '../PostgresKyselyMigrator';
|
|
@@ -16,415 +16,415 @@ import { PostgresMigrator } from '../PostgresMigrator';
|
|
|
16
16
|
|
|
17
17
|
// Test database schema
|
|
18
18
|
interface TestSchema {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
19
|
+
users: {
|
|
20
|
+
id: number;
|
|
21
|
+
name: string;
|
|
22
|
+
email: string;
|
|
23
|
+
created_at: Date;
|
|
24
|
+
};
|
|
25
|
+
posts: {
|
|
26
|
+
id: number;
|
|
27
|
+
title: string;
|
|
28
|
+
content: string;
|
|
29
|
+
user_id: number;
|
|
30
|
+
created_at: Date;
|
|
31
|
+
};
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
// Test migration provider
|
|
35
35
|
class TestMigrationProvider implements MigrationProvider {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
36
|
+
private migrations: Record<string, any> = {};
|
|
37
|
+
private shouldError = false;
|
|
38
|
+
|
|
39
|
+
addMigration(
|
|
40
|
+
name: string,
|
|
41
|
+
migration: {
|
|
42
|
+
up: (db: Kysely<any>) => Promise<void>;
|
|
43
|
+
down?: (db: Kysely<any>) => Promise<void>;
|
|
44
|
+
},
|
|
45
|
+
) {
|
|
46
|
+
this.migrations[name] = migration;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
setError(shouldError: boolean) {
|
|
50
|
+
this.shouldError = shouldError;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async getMigrations() {
|
|
54
|
+
if (this.shouldError) {
|
|
55
|
+
throw new Error('Failed to load migrations');
|
|
56
|
+
}
|
|
57
|
+
return this.migrations;
|
|
58
|
+
}
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
describe('PostgresKyselyMigrator', () => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
62
|
+
let testDbName: string;
|
|
63
|
+
let cleanupDb: () => Promise<void>;
|
|
64
|
+
let consoleSpy: any;
|
|
65
|
+
let consoleErrorSpy: any;
|
|
66
|
+
|
|
67
|
+
beforeAll(async () => {
|
|
68
|
+
// Create a unique test database for each test run
|
|
69
|
+
testDbName = `test_kysely_migrator_${Date.now()}`;
|
|
70
|
+
cleanupDb = await createTestDatabase(testDbName);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
beforeEach(() => {
|
|
74
|
+
consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
|
|
75
|
+
consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
afterEach(() => {
|
|
79
|
+
consoleSpy.mockRestore();
|
|
80
|
+
consoleErrorSpy.mockRestore();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
afterAll(async () => {
|
|
84
|
+
await cleanupDb();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
describe('constructor', () => {
|
|
88
|
+
it('should create a PostgresKyselyMigrator instance', () => {
|
|
89
|
+
const db = new Kysely<TestSchema>({
|
|
90
|
+
dialect: new PostgresDialect({
|
|
91
|
+
pool: new Pool({
|
|
92
|
+
host: 'localhost',
|
|
93
|
+
port: 5432,
|
|
94
|
+
user: 'geekmidas',
|
|
95
|
+
password: 'geekmidas',
|
|
96
|
+
database: testDbName,
|
|
97
|
+
}),
|
|
98
|
+
}),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const provider = new TestMigrationProvider();
|
|
102
|
+
const migrator = new PostgresKyselyMigrator({
|
|
103
|
+
uri: `postgresql://geekmidas:geekmidas@localhost:5432/${testDbName}`,
|
|
104
|
+
db,
|
|
105
|
+
provider,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
expect(migrator).toBeInstanceOf(PostgresKyselyMigrator);
|
|
109
|
+
expect(migrator).toBeInstanceOf(PostgresMigrator);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
describe('migrate method', () => {
|
|
114
|
+
it('should apply migrations successfully', async () => {
|
|
115
|
+
const newDbName = `test_migrate_${Date.now()}`;
|
|
116
|
+
const uri = `postgresql://geekmidas:geekmidas@localhost:5432/${newDbName}`;
|
|
117
|
+
|
|
118
|
+
const db = new Kysely<TestSchema>({
|
|
119
|
+
dialect: new PostgresDialect({
|
|
120
|
+
pool: new Pool({
|
|
121
|
+
host: 'localhost',
|
|
122
|
+
port: 5432,
|
|
123
|
+
user: 'geekmidas',
|
|
124
|
+
password: 'geekmidas',
|
|
125
|
+
database: newDbName,
|
|
126
|
+
}),
|
|
127
|
+
}),
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
const provider = new TestMigrationProvider();
|
|
131
|
+
|
|
132
|
+
// Add test migrations
|
|
133
|
+
provider.addMigration('001_create_users', {
|
|
134
|
+
up: async (db) => {
|
|
135
|
+
await db.schema
|
|
136
|
+
.createTable('users')
|
|
137
|
+
.addColumn('id', 'serial', (col) => col.primaryKey())
|
|
138
|
+
.addColumn('name', 'varchar', (col) => col.notNull())
|
|
139
|
+
.addColumn('email', 'varchar', (col) => col.notNull().unique())
|
|
140
|
+
.addColumn('created_at', 'timestamp', (col) =>
|
|
141
|
+
col.defaultTo(sql`now()`).notNull(),
|
|
142
|
+
)
|
|
143
|
+
.execute();
|
|
144
|
+
},
|
|
145
|
+
down: async (db) => {
|
|
146
|
+
await db.schema.dropTable('users').execute();
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
provider.addMigration('002_create_posts', {
|
|
151
|
+
up: async (db) => {
|
|
152
|
+
await db.schema
|
|
153
|
+
.createTable('posts')
|
|
154
|
+
.addColumn('id', 'serial', (col) => col.primaryKey())
|
|
155
|
+
.addColumn('title', 'varchar', (col) => col.notNull())
|
|
156
|
+
.addColumn('content', 'text', (col) => col.notNull())
|
|
157
|
+
.addColumn('user_id', 'integer', (col) =>
|
|
158
|
+
col.notNull().references('users.id').onDelete('cascade'),
|
|
159
|
+
)
|
|
160
|
+
.addColumn('created_at', 'timestamp', (col) =>
|
|
161
|
+
col.defaultTo(sql`now()`).notNull(),
|
|
162
|
+
)
|
|
163
|
+
.execute();
|
|
164
|
+
},
|
|
165
|
+
down: async (db) => {
|
|
166
|
+
await db.schema.dropTable('posts').execute();
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
const migrator = new PostgresKyselyMigrator({
|
|
171
|
+
uri,
|
|
172
|
+
db,
|
|
173
|
+
provider,
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// Start the migrator (creates database and runs migrations)
|
|
177
|
+
const cleanup = await migrator.start();
|
|
178
|
+
|
|
179
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
180
|
+
expect.stringContaining('Applied 2 migrations successfully'),
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
// Verify tables were created
|
|
184
|
+
const client = new Client({
|
|
185
|
+
host: 'localhost',
|
|
186
|
+
port: 5432,
|
|
187
|
+
user: 'geekmidas',
|
|
188
|
+
password: 'geekmidas',
|
|
189
|
+
database: newDbName,
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
try {
|
|
193
|
+
await client.connect();
|
|
194
|
+
const tablesResult = await client.query(`
|
|
195
195
|
SELECT table_name FROM information_schema.tables
|
|
196
196
|
WHERE table_schema = 'public'
|
|
197
197
|
AND table_name IN ('users', 'posts')
|
|
198
198
|
ORDER BY table_name
|
|
199
199
|
`);
|
|
200
200
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
201
|
+
expect(tablesResult.rowCount).toBe(2);
|
|
202
|
+
expect(tablesResult.rows).toEqual([
|
|
203
|
+
{ table_name: 'posts' },
|
|
204
|
+
{ table_name: 'users' },
|
|
205
|
+
]);
|
|
206
|
+
} finally {
|
|
207
|
+
await client.end();
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Cleanup
|
|
211
|
+
await cleanup();
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('should handle migration errors', async () => {
|
|
215
|
+
const errorDbName = `test_migrate_error_${Date.now()}`;
|
|
216
|
+
const uri = `postgresql://geekmidas:geekmidas@localhost:5432/${errorDbName}`;
|
|
217
|
+
|
|
218
|
+
const db = new Kysely<TestSchema>({
|
|
219
|
+
dialect: new PostgresDialect({
|
|
220
|
+
pool: new Pool({
|
|
221
|
+
host: 'localhost',
|
|
222
|
+
port: 5432,
|
|
223
|
+
user: 'geekmidas',
|
|
224
|
+
password: 'geekmidas',
|
|
225
|
+
database: errorDbName,
|
|
226
|
+
}),
|
|
227
|
+
}),
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
const provider = new TestMigrationProvider();
|
|
231
|
+
|
|
232
|
+
// Add a migration that will fail
|
|
233
|
+
provider.addMigration('001_failing_migration', {
|
|
234
|
+
up: async () => {
|
|
235
|
+
throw new Error('Migration failed intentionally');
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
const migrator = new PostgresKyselyMigrator({
|
|
240
|
+
uri,
|
|
241
|
+
db,
|
|
242
|
+
provider,
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// Expect the start method to throw
|
|
246
|
+
await expect(migrator.start()).rejects.toThrow(
|
|
247
|
+
'Migration failed intentionally',
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
251
|
+
expect.any(Error),
|
|
252
|
+
'Failed to apply migrations',
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
// Ensure db is closed before cleanup
|
|
256
|
+
await db.destroy();
|
|
257
|
+
|
|
258
|
+
// Cleanup the created database
|
|
259
|
+
const cleanupClient = new Client({
|
|
260
|
+
host: 'localhost',
|
|
261
|
+
port: 5432,
|
|
262
|
+
user: 'geekmidas',
|
|
263
|
+
password: 'geekmidas',
|
|
264
|
+
database: 'postgres',
|
|
265
|
+
});
|
|
266
|
+
try {
|
|
267
|
+
await cleanupClient.connect();
|
|
268
|
+
// Force disconnect any existing connections
|
|
269
|
+
await cleanupClient.query(`
|
|
270
270
|
SELECT pg_terminate_backend(pg_stat_activity.pid)
|
|
271
271
|
FROM pg_stat_activity
|
|
272
272
|
WHERE pg_stat_activity.datname = '${errorDbName}'
|
|
273
273
|
AND pid <> pg_backend_pid()
|
|
274
274
|
`);
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
275
|
+
await cleanupClient.query(`DROP DATABASE IF EXISTS "${errorDbName}"`);
|
|
276
|
+
} finally {
|
|
277
|
+
await cleanupClient.end();
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it('should destroy database connection after migrations', async () => {
|
|
282
|
+
const destroyDbName = `test_destroy_${Date.now()}`;
|
|
283
|
+
const uri = `postgresql://geekmidas:geekmidas@localhost:5432/${destroyDbName}`;
|
|
284
|
+
|
|
285
|
+
const db = new Kysely<TestSchema>({
|
|
286
|
+
dialect: new PostgresDialect({
|
|
287
|
+
pool: new Pool({
|
|
288
|
+
host: 'localhost',
|
|
289
|
+
port: 5432,
|
|
290
|
+
user: 'geekmidas',
|
|
291
|
+
password: 'geekmidas',
|
|
292
|
+
database: destroyDbName,
|
|
293
|
+
}),
|
|
294
|
+
}),
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
const destroySpy = vi.spyOn(db, 'destroy');
|
|
298
|
+
const provider = new TestMigrationProvider();
|
|
299
|
+
|
|
300
|
+
provider.addMigration('001_simple', {
|
|
301
|
+
up: async (db) => {
|
|
302
|
+
await db.schema
|
|
303
|
+
.createTable('test')
|
|
304
|
+
.addColumn('id', 'serial', (col) => col.primaryKey())
|
|
305
|
+
.execute();
|
|
306
|
+
},
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
const migrator = new PostgresKyselyMigrator({
|
|
310
|
+
uri,
|
|
311
|
+
db,
|
|
312
|
+
provider,
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
const cleanup = await migrator.start();
|
|
316
|
+
|
|
317
|
+
// Verify destroy was called after migrations
|
|
318
|
+
expect(destroySpy).toHaveBeenCalled();
|
|
319
|
+
|
|
320
|
+
// Cleanup
|
|
321
|
+
await cleanup();
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
describe('integration with PostgresMigrator', () => {
|
|
326
|
+
it('should work with complete workflow', async () => {
|
|
327
|
+
const integrationDbName = `test_integration_${Date.now()}`;
|
|
328
|
+
const uri = `postgresql://geekmidas:geekmidas@localhost:5432/${integrationDbName}`;
|
|
329
|
+
|
|
330
|
+
const db = new Kysely<TestSchema>({
|
|
331
|
+
dialect: new PostgresDialect({
|
|
332
|
+
pool: new Pool({
|
|
333
|
+
host: 'localhost',
|
|
334
|
+
port: 5432,
|
|
335
|
+
user: 'geekmidas',
|
|
336
|
+
password: 'geekmidas',
|
|
337
|
+
database: integrationDbName,
|
|
338
|
+
}),
|
|
339
|
+
}),
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
const provider = new TestMigrationProvider();
|
|
343
|
+
|
|
344
|
+
// Add comprehensive migrations
|
|
345
|
+
provider.addMigration('001_initial_schema', {
|
|
346
|
+
up: async (db) => {
|
|
347
|
+
// Users table
|
|
348
|
+
await db.schema
|
|
349
|
+
.createTable('users')
|
|
350
|
+
.addColumn('id', 'serial', (col) => col.primaryKey())
|
|
351
|
+
.addColumn('name', 'varchar', (col) => col.notNull())
|
|
352
|
+
.addColumn('email', 'varchar', (col) => col.notNull().unique())
|
|
353
|
+
.addColumn('created_at', 'timestamp', (col) =>
|
|
354
|
+
col.defaultTo(sql`now()`).notNull(),
|
|
355
|
+
)
|
|
356
|
+
.execute();
|
|
357
|
+
|
|
358
|
+
// Posts table
|
|
359
|
+
await db.schema
|
|
360
|
+
.createTable('posts')
|
|
361
|
+
.addColumn('id', 'serial', (col) => col.primaryKey())
|
|
362
|
+
.addColumn('title', 'varchar', (col) => col.notNull())
|
|
363
|
+
.addColumn('content', 'text', (col) => col.notNull())
|
|
364
|
+
.addColumn('user_id', 'integer', (col) =>
|
|
365
|
+
col.notNull().references('users.id').onDelete('cascade'),
|
|
366
|
+
)
|
|
367
|
+
.addColumn('created_at', 'timestamp', (col) =>
|
|
368
|
+
col.defaultTo(sql`now()`).notNull(),
|
|
369
|
+
)
|
|
370
|
+
.execute();
|
|
371
|
+
|
|
372
|
+
// Add index
|
|
373
|
+
await db.schema
|
|
374
|
+
.createIndex('idx_posts_user_id')
|
|
375
|
+
.on('posts')
|
|
376
|
+
.column('user_id')
|
|
377
|
+
.execute();
|
|
378
|
+
},
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
provider.addMigration('002_add_updated_at', {
|
|
382
|
+
up: async (db) => {
|
|
383
|
+
await db.schema
|
|
384
|
+
.alterTable('users')
|
|
385
|
+
.addColumn('updated_at', 'timestamp', (col) =>
|
|
386
|
+
col.defaultTo(sql`now()`).notNull(),
|
|
387
|
+
)
|
|
388
|
+
.execute();
|
|
389
|
+
|
|
390
|
+
await db.schema
|
|
391
|
+
.alterTable('posts')
|
|
392
|
+
.addColumn('updated_at', 'timestamp', (col) =>
|
|
393
|
+
col.defaultTo(sql`now()`).notNull(),
|
|
394
|
+
)
|
|
395
|
+
.execute();
|
|
396
|
+
},
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
const migrator = new PostgresKyselyMigrator({
|
|
400
|
+
uri,
|
|
401
|
+
db,
|
|
402
|
+
provider,
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
const cleanup = await migrator.start();
|
|
406
|
+
|
|
407
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
408
|
+
`Migrating database: ${integrationDbName}`,
|
|
409
|
+
);
|
|
410
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
411
|
+
'Applied 2 migrations successfully',
|
|
412
|
+
);
|
|
413
|
+
|
|
414
|
+
// Verify final schema
|
|
415
|
+
const verifyClient = new Client({
|
|
416
|
+
host: 'localhost',
|
|
417
|
+
port: 5432,
|
|
418
|
+
user: 'geekmidas',
|
|
419
|
+
password: 'geekmidas',
|
|
420
|
+
database: integrationDbName,
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
try {
|
|
424
|
+
await verifyClient.connect();
|
|
425
|
+
|
|
426
|
+
// Check columns exist
|
|
427
|
+
const columnsResult = await verifyClient.query(`
|
|
428
428
|
SELECT table_name, column_name
|
|
429
429
|
FROM information_schema.columns
|
|
430
430
|
WHERE table_schema = 'public'
|
|
@@ -433,258 +433,258 @@ describe('PostgresKyselyMigrator', () => {
|
|
|
433
433
|
ORDER BY table_name
|
|
434
434
|
`);
|
|
435
435
|
|
|
436
|
-
|
|
436
|
+
expect(columnsResult.rowCount).toBe(2);
|
|
437
437
|
|
|
438
|
-
|
|
439
|
-
|
|
438
|
+
// Check index exists
|
|
439
|
+
const indexResult = await verifyClient.query(`
|
|
440
440
|
SELECT indexname FROM pg_indexes
|
|
441
441
|
WHERE schemaname = 'public'
|
|
442
442
|
AND indexname = 'idx_posts_user_id'
|
|
443
443
|
`);
|
|
444
444
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
445
|
+
expect(indexResult.rowCount).toBe(1);
|
|
446
|
+
} finally {
|
|
447
|
+
await verifyClient.end();
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// Cleanup
|
|
451
|
+
await cleanup();
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
it('should handle empty migrations', async () => {
|
|
455
|
+
const emptyDbName = `test_empty_${Date.now()}`;
|
|
456
|
+
const uri = `postgresql://geekmidas:geekmidas@localhost:5432/${emptyDbName}`;
|
|
457
|
+
|
|
458
|
+
const db = new Kysely<TestSchema>({
|
|
459
|
+
dialect: new PostgresDialect({
|
|
460
|
+
pool: new Pool({
|
|
461
|
+
host: 'localhost',
|
|
462
|
+
port: 5432,
|
|
463
|
+
user: 'geekmidas',
|
|
464
|
+
password: 'geekmidas',
|
|
465
|
+
database: emptyDbName,
|
|
466
|
+
}),
|
|
467
|
+
}),
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
const provider = new TestMigrationProvider();
|
|
471
|
+
// No migrations added
|
|
472
|
+
|
|
473
|
+
const migrator = new PostgresKyselyMigrator({
|
|
474
|
+
uri,
|
|
475
|
+
db,
|
|
476
|
+
provider,
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
const cleanup = await migrator.start();
|
|
480
|
+
|
|
481
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
482
|
+
'Applied 0 migrations successfully',
|
|
483
|
+
);
|
|
484
|
+
|
|
485
|
+
await cleanup();
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
it('should work with FileMigrationProvider pattern', async () => {
|
|
489
|
+
const fileProviderDbName = `test_file_provider_${Date.now()}`;
|
|
490
|
+
const uri = `postgresql://geekmidas:geekmidas@localhost:5432/${fileProviderDbName}`;
|
|
491
|
+
|
|
492
|
+
const db = new Kysely<TestSchema>({
|
|
493
|
+
dialect: new PostgresDialect({
|
|
494
|
+
pool: new Pool({
|
|
495
|
+
host: 'localhost',
|
|
496
|
+
port: 5432,
|
|
497
|
+
user: 'geekmidas',
|
|
498
|
+
password: 'geekmidas',
|
|
499
|
+
database: fileProviderDbName,
|
|
500
|
+
}),
|
|
501
|
+
}),
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
// Simulate a file-based migration provider
|
|
505
|
+
const migrations = {
|
|
506
|
+
'2024_01_01_000001_create_users': {
|
|
507
|
+
up: async (db: Kysely<any>) => {
|
|
508
|
+
await db.schema
|
|
509
|
+
.createTable('users')
|
|
510
|
+
.addColumn('id', 'serial', (col) => col.primaryKey())
|
|
511
|
+
.addColumn('username', 'varchar', (col) => col.notNull().unique())
|
|
512
|
+
.execute();
|
|
513
|
+
},
|
|
514
|
+
down: async (db: Kysely<any>) => {
|
|
515
|
+
await db.schema.dropTable('users').execute();
|
|
516
|
+
},
|
|
517
|
+
},
|
|
518
|
+
'2024_01_02_000001_create_sessions': {
|
|
519
|
+
up: async (db: Kysely<any>) => {
|
|
520
|
+
await db.schema
|
|
521
|
+
.createTable('sessions')
|
|
522
|
+
.addColumn('id', 'serial', (col) => col.primaryKey())
|
|
523
|
+
.addColumn('user_id', 'integer', (col) =>
|
|
524
|
+
col.notNull().references('users.id'),
|
|
525
|
+
)
|
|
526
|
+
.addColumn('token', 'varchar', (col) => col.notNull())
|
|
527
|
+
.execute();
|
|
528
|
+
},
|
|
529
|
+
down: async (db: Kysely<any>) => {
|
|
530
|
+
await db.schema.dropTable('sessions').execute();
|
|
531
|
+
},
|
|
532
|
+
},
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
const provider: MigrationProvider = {
|
|
536
|
+
async getMigrations() {
|
|
537
|
+
return migrations;
|
|
538
|
+
},
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
const migrator = new PostgresKyselyMigrator({
|
|
542
|
+
uri,
|
|
543
|
+
db,
|
|
544
|
+
provider,
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
const cleanup = await migrator.start();
|
|
548
|
+
|
|
549
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
550
|
+
'Applied 2 migrations successfully',
|
|
551
|
+
);
|
|
552
|
+
|
|
553
|
+
// Verify both tables exist
|
|
554
|
+
const verifyClient = new Client({
|
|
555
|
+
host: 'localhost',
|
|
556
|
+
port: 5432,
|
|
557
|
+
user: 'geekmidas',
|
|
558
|
+
password: 'geekmidas',
|
|
559
|
+
database: fileProviderDbName,
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
try {
|
|
563
|
+
await verifyClient.connect();
|
|
564
|
+
const tablesResult = await verifyClient.query(`
|
|
565
565
|
SELECT table_name FROM information_schema.tables
|
|
566
566
|
WHERE table_schema = 'public'
|
|
567
567
|
AND table_name IN ('users', 'sessions')
|
|
568
568
|
ORDER BY table_name
|
|
569
569
|
`);
|
|
570
570
|
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
571
|
+
expect(tablesResult.rowCount).toBe(2);
|
|
572
|
+
} finally {
|
|
573
|
+
await verifyClient.end();
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
await cleanup();
|
|
577
|
+
});
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
describe('error scenarios', () => {
|
|
581
|
+
it('should handle provider errors', async () => {
|
|
582
|
+
const providerErrorDbName = `test_provider_error_${Date.now()}`;
|
|
583
|
+
const uri = `postgresql://geekmidas:geekmidas@localhost:5432/${providerErrorDbName}`;
|
|
584
|
+
|
|
585
|
+
const db = new Kysely<TestSchema>({
|
|
586
|
+
dialect: new PostgresDialect({
|
|
587
|
+
pool: new Pool({
|
|
588
|
+
host: 'localhost',
|
|
589
|
+
port: 5432,
|
|
590
|
+
user: 'geekmidas',
|
|
591
|
+
password: 'geekmidas',
|
|
592
|
+
database: providerErrorDbName,
|
|
593
|
+
}),
|
|
594
|
+
}),
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
const provider = new TestMigrationProvider();
|
|
598
|
+
provider.setError(true);
|
|
599
|
+
|
|
600
|
+
const migrator = new PostgresKyselyMigrator({
|
|
601
|
+
uri,
|
|
602
|
+
db,
|
|
603
|
+
provider,
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
await expect(migrator.start()).rejects.toThrow(
|
|
607
|
+
'Failed to load migrations',
|
|
608
|
+
);
|
|
609
|
+
|
|
610
|
+
// Ensure db is closed
|
|
611
|
+
await db.destroy();
|
|
612
|
+
|
|
613
|
+
// Cleanup
|
|
614
|
+
const cleanupClient = new Client({
|
|
615
|
+
host: 'localhost',
|
|
616
|
+
port: 5432,
|
|
617
|
+
user: 'geekmidas',
|
|
618
|
+
password: 'geekmidas',
|
|
619
|
+
database: 'postgres',
|
|
620
|
+
});
|
|
621
|
+
try {
|
|
622
|
+
await cleanupClient.connect();
|
|
623
|
+
await cleanupClient.query(
|
|
624
|
+
`DROP DATABASE IF EXISTS "${providerErrorDbName}"`,
|
|
625
|
+
);
|
|
626
|
+
} finally {
|
|
627
|
+
await cleanupClient.end();
|
|
628
|
+
}
|
|
629
|
+
}, 10000);
|
|
630
|
+
|
|
631
|
+
it('should handle invalid SQL in migrations', async () => {
|
|
632
|
+
const invalidSqlDbName = `test_invalid_sql_${Date.now()}`;
|
|
633
|
+
const uri = `postgresql://geekmidas:geekmidas@localhost:5432/${invalidSqlDbName}`;
|
|
634
|
+
|
|
635
|
+
const db = new Kysely<TestSchema>({
|
|
636
|
+
dialect: new PostgresDialect({
|
|
637
|
+
pool: new Pool({
|
|
638
|
+
host: 'localhost',
|
|
639
|
+
port: 5432,
|
|
640
|
+
user: 'geekmidas',
|
|
641
|
+
password: 'geekmidas',
|
|
642
|
+
database: invalidSqlDbName,
|
|
643
|
+
}),
|
|
644
|
+
}),
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
const provider = new TestMigrationProvider();
|
|
648
|
+
provider.addMigration('001_invalid_sql', {
|
|
649
|
+
up: async (db) => {
|
|
650
|
+
// Try to reference non-existent table
|
|
651
|
+
await db.schema
|
|
652
|
+
.createTable('posts')
|
|
653
|
+
.addColumn('id', 'serial', (col) => col.primaryKey())
|
|
654
|
+
.addColumn('user_id', 'integer', (col) =>
|
|
655
|
+
col.notNull().references('non_existent_table.id'),
|
|
656
|
+
)
|
|
657
|
+
.execute();
|
|
658
|
+
},
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
const migrator = new PostgresKyselyMigrator({
|
|
662
|
+
uri,
|
|
663
|
+
db,
|
|
664
|
+
provider,
|
|
665
|
+
});
|
|
666
|
+
|
|
667
|
+
await expect(migrator.start()).rejects.toThrow();
|
|
668
|
+
|
|
669
|
+
// Ensure db is closed
|
|
670
|
+
await db.destroy();
|
|
671
|
+
|
|
672
|
+
// Cleanup
|
|
673
|
+
const cleanupClient = new Client({
|
|
674
|
+
host: 'localhost',
|
|
675
|
+
port: 5432,
|
|
676
|
+
user: 'geekmidas',
|
|
677
|
+
password: 'geekmidas',
|
|
678
|
+
database: 'postgres',
|
|
679
|
+
});
|
|
680
|
+
try {
|
|
681
|
+
await cleanupClient.connect();
|
|
682
|
+
await cleanupClient.query(
|
|
683
|
+
`DROP DATABASE IF EXISTS "${invalidSqlDbName}"`,
|
|
684
|
+
);
|
|
685
|
+
} finally {
|
|
686
|
+
await cleanupClient.end();
|
|
687
|
+
}
|
|
688
|
+
}, 10000);
|
|
689
|
+
});
|
|
690
690
|
});
|