rake-db 2.3.17 → 2.3.19

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rake-db",
3
- "version": "2.3.17",
3
+ "version": "2.3.19",
4
4
  "description": "Migrations tool for Postgresql DB",
5
5
  "homepage": "https://orchid-orm.netlify.app/guide/migration-setup-and-overview.html",
6
6
  "repository": {
@@ -63,7 +63,7 @@
63
63
  "typescript": "^4.7.4"
64
64
  },
65
65
  "scripts": {
66
- "db": "ts-node -r tsconfig-paths/register db.ts",
66
+ "db": "ts-node -r tsconfig-paths/register app/dbScript.ts",
67
67
  "test": "jest",
68
68
  "build": "rimraf ./dist/ && rollup -c --rollup.config"
69
69
  }
@@ -34,7 +34,7 @@ const execute = async (
34
34
  const createOrDrop = async (
35
35
  options: AdapterOptions,
36
36
  adminOptions: AdapterOptions,
37
- config: RakeDbConfig,
37
+ config: Pick<RakeDbConfig, 'migrationsTable'>,
38
38
  args: {
39
39
  sql(params: { database: string; user: string }): string;
40
40
  successMessage(params: { database: string }): string;
@@ -12,7 +12,7 @@ export const writeMigrationFile = async (
12
12
  name: string,
13
13
  content: string,
14
14
  ) => {
15
- await mkdir(path.resolve(config.migrationsPath), { recursive: true });
15
+ await mkdir(config.migrationsPath, { recursive: true });
16
16
 
17
17
  const filePath = path.resolve(
18
18
  config.migrationsPath,
@@ -4,6 +4,7 @@ import { getMigrationFiles } from '../common';
4
4
  import { Adapter, noop, TransactionAdapter } from 'pqb';
5
5
  import { change } from '../migration/change';
6
6
  import { asMock } from '../test-utils';
7
+ import * as url from 'url';
7
8
 
8
9
  jest.mock('../common', () => ({
9
10
  ...jest.requireActual('../common'),
@@ -33,10 +34,11 @@ Adapter.prototype.transaction = (cb) => {
33
34
  const transactionQueryMock = jest.fn();
34
35
  TransactionAdapter.prototype.query = transactionQueryMock;
35
36
 
36
- const requireTsMock = jest.fn();
37
+ const importMock = jest.fn();
37
38
  const config = {
38
39
  ...migrationConfigDefaults,
39
- requireTs: requireTsMock,
40
+ basePath: __dirname,
41
+ import: importMock,
40
42
  log: false,
41
43
  logger: {
42
44
  log: jest.fn(),
@@ -64,7 +66,7 @@ getMigratedVersionsArrayMock.mockImplementation(() => ({
64
66
  describe('migrateOrRollback', () => {
65
67
  beforeEach(() => {
66
68
  jest.clearAllMocks();
67
- requireTsMock.mockImplementation(() => undefined);
69
+ importMock.mockImplementation(() => undefined);
68
70
  });
69
71
 
70
72
  describe('migrate', () => {
@@ -73,6 +75,7 @@ describe('migrateOrRollback', () => {
73
75
  migratedVersions = ['1'];
74
76
  const conf = {
75
77
  ...config,
78
+ basePath: __dirname,
76
79
  beforeMigrate: jest.fn(),
77
80
  afterMigrate: jest.fn(),
78
81
  };
@@ -84,8 +87,8 @@ describe('migrateOrRollback', () => {
84
87
  expect(conf.beforeMigrate).toBeCalled();
85
88
  expect(conf.afterMigrate).toBeCalled();
86
89
 
87
- expect(requireTsMock).toBeCalledWith('file2');
88
- expect(requireTsMock).toBeCalledWith('file3');
90
+ expect(importMock).toBeCalledWith(url.pathToFileURL('file2').pathname);
91
+ expect(importMock).toBeCalledWith(url.pathToFileURL('file3').pathname);
89
92
 
90
93
  expect(transactionQueryMock).toBeCalledWith(
91
94
  `INSERT INTO "schemaMigrations" VALUES ('2')`,
@@ -109,7 +112,7 @@ describe('migrateOrRollback', () => {
109
112
 
110
113
  expect(getMigrationFiles).toBeCalledWith(config, true);
111
114
  expect(createSchemaMigrations).toBeCalled();
112
- expect(requireTsMock).not.toBeCalled();
115
+ expect(importMock).not.toBeCalled();
113
116
  expect(transactionQueryMock).not.toBeCalled();
114
117
  expect(config.logger.log).not.toBeCalled();
115
118
  });
@@ -117,7 +120,7 @@ describe('migrateOrRollback', () => {
117
120
  it('should call appCodeUpdater only on the first run', async () => {
118
121
  migrationFiles = [files[0]];
119
122
  migratedVersions = [];
120
- requireTsMock.mockImplementationOnce(createTableCallback);
123
+ importMock.mockImplementationOnce(createTableCallback);
121
124
  const appCodeUpdater = jest.fn();
122
125
 
123
126
  await migrate(
@@ -132,7 +135,7 @@ describe('migrateOrRollback', () => {
132
135
  it('should not call appCodeUpdater when useCodeUpdater is set to false in config', async () => {
133
136
  migrationFiles = [files[0]];
134
137
  migratedVersions = [];
135
- requireTsMock.mockImplementation(createTableCallback);
138
+ importMock.mockImplementation(createTableCallback);
136
139
  const appCodeUpdater = jest.fn();
137
140
 
138
141
  await migrate(
@@ -147,7 +150,7 @@ describe('migrateOrRollback', () => {
147
150
  it('should not call appCodeUpdater when having argument --code false', async () => {
148
151
  migrationFiles = [files[0]];
149
152
  migratedVersions = [];
150
- requireTsMock.mockImplementation(createTableCallback);
153
+ importMock.mockImplementation(createTableCallback);
151
154
  const appCodeUpdater = jest.fn();
152
155
 
153
156
  await migrate(
@@ -162,7 +165,7 @@ describe('migrateOrRollback', () => {
162
165
  it('should call appCodeUpdater when having argument --code', async () => {
163
166
  migrationFiles = [files[0]];
164
167
  migratedVersions = [];
165
- requireTsMock.mockImplementation(createTableCallback);
168
+ importMock.mockImplementation(createTableCallback);
166
169
  const appCodeUpdater = jest.fn();
167
170
 
168
171
  await migrate(
@@ -192,8 +195,8 @@ describe('migrateOrRollback', () => {
192
195
 
193
196
  expect(getMigrationFiles).toBeCalledWith(conf, false);
194
197
 
195
- expect(requireTsMock).toBeCalledTimes(1);
196
- expect(requireTsMock).toBeCalledWith('file2');
198
+ expect(importMock).toBeCalledTimes(1);
199
+ expect(importMock).toBeCalledWith(url.pathToFileURL('file2').pathname);
197
200
 
198
201
  expect(transactionQueryMock).toBeCalledTimes(1);
199
202
  expect(transactionQueryMock).toBeCalledWith(
@@ -214,7 +217,7 @@ describe('migrateOrRollback', () => {
214
217
 
215
218
  expect(getMigrationFiles).toBeCalledWith(config, false);
216
219
  expect(createSchemaMigrations).toBeCalled();
217
- expect(requireTsMock).not.toBeCalled();
220
+ expect(importMock).not.toBeCalled();
218
221
  expect(transactionQueryMock).not.toBeCalled();
219
222
  expect(config.logger.log).not.toBeCalled();
220
223
  });
@@ -23,6 +23,7 @@ import {
23
23
  getCurrentChangeCallback,
24
24
  } from '../migration/change';
25
25
  import { createMigrationInterface } from '../migration/migration';
26
+ import { pathToFileURL } from 'url';
26
27
 
27
28
  const getDb = (adapter: Adapter) => createDb({ adapter });
28
29
 
@@ -123,7 +124,7 @@ const processMigration = async (
123
124
  if (callback) {
124
125
  change(callback);
125
126
  } else {
126
- await config.requireTs(file.path);
127
+ await config.import(pathToFileURL(file.path).pathname);
127
128
  changeCache[file.path] = getCurrentChangeCallback();
128
129
  }
129
130
 
@@ -2,17 +2,17 @@ import {
2
2
  createSchemaMigrations,
3
3
  getDatabaseAndUserFromOptions,
4
4
  getFirstWordAndRest,
5
- getMigrationConfigWithDefaults,
5
+ processRakeDbConfig,
6
6
  getMigrationFiles,
7
7
  getTextAfterTo,
8
8
  joinColumns,
9
9
  joinWords,
10
- migrationConfigDefaults,
11
10
  quoteWithSchema,
12
11
  setAdapterOptions,
13
12
  setAdminCredentialsToOptions,
14
13
  sortAsc,
15
14
  sortDesc,
15
+ migrationConfigDefaults,
16
16
  } from './common';
17
17
  import Enquirer from 'enquirer';
18
18
  import { Adapter } from 'pqb';
@@ -35,17 +35,20 @@ jest.mock('fs/promises', () => ({
35
35
  readdir: jest.fn(),
36
36
  }));
37
37
 
38
+ const config = { ...migrationConfigDefaults, basePath: __dirname };
39
+
38
40
  describe('common', () => {
39
- describe('getMigrationConfigWithDefaults', () => {
41
+ describe('processRakeDbConfig', () => {
40
42
  it('should return config with defaults', () => {
41
- const result = getMigrationConfigWithDefaults({
43
+ const result = processRakeDbConfig({
42
44
  migrationsPath: 'custom-path',
43
45
  });
44
46
 
45
47
  expect(result).toEqual({
46
- migrationsPath: 'custom-path',
48
+ basePath: __dirname,
49
+ migrationsPath: path.resolve(__dirname, 'custom-path'),
47
50
  migrationsTable: 'schemaMigrations',
48
- requireTs: expect.any(Function),
51
+ import: expect.any(Function),
49
52
  log: true,
50
53
  logger: console,
51
54
  useCodeUpdater: true,
@@ -179,7 +182,7 @@ describe('common', () => {
179
182
  it('should create a "schemaMigrations" table', async () => {
180
183
  mockedQuery.mockReturnValueOnce(undefined);
181
184
 
182
- await createSchemaMigrations(db, migrationConfigDefaults);
185
+ await createSchemaMigrations(db, config);
183
186
 
184
187
  expect(mockedQuery.mock.calls).toEqual([
185
188
  [`CREATE TABLE "schemaMigrations" ( version TEXT NOT NULL )`],
@@ -191,7 +194,7 @@ describe('common', () => {
191
194
  it('should inform if table already exists', async () => {
192
195
  mockedQuery.mockRejectedValue({ code: '42P07' });
193
196
 
194
- await createSchemaMigrations(db, migrationConfigDefaults);
197
+ await createSchemaMigrations(db, config);
195
198
 
196
199
  expect(mockedQuery.mock.calls).toEqual([
197
200
  [`CREATE TABLE "schemaMigrations" ( version TEXT NOT NULL )`],
@@ -227,10 +230,10 @@ describe('common', () => {
227
230
  const files = [`${version}_a.ts`, `${version}_b.ts`, `${version}_c.ts`];
228
231
  (readdir as jest.Mock).mockReturnValueOnce(files);
229
232
 
230
- const result = await getMigrationFiles(migrationConfigDefaults, true);
233
+ const result = await getMigrationFiles(config, true);
231
234
  expect(result).toEqual(
232
235
  files.map((file) => ({
233
- path: path.join(migrationConfigDefaults.migrationsPath, file),
236
+ path: path.resolve(config.migrationsPath, file),
234
237
  version,
235
238
  })),
236
239
  );
@@ -239,24 +242,22 @@ describe('common', () => {
239
242
  it('should return empty array on error', async () => {
240
243
  (readdir as jest.Mock).mockRejectedValue(new Error());
241
244
 
242
- const result = await getMigrationFiles(migrationConfigDefaults, true);
245
+ const result = await getMigrationFiles(config, true);
243
246
  expect(result).toEqual([]);
244
247
  });
245
248
 
246
249
  it('should throw if file is not a .ts file', async () => {
247
250
  (readdir as jest.Mock).mockReturnValueOnce(['file.js']);
248
251
 
249
- await expect(
250
- getMigrationFiles(migrationConfigDefaults, true),
251
- ).rejects.toThrow('Only .ts files are supported');
252
+ await expect(getMigrationFiles(config, true)).rejects.toThrow(
253
+ 'Only .ts files are supported',
254
+ );
252
255
  });
253
256
 
254
257
  it('should throw on improper version', async () => {
255
258
  (readdir as jest.Mock).mockReturnValueOnce(['1234567890_file.ts']);
256
259
 
257
- await expect(
258
- getMigrationFiles(migrationConfigDefaults, true),
259
- ).rejects.toThrow(
260
+ await expect(getMigrationFiles(config, true)).rejects.toThrow(
260
261
  'Migration file name should start with 14 digit version',
261
262
  );
262
263
  });
package/src/common.ts CHANGED
@@ -11,10 +11,12 @@ import Enquirer from 'enquirer';
11
11
  import path from 'path';
12
12
  import { readdir } from 'fs/promises';
13
13
  import { RakeDbAst } from './ast';
14
+ import CallSite = NodeJS.CallSite;
14
15
 
15
16
  type Db = DbResult<DefaultColumnTypes>;
16
17
 
17
18
  export type RakeDbConfig = {
19
+ basePath: string;
18
20
  migrationsPath: string;
19
21
  migrationsTable: string;
20
22
  commands: Record<
@@ -25,7 +27,7 @@ export type RakeDbConfig = {
25
27
  args: string[],
26
28
  ) => Promise<void>
27
29
  >;
28
- requireTs(path: string): Promise<void>;
30
+ import(path: string): Promise<void>;
29
31
  noPrimaryKey?: NoPrimaryKeyOption;
30
32
  appCodeUpdater?: AppCodeUpdater;
31
33
  useCodeUpdater?: boolean;
@@ -38,23 +40,56 @@ export type RakeDbConfig = {
38
40
  export type AppCodeUpdater = (params: {
39
41
  ast: RakeDbAst;
40
42
  options: AdapterOptions;
43
+ basePath: string;
41
44
  cache: object;
42
45
  }) => Promise<void>;
43
46
 
44
- export const migrationConfigDefaults: RakeDbConfig = {
45
- migrationsPath: path.resolve('src', 'db', 'migrations'),
47
+ export const migrationConfigDefaults: Omit<RakeDbConfig, 'basePath'> = {
48
+ migrationsPath: path.join('src', 'db', 'migrations'),
46
49
  migrationsTable: 'schemaMigrations',
47
50
  commands: {},
48
- requireTs: (path: string) => import(path),
51
+ import: (path: string) => import(path),
49
52
  log: true,
50
53
  logger: console,
51
54
  useCodeUpdater: true,
52
55
  };
53
56
 
54
- export const getMigrationConfigWithDefaults = (
57
+ export const processRakeDbConfig = (
55
58
  config: Partial<RakeDbConfig>,
56
- ) => {
57
- return { ...migrationConfigDefaults, ...config };
59
+ ): RakeDbConfig => {
60
+ const result = { ...migrationConfigDefaults, ...config };
61
+
62
+ if (!result.basePath) {
63
+ let stack: CallSite[] | undefined;
64
+ Error.prepareStackTrace = (_, s) => (stack = s);
65
+ new Error().stack;
66
+ if (stack) {
67
+ const thisFile = stack[0]?.getFileName();
68
+ for (const item of stack) {
69
+ const file = item.getFileName();
70
+ if (!file || file === thisFile || /\bnode_modules\b/.test(file)) {
71
+ continue;
72
+ }
73
+ result.basePath = path.dirname(file);
74
+ break;
75
+ }
76
+ }
77
+
78
+ if (!result.basePath) {
79
+ throw new Error(
80
+ 'Failed to determine path to db script. Please set basePath option of rakeDb',
81
+ );
82
+ }
83
+ }
84
+
85
+ if (!path.isAbsolute(result.migrationsPath)) {
86
+ result.migrationsPath = path.resolve(
87
+ result.basePath,
88
+ result.migrationsPath,
89
+ );
90
+ }
91
+
92
+ return result as RakeDbConfig;
58
93
  };
59
94
 
60
95
  export const getDatabaseAndUserFromOptions = (
@@ -140,7 +175,7 @@ export const setAdminCredentialsToOptions = async (
140
175
 
141
176
  export const createSchemaMigrations = async (
142
177
  db: Adapter,
143
- config: RakeDbConfig,
178
+ config: Pick<RakeDbConfig, 'migrationsTable'>,
144
179
  ) => {
145
180
  try {
146
181
  await db.query(
@@ -209,7 +244,7 @@ export const getMigrationFiles = async (
209
244
 
210
245
  let files: string[];
211
246
  try {
212
- files = await readdir(path.resolve(migrationsPath));
247
+ files = await readdir(migrationsPath);
213
248
  } catch (_) {
214
249
  return [];
215
250
  }
@@ -460,6 +460,7 @@ export const runCodeUpdater = (migration: MigrationBase, ast: RakeDbAst) => {
460
460
  return migration.options.appCodeUpdater?.({
461
461
  ast,
462
462
  options: migration.adapterOptions,
463
+ basePath: migration.options.basePath,
463
464
  cache: migration.appCodeUpdaterCache,
464
465
  });
465
466
  };
@@ -1,6 +1,6 @@
1
1
  import { DbStructure } from './dbStructure';
2
2
  import { pullDbStructure } from './pull';
3
- import { getMigrationConfigWithDefaults } from '../common';
3
+ import { processRakeDbConfig } from '../common';
4
4
  import { writeMigrationFile } from '../commands/generate';
5
5
 
6
6
  jest.mock('./dbStructure', () => {
@@ -76,7 +76,7 @@ describe('pull', () => {
76
76
  },
77
77
  ];
78
78
 
79
- const config = getMigrationConfigWithDefaults({
79
+ const config = processRakeDbConfig({
80
80
  migrationsPath: 'migrations',
81
81
  });
82
82
 
@@ -5,7 +5,7 @@ import { generate } from './commands/generate';
5
5
  import { pullDbStructure } from './pull/pull';
6
6
 
7
7
  jest.mock('./common', () => ({
8
- getMigrationConfigWithDefaults: (config: unknown) => config,
8
+ processRakeDbConfig: (config: unknown) => config,
9
9
  }));
10
10
 
11
11
  jest.mock('./commands/createOrDrop', () => ({
package/src/rakeDb.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { AdapterOptions, MaybeArray, toArray } from 'pqb';
2
2
  import { createDb, dropDb, resetDb } from './commands/createOrDrop';
3
3
  import { migrate, rollback } from './commands/migrateOrRollback';
4
- import { getMigrationConfigWithDefaults, RakeDbConfig } from './common';
4
+ import { processRakeDbConfig, RakeDbConfig } from './common';
5
5
  import { generate } from './commands/generate';
6
6
  import { pullDbStructure } from './pull/pull';
7
7
 
@@ -10,7 +10,7 @@ export const rakeDb = async (
10
10
  partialConfig: Partial<RakeDbConfig> = {},
11
11
  args: string[] = process.argv.slice(2),
12
12
  ) => {
13
- const config = getMigrationConfigWithDefaults(partialConfig);
13
+ const config = processRakeDbConfig(partialConfig);
14
14
 
15
15
  const command = args[0]?.split(':')[0];
16
16
 
package/src/test-utils.ts CHANGED
@@ -12,11 +12,13 @@ export const getDb = () => {
12
12
  {} as unknown as TransactionAdapter,
13
13
  true,
14
14
  {
15
+ basePath: __dirname,
15
16
  log: false,
16
17
  migrationsPath: 'migrations-path',
17
18
  migrationsTable: 'schemaMigrations',
18
- requireTs: require,
19
+ import: require,
19
20
  appCodeUpdater: appCodeUpdaterMock,
21
+ commands: {},
20
22
  },
21
23
  {},
22
24
  {},
package/tsconfig.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "extends": "../../tsconfig.json",
3
- "include": ["./src", "jest-setup.ts", "db.ts", "./migrations"],
3
+ "include": ["./src", "jest-setup.ts", "app"],
4
4
  "compilerOptions": {
5
5
  "outDir": "./dist",
6
6
  "noEmit": false,