rake-db 2.3.3 → 2.3.4
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 +6 -0
- package/dist/index.d.ts +0 -4
- package/dist/index.esm.js +78 -209
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +77 -208
- package/dist/index.js.map +1 -1
- package/migrations/20221017200326_createChatUser.ts +1 -1
- package/package.json +1 -1
- package/src/migration/migration.ts +0 -35
- package/migrations/20230124210600_pull.ts +0 -86
- package/src/migration/createJoinTable.test.ts +0 -96
- package/src/migration/createJoinTable.ts +0 -107
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { change } from '../src';
|
|
2
2
|
|
|
3
3
|
change(async (db) => {
|
|
4
|
-
await db.
|
|
4
|
+
await db.createTable('chatUser', (t) => ({
|
|
5
5
|
chatId: t.integer().foreignKey('chat', 'id'),
|
|
6
6
|
userId: t.integer().foreignKey('user', 'id'),
|
|
7
7
|
...t.timestamps(),
|
package/package.json
CHANGED
|
@@ -26,7 +26,6 @@ import {
|
|
|
26
26
|
quoteWithSchema,
|
|
27
27
|
getSchemaAndTableFromName,
|
|
28
28
|
} from '../common';
|
|
29
|
-
import { createJoinTable } from './createJoinTable';
|
|
30
29
|
import { RakeDbAst } from '../ast';
|
|
31
30
|
|
|
32
31
|
export type DropMode = 'CASCADE' | 'RESTRICT';
|
|
@@ -131,40 +130,6 @@ export class Migration extends TransactionAdapter {
|
|
|
131
130
|
return createTable(this, !this.up, tableName, options, fn);
|
|
132
131
|
}
|
|
133
132
|
|
|
134
|
-
createJoinTable(
|
|
135
|
-
tables: string[],
|
|
136
|
-
options?: JoinTableOptions,
|
|
137
|
-
fn?: ColumnsShapeCallback,
|
|
138
|
-
): Promise<void>;
|
|
139
|
-
createJoinTable(tables: string[], fn?: ColumnsShapeCallback): Promise<void>;
|
|
140
|
-
async createJoinTable(
|
|
141
|
-
tables: string[],
|
|
142
|
-
cbOrOptions?: ColumnsShapeCallback | JoinTableOptions,
|
|
143
|
-
cb?: ColumnsShapeCallback,
|
|
144
|
-
): Promise<void> {
|
|
145
|
-
const options = typeof cbOrOptions === 'function' ? {} : cbOrOptions || {};
|
|
146
|
-
const fn = (cb || cbOrOptions) as ColumnsShapeCallback | undefined;
|
|
147
|
-
|
|
148
|
-
return createJoinTable(this, this.up, tables, options, fn);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
dropJoinTable(
|
|
152
|
-
tables: string[],
|
|
153
|
-
options?: JoinTableOptions,
|
|
154
|
-
fn?: ColumnsShapeCallback,
|
|
155
|
-
): Promise<void>;
|
|
156
|
-
dropJoinTable(tables: string[], fn?: ColumnsShapeCallback): Promise<void>;
|
|
157
|
-
async dropJoinTable(
|
|
158
|
-
tables: string[],
|
|
159
|
-
cbOrOptions?: ColumnsShapeCallback | JoinTableOptions,
|
|
160
|
-
cb?: ColumnsShapeCallback,
|
|
161
|
-
): Promise<void> {
|
|
162
|
-
const options = typeof cbOrOptions === 'function' ? {} : cbOrOptions || {};
|
|
163
|
-
const fn = (cb || cbOrOptions) as ColumnsShapeCallback | undefined;
|
|
164
|
-
|
|
165
|
-
return createJoinTable(this, !this.up, tables, options, fn);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
133
|
changeTable(
|
|
169
134
|
tableName: string,
|
|
170
135
|
options: ChangeTableOptions,
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { change } from '../src';
|
|
2
|
-
|
|
3
|
-
change(async (db) => {
|
|
4
|
-
await db.createSchema('geo');
|
|
5
|
-
|
|
6
|
-
await db.createTable('chat', (t) => ({
|
|
7
|
-
id: t.serial().primaryKey(),
|
|
8
|
-
title: t.text(),
|
|
9
|
-
...t.timestamps(),
|
|
10
|
-
}));
|
|
11
|
-
|
|
12
|
-
await db.createTable('chatUser', (t) => ({
|
|
13
|
-
chatId: t.integer().foreignKey('chat', 'id'),
|
|
14
|
-
userId: t.integer().foreignKey('user', 'id'),
|
|
15
|
-
...t.timestamps(),
|
|
16
|
-
...t.primaryKey(['chatId', 'userId']),
|
|
17
|
-
}));
|
|
18
|
-
|
|
19
|
-
await db.createTable('geo.city', (t) => ({
|
|
20
|
-
id: t.serial().primaryKey(),
|
|
21
|
-
name: t.text(),
|
|
22
|
-
countryId: t.integer().foreignKey('country', 'id'),
|
|
23
|
-
}));
|
|
24
|
-
|
|
25
|
-
await db.createTable('geo.country', (t) => ({
|
|
26
|
-
id: t.serial().primaryKey(),
|
|
27
|
-
name: t.text(),
|
|
28
|
-
}));
|
|
29
|
-
|
|
30
|
-
await db.createTable('message', (t) => ({
|
|
31
|
-
id: t.serial().primaryKey(),
|
|
32
|
-
chatId: t.integer().foreignKey('chat', 'id').index({
|
|
33
|
-
name: 'messageChatIdIndex',
|
|
34
|
-
}),
|
|
35
|
-
authorId: t.integer().foreignKey('user', 'id').nullable().index({
|
|
36
|
-
name: 'messageAuthorIdIndex',
|
|
37
|
-
}),
|
|
38
|
-
text: t.text(),
|
|
39
|
-
meta: t.json((t) => t.unknown()).nullable(),
|
|
40
|
-
...t.timestamps(),
|
|
41
|
-
}));
|
|
42
|
-
|
|
43
|
-
await db.createTable('profile', (t) => ({
|
|
44
|
-
id: t.serial().primaryKey(),
|
|
45
|
-
userId: t.integer().foreignKey('user', 'id').nullable(),
|
|
46
|
-
bio: t.text().nullable(),
|
|
47
|
-
...t.timestamps(),
|
|
48
|
-
}));
|
|
49
|
-
|
|
50
|
-
await db.createTable('uniqueTable', (t) => ({
|
|
51
|
-
id: t.serial().primaryKey(),
|
|
52
|
-
one: t.text().unique({
|
|
53
|
-
name: 'uniqueTableOneIndex',
|
|
54
|
-
}),
|
|
55
|
-
two: t.integer().unique({
|
|
56
|
-
name: 'uniqueTableTwoIndex',
|
|
57
|
-
}),
|
|
58
|
-
thirdColumn: t.text(),
|
|
59
|
-
fourthColumn: t.integer(),
|
|
60
|
-
...t.index(
|
|
61
|
-
[
|
|
62
|
-
{
|
|
63
|
-
column: 'thirdColumn',
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
column: 'fourthColumn',
|
|
67
|
-
},
|
|
68
|
-
],
|
|
69
|
-
{
|
|
70
|
-
name: 'uniqueTableThirdColumnFourthColumnIndex',
|
|
71
|
-
unique: true,
|
|
72
|
-
},
|
|
73
|
-
),
|
|
74
|
-
}));
|
|
75
|
-
|
|
76
|
-
await db.createTable('user', (t) => ({
|
|
77
|
-
id: t.serial().primaryKey(),
|
|
78
|
-
name: t.text(),
|
|
79
|
-
password: t.text(),
|
|
80
|
-
picture: t.text().nullable(),
|
|
81
|
-
data: t.json((t) => t.unknown()).nullable(),
|
|
82
|
-
age: t.integer().nullable(),
|
|
83
|
-
active: t.boolean().nullable(),
|
|
84
|
-
...t.timestamps(),
|
|
85
|
-
}));
|
|
86
|
-
});
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { getPrimaryKeysOfTable } from './migrationUtils';
|
|
2
|
-
import { expectSql, getDb, queryMock, resetDb } from '../test-utils';
|
|
3
|
-
|
|
4
|
-
const db = getDb();
|
|
5
|
-
|
|
6
|
-
jest.mock('./migrationUtils', () => ({
|
|
7
|
-
...jest.requireActual('./migrationUtils'),
|
|
8
|
-
getPrimaryKeysOfTable: jest.fn(),
|
|
9
|
-
}));
|
|
10
|
-
|
|
11
|
-
describe('join table', () => {
|
|
12
|
-
beforeEach(resetDb);
|
|
13
|
-
|
|
14
|
-
(['createJoinTable', 'dropJoinTable'] as const).forEach((action) => {
|
|
15
|
-
describe(action, () => {
|
|
16
|
-
it(`should ${
|
|
17
|
-
action === 'createJoinTable' ? 'create' : 'drop'
|
|
18
|
-
} a join table`, async () => {
|
|
19
|
-
const fn = () => {
|
|
20
|
-
return db[action](['posts', 'comments'], (t) => ({
|
|
21
|
-
...t.timestamps(),
|
|
22
|
-
}));
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const expectCreateTable = async () => {
|
|
26
|
-
(getPrimaryKeysOfTable as jest.Mock)
|
|
27
|
-
.mockResolvedValueOnce([
|
|
28
|
-
{
|
|
29
|
-
name: 'uuid',
|
|
30
|
-
type: 'uuid',
|
|
31
|
-
},
|
|
32
|
-
])
|
|
33
|
-
.mockResolvedValueOnce([
|
|
34
|
-
{
|
|
35
|
-
name: 'id',
|
|
36
|
-
type: 'integer',
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
name: 'authorName',
|
|
40
|
-
type: 'text',
|
|
41
|
-
},
|
|
42
|
-
]);
|
|
43
|
-
|
|
44
|
-
await fn();
|
|
45
|
-
|
|
46
|
-
expectSql(`
|
|
47
|
-
CREATE TABLE "postsComments" (
|
|
48
|
-
"postUuid" uuid NOT NULL REFERENCES "posts"("uuid"),
|
|
49
|
-
"commentId" integer NOT NULL,
|
|
50
|
-
"commentAuthorName" text NOT NULL,
|
|
51
|
-
"createdAt" timestamp NOT NULL DEFAULT now(),
|
|
52
|
-
"updatedAt" timestamp NOT NULL DEFAULT now(),
|
|
53
|
-
PRIMARY KEY ("postUuid", "commentId", "commentAuthorName"),
|
|
54
|
-
CONSTRAINT "postsComments_commentId_commentAuthorName_fkey" FOREIGN KEY ("commentId", "commentAuthorName") REFERENCES "comments"("id", "authorName")
|
|
55
|
-
)
|
|
56
|
-
`);
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const expectDropTable = async () => {
|
|
60
|
-
await fn();
|
|
61
|
-
|
|
62
|
-
expectSql(`
|
|
63
|
-
DROP TABLE "postsComments"
|
|
64
|
-
`);
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
await (action === 'createJoinTable'
|
|
68
|
-
? expectCreateTable
|
|
69
|
-
: expectDropTable)();
|
|
70
|
-
|
|
71
|
-
db.up = false;
|
|
72
|
-
queryMock.mockClear();
|
|
73
|
-
await (action === 'createJoinTable'
|
|
74
|
-
? expectDropTable
|
|
75
|
-
: expectCreateTable)();
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('should throw error if table has no primary key', async () => {
|
|
79
|
-
db.up = action !== 'dropJoinTable';
|
|
80
|
-
|
|
81
|
-
(getPrimaryKeysOfTable as jest.Mock)
|
|
82
|
-
.mockResolvedValueOnce([
|
|
83
|
-
{
|
|
84
|
-
name: 'id',
|
|
85
|
-
type: 'integer',
|
|
86
|
-
},
|
|
87
|
-
])
|
|
88
|
-
.mockResolvedValueOnce([]);
|
|
89
|
-
|
|
90
|
-
await expect(db[action](['posts', 'comments'])).rejects.toThrow(
|
|
91
|
-
'Primary key for table "comments" is not defined',
|
|
92
|
-
);
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
});
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import { ColumnType, Operators } from 'pqb';
|
|
2
|
-
import { ColumnsShapeCallback, JoinTableOptions, Migration } from './migration';
|
|
3
|
-
import {
|
|
4
|
-
getSchemaAndTableFromName,
|
|
5
|
-
joinWords,
|
|
6
|
-
quoteWithSchema,
|
|
7
|
-
} from '../common';
|
|
8
|
-
import { getPrimaryKeysOfTable } from './migrationUtils';
|
|
9
|
-
import { singular } from 'pluralize';
|
|
10
|
-
import { createTable } from './createTable';
|
|
11
|
-
|
|
12
|
-
class UnknownColumn extends ColumnType {
|
|
13
|
-
operators = Operators.any;
|
|
14
|
-
|
|
15
|
-
constructor(public dataType: string) {
|
|
16
|
-
super();
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
toCode() {
|
|
20
|
-
return 'unknown';
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export const createJoinTable = async (
|
|
25
|
-
migration: Migration,
|
|
26
|
-
up: boolean,
|
|
27
|
-
tables: string[],
|
|
28
|
-
options: JoinTableOptions,
|
|
29
|
-
fn?: ColumnsShapeCallback,
|
|
30
|
-
) => {
|
|
31
|
-
const tableName = options.tableName || joinWords(...tables);
|
|
32
|
-
|
|
33
|
-
if (!up) {
|
|
34
|
-
return createTable(
|
|
35
|
-
migration,
|
|
36
|
-
up,
|
|
37
|
-
tableName,
|
|
38
|
-
{ ...options, noPrimaryKey: true },
|
|
39
|
-
() => ({}),
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const tablesWithPrimaryKeys = await Promise.all(
|
|
44
|
-
tables.map(async (table) => {
|
|
45
|
-
const primaryKeys = await getPrimaryKeysOfTable(migration, table).then(
|
|
46
|
-
(items) =>
|
|
47
|
-
items.map((item) => ({
|
|
48
|
-
...item,
|
|
49
|
-
joinedName: joinWords(singular(table), item.name),
|
|
50
|
-
})),
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
const [schema, name] = getSchemaAndTableFromName(table);
|
|
54
|
-
if (!primaryKeys.length) {
|
|
55
|
-
throw new Error(
|
|
56
|
-
`Primary key for table ${quoteWithSchema({
|
|
57
|
-
schema,
|
|
58
|
-
name,
|
|
59
|
-
})} is not defined`,
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return [schema, table, primaryKeys] as const;
|
|
64
|
-
}),
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
return createTable(migration, up, tableName, options, (t) => {
|
|
68
|
-
const result: Record<string, ColumnType> = {};
|
|
69
|
-
|
|
70
|
-
tablesWithPrimaryKeys.forEach(([schema, table, primaryKeys]) => {
|
|
71
|
-
if (primaryKeys.length === 1) {
|
|
72
|
-
const [{ type, joinedName, name }] = primaryKeys;
|
|
73
|
-
|
|
74
|
-
const column = new UnknownColumn(type);
|
|
75
|
-
|
|
76
|
-
result[joinedName] = column.foreignKey(
|
|
77
|
-
schema ? `${schema}.${table}` : table,
|
|
78
|
-
name,
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
primaryKeys.forEach(({ joinedName, type }) => {
|
|
85
|
-
result[joinedName] = new UnknownColumn(type);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
t.foreignKey(
|
|
89
|
-
primaryKeys.map((key) => key.joinedName) as [string, ...string[]],
|
|
90
|
-
table,
|
|
91
|
-
primaryKeys.map((key) => key.name) as [string, ...string[]],
|
|
92
|
-
);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
if (fn) {
|
|
96
|
-
Object.assign(result, fn(t));
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
t.primaryKey(
|
|
100
|
-
tablesWithPrimaryKeys.flatMap(([, , primaryKeys]) =>
|
|
101
|
-
primaryKeys.map((item) => item.joinedName),
|
|
102
|
-
),
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
return result;
|
|
106
|
-
});
|
|
107
|
-
};
|