node-pg-migrate
Advanced tools
Comparing version 7.7.0-rc.0 to 7.7.0
@@ -55,2 +55,3 @@ #!/usr/bin/env node | ||
const migrationsDirArg = "migrations-dir"; | ||
const useGlobArg = "use-glob"; | ||
const migrationsTableArg = "migrations-table"; | ||
@@ -88,5 +89,10 @@ const migrationsSchemaArg = "migrations-schema"; | ||
defaultDescription: '"migrations"', | ||
describe: "The directory containing your migration files", | ||
describe: `The directory name or glob pattern containing your migration files (resolved from cwd()). When using glob pattern, "${useGlobArg}" must be used as well`, | ||
type: "string" | ||
}, | ||
[useGlobArg]: { | ||
defaultDescription: "false", | ||
describe: `Use glob to find migration files. This will use "${migrationsDirArg}" _and_ "${ignorePatternArg}" to glob-search for migration files.`, | ||
type: "boolean" | ||
}, | ||
[migrationsTableArg]: { | ||
@@ -132,3 +138,3 @@ alias: "t", | ||
defaultDescription: '"\\..*"', | ||
describe: "Regex pattern for file names to ignore", | ||
describe: `Regex or glob pattern for migration files to be ignored. When using glob pattern, "${useGlobArg}" must be used as well`, | ||
type: "string" | ||
@@ -239,2 +245,3 @@ }, | ||
let MIGRATIONS_DIR = argv[migrationsDirArg]; | ||
let USE_GLOB = argv[useGlobArg]; | ||
let DB_CONNECTION = process.env[argv[databaseUrlVarArg]]; | ||
@@ -413,2 +420,3 @@ let IGNORE_PATTERN = argv[ignorePatternArg]; | ||
MIGRATIONS_DIR ??= (0, import_node_path.join)((0, import_node_process.cwd)(), "migrations"); | ||
USE_GLOB ??= false; | ||
MIGRATIONS_FILE_LANGUAGE ??= "js"; | ||
@@ -418,3 +426,2 @@ MIGRATIONS_FILENAME_FORMAT ??= "timestamp"; | ||
SCHEMA ??= ["public"]; | ||
IGNORE_PATTERN ??= "\\..*"; | ||
CHECK_ORDER ??= true; | ||
@@ -498,2 +505,3 @@ VERBOSE ??= true; | ||
dir: MIGRATIONS_DIR, | ||
useGlob: USE_GLOB, | ||
ignorePattern: IGNORE_PATTERN, | ||
@@ -500,0 +508,0 @@ schema: SCHEMA, |
@@ -51,2 +51,3 @@ #!/usr/bin/env node | ||
const migrationsDirArg = 'migrations-dir'; | ||
const useGlobArg = 'use-glob'; | ||
const migrationsTableArg = 'migrations-table'; | ||
@@ -88,5 +89,10 @@ const migrationsSchemaArg = 'migrations-schema'; | ||
defaultDescription: '"migrations"', | ||
describe: 'The directory containing your migration files', | ||
describe: `The directory name or glob pattern containing your migration files (resolved from cwd()). When using glob pattern, "${useGlobArg}" must be used as well`, | ||
type: 'string', | ||
}, | ||
[useGlobArg]: { | ||
defaultDescription: 'false', | ||
describe: `Use glob to find migration files. This will use "${migrationsDirArg}" _and_ "${ignorePatternArg}" to glob-search for migration files.`, | ||
type: 'boolean', | ||
}, | ||
[migrationsTableArg]: { | ||
@@ -133,3 +139,3 @@ alias: 't', | ||
defaultDescription: '"\\..*"', | ||
describe: 'Regex pattern for file names to ignore', | ||
describe: `Regex or glob pattern for migration files to be ignored. When using glob pattern, "${useGlobArg}" must be used as well`, | ||
type: 'string', | ||
@@ -259,2 +265,3 @@ }, | ||
let MIGRATIONS_DIR = argv[migrationsDirArg]; | ||
let USE_GLOB = argv[useGlobArg]; | ||
let DB_CONNECTION: string | ConnectionParameters | ClientConfig | undefined = | ||
@@ -476,2 +483,3 @@ process.env[argv[databaseUrlVarArg]]; | ||
MIGRATIONS_DIR ??= join(cwd(), 'migrations'); | ||
USE_GLOB ??= false; | ||
MIGRATIONS_FILE_LANGUAGE ??= 'js'; | ||
@@ -481,3 +489,2 @@ MIGRATIONS_FILENAME_FORMAT ??= 'timestamp'; | ||
SCHEMA ??= ['public']; | ||
IGNORE_PATTERN ??= '\\..*'; | ||
CHECK_ORDER ??= true; | ||
@@ -592,2 +599,3 @@ VERBOSE ??= true; | ||
dir: MIGRATIONS_DIR!, | ||
useGlob: USE_GLOB, | ||
ignorePattern: IGNORE_PATTERN, | ||
@@ -594,0 +602,0 @@ schema: SCHEMA, |
@@ -25,4 +25,53 @@ import type { QueryResult } from 'pg'; | ||
} & (CreateOptionsTemplate | CreateOptionsDefault); | ||
export declare function loadMigrationFiles(dir: string, ignorePattern?: string): Promise<string[]>; | ||
export declare function getTimestamp(logger: Logger, filename: string): number; | ||
interface LoadMigrationFilesOptions { | ||
/** | ||
* Regex pattern for file names to ignore (ignores files starting with `.` by default). | ||
* Alternatively, provide a [glob](https://www.npmjs.com/package/glob) pattern or | ||
* an array of glob patterns and set `isGlob = true` | ||
* | ||
* Note: enabling glob will read both, `dir` _and_ `ignorePattern` as glob patterns | ||
*/ | ||
ignorePattern?: string | string[]; | ||
/** | ||
* Use [glob](https://www.npmjs.com/package/glob) to find migration files. | ||
* This will use `dir` _and_ `options.ignorePattern` to glob-search for migration files. | ||
* | ||
* @default: false | ||
*/ | ||
useGlob?: boolean; | ||
/** | ||
* Redirect messages to this logger object, rather than `console`. | ||
*/ | ||
logger?: Logger; | ||
} | ||
/** | ||
* Reads files from `dir`, sorts them and returns an array of their absolute paths. | ||
* When not using globs, files are sorted by their numeric prefix values first. 17 digit numbers are interpreted as utc date and converted to the number representation of that date. | ||
* Glob matches are sorted via String.localeCompare with ignored punctuation. | ||
* | ||
* @param dir The directory containing your migration files. This path is resolved from `cwd()`. | ||
* Alternatively, provide a [glob](https://www.npmjs.com/package/glob) pattern or | ||
* an array of glob patterns and set `options.useGlob = true` | ||
* | ||
* Note: enabling glob will read both, `dir` _and_ `options.ignorePattern` as glob patterns | ||
* @param options | ||
* @returns Array of absolute paths | ||
*/ | ||
export declare function getMigrationFilePaths( | ||
/** | ||
* The directory containing your migration files. This path is resolved from `cwd()`. | ||
* Alternatively, provide a [glob](https://www.npmjs.com/package/glob) pattern or | ||
* an array of glob patterns and set `options.useGlob = true` | ||
* | ||
* Note: enabling glob will read both, `dir` _and_ `options.ignorePattern` as glob patterns | ||
*/ | ||
dir: string | string[], options?: LoadMigrationFilesOptions): Promise<string[]>; | ||
/** | ||
* extracts numeric value from everything in `filename` before `SEPARATOR`. | ||
* 17 digit numbers are interpreted as utc date and converted to the number representation of that date. | ||
* @param filename filename to extract the prefix from | ||
* @param logger Redirect messages to this logger object, rather than `console`. | ||
* @returns numeric value of the filename prefix (everything before `SEPARATOR`). | ||
*/ | ||
export declare function getNumericPrefix(filename: string, logger?: Logger): number; | ||
export declare class Migration implements RunMigration { | ||
@@ -46,1 +95,2 @@ static create(name: string, directory: string, options?: CreateOptions): Promise<string>; | ||
} | ||
export {}; |
@@ -35,6 +35,7 @@ "use strict"; | ||
Migration: () => Migration, | ||
getTimestamp: () => getTimestamp, | ||
loadMigrationFiles: () => loadMigrationFiles | ||
getMigrationFilePaths: () => getMigrationFilePaths, | ||
getNumericPrefix: () => getNumericPrefix | ||
}); | ||
module.exports = __toCommonJS(migration_exports); | ||
var import_glob = require("glob"); | ||
var import_node_fs = require("node:fs"); | ||
@@ -52,7 +53,35 @@ var import_promises = require("node:fs/promises"); | ||
const SEPARATOR = "_"; | ||
async function loadMigrationFiles(dir, ignorePattern) { | ||
function localeCompareStringsNumerically(a, b) { | ||
return a.localeCompare(b, void 0, { | ||
usage: "sort", | ||
numeric: true, | ||
sensitivity: "variant", | ||
ignorePunctuation: true | ||
}); | ||
} | ||
function compareFileNamesByTimestamp(a, b, logger) { | ||
const aTimestamp = getNumericPrefix(a, logger); | ||
const bTimestamp = getNumericPrefix(b, logger); | ||
return aTimestamp - bTimestamp; | ||
} | ||
async function getMigrationFilePaths(dir, options = {}) { | ||
const { ignorePattern, useGlob = false, logger } = options; | ||
if (useGlob) { | ||
const globMatches = await (0, import_glob.glob)(dir, { ignore: ignorePattern, nodir: true }); | ||
return globMatches.sort(localeCompareStringsNumerically); | ||
} | ||
if (Array.isArray(dir) || Array.isArray(ignorePattern)) { | ||
throw new TypeError( | ||
'Options "dir" and "ignorePattern" can only be arrays when "useGlob" is true' | ||
); | ||
} | ||
const ignoreRegexp = new RegExp( | ||
(ignorePattern == null ? void 0 : ignorePattern.length) ? `^${ignorePattern}$` : "^\\..*" | ||
); | ||
const dirContent = await (0, import_promises.readdir)(`${dir}/`, { withFileTypes: true }); | ||
const files = dirContent.map((file) => file.isFile() || file.isSymbolicLink() ? file.name : null).filter((file) => Boolean(file)).sort(); | ||
const filter = new RegExp(`^(${ignorePattern})$`); | ||
return ignorePattern === void 0 ? files : files.filter((i) => !filter.test(i)); | ||
return dirContent.filter( | ||
(dirent) => (dirent.isFile() || dirent.isSymbolicLink()) && !ignoreRegexp.test(dirent.name) | ||
).sort( | ||
(a, b) => compareFileNamesByTimestamp(a.name, b.name, logger) || localeCompareStringsNumerically(a.name, b.name) | ||
).map((dirent) => (0, import_node_path.resolve)(dir, dirent.name)); | ||
} | ||
@@ -64,3 +93,3 @@ function getSuffixFromFileName(fileName) { | ||
try { | ||
const files = await loadMigrationFiles(dir, ignorePattern); | ||
const files = await getMigrationFilePaths(dir, { ignorePattern }); | ||
return files.length > 0 ? getSuffixFromFileName(files[files.length - 1]) : void 0; | ||
@@ -71,3 +100,3 @@ } catch { | ||
} | ||
function getTimestamp(logger, filename) { | ||
function getNumericPrefix(filename, logger = console) { | ||
const prefix = filename.split(SEPARATOR)[0]; | ||
@@ -112,3 +141,3 @@ if (prefix && /^\d+$/.test(prefix)) { | ||
this.name = (0, import_node_path.basename)(migrationPath, (0, import_node_path.extname)(migrationPath)); | ||
this.timestamp = getTimestamp(logger, this.name); | ||
this.timestamp = getNumericPrefix(this.name, logger); | ||
this.up = up; | ||
@@ -225,4 +254,4 @@ this.down = down; | ||
Migration, | ||
getTimestamp, | ||
loadMigrationFiles | ||
getMigrationFilePaths, | ||
getNumericPrefix | ||
}); |
@@ -48,6 +48,9 @@ "use strict"; | ||
let shorthands = {}; | ||
const files = await (0, import_migration.loadMigrationFiles)(options.dir, options.ignorePattern); | ||
const absoluteFilePaths = await (0, import_migration.getMigrationFilePaths)(options.dir, { | ||
ignorePattern: options.ignorePattern, | ||
useGlob: options.useGlob, | ||
logger | ||
}); | ||
const migrations = await Promise.all( | ||
files.map(async (file) => { | ||
const filePath = (0, import_node_path.resolve)(options.dir, file); | ||
absoluteFilePaths.map(async (filePath) => { | ||
const actions = (0, import_node_path.extname)(filePath) === ".sql" ? await (0, import_sqlMigration.default)(filePath) : (0, import_node_module.createRequire)((0, import_node_path.resolve)("_"))(filePath); | ||
@@ -67,9 +70,3 @@ shorthands = { ...shorthands, ...actions.shorthands }; | ||
); | ||
return migrations.sort((m1, m2) => { | ||
const compare = m1.timestamp - m2.timestamp; | ||
if (compare !== 0) { | ||
return compare; | ||
} | ||
return m1.name.localeCompare(m2.name); | ||
}); | ||
return migrations; | ||
} catch (error) { | ||
@@ -76,0 +73,0 @@ throw new Error(`Can't get migration files: ${error.stack}`); |
@@ -694,6 +694,19 @@ import type { ClientBase, ClientConfig, QueryArrayConfig, QueryArrayResult, QueryConfig, QueryResult } from 'pg'; | ||
/** | ||
* The directory containing your migration files. | ||
* The directory containing your migration files. This path is resolved from `cwd()`. | ||
* Alternatively, provide a [glob](https://www.npmjs.com/package/glob) pattern or | ||
* an array of glob patterns and set `useGlob = true` | ||
* | ||
* Note: enabling glob will read both, `dir` _and_ `ignorePattern` as glob patterns | ||
*/ | ||
dir: string; | ||
dir: string | string[]; | ||
/** | ||
* Use [glob](https://www.npmjs.com/package/glob) to find migration files. | ||
* This will use `dir` _and_ `ignorePattern` to glob-search for migration files. | ||
* | ||
* Note: enabling glob will read both, `dir` _and_ `ignorePattern` as glob patterns | ||
* | ||
* @default false | ||
*/ | ||
useGlob?: boolean; | ||
/** | ||
* Check order of migrations before running them. | ||
@@ -716,4 +729,8 @@ */ | ||
* Regex pattern for file names to ignore (ignores files starting with `.` by default). | ||
* Alternatively, provide a [glob](https://www.npmjs.com/package/glob) pattern or | ||
* an array of glob patterns and set `isGlob = true` | ||
* | ||
* Note: enabling glob will read both, `dir` _and_ `ignorePattern` as glob patterns | ||
*/ | ||
ignorePattern?: string; | ||
ignorePattern?: string | string[]; | ||
/** | ||
@@ -720,0 +737,0 @@ * Run only migration with this name. |
{ | ||
"name": "node-pg-migrate", | ||
"version": "7.7.0-rc.0", | ||
"version": "7.7.0", | ||
"description": "PostgreSQL database migration management tool for node.js", | ||
@@ -79,2 +79,3 @@ "bin": { | ||
"dependencies": { | ||
"glob": "11.0.0", | ||
"yargs": "~17.7.0" | ||
@@ -86,10 +87,10 @@ }, | ||
"@eslint-types/unicorn": "52.0.0", | ||
"@types/config": "3.3.4", | ||
"@types/node": "18.19.47", | ||
"@types/pg": "8.11.8", | ||
"@types/config": "3.3.5", | ||
"@types/node": "18.19.51", | ||
"@types/pg": "8.11.10", | ||
"@types/yargs": "17.0.33", | ||
"@typescript-eslint/eslint-plugin": "7.18.0", | ||
"@typescript-eslint/parser": "7.18.0", | ||
"@vitest/coverage-v8": "2.0.5", | ||
"@vitest/ui": "2.0.5", | ||
"@vitest/coverage-v8": "2.1.1", | ||
"@vitest/ui": "2.1.1", | ||
"config": "3.3.12", | ||
@@ -99,3 +100,3 @@ "cross-env": "7.0.3", | ||
"dotenv-expand": "11.0.6", | ||
"eslint": "8.57.0", | ||
"eslint": "8.57.1", | ||
"eslint-config-prettier": "9.1.0", | ||
@@ -108,13 +109,13 @@ "eslint-define-config": "2.1.0", | ||
"node-pg-migrate": "file:.", | ||
"npm-run-all2": "6.2.2", | ||
"pg": "8.12.0", | ||
"npm-run-all2": "6.2.3", | ||
"pg": "8.13.0", | ||
"prettier": "3.3.3", | ||
"prettier-plugin-organize-imports": "4.0.0", | ||
"prettier-plugin-organize-imports": "4.1.0", | ||
"rimraf": "6.0.1", | ||
"ts-node": "10.9.2", | ||
"tsup": "8.2.4", | ||
"tsx": "4.19.0", | ||
"typescript": "5.5.4", | ||
"tsup": "8.3.0", | ||
"tsx": "4.19.1", | ||
"typescript": "5.6.2", | ||
"vitepress": "1.3.4", | ||
"vitest": "2.0.5" | ||
"vitest": "2.1.1" | ||
}, | ||
@@ -121,0 +122,0 @@ "peerDependencies": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
540166
13382
0
4
+ Addedglob@11.0.0
+ Added@isaacs/cliui@8.0.2(transitive)
+ Addedansi-regex@6.1.0(transitive)
+ Addedansi-styles@6.2.1(transitive)
+ Addedbalanced-match@1.0.2(transitive)
+ Addedbrace-expansion@2.0.1(transitive)
+ Addedcross-spawn@7.0.5(transitive)
+ Addedeastasianwidth@0.2.0(transitive)
+ Addedemoji-regex@9.2.2(transitive)
+ Addedforeground-child@3.3.0(transitive)
+ Addedglob@11.0.0(transitive)
+ Addedisexe@2.0.0(transitive)
+ Addedjackspeak@4.0.2(transitive)
+ Addedlru-cache@11.0.2(transitive)
+ Addedminimatch@10.0.1(transitive)
+ Addedminipass@7.1.2(transitive)
+ Addedpackage-json-from-dist@1.0.1(transitive)
+ Addedpath-key@3.1.1(transitive)
+ Addedpath-scurry@2.0.0(transitive)
+ Addedshebang-command@2.0.0(transitive)
+ Addedshebang-regex@3.0.0(transitive)
+ Addedsignal-exit@4.1.0(transitive)
+ Addedstring-width@5.1.2(transitive)
+ Addedstrip-ansi@7.1.0(transitive)
+ Addedwhich@2.0.2(transitive)
+ Addedwrap-ansi@8.1.0(transitive)