A recursive Umzug extension with migration-less installs
import pg from 'pg';
import {
UmzeptionPgStorage,
createUmzeptionPgContext,
umzeption,
} from 'umzeption';
import { Umzug } from 'umzug';
const umzug = new Umzug({
migrations: umzeption({
// Which dependencies we want to install migrations and schemas from
dependencies: [
'@yikesable/foo',
'@yikesable/bar',
],
// Optional: Which migrations do we have ourselves?
glob: ['migrations/*.js'],
// Optional: Which migrations do we have ourselves?
async installSchema ({ context: queryInterface }) {},
// Optional: Set to true if it should be a fresh install rather than a migration
install: true,
// Optional: Used to inform where to resolve "glob" from
meta: import.meta,
// Optional: Can be used instead of "meta" and if none are set, then process.cwd() is the default
// cwd: process.cwd(),
}),
// Other contexts can be created and plugins can support multiple contexts
context: createUmzeptionPgContext(new pg.Pool({
allowExitOnIdle: true,
connectionString: '...',
})),
// Any type of storage can be used, but UmzeptionStorage ones re-use the context's connection + ensures a match with the context types
storage: new UmzeptionPgStorage(),
logger: console,
});
umzug.up();
On the first install in an environment you set install: true
in umzeption()
. This makes it so that the installSchema()
methods will be what is run and all migrations will be marked as being run without actually running (as a fresh install should need no migrations).
On everything but the first install you set install: false
in umzeption()
(or leave it out). This makes it so that the installSchema()
methods not be run, but all new migrations will be run as normal through Umzug.
The dependency is expected to provide one of these two at its top level
Makes it easy to enforce types and keeps all Umzeption related stuff grouped together
/** @satisfies {import('umzeption').UmzeptionDependency} */
export const umzeptionConfig = {
dependencies: ['@yikesable/abc'],
glob: ['migrations/*.js'],
async installSchema ({ context }) {
if (context.type !== 'pg') {
throw new Error(`Unsupported context type: ${context.type}`);
}
const tables = await getTables();
await context.value.transact(async client => {
for (const table of tables) {
await client.query(table);
}
});
},
};
export const dependencies = ['@yikesable/abc'];
export const glob = ['migrations/*.js'];
/** @type {import('umzeption').UmzeptionDependency["installSchema"]} */
export async function installSchema ({ context }) {
if (context.type !== 'pg') {
throw new Error(`Unsupported context type: ${context.type}`);
}
const tables = await getTables();
await context.value.transact(async client => {
for (const table of tables) {
await client.query(table);
}
});
},
};
import { readFile } from 'node:fs/promises';
import { installSchemaFromString } from 'umzeption';
/** @satisfies {import('umzeption').UmzeptionDependency} */
export const umzeptionConfig = {
dependencies: ['@yikesable/abc'],
glob: ['migrations/*.js'],
installSchema: async ({ context }) => {
const tables = await readFile(new URL('create-tables.sql', import.meta.url), 'utf8');
return installSchemaFromString(context, tables);
},
};
umzug
– the base system this module is meant to be paired withplugin-importer
– the plugin loader that this module uses