graphile-migrate
Version:
Opinionated SQL-powered migration tool for PostgreSQL
208 lines (196 loc) • 8.32 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = require("fs");
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
const package_json_1 = require("../../package.json");
const current_1 = require("../current");
const settings_1 = require("../settings");
const _common_1 = require("./_common");
async function init(options = {}) {
if (await _common_1.exists(_common_1.DEFAULT_GMRC_PATH)) {
throw new Error(`.gmrc file already exists at ${_common_1.DEFAULT_GMRC_PATH}`);
}
if (await _common_1.exists(_common_1.DEFAULT_GMRCJS_PATH)) {
throw new Error(`.gmrc.js file already exists at ${_common_1.DEFAULT_GMRCJS_PATH}`);
}
if (options.config && (await _common_1.exists(options.config))) {
throw new Error(`.gmrc file already exists at ${options.config}`);
}
const gmrcPath = options.config || _common_1.DEFAULT_GMRC_PATH;
const dbStrings = process.env.DATABASE_URL &&
process.env.SHADOW_DATABASE_URL &&
process.env.ROOT_DATABASE_URL
? `
/*
* Database connections strings are sourced from the DATABASE_URL,
* SHADOW_DATABASE_URL and ROOT_DATABASE_URL environmental variables.
*/
`
: `
/*
* connectionString: this tells Graphile Migrate where to find the database
* to run the migrations against.
*
* RECOMMENDATION: use \`DATABASE_URL\` envvar instead.
*/
// "connectionString": "postgres://appuser:apppassword@host:5432/appdb",
/*
* shadowConnectionString: like connectionString, but this is used for the
* shadow database (which will be reset frequently).
*
* RECOMMENDATION: use \`SHADOW_DATABASE_URL\` envvar instead.
*/
// "shadowConnectionString": "postgres://appuser:apppassword@host:5432/appdb_shadow",
/*
* rootConnectionString: like connectionString, but this is used for
* dropping/creating the database in \`graphile-migrate reset\`. This isn't
* necessary, shouldn't be used in production, but helps during development.
*
* RECOMMENDATION: use \`ROOT_DATABASE_URL\` envvar instead.
*/
// "rootConnectionString": "postgres://adminuser:adminpassword@host:5432/postgres",
`;
const initialComment = `\
/*
* Graphile Migrate configuration.
*
* If you decide to commit this file (recommended) please ensure that it does
* not contain any secrets (passwords, etc) - we recommend you manage these
* with environmental variables instead.
*
* This file is in JSON5 format, in VSCode you can use "JSON with comments" as
* the file format.
*/
`;
const jsonContent = `\
{${dbStrings}
/*
* pgSettings: key-value settings to be automatically loaded into PostgreSQL
* before running migrations, using an equivalent of \`SET LOCAL <key> TO
* <value>\`
*/
"pgSettings": {
// "search_path": "app_public,app_private,app_hidden,public",
},
/*
* placeholders: substituted in SQL files when compiled/executed. Placeholder
* keys should be prefixed with a colon and in all caps, like
* \`:COLON_PREFIXED_ALL_CAPS\`. Placeholder values should be strings. They
* will be replaced verbatim with NO ESCAPING AT ALL (this differs from how
* psql handles placeholders) so should only be used with "safe" values. This
* is useful for committing migrations where certain parameters can change
* between environments (development, staging, production) but you wish to
* use the same signed migration files for all.
*
* The special value "!ENV" can be used to indicate an environmental variable
* of the same name should be used.
*
* Graphile Migrate automatically sets the \`:DATABASE_NAME\` and
* \`:DATABASE_OWNER\` placeholders, and you should not attempt to override
* these.
*/
"placeholders": {
// ":DATABASE_VISITOR": "!ENV", // Uses process.env.DATABASE_VISITOR
},
/*
* Actions allow you to run scripts or commands at certain points in the
* migration lifecycle. SQL files are ran against the database directly.
* "command" actions are ran with the following environmental variables set:
*
* - GM_DBURL: the PostgreSQL URL of the database being migrated
* - GM_DBNAME: the name of the database from GM_DBURL
* - GM_DBUSER: the user from GM_DBURL
* - GM_SHADOW: set to 1 if the shadow database is being migrated, left unset
* otherwise
*
* If "shadow" is unspecified, the actions will run on events to both shadow
* and normal databases. If "shadow" is true the action will only run on
* actions to the shadow DB, and if false only on actions to the main DB.
*/
/*
* afterReset: actions executed after a \`graphile-migrate reset\` command.
*/
"afterReset": [
// "afterReset.sql",
// { "_": "command", "command": "graphile-worker --schema-only" },
],
/*
* afterAllMigrations: actions executed once all migrations are complete.
*/
"afterAllMigrations": [
// {
// "_": "command",
// "shadow": true,
// "command": "if [ \\"$IN_TESTS\\" != \\"1\\" ]; then ./scripts/dump-db; fi",
// },
],
/*
* afterCurrent: actions executed once the current migration has been
* evaluated (i.e. in watch mode).
*/
"afterCurrent": [
// {
// "_": "command",
// "shadow": true,
// "command": "if [ \\"$IN_TESTS\\" = \\"1\\" ]; then ./scripts/test-seed; fi",
// },
],
/*
* blankMigrationContent: content to be written to the current migration
* after commit. NOTE: this should only contain comments.
*/
// "blankMigrationContent": "-- Write your migration here\\n",
/****************************************************************************\\
*** ***
*** You probably don't want to edit anything below here. ***
*** ***
\\****************************************************************************/
/*
* manageGraphileMigrateSchema: if you set this false, you must be sure to
* keep the graphile_migrate schema up to date yourself. We recommend you
* leave it at its default.
*/
// "manageGraphileMigrateSchema": true,
/*
* migrationsFolder: path to the folder in which to store your migrations.
*/
// migrationsFolder: "./migrations",
"//generatedWith": "${package_json_1.version}"
}`;
const fileContent = gmrcPath.endsWith(".js")
? `${initialComment}module.exports = ${jsonContent};\n`
: `${initialComment}${jsonContent}\n`;
await fs_1.promises.writeFile(gmrcPath, fileContent);
// eslint-disable-next-line
console.log(`Template .gmrc file written to '${gmrcPath}'; please read and edit it to suit your needs.`);
const settings = await _common_1.getSettings({ configFile: options.config });
const parsedSettings = await settings_1.parseSettings(Object.assign({ connectionString: process.env.DATABASE_URL || "NOT_NEEDED", shadowConnectionString: process.env.SHADOW_DATABASE_URL || "NOT_NEEDED" }, settings));
await fs_1.promises.mkdir(parsedSettings.migrationsFolder);
await fs_1.promises.mkdir(parsedSettings.migrationsFolder + "/committed");
if (options.folder) {
await fs_1.promises.mkdir(parsedSettings.migrationsFolder + "/current");
}
const currentLocation = await current_1.getCurrentMigrationLocation(parsedSettings);
await current_1.writeCurrentMigration(parsedSettings, currentLocation, parsedSettings.blankMigrationContent.trim() + "\n");
// eslint-disable-next-line
console.log(`The current migration was created at '${currentLocation.path}'.\n${process.env.DATABASE_URL
? "Try"
: "After configuring your connectionString/DATABASE_URL try"} running \`graphile-migrate watch\` and editing the current migration.`);
}
exports.init = init;
exports.initCommand = {
command: "init",
aliases: [],
describe: `\
Initializes a graphile-migrate project by creating a \`.gmrc\` file and \`migrations\` folder.`,
builder: {
folder: {
type: "boolean",
description: "Use a folder rather than a file for the current migration.",
default: false,
},
},
handler: init,
};
//# sourceMappingURL=init.js.map