mirror of
https://github.com/knex/knex.git
synced 2025-12-26 06:28:37 +00:00
parent
8a7db0c5a8
commit
369bbd6293
@ -1,3 +1,4 @@
|
||||
*.stub
|
||||
#
|
||||
lib/util/import-file.js
|
||||
lib/util/import-file.js
|
||||
test/jake-util/knexfile-imports
|
||||
22
bin/cli.js
22
bin/cli.js
@ -25,6 +25,9 @@ const { listMigrations } = require('./utils/migrationsLister');
|
||||
async function openKnexfile(configPath) {
|
||||
const importFile = require('../lib/util/import-file'); // require me late!
|
||||
let config = await importFile(configPath);
|
||||
if (config && config.default) {
|
||||
config = config.default;
|
||||
}
|
||||
if (typeof config === 'function') {
|
||||
config = await config();
|
||||
}
|
||||
@ -45,9 +48,22 @@ async function initKnex(env, opts) {
|
||||
// enable esm interop via 'esm' module
|
||||
require = require('esm')(module);
|
||||
// https://github.com/standard-things/esm/issues/868
|
||||
// complete the hack: enabling requiring esm from 'module' type package
|
||||
require.extensions['.js'] = (m, fileName) =>
|
||||
m._compile(require('fs').readFileSync(fileName, 'utf8'), fileName);
|
||||
const ext = require.extensions['.js'];
|
||||
require.extensions['.js'] = (m, fileName) => {
|
||||
try {
|
||||
// default to the original extension
|
||||
// this fails if target file parent is of type='module'
|
||||
return ext(m, fileName);
|
||||
} catch (err) {
|
||||
if (err && err.code === 'ERR_REQUIRE_ESM') {
|
||||
return m._compile(
|
||||
require('fs').readFileSync(fileName, 'utf8'),
|
||||
fileName
|
||||
);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
env.configuration = env.configPath
|
||||
|
||||
403
test/cli/esm-interop.spec.js
Normal file
403
test/cli/esm-interop.spec.js
Normal file
@ -0,0 +1,403 @@
|
||||
'use strict';
|
||||
const assert = require('assert');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const { execCommand } = require('cli-testlab');
|
||||
const sqlite3 = require('sqlite3');
|
||||
const KNEX = path.normalize(__dirname + '/../../bin/cli.js');
|
||||
const NODE_VERSION = Number((/v(\d+)/i.exec(process.version) || [])[1]);
|
||||
const isNode10 = NODE_VERSION === 10;
|
||||
const TEST_BASE = '../test/jake-util';
|
||||
|
||||
const fixture = [
|
||||
/** MIGRATIONS */
|
||||
{
|
||||
title: 'migrates esm modules',
|
||||
testCase: 'knexfile-esm',
|
||||
knexArgs: ['migrate:latest', '--esm'],
|
||||
dropDb: true,
|
||||
expectedOutput: 'Batch 1 run: 1 migrations',
|
||||
expectedSchema: [
|
||||
'knex_migrations',
|
||||
'sqlite_sequence',
|
||||
'knex_migrations_lock',
|
||||
'xyz',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'migrates esm modules from a module',
|
||||
testCase: 'knexfile-esm-module',
|
||||
knexArgs: ['migrate:latest', '--esm'],
|
||||
expectedOutput: 'Batch 1 run: 1 migrations',
|
||||
dropDb: true,
|
||||
expectedSchema: [
|
||||
'knex_migrations',
|
||||
'sqlite_sequence',
|
||||
'knex_migrations_lock',
|
||||
'xyz',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'migrate esm module without --esm flag from a module, throws error',
|
||||
testCase: 'knexfile-esm-module',
|
||||
knexArgs: ['migrate:latest'],
|
||||
dropDb: true,
|
||||
expectedOutput: 'Batch 1 run: 1 migrations',
|
||||
expectedErrorMessage: isNode10
|
||||
? 'Unexpected token export'
|
||||
: 'Must use import to load ES Module',
|
||||
expectedSchema: [],
|
||||
},
|
||||
{
|
||||
title: 'migrates mjs modules',
|
||||
testCase: 'knexfile-mjs',
|
||||
knexfile: 'knexfile.mjs',
|
||||
nodeArgs: [
|
||||
// TODO: document this !
|
||||
isNode10 && '--experimental-modules',
|
||||
isNode10 && '--no-warnings',
|
||||
],
|
||||
knexArgs: [
|
||||
'migrate:latest',
|
||||
// TODO: document this !
|
||||
isNode10 && `--esm`,
|
||||
],
|
||||
dropDb: true,
|
||||
expectedOutput: 'Batch 1 run: 1 migrations',
|
||||
expectedSchema: [
|
||||
'knex_migrations',
|
||||
'sqlite_sequence',
|
||||
'knex_migrations_lock',
|
||||
'xyz',
|
||||
],
|
||||
},
|
||||
/** SEEDS */
|
||||
{
|
||||
title: 'seeds esm files',
|
||||
testCase: 'knexfile-esm',
|
||||
expectedOutput: 'Ran 1 seed files',
|
||||
knexArgs: ['seed:run', '--esm'],
|
||||
dropDb: true,
|
||||
/** before assert */
|
||||
before: async ({ dbPath }) => {
|
||||
const db = new sqlite3.Database(dbPath);
|
||||
await createTable(db, `xyz (name TEXT)`);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'seeds esm files from module',
|
||||
testCase: 'knexfile-esm-module',
|
||||
expectedOutput: 'Ran 1 seed files',
|
||||
knexArgs: ['seed:run', '--esm'],
|
||||
/** before assert */
|
||||
before: async ({ dbPath }) => {
|
||||
const db = new sqlite3.Database(dbPath);
|
||||
await createTable(db, `xyz (name TEXT)`);
|
||||
},
|
||||
dropDb: true,
|
||||
},
|
||||
{
|
||||
title: 'seed throws when runs "esm" files from "module" without --esm flag',
|
||||
testCase: 'knexfile-esm-module',
|
||||
knexArgs: ['seed:run'],
|
||||
expectedErrorMessage: isNode10
|
||||
? 'Unexpected token export'
|
||||
: 'Must use import to load ES Module',
|
||||
dropDb: false,
|
||||
},
|
||||
{
|
||||
title: 'seeds mjs files',
|
||||
testCase: 'knexfile-mjs',
|
||||
knexfile: 'knexfile.mjs',
|
||||
nodeArgs: [
|
||||
// TODO: document this !
|
||||
isNode10 && '--experimental-modules',
|
||||
isNode10 && '--no-warnings',
|
||||
],
|
||||
knexArgs: [
|
||||
'seed:run',
|
||||
// TODO: document this !
|
||||
isNode10 && `--esm`,
|
||||
],
|
||||
expectedOutput: 'Ran 1 seed files',
|
||||
dropDb: true,
|
||||
/** before assert */
|
||||
before: async ({ dbPath }) => {
|
||||
const db = new sqlite3.Database(dbPath);
|
||||
await createTable(db, `xyz (name TEXT)`);
|
||||
},
|
||||
},
|
||||
/** SPECIAL CASES */
|
||||
{
|
||||
title: 'mjs files with mjs top level imports',
|
||||
testCase: 'knexfile-imports',
|
||||
knexfile: 'knexfile.mjs',
|
||||
nodeArgs: [
|
||||
isNode10 && '--experimental-modules',
|
||||
isNode10 && '--no-warnings',
|
||||
],
|
||||
knexArgs: ['migrate:latest', isNode10 && `--esm`],
|
||||
dropDb: true,
|
||||
expectedOutput: 'Batch 1 run: 1 migrations',
|
||||
expectedSchema: [
|
||||
'knex_migrations',
|
||||
'sqlite_sequence',
|
||||
'knex_migrations_lock',
|
||||
'xyz',
|
||||
],
|
||||
},
|
||||
{
|
||||
title:
|
||||
'Directory import is not supported, resolving ES modules imported from knexfile.mjs',
|
||||
testCase: 'knexfile-imports',
|
||||
knexfile: 'knexfile1.mjs',
|
||||
nodeArgs: [
|
||||
isNode10 && '--experimental-modules',
|
||||
isNode10 && '--no-warnings',
|
||||
],
|
||||
knexArgs: ['migrate:latest', isNode10 && `--esm`],
|
||||
expectedErrorMessage: isNode10
|
||||
? 'Error: Cannot find module'
|
||||
: `Error [ERR_UNSUPPORTED_DIR_IMPORT]`,
|
||||
},
|
||||
{
|
||||
title: 'dynamic importing js file from NON module package is not supported',
|
||||
testCase: 'knexfile-imports',
|
||||
knexfile: 'knexfile2.mjs',
|
||||
nodeArgs: [
|
||||
isNode10 && '--experimental-modules',
|
||||
isNode10 && '--no-warnings',
|
||||
],
|
||||
knexArgs: ['migrate:latest', isNode10 && `--esm`],
|
||||
expectedErrorMessage: isNode10
|
||||
? 'Error: Cannot load module from .mjs'
|
||||
: "Unexpected token 'export'",
|
||||
},
|
||||
{
|
||||
title: isNode10
|
||||
? "NODE10 can't static impor js from .mjs"
|
||||
: 'static importing js file from NON module package is not supported',
|
||||
testCase: 'knexfile-imports',
|
||||
knexfile: 'knexfile2.mjs',
|
||||
nodeArgs: [
|
||||
isNode10 && '--experimental-modules',
|
||||
isNode10 && '--no-warnings',
|
||||
],
|
||||
knexArgs: ['migrate:latest', isNode10 && `--esm`],
|
||||
expectedErrorMessage: isNode10
|
||||
? 'Error: Cannot load module from .mjs'
|
||||
: "Unexpected token 'export'",
|
||||
},
|
||||
{
|
||||
//Example: external module.type='module' by url 'packane-name/index.js'
|
||||
title: isNode10
|
||||
? "NODE10 can't dynamically import external ESM module package by URL"
|
||||
: 'can dynamically import external ESM module package by URL',
|
||||
testCase: 'knexfile-imports',
|
||||
knexfile: 'knexfile4.mjs',
|
||||
nodeArgs: [
|
||||
isNode10 && '--experimental-modules',
|
||||
isNode10 && '--no-warnings',
|
||||
],
|
||||
knexArgs: ['migrate:latest', isNode10 && `--esm`],
|
||||
expectedErrorMessage: isNode10 && 'Error: Cannot load module from .mjs',
|
||||
expectedOutput: !isNode10 && 'Batch 1 run: 1 migrations',
|
||||
expectedSchema: !isNode10 && [
|
||||
'knex_migrations',
|
||||
'sqlite_sequence',
|
||||
'knex_migrations_lock',
|
||||
'xyz',
|
||||
],
|
||||
dropDb: true,
|
||||
},
|
||||
{
|
||||
title: isNode10
|
||||
? "NODE10 can't create require"
|
||||
: 'Importing commonjs from a mjs module',
|
||||
testCase: 'knexfile-imports',
|
||||
knexfile: 'knexfile5.mjs',
|
||||
nodeArgs: [
|
||||
isNode10 && '--experimental-modules',
|
||||
isNode10 && '--no-warnings',
|
||||
],
|
||||
knexArgs: ['migrate:latest', isNode10 && `--esm`],
|
||||
expectedErrorMessage:
|
||||
isNode10 && 'TypeError: module.createRequire is not a function',
|
||||
expectedOutput: !isNode10 && 'Batch 1 run: 1 migrations',
|
||||
expectedSchema: !isNode10 && [
|
||||
'knex_migrations',
|
||||
'sqlite_sequence',
|
||||
'knex_migrations_lock',
|
||||
'xyz',
|
||||
],
|
||||
dropDb: true,
|
||||
},
|
||||
{
|
||||
title: 'Importing commonjs from a js ESM module and --esm interop',
|
||||
testCase: 'knexfile-imports',
|
||||
knexfile: 'knexfile6.js',
|
||||
nodeArgs: [
|
||||
isNode10 && '--experimental-modules',
|
||||
isNode10 && '--no-warnings',
|
||||
],
|
||||
knexArgs: ['migrate:latest', `--esm`],
|
||||
expectedOutput: 'Batch 1 run: 1 migrations',
|
||||
expectedSchema: [
|
||||
'knex_migrations',
|
||||
'sqlite_sequence',
|
||||
'knex_migrations_lock',
|
||||
'xyz',
|
||||
],
|
||||
dropDb: true,
|
||||
},
|
||||
{
|
||||
title: 'Importing js ESM from js ESM with --esm interop',
|
||||
testCase: 'knexfile-imports',
|
||||
knexfile: 'knexfile7.js',
|
||||
nodeArgs: [
|
||||
isNode10 && '--experimental-modules',
|
||||
isNode10 && '--no-warnings',
|
||||
],
|
||||
knexArgs: ['migrate:latest', `--esm`],
|
||||
expectedOutput: 'Batch 1 run: 1 migrations',
|
||||
expectedSchema: [
|
||||
'knex_migrations',
|
||||
'sqlite_sequence',
|
||||
'knex_migrations_lock',
|
||||
'xyz',
|
||||
],
|
||||
dropDb: true,
|
||||
},
|
||||
{
|
||||
title: 'Dynamic importing js ESM from js ESM with --esm interop',
|
||||
testCase: 'knexfile-imports',
|
||||
knexfile: 'knexfile8.js',
|
||||
nodeArgs: [
|
||||
isNode10 && '--experimental-modules',
|
||||
isNode10 && '--no-warnings',
|
||||
],
|
||||
knexArgs: ['migrate:latest', `--esm`],
|
||||
expectedOutput: 'Batch 1 run: 1 migrations',
|
||||
expectedSchema: [
|
||||
'knex_migrations',
|
||||
'sqlite_sequence',
|
||||
'knex_migrations_lock',
|
||||
'xyz',
|
||||
],
|
||||
dropDb: true,
|
||||
},
|
||||
{
|
||||
title: 'Static top level cjs import from js ESM with --esm interop',
|
||||
testCase: 'knexfile-imports',
|
||||
knexfile: 'knexfile9.js',
|
||||
nodeArgs: [
|
||||
isNode10 && '--experimental-modules',
|
||||
isNode10 && '--no-warnings',
|
||||
],
|
||||
knexArgs: ['migrate:latest', `--esm`],
|
||||
expectedOutput: 'Batch 1 run: 1 migrations',
|
||||
expectedSchema: [
|
||||
'knex_migrations',
|
||||
'sqlite_sequence',
|
||||
'knex_migrations_lock',
|
||||
'xyz',
|
||||
],
|
||||
dropDb: true,
|
||||
},
|
||||
];
|
||||
|
||||
describe('esm interop and mjs support', () => {
|
||||
before(() => {
|
||||
process.env.KNEX_PATH = '../knex.js';
|
||||
});
|
||||
|
||||
for (const spec of fixture) {
|
||||
it(spec.title, async function () {
|
||||
const {
|
||||
testCase,
|
||||
knexfile = 'knexfile.js',
|
||||
dbName = 'test.sqlite3',
|
||||
nodeArgs = [],
|
||||
knexArgs,
|
||||
expectedOutput,
|
||||
expectedSchema,
|
||||
expectedErrorMessage,
|
||||
before,
|
||||
dropDb = false,
|
||||
} = spec;
|
||||
const cwd = path.resolve(path.dirname(KNEX), TEST_BASE, testCase);
|
||||
const dbPath = path.resolve(cwd, dbName);
|
||||
// ...
|
||||
const cmd = [
|
||||
`node`,
|
||||
...nodeArgs,
|
||||
KNEX,
|
||||
...knexArgs,
|
||||
`--cwd="${cwd}"`,
|
||||
`--knexfile=${path.resolve(cwd, knexfile)}`,
|
||||
`--knexpath=${KNEX}`,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' ');
|
||||
// ...
|
||||
if (dropDb && fs.existsSync(dbPath)) fs.unlinkSync(dbPath);
|
||||
// ...
|
||||
if (before) {
|
||||
await before({
|
||||
...spec,
|
||||
cmd,
|
||||
cwd,
|
||||
testCase,
|
||||
knexfile,
|
||||
dbName,
|
||||
dbPath,
|
||||
nodeArgs,
|
||||
knexArgs,
|
||||
expectedOutput,
|
||||
expectedSchema,
|
||||
expectedErrorMessage,
|
||||
});
|
||||
}
|
||||
// ...
|
||||
await execCommand(cmd, { expectedOutput, expectedErrorMessage });
|
||||
// ...
|
||||
if (expectedSchema) {
|
||||
const db = new sqlite3.Database(dbPath);
|
||||
const result = await getSchema(db);
|
||||
await closeDB(db);
|
||||
// migration performed
|
||||
assert.deepEqual(
|
||||
result.map(({ name }) => name),
|
||||
expectedSchema
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function createTable(db, ddl) {
|
||||
return new Promise((resolve, reject) =>
|
||||
db.exec(`create TABLE if not exists ${ddl};`, (err) => {
|
||||
if (err) reject(err);
|
||||
else resolve();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function getSchema(db) {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.all('SELECT name from SQLITE_MASTER', (err, rows) => {
|
||||
if (err) reject(err);
|
||||
else resolve(rows);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function closeDB(db) {
|
||||
return new Promise((resolve, reject) =>
|
||||
db.close((err) => {
|
||||
if (err) reject(err);
|
||||
else resolve();
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -110,108 +110,4 @@ describe('seed:run', () => {
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('runs "esm" files', async () => {
|
||||
const cwd = path.resolve(__dirname, '../jake-util/knexfile-esm');
|
||||
const { Database } = new require('sqlite3');
|
||||
const db = new Database(path.resolve(cwd, 'test.sqlite3'));
|
||||
await new Promise((resolve, reject) =>
|
||||
db.exec(`create TABLE if not exists xyz (name TEXT);`, (err) => {
|
||||
if (err) reject(err);
|
||||
else resolve();
|
||||
})
|
||||
);
|
||||
await new Promise((resolve) => db.close(() => resolve()));
|
||||
return execCommand(
|
||||
[
|
||||
`node ${KNEX}`,
|
||||
'seed:run',
|
||||
'--esm',
|
||||
`--cwd=${cwd}`,
|
||||
`--knexfile=./knexfile.js`,
|
||||
].join(' '),
|
||||
{
|
||||
expectedOutput: 'Ran 1 seed files',
|
||||
notExpectedOutput: ['first.js', 'second.js'],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('runs "esm" files from "module"', async () => {
|
||||
const cwd = path.resolve(__dirname, '../jake-util/knexfile-esm-module');
|
||||
const { Database } = new require('sqlite3');
|
||||
const db = new Database(path.resolve(cwd, 'test.sqlite3'));
|
||||
await new Promise((resolve, reject) =>
|
||||
db.exec(`create TABLE if not exists xyz (name TEXT);`, (err) => {
|
||||
if (err) reject(err);
|
||||
else resolve();
|
||||
})
|
||||
);
|
||||
await new Promise((resolve) => db.close(() => resolve()));
|
||||
return execCommand(
|
||||
[
|
||||
`node ${KNEX}`,
|
||||
`--cwd=${cwd}`,
|
||||
'--esm',
|
||||
'seed:run',
|
||||
'--knexfile=./knexfile.js',
|
||||
].join(' '),
|
||||
{
|
||||
expectedOutput: 'Ran 1 seed files',
|
||||
notExpectedOutput: ['first.js', 'second.js'],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('throws when runs "esm" files from "module" without --esm flag', () => {
|
||||
const cwd = path.resolve(__dirname, '../jake-util/knexfile-esm-module');
|
||||
const version = Number((/v(\d+)/i.exec(process.version) || [])[1]);
|
||||
return execCommand(
|
||||
[
|
||||
`node ${KNEX}`,
|
||||
` --cwd=${cwd}`,
|
||||
' seed:run',
|
||||
'--knexfile=./knexfile.js',
|
||||
].join(' '),
|
||||
{
|
||||
expectedErrorMessage:
|
||||
version === 10
|
||||
? 'Unexpected token export'
|
||||
: 'Must use import to load ES Module',
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('runs mjs files', async () => {
|
||||
const cwd = path.resolve(__dirname, '../jake-util/knexfile-mjs');
|
||||
const { Database } = new require('sqlite3');
|
||||
const db = new Database(path.resolve(cwd, 'test.sqlite3'));
|
||||
await new Promise((resolve, reject) =>
|
||||
db.exec(`create TABLE if not exists xyz (name TEXT);`, (err) => {
|
||||
if (err) reject(err);
|
||||
else resolve();
|
||||
})
|
||||
);
|
||||
await new Promise((resolve) => db.close(() => resolve()));
|
||||
const version = Number((/v(\d+)/i.exec(process.version) || [])[1]);
|
||||
return execCommand(
|
||||
[
|
||||
`node`,
|
||||
// TODO: document this !
|
||||
version === 10 && '--experimental-modules',
|
||||
version === 10 && '--no-warnings',
|
||||
`${KNEX}`,
|
||||
// TODO: document this !
|
||||
version === 10 && `--esm`,
|
||||
`--cwd=${cwd}`,
|
||||
'seed:run',
|
||||
'--knexfile=./knexfile.mjs',
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' '),
|
||||
{
|
||||
expectedOutput: 'Ran 1 seed files',
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
@ -54,4 +54,5 @@ describe('CLI tests', function () {
|
||||
require('./cli/seed.spec');
|
||||
require('./cli/seed-make.spec');
|
||||
require('./cli/version.spec');
|
||||
require('./cli/esm-interop.spec');
|
||||
});
|
||||
|
||||
@ -6,5 +6,6 @@ const config = {
|
||||
},
|
||||
useNullAsDefault: true,
|
||||
};
|
||||
export default config;
|
||||
/** Named exports: or knex won't find them */
|
||||
export const { client, connection, useNullAsDefault } = config;
|
||||
|
||||
@ -2,5 +2,6 @@
|
||||
"name": "knexfile-esm-module",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"module": "knexfile.js",
|
||||
"license": "MIT"
|
||||
}
|
||||
|
||||
16
test/jake-util/knexfile-esm-package/.eslintrc.json
Normal file
16
test/jake-util/knexfile-esm-package/.eslintrc.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"extends": "../../../.eslintrc.js",
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true
|
||||
},
|
||||
"globals": {
|
||||
"Atomics": "readonly",
|
||||
"SharedArrayBuffer": "readonly"
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {}
|
||||
}
|
||||
8
test/jake-util/knexfile-esm-package/knexfile.js
Normal file
8
test/jake-util/knexfile-esm-package/knexfile.js
Normal file
@ -0,0 +1,8 @@
|
||||
/** @type {import("../../../").Config} */
|
||||
export default {
|
||||
client: 'sqlite3',
|
||||
connection: {
|
||||
filename: './test.sqlite3',
|
||||
},
|
||||
useNullAsDefault: true,
|
||||
};
|
||||
14
test/jake-util/knexfile-esm-package/migrations/one.js
Normal file
14
test/jake-util/knexfile-esm-package/migrations/one.js
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @param {import("../../../../")} knex
|
||||
*/
|
||||
export function up(knex) {
|
||||
return knex.schema.createTable('xyz', (table) => {
|
||||
table.string('name');
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @param {import("../../../../")} knex
|
||||
*/
|
||||
export function down(knex) {
|
||||
return knex.schema.dropTable('xyz');
|
||||
}
|
||||
8
test/jake-util/knexfile-esm-package/package.json
Normal file
8
test/jake-util/knexfile-esm-package/package.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "knexfile-esm-package",
|
||||
"private": true,
|
||||
"version": "0.1.0-1",
|
||||
"main": "knexfile.js",
|
||||
"module": "knexfile.js",
|
||||
"license": "MIT"
|
||||
}
|
||||
6
test/jake-util/knexfile-esm-package/seeds/one.js
Normal file
6
test/jake-util/knexfile-esm-package/seeds/one.js
Normal file
@ -0,0 +1,6 @@
|
||||
/**
|
||||
* @param {import("../../../../")} knex
|
||||
*/
|
||||
export function seed(knex) {
|
||||
return knex('xyz').del();
|
||||
}
|
||||
8
test/jake-util/knexfile-esm/knexfile.cjs.js
Normal file
8
test/jake-util/knexfile-esm/knexfile.cjs.js
Normal file
@ -0,0 +1,8 @@
|
||||
/** @type {import("../../../").Config} */
|
||||
module.exports = {
|
||||
client: 'sqlite3',
|
||||
connection: {
|
||||
filename: './test.sqlite3',
|
||||
},
|
||||
useNullAsDefault: true,
|
||||
};
|
||||
8
test/jake-util/knexfile-esm/knexfile.default.js
Normal file
8
test/jake-util/knexfile-esm/knexfile.default.js
Normal file
@ -0,0 +1,8 @@
|
||||
/** @type {import("../../../").Config} */
|
||||
export default {
|
||||
client: 'sqlite3',
|
||||
connection: {
|
||||
filename: './test.sqlite3',
|
||||
},
|
||||
useNullAsDefault: true,
|
||||
};
|
||||
@ -6,5 +6,5 @@ const config = {
|
||||
},
|
||||
useNullAsDefault: true,
|
||||
};
|
||||
/** Named exports: or knex won't find them */
|
||||
/** Named export */
|
||||
export const { client, connection, useNullAsDefault } = config;
|
||||
|
||||
16
test/jake-util/knexfile-imports/.eslintrc.json
Normal file
16
test/jake-util/knexfile-imports/.eslintrc.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"extends": "../../../.eslintrc.js",
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true
|
||||
},
|
||||
"globals": {
|
||||
"Atomics": "readonly",
|
||||
"SharedArrayBuffer": "readonly"
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {}
|
||||
}
|
||||
14
test/jake-util/knexfile-imports/esm/migrations/one.js
Normal file
14
test/jake-util/knexfile-imports/esm/migrations/one.js
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @param {import("../../../../")} knex
|
||||
*/
|
||||
export function up(knex) {
|
||||
return knex.schema.createTable('xyz', (table) => {
|
||||
table.string('name');
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @param {import("../../../../")} knex
|
||||
*/
|
||||
export function down(knex) {
|
||||
return knex.schema.dropTable('xyz');
|
||||
}
|
||||
6
test/jake-util/knexfile-imports/esm/seeds/one.js
Normal file
6
test/jake-util/knexfile-imports/esm/seeds/one.js
Normal file
@ -0,0 +1,6 @@
|
||||
/**
|
||||
* @param {import("../../../../")} knex
|
||||
*/
|
||||
export function seed(knex) {
|
||||
return knex('xyz').del();
|
||||
}
|
||||
19
test/jake-util/knexfile-imports/knexfile.mjs
Normal file
19
test/jake-util/knexfile-imports/knexfile.mjs
Normal file
@ -0,0 +1,19 @@
|
||||
import config from '../knexfile-mjs/knexfile.mjs'
|
||||
/** Named exports */
|
||||
export const {
|
||||
client,
|
||||
connection,
|
||||
useNullAsDefault,
|
||||
migrations,
|
||||
seeds
|
||||
} = {
|
||||
...config,
|
||||
migrations: {
|
||||
...config.migrations,
|
||||
directory: './mjs/migrations',
|
||||
},
|
||||
seeds: {
|
||||
...config.seeds,
|
||||
directory: './mjs/seeds',
|
||||
}
|
||||
};
|
||||
19
test/jake-util/knexfile-imports/knexfile1.mjs
Normal file
19
test/jake-util/knexfile-imports/knexfile1.mjs
Normal file
@ -0,0 +1,19 @@
|
||||
import config from '../knexfile-esm'
|
||||
/** Named exports */
|
||||
export const {
|
||||
client,
|
||||
connection,
|
||||
useNullAsDefault,
|
||||
migrations,
|
||||
seeds
|
||||
} = {
|
||||
...config,
|
||||
migrations: {
|
||||
...config.migrations,
|
||||
directory: './mjs/migrations',
|
||||
},
|
||||
seeds: {
|
||||
...config.seeds,
|
||||
directory: './mjs/seeds',
|
||||
}
|
||||
};
|
||||
20
test/jake-util/knexfile-imports/knexfile2.mjs
Normal file
20
test/jake-util/knexfile-imports/knexfile2.mjs
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
/**
|
||||
* CASE: 'Unexpected token 'export'
|
||||
* can't import ../knexfile-esm-package/knexfile.js as ESM Module
|
||||
* because package.json is not type 'module'
|
||||
*/
|
||||
export default async () => {
|
||||
const { default: config } = await import('../knexfile-esm-package/knexfile.js');
|
||||
return {
|
||||
...config,
|
||||
migrations: {
|
||||
...config.migrations,
|
||||
directory: './mjs/migrations',
|
||||
},
|
||||
seeds: {
|
||||
...config.seeds,
|
||||
directory: './mjs/seeds',
|
||||
}
|
||||
};
|
||||
}
|
||||
18
test/jake-util/knexfile-imports/knexfile3.mjs
Normal file
18
test/jake-util/knexfile-imports/knexfile3.mjs
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* CASE: 'Unexpected token 'export'
|
||||
* can't import ../knexfile-esm-package/knexfile.js as ESM Module
|
||||
* because package.json is not type 'module'
|
||||
*/
|
||||
import config from '../knexfile-esm-package/knexfile.js'
|
||||
/** */
|
||||
export default {
|
||||
...config,
|
||||
migrations: {
|
||||
...config.migrations,
|
||||
directory: './mjs/migrations',
|
||||
},
|
||||
seeds: {
|
||||
...config.seeds,
|
||||
directory: './mjs/seeds',
|
||||
}
|
||||
}
|
||||
23
test/jake-util/knexfile-imports/knexfile4.mjs
Normal file
23
test/jake-util/knexfile-imports/knexfile4.mjs
Normal file
@ -0,0 +1,23 @@
|
||||
const NODE_VERSION = Number((/v(\d+)/i.exec(process.version) || [])[1]);
|
||||
const isNode10 = NODE_VERSION === 10;
|
||||
/** @returns {Promise<import("../../../").Config>}*/
|
||||
export default async () => {
|
||||
const { default: config } = await import(
|
||||
isNode10
|
||||
? '../knexfile-esm-module/knexfile'
|
||||
: '../knexfile-esm-module/knexfile.js'
|
||||
);
|
||||
return ({
|
||||
...config,
|
||||
migrations: {
|
||||
directory: './mjs/migrations',
|
||||
extension: "mjs",
|
||||
loadExtensions: ['.mjs']
|
||||
},
|
||||
seeds: {
|
||||
directory: './mjs/seeds',
|
||||
extension: "mjs",
|
||||
loadExtensions: ['.mjs']
|
||||
}
|
||||
})
|
||||
}
|
||||
24
test/jake-util/knexfile-imports/knexfile5.mjs
Normal file
24
test/jake-util/knexfile-imports/knexfile5.mjs
Normal file
@ -0,0 +1,24 @@
|
||||
import module from "module";
|
||||
/**
|
||||
* Importing commonjs from a mjs module
|
||||
* @returns {Promise<import("../../../").Config>}
|
||||
* */
|
||||
export default async () => {
|
||||
const require = module.createRequire(
|
||||
import.meta.url
|
||||
)
|
||||
const config = require('../knexfile-esm/knexfile.cjs');
|
||||
return ({
|
||||
...config,
|
||||
migrations: {
|
||||
directory: './mjs/migrations',
|
||||
extension: "mjs",
|
||||
loadExtensions: ['.mjs']
|
||||
},
|
||||
seeds: {
|
||||
directory: './mjs/seeds',
|
||||
extension: "mjs",
|
||||
loadExtensions: ['.mjs']
|
||||
}
|
||||
})
|
||||
}
|
||||
34
test/jake-util/knexfile-imports/knexfile6.js
Normal file
34
test/jake-util/knexfile-imports/knexfile6.js
Normal file
@ -0,0 +1,34 @@
|
||||
import module from 'module';
|
||||
const NODE_VERSION = Number((/v(\d+)/i.exec(process.version) || [])[1]);
|
||||
const isNode10 = NODE_VERSION === 10;
|
||||
/**
|
||||
* Importing commonjs from a js ESM module
|
||||
* @returns {Promise<import("../../../").Config>}
|
||||
* */
|
||||
export default async () => {
|
||||
let config;
|
||||
if (typeof require === 'undefined') {
|
||||
// This shouldn't happen
|
||||
// you could NOT load this knexfile
|
||||
// if you didn't pass the '--esm' flag
|
||||
// unless you are transpiling it
|
||||
if (isNode10) {
|
||||
require = (await import('esm')).default(
|
||||
new module.Module(import.meta.url)
|
||||
);
|
||||
} else {
|
||||
// Node 12 & 14
|
||||
require = module.createRequire(import.meta.url);
|
||||
}
|
||||
}
|
||||
config = require('../knexfile-esm/knexfile.cjs');
|
||||
return {
|
||||
...config,
|
||||
migrations: {
|
||||
directory: './esm/migrations',
|
||||
},
|
||||
seeds: {
|
||||
directory: './esm/seeds',
|
||||
},
|
||||
};
|
||||
};
|
||||
13
test/jake-util/knexfile-imports/knexfile7.js
Normal file
13
test/jake-util/knexfile-imports/knexfile7.js
Normal file
@ -0,0 +1,13 @@
|
||||
import config from '../knexfile-esm/knexfile.default.js';
|
||||
/**
|
||||
* @returns {Promise<import("../../../").Config>}
|
||||
* */
|
||||
export default {
|
||||
...config,
|
||||
migrations: {
|
||||
directory: './esm/migrations',
|
||||
},
|
||||
seeds: {
|
||||
directory: './esm/seeds',
|
||||
},
|
||||
};
|
||||
17
test/jake-util/knexfile-imports/knexfile8.js
Normal file
17
test/jake-util/knexfile-imports/knexfile8.js
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @returns {Promise<import("../../../").Config>}
|
||||
* */
|
||||
export default async () => {
|
||||
const { default: config } = await import(
|
||||
'../knexfile-esm/knexfile.default.js'
|
||||
);
|
||||
return {
|
||||
...config,
|
||||
migrations: {
|
||||
directory: './esm/migrations',
|
||||
},
|
||||
seeds: {
|
||||
directory: './esm/seeds',
|
||||
},
|
||||
};
|
||||
};
|
||||
15
test/jake-util/knexfile-imports/knexfile9.js
Normal file
15
test/jake-util/knexfile-imports/knexfile9.js
Normal file
@ -0,0 +1,15 @@
|
||||
import config from '../knexfile-esm/knexfile.cjs';
|
||||
/**
|
||||
* Static 'cjs' import from js ESM with --esm interop
|
||||
* @returns {import("../../../").Config}
|
||||
* NOTE: this is NOT supported by NODE
|
||||
* */
|
||||
export default {
|
||||
...config,
|
||||
migrations: {
|
||||
directory: './esm/migrations',
|
||||
},
|
||||
seeds: {
|
||||
directory: './esm/seeds',
|
||||
},
|
||||
};
|
||||
14
test/jake-util/knexfile-imports/mjs/migrations/one.mjs
Normal file
14
test/jake-util/knexfile-imports/mjs/migrations/one.mjs
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @param {import("../../../../")} knex
|
||||
*/
|
||||
export function up(knex) {
|
||||
return knex.schema.createTable('xyz', (table) => {
|
||||
table.string('name');
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @param {import("../../../../")} knex
|
||||
*/
|
||||
export function down(knex) {
|
||||
return knex.schema.dropTable('xyz');
|
||||
}
|
||||
7
test/jake-util/knexfile-imports/mjs/seeds/one.mjs
Normal file
7
test/jake-util/knexfile-imports/mjs/seeds/one.mjs
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* @param {import("../../../../")} knex
|
||||
*/
|
||||
export function seed(knex) {
|
||||
return knex('xyz').del();
|
||||
}
|
||||
|
||||
@ -14,5 +14,7 @@ const config = {
|
||||
loadExtensions: ['.mjs']
|
||||
}
|
||||
};
|
||||
/** ignored by knex */
|
||||
export default config;
|
||||
/** Named exports: or knex won't find them */
|
||||
export const { client, connection, useNullAsDefault, migrations , seeds } = config;
|
||||
export const { client, connection, useNullAsDefault, migrations , seeds } = config;
|
||||
@ -703,144 +703,6 @@ test('migrate:list prints migrations both completed and pending', async (temp) =
|
||||
);
|
||||
});
|
||||
|
||||
test('migrate runs "esm" modules', async (temp) => {
|
||||
const cwd = path.resolve(
|
||||
path.dirname(KNEX),
|
||||
'../test/jake-util/knexfile-esm'
|
||||
);
|
||||
const dbPath = path.resolve(cwd, 'test.sqlite3');
|
||||
if (fs.existsSync(dbPath)) fs.unlinkSync(dbPath);
|
||||
const { stdout } = await assertExec(
|
||||
[
|
||||
`node ${KNEX}`,
|
||||
'migrate:latest',
|
||||
'--esm',
|
||||
`--cwd="${cwd}"`,
|
||||
`--knexfile=${path.resolve(cwd, 'knexfile.js')}`,
|
||||
`--knexpath=${KNEX}`,
|
||||
].join(' ')
|
||||
);
|
||||
assert.include(stdout, 'Batch 1 run: 1 migrations');
|
||||
const db = new sqlite3.Database(dbPath);
|
||||
const result = await new Promise((resolve, reject) => {
|
||||
db.all('SELECT name from SQLITE_MASTER', (err, rows) => {
|
||||
if (err) reject(err);
|
||||
else resolve(rows.map(({ name }) => name));
|
||||
});
|
||||
});
|
||||
await new Promise((resolve) => db.close(resolve));
|
||||
// migration performed
|
||||
assert.deepEqual(result, [
|
||||
'knex_migrations',
|
||||
'sqlite_sequence',
|
||||
'knex_migrations_lock',
|
||||
'xyz',
|
||||
]);
|
||||
});
|
||||
|
||||
test('migrate runs "esm" modules from a "module"', async (temp) => {
|
||||
const cwd = path.resolve(
|
||||
path.dirname(KNEX),
|
||||
'../test/jake-util/knexfile-esm-module'
|
||||
);
|
||||
const dbPath = path.resolve(cwd, 'test.sqlite3');
|
||||
if (fs.existsSync(dbPath)) fs.unlinkSync(dbPath);
|
||||
const { stdout } = await assertExec(
|
||||
[
|
||||
`node ${KNEX}`,
|
||||
'--esm',
|
||||
`--cwd=${cwd}`,
|
||||
`--knexfile=${path.resolve(cwd, 'knexfile.js')}`,
|
||||
`--knexpath=${KNEX}`,
|
||||
'migrate:latest',
|
||||
].join(' ')
|
||||
);
|
||||
assert.include(stdout, 'Batch 1 run: 1 migrations');
|
||||
const db = new sqlite3.Database(dbPath);
|
||||
const result = await new Promise((resolve, reject) => {
|
||||
db.all('SELECT name from SQLITE_MASTER', (err, rows) => {
|
||||
if (err) reject(err);
|
||||
else resolve(rows.map(({ name }) => name));
|
||||
});
|
||||
});
|
||||
await new Promise((resolve) => db.close(resolve));
|
||||
// migration performed
|
||||
assert.deepEqual(result, [
|
||||
'knex_migrations',
|
||||
'sqlite_sequence',
|
||||
'knex_migrations_lock',
|
||||
'xyz',
|
||||
]);
|
||||
});
|
||||
|
||||
test('migrate "esm" module without --esm flag from a "module", throws error', async (temp) => {
|
||||
const cwd = path.resolve(
|
||||
path.dirname(KNEX),
|
||||
'../test/jake-util/knexfile-esm-module'
|
||||
);
|
||||
const stderr = await assertExecError(
|
||||
[
|
||||
`node ${KNEX}`,
|
||||
`--cwd=${cwd}`,
|
||||
`--knexfile=${path.resolve(cwd, 'knexfile.js')}`,
|
||||
`--knexpath=${KNEX}`,
|
||||
'migrate:latest',
|
||||
].join(' ')
|
||||
);
|
||||
const version = Number((/v(\d+)/i.exec(process.version) || [])[1]);
|
||||
assert.include(
|
||||
stderr,
|
||||
version === 10
|
||||
? 'Unexpected token export'
|
||||
: 'Must use import to load ES Module'
|
||||
);
|
||||
});
|
||||
|
||||
test('migrate runs "mjs" modules', async (temp) => {
|
||||
const cwd = path.resolve(
|
||||
path.dirname(KNEX),
|
||||
'../test/jake-util/knexfile-mjs'
|
||||
);
|
||||
const dbPath = path.resolve(cwd, 'test.sqlite3');
|
||||
if (fs.existsSync(dbPath)) fs.unlinkSync(dbPath);
|
||||
|
||||
const version = Number((/v(\d+)/i.exec(process.version) || [])[1]);
|
||||
|
||||
const { stdout } = await assertExec(
|
||||
[
|
||||
`node`,
|
||||
// TODO: document this !
|
||||
version === 10 && '--experimental-modules',
|
||||
version === 10 && '--no-warnings',
|
||||
`${KNEX}`,
|
||||
// TODO: document this !
|
||||
version === 10 && `--esm`,
|
||||
`--cwd=${cwd}`,
|
||||
`--knexfile=${path.resolve(cwd, 'knexfile.mjs')}`,
|
||||
`--knexpath=${KNEX}`,
|
||||
'migrate:latest',
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' ')
|
||||
);
|
||||
assert.include(stdout, 'Batch 1 run: 1 migrations');
|
||||
const db = new sqlite3.Database(dbPath);
|
||||
const result = await new Promise((resolve, reject) => {
|
||||
db.all('SELECT name from SQLITE_MASTER', (err, rows) => {
|
||||
if (err) reject(err);
|
||||
else resolve(rows.map(({ name }) => name));
|
||||
});
|
||||
});
|
||||
await new Promise((resolve) => db.close(resolve));
|
||||
// migration performed
|
||||
assert.deepEqual(result, [
|
||||
'knex_migrations',
|
||||
'sqlite_sequence',
|
||||
'knex_migrations_lock',
|
||||
'xyz',
|
||||
]);
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
taskList,
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user