Gathering detailed insights and metrics for umzug
Gathering detailed insights and metrics for umzug
Gathering detailed insights and metrics for umzug
Gathering detailed insights and metrics for umzug
npm install umzug
83.5
Supply Chain
98.3
Quality
85.5
Maintenance
100
Vulnerability
98.9
License
Module System
Min. Node Version
Typescript Support
Node Version
NPM Version
2,033 Stars
778 Commits
160 Forks
21 Watching
27 Branches
58 Contributors
Updated on 26 Nov 2024
TypeScript (99.35%)
JavaScript (0.65%)
Cumulative downloads
Total Downloads
Last day
-3.2%
192,498
Compared to previous day
Last week
5.2%
1,091,373
Compared to previous week
Last month
4.6%
4,496,368
Compared to previous month
Last year
0%
48,009,014
Compared to previous year
Umzug is a framework-agnostic migration tool for Node. It provides a clean API for running and rolling back tasks.
Note: these are the docs for the latest version of umzug, which has several breaking changes from v2.x. See the upgrading section for a migration guide. For the previous stable version, please refer to the v2.x branch.
The following example uses a Sqlite database through sequelize and persists the migration data in the database itself through the sequelize storage. There are several more involved examples covering a few different scenarios in the examples folder. Note that although this uses Sequelize, Umzug isn't coupled to Sequelize, it's just one of the (most commonly-used) supported storages.
1// index.js
2const {Sequelize} = require('sequelize')
3const {Umzug, SequelizeStorage} = require('umzug')
4
5const sequelize = new Sequelize({dialect: 'sqlite', storage: './db.sqlite'})
6
7const umzug = new Umzug({
8 migrations: {glob: 'migrations/*.js'},
9 context: sequelize.getQueryInterface(),
10 storage: new SequelizeStorage({sequelize}),
11 logger: console,
12})
13
14// Checks migrations and run them if they are not already applied. To keep
15// track of the executed migrations, a table (and sequelize model) called SequelizeMeta
16// will be automatically created (if it doesn't exist already) and parsed.
17await umzug.up()
1// migrations/00_initial.js 2 3const {Sequelize} = require('sequelize') 4 5async function up({context: queryInterface}) { 6 await queryInterface.createTable('users', { 7 id: { 8 type: Sequelize.INTEGER, 9 allowNull: false, 10 primaryKey: true, 11 }, 12 name: { 13 type: Sequelize.STRING, 14 allowNull: false, 15 }, 16 createdAt: { 17 type: Sequelize.DATE, 18 allowNull: false, 19 }, 20 updatedAt: { 21 type: Sequelize.DATE, 22 allowNull: false, 23 }, 24 }) 25} 26 27async function down({context: queryInterface}) { 28 await queryInterface.dropTable('users') 29} 30 31module.exports = {up, down}
Note that we renamed the context
argument to queryInterface
for clarity. The context
is whatever we specified when creating the Umzug instance in index.js
.
1// index.ts 2require('ts-node/register') 3 4import { Sequelize } from 'sequelize'; 5import { Umzug, SequelizeStorage } from 'umzug'; 6 7const sequelize = new Sequelize({ dialect: 'sqlite', storage: './db.sqlite' }); 8 9const umzug = new Umzug({ 10 migrations: { glob: 'migrations/*.ts' }, 11 context: sequelize.getQueryInterface(), 12 storage: new SequelizeStorage({ sequelize }), 13 logger: console, 14}); 15 16// export the type helper exposed by umzug, which will have the `context` argument typed correctly 17export type Migration = typeof umzug._types.migration; 18 19(async () => { 20 await umzug.up(); 21})();
1// migrations/00_initial.ts 2import type { Migration } from '..'; 3 4// types will now be available for `queryInterface` 5export const up: Migration = ({ context: queryInterface }) => queryInterface.createTable(...) 6export const down: Migration = ({ context: queryInterface }) => queryInterface.dropTable(...)
See these tests for more examples of Umzug usage, including:
ignore
and cwd
parameters to the glob instructions.sql
Umzug is available on npm by specifying the correct tag:
1npm install umzug
It is possible to configure an Umzug instance by passing an object to the constructor.
1const {Umzug} = require('umzug') 2 3const umzug = new Umzug({ 4 /* ... options ... */ 5})
Detailed documentation for these options are in the UmzugOptions
TypeScript interface, which can be found in src/types.ts.
You can get a list of pending (i.e. not yet executed) migrations with the pending()
method:
1const migrations = await umzug.pending() 2// returns an array of all pending migrations.
You can get a list of already executed migrations with the executed()
method:
1const migrations = await umzug.executed() 2// returns an array of all already executed migrations
The up
method can be used to execute all pending migrations.
1const migrations = await umzug.up() 2// returns an array of all executed migrations
It is also possible to pass the name of a migration in order to just run the migrations from the current state to the passed migration name (inclusive).
1await umzug.up({to: '20141101203500-task'})
To limit the number of migrations that are run, step
can be used:
1// This will run the next two migrations 2await umzug.up({step: 2})
Running specific migrations while ignoring the right order, can be done like this:
1await umzug.up({migrations: ['20141101203500-task', '20141101203501-task-2']})
The down
method can be used to revert the last executed migration.
1const migration = await umzug.down() 2// reverts the last migration and returns it.
To revert more than one migration, you can use step
:
1// This will revert the last two migrations 2await umzug.down({step: 2})
It is possible to pass the name of a migration until which (inclusive) the migrations should be reverted. This allows the reverting of multiple migrations at once.
1const migrations = await umzug.down({to: '20141031080000-task'}) 2// returns an array of all reverted migrations.
To revert all migrations, you can pass 0 as the to
parameter:
1await umzug.down({to: 0})
Reverting specific migrations while ignoring the right order, can be done like this:
1await umzug.down({migrations: ['20141101203500-task', '20141101203501-task-2']})
There are two ways to specify migrations: via files or directly via an array of migrations.
A migration file ideally exposes an up
and a down
async functions. They will perform the task of upgrading or downgrading the database.
1module.exports = { 2 async up() { 3 /* ... */ 4 }, 5 async down() { 6 /* ... */ 7 }, 8}
Migration files can be located anywhere - they will typically be loaded according to a glob pattern provided to the Umzug
constructor.
You can also specify directly a list of migrations to the Umzug
constructor:
1const {Umzug} = require('umzug') 2 3const umzug = new Umzug({ 4 migrations: [ 5 { 6 // the name of the migration is mandatory 7 name: '00-first-migration', 8 async up({context}) { 9 /* ... */ 10 }, 11 async down({context}) { 12 /* ... */ 13 }, 14 }, 15 { 16 name: '01-foo-bar-migration', 17 async up({context}) { 18 /* ... */ 19 }, 20 async down({context}) { 21 /* ... */ 22 }, 23 }, 24 ], 25 context: sequelize.getQueryInterface(), 26 logger: console, 27})
Sometimes it's necessary to modify the parameters umzug
will pass to your migration methods when the library calls the up
and down
methods for each migration. This is the case when using migrations currently generated using sequelize-cli
. In this case you can use the resolve
fuction during migration configuration to determine which parameters will be passed to the relevant method
1import {Sequelize} from 'sequelize' 2import {Umzug, SequelizeStorage} from 'umzug' 3 4const sequelize = new Sequelize(/* ... */) 5 6const umzug = new Umzug({ 7 migrations: { 8 glob: 'migrations/*.js', 9 resolve: ({name, path, context}) => { 10 const migration = require(path) 11 return { 12 // adjust the parameters Umzug will 13 // pass to migration methods when called 14 name, 15 up: async () => migration.up(context, Sequelize), 16 down: async () => migration.down(context, Sequelize), 17 } 18 }, 19 }, 20 context: sequelize.getQueryInterface(), 21 storage: new SequelizeStorage({sequelize}), 22 logger: console, 23})
To load migrations in another format, you can use the resolve
function:
1const fs = require('fs') 2const {Sequelize} = require('sequelize') 3const {Umzug} = require('umzug') 4 5const umzug = new Umzug({ 6 migrations: { 7 glob: 'migrations/*.up.sql', 8 resolve: ({name, path, context: sequelize}) => ({ 9 name, 10 up: async () => { 11 const sql = fs.readFileSync(path).toString() 12 return sequelize.query(sql) 13 }, 14 down: async () => { 15 // Get the corresponding `.down.sql` file to undo this migration 16 const sql = fs 17 .readFileSync(path.replace('.up.sql', '.down.sql')) 18 .toString() 19 return sequelize.query(sql) 20 }, 21 }), 22 }, 23 context: new Sequelize(/* ... */), 24 logger: console, 25})
You can support mixed migration file types, and use umzug's default resolver for javascript/typescript:
1const fs = require('fs')
2const {Sequelize} = require('sequelize')
3const {Umzug} = require('umzug')
4
5const umzug = new Umzug({
6 migrations: {
7 glob: 'migrations/*.{js,ts,up.sql}',
8 resolve: params => {
9 if (!params.path.endsWith('.sql')) {
10 return Umzug.defaultResolver(params)
11 }
12 const {context: sequelize} = params
13 return {
14 name: params.name,
15 up: async () => {
16 const sql = fs.readFileSync(params.path).toString()
17 return sequelize.query(sql)
18 },
19 down: async () => {
20 // Get the corresponding `.down.sql` file to undo this migration
21 const sql = fs
22 .readFileSync(params.path.replace('.up.sql', '.down.sql'))
23 .toString()
24 return sequelize.query(sql)
25 },
26 }
27 },
28 },
29 logger: console,
30 context: new Sequelize(/* ... */),
31})
The glob syntax allows loading migrations from multiple locations:
1const {Sequelize} = require('sequelize')
2const {Umzug} = require('umzug')
3
4const umzug = new Umzug({
5 migrations: {
6 glob: '{first-folder/*.js,second-folder-with-different-naming-convention/*.js}',
7 },
8 context: new Sequelize(/* ... */),
9 logger: console,
10})
Note on migration file sorting:
one/m1.js
, two/m2.js
, three/m3.js
, the resultant order will be one/m1.js
, three/m3.js
, two/m2.js
m1.js
, m2.js
, ... m10.js
, m11.js
, the resultant ordering will be m1.js
, m10.js
, m11.js
, ... m2.js
.extend(...)
- see below for example using a new instance)The Umzug class should be imported as a named import, i.e. import { Umzug } from 'umzug'
.
The MigrationMeta
type, which is returned by umzug.executed()
and umzug.pending()
, no longer has a file
property - it has a name
and optional path
- since migrations are not necessarily bound to files on the file system.
The migrations.glob
parameter replaces path
, pattern
and traverseDirectories
. It can be used, in combination with cwd
and ignore
to do much more flexible file lookups. See https://npmjs.com/package/fast-glob for more information on the syntax.
The migrations.resolve
parameter replaces customResolver
. Explicit support for wrap
and nameFormatter
has been removed - these can be easily implemented in a resolve
function.
The constructor option logging
is replaced by logger
to allow for warn
and error
messages in future. NodeJS's global console
object can be passed to this. To disable logging, replace logging: false
with logger: undefined
.
Events have moved from the default nodejs EventEmitter
to emittery. It has better design for async code, a less bloated API surface and strong types. But, it doesn't allow passing multiple arguments to callbacks, so listeners have to change slightly, as well as .addListener(...)
and .removeListener(...)
no longer being supported (.on(...)
and .off(...)
should now be used):
Before:
1umzug.on('migrating', (name, m) => console.log({name, path: m.path}))
After:
1umzug.on('migrating', ev => console.log({name: ev.name, path: ev.path}))
The Umzug#execute
method is removed. Use Umzug#up
or Umzug#down
.
The options for Umguz#up
and Umzug#down
have changed:
umzug.up({ to: 'some-name' })
and umzug.down({ to: 'some-name' })
are still valid.umzug.up({ from: '...' })
and umzug.down({ from: '...' })
are no longer supported. To run migrations out-of-order (which is not generally recommended), you can explicitly use umzug.up({ migrations: ['...'] })
and umzug.down({ migrations: ['...'] })
.umzug.up({ to: 'some-n' })
will no longer match a migration called some-name
.umzug.down({ to: 0 })
is still valid but umzug.up({ to: 0 })
is not.umzug.up({ migrations: ['m1', 'm2'] })
is still valid but the shorthand umzug.up(['m1', 'm2'])
has been removed.umzug.down({ migrations: ['m1', 'm2'] })
is still valid but the shorthand umzug.down(['m1', 'm2'])
has been removed.umzug.up({ migrations: ['m1', 'already-run'] })
will throw an error, if already-run
is not found in the list of pending migrations.umzug.down({ migrations: ['m1', 'has-not-been-run'] })
will throw an error, if has-not-been-run
is not found in the list of executed migrations.umzug.up({ migrations: ['m1', 'm2'], rerun: 'ALLOW' })
will re-apply migrations m1
and m2
even if they've already been run.umzug.up({ migrations: ['m1', 'm2'], rerun: 'SKIP' })
will skip migrations m1
and m2
if they've already been run.umzug.down({ migrations: ['m1', 'm2'], rerun: 'ALLOW' })
will "revert" migrations m1
and m2
even if they've never been run.umzug.down({ migrations: ['m1', 'm2'], rerun: 'SKIP' })
will skip reverting migrations m1
and m2
if they haven't been run or are already reverted.umzug.up({ migrations: ['m1', 'does-not-exist', 'm2'] })
will throw an error if the migration name is not found. Note that the error will be thrown and no migrations run unless all migration names are found - whether or not rerun: 'ALLOW'
is added.The context
parameter replaces params
, and is passed in as a property to migration functions as an options object, alongs side name
and path
. This means the signature for migrations, which in v2 was (context) => Promise<void>
, has changed slightly in v3, to ({ name, path, context }) => Promise<void>
.
The resolve
function can also be used to upgrade your umzug version to v3 when you have existing v2-compatible migrations:
1const {Umzug} = require('umzug')
2
3const umzug = new Umzug({
4 migrations: {
5 glob: 'migrations/umzug-v2-format/*.js',
6 resolve: ({name, path, context}) => {
7 // Adjust the migration from the new signature to the v2 signature, making easier to upgrade to v3
8 const migration = require(path)
9 return {
10 name,
11 up: async () => migration.up(context),
12 down: async () => migration.down(context),
13 }
14 },
15 },
16 context: sequelize.getQueryInterface(),
17 logger: console,
18})
Similarly, you no longer need migrationSorting
, you can instantiate a new Umzug
instance to manipulate migration lists directly:
1const {Umzug} = require('umzug')
2
3const parent = new Umzug({
4 migrations: {glob: 'migrations/**/*.js'},
5 context: sequelize.getQueryInterface(),
6})
7
8const umzug = new Umzug({
9 ...parent.options,
10 migrations: async ctx =>
11 (await parent.migrations()).sort((a, b) => b.path.localeCompare(a.path)),
12})
Storages define where the migration data is stored.
Using JSONStorage
will create a JSON file which will contain an array with all the executed migrations. You can specify the path to the file. The default for that is umzug.json
in the working directory of the process.
Detailed documentation for the options it can take are in the JSONStorageConstructorOptions
TypeScript interface, which can be found in src/storage/json.ts.
Using memoryStorage
will store migrations with an in-memory array. This can be useful for proof-of-concepts or tests, since it doesn't interact with databases or filesystems.
It doesn't take any options, just import the memoryStorage
function and call it to return a storage instance:
1import { Umzug, memoryStorage } from 'umzug' 2 3const umzug = new Umzug({ 4 migrations: ..., 5 storage: memoryStorage(), 6 logger: console, 7})
Using SequelizeStorage
will create a table in your SQL database called SequelizeMeta
containing an entry for each executed migration. You will have to pass a configured instance of Sequelize or an existing Sequelize model. Optionally you can specify the model name, table name, or column name. All major Sequelize versions are supported.
Detailed documentation for the options it can take are in the _SequelizeStorageConstructorOptions
TypeScript interface, which can be found in src/storage/sequelize.ts.
This library has been tested with sequelize v6. It may or may not work with lower versions - use at your own risk.
Using MongoDBStorage
will create a collection in your MongoDB database called migrations
containing an entry for each executed migration. You will have either to pass a MongoDB Driver Collection as collection
property. Alternatively you can pass a established MongoDB Driver connection and a collection name.
Detailed documentation for the options it can take are in the MongoDBStorageConstructorOptions
TypeScript interface, which can be found in src/storage/mongodb.ts.
In order to use a custom storage, you can pass your storage instance to Umzug constructor.
1class CustomStorage { 2 constructor() {} 3 logMigration() {} 4 unlogMigration() {} 5 executed() {} 6} 7 8const umzug = new Umzug({ 9 storage: new CustomStorage(/* ... */), 10 logger: console, 11})
Your instance must adhere to the UmzugStorage interface. If you're using TypeScript you can ensure this at compile time, and get IDE type hints by importing it:
1import { UmzugStorage } from 'umzug' 2 3class CustomStorage implements UmzugStorage { 4 /* ... */ 5}
Umzug is an emittery event emitter. Each of the following events will be called with migration parameters as its payload (with context
, name
, and nullable path
properties). Events are a convenient place to implement application-specific logic that must run around each migration:
migrating
- A migration is about to be executed.migrated
- A migration has successfully been executed.reverting
- A migration is about to be reverted.reverted
- A migration has successfully been reverted.These events run at the beginning and end of up
and down
calls. They'll receive an object containing a context
property:
beforeCommand
- Before any command ('up' | 'down' | 'executed' | 'pending'
) is run.afterCommand
- After any command ('up' | 'down' | 'executed' | 'pending'
) is run. Note: this will always run, even if the command throws an error.The FileLocker
class uses beforeAll
and afterAll
to implement a simple filesystem-based locking mechanism.
All events are type-safe, so IDEs will prevent typos and supply strong types for the event payloads.
When a migration throws an error, it will be wrapped in a MigrationError
which captures the migration metadata (name, path etc.) as well as the original error message, and will be rethrown. In most cases, this is expected behaviour, and doesn't require any special handling beyond standard error logging setups.
If you expect failures and want to try to recover from them, you will need to try-catch the call to umzug.up()
. You can access the original error from the .cause
property if necessary:
1try { 2 await umzug.up() 3} catch (e) { 4 if (e instanceof MigrationError) { 5 const original = e.cause 6 // do something with the original error here 7 } 8 throw e 9}
Under the hood, verror is used to wrap errors.
🚧🚧🚧 The CLI is new to Umzug v3. Feedback on it is welcome in discussions 🚧🚧🚧
Umzug instances provide a .runAsCLI()
method. When called, this method will automatically cause your program to become a complete CLI, with help text and such:
1// migrator.js 2const {Umzug} = require('umzug') 3 4const umzug = new Umzug({ 5 /* ... */ 6}) 7 8exports.umzug = umzug 9 10if (require.main === module) { 11 umzug.runAsCLI() 12}
Note that this uses the @rushstack/ts-command-line package, which shows only the top-level message of any errors throw by default. See here for how you can see a full stack trace.
A script like the one above is now a runnable CLI program. You can run node migrator.js --help
to see how to use it. It will print something like:
usage: <script> [-h] <command> ...
Umzug migrator
Positional arguments:
<command>
up Applies pending migrations
down Revert migrations
pending Lists pending migrations
executed Lists executed migrations
create Create a migration file
Optional arguments:
-h, --help Show this help message and exit.
For detailed help about a specific command, use: <script> <command> -h
node migrator up
and node migrator down
apply and revert migrations respectively. They're the equivalent of the .up()
and .down()
methods.
Use node migrator up --help
and node migrator down --help
for options (running "to" a specific migration, passing migration names to be run explicitly, and specifying the rerun behavior):
Up:
usage: <script> up [-h] [--to NAME] [--step COUNT] [--name MIGRATION]
[--rerun {THROW,SKIP,ALLOW}]
Performs all migrations. See --help for more options
Optional arguments:
-h, --help Show this help message and exit.
--to NAME All migrations up to and including this one should be
applied
--step COUNT Apply this many migrations. If not specified, all
will be applied.
--name MIGRATION Explicity declare migration name(s) to be applied.
Only these migrations will be applied.
--rerun {THROW,SKIP,ALLOW}
Specify what action should be taken when a migration
that has already been applied is passed to --name.
The default value is "THROW".
Down:
usage: <script> down [-h] [--to NAME] [--step COUNT] [--name MIGRATION]
[--rerun {THROW,SKIP,ALLOW}]
Undoes previously-applied migrations. By default, undoes the most recent
migration only. Use --help for more options. Useful in development to start
from a clean slate. Use with care in production!
Optional arguments:
-h, --help Show this help message and exit.
--to NAME All migrations up to and including this one should be
reverted. Pass '0' to revert all.
--step COUNT Revert this many migrations. If not specified, only
the most recent migration will be reverted.
--name MIGRATION Explicity declare migration name(s) to be reverted.
Only these migrations will be reverted.
--rerun {THROW,SKIP,ALLOW}
Specify what action should be taken when a migration
that has already been applied is passed to --name.
The default value is "THROW".
1node migrator pending # list migrations yet to be run 2node migrator executed # list migrations that have already run 3 4node migrator pending --json # list pending migrations including names and paths, in a json array format 5node migrator executed --json # list executed migrations including names and paths, in a json array format 6 7node migrator pending --help # show help/options 8node migrator executed --help # show help/options
usage: <script> pending [-h] [--json]
Prints migrations returned by `umzug.pending()`. By default, prints migration
names one per line.
Optional arguments:
-h, --help Show this help message and exit.
--json Print pending migrations in a json format including names and
paths. This allows piping output to tools like jq. Without this
flag, the migration names will be printed one per line.
usage: <script> executed [-h] [--json]
Prints migrations returned by `umzug.executed()`. By default, prints
migration names one per line.
Optional arguments:
-h, --help Show this help message and exit.
--json Print executed migrations in a json format including names and
paths. This allows piping output to tools like jq. Without this
flag, the migration names will be printed one per line.
Usually, migrations correspond to files on the filesystem. The CLI exposes a way to create migration files easily:
1node migrator create --name my-migration.js
This will create a file with a name like 2000.12.25T12.34.56.my-migration.js
in the same directory as the most recent migration file. If it's the very first migration file, you need to specify the folder explicitly:
1node migrator create --name my-migration.js --folder path/to/directory
The timestamp prefix can be customized to be date-only or omitted, but be aware that it's strongly recommended to ensure your migrations are lexicographically sortable so it's easy for humans and tools to determine what order they should run in - so the default prefix is recommended.
This will generate a migration file called <<timestamp>>.my-migration.js
with the default migration template for .js
files that ships with Umzug.
Umzug also ships with default templates for .ts
, .cjs
, .mjs
and .sql
files. Umzug will choose the template based on the extension you provide in name
.
You can specify a custom template for your project when constructing an umzug instance via the template
option. It should be a function which receives a filepath string, and returns an array of [filepath, content]
pairs. Usually, just one pair is needed, but a second could be used to include a "down" migration in a separate file:
1const umzug = new Umzug({
2 migrations: {
3 /*...*/
4 },
5 create: {
6 template: filepath => [
7 [filepath, fs.readFileSync('path/to/your/template/file').toString()],
8 ],
9 },
10})
The create command includes some safety checks to make sure migrations aren't created with ambiguous ordering, and that they will be picked up by umzug when applying migrations. The first pair is expected to be the "up" migration file, and to be picked up by the pending
command.
Use node migrator create --help
for more options:
usage: <script> create [-h] --name NAME [--prefix {TIMESTAMP,DATE,NONE}]
[--folder PATH] [--allow-extension EXTENSION]
[--skip-verify] [--allow-confusing-ordering]
Generates a placeholder migration file using a timestamp as a prefix. By
default, mimics the last existing migration, or guesses where to generate the
file if no migration exists yet.
Optional arguments:
-h, --help Show this help message and exit.
--name NAME The name of the migration file. e.g. my-migration.js,
my-migration.ts or my-migration.sql. Note - a prefix
will be added to this name, usually based on a
timestamp. See --prefix
--prefix {TIMESTAMP,DATE,NONE}
The prefix format for generated files. TIMESTAMP uses
a second-resolution timestamp, DATE uses a
day-resolution timestamp, and NONE removes the prefix
completely. The default value is "TIMESTAMP".
--folder PATH Path on the filesystem where the file should be
created. The new migration will be created as a
sibling of the last existing one if this is omitted.
--allow-extension EXTENSION
Allowable extension for created files. By default .js,
.ts and .sql files can be created. To create txt
file migrations, for example, you could use '--name
my-migration.txt --allow-extension .txt' This
parameter may alternatively be specified via the
UMZUG_ALLOW_EXTENSION environment variable.
--skip-verify By default, the generated file will be checked after
creation to make sure it is detected as a pending
migration. This catches problems like creation in the
wrong folder, or invalid naming conventions. This
flag bypasses that verification step.
--allow-confusing-ordering
By default, an error will be thrown if you try to
create a migration that will run before a migration
that already exists. This catches errors which can
cause problems if you change file naming conventions.
If you use a custom ordering system, you can disable
this behavior, but it's strongly recommended that you
don't! If you're unsure, just ignore this option.
Umzug includes an optional helper for generating migration files. It's often most convenient to create files using the CLI helper, but the equivalent API also exists on an umzug instance:
1await umzug.create({name: 'my-new-migration.js'})
See the LICENSE file
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
no dangerous workflow patterns detected
Reason
license file detected
Details
Reason
2 existing vulnerabilities detected
Details
Reason
9 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 7
Reason
Found 2/21 approved changesets -- score normalized to 0
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Score
Last Scanned on 2024-11-18
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More