rake-db 2.1.2 → 2.1.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.
@@ -7,16 +7,15 @@ const db = getDb();
7
7
  beforeEach(resetDb);
8
8
 
9
9
  it(`should ${action} with comment`, async () => {
10
- await db[action](
11
- 'name',
12
- { comment: 'this is a table comment' },
13
- () => ({}),
14
- );
10
+ await db[action]('name', { comment: 'this is a table comment' }, (t) => ({
11
+ id: t.serial().primaryKey(),
12
+ }));
15
13
 
16
14
  if (action === 'createTable') {
17
15
  expectSql([
18
16
  `
19
17
  CREATE TABLE "name" (
18
+ "id" serial PRIMARY KEY
20
19
  )
21
20
  `,
22
21
  `COMMENT ON TABLE "name" IS 'this is a table comment'`,
@@ -170,7 +169,7 @@ const db = getDb();
170
169
 
171
170
  it('should support composite index', async () => {
172
171
  await db[action]('table', (t) => ({
173
- id: t.integer(),
172
+ id: t.serial().primaryKey(),
174
173
  name: t.text(),
175
174
  ...t.index(['id', { column: 'name', order: 'DESC' }], {
176
175
  name: 'compositeIndexOnTable',
@@ -181,7 +180,7 @@ const db = getDb();
181
180
  expectSql([
182
181
  `
183
182
  CREATE TABLE "table" (
184
- "id" integer NOT NULL,
183
+ "id" serial PRIMARY KEY,
185
184
  "name" text NOT NULL
186
185
  )
187
186
  `,
@@ -198,7 +197,7 @@ const db = getDb();
198
197
 
199
198
  it('should support composite unique index', async () => {
200
199
  await db[action]('table', (t) => ({
201
- id: t.integer(),
200
+ id: t.serial().primaryKey(),
202
201
  name: t.text(),
203
202
  ...t.unique(['id', { column: 'name', order: 'DESC' }], {
204
203
  name: 'compositeIndexOnTable',
@@ -209,7 +208,7 @@ const db = getDb();
209
208
  expectSql([
210
209
  `
211
210
  CREATE TABLE "table" (
212
- "id" integer NOT NULL,
211
+ "id" serial PRIMARY KEY,
213
212
  "name" text NOT NULL
214
213
  )
215
214
  `,
@@ -226,7 +225,7 @@ const db = getDb();
226
225
 
227
226
  it('should support composite foreign key', async () => {
228
227
  await db[action]('table', (t) => ({
229
- id: t.integer(),
228
+ id: t.serial().primaryKey(),
230
229
  name: t.text(),
231
230
  ...t.foreignKey(
232
231
  ['id', 'name'],
@@ -253,7 +252,7 @@ const db = getDb();
253
252
 
254
253
  expectSql(`
255
254
  CREATE TABLE "table" (
256
- "id" integer NOT NULL,
255
+ "id" serial PRIMARY KEY,
257
256
  "name" text NOT NULL,
258
257
  ${expectedConstraint}
259
258
  )
@@ -264,5 +263,50 @@ const db = getDb();
264
263
  `);
265
264
  }
266
265
  });
266
+
267
+ describe('noPrimaryKey', () => {
268
+ const { warn } = console;
269
+ afterAll(() => {
270
+ db.options.noPrimaryKey = undefined;
271
+ console.warn = warn;
272
+ });
273
+
274
+ it('should throw by default when no primary key', async () => {
275
+ await expect(() => db[action]('table', () => ({}))).rejects.toThrow(
276
+ 'Table table has no primary key',
277
+ );
278
+ });
279
+
280
+ it('should throw when no primary key and noPrimaryKey is set to `error`', async () => {
281
+ db.options.noPrimaryKey = 'error';
282
+
283
+ await expect(() => db[action]('table', () => ({}))).rejects.toThrow(
284
+ 'Table table has no primary key',
285
+ );
286
+ });
287
+
288
+ it('should warn when no primary key and noPrimaryKey is set to `warning`', async () => {
289
+ console.warn = jest.fn();
290
+ db.options.noPrimaryKey = 'warning';
291
+
292
+ db[action]('table', () => ({}));
293
+
294
+ expect(console.warn).toBeCalledWith('Table table has no primary key');
295
+ });
296
+
297
+ it('should not throw when no primary key and noPrimaryKey is set to `ignore`', async () => {
298
+ db.options.noPrimaryKey = 'ignore';
299
+
300
+ expect(() => db[action]('table', () => ({}))).not.toThrow();
301
+ });
302
+
303
+ it(`should not throw if option is set to \`true\` as a ${action} option`, async () => {
304
+ db.options.noPrimaryKey = 'error';
305
+
306
+ expect(() =>
307
+ db[action]('table', { noPrimaryKey: true }, () => ({})),
308
+ ).not.toThrow();
309
+ });
310
+ });
267
311
  });
268
312
  });
@@ -120,6 +120,29 @@ export const createTable = async (
120
120
  fn: ColumnsShapeCallback,
121
121
  ) => {
122
122
  const shape = getColumnTypes(types, fn);
123
+ const tableData = getTableData();
124
+
125
+ const { noPrimaryKey } = migration.options;
126
+ if (!options.noPrimaryKey && (!noPrimaryKey || noPrimaryKey !== 'ignore')) {
127
+ let hasPrimaryKey = !!tableData.primaryKey?.columns?.length;
128
+ if (!hasPrimaryKey) {
129
+ for (const key in shape) {
130
+ if (shape[key].isPrimaryKey) {
131
+ hasPrimaryKey = true;
132
+ break;
133
+ }
134
+ }
135
+ }
136
+
137
+ if (!hasPrimaryKey) {
138
+ const message = `Table ${tableName} has no primary key`;
139
+ if (!noPrimaryKey || noPrimaryKey === 'error') {
140
+ throw new Error(message);
141
+ } else {
142
+ console.warn(message);
143
+ }
144
+ }
145
+ }
123
146
 
124
147
  if (!up) {
125
148
  const { dropMode } = options;
@@ -152,7 +175,6 @@ export const createTable = async (
152
175
  lines.push(`\n ${columnToSql(key, item, state)}`);
153
176
  }
154
177
 
155
- const tableData = getTableData();
156
178
  if (tableData.primaryKey) {
157
179
  lines.push(`\n ${primaryKeyToSql(tableData.primaryKey)}`);
158
180
  }
@@ -10,7 +10,6 @@ import {
10
10
  QueryArraysResult,
11
11
  QueryInput,
12
12
  QueryLogObject,
13
- QueryLogOptions,
14
13
  QueryResult,
15
14
  QueryResultRow,
16
15
  Sql,
@@ -20,11 +19,16 @@ import {
20
19
  } from 'pqb';
21
20
  import { createJoinTable, createTable } from './createTable';
22
21
  import { changeTable, TableChangeData, TableChanger } from './changeTable';
23
- import { quoteTable } from '../common';
22
+ import { MigrationConfig, quoteTable } from '../common';
24
23
 
25
24
  export type DropMode = 'CASCADE' | 'RESTRICT';
26
25
 
27
- export type TableOptions = { dropMode?: DropMode; comment?: string };
26
+ export type TableOptions = {
27
+ dropMode?: DropMode;
28
+ comment?: string;
29
+ noPrimaryKey?: boolean;
30
+ };
31
+
28
32
  export type ColumnsShapeCallback = (
29
33
  t: ColumnTypes & { raw: typeof raw },
30
34
  ) => ColumnsShape;
@@ -56,7 +60,7 @@ export class Migration extends TransactionAdapter {
56
60
  constructor(
57
61
  tx: TransactionAdapter,
58
62
  public up: boolean,
59
- options: QueryLogOptions,
63
+ public options: MigrationConfig,
60
64
  ) {
61
65
  super(tx.pool, tx.client, tx.types);
62
66
  this.log = logParamToLogObject(options.logger || console, options.log);
package/src/test-utils.ts CHANGED
@@ -8,6 +8,9 @@ export const getDb = () => {
8
8
 
9
9
  db = new Migration({} as unknown as TransactionAdapter, true, {
10
10
  log: false,
11
+ migrationsPath: 'migrations-path',
12
+ migrationsTable: 'schemaMigrations',
13
+ requireTs: require,
11
14
  });
12
15
  db.query = queryMock;
13
16
  return db;