From 6075cd555c1d17941d30f6bcf9760f92353b8256 Mon Sep 17 00:00:00 2001 From: Shinigami92 Date: Thu, 29 Feb 2024 00:01:40 +0100 Subject: [PATCH] chore: run prettier format --- .eslintrc.js | 2 +- README.md | 12 +- bin/node-pg-migrate | 361 ++++++----- docs/README.md | 12 +- docs/index.html | 14 +- docs/migrations.md | 22 +- mocha.bootstrap.js | 18 +- src/db.ts | 142 +++-- src/index.ts | 184 +++--- src/migration-builder.ts | 560 ++++++++++------- src/migration.ts | 262 ++++---- src/operations/PgLiteral.ts | 6 +- src/operations/domains.ts | 107 ++-- src/operations/domainsTypes.ts | 37 +- src/operations/extensions.ts | 44 +- src/operations/extensionsTypes.ts | 20 +- src/operations/functions.ts | 101 +-- src/operations/functionsTypes.ts | 42 +- src/operations/generalTypes.ts | 33 +- src/operations/indexes.ts | 125 ++-- src/operations/indexesTypes.ts | 40 +- src/operations/operators.ts | 276 ++++---- src/operations/operatorsTypes.ts | 104 +-- src/operations/other.ts | 18 +- src/operations/othersTypes.ts | 9 +- src/operations/policies.ts | 88 +-- src/operations/policiesTypes.ts | 38 +- src/operations/roles.ts | 112 ++-- src/operations/rolesTypes.ts | 51 +- src/operations/schemas.ts | 51 +- src/operations/schemasTypes.ts | 23 +- src/operations/sequences.ts | 114 ++-- src/operations/sequencesTypes.ts | 50 +- src/operations/tables.ts | 594 +++++++++++------- src/operations/tablesTypes.ts | 185 +++--- src/operations/triggers.ts | 135 ++-- src/operations/triggersTypes.ts | 48 +- src/operations/types.ts | 166 ++--- src/operations/typesTypes.ts | 75 ++- src/operations/views.ts | 146 +++-- src/operations/viewsMaterialized.ts | 159 +++-- src/operations/viewsMaterializedTypes.ts | 68 +- src/operations/viewsTypes.ts | 50 +- src/runner.ts | 280 +++++---- src/sqlMigration.ts | 40 +- src/types.ts | 327 +++++----- src/utils.ts | 215 ++++--- test/1414549381268_names.js | 12 +- test/1414549381268_names_promise.js | 8 +- test/cockroach/004_table.js | 8 +- test/cockroach/006_table_rename.js | 4 +- test/cockroach/008_column_drop.js | 8 +- test/cockroach/009_column.js | 4 +- test/cockroach/011_column_rename.js | 4 +- test/cockroach/012_column_alter.js | 8 +- test/cockroach/014_add_constraint.js | 8 +- test/cockroach/017_drop_constraint.js | 8 +- test/cockroach/019_add_index.js | 4 +- test/cockroach/020_create_index.js | 4 +- test/cockroach/062_view.js | 10 +- test/cockroach/062_view_test.js | 6 +- test/db-test.ts | 156 ++--- test/indexes-test.ts | 106 ++-- test/migration-test.ts | 212 ++++--- test/migrations/001_noop.js | 2 +- test/migrations/002_callback.js | 4 +- test/migrations/003_promise.js | 4 +- test/migrations/004_table.js | 10 +- test/migrations/005_table_test.js | 44 +- test/migrations/006_table_rename.js | 4 +- test/migrations/007_table_rename_test.js | 6 +- test/migrations/008_column_drop.js | 8 +- test/migrations/009_column.js | 4 +- test/migrations/010_column_test.js | 26 +- test/migrations/011_column_rename.js | 4 +- test/migrations/012_column_alter.js | 8 +- test/migrations/013_column_alter_test.js | 14 +- test/migrations/014_add_constraint.js | 6 +- test/migrations/015_add_constraint_test.js | 16 +- test/migrations/016_rename_constraint.js | 8 +- test/migrations/017_drop_constraint.js | 10 +- test/migrations/018_drop_constraint_test.js | 4 +- test/migrations/019_add_index.js | 4 +- test/migrations/020_drop_index.js | 8 +- test/migrations/021_add_type.js | 6 +- test/migrations/022_add_type_test.js | 10 +- test/migrations/023_add_type_attribute.js | 4 +- .../migrations/024_add_type_attribute_test.js | 6 +- test/migrations/025_set_type_attribute.js | 8 +- .../migrations/026_set_type_attribute_test.js | 14 +- test/migrations/027_add_type_value.js | 8 +- test/migrations/028_add_type_value_test.js | 8 +- test/migrations/029_rename_type_attribute.js | 4 +- .../030_rename_type_attribute_test.js | 6 +- test/migrations/031_drop_type_attribute.js | 8 +- .../032_drop_type_attribute_test.js | 14 +- test/migrations/033_drop_type.js | 8 +- test/migrations/034_drop_type_test.js | 14 +- test/migrations/035_role_add.js | 4 +- test/migrations/036_role_alter.js | 8 +- test/migrations/037_role_rename.js | 4 +- test/migrations/038_role_drop.js | 14 +- test/migrations/039_function_create.js | 8 +- test/migrations/040_function_rename.js | 6 +- test/migrations/041_function_test.js | 8 +- test/migrations/042_function_drop.js | 14 +- test/migrations/043_trigger_create_rename.js | 12 +- test/migrations/044_trigger_test.js | 10 +- test/migrations/045_trigger_drop.js | 12 +- test/migrations/046_domain_create_rename.js | 8 +- test/migrations/047_domain_check.js | 14 +- test/migrations/048_domain_drop.js | 10 +- test/migrations/049_sequence_create_rename.js | 8 +- test/migrations/050_sequence_test.js | 10 +- test/migrations/051_sequence_alter.js | 6 +- test/migrations/052_sequence_alter_test.js | 10 +- test/migrations/053_sequence_drop.js | 10 +- test/migrations/054_operator_create.js | 10 +- test/migrations/055_operator_test.js | 10 +- test/migrations/056_operator_drop.js | 12 +- test/migrations/057_policy_create.js | 38 +- test/migrations/058_policy_test.js | 20 +- test/migrations/059_policy_drop.js | 6 +- test/migrations/060_column_comment.js | 12 +- test/migrations/061_column_comment_test.js | 12 +- test/migrations/062_view.js | 8 +- test/migrations/063_view_test.js | 6 +- test/migrations/064_alter_view_column.js | 8 +- test/migrations/065_materialized_view.js | 14 +- test/migrations/066_materialized_view_test.js | 6 +- .../migrations/067_materialized_view_alter.js | 6 +- test/migrations/068_extension.js | 12 +- test/migrations/069_comments.js | 8 +- test/migrations/070_extension_schema.js | 6 +- .../071_constraint_name_for_foreign_key.js | 8 +- test/migrations/072_alter_column_comment.js | 22 +- .../073_alter_column_comment_test.js | 12 +- test/migrations/074_rename_type_value.js | 26 +- test/migrations/075_drop_index_schema.js | 22 +- test/migrations/076_create_table_like.js | 8 +- .../077_create_table_generated_column.js | 26 +- .../078_add_column_if_not_exists.js | 14 +- test/migrations/079_drop_index_schema.js | 24 +- ...80_create_table_generated_column_take_2.js | 34 +- test/migrations/081_temporary_table.js | 18 +- test/migrations/082_view_options.js | 18 +- test/migrations/083_alter_column_sequence.js | 30 +- test/migrations/084_drop_unique_index.js | 12 +- test/roles-test.ts | 24 +- test/sqlMigration-test.ts | 136 ++-- test/tables-test.ts | 247 ++++---- test/ts/customRunner.ts | 52 +- test/ts/customRunnerDBClient.ts | 16 +- test/ts/customRunnerDBUrl.ts | 13 +- test/ts/customRunnerUndefCount.ts | 10 +- test/ts/migrations/1-test-migration.ts | 8 +- test/ts/migrations/2-test-migration.ts | 6 +- test/utils-test.ts | 156 ++--- test/utils.ts | 8 +- 159 files changed, 4474 insertions(+), 3294 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 81a92c2e..8d75d872 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -36,4 +36,4 @@ module.exports = { }, }, ], -} +}; diff --git a/README.md b/README.md index ff6c0e1f..5b521a59 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ exports.up = (pgm) => { notNull: true, default: pgm.func('current_timestamp'), }, - }) + }); pgm.createTable('posts', { id: 'id', userId: { @@ -56,9 +56,9 @@ exports.up = (pgm) => { notNull: true, default: pgm.func('current_timestamp'), }, - }) - pgm.createIndex('posts', 'userId') -} + }); + pgm.createIndex('posts', 'userId'); +}; ``` Save migration file. @@ -76,8 +76,8 @@ Run `npm run migrate create posts lead`, edit `xxx_posts_lead.js`: exports.up = (pgm) => { pgm.addColumns('posts', { lead: { type: 'text', notNull: true }, - }) -} + }); +}; ``` Run `npm run migrate up` and there will be new column in `posts` table :tada: :tada: diff --git a/bin/node-pg-migrate b/bin/node-pg-migrate index a8f1d5b5..959f262a 100755 --- a/bin/node-pg-migrate +++ b/bin/node-pg-migrate @@ -1,56 +1,56 @@ #!/usr/bin/env node /* eslint-disable strict, no-console */ -'use strict' +'use strict'; -const fs = require('fs') -const util = require('util') -const path = require('path') -const yargs = require('yargs') -const ConnectionParameters = require('pg/lib/connection-parameters') -const { default: migrationRunner, Migration } = require('../dist') +const fs = require('fs'); +const util = require('util'); +const path = require('path'); +const yargs = require('yargs'); +const ConnectionParameters = require('pg/lib/connection-parameters'); +const { default: migrationRunner, Migration } = require('../dist'); process.on('uncaughtException', (err) => { - console.error(err) - process.exit(1) -}) + console.error(err); + process.exit(1); +}); function tryRequire(moduleName) { try { // eslint-disable-next-line import/no-dynamic-require,global-require,security/detect-non-literal-require - return require(moduleName) + return require(moduleName); } catch (err) { if (err.code !== 'MODULE_NOT_FOUND') { - throw err + throw err; } - return null + return null; } } -const schemaArg = 'schema' -const createSchemaArg = 'create-schema' -const databaseUrlVarArg = 'database-url-var' -const migrationsDirArg = 'migrations-dir' -const migrationsTableArg = 'migrations-table' -const migrationsSchemaArg = 'migrations-schema' -const createMigrationsSchemaArg = 'create-migrations-schema' -const migrationFileLanguageArg = 'migration-file-language' -const migrationFilenameFormatArg = 'migration-filename-format' -const templateFileNameArg = 'template-file-name' -const checkOrderArg = 'check-order' -const configValueArg = 'config-value' -const configFileArg = 'config-file' -const ignorePatternArg = 'ignore-pattern' -const singleTransactionArg = 'single-transaction' -const lockArg = 'lock' -const timestampArg = 'timestamp' -const dryRunArg = 'dry-run' -const fakeArg = 'fake' -const decamelizeArg = 'decamelize' -const tsconfigArg = 'tsconfig' -const verboseArg = 'verbose' -const rejectUnauthorizedArg = 'reject-unauthorized' -const envPathArg = 'envPath' +const schemaArg = 'schema'; +const createSchemaArg = 'create-schema'; +const databaseUrlVarArg = 'database-url-var'; +const migrationsDirArg = 'migrations-dir'; +const migrationsTableArg = 'migrations-table'; +const migrationsSchemaArg = 'migrations-schema'; +const createMigrationsSchemaArg = 'create-migrations-schema'; +const migrationFileLanguageArg = 'migration-file-language'; +const migrationFilenameFormatArg = 'migration-filename-format'; +const templateFileNameArg = 'template-file-name'; +const checkOrderArg = 'check-order'; +const configValueArg = 'config-value'; +const configFileArg = 'config-file'; +const ignorePatternArg = 'ignore-pattern'; +const singleTransactionArg = 'single-transaction'; +const lockArg = 'lock'; +const timestampArg = 'timestamp'; +const dryRunArg = 'dry-run'; +const fakeArg = 'fake'; +const decamelizeArg = 'decamelize'; +const tsconfigArg = 'tsconfig'; +const verboseArg = 'verbose'; +const rejectUnauthorizedArg = 'reject-unauthorized'; +const envPathArg = 'envPath'; const { argv } = yargs .usage('Usage: $0 [up|down|create|redo] [migrationName] [options]') @@ -79,7 +79,8 @@ const { argv } = yargs .option('s', { alias: schemaArg, defaultDescription: '"public"', - describe: 'The schema on which migration will be run (defaults to `public`)', + describe: + 'The schema on which migration will be run (defaults to `public`)', type: 'string', array: true, }) @@ -142,14 +143,16 @@ const { argv } = yargs alias: migrationFileLanguageArg, defaultDescription: 'last one used or "js" if there is no migration yet', choices: ['js', 'ts', 'sql'], - describe: 'Language of the migration file (Only valid with the create action)', + describe: + 'Language of the migration file (Only valid with the create action)', type: 'string', }) .option(migrationFilenameFormatArg, { defaultDescription: '"timestamp"', choices: ['timestamp', 'utc'], - describe: 'Prefix type of migration filename (Only valid with the create action)', + describe: + 'Prefix type of migration filename (Only valid with the create action)', type: 'string', }) @@ -207,100 +210,134 @@ const { argv } = yargs .version() .alias('version', 'i') - .help() + .help(); if (argv.help || argv._.length === 0) { - yargs.showHelp() - process.exit(1) + yargs.showHelp(); + process.exit(1); } /* Load env before accessing process.env */ -const envPath = argv[envPathArg] +const envPath = argv[envPathArg]; // Create default dotenv config -const dotenvConfig = { silent: true } +const dotenvConfig = { silent: true }; // If the path has been configured, add it to the config, otherwise don't change the default dotenv path if (envPath) { - dotenvConfig.path = envPath + dotenvConfig.path = envPath; } -const dotenv = tryRequire('dotenv') +const dotenv = tryRequire('dotenv'); if (dotenv) { // Load config from ".env" file - const myEnv = dotenv.config(dotenvConfig) - const dotenvExpand = tryRequire('dotenv-expand') + const myEnv = dotenv.config(dotenvConfig); + const dotenvExpand = tryRequire('dotenv-expand'); if (dotenvExpand && dotenvExpand.expand) { - dotenvExpand.expand(myEnv) + dotenvExpand.expand(myEnv); } } -let MIGRATIONS_DIR = argv[migrationsDirArg] -let DB_CONNECTION = process.env[argv[databaseUrlVarArg]] -let IGNORE_PATTERN = argv[ignorePatternArg] -let SCHEMA = argv[schemaArg] -let CREATE_SCHEMA = argv[createSchemaArg] -let MIGRATIONS_SCHEMA = argv[migrationsSchemaArg] -let CREATE_MIGRATIONS_SCHEMA = argv[createMigrationsSchemaArg] -let MIGRATIONS_TABLE = argv[migrationsTableArg] -let MIGRATIONS_FILE_LANGUAGE = argv[migrationFileLanguageArg] -let MIGRATIONS_FILENAME_FORMAT = argv[migrationFilenameFormatArg] -let TEMPLATE_FILE_NAME = argv[templateFileNameArg] -let CHECK_ORDER = argv[checkOrderArg] -let VERBOSE = argv[verboseArg] -let DECAMELIZE = argv[decamelizeArg] -let tsconfigPath = argv[tsconfigArg] +let MIGRATIONS_DIR = argv[migrationsDirArg]; +let DB_CONNECTION = process.env[argv[databaseUrlVarArg]]; +let IGNORE_PATTERN = argv[ignorePatternArg]; +let SCHEMA = argv[schemaArg]; +let CREATE_SCHEMA = argv[createSchemaArg]; +let MIGRATIONS_SCHEMA = argv[migrationsSchemaArg]; +let CREATE_MIGRATIONS_SCHEMA = argv[createMigrationsSchemaArg]; +let MIGRATIONS_TABLE = argv[migrationsTableArg]; +let MIGRATIONS_FILE_LANGUAGE = argv[migrationFileLanguageArg]; +let MIGRATIONS_FILENAME_FORMAT = argv[migrationFilenameFormatArg]; +let TEMPLATE_FILE_NAME = argv[templateFileNameArg]; +let CHECK_ORDER = argv[checkOrderArg]; +let VERBOSE = argv[verboseArg]; +let DECAMELIZE = argv[decamelizeArg]; +let tsconfigPath = argv[tsconfigArg]; function readTsconfig() { if (tsconfigPath) { - let tsconfig - const json5 = tryRequire('json5') + let tsconfig; + const json5 = tryRequire('json5'); try { // eslint-disable-next-line security/detect-non-literal-fs-filename - const config = fs.readFileSync(path.resolve(process.cwd(), tsconfigPath), { encoding: 'utf-8' }) - tsconfig = json5 ? json5.parse(config) : JSON.parse(config) + const config = fs.readFileSync( + path.resolve(process.cwd(), tsconfigPath), + { encoding: 'utf-8' } + ); + tsconfig = json5 ? json5.parse(config) : JSON.parse(config); } catch (err) { - console.error("Can't load tsconfig.json:", err) + console.error("Can't load tsconfig.json:", err); } - const tsnode = tryRequire('ts-node') + const tsnode = tryRequire('ts-node'); if (!tsnode) { - console.error("For TypeScript support, please install 'ts-node' module") + console.error("For TypeScript support, please install 'ts-node' module"); } if (tsconfig && tsnode) { - tsnode.register(tsconfig) + tsnode.register(tsconfig); if (!MIGRATIONS_FILE_LANGUAGE) { - MIGRATIONS_FILE_LANGUAGE = 'ts' + MIGRATIONS_FILE_LANGUAGE = 'ts'; } } else { - process.exit(1) + process.exit(1); } } } function readJson(json) { if (typeof json === 'object') { - SCHEMA = typeof SCHEMA !== 'undefined' ? SCHEMA : json[schemaArg] - CREATE_SCHEMA = typeof CREATE_SCHEMA !== 'undefined' ? CREATE_SCHEMA : json[createSchemaArg] - MIGRATIONS_DIR = typeof MIGRATIONS_DIR !== 'undefined' ? MIGRATIONS_DIR : json[migrationsDirArg] - MIGRATIONS_SCHEMA = typeof MIGRATIONS_SCHEMA !== 'undefined' ? MIGRATIONS_SCHEMA : json[migrationsSchemaArg] + SCHEMA = typeof SCHEMA !== 'undefined' ? SCHEMA : json[schemaArg]; + CREATE_SCHEMA = + typeof CREATE_SCHEMA !== 'undefined' + ? CREATE_SCHEMA + : json[createSchemaArg]; + MIGRATIONS_DIR = + typeof MIGRATIONS_DIR !== 'undefined' + ? MIGRATIONS_DIR + : json[migrationsDirArg]; + MIGRATIONS_SCHEMA = + typeof MIGRATIONS_SCHEMA !== 'undefined' + ? MIGRATIONS_SCHEMA + : json[migrationsSchemaArg]; CREATE_MIGRATIONS_SCHEMA = - typeof CREATE_MIGRATIONS_SCHEMA !== 'undefined' ? CREATE_MIGRATIONS_SCHEMA : json[createMigrationsSchemaArg] - MIGRATIONS_TABLE = typeof MIGRATIONS_TABLE !== 'undefined' ? MIGRATIONS_TABLE : json[migrationsTableArg] + typeof CREATE_MIGRATIONS_SCHEMA !== 'undefined' + ? CREATE_MIGRATIONS_SCHEMA + : json[createMigrationsSchemaArg]; + MIGRATIONS_TABLE = + typeof MIGRATIONS_TABLE !== 'undefined' + ? MIGRATIONS_TABLE + : json[migrationsTableArg]; MIGRATIONS_FILE_LANGUAGE = - typeof MIGRATIONS_FILE_LANGUAGE !== 'undefined' ? MIGRATIONS_FILE_LANGUAGE : json[migrationFileLanguageArg] + typeof MIGRATIONS_FILE_LANGUAGE !== 'undefined' + ? MIGRATIONS_FILE_LANGUAGE + : json[migrationFileLanguageArg]; MIGRATIONS_FILENAME_FORMAT = - typeof MIGRATIONS_FILENAME_FORMAT !== 'undefined' ? MIGRATIONS_FILENAME_FORMAT : json[migrationFilenameFormatArg] - TEMPLATE_FILE_NAME = typeof TEMPLATE_FILE_NAME !== 'undefined' ? TEMPLATE_FILE_NAME : json[templateFileNameArg] - IGNORE_PATTERN = typeof IGNORE_PATTERN !== 'undefined' ? IGNORE_PATTERN : json[ignorePatternArg] - CHECK_ORDER = typeof CHECK_ORDER !== 'undefined' ? CHECK_ORDER : json[checkOrderArg] - VERBOSE = typeof VERBOSE !== 'undefined' ? VERBOSE : json[verboseArg] - DECAMELIZE = typeof DECAMELIZE !== 'undefined' ? DECAMELIZE : json[decamelizeArg] - DB_CONNECTION = typeof DB_CONNECTION !== 'undefined' ? DB_CONNECTION : process.env[json[databaseUrlVarArg]] - tsconfigPath = typeof tsconfigPath !== 'undefined' ? tsconfigPath : json[tsconfigArg] + typeof MIGRATIONS_FILENAME_FORMAT !== 'undefined' + ? MIGRATIONS_FILENAME_FORMAT + : json[migrationFilenameFormatArg]; + TEMPLATE_FILE_NAME = + typeof TEMPLATE_FILE_NAME !== 'undefined' + ? TEMPLATE_FILE_NAME + : json[templateFileNameArg]; + IGNORE_PATTERN = + typeof IGNORE_PATTERN !== 'undefined' + ? IGNORE_PATTERN + : json[ignorePatternArg]; + CHECK_ORDER = + typeof CHECK_ORDER !== 'undefined' ? CHECK_ORDER : json[checkOrderArg]; + VERBOSE = typeof VERBOSE !== 'undefined' ? VERBOSE : json[verboseArg]; + DECAMELIZE = + typeof DECAMELIZE !== 'undefined' ? DECAMELIZE : json[decamelizeArg]; + DB_CONNECTION = + typeof DB_CONNECTION !== 'undefined' + ? DB_CONNECTION + : process.env[json[databaseUrlVarArg]]; + tsconfigPath = + typeof tsconfigPath !== 'undefined' ? tsconfigPath : json[tsconfigArg]; if (json.url) { - DB_CONNECTION = typeof DB_CONNECTION !== 'undefined' ? DB_CONNECTION : json.url + DB_CONNECTION = + typeof DB_CONNECTION !== 'undefined' ? DB_CONNECTION : json.url; } else if (json.host || json.port || json.name || json.database) { DB_CONNECTION = typeof DB_CONNECTION !== 'undefined' @@ -312,51 +349,56 @@ function readJson(json) { password: json.password, port: json.port || 5432, ssl: json.ssl, - } + }; } } else { - DB_CONNECTION = typeof DB_CONNECTION !== 'undefined' ? DB_CONNECTION : json + DB_CONNECTION = typeof DB_CONNECTION !== 'undefined' ? DB_CONNECTION : json; } } // Load config (and suppress the no-config-warning) -const oldSuppressWarning = process.env.SUPPRESS_NO_CONFIG_WARNING -process.env.SUPPRESS_NO_CONFIG_WARNING = 1 -const config = tryRequire('config') +const oldSuppressWarning = process.env.SUPPRESS_NO_CONFIG_WARNING; +process.env.SUPPRESS_NO_CONFIG_WARNING = 1; +const config = tryRequire('config'); if (config && config.has(argv[configValueArg])) { - const db = config.get(argv[configValueArg]) - readJson(db) + const db = config.get(argv[configValueArg]); + readJson(db); } -process.env.SUPPRESS_NO_CONFIG_WARNING = oldSuppressWarning +process.env.SUPPRESS_NO_CONFIG_WARNING = oldSuppressWarning; -const configFileName = argv[configFileArg] +const configFileName = argv[configFileArg]; if (configFileName) { // eslint-disable-next-line global-require,import/no-dynamic-require,security/detect-non-literal-require - const jsonConfig = require(path.resolve(configFileName)) - readJson(jsonConfig) + const jsonConfig = require(path.resolve(configFileName)); + readJson(jsonConfig); } -readTsconfig() +readTsconfig(); -const action = argv._.shift() +const action = argv._.shift(); // defaults -MIGRATIONS_DIR = typeof MIGRATIONS_DIR === 'undefined' ? `${process.cwd()}/migrations` : MIGRATIONS_DIR -MIGRATIONS_TABLE = typeof MIGRATIONS_TABLE === 'undefined' ? 'pgmigrations' : MIGRATIONS_TABLE -SCHEMA = typeof SCHEMA === 'undefined' ? 'public' : SCHEMA -IGNORE_PATTERN = typeof IGNORE_PATTERN === 'undefined' ? '\\..*' : IGNORE_PATTERN -CHECK_ORDER = typeof CHECK_ORDER === 'undefined' ? true : CHECK_ORDER -VERBOSE = typeof VERBOSE === 'undefined' ? true : VERBOSE +MIGRATIONS_DIR = + typeof MIGRATIONS_DIR === 'undefined' + ? `${process.cwd()}/migrations` + : MIGRATIONS_DIR; +MIGRATIONS_TABLE = + typeof MIGRATIONS_TABLE === 'undefined' ? 'pgmigrations' : MIGRATIONS_TABLE; +SCHEMA = typeof SCHEMA === 'undefined' ? 'public' : SCHEMA; +IGNORE_PATTERN = + typeof IGNORE_PATTERN === 'undefined' ? '\\..*' : IGNORE_PATTERN; +CHECK_ORDER = typeof CHECK_ORDER === 'undefined' ? true : CHECK_ORDER; +VERBOSE = typeof VERBOSE === 'undefined' ? true : VERBOSE; if (action === 'create') { // replaces spaces with dashes - should help fix some errors - let newMigrationName = argv._.length ? argv._.join('-') : '' + let newMigrationName = argv._.length ? argv._.join('-') : ''; // forces use of dashes in names - keep thing clean - newMigrationName = newMigrationName.replace(/[_ ]+/g, '-') + newMigrationName = newMigrationName.replace(/[_ ]+/g, '-'); if (!newMigrationName) { - console.error("'migrationName' is required.") - yargs.showHelp() - process.exit(1) + console.error("'migrationName' is required."); + yargs.showHelp(); + process.exit(1); } Migration.create(newMigrationName, MIGRATIONS_DIR, { @@ -369,60 +411,67 @@ if (action === 'create') { }), }) .then((migrationPath) => { - console.log(util.format('Created migration -- %s', migrationPath)) - process.exit(0) + console.log(util.format('Created migration -- %s', migrationPath)); + process.exit(0); }) .catch((err) => { - console.error(err) - process.exit(1) - }) + console.error(err); + process.exit(1); + }); } else if (action === 'up' || action === 'down' || action === 'redo') { if (!DB_CONNECTION) { - const cp = new ConnectionParameters() + const cp = new ConnectionParameters(); if (!cp.host && !cp.port && !cp.database) { - console.error(`The $${argv[databaseUrlVarArg]} environment variable is not set.`) - process.exit(1) + console.error( + `The $${argv[databaseUrlVarArg]} environment variable is not set.` + ); + process.exit(1); } - DB_CONNECTION = cp + DB_CONNECTION = cp; } - const dryRun = argv[dryRunArg] + const dryRun = argv[dryRunArg]; if (dryRun) { - console.log('dry run') + console.log('dry run'); } - const singleTransaction = argv[singleTransactionArg] - const fake = argv[fakeArg] - const TIMESTAMP = argv[timestampArg] - const rejectUnauthorized = argv[rejectUnauthorizedArg] - const noLock = !argv[lockArg] + const singleTransaction = argv[singleTransactionArg]; + const fake = argv[fakeArg]; + const TIMESTAMP = argv[timestampArg]; + const rejectUnauthorized = argv[rejectUnauthorizedArg]; + const noLock = !argv[lockArg]; if (noLock) { - console.log('no lock') + console.log('no lock'); } - const updownArg = argv._.length ? argv._[0] : null - let numMigrations - let migrationName + const updownArg = argv._.length ? argv._[0] : null; + let numMigrations; + let migrationName; if (updownArg !== null) { // eslint-disable-next-line eqeqeq if (parseInt(updownArg, 10) == updownArg) { - numMigrations = parseInt(updownArg, 10) + numMigrations = parseInt(updownArg, 10); } else { - migrationName = argv._.join('-').replace(/_ /g, '-') + migrationName = argv._.join('-').replace(/_ /g, '-'); } } - const databaseUrl = typeof DB_CONNECTION === 'string' ? { connectionString: DB_CONNECTION } : DB_CONNECTION + const databaseUrl = + typeof DB_CONNECTION === 'string' + ? { connectionString: DB_CONNECTION } + : DB_CONNECTION; const options = (direction, _count, _timestamp) => { - const count = _count === undefined ? numMigrations : _count - const timestamp = _timestamp === undefined ? TIMESTAMP : _timestamp + const count = _count === undefined ? numMigrations : _count; + const timestamp = _timestamp === undefined ? TIMESTAMP : _timestamp; return { dryRun, databaseUrl: { ...databaseUrl, - ...(typeof rejectUnauthorized === 'boolean' ? { ssl: { ...databaseUrl.ssl, rejectUnauthorized } } : undefined), + ...(typeof rejectUnauthorized === 'boolean' + ? { ssl: { ...databaseUrl.ssl, rejectUnauthorized } } + : undefined), }, dir: MIGRATIONS_DIR, ignorePattern: IGNORE_PATTERN, @@ -441,28 +490,30 @@ if (action === 'create') { noLock, fake, decamelize: DECAMELIZE, - } - } + }; + }; const promise = action === 'redo' - ? migrationRunner(options('down')).then(() => migrationRunner(options('up', Infinity, false))) - : migrationRunner(options(action)) + ? migrationRunner(options('down')).then(() => + migrationRunner(options('up', Infinity, false)) + ) + : migrationRunner(options(action)); promise .then(() => { - console.log('Migrations complete!') - process.exit(0) + console.log('Migrations complete!'); + process.exit(0); }) .catch((err) => { - console.error(err) - process.exit(1) - }) + console.error(err); + process.exit(1); + }); } else { - console.error('Invalid Action: Must be [up|down|create|redo].') - yargs.showHelp() - process.exit(1) + console.error('Invalid Action: Must be [up|down|create|redo].'); + yargs.showHelp(); + process.exit(1); } if (argv['force-exit']) { - console.log('Forcing exit') - process.exit(0) + console.log('Forcing exit'); + process.exit(0); } diff --git a/docs/README.md b/docs/README.md index d54a70b3..278557df 100644 --- a/docs/README.md +++ b/docs/README.md @@ -43,7 +43,7 @@ exports.up = (pgm) => { notNull: true, default: pgm.func('current_timestamp'), }, - }) + }); pgm.createTable('posts', { id: 'id', userId: { @@ -58,9 +58,9 @@ exports.up = (pgm) => { notNull: true, default: pgm.func('current_timestamp'), }, - }) - pgm.createIndex('posts', 'userId') -} + }); + pgm.createIndex('posts', 'userId'); +}; ``` Save migration file. @@ -78,8 +78,8 @@ Run `npm run migrate create posts lead`, edit `xxx_posts_lead.js`: exports.up = (pgm) => { pgm.addColumns('posts', { lead: { type: 'text', notNull: true }, - }) -} + }); +}; ``` Run `npm run migrate up` and there will be new column in `posts` table :tada: :tada: diff --git a/docs/index.html b/docs/index.html index f161c43b..1d8b8ec4 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,10 +1,16 @@ - + - node-pg-migrate - Postgresql database migration management tool for node.js + + node-pg-migrate - Postgresql database migration management tool for + node.js + - + diff --git a/docs/migrations.md b/docs/migrations.md index 122c8fa9..14b71990 100644 --- a/docs/migrations.md +++ b/docs/migrations.md @@ -3,11 +3,11 @@ When you run `node-pg-migrate create` a new migration file is created that looks like this: ```javascript -exports.shorthands = undefined +exports.shorthands = undefined; -exports.up = function up(pgm) {} +exports.up = function up(pgm) {}; -exports.down = function down(pgm) {} +exports.down = function down(pgm) {}; ``` `pgm` is a helper object that provides migration operations and `run` is the callback to call when you are done. @@ -32,9 +32,9 @@ In some cases, you may want to perform some async operation during a migration, ```javascript exports.up = function up(pgm, run) { doSomethingAsync(function () { - run() - }) -} + run(); + }); +}; ``` Another way how to perform some async operation is to return [Promise](https://promisesaplus.com/) from `up` or `down` function. Example: @@ -43,9 +43,9 @@ Another way how to perform some async operation is to return [Promise](https://p exports.up = function (pgm) { return new Promise((resolve) => { // doSomethingAsync - resolve() - }) -} + resolve(); + }); +}; ``` or @@ -53,7 +53,7 @@ or ```javascript exports.up = async (pgm) => { // doSomethingAsync -} +}; ``` ### Using schemas @@ -73,7 +73,7 @@ CREATE TABLE "my_schema"."my_table_name" ( #### Type ```ts -type Name = string | { schema: string; name: string } +type Name = string | { schema: string; name: string }; ``` ### Locking diff --git a/mocha.bootstrap.js b/mocha.bootstrap.js index f86f2683..bcc07973 100644 --- a/mocha.bootstrap.js +++ b/mocha.bootstrap.js @@ -1,15 +1,15 @@ /* eslint import/no-extraneous-dependencies: ["error", {"devDependencies": true}] */ -const chai = require('chai') -const sinonChai = require('sinon-chai') -const chaiAsPromised = require('chai-as-promised') +const chai = require('chai'); +const sinonChai = require('sinon-chai'); +const chaiAsPromised = require('chai-as-promised'); -const config = require('./tsconfig-test.json') +const config = require('./tsconfig-test.json'); -config.compilerOptions.module = 'commonjs' -config.transpileOnly = true +config.compilerOptions.module = 'commonjs'; +config.transpileOnly = true; // eslint-disable-next-line import/no-extraneous-dependencies -require('ts-node').register(config) +require('ts-node').register(config); -chai.use(sinonChai) -chai.use(chaiAsPromised) +chai.use(sinonChai); +chai.use(chaiAsPromised); diff --git a/src/db.ts b/src/db.ts index 5ca78969..e9d5a341 100644 --- a/src/db.ts +++ b/src/db.ts @@ -1,21 +1,37 @@ /* This file just manages the database connection and provides a query method */ -import { inspect } from 'util' -import { ClientBase, Client, ClientConfig, QueryArrayResult, QueryResult, QueryArrayConfig, QueryConfig } from 'pg' -import { Logger, DB } from './types' +import { + Client, + ClientBase, + ClientConfig, + QueryArrayConfig, + QueryArrayResult, + QueryConfig, + QueryResult, +} from 'pg'; +import { inspect } from 'util'; +import { DB, Logger } from './types'; /* eslint-disable @typescript-eslint/no-explicit-any */ export interface DBConnection extends DB { - createConnection(): Promise + createConnection(): Promise; - column(columnName: string, queryConfig: QueryArrayConfig, values?: any[]): Promise - column(columnName: string, queryConfig: QueryConfig): Promise - column(columnName: string, queryTextOrConfig: string | QueryConfig, values?: any[]): Promise + column( + columnName: string, + queryConfig: QueryArrayConfig, + values?: any[] + ): Promise; + column(columnName: string, queryConfig: QueryConfig): Promise; + column( + columnName: string, + queryTextOrConfig: string | QueryConfig, + values?: any[] + ): Promise; - connected: () => boolean - addBeforeCloseListener: (listener: any) => number - close(): Promise + connected: () => boolean; + addBeforeCloseListener: (listener: any) => number; + close(): Promise; } enum ConnectionStatus { @@ -24,82 +40,95 @@ enum ConnectionStatus { ERROR = 'ERROR', } -const db = (connection: ClientBase | string | ClientConfig, logger: Logger = console): DBConnection => { +const db = ( + connection: ClientBase | string | ClientConfig, + logger: Logger = console +): DBConnection => { const isExternalClient = - typeof connection === 'object' && 'query' in connection && typeof connection.query === 'function' - let connectionStatus = ConnectionStatus.DISCONNECTED + typeof connection === 'object' && + 'query' in connection && + typeof connection.query === 'function'; + let connectionStatus = ConnectionStatus.DISCONNECTED; - const client: Client = isExternalClient ? (connection as Client) : new Client(connection as string | ClientConfig) + const client: Client = isExternalClient + ? (connection as Client) + : new Client(connection as string | ClientConfig); - const beforeCloseListeners: any[] = [] + const beforeCloseListeners: any[] = []; const createConnection: () => Promise = () => new Promise((resolve, reject) => { if (isExternalClient || connectionStatus === ConnectionStatus.CONNECTED) { - resolve() + resolve(); } else if (connectionStatus === ConnectionStatus.ERROR) { - reject(new Error('Connection already failed, do not try to connect again')) + reject( + new Error('Connection already failed, do not try to connect again') + ); } else { client.connect((err) => { if (err) { - connectionStatus = ConnectionStatus.ERROR - logger.error(`could not connect to postgres: ${inspect(err)}`) - return reject(err) + connectionStatus = ConnectionStatus.ERROR; + logger.error(`could not connect to postgres: ${inspect(err)}`); + return reject(err); } - connectionStatus = ConnectionStatus.CONNECTED - return resolve() - }) + connectionStatus = ConnectionStatus.CONNECTED; + return resolve(); + }); } - }) + }); const query: DBConnection['query'] = async ( queryTextOrConfig: string | QueryConfig | QueryArrayConfig, - values?: any[], + values?: any[] ): Promise => { - await createConnection() + await createConnection(); try { - return await client.query(queryTextOrConfig, values) + return await client.query(queryTextOrConfig, values); } catch (err: any) { - const { message, position }: { message: string; position: number } = err - const string: string = typeof queryTextOrConfig === 'string' ? queryTextOrConfig : queryTextOrConfig.text + const { message, position }: { message: string; position: number } = err; + const string: string = + typeof queryTextOrConfig === 'string' + ? queryTextOrConfig + : queryTextOrConfig.text; if (message && position >= 1) { - const endLineWrapIndexOf = string.indexOf('\n', position) - const endLineWrapPos = endLineWrapIndexOf >= 0 ? endLineWrapIndexOf : string.length - const stringStart = string.substring(0, endLineWrapPos) - const stringEnd = string.substr(endLineWrapPos) - const startLineWrapPos = stringStart.lastIndexOf('\n') + 1 - const padding = ' '.repeat(position - startLineWrapPos - 1) + const endLineWrapIndexOf = string.indexOf('\n', position); + const endLineWrapPos = + endLineWrapIndexOf >= 0 ? endLineWrapIndexOf : string.length; + const stringStart = string.substring(0, endLineWrapPos); + const stringEnd = string.substr(endLineWrapPos); + const startLineWrapPos = stringStart.lastIndexOf('\n') + 1; + const padding = ' '.repeat(position - startLineWrapPos - 1); logger.error(`Error executing: ${stringStart} ${padding}^^^^${stringEnd} ${message} -`) +`); } else { logger.error(`Error executing: ${string} ${err} -`) +`); } - throw err + throw err; } - } + }; const select: DBConnection['select'] = async ( queryTextOrConfig: string | QueryConfig | QueryArrayConfig, - values?: any[], + values?: any[] ) => { - const { rows } = await query(queryTextOrConfig, values) - return rows - } + const { rows } = await query(queryTextOrConfig, values); + return rows; + }; const column: DBConnection['column'] = async ( columnName: string, queryTextOrConfig: string | QueryConfig | QueryArrayConfig, - values?: any[], + values?: any[] ) => { - const rows = await select(queryTextOrConfig, values) - return rows.map((r: { [key: string]: any }) => r[columnName]) - } + const rows = await select(queryTextOrConfig, values); + return rows.map((r: { [key: string]: any }) => r[columnName]); + }; return { createConnection, @@ -111,15 +140,18 @@ ${err} addBeforeCloseListener: (listener) => beforeCloseListeners.push(listener), close: async () => { await beforeCloseListeners.reduce( - (promise, listener) => promise.then(listener).catch((err: any) => logger.error(err.stack || err)), - Promise.resolve(), - ) + (promise, listener) => + promise + .then(listener) + .catch((err: any) => logger.error(err.stack || err)), + Promise.resolve() + ); if (!isExternalClient) { - connectionStatus = ConnectionStatus.DISCONNECTED - client.end() + connectionStatus = ConnectionStatus.DISCONNECTED; + client.end(); } }, - } -} + }; +}; -export default db +export default db; diff --git a/src/index.ts b/src/index.ts index 34053e4a..381e97b1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,122 +1,148 @@ -import runner from './runner' -import { Migration } from './migration' -import { RunnerOption, MigrationBuilder, PgType } from './types' -import PgLiteral from './operations/PgLiteral' -import { - PgLiteralValue, - Value, - Name, - Type, - IfExistsOption, - IfNotExistsOption, - CascadeOption, - DropOptions, -} from './operations/generalTypes' +import { Migration } from './migration'; import { + AlterDomain, CreateDomain, + DomainOptionsAlter, + DomainOptionsCreate, DropDomain, - AlterDomain, RenameDomain, - DomainOptionsCreate, - DomainOptionsAlter, -} from './operations/domainsTypes' -import { CreateExtension, DropExtension, Extension, CreateExtensionOptions } from './operations/extensionsTypes' +} from './operations/domainsTypes'; +import { + CreateExtension, + CreateExtensionOptions, + DropExtension, + Extension, +} from './operations/extensionsTypes'; import { CreateFunction, DropFunction, - RenameFunction, - FunctionParam, FunctionOptions, -} from './operations/functionsTypes' -import { DropIndex, CreateIndex, CreateIndexOptions, DropIndexOptions } from './operations/indexesTypes' + FunctionParam, + RenameFunction, +} from './operations/functionsTypes'; +import { + CascadeOption, + DropOptions, + IfExistsOption, + IfNotExistsOption, + Name, + PgLiteralValue, + Type, + Value, +} from './operations/generalTypes'; +import { + CreateIndex, + CreateIndexOptions, + DropIndex, + DropIndexOptions, +} from './operations/indexesTypes'; import { + AddToOperatorFamily, CreateOperator, - DropOperator, CreateOperatorClass, - DropOperatorClass, + CreateOperatorClassOptions, CreateOperatorFamily, - DropOperatorFamily, - AddToOperatorFamily, - RenameOperatorFamily, - RenameOperatorClass, - RemoveFromOperatorFamily, CreateOperatorOptions, + DropOperator, + DropOperatorClass, + DropOperatorFamily, DropOperatorOptions, OperatorListDefinition, - CreateOperatorClassOptions, -} from './operations/operatorsTypes' -import { Sql } from './operations/othersTypes' + RemoveFromOperatorFamily, + RenameOperatorClass, + RenameOperatorFamily, +} from './operations/operatorsTypes'; +import { Sql } from './operations/othersTypes'; +import PgLiteral from './operations/PgLiteral'; import { - CreatePolicy, - DropPolicy, AlterPolicy, - RenamePolicy, + CreatePolicy, CreatePolicyOptions, + DropPolicy, PolicyOptions, -} from './operations/policiesTypes' -import { CreateRole, DropRole, AlterRole, RenameRole, RoleOptions } from './operations/rolesTypes' + RenamePolicy, +} from './operations/policiesTypes'; +import { + AlterRole, + CreateRole, + DropRole, + RenameRole, + RoleOptions, +} from './operations/rolesTypes'; +import { + CreateSchema, + CreateSchemaOptions, + DropSchema, + RenameSchema, +} from './operations/schemasTypes'; import { + AlterSequence, CreateSequence, DropSequence, - AlterSequence, RenameSequence, - SequenceOptionsCreate, SequenceOptionsAlter, -} from './operations/sequencesTypes' -import { CreateSchema, DropSchema, RenameSchema, CreateSchemaOptions } from './operations/schemasTypes' + SequenceOptionsCreate, +} from './operations/sequencesTypes'; import { - CreateTable, - DropTable, - AlterTable, - RenameTable, AddColumns, - DropColumns, AlterColumn, - RenameColumn, + AlterColumnOptions, + AlterTable, + AlterTableOptions, + ColumnDefinition, + ColumnDefinitions, + ConstraintOptions, CreateConstraint, + CreateTable, + DropColumns, DropConstraint, + DropTable, + RenameColumn, RenameConstraint, - ColumnDefinition, - ColumnDefinitions, + RenameTable, TableOptions, - AlterTableOptions, - AlterColumnOptions, - ConstraintOptions, -} from './operations/tablesTypes' -import { CreateTrigger, DropTrigger, RenameTrigger, TriggerOptions } from './operations/triggersTypes' +} from './operations/tablesTypes'; import { + CreateTrigger, + DropTrigger, + RenameTrigger, + TriggerOptions, +} from './operations/triggersTypes'; +import { + AddTypeAttribute, + AddTypeValue, + AddTypeValueOptions, CreateType, DropType, - RenameType, - AddTypeAttribute, DropTypeAttribute, - SetTypeAttribute, - AddTypeValue, + RenameType, RenameTypeAttribute, RenameTypeValue, - AddTypeValueOptions, -} from './operations/typesTypes' -import { - CreateView, - DropView, - AlterView, - AlterViewColumn, - RenameView, - CreateViewOptions, - AlterViewOptions, - AlterViewColumnOptions, -} from './operations/viewsTypes' + SetTypeAttribute, +} from './operations/typesTypes'; import { + AlterMaterializedView, + AlterMaterializedViewOptions, CreateMaterializedView, + CreateMaterializedViewOptions, DropMaterializedView, - AlterMaterializedView, - RenameMaterializedView, - RenameMaterializedViewColumn, RefreshMaterializedView, - CreateMaterializedViewOptions, - AlterMaterializedViewOptions, RefreshMaterializedViewOptions, -} from './operations/viewsMaterializedTypes' + RenameMaterializedView, + RenameMaterializedViewColumn, +} from './operations/viewsMaterializedTypes'; +import { + AlterView, + AlterViewColumn, + AlterViewColumnOptions, + AlterViewOptions, + CreateView, + CreateViewOptions, + DropView, + RenameView, +} from './operations/viewsTypes'; +import runner from './runner'; +import { MigrationBuilder, PgType, RunnerOption } from './types'; export { PgLiteral, @@ -235,6 +261,6 @@ export { CreateMaterializedViewOptions, AlterMaterializedViewOptions, RefreshMaterializedViewOptions, -} +}; -export default runner +export default runner; diff --git a/src/migration-builder.ts b/src/migration-builder.ts index 9a36a4e8..ab18ffcf 100644 --- a/src/migration-builder.ts +++ b/src/migration-builder.ts @@ -9,201 +9,315 @@ and it makes inference of down migrations possible. */ -import { createSchemalize } from './utils' -import { ColumnDefinitions } from './operations/tablesTypes' -import { DB, MigrationBuilder, MigrationOptions, Logger } from './types' - -import * as domains from './operations/domains' -import * as extensions from './operations/extensions' -import * as functions from './operations/functions' -import * as indexes from './operations/indexes' -import * as operators from './operations/operators' -import * as other from './operations/other' -import * as policies from './operations/policies' -import * as roles from './operations/roles' -import * as schemas from './operations/schemas' -import * as sequences from './operations/sequences' -import * as tables from './operations/tables' -import * as triggers from './operations/triggers' -import * as types from './operations/types' -import * as views from './operations/views' -import * as mViews from './operations/viewsMaterialized' -import PgLiteral from './operations/PgLiteral' +import * as domains from './operations/domains'; +import * as extensions from './operations/extensions'; +import * as functions from './operations/functions'; +import * as indexes from './operations/indexes'; +import * as operators from './operations/operators'; +import * as other from './operations/other'; +import PgLiteral from './operations/PgLiteral'; +import * as policies from './operations/policies'; +import * as roles from './operations/roles'; +import * as schemas from './operations/schemas'; +import * as sequences from './operations/sequences'; +import * as tables from './operations/tables'; +import { ColumnDefinitions } from './operations/tablesTypes'; +import * as triggers from './operations/triggers'; +import * as types from './operations/types'; +import * as views from './operations/views'; +import * as mViews from './operations/viewsMaterialized'; +import { DB, Logger, MigrationBuilder, MigrationOptions } from './types'; +import { createSchemalize } from './utils'; export default class MigrationBuilderImpl implements MigrationBuilder { - public readonly createExtension: (...args: Parameters) => void + public readonly createExtension: ( + ...args: Parameters + ) => void; - public readonly dropExtension: (...args: Parameters) => void + public readonly dropExtension: ( + ...args: Parameters + ) => void; - public readonly addExtension: (...args: Parameters) => void + public readonly addExtension: ( + ...args: Parameters + ) => void; - public readonly createTable: (...args: Parameters) => void + public readonly createTable: ( + ...args: Parameters + ) => void; - public readonly dropTable: (...args: Parameters) => void + public readonly dropTable: (...args: Parameters) => void; - public readonly renameTable: (...args: Parameters) => void + public readonly renameTable: ( + ...args: Parameters + ) => void; - public readonly alterTable: (...args: Parameters) => void + public readonly alterTable: (...args: Parameters) => void; - public readonly addColumns: (...args: Parameters) => void + public readonly addColumns: (...args: Parameters) => void; - public readonly dropColumns: (...args: Parameters) => void + public readonly dropColumns: ( + ...args: Parameters + ) => void; - public readonly renameColumn: (...args: Parameters) => void + public readonly renameColumn: ( + ...args: Parameters + ) => void; - public readonly alterColumn: (...args: Parameters) => void + public readonly alterColumn: ( + ...args: Parameters + ) => void; - public readonly addColumn: (...args: Parameters) => void + public readonly addColumn: (...args: Parameters) => void; - public readonly dropColumn: (...args: Parameters) => void + public readonly dropColumn: (...args: Parameters) => void; - public readonly addConstraint: (...args: Parameters) => void + public readonly addConstraint: ( + ...args: Parameters + ) => void; - public readonly dropConstraint: (...args: Parameters) => void + public readonly dropConstraint: ( + ...args: Parameters + ) => void; - public readonly renameConstraint: (...args: Parameters) => void + public readonly renameConstraint: ( + ...args: Parameters + ) => void; - public readonly createConstraint: (...args: Parameters) => void + public readonly createConstraint: ( + ...args: Parameters + ) => void; - public readonly createType: (...args: Parameters) => void + public readonly createType: (...args: Parameters) => void; - public readonly dropType: (...args: Parameters) => void + public readonly dropType: (...args: Parameters) => void; - public readonly addType: (...args: Parameters) => void + public readonly addType: (...args: Parameters) => void; - public readonly renameType: (...args: Parameters) => void + public readonly renameType: (...args: Parameters) => void; - public readonly renameTypeAttribute: (...args: Parameters) => void + public readonly renameTypeAttribute: ( + ...args: Parameters + ) => void; - public readonly renameTypeValue: (...args: Parameters) => void + public readonly renameTypeValue: ( + ...args: Parameters + ) => void; - public readonly addTypeAttribute: (...args: Parameters) => void + public readonly addTypeAttribute: ( + ...args: Parameters + ) => void; - public readonly dropTypeAttribute: (...args: Parameters) => void + public readonly dropTypeAttribute: ( + ...args: Parameters + ) => void; - public readonly setTypeAttribute: (...args: Parameters) => void + public readonly setTypeAttribute: ( + ...args: Parameters + ) => void; - public readonly addTypeValue: (...args: Parameters) => void + public readonly addTypeValue: ( + ...args: Parameters + ) => void; - public readonly createIndex: (...args: Parameters) => void + public readonly createIndex: ( + ...args: Parameters + ) => void; - public readonly dropIndex: (...args: Parameters) => void + public readonly dropIndex: (...args: Parameters) => void; - public readonly addIndex: (...args: Parameters) => void + public readonly addIndex: (...args: Parameters) => void; - public readonly createRole: (...args: Parameters) => void + public readonly createRole: (...args: Parameters) => void; - public readonly dropRole: (...args: Parameters) => void + public readonly dropRole: (...args: Parameters) => void; - public readonly alterRole: (...args: Parameters) => void + public readonly alterRole: (...args: Parameters) => void; - public readonly renameRole: (...args: Parameters) => void + public readonly renameRole: (...args: Parameters) => void; - public readonly createFunction: (...args: Parameters) => void + public readonly createFunction: ( + ...args: Parameters + ) => void; - public readonly dropFunction: (...args: Parameters) => void + public readonly dropFunction: ( + ...args: Parameters + ) => void; - public readonly renameFunction: (...args: Parameters) => void + public readonly renameFunction: ( + ...args: Parameters + ) => void; - public readonly createTrigger: (...args: Parameters) => void + public readonly createTrigger: ( + ...args: Parameters + ) => void; - public readonly dropTrigger: (...args: Parameters) => void + public readonly dropTrigger: ( + ...args: Parameters + ) => void; - public readonly renameTrigger: (...args: Parameters) => void + public readonly renameTrigger: ( + ...args: Parameters + ) => void; - public readonly createSchema: (...args: Parameters) => void + public readonly createSchema: ( + ...args: Parameters + ) => void; - public readonly dropSchema: (...args: Parameters) => void + public readonly dropSchema: (...args: Parameters) => void; - public readonly renameSchema: (...args: Parameters) => void + public readonly renameSchema: ( + ...args: Parameters + ) => void; - public readonly createDomain: (...args: Parameters) => void + public readonly createDomain: ( + ...args: Parameters + ) => void; - public readonly dropDomain: (...args: Parameters) => void + public readonly dropDomain: (...args: Parameters) => void; - public readonly alterDomain: (...args: Parameters) => void + public readonly alterDomain: ( + ...args: Parameters + ) => void; - public readonly renameDomain: (...args: Parameters) => void + public readonly renameDomain: ( + ...args: Parameters + ) => void; - public readonly createSequence: (...args: Parameters) => void + public readonly createSequence: ( + ...args: Parameters + ) => void; - public readonly dropSequence: (...args: Parameters) => void + public readonly dropSequence: ( + ...args: Parameters + ) => void; - public readonly alterSequence: (...args: Parameters) => void + public readonly alterSequence: ( + ...args: Parameters + ) => void; - public readonly renameSequence: (...args: Parameters) => void + public readonly renameSequence: ( + ...args: Parameters + ) => void; - public readonly createOperator: (...args: Parameters) => void + public readonly createOperator: ( + ...args: Parameters + ) => void; - public readonly dropOperator: (...args: Parameters) => void + public readonly dropOperator: ( + ...args: Parameters + ) => void; - public readonly createOperatorClass: (...args: Parameters) => void + public readonly createOperatorClass: ( + ...args: Parameters + ) => void; - public readonly dropOperatorClass: (...args: Parameters) => void + public readonly dropOperatorClass: ( + ...args: Parameters + ) => void; - public readonly renameOperatorClass: (...args: Parameters) => void + public readonly renameOperatorClass: ( + ...args: Parameters + ) => void; - public readonly createOperatorFamily: (...args: Parameters) => void + public readonly createOperatorFamily: ( + ...args: Parameters + ) => void; - public readonly dropOperatorFamily: (...args: Parameters) => void + public readonly dropOperatorFamily: ( + ...args: Parameters + ) => void; - public readonly renameOperatorFamily: (...args: Parameters) => void + public readonly renameOperatorFamily: ( + ...args: Parameters + ) => void; - public readonly addToOperatorFamily: (...args: Parameters) => void + public readonly addToOperatorFamily: ( + ...args: Parameters + ) => void; - public readonly removeFromOperatorFamily: (...args: Parameters) => void + public readonly removeFromOperatorFamily: ( + ...args: Parameters + ) => void; - public readonly createPolicy: (...args: Parameters) => void + public readonly createPolicy: ( + ...args: Parameters + ) => void; - public readonly dropPolicy: (...args: Parameters) => void + public readonly dropPolicy: ( + ...args: Parameters + ) => void; - public readonly alterPolicy: (...args: Parameters) => void + public readonly alterPolicy: ( + ...args: Parameters + ) => void; - public readonly renamePolicy: (...args: Parameters) => void + public readonly renamePolicy: ( + ...args: Parameters + ) => void; - public readonly createView: (...args: Parameters) => void + public readonly createView: (...args: Parameters) => void; - public readonly dropView: (...args: Parameters) => void + public readonly dropView: (...args: Parameters) => void; - public readonly alterView: (...args: Parameters) => void + public readonly alterView: (...args: Parameters) => void; - public readonly alterViewColumn: (...args: Parameters) => void + public readonly alterViewColumn: ( + ...args: Parameters + ) => void; - public readonly renameView: (...args: Parameters) => void + public readonly renameView: (...args: Parameters) => void; - public readonly createMaterializedView: (...args: Parameters) => void + public readonly createMaterializedView: ( + ...args: Parameters + ) => void; - public readonly dropMaterializedView: (...args: Parameters) => void + public readonly dropMaterializedView: ( + ...args: Parameters + ) => void; - public readonly alterMaterializedView: (...args: Parameters) => void + public readonly alterMaterializedView: ( + ...args: Parameters + ) => void; - public readonly renameMaterializedView: (...args: Parameters) => void + public readonly renameMaterializedView: ( + ...args: Parameters + ) => void; - public readonly renameMaterializedViewColumn: (...args: Parameters) => void + public readonly renameMaterializedViewColumn: ( + ...args: Parameters + ) => void; - public readonly refreshMaterializedView: (...args: Parameters) => void + public readonly refreshMaterializedView: ( + ...args: Parameters + ) => void; - public readonly sql: (...args: Parameters) => void + public readonly sql: (...args: Parameters) => void; - public readonly func: (sql: string) => PgLiteral + public readonly func: (sql: string) => PgLiteral; - public readonly db: DB + public readonly db: DB; - private _steps: string[] + private _steps: string[]; - private _REVERSE_MODE: boolean + private _REVERSE_MODE: boolean; - private _useTransaction: boolean + private _useTransaction: boolean; - constructor(db: DB, typeShorthands: ColumnDefinitions | undefined, shouldDecamelize: boolean, logger: Logger) { - this._steps = [] - this._REVERSE_MODE = false + constructor( + db: DB, + typeShorthands: ColumnDefinitions | undefined, + shouldDecamelize: boolean, + logger: Logger + ) { + this._steps = []; + this._REVERSE_MODE = false; // by default, all migrations are wrapped in a transaction - this._useTransaction = true + this._useTransaction = true; // eslint-disable-next-line @typescript-eslint/no-explicit-any - type OperationFn = (...args: any[]) => string | string[] - type Operation = OperationFn & { reverse?: OperationFn } + type OperationFn = (...args: any[]) => string | string[]; + type Operation = OperationFn & { reverse?: OperationFn }; // this function wraps each operation within a function that either // calls the operation or its reverse, and appends the result (array of sql statements) @@ -213,122 +327,130 @@ export default class MigrationBuilderImpl implements MigrationBuilder { (...args: Parameters) => { if (this._REVERSE_MODE) { if (typeof operation.reverse !== 'function') { - const name = `pgm.${operation.name}()` - throw new Error(`Impossible to automatically infer down migration for "${name}"`) + const name = `pgm.${operation.name}()`; + throw new Error( + `Impossible to automatically infer down migration for "${name}"` + ); } - this._steps = this._steps.concat(operation.reverse(...args)) + this._steps = this._steps.concat(operation.reverse(...args)); } else { - this._steps = this._steps.concat(operation(...args)) + this._steps = this._steps.concat(operation(...args)); } - } + }; const options: MigrationOptions = { typeShorthands, schemalize: createSchemalize(shouldDecamelize, false), literal: createSchemalize(shouldDecamelize, true), logger, - } + }; // defines the methods that are accessible via pgm in each migrations // there are some convenience aliases to make usage easier - this.createExtension = wrap(extensions.createExtension(options)) - this.dropExtension = wrap(extensions.dropExtension(options)) - this.addExtension = this.createExtension - - this.createTable = wrap(tables.createTable(options)) - this.dropTable = wrap(tables.dropTable(options)) - this.renameTable = wrap(tables.renameTable(options)) - this.alterTable = wrap(tables.alterTable(options)) - - this.addColumns = wrap(tables.addColumns(options)) - this.dropColumns = wrap(tables.dropColumns(options)) - this.renameColumn = wrap(tables.renameColumn(options)) - this.alterColumn = wrap(tables.alterColumn(options)) - this.addColumn = this.addColumns - this.dropColumn = this.dropColumns - - this.addConstraint = wrap(tables.addConstraint(options)) - this.dropConstraint = wrap(tables.dropConstraint(options)) - this.renameConstraint = wrap(tables.renameConstraint(options)) - this.createConstraint = this.addConstraint - - this.createType = wrap(types.createType(options)) - this.dropType = wrap(types.dropType(options)) - this.addType = this.createType - this.renameType = wrap(types.renameType(options)) - this.renameTypeAttribute = wrap(types.renameTypeAttribute(options)) - this.renameTypeValue = wrap(types.renameTypeValue(options)) - this.addTypeAttribute = wrap(types.addTypeAttribute(options)) - this.dropTypeAttribute = wrap(types.dropTypeAttribute(options)) - this.setTypeAttribute = wrap(types.setTypeAttribute(options)) - this.addTypeValue = wrap(types.addTypeValue(options)) - - this.createIndex = wrap(indexes.createIndex(options)) - this.dropIndex = wrap(indexes.dropIndex(options)) - this.addIndex = this.createIndex - - this.createRole = wrap(roles.createRole(options)) - this.dropRole = wrap(roles.dropRole(options)) - this.alterRole = wrap(roles.alterRole(options)) - this.renameRole = wrap(roles.renameRole(options)) - - this.createFunction = wrap(functions.createFunction(options)) - this.dropFunction = wrap(functions.dropFunction(options)) - this.renameFunction = wrap(functions.renameFunction(options)) - - this.createTrigger = wrap(triggers.createTrigger(options)) - this.dropTrigger = wrap(triggers.dropTrigger(options)) - this.renameTrigger = wrap(triggers.renameTrigger(options)) - - this.createSchema = wrap(schemas.createSchema(options)) - this.dropSchema = wrap(schemas.dropSchema(options)) - this.renameSchema = wrap(schemas.renameSchema(options)) - - this.createDomain = wrap(domains.createDomain(options)) - this.dropDomain = wrap(domains.dropDomain(options)) - this.alterDomain = wrap(domains.alterDomain(options)) - this.renameDomain = wrap(domains.renameDomain(options)) - - this.createSequence = wrap(sequences.createSequence(options)) - this.dropSequence = wrap(sequences.dropSequence(options)) - this.alterSequence = wrap(sequences.alterSequence(options)) - this.renameSequence = wrap(sequences.renameSequence(options)) - - this.createOperator = wrap(operators.createOperator(options)) - this.dropOperator = wrap(operators.dropOperator(options)) - this.createOperatorClass = wrap(operators.createOperatorClass(options)) - this.dropOperatorClass = wrap(operators.dropOperatorClass(options)) - this.renameOperatorClass = wrap(operators.renameOperatorClass(options)) - this.createOperatorFamily = wrap(operators.createOperatorFamily(options)) - this.dropOperatorFamily = wrap(operators.dropOperatorFamily(options)) - this.renameOperatorFamily = wrap(operators.renameOperatorFamily(options)) - this.addToOperatorFamily = wrap(operators.addToOperatorFamily(options)) - this.removeFromOperatorFamily = wrap(operators.removeFromOperatorFamily(options)) - - this.createPolicy = wrap(policies.createPolicy(options)) - this.dropPolicy = wrap(policies.dropPolicy(options)) - this.alterPolicy = wrap(policies.alterPolicy(options)) - this.renamePolicy = wrap(policies.renamePolicy(options)) - - this.createView = wrap(views.createView(options)) - this.dropView = wrap(views.dropView(options)) - this.alterView = wrap(views.alterView(options)) - this.alterViewColumn = wrap(views.alterViewColumn(options)) - this.renameView = wrap(views.renameView(options)) - - this.createMaterializedView = wrap(mViews.createMaterializedView(options)) - this.dropMaterializedView = wrap(mViews.dropMaterializedView(options)) - this.alterMaterializedView = wrap(mViews.alterMaterializedView(options)) - this.renameMaterializedView = wrap(mViews.renameMaterializedView(options)) - this.renameMaterializedViewColumn = wrap(mViews.renameMaterializedViewColumn(options)) - this.refreshMaterializedView = wrap(mViews.refreshMaterializedView(options)) - - this.sql = wrap(other.sql(options)) + this.createExtension = wrap(extensions.createExtension(options)); + this.dropExtension = wrap(extensions.dropExtension(options)); + this.addExtension = this.createExtension; + + this.createTable = wrap(tables.createTable(options)); + this.dropTable = wrap(tables.dropTable(options)); + this.renameTable = wrap(tables.renameTable(options)); + this.alterTable = wrap(tables.alterTable(options)); + + this.addColumns = wrap(tables.addColumns(options)); + this.dropColumns = wrap(tables.dropColumns(options)); + this.renameColumn = wrap(tables.renameColumn(options)); + this.alterColumn = wrap(tables.alterColumn(options)); + this.addColumn = this.addColumns; + this.dropColumn = this.dropColumns; + + this.addConstraint = wrap(tables.addConstraint(options)); + this.dropConstraint = wrap(tables.dropConstraint(options)); + this.renameConstraint = wrap(tables.renameConstraint(options)); + this.createConstraint = this.addConstraint; + + this.createType = wrap(types.createType(options)); + this.dropType = wrap(types.dropType(options)); + this.addType = this.createType; + this.renameType = wrap(types.renameType(options)); + this.renameTypeAttribute = wrap(types.renameTypeAttribute(options)); + this.renameTypeValue = wrap(types.renameTypeValue(options)); + this.addTypeAttribute = wrap(types.addTypeAttribute(options)); + this.dropTypeAttribute = wrap(types.dropTypeAttribute(options)); + this.setTypeAttribute = wrap(types.setTypeAttribute(options)); + this.addTypeValue = wrap(types.addTypeValue(options)); + + this.createIndex = wrap(indexes.createIndex(options)); + this.dropIndex = wrap(indexes.dropIndex(options)); + this.addIndex = this.createIndex; + + this.createRole = wrap(roles.createRole(options)); + this.dropRole = wrap(roles.dropRole(options)); + this.alterRole = wrap(roles.alterRole(options)); + this.renameRole = wrap(roles.renameRole(options)); + + this.createFunction = wrap(functions.createFunction(options)); + this.dropFunction = wrap(functions.dropFunction(options)); + this.renameFunction = wrap(functions.renameFunction(options)); + + this.createTrigger = wrap(triggers.createTrigger(options)); + this.dropTrigger = wrap(triggers.dropTrigger(options)); + this.renameTrigger = wrap(triggers.renameTrigger(options)); + + this.createSchema = wrap(schemas.createSchema(options)); + this.dropSchema = wrap(schemas.dropSchema(options)); + this.renameSchema = wrap(schemas.renameSchema(options)); + + this.createDomain = wrap(domains.createDomain(options)); + this.dropDomain = wrap(domains.dropDomain(options)); + this.alterDomain = wrap(domains.alterDomain(options)); + this.renameDomain = wrap(domains.renameDomain(options)); + + this.createSequence = wrap(sequences.createSequence(options)); + this.dropSequence = wrap(sequences.dropSequence(options)); + this.alterSequence = wrap(sequences.alterSequence(options)); + this.renameSequence = wrap(sequences.renameSequence(options)); + + this.createOperator = wrap(operators.createOperator(options)); + this.dropOperator = wrap(operators.dropOperator(options)); + this.createOperatorClass = wrap(operators.createOperatorClass(options)); + this.dropOperatorClass = wrap(operators.dropOperatorClass(options)); + this.renameOperatorClass = wrap(operators.renameOperatorClass(options)); + this.createOperatorFamily = wrap(operators.createOperatorFamily(options)); + this.dropOperatorFamily = wrap(operators.dropOperatorFamily(options)); + this.renameOperatorFamily = wrap(operators.renameOperatorFamily(options)); + this.addToOperatorFamily = wrap(operators.addToOperatorFamily(options)); + this.removeFromOperatorFamily = wrap( + operators.removeFromOperatorFamily(options) + ); + + this.createPolicy = wrap(policies.createPolicy(options)); + this.dropPolicy = wrap(policies.dropPolicy(options)); + this.alterPolicy = wrap(policies.alterPolicy(options)); + this.renamePolicy = wrap(policies.renamePolicy(options)); + + this.createView = wrap(views.createView(options)); + this.dropView = wrap(views.dropView(options)); + this.alterView = wrap(views.alterView(options)); + this.alterViewColumn = wrap(views.alterViewColumn(options)); + this.renameView = wrap(views.renameView(options)); + + this.createMaterializedView = wrap(mViews.createMaterializedView(options)); + this.dropMaterializedView = wrap(mViews.dropMaterializedView(options)); + this.alterMaterializedView = wrap(mViews.alterMaterializedView(options)); + this.renameMaterializedView = wrap(mViews.renameMaterializedView(options)); + this.renameMaterializedViewColumn = wrap( + mViews.renameMaterializedViewColumn(options) + ); + this.refreshMaterializedView = wrap( + mViews.refreshMaterializedView(options) + ); + + this.sql = wrap(other.sql(options)); // Other utilities which may be useful // .func creates a string which will not be escaped // common uses are for PG functions, ex: { ... default: pgm.func('NOW()') } - this.func = PgLiteral.create + this.func = PgLiteral.create; // expose DB so we can access database within transaction /* eslint-disable @typescript-eslint/no-explicit-any */ @@ -336,38 +458,38 @@ export default class MigrationBuilderImpl implements MigrationBuilder { (operation: (...args: T) => R) => (...args: T) => { if (this._REVERSE_MODE) { - throw new Error('Impossible to automatically infer down migration') + throw new Error('Impossible to automatically infer down migration'); } - return operation(...args) - } + return operation(...args); + }; /* eslint-enable @typescript-eslint/no-explicit-any */ this.db = { query: wrapDB(db.query), select: wrapDB(db.select), - } + }; } enableReverseMode(): this { - this._REVERSE_MODE = true - return this + this._REVERSE_MODE = true; + return this; } noTransaction(): this { - this._useTransaction = false - return this + this._useTransaction = false; + return this; } isUsingTransaction(): boolean { - return this._useTransaction + return this._useTransaction; } getSql(): string { - return `${this.getSqlSteps().join('\n')}\n` + return `${this.getSqlSteps().join('\n')}\n`; } getSqlSteps(): string[] { // in reverse mode, we flip the order of the statements - return this._REVERSE_MODE ? this._steps.slice().reverse() : this._steps + return this._REVERSE_MODE ? this._steps.slice().reverse() : this._steps; } } /* eslint-enable security/detect-non-literal-fs-filename */ diff --git a/src/migration.ts b/src/migration.ts index eef6419c..ef07e144 100644 --- a/src/migration.ts +++ b/src/migration.ts @@ -6,21 +6,27 @@ */ -import fs from 'fs' -import mkdirp from 'mkdirp' -import path from 'path' -import { DBConnection } from './db' -import MigrationBuilder from './migration-builder' -import { MigrationAction, MigrationBuilderActions, MigrationDirection, RunnerOption, Logger } from './types' -import { getMigrationTableSchema } from './utils' -import { ColumnDefinitions } from './operations/tablesTypes' - -const { readdir } = fs.promises +import fs from 'fs'; +import mkdirp from 'mkdirp'; +import path from 'path'; +import { DBConnection } from './db'; +import MigrationBuilder from './migration-builder'; +import { ColumnDefinitions } from './operations/tablesTypes'; +import { + Logger, + MigrationAction, + MigrationBuilderActions, + MigrationDirection, + RunnerOption, +} from './types'; +import { getMigrationTableSchema } from './utils'; + +const { readdir } = fs.promises; export interface RunMigration { - readonly path: string - readonly name: string - readonly timestamp: number + readonly path: string; + readonly name: string; + readonly timestamp: number; } export enum FilenameFormat { @@ -29,66 +35,78 @@ export enum FilenameFormat { } export interface CreateOptionsTemplate { - templateFileName: string + templateFileName: string; } export interface CreateOptionsDefault { - language?: 'js' | 'ts' | 'sql' - ignorePattern?: string + language?: 'js' | 'ts' | 'sql'; + ignorePattern?: string; } export type CreateOptions = { - filenameFormat?: FilenameFormat -} & (CreateOptionsTemplate | CreateOptionsDefault) + filenameFormat?: FilenameFormat; +} & (CreateOptionsTemplate | CreateOptionsDefault); -const SEPARATOR = '_' +const SEPARATOR = '_'; -export const loadMigrationFiles = async (dir: string, ignorePattern?: string) => { - const dirContent = await readdir(`${dir}/`, { withFileTypes: true }) +export const loadMigrationFiles = async ( + dir: string, + ignorePattern?: string +) => { + const dirContent = await readdir(`${dir}/`, { withFileTypes: true }); const files = dirContent .map((file) => (file.isFile() || file.isSymbolicLink() ? file.name : null)) .filter((file): file is string => Boolean(file)) - .sort() - const filter = new RegExp(`^(${ignorePattern})$`) // eslint-disable-line security/detect-non-literal-regexp - return ignorePattern === undefined ? files : files.filter((i) => !filter.test(i)) -} + .sort(); + const filter = new RegExp(`^(${ignorePattern})$`); // eslint-disable-line security/detect-non-literal-regexp + return ignorePattern === undefined + ? files + : files.filter((i) => !filter.test(i)); +}; -const getSuffixFromFileName = (fileName: string) => path.extname(fileName).substr(1) +const getSuffixFromFileName = (fileName: string) => + path.extname(fileName).substr(1); const getLastSuffix = async (dir: string, ignorePattern?: string) => { try { - const files = await loadMigrationFiles(dir, ignorePattern) - return files.length > 0 ? getSuffixFromFileName(files[files.length - 1]) : undefined + const files = await loadMigrationFiles(dir, ignorePattern); + return files.length > 0 + ? getSuffixFromFileName(files[files.length - 1]) + : undefined; } catch (err) { - return undefined + return undefined; } -} +}; export const getTimestamp = (logger: Logger, filename: string): number => { - const prefix = filename.split(SEPARATOR)[0] + const prefix = filename.split(SEPARATOR)[0]; if (prefix && /^\d+$/.test(prefix)) { if (prefix.length === 13) { // timestamp: 1391877300255 - return Number(prefix) + return Number(prefix); } if (prefix && prefix.length === 17) { // utc: 20200513070724505 - const year = prefix.substr(0, 4) - const month = prefix.substr(4, 2) - const date = prefix.substr(6, 2) - const hours = prefix.substr(8, 2) - const minutes = prefix.substr(10, 2) - const seconds = prefix.substr(12, 2) - const ms = prefix.substr(14) - return new Date(`${year}-${month}-${date}T${hours}:${minutes}:${seconds}.${ms}Z`).valueOf() + const year = prefix.substr(0, 4); + const month = prefix.substr(4, 2); + const date = prefix.substr(6, 2); + const hours = prefix.substr(8, 2); + const minutes = prefix.substr(10, 2); + const seconds = prefix.substr(12, 2); + const ms = prefix.substr(14); + return new Date( + `${year}-${month}-${date}T${hours}:${minutes}:${seconds}.${ms}Z` + ).valueOf(); } } - logger.error(`Can't determine timestamp for ${prefix}`) - return Number(prefix) || 0 -} + logger.error(`Can't determine timestamp for ${prefix}`); + return Number(prefix) || 0; +}; -const resolveSuffix = async (directory: string, { language, ignorePattern }: CreateOptionsDefault) => - language || (await getLastSuffix(directory, ignorePattern)) || 'js' +const resolveSuffix = async ( + directory: string, + { language, ignorePattern }: CreateOptionsDefault +) => language || (await getLastSuffix(directory, ignorePattern)) || 'js'; export class Migration implements RunMigration { // class method that creates a new migration file by cloning the migration template @@ -97,32 +115,44 @@ export class Migration implements RunMigration { directory: string, _language?: 'js' | 'ts' | 'sql' | CreateOptions, _ignorePattern?: string, - _filenameFormat?: FilenameFormat, + _filenameFormat?: FilenameFormat ) { if (typeof _language === 'string') { // eslint-disable-next-line no-console - console.warn('This usage is deprecated. Please use this method with options object argument') + console.warn( + 'This usage is deprecated. Please use this method with options object argument' + ); } const options = typeof _language === 'object' ? _language - : { language: _language, ignorePattern: _ignorePattern, filenameFormat: _filenameFormat } - const { filenameFormat = FilenameFormat.timestamp } = options + : { + language: _language, + ignorePattern: _ignorePattern, + filenameFormat: _filenameFormat, + }; + const { filenameFormat = FilenameFormat.timestamp } = options; // ensure the migrations directory exists - mkdirp.sync(directory) + mkdirp.sync(directory); - const now = new Date() - const time = filenameFormat === FilenameFormat.utc ? now.toISOString().replace(/[^\d]/g, '') : now.valueOf() + const now = new Date(); + const time = + filenameFormat === FilenameFormat.utc + ? now.toISOString().replace(/[^\d]/g, '') + : now.valueOf(); const templateFileName = 'templateFileName' in options ? path.resolve(process.cwd(), options.templateFileName) - : path.resolve(__dirname, `../templates/migration-template.${await resolveSuffix(directory, options)}`) - const suffix = getSuffixFromFileName(templateFileName) + : path.resolve( + __dirname, + `../templates/migration-template.${await resolveSuffix(directory, options)}` + ); + const suffix = getSuffixFromFileName(templateFileName); // file name looks like migrations/1391877300255_migration-title.js - const newFile = `${directory}/${time}${SEPARATOR}${name}.${suffix}` + const newFile = `${directory}/${time}${SEPARATOR}${name}.${suffix}`; // copy the default migration template to the new file location await new Promise((resolve, reject) => { @@ -131,29 +161,29 @@ export class Migration implements RunMigration { // eslint-disable-next-line security/detect-non-literal-fs-filename .pipe(fs.createWriteStream(newFile)) .on('close', resolve) - .on('error', reject) - }) + .on('error', reject); + }); - return newFile + return newFile; } - public readonly db: DBConnection + public readonly db: DBConnection; - public readonly path: string + public readonly path: string; - public readonly name: string + public readonly name: string; - public readonly timestamp: number + public readonly timestamp: number; - public up?: false | MigrationAction + public up?: false | MigrationAction; - public down?: false | MigrationAction + public down?: false | MigrationAction; - public readonly options: RunnerOption + public readonly options: RunnerOption; - public readonly typeShorthands?: ColumnDefinitions + public readonly typeShorthands?: ColumnDefinitions; - public readonly logger: Logger + public readonly logger: Logger; constructor( db: DBConnection, @@ -161,104 +191,114 @@ export class Migration implements RunMigration { { up, down }: MigrationBuilderActions, options: RunnerOption, typeShorthands?: ColumnDefinitions, - logger: Logger = console, + logger: Logger = console ) { - this.db = db - this.path = migrationPath - this.name = path.basename(migrationPath, path.extname(migrationPath)) - this.timestamp = getTimestamp(logger, this.name) - this.up = up - this.down = down - this.options = options - this.typeShorthands = typeShorthands - this.logger = logger + this.db = db; + this.path = migrationPath; + this.name = path.basename(migrationPath, path.extname(migrationPath)); + this.timestamp = getTimestamp(logger, this.name); + this.up = up; + this.down = down; + this.options = options; + this.typeShorthands = typeShorthands; + this.logger = logger; } _getMarkAsRun(action: MigrationAction) { - const schema = getMigrationTableSchema(this.options) - const { migrationsTable } = this.options - const { name } = this + const schema = getMigrationTableSchema(this.options); + const { migrationsTable } = this.options; + const { name } = this; switch (action) { case this.down: - this.logger.info(`### MIGRATION ${this.name} (DOWN) ###`) - return `DELETE FROM "${schema}"."${migrationsTable}" WHERE name='${name}';` + this.logger.info(`### MIGRATION ${this.name} (DOWN) ###`); + return `DELETE FROM "${schema}"."${migrationsTable}" WHERE name='${name}';`; case this.up: - this.logger.info(`### MIGRATION ${this.name} (UP) ###`) - return `INSERT INTO "${schema}"."${migrationsTable}" (name, run_on) VALUES ('${name}', NOW());` + this.logger.info(`### MIGRATION ${this.name} (UP) ###`); + return `INSERT INTO "${schema}"."${migrationsTable}" (name, run_on) VALUES ('${name}', NOW());`; default: - throw new Error('Unknown direction') + throw new Error('Unknown direction'); } } async _apply(action: MigrationAction, pgm: MigrationBuilder) { if (action.length === 2) { await new Promise((resolve) => { - action(pgm, resolve) - }) + action(pgm, resolve); + }); } else { - await action(pgm) + await action(pgm); } - const sqlSteps = pgm.getSqlSteps() + const sqlSteps = pgm.getSqlSteps(); - sqlSteps.push(this._getMarkAsRun(action)) + sqlSteps.push(this._getMarkAsRun(action)); if (!this.options.singleTransaction && pgm.isUsingTransaction()) { // if not in singleTransaction mode we need to create our own transaction - sqlSteps.unshift('BEGIN;') - sqlSteps.push('COMMIT;') + sqlSteps.unshift('BEGIN;'); + sqlSteps.push('COMMIT;'); } else if (this.options.singleTransaction && !pgm.isUsingTransaction()) { // in singleTransaction mode we are already wrapped in a global transaction - this.logger.warn('#> WARNING: Need to break single transaction! <') - sqlSteps.unshift('COMMIT;') - sqlSteps.push('BEGIN;') + this.logger.warn('#> WARNING: Need to break single transaction! <'); + sqlSteps.unshift('COMMIT;'); + sqlSteps.push('BEGIN;'); } else if (!this.options.singleTransaction || !pgm.isUsingTransaction()) { - this.logger.warn('#> WARNING: This migration is not wrapped in a transaction! <') + this.logger.warn( + '#> WARNING: This migration is not wrapped in a transaction! <' + ); } if (typeof this.logger.debug === 'function') { - this.logger.debug(`${sqlSteps.join('\n')}\n\n`) + this.logger.debug(`${sqlSteps.join('\n')}\n\n`); } return sqlSteps.reduce( - (promise: Promise, sql) => promise.then((): unknown => this.options.dryRun || this.db.query(sql)), - Promise.resolve(), - ) + (promise: Promise, sql) => + promise.then((): unknown => this.options.dryRun || this.db.query(sql)), + Promise.resolve() + ); } _getAction(direction: MigrationDirection) { if (direction === 'down' && this.down === undefined) { - this.down = this.up + this.down = this.up; } - const action: MigrationAction | false | undefined = this[direction] + const action: MigrationAction | false | undefined = this[direction]; if (action === false) { - throw new Error(`User has disabled ${direction} migration on file: ${this.name}`) + throw new Error( + `User has disabled ${direction} migration on file: ${this.name}` + ); } if (typeof action !== 'function') { throw new Error( - `Unknown value for direction: ${direction}. Is the migration ${this.name} exporting a '${direction}' function?`, - ) + `Unknown value for direction: ${direction}. Is the migration ${this.name} exporting a '${direction}' function?` + ); } - return action + return action; } apply(direction: MigrationDirection) { - const pgm = new MigrationBuilder(this.db, this.typeShorthands, Boolean(this.options.decamelize), this.logger) - const action = this._getAction(direction) + const pgm = new MigrationBuilder( + this.db, + this.typeShorthands, + Boolean(this.options.decamelize), + this.logger + ); + const action = this._getAction(direction); if (this.down === this.up) { // automatically infer the down migration by running the up migration in reverse mode... - pgm.enableReverseMode() + pgm.enableReverseMode(); } - return this._apply(action, pgm) + return this._apply(action, pgm); } markAsRun(direction: MigrationDirection) { - return this.db.query(this._getMarkAsRun(this._getAction(direction))) + return this.db.query(this._getMarkAsRun(this._getAction(direction))); } } diff --git a/src/operations/PgLiteral.ts b/src/operations/PgLiteral.ts index 59775232..9cbb1d7c 100644 --- a/src/operations/PgLiteral.ts +++ b/src/operations/PgLiteral.ts @@ -2,15 +2,15 @@ // exposed in the migrations via pgm.func export default class PgLiteral { static create(str: string): PgLiteral { - return new PgLiteral(str) + return new PgLiteral(str); } - public readonly literal = true + public readonly literal = true; // eslint-disable-next-line no-useless-constructor constructor(public readonly value: string) {} toString(): string { - return this.value + return this.value; } } diff --git a/src/operations/domains.ts b/src/operations/domains.ts index 583df4ec..8888c04e 100644 --- a/src/operations/domains.ts +++ b/src/operations/domains.ts @@ -1,83 +1,106 @@ -import { MigrationOptions } from '../types' -import { applyType, escapeValue } from '../utils' -import { CreateDomain, DropDomain, AlterDomain, RenameDomain } from './domainsTypes' +import { MigrationOptions } from '../types'; +import { applyType, escapeValue } from '../utils'; +import { + AlterDomain, + CreateDomain, + DropDomain, + RenameDomain, +} from './domainsTypes'; -export { CreateDomain, DropDomain, AlterDomain, RenameDomain } +export { CreateDomain, DropDomain, AlterDomain, RenameDomain }; export function dropDomain(mOptions: MigrationOptions) { const _drop: DropDomain = (domainName, options = {}) => { - const { ifExists, cascade } = options - const ifExistsStr = ifExists ? ' IF EXISTS' : '' - const cascadeStr = cascade ? ' CASCADE' : '' - const domainNameStr = mOptions.literal(domainName) - return `DROP DOMAIN${ifExistsStr} ${domainNameStr}${cascadeStr};` - } - return _drop + const { ifExists, cascade } = options; + const ifExistsStr = ifExists ? ' IF EXISTS' : ''; + const cascadeStr = cascade ? ' CASCADE' : ''; + const domainNameStr = mOptions.literal(domainName); + return `DROP DOMAIN${ifExistsStr} ${domainNameStr}${cascadeStr};`; + }; + return _drop; } export function createDomain(mOptions: MigrationOptions) { const _create: CreateDomain = (domainName, type, options = {}) => { - const { default: defaultValue, collation, notNull, check, constraintName } = options - const constraints = [] + const { + default: defaultValue, + collation, + notNull, + check, + constraintName, + } = options; + const constraints = []; if (collation) { - constraints.push(`COLLATE ${collation}`) + constraints.push(`COLLATE ${collation}`); } if (defaultValue !== undefined) { - constraints.push(`DEFAULT ${escapeValue(defaultValue)}`) + constraints.push(`DEFAULT ${escapeValue(defaultValue)}`); } if (notNull && check) { - throw new Error('"notNull" and "check" can\'t be specified together') + throw new Error('"notNull" and "check" can\'t be specified together'); } else if (notNull || check) { if (constraintName) { - constraints.push(`CONSTRAINT ${mOptions.literal(constraintName)}`) + constraints.push(`CONSTRAINT ${mOptions.literal(constraintName)}`); } if (notNull) { - constraints.push('NOT NULL') + constraints.push('NOT NULL'); } else if (check) { - constraints.push(`CHECK (${check})`) + constraints.push(`CHECK (${check})`); } } - const constraintsStr = constraints.length ? ` ${constraints.join(' ')}` : '' + const constraintsStr = constraints.length + ? ` ${constraints.join(' ')}` + : ''; - const typeStr = applyType(type, mOptions.typeShorthands).type - const domainNameStr = mOptions.literal(domainName) + const typeStr = applyType(type, mOptions.typeShorthands).type; + const domainNameStr = mOptions.literal(domainName); - return `CREATE DOMAIN ${domainNameStr} AS ${typeStr}${constraintsStr};` - } - _create.reverse = (domainName, type, options) => dropDomain(mOptions)(domainName, options) - return _create + return `CREATE DOMAIN ${domainNameStr} AS ${typeStr}${constraintsStr};`; + }; + _create.reverse = (domainName, type, options) => + dropDomain(mOptions)(domainName, options); + return _create; } export function alterDomain(mOptions: MigrationOptions) { const _alter: AlterDomain = (domainName, options) => { - const { default: defaultValue, notNull, allowNull, check, constraintName } = options - const actions = [] + const { + default: defaultValue, + notNull, + allowNull, + check, + constraintName, + } = options; + const actions = []; if (defaultValue === null) { - actions.push('DROP DEFAULT') + actions.push('DROP DEFAULT'); } else if (defaultValue !== undefined) { - actions.push(`SET DEFAULT ${escapeValue(defaultValue)}`) + actions.push(`SET DEFAULT ${escapeValue(defaultValue)}`); } if (notNull) { - actions.push('SET NOT NULL') + actions.push('SET NOT NULL'); } else if (notNull === false || allowNull) { - actions.push('DROP NOT NULL') + actions.push('DROP NOT NULL'); } if (check) { - actions.push(`${constraintName ? `CONSTRAINT ${mOptions.literal(constraintName)} ` : ''}CHECK (${check})`) + actions.push( + `${constraintName ? `CONSTRAINT ${mOptions.literal(constraintName)} ` : ''}CHECK (${check})` + ); } - return `${actions.map((action) => `ALTER DOMAIN ${mOptions.literal(domainName)} ${action}`).join(';\n')};` - } - return _alter + return `${actions.map((action) => `ALTER DOMAIN ${mOptions.literal(domainName)} ${action}`).join(';\n')};`; + }; + return _alter; } export function renameDomain(mOptions: MigrationOptions) { const _rename: RenameDomain = (domainName, newDomainName) => { - const domainNameStr = mOptions.literal(domainName) - const newDomainNameStr = mOptions.literal(newDomainName) - return `ALTER DOMAIN ${domainNameStr} RENAME TO ${newDomainNameStr};` - } - _rename.reverse = (domainName, newDomainName) => _rename(newDomainName, domainName) - return _rename + const domainNameStr = mOptions.literal(domainName); + const newDomainNameStr = mOptions.literal(newDomainName); + return `ALTER DOMAIN ${domainNameStr} RENAME TO ${newDomainNameStr};`; + }; + _rename.reverse = (domainName, newDomainName) => + _rename(newDomainName, domainName); + return _rename; } diff --git a/src/operations/domainsTypes.ts b/src/operations/domainsTypes.ts index b4f9e7c0..d0b4569e 100644 --- a/src/operations/domainsTypes.ts +++ b/src/operations/domainsTypes.ts @@ -1,27 +1,36 @@ -import { Value, Name, Type, DropOptions } from './generalTypes' +import { DropOptions, Name, Type, Value } from './generalTypes'; export interface DomainOptions { - default?: Value - notNull?: boolean - check?: string - constraintName?: string + default?: Value; + notNull?: boolean; + check?: string; + constraintName?: string; } export interface DomainOptionsCreate extends DomainOptions { - collation?: string + collation?: string; } export interface DomainOptionsAlter extends DomainOptions { - allowNull?: boolean + allowNull?: boolean; } type CreateDomainFn = ( domainName: Name, type: Type, - domainOptions?: DomainOptionsCreate & DropOptions, -) => string | string[] -export type CreateDomain = CreateDomainFn & { reverse: CreateDomainFn } -export type DropDomain = (domainName: Name, dropOptions?: DropOptions) => string | string[] -export type AlterDomain = (domainName: Name, domainOptions: DomainOptionsAlter) => string | string[] -type RenameDomainFn = (oldDomainName: Name, newDomainName: Name) => string | string[] -export type RenameDomain = RenameDomainFn & { reverse: RenameDomainFn } + domainOptions?: DomainOptionsCreate & DropOptions +) => string | string[]; +export type CreateDomain = CreateDomainFn & { reverse: CreateDomainFn }; +export type DropDomain = ( + domainName: Name, + dropOptions?: DropOptions +) => string | string[]; +export type AlterDomain = ( + domainName: Name, + domainOptions: DomainOptionsAlter +) => string | string[]; +type RenameDomainFn = ( + oldDomainName: Name, + newDomainName: Name +) => string | string[]; +export type RenameDomain = RenameDomainFn & { reverse: RenameDomainFn }; diff --git a/src/operations/extensions.ts b/src/operations/extensions.ts index bd4358af..378e8b79 100644 --- a/src/operations/extensions.ts +++ b/src/operations/extensions.ts @@ -1,33 +1,33 @@ -import { MigrationOptions } from '../types' -import { CreateExtension, DropExtension } from './extensionsTypes' +import { MigrationOptions } from '../types'; +import { CreateExtension, DropExtension } from './extensionsTypes'; -export { CreateExtension, DropExtension } +export { CreateExtension, DropExtension }; export function dropExtension(mOptions: MigrationOptions) { const _drop: DropExtension = (_extensions, options = {}) => { - const { ifExists, cascade } = options - const extensions = Array.isArray(_extensions) ? _extensions : [_extensions] - const ifExistsStr = ifExists ? ' IF EXISTS' : '' - const cascadeStr = cascade ? ' CASCADE' : '' + const { ifExists, cascade } = options; + const extensions = Array.isArray(_extensions) ? _extensions : [_extensions]; + const ifExistsStr = ifExists ? ' IF EXISTS' : ''; + const cascadeStr = cascade ? ' CASCADE' : ''; return extensions.map((extension) => { - const extensionStr = mOptions.literal(extension) - return `DROP EXTENSION${ifExistsStr} ${extensionStr}${cascadeStr};` - }) - } - return _drop + const extensionStr = mOptions.literal(extension); + return `DROP EXTENSION${ifExistsStr} ${extensionStr}${cascadeStr};`; + }); + }; + return _drop; } export function createExtension(mOptions: MigrationOptions) { const _create: CreateExtension = (_extensions, options = {}) => { - const { ifNotExists, schema } = options - const extensions = Array.isArray(_extensions) ? _extensions : [_extensions] - const ifNotExistsStr = ifNotExists ? ' IF NOT EXISTS' : '' - const schemaStr = schema ? ` SCHEMA ${mOptions.literal(schema)}` : '' + const { ifNotExists, schema } = options; + const extensions = Array.isArray(_extensions) ? _extensions : [_extensions]; + const ifNotExistsStr = ifNotExists ? ' IF NOT EXISTS' : ''; + const schemaStr = schema ? ` SCHEMA ${mOptions.literal(schema)}` : ''; return extensions.map((extension) => { - const extensionStr = mOptions.literal(extension) - return `CREATE EXTENSION${ifNotExistsStr} ${extensionStr}${schemaStr};` - }) - } - _create.reverse = dropExtension(mOptions) - return _create + const extensionStr = mOptions.literal(extension); + return `CREATE EXTENSION${ifNotExistsStr} ${extensionStr}${schemaStr};`; + }); + }; + _create.reverse = dropExtension(mOptions); + return _create; } diff --git a/src/operations/extensionsTypes.ts b/src/operations/extensionsTypes.ts index ec18600f..a5b333e2 100644 --- a/src/operations/extensionsTypes.ts +++ b/src/operations/extensionsTypes.ts @@ -1,4 +1,4 @@ -import { LiteralUnion, DropOptions, IfNotExistsOption } from './generalTypes' +import { DropOptions, IfNotExistsOption, LiteralUnion } from './generalTypes'; export type Extension = | 'adminpack' @@ -45,19 +45,21 @@ export type Extension = | 'tsm_system_time' | 'unaccent' | 'uuid-ossp' - | 'xml2' + | 'xml2'; export interface CreateExtensionOptions extends IfNotExistsOption { - schema?: string + schema?: string; } -type StringExtension = LiteralUnion +type StringExtension = LiteralUnion; type CreateExtensionFn = ( extension: StringExtension | Array, - options?: CreateExtensionOptions & DropOptions, -) => string | string[] -export type CreateExtension = CreateExtensionFn & { reverse: CreateExtensionFn } + options?: CreateExtensionOptions & DropOptions +) => string | string[]; +export type CreateExtension = CreateExtensionFn & { + reverse: CreateExtensionFn; +}; export type DropExtension = ( extension: StringExtension | Array, - dropOptions?: DropOptions, -) => string | string[] + dropOptions?: DropOptions +) => string | string[]; diff --git a/src/operations/functions.ts b/src/operations/functions.ts index 44ff6bf9..4a5a9cb0 100644 --- a/src/operations/functions.ts +++ b/src/operations/functions.ts @@ -1,66 +1,89 @@ -import { MigrationOptions } from '../types' -import { escapeValue, formatParams } from '../utils' -import { CreateFunction, DropFunction, RenameFunction } from './functionsTypes' +import { MigrationOptions } from '../types'; +import { escapeValue, formatParams } from '../utils'; +import { CreateFunction, DropFunction, RenameFunction } from './functionsTypes'; -export { CreateFunction, DropFunction, RenameFunction } +export { CreateFunction, DropFunction, RenameFunction }; export function dropFunction(mOptions: MigrationOptions) { - const _drop: DropFunction = (functionName, functionParams = [], options = {}) => { - const { ifExists, cascade } = options - const ifExistsStr = ifExists ? ' IF EXISTS' : '' - const cascadeStr = cascade ? ' CASCADE' : '' - const paramsStr = formatParams(functionParams, mOptions) - const functionNameStr = mOptions.literal(functionName) - return `DROP FUNCTION${ifExistsStr} ${functionNameStr}${paramsStr}${cascadeStr};` - } - return _drop + const _drop: DropFunction = ( + functionName, + functionParams = [], + options = {} + ) => { + const { ifExists, cascade } = options; + const ifExistsStr = ifExists ? ' IF EXISTS' : ''; + const cascadeStr = cascade ? ' CASCADE' : ''; + const paramsStr = formatParams(functionParams, mOptions); + const functionNameStr = mOptions.literal(functionName); + return `DROP FUNCTION${ifExistsStr} ${functionNameStr}${paramsStr}${cascadeStr};`; + }; + return _drop; } export function createFunction(mOptions: MigrationOptions) { - // eslint-disable-next-line default-param-last - const _create: CreateFunction = (functionName, functionParams = [], functionOptions, definition) => { - const { replace, returns = 'void', language, window, behavior = 'VOLATILE', onNull, parallel } = functionOptions - const options = [] + const _create: CreateFunction = ( + functionName, + // eslint-disable-next-line default-param-last + functionParams = [], + functionOptions, + definition + ) => { + const { + replace, + returns = 'void', + language, + window, + behavior = 'VOLATILE', + onNull, + parallel, + } = functionOptions; + const options = []; if (behavior) { - options.push(behavior) + options.push(behavior); } if (language) { - options.push(`LANGUAGE ${language}`) + options.push(`LANGUAGE ${language}`); } else { - throw new Error(`Language for function ${functionName} have to be specified`) + throw new Error( + `Language for function ${functionName} have to be specified` + ); } if (window) { - options.push('WINDOW') + options.push('WINDOW'); } if (onNull) { - options.push('RETURNS NULL ON NULL INPUT') + options.push('RETURNS NULL ON NULL INPUT'); } if (parallel) { - options.push(`PARALLEL ${parallel}`) + options.push(`PARALLEL ${parallel}`); } - const replaceStr = replace ? ' OR REPLACE' : '' - const paramsStr = formatParams(functionParams, mOptions) - const functionNameStr = mOptions.literal(functionName) + const replaceStr = replace ? ' OR REPLACE' : ''; + const paramsStr = formatParams(functionParams, mOptions); + const functionNameStr = mOptions.literal(functionName); return `CREATE${replaceStr} FUNCTION ${functionNameStr}${paramsStr} RETURNS ${returns} AS ${escapeValue(definition)} - ${options.join('\n ')};` - } - _create.reverse = dropFunction(mOptions) - return _create + ${options.join('\n ')};`; + }; + _create.reverse = dropFunction(mOptions); + return _create; } export function renameFunction(mOptions: MigrationOptions) { - // eslint-disable-next-line default-param-last - const _rename: RenameFunction = (oldFunctionName, functionParams = [], newFunctionName) => { - const paramsStr = formatParams(functionParams, mOptions) - const oldFunctionNameStr = mOptions.literal(oldFunctionName) - const newFunctionNameStr = mOptions.literal(newFunctionName) - return `ALTER FUNCTION ${oldFunctionNameStr}${paramsStr} RENAME TO ${newFunctionNameStr};` - } + const _rename: RenameFunction = ( + oldFunctionName, + // eslint-disable-next-line default-param-last + functionParams = [], + newFunctionName + ) => { + const paramsStr = formatParams(functionParams, mOptions); + const oldFunctionNameStr = mOptions.literal(oldFunctionName); + const newFunctionNameStr = mOptions.literal(newFunctionName); + return `ALTER FUNCTION ${oldFunctionNameStr}${paramsStr} RENAME TO ${newFunctionNameStr};`; + }; _rename.reverse = (oldFunctionName, functionParams, newFunctionName) => - _rename(newFunctionName, functionParams, oldFunctionName) - return _rename + _rename(newFunctionName, functionParams, oldFunctionName); + return _rename; } diff --git a/src/operations/functionsTypes.ts b/src/operations/functionsTypes.ts index 3113f0e0..2e2d6905 100644 --- a/src/operations/functionsTypes.ts +++ b/src/operations/functionsTypes.ts @@ -1,39 +1,39 @@ -import { Name, Value, DropOptions } from './generalTypes' +import { DropOptions, Name, Value } from './generalTypes'; export interface FunctionParamType { - mode?: 'IN' | 'OUT' | 'INOUT' | 'VARIADIC' - name?: string - type: string - default?: Value + mode?: 'IN' | 'OUT' | 'INOUT' | 'VARIADIC'; + name?: string; + type: string; + default?: Value; } -export type FunctionParam = string | FunctionParamType +export type FunctionParam = string | FunctionParamType; export interface FunctionOptions { - returns?: string - language: string - replace?: boolean - window?: boolean - behavior?: 'IMMUTABLE' | 'STABLE' | 'VOLATILE' - onNull?: boolean - parallel?: 'UNSAFE' | 'RESTRICTED' | 'SAFE' + returns?: string; + language: string; + replace?: boolean; + window?: boolean; + behavior?: 'IMMUTABLE' | 'STABLE' | 'VOLATILE'; + onNull?: boolean; + parallel?: 'UNSAFE' | 'RESTRICTED' | 'SAFE'; } type CreateFunctionFn = ( functionName: Name, functionParams: FunctionParam[], functionOptions: FunctionOptions & DropOptions, - definition: Value, -) => string | string[] -export type CreateFunction = CreateFunctionFn & { reverse: CreateFunctionFn } + definition: Value +) => string | string[]; +export type CreateFunction = CreateFunctionFn & { reverse: CreateFunctionFn }; export type DropFunction = ( functionName: Name, functionParams: FunctionParam[], - dropOptions?: DropOptions, -) => string | string[] + dropOptions?: DropOptions +) => string | string[]; type RenameFunctionFn = ( oldFunctionName: Name, functionParams: FunctionParam[], - newFunctionName: Name, -) => string | string[] -export type RenameFunction = RenameFunctionFn & { reverse: RenameFunctionFn } + newFunctionName: Name +) => string | string[]; +export type RenameFunction = RenameFunctionFn & { reverse: RenameFunctionFn }; diff --git a/src/operations/generalTypes.ts b/src/operations/generalTypes.ts index 618c5b99..69d2b6a9 100644 --- a/src/operations/generalTypes.ts +++ b/src/operations/generalTypes.ts @@ -1,28 +1,37 @@ -import PgLiteral from './PgLiteral' +import PgLiteral from './PgLiteral'; // eslint-disable-next-line camelcase -export type LiteralUnion = T | (string & { zz_IGNORE_ME?: never }) -export type PublicPart = { [K in keyof T]: T[K] } +export type LiteralUnion = + | T + | (string & { zz_IGNORE_ME?: never }); +export type PublicPart = { [K in keyof T]: T[K] }; -export type Nullable = { [P in keyof T]: T[P] | null } +export type Nullable = { [P in keyof T]: T[P] | null }; -export type PgLiteralValue = PublicPart -export type Value = null | boolean | string | number | PgLiteral | PgLiteralValue | Value[] +export type PgLiteralValue = PublicPart; +export type Value = + | null + | boolean + | string + | number + | PgLiteral + | PgLiteralValue + | Value[]; -export type Type = string | { type: string } +export type Type = string | { type: string }; -export type Name = string | { schema?: string; name: string } +export type Name = string | { schema?: string; name: string }; export interface IfNotExistsOption { - ifNotExists?: boolean + ifNotExists?: boolean; } export interface IfExistsOption { - ifExists?: boolean + ifExists?: boolean; } export interface CascadeOption { - cascade?: boolean + cascade?: boolean; } -export type DropOptions = IfExistsOption & CascadeOption +export type DropOptions = IfExistsOption & CascadeOption; diff --git a/src/operations/indexes.ts b/src/operations/indexes.ts index 6d9cb4d9..b0fe0a67 100644 --- a/src/operations/indexes.ts +++ b/src/operations/indexes.ts @@ -1,37 +1,50 @@ -import { MigrationOptions, Literal } from '../types' -import { Name } from './generalTypes' -import { DropIndex, CreateIndex, CreateIndexOptions, DropIndexOptions, IndexColumn } from './indexesTypes' +import { Literal, MigrationOptions } from '../types'; +import { Name } from './generalTypes'; +import { + CreateIndex, + CreateIndexOptions, + DropIndex, + DropIndexOptions, + IndexColumn, +} from './indexesTypes'; -export { CreateIndex, DropIndex } +export { CreateIndex, DropIndex }; function generateIndexName( table: Name, columns: (string | IndexColumn)[], options: CreateIndexOptions | DropIndexOptions, - schemalize: Literal, + schemalize: Literal ) { if (options.name) { - return typeof table === 'object' ? { schema: table.schema, name: options.name } : options.name + return typeof table === 'object' + ? { schema: table.schema, name: options.name } + : options.name; } - const cols = columns.map((col) => schemalize(typeof col === 'string' ? col : col.name)).join('_') - const uniq = 'unique' in options && options.unique ? '_unique' : '' + const cols = columns + .map((col) => schemalize(typeof col === 'string' ? col : col.name)) + .join('_'); + const uniq = 'unique' in options && options.unique ? '_unique' : ''; return typeof table === 'object' ? { schema: table.schema, name: `${table.name}_${cols}${uniq}_index`, } - : `${table}_${cols}${uniq}_index` + : `${table}_${cols}${uniq}_index`; } function generateColumnString(column: Name, mOptions: MigrationOptions) { - const name = mOptions.schemalize(column) - const isSpecial = /[. ()]/.test(name) + const name = mOptions.schemalize(column); + const isSpecial = /[. ()]/.test(name); return isSpecial ? name // expression - : mOptions.literal(name) // single column + : mOptions.literal(name); // single column } -function generateColumnsString(columns: (string | IndexColumn)[], mOptions: MigrationOptions) { +function generateColumnsString( + columns: (string | IndexColumn)[], + mOptions: MigrationOptions +) { return columns .map((column) => typeof column === 'string' @@ -42,24 +55,31 @@ function generateColumnsString(columns: (string | IndexColumn)[], mOptions: Migr column.sort, ] .filter((s) => typeof s === 'string' && s !== '') - .join(' '), + .join(' ') ) - .join(', ') + .join(', '); } export function dropIndex(mOptions: MigrationOptions) { const _drop: DropIndex = (tableName, rawColumns, options = {}) => { - const { concurrently, ifExists, cascade } = options - const columns = Array.isArray(rawColumns) ? rawColumns.slice() : [rawColumns] - const concurrentlyStr = concurrently ? ' CONCURRENTLY' : '' - const ifExistsStr = ifExists ? ' IF EXISTS' : '' - const indexName = generateIndexName(tableName, columns, options, mOptions.schemalize) - const cascadeStr = cascade ? ' CASCADE' : '' - const indexNameStr = mOptions.literal(indexName) + const { concurrently, ifExists, cascade } = options; + const columns = Array.isArray(rawColumns) + ? rawColumns.slice() + : [rawColumns]; + const concurrentlyStr = concurrently ? ' CONCURRENTLY' : ''; + const ifExistsStr = ifExists ? ' IF EXISTS' : ''; + const indexName = generateIndexName( + tableName, + columns, + options, + mOptions.schemalize + ); + const cascadeStr = cascade ? ' CASCADE' : ''; + const indexNameStr = mOptions.literal(indexName); - return `DROP INDEX${concurrentlyStr}${ifExistsStr} ${indexNameStr}${cascadeStr};` - } - return _drop + return `DROP INDEX${concurrentlyStr}${ifExistsStr} ${indexNameStr}${cascadeStr};`; + }; + return _drop; } export function createIndex(mOptions: MigrationOptions) { @@ -75,43 +95,50 @@ export function createIndex(mOptions: MigrationOptions) { ifNotExists - optionally create index options.method - [ btree | hash | gist | spgist | gin ] */ - const columns = Array.isArray(rawColumns) ? rawColumns.slice() : [rawColumns] + const columns = Array.isArray(rawColumns) + ? rawColumns.slice() + : [rawColumns]; if (options.opclass) { mOptions.logger.warn( - "Using opclass is deprecated. You should use it as part of column definition e.g. pgm.createIndex('table', [['column', 'opclass', 'ASC']])", - ) - const lastIndex = columns.length - 1 - const lastColumn = columns[lastIndex] + "Using opclass is deprecated. You should use it as part of column definition e.g. pgm.createIndex('table', [['column', 'opclass', 'ASC']])" + ); + const lastIndex = columns.length - 1; + const lastColumn = columns[lastIndex]; if (typeof lastColumn === 'string') { - columns[lastIndex] = { name: lastColumn, opclass: options.opclass } + columns[lastIndex] = { name: lastColumn, opclass: options.opclass }; } else if (lastColumn.opclass) { - throw new Error("There is already defined opclass on column, can't override it with global one") + throw new Error( + "There is already defined opclass on column, can't override it with global one" + ); } else { - columns[lastIndex] = { ...lastColumn, opclass: options.opclass } + columns[lastIndex] = { ...lastColumn, opclass: options.opclass }; } } const indexName = generateIndexName( typeof tableName === 'object' ? tableName.name : tableName, columns, options, - mOptions.schemalize, - ) - const columnsString = generateColumnsString(columns, mOptions) - const unique = options.unique ? ' UNIQUE' : '' - const concurrently = options.concurrently ? ' CONCURRENTLY' : '' - const ifNotExistsStr = options.ifNotExists ? ' IF NOT EXISTS' : '' - const method = options.method ? ` USING ${options.method}` : '' - const where = options.where ? ` WHERE ${options.where}` : '' + mOptions.schemalize + ); + const columnsString = generateColumnsString(columns, mOptions); + const unique = options.unique ? ' UNIQUE' : ''; + const concurrently = options.concurrently ? ' CONCURRENTLY' : ''; + const ifNotExistsStr = options.ifNotExists ? ' IF NOT EXISTS' : ''; + const method = options.method ? ` USING ${options.method}` : ''; + const where = options.where ? ` WHERE ${options.where}` : ''; const include = options.include - ? ` INCLUDE (${(Array.isArray(options.include) ? options.include : [options.include]) + ? ` INCLUDE (${(Array.isArray(options.include) + ? options.include + : [options.include] + ) .map(mOptions.literal) .join(', ')})` - : '' - const indexNameStr = mOptions.literal(indexName) - const tableNameStr = mOptions.literal(tableName) + : ''; + const indexNameStr = mOptions.literal(indexName); + const tableNameStr = mOptions.literal(tableName); - return `CREATE${unique} INDEX${concurrently}${ifNotExistsStr} ${indexNameStr} ON ${tableNameStr}${method} (${columnsString})${include}${where};` - } - _create.reverse = dropIndex(mOptions) - return _create + return `CREATE${unique} INDEX${concurrently}${ifNotExistsStr} ${indexNameStr} ON ${tableNameStr}${method} (${columnsString})${include}${where};`; + }; + _create.reverse = dropIndex(mOptions); + return _create; } diff --git a/src/operations/indexesTypes.ts b/src/operations/indexesTypes.ts index bb4bf823..414e2694 100644 --- a/src/operations/indexesTypes.ts +++ b/src/operations/indexesTypes.ts @@ -1,39 +1,39 @@ -import { Name, DropOptions } from './generalTypes' +import { DropOptions, Name } from './generalTypes'; export interface IndexColumn { - name: string - opclass?: Name - sort?: 'ASC' | 'DESC' + name: string; + opclass?: Name; + sort?: 'ASC' | 'DESC'; } export interface CreateIndexOptions { - name?: string - unique?: boolean - where?: string - concurrently?: boolean - ifNotExists?: boolean + name?: string; + unique?: boolean; + where?: string; + concurrently?: boolean; + ifNotExists?: boolean; /** * @deprecated should be parameter of IndexColumn */ - opclass?: Name - method?: 'btree' | 'hash' | 'gist' | 'spgist' | 'gin' - include?: string | string[] + opclass?: Name; + method?: 'btree' | 'hash' | 'gist' | 'spgist' | 'gin'; + include?: string | string[]; } export interface DropIndexOptions extends DropOptions { - unique?: boolean - name?: string - concurrently?: boolean + unique?: boolean; + name?: string; + concurrently?: boolean; } type CreateIndexFn = ( tableName: Name, columns: string | (string | IndexColumn)[], - options?: CreateIndexOptions & DropIndexOptions, -) => string | string[] -export type CreateIndex = CreateIndexFn & { reverse: CreateIndexFn } + options?: CreateIndexOptions & DropIndexOptions +) => string | string[]; +export type CreateIndex = CreateIndexFn & { reverse: CreateIndexFn }; export type DropIndex = ( tableName: Name, columns: string | (string | IndexColumn)[], - options?: DropIndexOptions, -) => string | string[] + options?: DropIndexOptions +) => string | string[]; diff --git a/src/operations/operators.ts b/src/operations/operators.ts index bddd7b1a..4d9cd1a7 100644 --- a/src/operations/operators.ts +++ b/src/operations/operators.ts @@ -1,18 +1,18 @@ -import { MigrationOptions } from '../types' -import { applyType, formatParams } from '../utils' +import { MigrationOptions } from '../types'; +import { applyType, formatParams } from '../utils'; import { - OperatorListDefinition, + AddToOperatorFamily, CreateOperator, - DropOperator, CreateOperatorClass, - DropOperatorClass, - RenameOperatorClass, CreateOperatorFamily, + DropOperator, + DropOperatorClass, DropOperatorFamily, - AddToOperatorFamily, - RenameOperatorFamily, + OperatorListDefinition, RemoveFromOperatorFamily, -} from './operatorsTypes' + RenameOperatorClass, + RenameOperatorFamily, +} from './operatorsTypes'; export { CreateOperator, @@ -25,174 +25,228 @@ export { AddToOperatorFamily, RenameOperatorFamily, RemoveFromOperatorFamily, -} +}; export function dropOperator(mOptions: MigrationOptions) { const _drop: DropOperator = (operatorName, options = {}) => { - const { ifExists, cascade, left, right } = options + const { ifExists, cascade, left, right } = options; - const operatorNameStr = mOptions.schemalize(operatorName) - const leftStr = mOptions.literal(left || 'none') - const rightStr = mOptions.literal(right || 'none') + const operatorNameStr = mOptions.schemalize(operatorName); + const leftStr = mOptions.literal(left || 'none'); + const rightStr = mOptions.literal(right || 'none'); - const ifExistsStr = ifExists ? ' IF EXISTS' : '' - const cascadeStr = cascade ? ' CASCADE' : '' + const ifExistsStr = ifExists ? ' IF EXISTS' : ''; + const cascadeStr = cascade ? ' CASCADE' : ''; - return `DROP OPERATOR${ifExistsStr} ${operatorNameStr}(${leftStr}, ${rightStr})${cascadeStr};` - } - return _drop + return `DROP OPERATOR${ifExistsStr} ${operatorNameStr}(${leftStr}, ${rightStr})${cascadeStr};`; + }; + return _drop; } export function createOperator(mOptions: MigrationOptions) { const _create: CreateOperator = (operatorName, options) => { - const { procedure, left, right, commutator, negator, restrict, join, hashes, merges } = options || {} - - const defs = [] - defs.push(`PROCEDURE = ${mOptions.literal(procedure)}`) + const { + procedure, + left, + right, + commutator, + negator, + restrict, + join, + hashes, + merges, + } = options || {}; + + const defs = []; + defs.push(`PROCEDURE = ${mOptions.literal(procedure)}`); if (left) { - defs.push(`LEFTARG = ${mOptions.literal(left)}`) + defs.push(`LEFTARG = ${mOptions.literal(left)}`); } if (right) { - defs.push(`RIGHTARG = ${mOptions.literal(right)}`) + defs.push(`RIGHTARG = ${mOptions.literal(right)}`); } if (commutator) { - defs.push(`COMMUTATOR = ${mOptions.schemalize(commutator)}`) + defs.push(`COMMUTATOR = ${mOptions.schemalize(commutator)}`); } if (negator) { - defs.push(`NEGATOR = ${mOptions.schemalize(negator)}`) + defs.push(`NEGATOR = ${mOptions.schemalize(negator)}`); } if (restrict) { - defs.push(`RESTRICT = ${mOptions.literal(restrict)}`) + defs.push(`RESTRICT = ${mOptions.literal(restrict)}`); } if (join) { - defs.push(`JOIN = ${mOptions.literal(join)}`) + defs.push(`JOIN = ${mOptions.literal(join)}`); } if (hashes) { - defs.push('HASHES') + defs.push('HASHES'); } if (merges) { - defs.push('MERGES') + defs.push('MERGES'); } - const operatorNameStr = mOptions.schemalize(operatorName) - return `CREATE OPERATOR ${operatorNameStr} (${defs.join(', ')});` - } - _create.reverse = dropOperator(mOptions) - return _create + const operatorNameStr = mOptions.schemalize(operatorName); + return `CREATE OPERATOR ${operatorNameStr} (${defs.join(', ')});`; + }; + _create.reverse = dropOperator(mOptions); + return _create; } export function dropOperatorFamily(mOptions: MigrationOptions) { - const _drop: DropOperatorFamily = (operatorFamilyName, indexMethod, options = {}) => { - const { ifExists, cascade } = options - const operatorFamilyNameStr = mOptions.literal(operatorFamilyName) - const ifExistsStr = ifExists ? ' IF EXISTS' : '' - const cascadeStr = cascade ? ' CASCADE' : '' - return `DROP OPERATOR FAMILY ${ifExistsStr} ${operatorFamilyNameStr} USING ${indexMethod}${cascadeStr};` - } - return _drop + const _drop: DropOperatorFamily = ( + operatorFamilyName, + indexMethod, + options = {} + ) => { + const { ifExists, cascade } = options; + const operatorFamilyNameStr = mOptions.literal(operatorFamilyName); + const ifExistsStr = ifExists ? ' IF EXISTS' : ''; + const cascadeStr = cascade ? ' CASCADE' : ''; + return `DROP OPERATOR FAMILY ${ifExistsStr} ${operatorFamilyNameStr} USING ${indexMethod}${cascadeStr};`; + }; + return _drop; } export function createOperatorFamily(mOptions: MigrationOptions) { const _create: CreateOperatorFamily = (operatorFamilyName, indexMethod) => { - const operatorFamilyNameStr = mOptions.literal(operatorFamilyName) - return `CREATE OPERATOR FAMILY ${operatorFamilyNameStr} USING ${indexMethod};` - } - _create.reverse = dropOperatorFamily(mOptions) - return _create + const operatorFamilyNameStr = mOptions.literal(operatorFamilyName); + return `CREATE OPERATOR FAMILY ${operatorFamilyNameStr} USING ${indexMethod};`; + }; + _create.reverse = dropOperatorFamily(mOptions); + return _create; } const operatorMap = (mOptions: MigrationOptions) => ({ type, number, name, params = [] }: OperatorListDefinition) => { - const nameStr = mOptions.literal(name) + const nameStr = mOptions.literal(name); if (String(type).toLowerCase() === 'function') { if (params.length > 2) { - throw new Error("Operator can't have more than 2 parameters") + throw new Error("Operator can't have more than 2 parameters"); } - const paramsStr = params.length > 0 ? formatParams(params, mOptions) : '' + const paramsStr = params.length > 0 ? formatParams(params, mOptions) : ''; - return `OPERATOR ${number} ${nameStr}${paramsStr}` + return `OPERATOR ${number} ${nameStr}${paramsStr}`; } if (String(type).toLowerCase() === 'operator') { - const paramsStr = formatParams(params, mOptions) - return `FUNCTION ${number} ${nameStr}${paramsStr}` + const paramsStr = formatParams(params, mOptions); + return `FUNCTION ${number} ${nameStr}${paramsStr}`; } - throw new Error('Operator "type" must be either "function" or "operator"') - } + throw new Error('Operator "type" must be either "function" or "operator"'); + }; export const removeFromOperatorFamily = (mOptions: MigrationOptions) => { - const method: RemoveFromOperatorFamily = (operatorFamilyName, indexMethod, operatorList) => { - const operatorFamilyNameStr = mOptions.literal(operatorFamilyName) - const operatorListStr = operatorList.map(operatorMap(mOptions)).join(',\n ') + const method: RemoveFromOperatorFamily = ( + operatorFamilyName, + indexMethod, + operatorList + ) => { + const operatorFamilyNameStr = mOptions.literal(operatorFamilyName); + const operatorListStr = operatorList + .map(operatorMap(mOptions)) + .join(',\n '); return `ALTER OPERATOR FAMILY ${operatorFamilyNameStr} USING ${indexMethod} DROP - ${operatorListStr};` - } - return method -} + ${operatorListStr};`; + }; + return method; +}; export const addToOperatorFamily = (mOptions: MigrationOptions) => { - const method: AddToOperatorFamily = (operatorFamilyName, indexMethod, operatorList) => { - const operatorFamilyNameStr = mOptions.literal(operatorFamilyName) - const operatorListStr = operatorList.map(operatorMap(mOptions)).join(',\n ') + const method: AddToOperatorFamily = ( + operatorFamilyName, + indexMethod, + operatorList + ) => { + const operatorFamilyNameStr = mOptions.literal(operatorFamilyName); + const operatorListStr = operatorList + .map(operatorMap(mOptions)) + .join(',\n '); return `ALTER OPERATOR FAMILY ${operatorFamilyNameStr} USING ${indexMethod} ADD - ${operatorListStr};` - } - method.reverse = removeFromOperatorFamily(mOptions) - return method -} + ${operatorListStr};`; + }; + method.reverse = removeFromOperatorFamily(mOptions); + return method; +}; export function renameOperatorFamily(mOptions: MigrationOptions) { - const _rename: RenameOperatorFamily = (oldOperatorFamilyName, indexMethod, newOperatorFamilyName) => { - const oldOperatorFamilyNameStr = mOptions.literal(oldOperatorFamilyName) - const newOperatorFamilyNameStr = mOptions.literal(newOperatorFamilyName) - - return `ALTER OPERATOR FAMILY ${oldOperatorFamilyNameStr} USING ${indexMethod} RENAME TO ${newOperatorFamilyNameStr};` - } - _rename.reverse = (oldOperatorFamilyName, indexMethod, newOperatorFamilyName) => - _rename(newOperatorFamilyName, indexMethod, oldOperatorFamilyName) - return _rename + const _rename: RenameOperatorFamily = ( + oldOperatorFamilyName, + indexMethod, + newOperatorFamilyName + ) => { + const oldOperatorFamilyNameStr = mOptions.literal(oldOperatorFamilyName); + const newOperatorFamilyNameStr = mOptions.literal(newOperatorFamilyName); + + return `ALTER OPERATOR FAMILY ${oldOperatorFamilyNameStr} USING ${indexMethod} RENAME TO ${newOperatorFamilyNameStr};`; + }; + _rename.reverse = ( + oldOperatorFamilyName, + indexMethod, + newOperatorFamilyName + ) => _rename(newOperatorFamilyName, indexMethod, oldOperatorFamilyName); + return _rename; } export function dropOperatorClass(mOptions: MigrationOptions) { - const _drop: DropOperatorClass = (operatorClassName, indexMethod, options = {}) => { - const { ifExists, cascade } = options - const operatorClassNameStr = mOptions.literal(operatorClassName) - const ifExistsStr = ifExists ? ' IF EXISTS' : '' - const cascadeStr = cascade ? ' CASCADE' : '' - - return `DROP OPERATOR CLASS ${ifExistsStr} ${operatorClassNameStr} USING ${indexMethod}${cascadeStr};` - } - return _drop + const _drop: DropOperatorClass = ( + operatorClassName, + indexMethod, + options = {} + ) => { + const { ifExists, cascade } = options; + const operatorClassNameStr = mOptions.literal(operatorClassName); + const ifExistsStr = ifExists ? ' IF EXISTS' : ''; + const cascadeStr = cascade ? ' CASCADE' : ''; + + return `DROP OPERATOR CLASS ${ifExistsStr} ${operatorClassNameStr} USING ${indexMethod}${cascadeStr};`; + }; + return _drop; } export function createOperatorClass(mOptions: MigrationOptions) { - const _create: CreateOperatorClass = (operatorClassName, type, indexMethod, operatorList, options) => { - const { default: isDefault, family } = options - const operatorClassNameStr = mOptions.literal(operatorClassName) - const defaultStr = isDefault ? ' DEFAULT' : '' - const typeStr = mOptions.literal(applyType(type).type) - const indexMethodStr = mOptions.literal(indexMethod) - const familyStr = family ? ` FAMILY ${family}` : '' - const operatorListStr = operatorList.map(operatorMap(mOptions)).join(',\n ') + const _create: CreateOperatorClass = ( + operatorClassName, + type, + indexMethod, + operatorList, + options + ) => { + const { default: isDefault, family } = options; + const operatorClassNameStr = mOptions.literal(operatorClassName); + const defaultStr = isDefault ? ' DEFAULT' : ''; + const typeStr = mOptions.literal(applyType(type).type); + const indexMethodStr = mOptions.literal(indexMethod); + const familyStr = family ? ` FAMILY ${family}` : ''; + const operatorListStr = operatorList + .map(operatorMap(mOptions)) + .join(',\n '); return `CREATE OPERATOR CLASS ${operatorClassNameStr}${defaultStr} FOR TYPE ${typeStr} USING ${indexMethodStr} ${familyStr} AS - ${operatorListStr};` - } - _create.reverse = (operatorClassName, type, indexMethod, operatorList, options) => - dropOperatorClass(mOptions)(operatorClassName, indexMethod, options) - return _create + ${operatorListStr};`; + }; + _create.reverse = ( + operatorClassName, + type, + indexMethod, + operatorList, + options + ) => dropOperatorClass(mOptions)(operatorClassName, indexMethod, options); + return _create; } export function renameOperatorClass(mOptions: MigrationOptions) { - const _rename: RenameOperatorClass = (oldOperatorClassName, indexMethod, newOperatorClassName) => { - const oldOperatorClassNameStr = mOptions.literal(oldOperatorClassName) - const newOperatorClassNameStr = mOptions.literal(newOperatorClassName) - - return `ALTER OPERATOR CLASS ${oldOperatorClassNameStr} USING ${indexMethod} RENAME TO ${newOperatorClassNameStr};` - } + const _rename: RenameOperatorClass = ( + oldOperatorClassName, + indexMethod, + newOperatorClassName + ) => { + const oldOperatorClassNameStr = mOptions.literal(oldOperatorClassName); + const newOperatorClassNameStr = mOptions.literal(newOperatorClassName); + + return `ALTER OPERATOR CLASS ${oldOperatorClassNameStr} USING ${indexMethod} RENAME TO ${newOperatorClassNameStr};`; + }; _rename.reverse = (oldOperatorClassName, indexMethod, newOperatorClassName) => - _rename(newOperatorClassName, indexMethod, oldOperatorClassName) - return _rename + _rename(newOperatorClassName, indexMethod, oldOperatorClassName); + return _rename; } diff --git a/src/operations/operatorsTypes.ts b/src/operations/operatorsTypes.ts index 6a8a60e1..1e2726b6 100644 --- a/src/operations/operatorsTypes.ts +++ b/src/operations/operatorsTypes.ts @@ -1,78 +1,98 @@ -import { Name, Type, DropOptions } from './generalTypes' -import { FunctionParam } from './functionsTypes' +import { FunctionParam } from './functionsTypes'; +import { DropOptions, Name, Type } from './generalTypes'; export interface CreateOperatorOptions { - procedure: Name - left?: Name - right?: Name - commutator?: Name - negator?: Name - restrict?: Name - join?: Name - hashes?: boolean - merges?: boolean + procedure: Name; + left?: Name; + right?: Name; + commutator?: Name; + negator?: Name; + restrict?: Name; + join?: Name; + hashes?: boolean; + merges?: boolean; } export interface DropOperatorOptions extends DropOptions { - left?: Name - right?: Name + left?: Name; + right?: Name; } export interface CreateOperatorClassOptions { - default?: boolean - family?: string + default?: boolean; + family?: string; } export interface OperatorListDefinition { - type: 'function' | 'operator' - number: number - name: Name - params?: FunctionParam[] + type: 'function' | 'operator'; + number: number; + name: Name; + params?: FunctionParam[]; } -type CreateOperatorFn = (operatorName: Name, options: CreateOperatorOptions & DropOperatorOptions) => string | string[] -export type CreateOperator = CreateOperatorFn & { reverse: CreateOperatorFn } -export type DropOperator = (operatorName: Name, dropOptions?: DropOperatorOptions) => string | string[] +type CreateOperatorFn = ( + operatorName: Name, + options: CreateOperatorOptions & DropOperatorOptions +) => string | string[]; +export type CreateOperator = CreateOperatorFn & { reverse: CreateOperatorFn }; +export type DropOperator = ( + operatorName: Name, + dropOptions?: DropOperatorOptions +) => string | string[]; type CreateOperatorClassFn = ( operatorClassName: Name, type: Type, indexMethod: Name, operatorList: OperatorListDefinition[], - options: CreateOperatorClassOptions & DropOptions, -) => string | string[] -export type CreateOperatorClass = CreateOperatorClassFn & { reverse: CreateOperatorClassFn } + options: CreateOperatorClassOptions & DropOptions +) => string | string[]; +export type CreateOperatorClass = CreateOperatorClassFn & { + reverse: CreateOperatorClassFn; +}; export type DropOperatorClass = ( operatorClassName: Name, indexMethod: Name, - dropOptions?: DropOptions, -) => string | string[] + dropOptions?: DropOptions +) => string | string[]; type RenameOperatorClassFn = ( oldOperatorClassName: Name, indexMethod: Name, - newOperatorClassName: Name, -) => string | string[] -export type RenameOperatorClass = RenameOperatorClassFn & { reverse: RenameOperatorClassFn } -type CreateOperatorFamilyFn = (operatorFamilyName: Name, indexMethod: Name, options?: DropOptions) => string | string[] -export type CreateOperatorFamily = CreateOperatorFamilyFn & { reverse: CreateOperatorFamilyFn } + newOperatorClassName: Name +) => string | string[]; +export type RenameOperatorClass = RenameOperatorClassFn & { + reverse: RenameOperatorClassFn; +}; +type CreateOperatorFamilyFn = ( + operatorFamilyName: Name, + indexMethod: Name, + options?: DropOptions +) => string | string[]; +export type CreateOperatorFamily = CreateOperatorFamilyFn & { + reverse: CreateOperatorFamilyFn; +}; export type DropOperatorFamily = ( operatorFamilyName: Name, newSchemaName: Name, - dropOptions?: DropOptions, -) => string | string[] + dropOptions?: DropOptions +) => string | string[]; type RenameOperatorFamilyFn = ( oldOperatorFamilyName: Name, indexMethod: Name, - newOperatorFamilyName: Name, -) => string | string[] -export type RenameOperatorFamily = RenameOperatorFamilyFn & { reverse: RenameOperatorFamilyFn } + newOperatorFamilyName: Name +) => string | string[]; +export type RenameOperatorFamily = RenameOperatorFamilyFn & { + reverse: RenameOperatorFamilyFn; +}; type AddToOperatorFamilyFn = ( operatorFamilyName: Name, indexMethod: Name, - operatorList: OperatorListDefinition[], -) => string | string[] -export type AddToOperatorFamily = AddToOperatorFamilyFn & { reverse: AddToOperatorFamilyFn } + operatorList: OperatorListDefinition[] +) => string | string[]; +export type AddToOperatorFamily = AddToOperatorFamilyFn & { + reverse: AddToOperatorFamilyFn; +}; export type RemoveFromOperatorFamily = ( operatorFamilyName: Name, indexMethod: Name, - operatorList: OperatorListDefinition[], -) => string | string[] + operatorList: OperatorListDefinition[] +) => string | string[]; diff --git a/src/operations/other.ts b/src/operations/other.ts index ff110452..ae27add0 100644 --- a/src/operations/other.ts +++ b/src/operations/other.ts @@ -1,18 +1,18 @@ -import { MigrationOptions } from '../types' -import { createTransformer } from '../utils' -import { Sql } from './othersTypes' +import { MigrationOptions } from '../types'; +import { createTransformer } from '../utils'; +import { Sql } from './othersTypes'; -export { Sql } +export { Sql }; export function sql(mOptions: MigrationOptions): Sql { - const t = createTransformer(mOptions.literal) + const t = createTransformer(mOptions.literal); return (sqlStr, args) => { // applies some very basic templating using the utils.p - let s: string = t(sqlStr, args) + let s: string = t(sqlStr, args); // add trailing ; if not present if (s.lastIndexOf(';') !== s.length - 1) { - s += ';' + s += ';'; } - return s - } + return s; + }; } diff --git a/src/operations/othersTypes.ts b/src/operations/othersTypes.ts index a67ac493..89edbf4e 100644 --- a/src/operations/othersTypes.ts +++ b/src/operations/othersTypes.ts @@ -1,4 +1,7 @@ -import { Value } from '..' -import { Name } from './generalTypes' +import { Value } from '..'; +import { Name } from './generalTypes'; -export type Sql = (sqlStr: string, args?: { [key: string]: Name | Value }) => string | string[] +export type Sql = ( + sqlStr: string, + args?: { [key: string]: Name | Value } +) => string | string[]; diff --git a/src/operations/policies.ts b/src/operations/policies.ts index be5ca145..6aabf655 100644 --- a/src/operations/policies.ts +++ b/src/operations/policies.ts @@ -1,32 +1,38 @@ -import { MigrationOptions } from '../types' -import { PolicyOptions, CreatePolicy, DropPolicy, AlterPolicy, RenamePolicy } from './policiesTypes' +import { MigrationOptions } from '../types'; +import { + AlterPolicy, + CreatePolicy, + DropPolicy, + PolicyOptions, + RenamePolicy, +} from './policiesTypes'; -export { CreatePolicy, DropPolicy, AlterPolicy, RenamePolicy } +export { CreatePolicy, DropPolicy, AlterPolicy, RenamePolicy }; const makeClauses = ({ role, using, check }: PolicyOptions) => { - const roles = (Array.isArray(role) ? role : [role]).join(', ') - const clauses: string[] = [] + const roles = (Array.isArray(role) ? role : [role]).join(', '); + const clauses: string[] = []; if (roles) { - clauses.push(`TO ${roles}`) + clauses.push(`TO ${roles}`); } if (using) { - clauses.push(`USING (${using})`) + clauses.push(`USING (${using})`); } if (check) { - clauses.push(`WITH CHECK (${check})`) + clauses.push(`WITH CHECK (${check})`); } - return clauses -} + return clauses; +}; export function dropPolicy(mOptions: MigrationOptions) { const _drop: DropPolicy = (tableName, policyName, options = {}) => { - const { ifExists } = options - const ifExistsStr = ifExists ? ' IF EXISTS' : '' - const policyNameStr = mOptions.literal(policyName) - const tableNameStr = mOptions.literal(tableName) - return `DROP POLICY${ifExistsStr} ${policyNameStr} ON ${tableNameStr};` - } - return _drop + const { ifExists } = options; + const ifExistsStr = ifExists ? ' IF EXISTS' : ''; + const policyNameStr = mOptions.literal(policyName); + const tableNameStr = mOptions.literal(tableName); + return `DROP POLICY${ifExistsStr} ${policyNameStr} ON ${tableNameStr};`; + }; + return _drop; } export function createPolicy(mOptions: MigrationOptions) { @@ -34,34 +40,38 @@ export function createPolicy(mOptions: MigrationOptions) { const createOptions = { ...options, role: options.role || 'PUBLIC', - } - const clauses = [`FOR ${options.command || 'ALL'}`, ...makeClauses(createOptions)] - const clausesStr = clauses.join(' ') - const policyNameStr = mOptions.literal(policyName) - const tableNameStr = mOptions.literal(tableName) - return `CREATE POLICY ${policyNameStr} ON ${tableNameStr} ${clausesStr};` - } - _create.reverse = dropPolicy(mOptions) - return _create + }; + const clauses = [ + `FOR ${options.command || 'ALL'}`, + ...makeClauses(createOptions), + ]; + const clausesStr = clauses.join(' '); + const policyNameStr = mOptions.literal(policyName); + const tableNameStr = mOptions.literal(tableName); + return `CREATE POLICY ${policyNameStr} ON ${tableNameStr} ${clausesStr};`; + }; + _create.reverse = dropPolicy(mOptions); + return _create; } export function alterPolicy(mOptions: MigrationOptions) { const _alter: AlterPolicy = (tableName, policyName, options = {}) => { - const clausesStr = makeClauses(options).join(' ') - const policyNameStr = mOptions.literal(policyName) - const tableNameStr = mOptions.literal(tableName) - return `ALTER POLICY ${policyNameStr} ON ${tableNameStr} ${clausesStr};` - } - return _alter + const clausesStr = makeClauses(options).join(' '); + const policyNameStr = mOptions.literal(policyName); + const tableNameStr = mOptions.literal(tableName); + return `ALTER POLICY ${policyNameStr} ON ${tableNameStr} ${clausesStr};`; + }; + return _alter; } export function renamePolicy(mOptions: MigrationOptions) { const _rename: RenamePolicy = (tableName, policyName, newPolicyName) => { - const policyNameStr = mOptions.literal(policyName) - const newPolicyNameStr = mOptions.literal(newPolicyName) - const tableNameStr = mOptions.literal(tableName) - return `ALTER POLICY ${policyNameStr} ON ${tableNameStr} RENAME TO ${newPolicyNameStr};` - } - _rename.reverse = (tableName, policyName, newPolicyName) => _rename(tableName, newPolicyName, policyName) - return _rename + const policyNameStr = mOptions.literal(policyName); + const newPolicyNameStr = mOptions.literal(newPolicyName); + const tableNameStr = mOptions.literal(tableName); + return `ALTER POLICY ${policyNameStr} ON ${tableNameStr} RENAME TO ${newPolicyNameStr};`; + }; + _rename.reverse = (tableName, policyName, newPolicyName) => + _rename(tableName, newPolicyName, policyName); + return _rename; } diff --git a/src/operations/policiesTypes.ts b/src/operations/policiesTypes.ts index b4005a39..8f2de7c2 100644 --- a/src/operations/policiesTypes.ts +++ b/src/operations/policiesTypes.ts @@ -1,24 +1,36 @@ -import { Name, IfExistsOption } from './generalTypes' +import { IfExistsOption, Name } from './generalTypes'; export interface PolicyOptions { - role?: string | string[] - using?: string - check?: string + role?: string | string[]; + using?: string; + check?: string; } interface CreatePolicyOptionsEn { - command?: 'ALL' | 'SELECT' | 'INSERT' | 'UPDATE' | 'DELETE' + command?: 'ALL' | 'SELECT' | 'INSERT' | 'UPDATE' | 'DELETE'; } -export type CreatePolicyOptions = CreatePolicyOptionsEn & PolicyOptions +export type CreatePolicyOptions = CreatePolicyOptionsEn & PolicyOptions; type CreatePolicyFn = ( tableName: Name, policyName: string, - options?: CreatePolicyOptions & IfExistsOption, -) => string | string[] -export type CreatePolicy = CreatePolicyFn & { reverse: CreatePolicyFn } -export type DropPolicy = (tableName: Name, policyName: string, options?: IfExistsOption) => string | string[] -export type AlterPolicy = (tableName: Name, policyName: string, options: PolicyOptions) => string | string[] -type RenamePolicyFn = (tableName: Name, policyName: string, newPolicyName: string) => string | string[] -export type RenamePolicy = RenamePolicyFn & { reverse: RenamePolicyFn } + options?: CreatePolicyOptions & IfExistsOption +) => string | string[]; +export type CreatePolicy = CreatePolicyFn & { reverse: CreatePolicyFn }; +export type DropPolicy = ( + tableName: Name, + policyName: string, + options?: IfExistsOption +) => string | string[]; +export type AlterPolicy = ( + tableName: Name, + policyName: string, + options: PolicyOptions +) => string | string[]; +type RenamePolicyFn = ( + tableName: Name, + policyName: string, + newPolicyName: string +) => string | string[]; +export type RenamePolicy = RenamePolicyFn & { reverse: RenamePolicyFn }; diff --git a/src/operations/roles.ts b/src/operations/roles.ts index 17b709b1..3e91229f 100644 --- a/src/operations/roles.ts +++ b/src/operations/roles.ts @@ -1,67 +1,82 @@ -import { MigrationOptions } from '../types' -import { escapeValue } from '../utils' -import { CreateRole, DropRole, AlterRole, RenameRole, RoleOptions } from './rolesTypes' +import { MigrationOptions } from '../types'; +import { escapeValue } from '../utils'; +import { + AlterRole, + CreateRole, + DropRole, + RenameRole, + RoleOptions, +} from './rolesTypes'; -export { CreateRole, DropRole, AlterRole, RenameRole } +export { CreateRole, DropRole, AlterRole, RenameRole }; const formatRoleOptions = (roleOptions: RoleOptions = {}) => { - const options = [] + const options = []; if (roleOptions.superuser !== undefined) { - options.push(roleOptions.superuser ? 'SUPERUSER' : 'NOSUPERUSER') + options.push(roleOptions.superuser ? 'SUPERUSER' : 'NOSUPERUSER'); } if (roleOptions.createdb !== undefined) { - options.push(roleOptions.createdb ? 'CREATEDB' : 'NOCREATEDB') + options.push(roleOptions.createdb ? 'CREATEDB' : 'NOCREATEDB'); } if (roleOptions.createrole !== undefined) { - options.push(roleOptions.createrole ? 'CREATEROLE' : 'NOCREATEROLE') + options.push(roleOptions.createrole ? 'CREATEROLE' : 'NOCREATEROLE'); } if (roleOptions.inherit !== undefined) { - options.push(roleOptions.inherit ? 'INHERIT' : 'NOINHERIT') + options.push(roleOptions.inherit ? 'INHERIT' : 'NOINHERIT'); } if (roleOptions.login !== undefined) { - options.push(roleOptions.login ? 'LOGIN' : 'NOLOGIN') + options.push(roleOptions.login ? 'LOGIN' : 'NOLOGIN'); } if (roleOptions.replication !== undefined) { - options.push(roleOptions.replication ? 'REPLICATION' : 'NOREPLICATION') + options.push(roleOptions.replication ? 'REPLICATION' : 'NOREPLICATION'); } if (roleOptions.bypassrls !== undefined) { - options.push(roleOptions.bypassrls ? 'BYPASSRLS' : 'NOBYPASSRLS') + options.push(roleOptions.bypassrls ? 'BYPASSRLS' : 'NOBYPASSRLS'); } if (roleOptions.limit) { - options.push(`CONNECTION LIMIT ${Number(roleOptions.limit)}`) + options.push(`CONNECTION LIMIT ${Number(roleOptions.limit)}`); } if (roleOptions.password !== undefined) { - const encrypted = roleOptions.encrypted === false ? 'UNENCRYPTED' : 'ENCRYPTED' - options.push(`${encrypted} PASSWORD ${escapeValue(roleOptions.password)}`) + const encrypted = + roleOptions.encrypted === false ? 'UNENCRYPTED' : 'ENCRYPTED'; + options.push(`${encrypted} PASSWORD ${escapeValue(roleOptions.password)}`); } if (roleOptions.valid !== undefined) { - const valid = roleOptions.valid ? escapeValue(roleOptions.valid) : "'infinity'" - options.push(`VALID UNTIL ${valid}`) + const valid = roleOptions.valid + ? escapeValue(roleOptions.valid) + : "'infinity'"; + options.push(`VALID UNTIL ${valid}`); } if (roleOptions.inRole) { - const inRole = Array.isArray(roleOptions.inRole) ? roleOptions.inRole.join(',') : roleOptions.inRole - options.push(`IN ROLE ${inRole}`) + const inRole = Array.isArray(roleOptions.inRole) + ? roleOptions.inRole.join(',') + : roleOptions.inRole; + options.push(`IN ROLE ${inRole}`); } if (roleOptions.role) { - const role = Array.isArray(roleOptions.role) ? roleOptions.role.join(',') : roleOptions.role - options.push(`ROLE ${role}`) + const role = Array.isArray(roleOptions.role) + ? roleOptions.role.join(',') + : roleOptions.role; + options.push(`ROLE ${role}`); } if (roleOptions.admin) { - const admin = Array.isArray(roleOptions.admin) ? roleOptions.admin.join(',') : roleOptions.admin - options.push(`ADMIN ${admin}`) + const admin = Array.isArray(roleOptions.admin) + ? roleOptions.admin.join(',') + : roleOptions.admin; + options.push(`ADMIN ${admin}`); } - return options.join(' ') -} + return options.join(' '); +}; export function dropRole(mOptions: MigrationOptions) { const _drop: DropRole = (roleName, options = {}) => { - const { ifExists } = options - const ifExistsStr = ifExists ? ' IF EXISTS' : '' - const roleNameStr = mOptions.literal(roleName) - return `DROP ROLE${ifExistsStr} ${roleNameStr};` - } - return _drop + const { ifExists } = options; + const ifExistsStr = ifExists ? ' IF EXISTS' : ''; + const roleNameStr = mOptions.literal(roleName); + return `DROP ROLE${ifExistsStr} ${roleNameStr};`; + }; + return _drop; } export function createRole(mOptions: MigrationOptions) { @@ -74,28 +89,31 @@ export function createRole(mOptions: MigrationOptions) { inherit: roleOptions.inherit !== false, login: roleOptions.login || false, replication: roleOptions.replication || false, - }) - const optionsStr = options ? ` WITH ${options}` : '' - return `CREATE ROLE ${mOptions.literal(roleName)}${optionsStr};` - } - _create.reverse = dropRole(mOptions) - return _create + }); + const optionsStr = options ? ` WITH ${options}` : ''; + return `CREATE ROLE ${mOptions.literal(roleName)}${optionsStr};`; + }; + _create.reverse = dropRole(mOptions); + return _create; } export function alterRole(mOptions: MigrationOptions) { const _alter: AlterRole = (roleName, roleOptions = {}) => { - const options = formatRoleOptions(roleOptions) - return options ? `ALTER ROLE ${mOptions.literal(roleName)} WITH ${options};` : '' - } - return _alter + const options = formatRoleOptions(roleOptions); + return options + ? `ALTER ROLE ${mOptions.literal(roleName)} WITH ${options};` + : ''; + }; + return _alter; } export function renameRole(mOptions: MigrationOptions) { const _rename: RenameRole = (oldRoleName, newRoleName) => { - const oldRoleNameStr = mOptions.literal(oldRoleName) - const newRoleNameStr = mOptions.literal(newRoleName) - return `ALTER ROLE ${oldRoleNameStr} RENAME TO ${newRoleNameStr};` - } - _rename.reverse = (oldRoleName, newRoleName) => _rename(newRoleName, oldRoleName) - return _rename + const oldRoleNameStr = mOptions.literal(oldRoleName); + const newRoleNameStr = mOptions.literal(newRoleName); + return `ALTER ROLE ${oldRoleNameStr} RENAME TO ${newRoleNameStr};`; + }; + _rename.reverse = (oldRoleName, newRoleName) => + _rename(newRoleName, oldRoleName); + return _rename; } diff --git a/src/operations/rolesTypes.ts b/src/operations/rolesTypes.ts index 3ef8e9ac..ebfddcc8 100644 --- a/src/operations/rolesTypes.ts +++ b/src/operations/rolesTypes.ts @@ -1,25 +1,34 @@ -import { Name, Value, IfExistsOption } from './generalTypes' +import { IfExistsOption, Name, Value } from './generalTypes'; export interface RoleOptions { - superuser?: boolean - createdb?: boolean - createrole?: boolean - inherit?: boolean - login?: boolean - replication?: boolean - bypassrls?: boolean - limit?: number - password?: Value - encrypted?: boolean - valid?: Value - inRole?: string | string[] - role?: string | string[] - admin?: string | string[] + superuser?: boolean; + createdb?: boolean; + createrole?: boolean; + inherit?: boolean; + login?: boolean; + replication?: boolean; + bypassrls?: boolean; + limit?: number; + password?: Value; + encrypted?: boolean; + valid?: Value; + inRole?: string | string[]; + role?: string | string[]; + admin?: string | string[]; } -type CreateRoleFn = (roleName: Name, roleOptions?: RoleOptions & IfExistsOption) => string | string[] -export type CreateRole = CreateRoleFn & { reverse: CreateRoleFn } -export type DropRole = (roleName: Name, options?: IfExistsOption) => string | string[] -export type AlterRole = (roleName: Name, roleOptions: RoleOptions) => string | string[] -type RenameRoleFn = (oldRoleName: Name, newRoleName: Name) => string | string[] -export type RenameRole = RenameRoleFn & { reverse: RenameRoleFn } +type CreateRoleFn = ( + roleName: Name, + roleOptions?: RoleOptions & IfExistsOption +) => string | string[]; +export type CreateRole = CreateRoleFn & { reverse: CreateRoleFn }; +export type DropRole = ( + roleName: Name, + options?: IfExistsOption +) => string | string[]; +export type AlterRole = ( + roleName: Name, + roleOptions: RoleOptions +) => string | string[]; +type RenameRoleFn = (oldRoleName: Name, newRoleName: Name) => string | string[]; +export type RenameRole = RenameRoleFn & { reverse: RenameRoleFn }; diff --git a/src/operations/schemas.ts b/src/operations/schemas.ts index df68f239..84951bb3 100644 --- a/src/operations/schemas.ts +++ b/src/operations/schemas.ts @@ -1,37 +1,40 @@ -import { MigrationOptions } from '../types' -import { CreateSchema, DropSchema, RenameSchema } from './schemasTypes' +import { MigrationOptions } from '../types'; +import { CreateSchema, DropSchema, RenameSchema } from './schemasTypes'; -export { CreateSchema, DropSchema, RenameSchema } +export { CreateSchema, DropSchema, RenameSchema }; export function dropSchema(mOptions: MigrationOptions) { const _drop: DropSchema = (schemaName, options = {}) => { - const { ifExists, cascade } = options - const ifExistsStr = ifExists ? ' IF EXISTS' : '' - const cascadeStr = cascade ? ' CASCADE' : '' - const schemaNameStr = mOptions.literal(schemaName) - return `DROP SCHEMA${ifExistsStr} ${schemaNameStr}${cascadeStr};` - } - return _drop + const { ifExists, cascade } = options; + const ifExistsStr = ifExists ? ' IF EXISTS' : ''; + const cascadeStr = cascade ? ' CASCADE' : ''; + const schemaNameStr = mOptions.literal(schemaName); + return `DROP SCHEMA${ifExistsStr} ${schemaNameStr}${cascadeStr};`; + }; + return _drop; } export function createSchema(mOptions: MigrationOptions) { const _create: CreateSchema = (schemaName: string, options = {}) => { - const { ifNotExists, authorization } = options - const ifNotExistsStr = ifNotExists ? ' IF NOT EXISTS' : '' - const schemaNameStr = mOptions.literal(schemaName) - const authorizationStr = authorization ? ` AUTHORIZATION ${authorization}` : '' - return `CREATE SCHEMA${ifNotExistsStr} ${schemaNameStr}${authorizationStr};` - } - _create.reverse = dropSchema(mOptions) - return _create + const { ifNotExists, authorization } = options; + const ifNotExistsStr = ifNotExists ? ' IF NOT EXISTS' : ''; + const schemaNameStr = mOptions.literal(schemaName); + const authorizationStr = authorization + ? ` AUTHORIZATION ${authorization}` + : ''; + return `CREATE SCHEMA${ifNotExistsStr} ${schemaNameStr}${authorizationStr};`; + }; + _create.reverse = dropSchema(mOptions); + return _create; } export function renameSchema(mOptions: MigrationOptions) { const _rename: RenameSchema = (schemaName, newSchemaName) => { - const schemaNameStr = mOptions.literal(schemaName) - const newSchemaNameStr = mOptions.literal(newSchemaName) - return `ALTER SCHEMA ${schemaNameStr} RENAME TO ${newSchemaNameStr};` - } - _rename.reverse = (schemaName, newSchemaName) => _rename(newSchemaName, schemaName) - return _rename + const schemaNameStr = mOptions.literal(schemaName); + const newSchemaNameStr = mOptions.literal(newSchemaName); + return `ALTER SCHEMA ${schemaNameStr} RENAME TO ${newSchemaNameStr};`; + }; + _rename.reverse = (schemaName, newSchemaName) => + _rename(newSchemaName, schemaName); + return _rename; } diff --git a/src/operations/schemasTypes.ts b/src/operations/schemasTypes.ts index 6e89f828..e34b8fd0 100644 --- a/src/operations/schemasTypes.ts +++ b/src/operations/schemasTypes.ts @@ -1,11 +1,20 @@ -import { DropOptions, IfNotExistsOption } from './generalTypes' +import { DropOptions, IfNotExistsOption } from './generalTypes'; export interface CreateSchemaOptions extends IfNotExistsOption { - authorization?: string + authorization?: string; } -type CreateSchemaFn = (schemaName: string, schemaOptions?: CreateSchemaOptions & DropOptions) => string | string[] -export type CreateSchema = CreateSchemaFn & { reverse: CreateSchemaFn } -export type DropSchema = (schemaName: string, dropOptions?: DropOptions) => string | string[] -type RenameSchemaFn = (oldSchemaName: string, newSchemaName: string) => string | string[] -export type RenameSchema = RenameSchemaFn & { reverse: RenameSchemaFn } +type CreateSchemaFn = ( + schemaName: string, + schemaOptions?: CreateSchemaOptions & DropOptions +) => string | string[]; +export type CreateSchema = CreateSchemaFn & { reverse: CreateSchemaFn }; +export type DropSchema = ( + schemaName: string, + dropOptions?: DropOptions +) => string | string[]; +type RenameSchemaFn = ( + oldSchemaName: string, + newSchemaName: string +) => string | string[]; +export type RenameSchema = RenameSchemaFn & { reverse: RenameSchemaFn }; diff --git a/src/operations/sequences.ts b/src/operations/sequences.ts index b9a4e772..14a94a76 100644 --- a/src/operations/sequences.ts +++ b/src/operations/sequences.ts @@ -1,95 +1,109 @@ -import { MigrationOptions } from '../types' -import { applyType } from '../utils' -import { SequenceOptions, CreateSequence, DropSequence, AlterSequence, RenameSequence } from './sequencesTypes' -import { ColumnDefinitions } from './tablesTypes' +import { MigrationOptions } from '../types'; +import { applyType } from '../utils'; +import { + AlterSequence, + CreateSequence, + DropSequence, + RenameSequence, + SequenceOptions, +} from './sequencesTypes'; +import { ColumnDefinitions } from './tablesTypes'; -export { CreateSequence, DropSequence, AlterSequence, RenameSequence } +export { CreateSequence, DropSequence, AlterSequence, RenameSequence }; -export const parseSequenceOptions = (typeShorthands: ColumnDefinitions | undefined, options: SequenceOptions) => { - const { type, increment, minvalue, maxvalue, start, cache, cycle, owner } = options - const clauses: string[] = [] +export const parseSequenceOptions = ( + typeShorthands: ColumnDefinitions | undefined, + options: SequenceOptions +) => { + const { type, increment, minvalue, maxvalue, start, cache, cycle, owner } = + options; + const clauses: string[] = []; if (type) { - clauses.push(`AS ${applyType(type, typeShorthands).type}`) + clauses.push(`AS ${applyType(type, typeShorthands).type}`); } if (increment) { - clauses.push(`INCREMENT BY ${increment}`) + clauses.push(`INCREMENT BY ${increment}`); } if (minvalue) { - clauses.push(`MINVALUE ${minvalue}`) + clauses.push(`MINVALUE ${minvalue}`); } else if (minvalue === null || minvalue === false) { - clauses.push('NO MINVALUE') + clauses.push('NO MINVALUE'); } if (maxvalue) { - clauses.push(`MAXVALUE ${maxvalue}`) + clauses.push(`MAXVALUE ${maxvalue}`); } else if (maxvalue === null || maxvalue === false) { - clauses.push('NO MAXVALUE') + clauses.push('NO MAXVALUE'); } if (start) { - clauses.push(`START WITH ${start}`) + clauses.push(`START WITH ${start}`); } if (cache) { - clauses.push(`CACHE ${cache}`) + clauses.push(`CACHE ${cache}`); } if (cycle) { - clauses.push('CYCLE') + clauses.push('CYCLE'); } else if (cycle === false) { - clauses.push('NO CYCLE') + clauses.push('NO CYCLE'); } if (owner) { - clauses.push(`OWNED BY ${owner}`) + clauses.push(`OWNED BY ${owner}`); } else if (owner === null || owner === false) { - clauses.push('OWNED BY NONE') + clauses.push('OWNED BY NONE'); } - return clauses -} + return clauses; +}; export function dropSequence(mOptions: MigrationOptions) { const _drop: DropSequence = (sequenceName, options = {}) => { - const { ifExists, cascade } = options - const ifExistsStr = ifExists ? ' IF EXISTS' : '' - const cascadeStr = cascade ? ' CASCADE' : '' - const sequenceNameStr = mOptions.literal(sequenceName) - return `DROP SEQUENCE${ifExistsStr} ${sequenceNameStr}${cascadeStr};` - } - return _drop + const { ifExists, cascade } = options; + const ifExistsStr = ifExists ? ' IF EXISTS' : ''; + const cascadeStr = cascade ? ' CASCADE' : ''; + const sequenceNameStr = mOptions.literal(sequenceName); + return `DROP SEQUENCE${ifExistsStr} ${sequenceNameStr}${cascadeStr};`; + }; + return _drop; } export function createSequence(mOptions: MigrationOptions) { const _create: CreateSequence = (sequenceName, options = {}) => { - const { temporary, ifNotExists } = options - const temporaryStr = temporary ? ' TEMPORARY' : '' - const ifNotExistsStr = ifNotExists ? ' IF NOT EXISTS' : '' - const sequenceNameStr = mOptions.literal(sequenceName) - const clausesStr = parseSequenceOptions(mOptions.typeShorthands, options).join('\n ') + const { temporary, ifNotExists } = options; + const temporaryStr = temporary ? ' TEMPORARY' : ''; + const ifNotExistsStr = ifNotExists ? ' IF NOT EXISTS' : ''; + const sequenceNameStr = mOptions.literal(sequenceName); + const clausesStr = parseSequenceOptions( + mOptions.typeShorthands, + options + ).join('\n '); return `CREATE${temporaryStr} SEQUENCE${ifNotExistsStr} ${sequenceNameStr} - ${clausesStr};` - } - _create.reverse = dropSequence(mOptions) - return _create + ${clausesStr};`; + }; + _create.reverse = dropSequence(mOptions); + return _create; } export function alterSequence(mOptions: MigrationOptions): AlterSequence { return (sequenceName, options) => { - const { restart } = options - const clauses = parseSequenceOptions(mOptions.typeShorthands, options) + const { restart } = options; + const clauses = parseSequenceOptions(mOptions.typeShorthands, options); if (restart) { if (restart === true) { - clauses.push('RESTART') + clauses.push('RESTART'); } else { - clauses.push(`RESTART WITH ${restart}`) + clauses.push(`RESTART WITH ${restart}`); } } return `ALTER SEQUENCE ${mOptions.literal(sequenceName)} - ${clauses.join('\n ')};` - } + ${clauses.join('\n ')};`; + }; } export function renameSequence(mOptions: MigrationOptions) { const _rename: RenameSequence = (sequenceName, newSequenceName) => { - const sequenceNameStr = mOptions.literal(sequenceName) - const newSequenceNameStr = mOptions.literal(newSequenceName) - return `ALTER SEQUENCE ${sequenceNameStr} RENAME TO ${newSequenceNameStr};` - } - _rename.reverse = (sequenceName, newSequenceName) => _rename(newSequenceName, sequenceName) - return _rename + const sequenceNameStr = mOptions.literal(sequenceName); + const newSequenceNameStr = mOptions.literal(newSequenceName); + return `ALTER SEQUENCE ${sequenceNameStr} RENAME TO ${newSequenceNameStr};`; + }; + _rename.reverse = (sequenceName, newSequenceName) => + _rename(newSequenceName, sequenceName); + return _rename; } diff --git a/src/operations/sequencesTypes.ts b/src/operations/sequencesTypes.ts index 78e3c339..6568bcc2 100644 --- a/src/operations/sequencesTypes.ts +++ b/src/operations/sequencesTypes.ts @@ -1,27 +1,41 @@ -import { Name, Type, DropOptions, IfNotExistsOption } from './generalTypes' +import { DropOptions, IfNotExistsOption, Name, Type } from './generalTypes'; export interface SequenceOptions { - type?: Type - increment?: number - minvalue?: number | null | false - maxvalue?: number | null | false - start?: number - cache?: number - cycle?: boolean - owner?: string | null | false + type?: Type; + increment?: number; + minvalue?: number | null | false; + maxvalue?: number | null | false; + start?: number; + cache?: number; + cycle?: boolean; + owner?: string | null | false; } -export interface SequenceOptionsCreate extends SequenceOptions, IfNotExistsOption { - temporary?: boolean +export interface SequenceOptionsCreate + extends SequenceOptions, + IfNotExistsOption { + temporary?: boolean; } export interface SequenceOptionsAlter extends SequenceOptions { - restart?: number | true + restart?: number | true; } -type CreateSequenceFn = (sequenceName: Name, sequenceOptions?: SequenceOptionsCreate & DropOptions) => string | string[] -export type CreateSequence = CreateSequenceFn & { reverse: CreateSequenceFn } -export type DropSequence = (sequenceName: Name, dropOptions?: DropOptions) => string | string[] -export type AlterSequence = (sequenceName: Name, sequenceOptions: SequenceOptionsAlter) => string | string[] -type RenameSequenceFn = (oldSequenceName: Name, newSequenceName: Name) => string | string[] -export type RenameSequence = RenameSequenceFn & { reverse: RenameSequenceFn } +type CreateSequenceFn = ( + sequenceName: Name, + sequenceOptions?: SequenceOptionsCreate & DropOptions +) => string | string[]; +export type CreateSequence = CreateSequenceFn & { reverse: CreateSequenceFn }; +export type DropSequence = ( + sequenceName: Name, + dropOptions?: DropOptions +) => string | string[]; +export type AlterSequence = ( + sequenceName: Name, + sequenceOptions: SequenceOptionsAlter +) => string | string[]; +type RenameSequenceFn = ( + oldSequenceName: Name, + newSequenceName: Name +) => string | string[]; +export type RenameSequence = RenameSequenceFn & { reverse: RenameSequenceFn }; diff --git a/src/operations/tables.ts b/src/operations/tables.ts index 498b208c..faae9475 100644 --- a/src/operations/tables.ts +++ b/src/operations/tables.ts @@ -1,27 +1,34 @@ -import { MigrationOptions, Literal } from '../types' -import { applyType, applyTypeAdapters, escapeValue, formatLines, intersection, makeComment } from '../utils' -import { parseSequenceOptions } from './sequences' +import { Literal, MigrationOptions } from '../types'; +import { + applyType, + applyTypeAdapters, + escapeValue, + formatLines, + intersection, + makeComment, +} from '../utils'; +import { FunctionParamType } from './functionsTypes'; +import { Name } from './generalTypes'; +import { parseSequenceOptions } from './sequences'; import { - CreateTable, - DropTable, - AlterTable, - RenameTable, AddColumns, - DropColumns, AlterColumn, - RenameColumn, + AlterTable, + ColumnDefinition, + ColumnDefinitions, + ConstraintOptions, CreateConstraint, + CreateTable, + DropColumns, DropConstraint, - RenameConstraint, - ReferencesOptions, - ConstraintOptions, - LikeOptions, + DropTable, Like, - ColumnDefinition, - ColumnDefinitions, -} from './tablesTypes' -import { Name } from './generalTypes' -import { FunctionParamType } from './functionsTypes' + LikeOptions, + ReferencesOptions, + RenameColumn, + RenameConstraint, + RenameTable, +} from './tablesTypes'; export { CreateTable, @@ -35,49 +42,56 @@ export { CreateConstraint, DropConstraint, RenameConstraint, -} +}; const parseReferences = (options: ReferencesOptions, literal: Literal) => { - const { references, match, onDelete, onUpdate } = options - const clauses: string[] = [] + const { references, match, onDelete, onUpdate } = options; + const clauses: string[] = []; clauses.push( - typeof references === 'string' && (references.startsWith('"') || references.endsWith(')')) + typeof references === 'string' && + (references.startsWith('"') || references.endsWith(')')) ? `REFERENCES ${references}` - : `REFERENCES ${literal(references)}`, - ) + : `REFERENCES ${literal(references)}` + ); if (match) { - clauses.push(`MATCH ${match}`) + clauses.push(`MATCH ${match}`); } if (onDelete) { - clauses.push(`ON DELETE ${onDelete}`) + clauses.push(`ON DELETE ${onDelete}`); } if (onUpdate) { - clauses.push(`ON UPDATE ${onUpdate}`) + clauses.push(`ON UPDATE ${onUpdate}`); } - return clauses.join(' ') -} + return clauses.join(' '); +}; const parseDeferrable = (options: { deferred?: boolean }) => - `DEFERRABLE INITIALLY ${options.deferred ? 'DEFERRED' : 'IMMEDIATE'}` + `DEFERRABLE INITIALLY ${options.deferred ? 'DEFERRED' : 'IMMEDIATE'}`; const parseColumns = ( tableName: Name, columns: ColumnDefinitions, - mOptions: MigrationOptions, + mOptions: MigrationOptions ): { - columns: string[] - constraints: ConstraintOptions - comments: string[] + columns: string[]; + constraints: ConstraintOptions; + comments: string[]; } => { - const extendingTypeShorthands = mOptions.typeShorthands + const extendingTypeShorthands = mOptions.typeShorthands; let columnsWithOptions = Object.keys(columns).reduce<{ - [x: string]: ColumnDefinition & FunctionParamType - }>((previous, column) => ({ ...previous, [column]: applyType(columns[column], extendingTypeShorthands) }), {}) + [x: string]: ColumnDefinition & FunctionParamType; + }>( + (previous, column) => ({ + ...previous, + [column]: applyType(columns[column], extendingTypeShorthands), + }), + {} + ); const primaryColumns = Object.entries(columnsWithOptions) .filter(([, { primaryKey }]) => Boolean(primaryKey)) - .map(([columnName]) => columnName) - const multiplePrimaryColumns = primaryColumns.length > 1 + .map(([columnName]) => columnName); + const multiplePrimaryColumns = primaryColumns.length > 1; if (multiplePrimaryColumns) { columnsWithOptions = Object.entries(columnsWithOptions).reduce( @@ -88,18 +102,22 @@ const parseColumns = ( primaryKey: false, }, }), - {}, - ) + {} + ); } const comments = Object.entries(columnsWithOptions) .map(([columnName, { comment }]) => { return ( typeof comment !== 'undefined' && - makeComment('COLUMN', `${mOptions.literal(tableName)}.${mOptions.literal(columnName)}`, comment) - ) + makeComment( + 'COLUMN', + `${mOptions.literal(tableName)}.${mOptions.literal(columnName)}`, + comment + ) + ); }) - .filter((comment): comment is string => Boolean(comment)) + .filter((comment): comment is string => Boolean(comment)); return { columns: Object.entries(columnsWithOptions).map(([columnName, options]) => { @@ -116,355 +134,475 @@ const parseColumns = ( referencesConstraintComment, deferrable, expressionGenerated, - }: ColumnDefinition = options - const sequenceGenerated = options.sequenceGenerated === undefined ? options.generated : options.sequenceGenerated - const constraints: string[] = [] + }: ColumnDefinition = options; + const sequenceGenerated = + options.sequenceGenerated === undefined + ? options.generated + : options.sequenceGenerated; + const constraints: string[] = []; if (collation) { - constraints.push(`COLLATE ${collation}`) + constraints.push(`COLLATE ${collation}`); } if (defaultValue !== undefined) { - constraints.push(`DEFAULT ${escapeValue(defaultValue)}`) + constraints.push(`DEFAULT ${escapeValue(defaultValue)}`); } if (unique) { - constraints.push('UNIQUE') + constraints.push('UNIQUE'); } if (primaryKey) { - constraints.push('PRIMARY KEY') + constraints.push('PRIMARY KEY'); } if (notNull) { - constraints.push('NOT NULL') + constraints.push('NOT NULL'); } if (check) { - constraints.push(`CHECK (${check})`) + constraints.push(`CHECK (${check})`); } if (references) { - const name = referencesConstraintName || (referencesConstraintComment ? `${tableName}_fk_${columnName}` : '') - const constraintName = name ? `CONSTRAINT ${mOptions.literal(name)} ` : '' - constraints.push(`${constraintName}${parseReferences(options as ReferencesOptions, mOptions.literal)}`) + const name = + referencesConstraintName || + (referencesConstraintComment ? `${tableName}_fk_${columnName}` : ''); + const constraintName = name + ? `CONSTRAINT ${mOptions.literal(name)} ` + : ''; + constraints.push( + `${constraintName}${parseReferences(options as ReferencesOptions, mOptions.literal)}` + ); if (referencesConstraintComment) { comments.push( makeComment( `CONSTRAINT ${mOptions.literal(name)} ON`, mOptions.literal(tableName), - referencesConstraintComment, - ), - ) + referencesConstraintComment + ) + ); } } if (deferrable) { - constraints.push(parseDeferrable(options)) + constraints.push(parseDeferrable(options)); } if (sequenceGenerated) { - const sequenceOptions = parseSequenceOptions(extendingTypeShorthands, sequenceGenerated).join(' ') + const sequenceOptions = parseSequenceOptions( + extendingTypeShorthands, + sequenceGenerated + ).join(' '); constraints.push( - `GENERATED ${sequenceGenerated.precedence} AS IDENTITY${sequenceOptions ? ` (${sequenceOptions})` : ''}`, - ) + `GENERATED ${sequenceGenerated.precedence} AS IDENTITY${sequenceOptions ? ` (${sequenceOptions})` : ''}` + ); } if (expressionGenerated) { - constraints.push(`GENERATED ALWAYS AS (${expressionGenerated}) STORED`) + constraints.push(`GENERATED ALWAYS AS (${expressionGenerated}) STORED`); } - const constraintsStr = constraints.length ? ` ${constraints.join(' ')}` : '' + const constraintsStr = constraints.length + ? ` ${constraints.join(' ')}` + : ''; - const sType = typeof type === 'object' ? mOptions.literal(type) : type + const sType = typeof type === 'object' ? mOptions.literal(type) : type; - return `${mOptions.literal(columnName)} ${sType}${constraintsStr}` + return `${mOptions.literal(columnName)} ${sType}${constraintsStr}`; }), constraints: multiplePrimaryColumns ? { primaryKey: primaryColumns } : {}, comments, - } -} + }; +}; -const parseConstraints = (table: Name, options: ConstraintOptions, optionName: string | null, literal: Literal) => { - const { check, unique, primaryKey, foreignKeys, exclude, deferrable, comment }: ConstraintOptions = options - const tableName = typeof table === 'object' ? table.name : table - let constraints = [] - const comments = [] +const parseConstraints = ( + table: Name, + options: ConstraintOptions, + optionName: string | null, + literal: Literal +) => { + const { + check, + unique, + primaryKey, + foreignKeys, + exclude, + deferrable, + comment, + }: ConstraintOptions = options; + const tableName = typeof table === 'object' ? table.name : table; + let constraints = []; + const comments = []; if (check) { if (Array.isArray(check)) { check.forEach((ch, i) => { - const name = literal(optionName || `${tableName}_chck_${i + 1}`) - constraints.push(`CONSTRAINT ${name} CHECK (${ch})`) - }) + const name = literal(optionName || `${tableName}_chck_${i + 1}`); + constraints.push(`CONSTRAINT ${name} CHECK (${ch})`); + }); } else { - const name = literal(optionName || `${tableName}_chck`) - constraints.push(`CONSTRAINT ${name} CHECK (${check})`) + const name = literal(optionName || `${tableName}_chck`); + constraints.push(`CONSTRAINT ${name} CHECK (${check})`); } } if (unique) { - const uniqueArray: Array = Array.isArray(unique) ? unique : [unique] - const isArrayOfArrays = uniqueArray.some((uniqueSet) => Array.isArray(uniqueSet)) - ;((isArrayOfArrays ? uniqueArray : [uniqueArray]) as Array).forEach((uniqueSet) => { - const cols = Array.isArray(uniqueSet) ? uniqueSet : [uniqueSet] - const name = literal(optionName || `${tableName}_uniq_${cols.join('_')}`) - constraints.push(`CONSTRAINT ${name} UNIQUE (${cols.map(literal).join(', ')})`) - }) + const uniqueArray: Array = Array.isArray(unique) + ? unique + : [unique]; + const isArrayOfArrays = uniqueArray.some((uniqueSet) => + Array.isArray(uniqueSet) + ); + ( + (isArrayOfArrays ? uniqueArray : [uniqueArray]) as Array + ).forEach((uniqueSet) => { + const cols = Array.isArray(uniqueSet) ? uniqueSet : [uniqueSet]; + const name = literal(optionName || `${tableName}_uniq_${cols.join('_')}`); + constraints.push( + `CONSTRAINT ${name} UNIQUE (${cols.map(literal).join(', ')})` + ); + }); } if (primaryKey) { - const name = literal(optionName || `${tableName}_pkey`) - const key = (Array.isArray(primaryKey) ? primaryKey : [primaryKey]).map(literal).join(', ') - constraints.push(`CONSTRAINT ${name} PRIMARY KEY (${key})`) + const name = literal(optionName || `${tableName}_pkey`); + const key = (Array.isArray(primaryKey) ? primaryKey : [primaryKey]) + .map(literal) + .join(', '); + constraints.push(`CONSTRAINT ${name} PRIMARY KEY (${key})`); } if (foreignKeys) { - ;(Array.isArray(foreignKeys) ? foreignKeys : [foreignKeys]).forEach((fk) => { - const { columns, referencesConstraintName, referencesConstraintComment } = fk - const cols = Array.isArray(columns) ? columns : [columns] - const name = literal(referencesConstraintName || optionName || `${tableName}_fk_${cols.join('_')}`) - const key = cols.map(literal).join(', ') - const referencesStr = parseReferences(fk, literal) - constraints.push(`CONSTRAINT ${name} FOREIGN KEY (${key}) ${referencesStr}`) + (Array.isArray(foreignKeys) ? foreignKeys : [foreignKeys]).forEach((fk) => { + const { columns, referencesConstraintName, referencesConstraintComment } = + fk; + const cols = Array.isArray(columns) ? columns : [columns]; + const name = literal( + referencesConstraintName || + optionName || + `${tableName}_fk_${cols.join('_')}` + ); + const key = cols.map(literal).join(', '); + const referencesStr = parseReferences(fk, literal); + constraints.push( + `CONSTRAINT ${name} FOREIGN KEY (${key}) ${referencesStr}` + ); if (referencesConstraintComment) { - comments.push(makeComment(`CONSTRAINT ${name} ON`, literal(tableName), referencesConstraintComment)) + comments.push( + makeComment( + `CONSTRAINT ${name} ON`, + literal(tableName), + referencesConstraintComment + ) + ); } - }) + }); } if (exclude) { - const name = literal(optionName || `${tableName}_excl`) - constraints.push(`CONSTRAINT ${name} EXCLUDE ${exclude}`) + const name = literal(optionName || `${tableName}_excl`); + constraints.push(`CONSTRAINT ${name} EXCLUDE ${exclude}`); } if (deferrable) { - constraints = constraints.map((constraint) => `${constraint} ${parseDeferrable(options)}`) + constraints = constraints.map( + (constraint) => `${constraint} ${parseDeferrable(options)}` + ); } if (comment) { - if (!optionName) throw new Error('cannot comment on unspecified constraints') - comments.push(makeComment(`CONSTRAINT ${literal(optionName)} ON`, literal(tableName), comment)) + if (!optionName) + throw new Error('cannot comment on unspecified constraints'); + comments.push( + makeComment( + `CONSTRAINT ${literal(optionName)} ON`, + literal(tableName), + comment + ) + ); } return { constraints, comments, - } -} + }; +}; -const parseLike = (like: Name | { table: Name; options?: LikeOptions }, literal: Literal) => { - const formatOptions = (name: 'INCLUDING' | 'EXCLUDING', options?: Like | Like[]) => +const parseLike = ( + like: Name | { table: Name; options?: LikeOptions }, + literal: Literal +) => { + const formatOptions = ( + name: 'INCLUDING' | 'EXCLUDING', + options?: Like | Like[] + ) => (Array.isArray(options) ? options : [options]) .filter((option): option is Like => option !== undefined) .map((option) => ` ${name} ${option}`) - .join('') + .join(''); - const table = typeof like === 'string' || !('table' in like) ? like : like.table + const table = + typeof like === 'string' || !('table' in like) ? like : like.table; const options = - typeof like === 'string' || !('options' in like) || like.options === undefined + typeof like === 'string' || + !('options' in like) || + like.options === undefined ? '' - : [formatOptions('INCLUDING', like.options.including), formatOptions('EXCLUDING', like.options.excluding)].join( - '', - ) - return `LIKE ${literal(table)}${options}` -} + : [ + formatOptions('INCLUDING', like.options.including), + formatOptions('EXCLUDING', like.options.excluding), + ].join(''); + return `LIKE ${literal(table)}${options}`; +}; // TABLE export function dropTable(mOptions: MigrationOptions) { const _drop: DropTable = (tableName, options = {}) => { - const { ifExists, cascade } = options - const ifExistsStr = ifExists ? ' IF EXISTS' : '' - const cascadeStr = cascade ? ' CASCADE' : '' - const tableNameStr = mOptions.literal(tableName) - return `DROP TABLE${ifExistsStr} ${tableNameStr}${cascadeStr};` - } - return _drop + const { ifExists, cascade } = options; + const ifExistsStr = ifExists ? ' IF EXISTS' : ''; + const cascadeStr = cascade ? ' CASCADE' : ''; + const tableNameStr = mOptions.literal(tableName); + return `DROP TABLE${ifExistsStr} ${tableNameStr}${cascadeStr};`; + }; + return _drop; } export function createTable(mOptions: MigrationOptions) { const _create: CreateTable = (tableName, columns, options = {}) => { - const { temporary, ifNotExists, inherits, like, constraints: optionsConstraints = {}, comment } = options + const { + temporary, + ifNotExists, + inherits, + like, + constraints: optionsConstraints = {}, + comment, + } = options; const { columns: columnLines, constraints: crossColumnConstraints, comments: columnComments = [], - } = parseColumns(tableName, columns, mOptions) - const dupes = intersection(Object.keys(optionsConstraints), Object.keys(crossColumnConstraints)) + } = parseColumns(tableName, columns, mOptions); + const dupes = intersection( + Object.keys(optionsConstraints), + Object.keys(crossColumnConstraints) + ); if (dupes.length > 0) { - const dupesStr = dupes.join(', ') - throw new Error(`There is duplicate constraint definition in table and columns options: ${dupesStr}`) + const dupesStr = dupes.join(', '); + throw new Error( + `There is duplicate constraint definition in table and columns options: ${dupesStr}` + ); } const constraints: ConstraintOptions = { ...optionsConstraints, ...crossColumnConstraints, - } - const { constraints: constraintLines, comments: constraintComments } = parseConstraints( - tableName, - constraints, - '', - mOptions.literal, - ) - const tableDefinition = [...columnLines, ...constraintLines].concat(like ? [parseLike(like, mOptions.literal)] : []) + }; + const { constraints: constraintLines, comments: constraintComments } = + parseConstraints(tableName, constraints, '', mOptions.literal); + const tableDefinition = [...columnLines, ...constraintLines].concat( + like ? [parseLike(like, mOptions.literal)] : [] + ); - const temporaryStr = temporary ? ' TEMPORARY' : '' - const ifNotExistsStr = ifNotExists ? ' IF NOT EXISTS' : '' - const inheritsStr = inherits ? ` INHERITS (${mOptions.literal(inherits)})` : '' - const tableNameStr = mOptions.literal(tableName) + const temporaryStr = temporary ? ' TEMPORARY' : ''; + const ifNotExistsStr = ifNotExists ? ' IF NOT EXISTS' : ''; + const inheritsStr = inherits + ? ` INHERITS (${mOptions.literal(inherits)})` + : ''; + const tableNameStr = mOptions.literal(tableName); const createTableQuery = `CREATE${temporaryStr} TABLE${ifNotExistsStr} ${tableNameStr} ( ${formatLines(tableDefinition)} -)${inheritsStr};` - const comments = [...columnComments, ...constraintComments] +)${inheritsStr};`; + const comments = [...columnComments, ...constraintComments]; if (typeof comment !== 'undefined') { - comments.push(makeComment('TABLE', mOptions.literal(tableName), comment)) + comments.push(makeComment('TABLE', mOptions.literal(tableName), comment)); } - return `${createTableQuery}${comments.length > 0 ? `\n${comments.join('\n')}` : ''}` - } - _create.reverse = dropTable(mOptions) - return _create + return `${createTableQuery}${comments.length > 0 ? `\n${comments.join('\n')}` : ''}`; + }; + _create.reverse = dropTable(mOptions); + return _create; } export function alterTable(mOptions: MigrationOptions) { const _alter: AlterTable = (tableName, options) => { - const alterDefinition = [] + const alterDefinition = []; if (options.levelSecurity) { - alterDefinition.push(`${options.levelSecurity} ROW LEVEL SECURITY`) + alterDefinition.push(`${options.levelSecurity} ROW LEVEL SECURITY`); } return `ALTER TABLE ${mOptions.literal(tableName)} - ${formatLines(alterDefinition)};` - } - return _alter + ${formatLines(alterDefinition)};`; + }; + return _alter; } // COLUMNS export function dropColumns(mOptions: MigrationOptions) { const _drop: DropColumns = (tableName, columns, options = {}) => { - const { ifExists, cascade } = options + const { ifExists, cascade } = options; if (typeof columns === 'string') { - columns = [columns] // eslint-disable-line no-param-reassign + columns = [columns]; // eslint-disable-line no-param-reassign } else if (!Array.isArray(columns) && typeof columns === 'object') { - columns = Object.keys(columns) // eslint-disable-line no-param-reassign + columns = Object.keys(columns); // eslint-disable-line no-param-reassign } const columnsStr = formatLines( columns.map(mOptions.literal), ` DROP ${ifExists ? ' IF EXISTS' : ''}`, - `${cascade ? ' CASCADE' : ''},`, - ) + `${cascade ? ' CASCADE' : ''},` + ); return `ALTER TABLE ${mOptions.literal(tableName)} -${columnsStr};` - } - return _drop +${columnsStr};`; + }; + return _drop; } export function addColumns(mOptions: MigrationOptions) { const _add: AddColumns = (tableName, columns, options = {}) => { - const { ifNotExists } = options - const { columns: columnLines, comments: columnComments = [] } = parseColumns(tableName, columns, mOptions) - const columnsStr = formatLines(columnLines, ` ADD ${ifNotExists ? 'IF NOT EXISTS ' : ''}`) - const tableNameStr = mOptions.literal(tableName) - const alterTableQuery = `ALTER TABLE ${tableNameStr}\n${columnsStr};` - const columnCommentsStr = columnComments.length > 0 ? `\n${columnComments.join('\n')}` : '' - return `${alterTableQuery}${columnCommentsStr}` - } - _add.reverse = dropColumns(mOptions) - return _add + const { ifNotExists } = options; + const { columns: columnLines, comments: columnComments = [] } = + parseColumns(tableName, columns, mOptions); + const columnsStr = formatLines( + columnLines, + ` ADD ${ifNotExists ? 'IF NOT EXISTS ' : ''}` + ); + const tableNameStr = mOptions.literal(tableName); + const alterTableQuery = `ALTER TABLE ${tableNameStr}\n${columnsStr};`; + const columnCommentsStr = + columnComments.length > 0 ? `\n${columnComments.join('\n')}` : ''; + return `${alterTableQuery}${columnCommentsStr}`; + }; + _add.reverse = dropColumns(mOptions); + return _add; } export function alterColumn(mOptions: MigrationOptions): AlterColumn { return (tableName, columnName, options) => { - const { default: defaultValue, type, collation, using, notNull, allowNull, comment } = options - const sequenceGenerated = options.sequenceGenerated === undefined ? options.generated : options.sequenceGenerated - const actions: string[] = [] + const { + default: defaultValue, + type, + collation, + using, + notNull, + allowNull, + comment, + } = options; + const sequenceGenerated = + options.sequenceGenerated === undefined + ? options.generated + : options.sequenceGenerated; + const actions: string[] = []; if (defaultValue === null) { - actions.push('DROP DEFAULT') + actions.push('DROP DEFAULT'); } else if (defaultValue !== undefined) { - actions.push(`SET DEFAULT ${escapeValue(defaultValue)}`) + actions.push(`SET DEFAULT ${escapeValue(defaultValue)}`); } if (type) { - const typeStr = applyTypeAdapters(type) - const collationStr = collation ? ` COLLATE ${collation}` : '' - const usingStr = using ? ` USING ${using}` : '' - actions.push(`SET DATA TYPE ${typeStr}${collationStr}${usingStr}`) + const typeStr = applyTypeAdapters(type); + const collationStr = collation ? ` COLLATE ${collation}` : ''; + const usingStr = using ? ` USING ${using}` : ''; + actions.push(`SET DATA TYPE ${typeStr}${collationStr}${usingStr}`); } if (notNull) { - actions.push('SET NOT NULL') + actions.push('SET NOT NULL'); } else if (notNull === false || allowNull) { - actions.push('DROP NOT NULL') + actions.push('DROP NOT NULL'); } if (sequenceGenerated !== undefined) { if (!sequenceGenerated) { - actions.push('DROP IDENTITY') + actions.push('DROP IDENTITY'); } else { - const sequenceOptions = parseSequenceOptions(mOptions.typeShorthands, sequenceGenerated).join(' ') + const sequenceOptions = parseSequenceOptions( + mOptions.typeShorthands, + sequenceGenerated + ).join(' '); actions.push( - `ADD GENERATED ${sequenceGenerated.precedence} AS IDENTITY${sequenceOptions ? ` (${sequenceOptions})` : ''}`, - ) + `ADD GENERATED ${sequenceGenerated.precedence} AS IDENTITY${sequenceOptions ? ` (${sequenceOptions})` : ''}` + ); } } - const queries: string[] = [] + const queries: string[] = []; if (actions.length > 0) { - const columnsStr = formatLines(actions, ` ALTER ${mOptions.literal(columnName)} `) - queries.push(`ALTER TABLE ${mOptions.literal(tableName)}\n${columnsStr};`) + const columnsStr = formatLines( + actions, + ` ALTER ${mOptions.literal(columnName)} ` + ); + queries.push( + `ALTER TABLE ${mOptions.literal(tableName)}\n${columnsStr};` + ); } if (typeof comment !== 'undefined') { - queries.push(makeComment('COLUMN', `${mOptions.literal(tableName)}.${mOptions.literal(columnName)}`, comment)) + queries.push( + makeComment( + 'COLUMN', + `${mOptions.literal(tableName)}.${mOptions.literal(columnName)}`, + comment + ) + ); } - return queries.join('\n') - } + return queries.join('\n'); + }; } export function renameTable(mOptions: MigrationOptions) { const _rename: RenameTable = (tableName, newName) => { - const tableNameStr = mOptions.literal(tableName) - const newNameStr = mOptions.literal(newName) - return `ALTER TABLE ${tableNameStr} RENAME TO ${newNameStr};` - } - _rename.reverse = (tableName, newName) => _rename(newName, tableName) - return _rename + const tableNameStr = mOptions.literal(tableName); + const newNameStr = mOptions.literal(newName); + return `ALTER TABLE ${tableNameStr} RENAME TO ${newNameStr};`; + }; + _rename.reverse = (tableName, newName) => _rename(newName, tableName); + return _rename; } export function renameColumn(mOptions: MigrationOptions) { const _rename: RenameColumn = (tableName, columnName, newName) => { - const tableNameStr = mOptions.literal(tableName) - const columnNameStr = mOptions.literal(columnName) - const newNameStr = mOptions.literal(newName) - return `ALTER TABLE ${tableNameStr} RENAME ${columnNameStr} TO ${newNameStr};` - } - _rename.reverse = (tableName, columnName, newName) => _rename(tableName, newName, columnName) - return _rename + const tableNameStr = mOptions.literal(tableName); + const columnNameStr = mOptions.literal(columnName); + const newNameStr = mOptions.literal(newName); + return `ALTER TABLE ${tableNameStr} RENAME ${columnNameStr} TO ${newNameStr};`; + }; + _rename.reverse = (tableName, columnName, newName) => + _rename(tableName, newName, columnName); + return _rename; } export function renameConstraint(mOptions: MigrationOptions) { const _rename: RenameConstraint = (tableName, constraintName, newName) => { - const tableNameStr = mOptions.literal(tableName) - const constraintNameStr = mOptions.literal(constraintName) - const newNameStr = mOptions.literal(newName) - return `ALTER TABLE ${tableNameStr} RENAME CONSTRAINT ${constraintNameStr} TO ${newNameStr};` - } - _rename.reverse = (tableName, constraintName, newName) => _rename(tableName, newName, constraintName) - return _rename + const tableNameStr = mOptions.literal(tableName); + const constraintNameStr = mOptions.literal(constraintName); + const newNameStr = mOptions.literal(newName); + return `ALTER TABLE ${tableNameStr} RENAME CONSTRAINT ${constraintNameStr} TO ${newNameStr};`; + }; + _rename.reverse = (tableName, constraintName, newName) => + _rename(tableName, newName, constraintName); + return _rename; } export function dropConstraint(mOptions: MigrationOptions) { const _drop: DropConstraint = (tableName, constraintName, options = {}) => { - const { ifExists, cascade } = options - const ifExistsStr = ifExists ? ' IF EXISTS' : '' - const cascadeStr = cascade ? ' CASCADE' : '' - const tableNameStr = mOptions.literal(tableName) - const constraintNameStr = mOptions.literal(constraintName) - return `ALTER TABLE ${tableNameStr} DROP CONSTRAINT${ifExistsStr} ${constraintNameStr}${cascadeStr};` - } - return _drop + const { ifExists, cascade } = options; + const ifExistsStr = ifExists ? ' IF EXISTS' : ''; + const cascadeStr = cascade ? ' CASCADE' : ''; + const tableNameStr = mOptions.literal(tableName); + const constraintNameStr = mOptions.literal(constraintName); + return `ALTER TABLE ${tableNameStr} DROP CONSTRAINT${ifExistsStr} ${constraintNameStr}${cascadeStr};`; + }; + return _drop; } export function addConstraint(mOptions: MigrationOptions) { const _add: CreateConstraint = (tableName, constraintName, expression) => { const { constraints, comments } = typeof expression === 'string' ? { - constraints: [`${constraintName ? `CONSTRAINT ${mOptions.literal(constraintName)} ` : ''}${expression}`], + constraints: [ + `${constraintName ? `CONSTRAINT ${mOptions.literal(constraintName)} ` : ''}${expression}`, + ], comments: [], } : parseConstraints( tableName, expression as Exclude, constraintName, - mOptions.literal, - ) - const constraintStr = formatLines(constraints, ' ADD ') - return [`ALTER TABLE ${mOptions.literal(tableName)}\n${constraintStr};`, ...comments].join('\n') - } + mOptions.literal + ); + const constraintStr = formatLines(constraints, ' ADD '); + return [ + `ALTER TABLE ${mOptions.literal(tableName)}\n${constraintStr};`, + ...comments, + ].join('\n'); + }; _add.reverse = (tableName, constraintName, options) => { if (constraintName === null) { - throw new Error(`Impossible to automatically infer down migration for addConstraint without naming constraint`) + throw new Error( + `Impossible to automatically infer down migration for addConstraint without naming constraint` + ); } - return dropConstraint(mOptions)(tableName, constraintName, options) - } - return _add + return dropConstraint(mOptions)(tableName, constraintName, options); + }; + return _add; } diff --git a/src/operations/tablesTypes.ts b/src/operations/tablesTypes.ts index 821d04d0..032bd48c 100644 --- a/src/operations/tablesTypes.ts +++ b/src/operations/tablesTypes.ts @@ -1,123 +1,164 @@ -import { Name, Value, IfNotExistsOption, DropOptions } from './generalTypes' -import { SequenceOptions } from './sequencesTypes' +import { DropOptions, IfNotExistsOption, Name, Value } from './generalTypes'; +import { SequenceOptions } from './sequencesTypes'; -export type Action = 'NO ACTION' | 'RESTRICT' | 'CASCADE' | 'SET NULL' | 'SET DEFAULT' +export type Action = + | 'NO ACTION' + | 'RESTRICT' + | 'CASCADE' + | 'SET NULL' + | 'SET DEFAULT'; export interface ReferencesOptions { - referencesConstraintName?: string - referencesConstraintComment?: string - references: Name - onDelete?: Action - onUpdate?: Action - match?: 'FULL' | 'SIMPLE' + referencesConstraintName?: string; + referencesConstraintComment?: string; + references: Name; + onDelete?: Action; + onUpdate?: Action; + match?: 'FULL' | 'SIMPLE'; } -type SequenceGeneratedOptions = { precedence: 'ALWAYS' | 'BY DEFAULT' } & SequenceOptions +type SequenceGeneratedOptions = { + precedence: 'ALWAYS' | 'BY DEFAULT'; +} & SequenceOptions; export interface ColumnDefinition extends Partial { - type: string - collation?: string - unique?: boolean - primaryKey?: boolean - notNull?: boolean - default?: Value - check?: string - deferrable?: boolean - deferred?: boolean - comment?: string | null + type: string; + collation?: string; + unique?: boolean; + primaryKey?: boolean; + notNull?: boolean; + default?: Value; + check?: string; + deferrable?: boolean; + deferred?: boolean; + comment?: string | null; /** * @deprecated use sequenceGenerated */ - generated?: SequenceGeneratedOptions - sequenceGenerated?: SequenceGeneratedOptions - expressionGenerated?: string + generated?: SequenceGeneratedOptions; + sequenceGenerated?: SequenceGeneratedOptions; + expressionGenerated?: string; } export interface ColumnDefinitions { - [name: string]: ColumnDefinition | string + [name: string]: ColumnDefinition | string; } -export type Like = 'COMMENTS' | 'CONSTRAINTS' | 'DEFAULTS' | 'IDENTITY' | 'INDEXES' | 'STATISTICS' | 'STORAGE' | 'ALL' +export type Like = + | 'COMMENTS' + | 'CONSTRAINTS' + | 'DEFAULTS' + | 'IDENTITY' + | 'INDEXES' + | 'STATISTICS' + | 'STORAGE' + | 'ALL'; export interface LikeOptions { - including?: Like | Like[] - excluding?: Like | Like[] + including?: Like | Like[]; + excluding?: Like | Like[]; } export interface ForeignKeyOptions extends ReferencesOptions { - columns: Name | Name[] + columns: Name | Name[]; } export interface ConstraintOptions { - check?: string | string[] - unique?: Name | Array - primaryKey?: Name | Name[] - foreignKeys?: ForeignKeyOptions | ForeignKeyOptions[] - exclude?: string - deferrable?: boolean - deferred?: boolean - comment?: string + check?: string | string[]; + unique?: Name | Array; + primaryKey?: Name | Name[]; + foreignKeys?: ForeignKeyOptions | ForeignKeyOptions[]; + exclude?: string; + deferrable?: boolean; + deferred?: boolean; + comment?: string; } export interface TableOptions extends IfNotExistsOption { - temporary?: boolean - inherits?: Name - like?: Name | { table: Name; options?: LikeOptions } - constraints?: ConstraintOptions - comment?: string | null + temporary?: boolean; + inherits?: Name; + like?: Name | { table: Name; options?: LikeOptions }; + constraints?: ConstraintOptions; + comment?: string | null; } export interface AlterTableOptions { - levelSecurity: 'DISABLE' | 'ENABLE' | 'FORCE' | 'NO FORCE' + levelSecurity: 'DISABLE' | 'ENABLE' | 'FORCE' | 'NO FORCE'; } export interface AlterColumnOptions { - type?: string - default?: Value - notNull?: boolean - allowNull?: boolean - collation?: string - using?: string - comment?: string | null + type?: string; + default?: Value; + notNull?: boolean; + allowNull?: boolean; + collation?: string; + using?: string; + comment?: string | null; /** * @deprecated use sequenceGenerated */ - generated?: null | false | SequenceGeneratedOptions - sequenceGenerated?: null | false | SequenceGeneratedOptions + generated?: null | false | SequenceGeneratedOptions; + sequenceGenerated?: null | false | SequenceGeneratedOptions; } type CreateTableFn = ( tableName: Name, columns: ColumnDefinitions, - options?: TableOptions & DropOptions, -) => string | string[] -export type CreateTable = CreateTableFn & { reverse: CreateTableFn } -export type DropTable = (tableName: Name, dropOptions?: DropOptions) => string | string[] -type RenameTableFn = (tableName: Name, newtableName: Name) => string | string[] -export type RenameTable = RenameTableFn & { reverse: RenameTableFn } -export type AlterTable = (tableName: Name, alterOptions: AlterTableOptions) => string | string[] + options?: TableOptions & DropOptions +) => string | string[]; +export type CreateTable = CreateTableFn & { reverse: CreateTableFn }; +export type DropTable = ( + tableName: Name, + dropOptions?: DropOptions +) => string | string[]; +type RenameTableFn = (tableName: Name, newtableName: Name) => string | string[]; +export type RenameTable = RenameTableFn & { reverse: RenameTableFn }; +export type AlterTable = ( + tableName: Name, + alterOptions: AlterTableOptions +) => string | string[]; type AddColumnsFn = ( tableName: Name, newColumns: ColumnDefinitions, - addOptions?: IfNotExistsOption & DropOptions, -) => string | string[] -export type AddColumns = AddColumnsFn & { reverse: AddColumnsFn } + addOptions?: IfNotExistsOption & DropOptions +) => string | string[]; +export type AddColumns = AddColumnsFn & { reverse: AddColumnsFn }; export type DropColumns = ( tableName: Name, columns: string | string[] | { [name: string]: unknown }, - dropOptions?: DropOptions, -) => string | string[] -type RenameColumnFn = (tableName: Name, oldColumnName: string, newColumnName: string) => string | string[] -export type RenameColumn = RenameColumnFn & { reverse: RenameColumnFn } -export type AlterColumn = (tableName: Name, columnName: string, options: AlterColumnOptions) => string | string[] + dropOptions?: DropOptions +) => string | string[]; +type RenameColumnFn = ( + tableName: Name, + oldColumnName: string, + newColumnName: string +) => string | string[]; +export type RenameColumn = RenameColumnFn & { reverse: RenameColumnFn }; +export type AlterColumn = ( + tableName: Name, + columnName: string, + options: AlterColumnOptions +) => string | string[]; type CreateConstraintFn = ( tableName: Name, constraintName: string | null, - expression: (string | ConstraintOptions) & DropOptions, -) => string | string[] -export type CreateConstraint = CreateConstraintFn & { reverse: CreateConstraintFn } -export type DropConstraint = (tableName: Name, constraintName: string, options?: DropOptions) => string | string[] -type RenameConstraintFn = (tableName: Name, oldConstraintName: string, newConstraintName: string) => string | string[] -export type RenameConstraint = RenameConstraintFn & { reverse: RenameConstraintFn } + expression: (string | ConstraintOptions) & DropOptions +) => string | string[]; +export type CreateConstraint = CreateConstraintFn & { + reverse: CreateConstraintFn; +}; +export type DropConstraint = ( + tableName: Name, + constraintName: string, + options?: DropOptions +) => string | string[]; +type RenameConstraintFn = ( + tableName: Name, + oldConstraintName: string, + newConstraintName: string +) => string | string[]; +export type RenameConstraint = RenameConstraintFn & { + reverse: RenameConstraintFn; +}; diff --git a/src/operations/triggers.ts b/src/operations/triggers.ts index 6cb54982..5b81d0aa 100644 --- a/src/operations/triggers.ts +++ b/src/operations/triggers.ts @@ -1,107 +1,134 @@ -import { MigrationOptions } from '../types' -import { escapeValue } from '../utils' -import { createFunction, dropFunction } from './functions' -import { Name, DropOptions, Value } from './generalTypes' -import { CreateTrigger, DropTrigger, RenameTrigger, TriggerOptions } from './triggersTypes' -import { FunctionOptions } from './functionsTypes' +import { MigrationOptions } from '../types'; +import { escapeValue } from '../utils'; +import { createFunction, dropFunction } from './functions'; +import { FunctionOptions } from './functionsTypes'; +import { DropOptions, Name, Value } from './generalTypes'; +import { + CreateTrigger, + DropTrigger, + RenameTrigger, + TriggerOptions, +} from './triggersTypes'; -export { CreateTrigger, DropTrigger, RenameTrigger } +export { CreateTrigger, DropTrigger, RenameTrigger }; export function dropTrigger(mOptions: MigrationOptions) { const _drop: DropTrigger = (tableName, triggerName, options = {}) => { - const { ifExists, cascade } = options - const ifExistsStr = ifExists ? ' IF EXISTS' : '' - const cascadeStr = cascade ? ' CASCADE' : '' - const triggerNameStr = mOptions.literal(triggerName) - const tableNameStr = mOptions.literal(tableName) - return `DROP TRIGGER${ifExistsStr} ${triggerNameStr} ON ${tableNameStr}${cascadeStr};` - } - return _drop + const { ifExists, cascade } = options; + const ifExistsStr = ifExists ? ' IF EXISTS' : ''; + const cascadeStr = cascade ? ' CASCADE' : ''; + const triggerNameStr = mOptions.literal(triggerName); + const tableNameStr = mOptions.literal(tableName); + return `DROP TRIGGER${ifExistsStr} ${triggerNameStr} ON ${tableNameStr}${cascadeStr};`; + }; + return _drop; } export function createTrigger(mOptions: MigrationOptions) { const _create: CreateTrigger = ( tableName: Name, triggerName: string, - triggerOptions: (TriggerOptions & DropOptions) | (TriggerOptions & FunctionOptions & DropOptions), - definition?: Value, + triggerOptions: + | (TriggerOptions & DropOptions) + | (TriggerOptions & FunctionOptions & DropOptions), + definition?: Value ) => { - const { constraint, condition, operation, deferrable, deferred, functionParams = [] } = triggerOptions - let { when, level = 'STATEMENT', function: functionName } = triggerOptions - const operations = Array.isArray(operation) ? operation.join(' OR ') : operation + const { + constraint, + condition, + operation, + deferrable, + deferred, + functionParams = [], + } = triggerOptions; + let { when, level = 'STATEMENT', function: functionName } = triggerOptions; + const operations = Array.isArray(operation) + ? operation.join(' OR ') + : operation; if (constraint) { - when = 'AFTER' + when = 'AFTER'; } if (!when) { - throw new Error('"when" (BEFORE/AFTER/INSTEAD OF) have to be specified') + throw new Error('"when" (BEFORE/AFTER/INSTEAD OF) have to be specified'); } - const isInsteadOf = /instead\s+of/i.test(when) + const isInsteadOf = /instead\s+of/i.test(when); if (isInsteadOf) { - level = 'ROW' + level = 'ROW'; } if (definition) { - functionName = functionName === undefined ? triggerName : functionName + functionName = functionName === undefined ? triggerName : functionName; } if (!functionName) { - throw new Error("Can't determine function name") + throw new Error("Can't determine function name"); } if (isInsteadOf && condition) { - throw new Error("INSTEAD OF trigger can't have condition specified") + throw new Error("INSTEAD OF trigger can't have condition specified"); } if (!operations) { - throw new Error('"operation" (INSERT/UPDATE[ OF ...]/DELETE/TRUNCATE) have to be specified') + throw new Error( + '"operation" (INSERT/UPDATE[ OF ...]/DELETE/TRUNCATE) have to be specified' + ); } const defferStr = constraint ? `${deferrable ? `DEFERRABLE INITIALLY ${deferred ? 'DEFERRED' : 'IMMEDIATE'}` : 'NOT DEFERRABLE'}\n ` - : '' - const conditionClause = condition ? `WHEN (${condition})\n ` : '' - const constraintStr = constraint ? ' CONSTRAINT' : '' - const paramsStr = functionParams.map(escapeValue).join(', ') - const triggerNameStr = mOptions.literal(triggerName) - const tableNameStr = mOptions.literal(tableName) - const functionNameStr = mOptions.literal(functionName) + : ''; + const conditionClause = condition ? `WHEN (${condition})\n ` : ''; + const constraintStr = constraint ? ' CONSTRAINT' : ''; + const paramsStr = functionParams.map(escapeValue).join(', '); + const triggerNameStr = mOptions.literal(triggerName); + const tableNameStr = mOptions.literal(tableName); + const functionNameStr = mOptions.literal(functionName); const triggerSQL = `CREATE${constraintStr} TRIGGER ${triggerNameStr} ${when} ${operations} ON ${tableNameStr} ${defferStr}FOR EACH ${level} - ${conditionClause}EXECUTE PROCEDURE ${functionNameStr}(${paramsStr});` + ${conditionClause}EXECUTE PROCEDURE ${functionNameStr}(${paramsStr});`; const fnSQL = definition ? `${createFunction(mOptions)( functionName, [], { ...(triggerOptions as FunctionOptions), returns: 'trigger' }, - definition, + definition )}\n` - : '' - return `${fnSQL}${triggerSQL}` - } + : ''; + return `${fnSQL}${triggerSQL}`; + }; _create.reverse = ( tableName: Name, triggerName: string, triggerOptions: TriggerOptions & DropOptions, - definition?: Value, + definition?: Value ) => { - const triggerSQL = dropTrigger(mOptions)(tableName, triggerName, triggerOptions) + const triggerSQL = dropTrigger(mOptions)( + tableName, + triggerName, + triggerOptions + ); const fnSQL = definition ? `\n${dropFunction(mOptions)(triggerOptions.function || triggerName, [], triggerOptions)}` - : '' - return `${triggerSQL}${fnSQL}` - } + : ''; + return `${triggerSQL}${fnSQL}`; + }; - return _create + return _create; } export function renameTrigger(mOptions: MigrationOptions) { - const _rename: RenameTrigger = (tableName, oldTriggerName, newTriggerName) => { - const oldTriggerNameStr = mOptions.literal(oldTriggerName) - const tableNameStr = mOptions.literal(tableName) - const newTriggerNameStr = mOptions.literal(newTriggerName) - return `ALTER TRIGGER ${oldTriggerNameStr} ON ${tableNameStr} RENAME TO ${newTriggerNameStr};` - } - _rename.reverse = (tableName, oldTriggerName, newTriggerName) => _rename(tableName, newTriggerName, oldTriggerName) - return _rename + const _rename: RenameTrigger = ( + tableName, + oldTriggerName, + newTriggerName + ) => { + const oldTriggerNameStr = mOptions.literal(oldTriggerName); + const tableNameStr = mOptions.literal(tableName); + const newTriggerNameStr = mOptions.literal(newTriggerName); + return `ALTER TRIGGER ${oldTriggerNameStr} ON ${tableNameStr} RENAME TO ${newTriggerNameStr};`; + }; + _rename.reverse = (tableName, oldTriggerName, newTriggerName) => + _rename(tableName, newTriggerName, oldTriggerName); + return _rename; } diff --git a/src/operations/triggersTypes.ts b/src/operations/triggersTypes.ts index db668a49..05865d75 100644 --- a/src/operations/triggersTypes.ts +++ b/src/operations/triggersTypes.ts @@ -1,31 +1,39 @@ -import { Name, Value, DropOptions } from './generalTypes' -import { FunctionOptions } from './functionsTypes' +import { FunctionOptions } from './functionsTypes'; +import { DropOptions, Name, Value } from './generalTypes'; export interface TriggerOptions { - when?: 'BEFORE' | 'AFTER' | 'INSTEAD OF' - operation: string | string[] - constraint?: boolean - function?: Name - functionParams?: Value[] - level?: 'STATEMENT' | 'ROW' - condition?: string - deferrable?: boolean - deferred?: boolean + when?: 'BEFORE' | 'AFTER' | 'INSTEAD OF'; + operation: string | string[]; + constraint?: boolean; + function?: Name; + functionParams?: Value[]; + level?: 'STATEMENT' | 'ROW'; + condition?: string; + deferrable?: boolean; + deferred?: boolean; } type CreateTriggerFn1 = ( tableName: Name, triggerName: string, - triggerOptions: TriggerOptions & DropOptions, -) => string | string[] + triggerOptions: TriggerOptions & DropOptions +) => string | string[]; type CreateTriggerFn2 = ( tableName: Name, triggerName: string, triggerOptions: TriggerOptions & FunctionOptions & DropOptions, - definition: Value, -) => string | string[] -type CreateTriggerFn = CreateTriggerFn1 | CreateTriggerFn2 -export type CreateTrigger = CreateTriggerFn & { reverse: CreateTriggerFn } -export type DropTrigger = (tableName: Name, triggerName: string, dropOptions?: DropOptions) => string | string[] -type RenameTriggerFn = (tableName: Name, oldTriggerName: string, newTriggerName: string) => string | string[] -export type RenameTrigger = RenameTriggerFn & { reverse: RenameTriggerFn } + definition: Value +) => string | string[]; +type CreateTriggerFn = CreateTriggerFn1 | CreateTriggerFn2; +export type CreateTrigger = CreateTriggerFn & { reverse: CreateTriggerFn }; +export type DropTrigger = ( + tableName: Name, + triggerName: string, + dropOptions?: DropOptions +) => string | string[]; +type RenameTriggerFn = ( + tableName: Name, + oldTriggerName: string, + newTriggerName: string +) => string | string[]; +export type RenameTrigger = RenameTriggerFn & { reverse: RenameTriggerFn }; diff --git a/src/operations/types.ts b/src/operations/types.ts index b6942c09..1daf5100 100644 --- a/src/operations/types.ts +++ b/src/operations/types.ts @@ -1,16 +1,16 @@ -import { MigrationOptions } from '../types' -import { applyType, escapeValue } from '../utils' +import { MigrationOptions } from '../types'; +import { applyType, escapeValue } from '../utils'; import { + AddTypeAttribute, + AddTypeValue, CreateType, DropType, - RenameType, - AddTypeAttribute, DropTypeAttribute, - SetTypeAttribute, - AddTypeValue, + RenameType, RenameTypeAttribute, RenameTypeValue, -} from './typesTypes' + SetTypeAttribute, +} from './typesTypes'; export { CreateType, @@ -22,116 +22,130 @@ export { AddTypeValue, RenameTypeAttribute, RenameTypeValue, -} +}; export function dropType(mOptions: MigrationOptions) { const _drop: DropType = (typeName, options = {}) => { - const { ifExists, cascade } = options - const ifExistsStr = ifExists ? ' IF EXISTS' : '' - const cascadeStr = cascade ? ' CASCADE' : '' - const typeNameStr = mOptions.literal(typeName) - return `DROP TYPE${ifExistsStr} ${typeNameStr}${cascadeStr};` - } - return _drop + const { ifExists, cascade } = options; + const ifExistsStr = ifExists ? ' IF EXISTS' : ''; + const cascadeStr = cascade ? ' CASCADE' : ''; + const typeNameStr = mOptions.literal(typeName); + return `DROP TYPE${ifExistsStr} ${typeNameStr}${cascadeStr};`; + }; + return _drop; } export function createType(mOptions: MigrationOptions) { const _create: CreateType = (typeName, options) => { if (Array.isArray(options)) { - const optionsStr = options.map(escapeValue).join(', ') - const typeNameStr = mOptions.literal(typeName) - return `CREATE TYPE ${typeNameStr} AS ENUM (${optionsStr});` + const optionsStr = options.map(escapeValue).join(', '); + const typeNameStr = mOptions.literal(typeName); + return `CREATE TYPE ${typeNameStr} AS ENUM (${optionsStr});`; } const attributes = Object.entries(options) .map(([attributeName, attribute]) => { - const typeStr = applyType(attribute, mOptions.typeShorthands).type - return `${mOptions.literal(attributeName)} ${typeStr}` + const typeStr = applyType(attribute, mOptions.typeShorthands).type; + return `${mOptions.literal(attributeName)} ${typeStr}`; }) - .join(',\n') - return `CREATE TYPE ${mOptions.literal(typeName)} AS (\n${attributes}\n);` - } - _create.reverse = dropType(mOptions) - return _create + .join(',\n'); + return `CREATE TYPE ${mOptions.literal(typeName)} AS (\n${attributes}\n);`; + }; + _create.reverse = dropType(mOptions); + return _create; } export function dropTypeAttribute(mOptions: MigrationOptions) { - const _drop: DropTypeAttribute = (typeName, attributeName, { ifExists } = {}) => { - const ifExistsStr = ifExists ? ' IF EXISTS' : '' - const typeNameStr = mOptions.literal(typeName) - const attributeNameStr = mOptions.literal(attributeName) - return `ALTER TYPE ${typeNameStr} DROP ATTRIBUTE ${attributeNameStr}${ifExistsStr};` - } - return _drop + const _drop: DropTypeAttribute = ( + typeName, + attributeName, + { ifExists } = {} + ) => { + const ifExistsStr = ifExists ? ' IF EXISTS' : ''; + const typeNameStr = mOptions.literal(typeName); + const attributeNameStr = mOptions.literal(attributeName); + return `ALTER TYPE ${typeNameStr} DROP ATTRIBUTE ${attributeNameStr}${ifExistsStr};`; + }; + return _drop; } export function addTypeAttribute(mOptions: MigrationOptions) { - const _alterAttributeAdd: AddTypeAttribute = (typeName, attributeName, attributeType) => { - const typeStr = applyType(attributeType, mOptions.typeShorthands).type - const typeNameStr = mOptions.literal(typeName) - const attributeNameStr = mOptions.literal(attributeName) + const _alterAttributeAdd: AddTypeAttribute = ( + typeName, + attributeName, + attributeType + ) => { + const typeStr = applyType(attributeType, mOptions.typeShorthands).type; + const typeNameStr = mOptions.literal(typeName); + const attributeNameStr = mOptions.literal(attributeName); - return `ALTER TYPE ${typeNameStr} ADD ATTRIBUTE ${attributeNameStr} ${typeStr};` - } - _alterAttributeAdd.reverse = dropTypeAttribute(mOptions) - return _alterAttributeAdd + return `ALTER TYPE ${typeNameStr} ADD ATTRIBUTE ${attributeNameStr} ${typeStr};`; + }; + _alterAttributeAdd.reverse = dropTypeAttribute(mOptions); + return _alterAttributeAdd; } export function setTypeAttribute(mOptions: MigrationOptions): SetTypeAttribute { return (typeName, attributeName, attributeType) => { - const typeStr = applyType(attributeType, mOptions.typeShorthands).type - const typeNameStr = mOptions.literal(typeName) - const attributeNameStr = mOptions.literal(attributeName) + const typeStr = applyType(attributeType, mOptions.typeShorthands).type; + const typeNameStr = mOptions.literal(typeName); + const attributeNameStr = mOptions.literal(attributeName); - return `ALTER TYPE ${typeNameStr} ALTER ATTRIBUTE ${attributeNameStr} SET DATA TYPE ${typeStr};` - } + return `ALTER TYPE ${typeNameStr} ALTER ATTRIBUTE ${attributeNameStr} SET DATA TYPE ${typeStr};`; + }; } export function addTypeValue(mOptions: MigrationOptions) { const _add: AddTypeValue = (typeName, value, options = {}) => { - const { ifNotExists, before, after } = options + const { ifNotExists, before, after } = options; if (before && after) { - throw new Error('"before" and "after" can\'t be specified together') + throw new Error('"before" and "after" can\'t be specified together'); } - const beforeStr = before ? ` BEFORE ${escapeValue(before)}` : '' - const afterStr = after ? ` AFTER ${escapeValue(after)}` : '' - const ifNotExistsStr = ifNotExists ? ' IF NOT EXISTS' : '' - const valueStr = escapeValue(value) - const typeNameStr = mOptions.literal(typeName) + const beforeStr = before ? ` BEFORE ${escapeValue(before)}` : ''; + const afterStr = after ? ` AFTER ${escapeValue(after)}` : ''; + const ifNotExistsStr = ifNotExists ? ' IF NOT EXISTS' : ''; + const valueStr = escapeValue(value); + const typeNameStr = mOptions.literal(typeName); - return `ALTER TYPE ${typeNameStr} ADD VALUE${ifNotExistsStr} ${valueStr}${beforeStr}${afterStr};` - } - return _add + return `ALTER TYPE ${typeNameStr} ADD VALUE${ifNotExistsStr} ${valueStr}${beforeStr}${afterStr};`; + }; + return _add; } export function renameType(mOptions: MigrationOptions) { const _rename: RenameType = (typeName, newTypeName) => { - const typeNameStr = mOptions.literal(typeName) - const newTypeNameStr = mOptions.literal(newTypeName) - return `ALTER TYPE ${typeNameStr} RENAME TO ${newTypeNameStr};` - } - _rename.reverse = (typeName, newTypeName) => _rename(newTypeName, typeName) - return _rename + const typeNameStr = mOptions.literal(typeName); + const newTypeNameStr = mOptions.literal(newTypeName); + return `ALTER TYPE ${typeNameStr} RENAME TO ${newTypeNameStr};`; + }; + _rename.reverse = (typeName, newTypeName) => _rename(newTypeName, typeName); + return _rename; } export function renameTypeAttribute(mOptions: MigrationOptions) { - const _rename: RenameTypeAttribute = (typeName, attributeName, newAttributeName) => { - const typeNameStr = mOptions.literal(typeName) - const attributeNameStr = mOptions.literal(attributeName) - const newAttributeNameStr = mOptions.literal(newAttributeName) - return `ALTER TYPE ${typeNameStr} RENAME ATTRIBUTE ${attributeNameStr} TO ${newAttributeNameStr};` - } - _rename.reverse = (typeName, attributeName, newAttributeName) => _rename(typeName, newAttributeName, attributeName) - return _rename + const _rename: RenameTypeAttribute = ( + typeName, + attributeName, + newAttributeName + ) => { + const typeNameStr = mOptions.literal(typeName); + const attributeNameStr = mOptions.literal(attributeName); + const newAttributeNameStr = mOptions.literal(newAttributeName); + return `ALTER TYPE ${typeNameStr} RENAME ATTRIBUTE ${attributeNameStr} TO ${newAttributeNameStr};`; + }; + _rename.reverse = (typeName, attributeName, newAttributeName) => + _rename(typeName, newAttributeName, attributeName); + return _rename; } export function renameTypeValue(mOptions: MigrationOptions) { const _rename: RenameTypeValue = (typeName, value, newValue) => { - const valueStr = escapeValue(value) - const newValueStr = escapeValue(newValue) - const typeNameStr = mOptions.literal(typeName) - return `ALTER TYPE ${typeNameStr} RENAME VALUE ${valueStr} TO ${newValueStr};` - } - _rename.reverse = (typeName, value, newValue) => _rename(typeName, newValue, value) - return _rename + const valueStr = escapeValue(value); + const newValueStr = escapeValue(newValue); + const typeNameStr = mOptions.literal(typeName); + return `ALTER TYPE ${typeNameStr} RENAME VALUE ${valueStr} TO ${newValueStr};`; + }; + _rename.reverse = (typeName, value, newValue) => + _rename(typeName, newValue, value); + return _rename; } diff --git a/src/operations/typesTypes.ts b/src/operations/typesTypes.ts index fbecd4ad..8842c597 100644 --- a/src/operations/typesTypes.ts +++ b/src/operations/typesTypes.ts @@ -1,25 +1,64 @@ -import { Name, Value, Type, DropOptions, IfExistsOption, IfNotExistsOption } from './generalTypes' +import { + DropOptions, + IfExistsOption, + IfNotExistsOption, + Name, + Type, + Value, +} from './generalTypes'; export interface AddTypeValueOptions extends IfNotExistsOption { - before?: string - after?: string + before?: string; + after?: string; } -type CreateTypeFn = (typeName: Name, values: (Value[] | { [name: string]: Type }) & DropOptions) => string | string[] -export type CreateType = CreateTypeFn & { reverse: CreateTypeFn } -export type DropType = (typeName: Name, dropOptions?: DropOptions) => string | string[] -type RenameTypeFn = (typeName: Name, newTypeName: Name) => string | string[] -export type RenameType = RenameTypeFn & { reverse: RenameTypeFn } +type CreateTypeFn = ( + typeName: Name, + values: (Value[] | { [name: string]: Type }) & DropOptions +) => string | string[]; +export type CreateType = CreateTypeFn & { reverse: CreateTypeFn }; +export type DropType = ( + typeName: Name, + dropOptions?: DropOptions +) => string | string[]; +type RenameTypeFn = (typeName: Name, newTypeName: Name) => string | string[]; +export type RenameType = RenameTypeFn & { reverse: RenameTypeFn }; type AddTypeAttributeFn = ( typeName: Name, attributeName: string, - attributeType: Type & IfExistsOption, -) => string | string[] -export type AddTypeAttribute = AddTypeAttributeFn & { reverse: AddTypeAttributeFn } -export type DropTypeAttribute = (typeName: Name, attributeName: string, options: IfExistsOption) => string | string[] -export type SetTypeAttribute = (typeName: Name, attributeName: string, attributeType: Type) => string | string[] -export type AddTypeValue = (typeName: Name, value: Value, options?: AddTypeValueOptions) => string | string[] -type RenameTypeAttributeFn = (typeName: Name, attributeName: string, newAttributeName: string) => string | string[] -export type RenameTypeAttribute = RenameTypeAttributeFn & { reverse: RenameTypeAttributeFn } -type RenameTypeValueFn = (typeName: Name, value: string, newValue: string) => string | string[] -export type RenameTypeValue = RenameTypeValueFn & { reverse: RenameTypeValueFn } + attributeType: Type & IfExistsOption +) => string | string[]; +export type AddTypeAttribute = AddTypeAttributeFn & { + reverse: AddTypeAttributeFn; +}; +export type DropTypeAttribute = ( + typeName: Name, + attributeName: string, + options: IfExistsOption +) => string | string[]; +export type SetTypeAttribute = ( + typeName: Name, + attributeName: string, + attributeType: Type +) => string | string[]; +export type AddTypeValue = ( + typeName: Name, + value: Value, + options?: AddTypeValueOptions +) => string | string[]; +type RenameTypeAttributeFn = ( + typeName: Name, + attributeName: string, + newAttributeName: string +) => string | string[]; +export type RenameTypeAttribute = RenameTypeAttributeFn & { + reverse: RenameTypeAttributeFn; +}; +type RenameTypeValueFn = ( + typeName: Name, + value: string, + newValue: string +) => string | string[]; +export type RenameTypeValue = RenameTypeValueFn & { + reverse: RenameTypeValueFn; +}; diff --git a/src/operations/views.ts b/src/operations/views.ts index d8f95b09..ba6e201a 100644 --- a/src/operations/views.ts +++ b/src/operations/views.ts @@ -1,100 +1,136 @@ -import { MigrationOptions } from '../types' -import { escapeValue } from '../utils' -import { CreateView, DropView, AlterView, AlterViewColumn, RenameView, ViewOptions } from './viewsTypes' -import { Nullable } from './generalTypes' +import { MigrationOptions } from '../types'; +import { escapeValue } from '../utils'; +import { Nullable } from './generalTypes'; +import { + AlterView, + AlterViewColumn, + CreateView, + DropView, + RenameView, + ViewOptions, +} from './viewsTypes'; -export { CreateView, DropView, AlterView, AlterViewColumn, RenameView, ViewOptions } +export { + CreateView, + DropView, + AlterView, + AlterViewColumn, + RenameView, + ViewOptions, +}; const viewOptionStr = , K extends keyof T>(options: T) => (key: K) => { - const value = options[key] === true ? '' : ` = ${options[key]}` - return `${key}${value}` - } + const value = options[key] === true ? '' : ` = ${options[key]}`; + return `${key}${value}`; + }; export function dropView(mOptions: MigrationOptions) { const _drop: DropView = (viewName, options = {}) => { - const { ifExists, cascade } = options - const ifExistsStr = ifExists ? ' IF EXISTS' : '' - const cascadeStr = cascade ? ' CASCADE' : '' - const viewNameStr = mOptions.literal(viewName) - return `DROP VIEW${ifExistsStr} ${viewNameStr}${cascadeStr};` - } - return _drop + const { ifExists, cascade } = options; + const ifExistsStr = ifExists ? ' IF EXISTS' : ''; + const cascadeStr = cascade ? ' CASCADE' : ''; + const viewNameStr = mOptions.literal(viewName); + return `DROP VIEW${ifExistsStr} ${viewNameStr}${cascadeStr};`; + }; + return _drop; } export function createView(mOptions: MigrationOptions) { const _create: CreateView = (viewName, viewOptions, definition) => { - const { temporary, replace, recursive, columns = [], options = {}, checkOption } = viewOptions - const columnNames = (Array.isArray(columns) ? columns : [columns]).map(mOptions.literal).join(', ') - const withOptions = Object.keys(options).map(viewOptionStr(options)).join(', ') + const { + temporary, + replace, + recursive, + columns = [], + options = {}, + checkOption, + } = viewOptions; + const columnNames = (Array.isArray(columns) ? columns : [columns]) + .map(mOptions.literal) + .join(', '); + const withOptions = Object.keys(options) + .map(viewOptionStr(options)) + .join(', '); - const replaceStr = replace ? ' OR REPLACE' : '' - const temporaryStr = temporary ? ' TEMPORARY' : '' - const recursiveStr = recursive ? ' RECURSIVE' : '' - const columnStr = columnNames ? `(${columnNames})` : '' - const withOptionsStr = withOptions ? ` WITH (${withOptions})` : '' - const checkOptionStr = checkOption ? ` WITH ${checkOption} CHECK OPTION` : '' - const viewNameStr = mOptions.literal(viewName) + const replaceStr = replace ? ' OR REPLACE' : ''; + const temporaryStr = temporary ? ' TEMPORARY' : ''; + const recursiveStr = recursive ? ' RECURSIVE' : ''; + const columnStr = columnNames ? `(${columnNames})` : ''; + const withOptionsStr = withOptions ? ` WITH (${withOptions})` : ''; + const checkOptionStr = checkOption + ? ` WITH ${checkOption} CHECK OPTION` + : ''; + const viewNameStr = mOptions.literal(viewName); - return `CREATE${replaceStr}${temporaryStr}${recursiveStr} VIEW ${viewNameStr}${columnStr}${withOptionsStr} AS ${definition}${checkOptionStr};` - } - _create.reverse = dropView(mOptions) - return _create + return `CREATE${replaceStr}${temporaryStr}${recursiveStr} VIEW ${viewNameStr}${columnStr}${withOptionsStr} AS ${definition}${checkOptionStr};`; + }; + _create.reverse = dropView(mOptions); + return _create; } export function alterView(mOptions: MigrationOptions) { const _alter: AlterView = (viewName, viewOptions) => { - const { checkOption, options = {} } = viewOptions + const { checkOption, options = {} } = viewOptions; if (checkOption !== undefined) { if (options.check_option === undefined) { - options.check_option = checkOption + options.check_option = checkOption; } else { - throw new Error('"options.check_option" and "checkOption" can\'t be specified together') + throw new Error( + '"options.check_option" and "checkOption" can\'t be specified together' + ); } } - const clauses = [] + const clauses = []; const withOptions = Object.keys(options) .filter((key) => options[key] !== null) .map(viewOptionStr(options)) - .join(', ') + .join(', '); if (withOptions) { - clauses.push(`SET (${withOptions})`) + clauses.push(`SET (${withOptions})`); } const resetOptions = Object.keys(options) .filter((key) => options[key] === null) - .join(', ') + .join(', '); if (resetOptions) { - clauses.push(`RESET (${resetOptions})`) + clauses.push(`RESET (${resetOptions})`); } - return clauses.map((clause) => `ALTER VIEW ${mOptions.literal(viewName)} ${clause};`).join('\n') - } - return _alter + return clauses + .map((clause) => `ALTER VIEW ${mOptions.literal(viewName)} ${clause};`) + .join('\n'); + }; + return _alter; } export function alterViewColumn(mOptions: MigrationOptions) { const _alter: AlterViewColumn = (viewName, columnName, options) => { - const { default: defaultValue } = options - const actions = [] + const { default: defaultValue } = options; + const actions = []; if (defaultValue === null) { - actions.push('DROP DEFAULT') + actions.push('DROP DEFAULT'); } else if (defaultValue !== undefined) { - actions.push(`SET DEFAULT ${escapeValue(defaultValue)}`) + actions.push(`SET DEFAULT ${escapeValue(defaultValue)}`); } - const viewNameStr = mOptions.literal(viewName) - const columnNameStr = mOptions.literal(columnName) - return actions.map((action) => `ALTER VIEW ${viewNameStr} ALTER COLUMN ${columnNameStr} ${action};`).join('\n') - } - return _alter + const viewNameStr = mOptions.literal(viewName); + const columnNameStr = mOptions.literal(columnName); + return actions + .map( + (action) => + `ALTER VIEW ${viewNameStr} ALTER COLUMN ${columnNameStr} ${action};` + ) + .join('\n'); + }; + return _alter; } export function renameView(mOptions: MigrationOptions) { const _rename: RenameView = (viewName, newViewName) => { - const viewNameStr = mOptions.literal(viewName) - const newViewNameStr = mOptions.literal(newViewName) - return `ALTER VIEW ${viewNameStr} RENAME TO ${newViewNameStr};` - } - _rename.reverse = (viewName, newViewName) => _rename(newViewName, viewName) - return _rename + const viewNameStr = mOptions.literal(viewName); + const newViewNameStr = mOptions.literal(newViewName); + return `ALTER VIEW ${viewNameStr} RENAME TO ${newViewNameStr};`; + }; + _rename.reverse = (viewName, newViewName) => _rename(newViewName, viewName); + return _rename; } diff --git a/src/operations/viewsMaterialized.ts b/src/operations/viewsMaterialized.ts index bda67f22..e42c8513 100644 --- a/src/operations/viewsMaterialized.ts +++ b/src/operations/viewsMaterialized.ts @@ -1,15 +1,15 @@ -import { MigrationOptions } from '../types' -import { formatLines } from '../utils' +import { MigrationOptions } from '../types'; +import { formatLines } from '../utils'; +import { Nullable } from './generalTypes'; import { - StorageParameters, + AlterMaterializedView, CreateMaterializedView, DropMaterializedView, - AlterMaterializedView, + RefreshMaterializedView, RenameMaterializedView, RenameMaterializedViewColumn, - RefreshMaterializedView, -} from './viewsMaterializedTypes' -import { Nullable } from './generalTypes' + StorageParameters, +} from './viewsMaterializedTypes'; export { CreateMaterializedView, @@ -18,109 +18,130 @@ export { RenameMaterializedView, RenameMaterializedViewColumn, RefreshMaterializedView, -} +}; -const dataClause = (data?: boolean) => (data !== undefined ? ` WITH${data ? '' : ' NO'} DATA` : '') +const dataClause = (data?: boolean) => + data !== undefined ? ` WITH${data ? '' : ' NO'} DATA` : ''; const storageParameterStr = - , K extends keyof T>(storageParameters: T) => + , K extends keyof T>( + storageParameters: T + ) => (key: K) => { - const value = storageParameters[key] === true ? '' : ` = ${storageParameters[key]}` - return `${key}${value}` - } + const value = + storageParameters[key] === true ? '' : ` = ${storageParameters[key]}`; + return `${key}${value}`; + }; export function dropMaterializedView(mOptions: MigrationOptions) { const _drop: DropMaterializedView = (viewName, options = {}) => { - const { ifExists, cascade } = options - const ifExistsStr = ifExists ? ' IF EXISTS' : '' - const cascadeStr = cascade ? ' CASCADE' : '' - const viewNameStr = mOptions.literal(viewName) - return `DROP MATERIALIZED VIEW${ifExistsStr} ${viewNameStr}${cascadeStr};` - } - return _drop + const { ifExists, cascade } = options; + const ifExistsStr = ifExists ? ' IF EXISTS' : ''; + const cascadeStr = cascade ? ' CASCADE' : ''; + const viewNameStr = mOptions.literal(viewName); + return `DROP MATERIALIZED VIEW${ifExistsStr} ${viewNameStr}${cascadeStr};`; + }; + return _drop; } export function createMaterializedView(mOptions: MigrationOptions) { const _create: CreateMaterializedView = (viewName, options, definition) => { - const { ifNotExists, columns = [], tablespace, storageParameters = {}, data } = options - const columnNames = (Array.isArray(columns) ? columns : [columns]).map(mOptions.literal).join(', ') - const withOptions = Object.keys(storageParameters).map(storageParameterStr(storageParameters)).join(', ') + const { + ifNotExists, + columns = [], + tablespace, + storageParameters = {}, + data, + } = options; + const columnNames = (Array.isArray(columns) ? columns : [columns]) + .map(mOptions.literal) + .join(', '); + const withOptions = Object.keys(storageParameters) + .map(storageParameterStr(storageParameters)) + .join(', '); - const ifNotExistsStr = ifNotExists ? ' IF NOT EXISTS' : '' - const columnsStr = columnNames ? `(${columnNames})` : '' - const withOptionsStr = withOptions ? ` WITH (${withOptions})` : '' - const tablespaceStr = tablespace ? `TABLESPACE ${mOptions.literal(tablespace)}` : '' - const dataStr = dataClause(data) - const viewNameStr = mOptions.literal(viewName) + const ifNotExistsStr = ifNotExists ? ' IF NOT EXISTS' : ''; + const columnsStr = columnNames ? `(${columnNames})` : ''; + const withOptionsStr = withOptions ? ` WITH (${withOptions})` : ''; + const tablespaceStr = tablespace + ? `TABLESPACE ${mOptions.literal(tablespace)}` + : ''; + const dataStr = dataClause(data); + const viewNameStr = mOptions.literal(viewName); - return `CREATE MATERIALIZED VIEW${ifNotExistsStr} ${viewNameStr}${columnsStr}${withOptionsStr}${tablespaceStr} AS ${definition}${dataStr};` - } - _create.reverse = dropMaterializedView(mOptions) - return _create + return `CREATE MATERIALIZED VIEW${ifNotExistsStr} ${viewNameStr}${columnsStr}${withOptionsStr}${tablespaceStr} AS ${definition}${dataStr};`; + }; + _create.reverse = dropMaterializedView(mOptions); + return _create; } export function alterMaterializedView(mOptions: MigrationOptions) { const _alter: AlterMaterializedView = (viewName, options) => { - const { cluster, extension, storageParameters = {} } = options - const clauses = [] + const { cluster, extension, storageParameters = {} } = options; + const clauses = []; if (cluster !== undefined) { if (cluster) { - clauses.push(`CLUSTER ON ${mOptions.literal(cluster)}`) + clauses.push(`CLUSTER ON ${mOptions.literal(cluster)}`); } else { - clauses.push(`SET WITHOUT CLUSTER`) + clauses.push(`SET WITHOUT CLUSTER`); } } if (extension) { - clauses.push(`DEPENDS ON EXTENSION ${mOptions.literal(extension)}`) + clauses.push(`DEPENDS ON EXTENSION ${mOptions.literal(extension)}`); } const withOptions = Object.keys(storageParameters) .filter((key) => storageParameters[key] !== null) .map(storageParameterStr(storageParameters)) - .join(', ') + .join(', '); if (withOptions) { - clauses.push(`SET (${withOptions})`) + clauses.push(`SET (${withOptions})`); } const resetOptions = Object.keys(storageParameters) .filter((key) => storageParameters[key] === null) - .join(', ') + .join(', '); if (resetOptions) { - clauses.push(`RESET (${resetOptions})`) + clauses.push(`RESET (${resetOptions})`); } - const clausesStr = formatLines(clauses) - const viewNameStr = mOptions.literal(viewName) - return `ALTER MATERIALIZED VIEW ${viewNameStr}\n${clausesStr};` - } - return _alter + const clausesStr = formatLines(clauses); + const viewNameStr = mOptions.literal(viewName); + return `ALTER MATERIALIZED VIEW ${viewNameStr}\n${clausesStr};`; + }; + return _alter; } export function renameMaterializedView(mOptions: MigrationOptions) { const _rename: RenameMaterializedView = (viewName, newViewName) => { - const viewNameStr = mOptions.literal(viewName) - const newViewNameStr = mOptions.literal(newViewName) - return `ALTER MATERIALIZED VIEW ${viewNameStr} RENAME TO ${newViewNameStr};` - } - _rename.reverse = (viewName, newViewName) => _rename(newViewName, viewName) - return _rename + const viewNameStr = mOptions.literal(viewName); + const newViewNameStr = mOptions.literal(newViewName); + return `ALTER MATERIALIZED VIEW ${viewNameStr} RENAME TO ${newViewNameStr};`; + }; + _rename.reverse = (viewName, newViewName) => _rename(newViewName, viewName); + return _rename; } export function renameMaterializedViewColumn(mOptions: MigrationOptions) { - const _rename: RenameMaterializedViewColumn = (viewName, columnName, newColumnName) => { - const viewNameStr = mOptions.literal(viewName) - const columnNameStr = mOptions.literal(columnName) - const newColumnNameStr = mOptions.literal(newColumnName) - return `ALTER MATERIALIZED VIEW ${viewNameStr} RENAME COLUMN ${columnNameStr} TO ${newColumnNameStr};` - } - _rename.reverse = (viewName, columnName, newColumnName) => _rename(viewName, newColumnName, columnName) - return _rename + const _rename: RenameMaterializedViewColumn = ( + viewName, + columnName, + newColumnName + ) => { + const viewNameStr = mOptions.literal(viewName); + const columnNameStr = mOptions.literal(columnName); + const newColumnNameStr = mOptions.literal(newColumnName); + return `ALTER MATERIALIZED VIEW ${viewNameStr} RENAME COLUMN ${columnNameStr} TO ${newColumnNameStr};`; + }; + _rename.reverse = (viewName, columnName, newColumnName) => + _rename(viewName, newColumnName, columnName); + return _rename; } export function refreshMaterializedView(mOptions: MigrationOptions) { const _refresh: RefreshMaterializedView = (viewName, options = {}) => { - const { concurrently, data } = options - const concurrentlyStr = concurrently ? ' CONCURRENTLY' : '' - const dataStr = dataClause(data) - const viewNameStr = mOptions.literal(viewName) - return `REFRESH MATERIALIZED VIEW${concurrentlyStr} ${viewNameStr}${dataStr};` - } - _refresh.reverse = _refresh - return _refresh + const { concurrently, data } = options; + const concurrentlyStr = concurrently ? ' CONCURRENTLY' : ''; + const dataStr = dataClause(data); + const viewNameStr = mOptions.literal(viewName); + return `REFRESH MATERIALIZED VIEW${concurrentlyStr} ${viewNameStr}${dataStr};`; + }; + _refresh.reverse = _refresh; + return _refresh; } diff --git a/src/operations/viewsMaterializedTypes.ts b/src/operations/viewsMaterializedTypes.ts index b5932f8a..15eab9a8 100644 --- a/src/operations/viewsMaterializedTypes.ts +++ b/src/operations/viewsMaterializedTypes.ts @@ -1,36 +1,60 @@ -import { Name, DropOptions, IfNotExistsOption, Nullable } from './generalTypes' +import { DropOptions, IfNotExistsOption, Name, Nullable } from './generalTypes'; -export type StorageParameters = { [key: string]: boolean | number } +export type StorageParameters = { [key: string]: boolean | number }; export interface CreateMaterializedViewOptions extends IfNotExistsOption { - columns?: string | string[] - tablespace?: string - storageParameters?: StorageParameters - data?: boolean + columns?: string | string[]; + tablespace?: string; + storageParameters?: StorageParameters; + data?: boolean; } export interface AlterMaterializedViewOptions { - cluster?: null | false | string - extension?: string - storageParameters?: Nullable + cluster?: null | false | string; + extension?: string; + storageParameters?: Nullable; } export interface RefreshMaterializedViewOptions { - concurrently?: boolean - data?: boolean + concurrently?: boolean; + data?: boolean; } type CreateMaterializedViewFn = ( viewName: Name, options: CreateMaterializedViewOptions & DropOptions, - definition: string, -) => string | string[] -export type CreateMaterializedView = CreateMaterializedViewFn & { reverse: CreateMaterializedViewFn } -export type DropMaterializedView = (viewName: Name, options?: DropOptions) => string | string[] -export type AlterMaterializedView = (viewName: Name, options: AlterMaterializedViewOptions) => string | string[] -type RenameMaterializedViewFn = (viewName: Name, newViewName: Name) => string | string[] -export type RenameMaterializedView = RenameMaterializedViewFn & { reverse: RenameMaterializedViewFn } -type RenameMaterializedViewColumnFn = (viewName: Name, columnName: string, newColumnName: string) => string | string[] -export type RenameMaterializedViewColumn = RenameMaterializedViewColumnFn & { reverse: RenameMaterializedViewColumnFn } -type RefreshMaterializedViewFn = (viewName: Name, options?: RefreshMaterializedViewOptions) => string | string[] -export type RefreshMaterializedView = RefreshMaterializedViewFn & { reverse: RefreshMaterializedViewFn } + definition: string +) => string | string[]; +export type CreateMaterializedView = CreateMaterializedViewFn & { + reverse: CreateMaterializedViewFn; +}; +export type DropMaterializedView = ( + viewName: Name, + options?: DropOptions +) => string | string[]; +export type AlterMaterializedView = ( + viewName: Name, + options: AlterMaterializedViewOptions +) => string | string[]; +type RenameMaterializedViewFn = ( + viewName: Name, + newViewName: Name +) => string | string[]; +export type RenameMaterializedView = RenameMaterializedViewFn & { + reverse: RenameMaterializedViewFn; +}; +type RenameMaterializedViewColumnFn = ( + viewName: Name, + columnName: string, + newColumnName: string +) => string | string[]; +export type RenameMaterializedViewColumn = RenameMaterializedViewColumnFn & { + reverse: RenameMaterializedViewColumnFn; +}; +type RefreshMaterializedViewFn = ( + viewName: Name, + options?: RefreshMaterializedViewOptions +) => string | string[]; +export type RefreshMaterializedView = RefreshMaterializedViewFn & { + reverse: RefreshMaterializedViewFn; +}; diff --git a/src/operations/viewsTypes.ts b/src/operations/viewsTypes.ts index 4895491a..ca0e3f92 100644 --- a/src/operations/viewsTypes.ts +++ b/src/operations/viewsTypes.ts @@ -1,29 +1,43 @@ -import { Name, Value, DropOptions, Nullable } from './generalTypes' +import { DropOptions, Name, Nullable, Value } from './generalTypes'; -export type ViewOptions = { [key: string]: boolean | number | string } +export type ViewOptions = { [key: string]: boolean | number | string }; export interface CreateViewOptions { - temporary?: boolean - replace?: boolean - recursive?: boolean - columns?: string | string[] - checkOption?: 'CASCADED' | 'LOCAL' - options?: ViewOptions + temporary?: boolean; + replace?: boolean; + recursive?: boolean; + columns?: string | string[]; + checkOption?: 'CASCADED' | 'LOCAL'; + options?: ViewOptions; } export interface AlterViewOptions { - checkOption?: null | 'CASCADED' | 'LOCAL' - options?: Nullable + checkOption?: null | 'CASCADED' | 'LOCAL'; + options?: Nullable; } export interface AlterViewColumnOptions { - default?: Value + default?: Value; } -type CreateViewFn = (viewName: Name, options: CreateViewOptions & DropOptions, definition: string) => string | string[] -export type CreateView = CreateViewFn & { reverse: CreateViewFn } -export type DropView = (viewName: Name, options?: DropOptions) => string | string[] -export type AlterView = (viewName: Name, options: AlterViewOptions) => string | string[] -export type AlterViewColumn = (viewName: Name, columnName: string, options: AlterViewColumnOptions) => string | string[] -type RenameViewFn = (viewName: Name, newViewName: Name) => string | string[] -export type RenameView = RenameViewFn & { reverse: RenameViewFn } +type CreateViewFn = ( + viewName: Name, + options: CreateViewOptions & DropOptions, + definition: string +) => string | string[]; +export type CreateView = CreateViewFn & { reverse: CreateViewFn }; +export type DropView = ( + viewName: Name, + options?: DropOptions +) => string | string[]; +export type AlterView = ( + viewName: Name, + options: AlterViewOptions +) => string | string[]; +export type AlterViewColumn = ( + viewName: Name, + columnName: string, + options: AlterViewColumnOptions +) => string | string[]; +type RenameViewFn = (viewName: Name, newViewName: Name) => string | string[]; +export type RenameView = RenameViewFn & { reverse: RenameViewFn }; diff --git a/src/runner.ts b/src/runner.ts index 307a0c51..5a91edf8 100644 --- a/src/runner.ts +++ b/src/runner.ts @@ -1,39 +1,43 @@ -import path from 'path' -import Db, { DBConnection } from './db' -import { ColumnDefinitions } from './operations/tablesTypes' -import { Migration, loadMigrationFiles, RunMigration } from './migration' +import path from 'path'; +import Db, { DBConnection } from './db'; +import { loadMigrationFiles, Migration, RunMigration } from './migration'; +import { ColumnDefinitions } from './operations/tablesTypes'; +import migrateSqlFile from './sqlMigration'; import { + Logger, MigrationBuilderActions, MigrationDirection, + RunnerOption, RunnerOptionClient, RunnerOptionUrl, - RunnerOption, - Logger, -} from './types' -import { createSchemalize, getMigrationTableSchema, getSchemas } from './utils' -import migrateSqlFile from './sqlMigration' +} from './types'; +import { createSchemalize, getMigrationTableSchema, getSchemas } from './utils'; // Random but well-known identifier shared by all instances of node-pg-migrate -const PG_MIGRATE_LOCK_ID = 7241865325823964 +const PG_MIGRATE_LOCK_ID = 7241865325823964; -const idColumn = 'id' -const nameColumn = 'name' -const runOnColumn = 'run_on' +const idColumn = 'id'; +const nameColumn = 'name'; +const runOnColumn = 'run_on'; -const loadMigrations = async (db: DBConnection, options: RunnerOption, logger: Logger) => { +const loadMigrations = async ( + db: DBConnection, + options: RunnerOption, + logger: Logger +) => { try { - let shorthands: ColumnDefinitions = {} - const files = await loadMigrationFiles(options.dir, options.ignorePattern) + let shorthands: ColumnDefinitions = {}; + const files = await loadMigrationFiles(options.dir, options.ignorePattern); return ( await Promise.all( files.map(async (file) => { - const filePath = `${options.dir}/${file}` + const filePath = `${options.dir}/${file}`; const actions: MigrationBuilderActions = path.extname(filePath) === '.sql' ? await migrateSqlFile(filePath) : // eslint-disable-next-line global-require,import/no-dynamic-require,security/detect-non-literal-require - require(path.relative(__dirname, filePath)) - shorthands = { ...shorthands, ...actions.shorthands } + require(path.relative(__dirname, filePath)); + shorthands = { ...shorthands, ...actions.shorthands }; return new Migration( db, filePath, @@ -42,133 +46,169 @@ const loadMigrations = async (db: DBConnection, options: RunnerOption, logger: L { ...shorthands, }, - logger, - ) - }), + logger + ); + }) ) ).sort((m1, m2) => { - const compare = m1.timestamp - m2.timestamp - if (compare !== 0) return compare - return m1.name.localeCompare(m2.name) - }) + const compare = m1.timestamp - m2.timestamp; + if (compare !== 0) return compare; + return m1.name.localeCompare(m2.name); + }); // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (err: any) { - throw new Error(`Can't get migration files: ${err.stack}`) + throw new Error(`Can't get migration files: ${err.stack}`); } -} +}; const lock = async (db: DBConnection): Promise => { - const [result] = await db.select(`select pg_try_advisory_lock(${PG_MIGRATE_LOCK_ID}) as "lockObtained"`) + const [result] = await db.select( + `select pg_try_advisory_lock(${PG_MIGRATE_LOCK_ID}) as "lockObtained"` + ); if (!result.lockObtained) { - throw new Error('Another migration is already running') + throw new Error('Another migration is already running'); } -} +}; const unlock = async (db: DBConnection): Promise => { - const [result] = await db.select(`select pg_advisory_unlock(${PG_MIGRATE_LOCK_ID}) as "lockReleased"`) + const [result] = await db.select( + `select pg_advisory_unlock(${PG_MIGRATE_LOCK_ID}) as "lockReleased"` + ); if (!result.lockReleased) { - throw new Error('Failed to release migration lock') + throw new Error('Failed to release migration lock'); } -} +}; -const ensureMigrationsTable = async (db: DBConnection, options: RunnerOption): Promise => { +const ensureMigrationsTable = async ( + db: DBConnection, + options: RunnerOption +): Promise => { try { - const schema = getMigrationTableSchema(options) - const { migrationsTable } = options + const schema = getMigrationTableSchema(options); + const { migrationsTable } = options; const fullTableName = createSchemalize( Boolean(options.decamelize), - true, + true )({ schema, name: migrationsTable, - }) + }); const migrationTables = await db.select( - `SELECT table_name FROM information_schema.tables WHERE table_schema = '${schema}' AND table_name = '${migrationsTable}'`, - ) + `SELECT table_name FROM information_schema.tables WHERE table_schema = '${schema}' AND table_name = '${migrationsTable}'` + ); if (migrationTables && migrationTables.length === 1) { const primaryKeyConstraints = await db.select( - `SELECT constraint_name FROM information_schema.table_constraints WHERE table_schema = '${schema}' AND table_name = '${migrationsTable}' AND constraint_type = 'PRIMARY KEY'`, - ) + `SELECT constraint_name FROM information_schema.table_constraints WHERE table_schema = '${schema}' AND table_name = '${migrationsTable}' AND constraint_type = 'PRIMARY KEY'` + ); if (!primaryKeyConstraints || primaryKeyConstraints.length !== 1) { - await db.query(`ALTER TABLE ${fullTableName} ADD PRIMARY KEY (${idColumn})`) + await db.query( + `ALTER TABLE ${fullTableName} ADD PRIMARY KEY (${idColumn})` + ); } } else { await db.query( - `CREATE TABLE ${fullTableName} ( ${idColumn} SERIAL PRIMARY KEY, ${nameColumn} varchar(255) NOT NULL, ${runOnColumn} timestamp NOT NULL)`, - ) + `CREATE TABLE ${fullTableName} ( ${idColumn} SERIAL PRIMARY KEY, ${nameColumn} varchar(255) NOT NULL, ${runOnColumn} timestamp NOT NULL)` + ); } // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (err: any) { - throw new Error(`Unable to ensure migrations table: ${err.stack}`) + throw new Error(`Unable to ensure migrations table: ${err.stack}`); } -} +}; const getRunMigrations = async (db: DBConnection, options: RunnerOption) => { - const schema = getMigrationTableSchema(options) - const { migrationsTable } = options + const schema = getMigrationTableSchema(options); + const { migrationsTable } = options; const fullTableName = createSchemalize( Boolean(options.decamelize), - true, + true )({ schema, name: migrationsTable, - }) - return db.column(nameColumn, `SELECT ${nameColumn} FROM ${fullTableName} ORDER BY ${runOnColumn}, ${idColumn}`) -} + }); + return db.column( + nameColumn, + `SELECT ${nameColumn} FROM ${fullTableName} ORDER BY ${runOnColumn}, ${idColumn}` + ); +}; -const getMigrationsToRun = (options: RunnerOption, runNames: string[], migrations: Migration[]): Migration[] => { +const getMigrationsToRun = ( + options: RunnerOption, + runNames: string[], + migrations: Migration[] +): Migration[] => { if (options.direction === 'down') { const downMigrations: Array = runNames - .filter((migrationName) => !options.file || options.file === migrationName) - .map((migrationName) => migrations.find(({ name }) => name === migrationName) || migrationName) - const { count = 1 } = options + .filter( + (migrationName) => !options.file || options.file === migrationName + ) + .map( + (migrationName) => + migrations.find(({ name }) => name === migrationName) || migrationName + ); + const { count = 1 } = options; const toRun = ( options.timestamp - ? downMigrations.filter((migration) => typeof migration === 'object' && migration.timestamp >= count) + ? downMigrations.filter( + (migration) => + typeof migration === 'object' && migration.timestamp >= count + ) : downMigrations.slice(-Math.abs(count)) - ).reverse() - const deletedMigrations = toRun.filter((migration): migration is string => typeof migration === 'string') + ).reverse(); + const deletedMigrations = toRun.filter( + (migration): migration is string => typeof migration === 'string' + ); if (deletedMigrations.length) { - const deletedMigrationsStr = deletedMigrations.join(', ') - throw new Error(`Definitions of migrations ${deletedMigrationsStr} have been deleted.`) + const deletedMigrationsStr = deletedMigrations.join(', '); + throw new Error( + `Definitions of migrations ${deletedMigrationsStr} have been deleted.` + ); } - return toRun as Migration[] + return toRun as Migration[]; } const upMigrations = migrations.filter( - ({ name }) => runNames.indexOf(name) < 0 && (!options.file || options.file === name), - ) - const { count = Infinity } = options + ({ name }) => + runNames.indexOf(name) < 0 && (!options.file || options.file === name) + ); + const { count = Infinity } = options; return options.timestamp ? upMigrations.filter(({ timestamp }) => timestamp <= count) - : upMigrations.slice(0, Math.abs(count)) -} + : upMigrations.slice(0, Math.abs(count)); +}; const checkOrder = (runNames: string[], migrations: Migration[]) => { - const len = Math.min(runNames.length, migrations.length) + const len = Math.min(runNames.length, migrations.length); for (let i = 0; i < len; i += 1) { - const runName = runNames[i] - const migrationName = migrations[i].name + const runName = runNames[i]; + const migrationName = migrations[i].name; if (runName !== migrationName) { - throw new Error(`Not run migration ${migrationName} is preceding already run migration ${runName}`) + throw new Error( + `Not run migration ${migrationName} is preceding already run migration ${runName}` + ); } } -} +}; -const runMigrations = (toRun: Migration[], method: 'markAsRun' | 'apply', direction: MigrationDirection) => +const runMigrations = ( + toRun: Migration[], + method: 'markAsRun' | 'apply', + direction: MigrationDirection +) => toRun.reduce( - (promise: Promise, migration) => promise.then(() => migration[method](direction)), - Promise.resolve(), - ) + (promise: Promise, migration) => + promise.then(() => migration[method](direction)), + Promise.resolve() + ); const getLogger = ({ log, logger, verbose }: RunnerOption): Logger => { - let loggerObject: Logger = console + let loggerObject: Logger = console; if (typeof logger === 'object') { - loggerObject = logger + loggerObject = logger; } else if (typeof log === 'function') { - loggerObject = { debug: log, info: log, warn: log, error: log } + loggerObject = { debug: log, info: log, warn: log, error: log }; } return verbose ? loggerObject @@ -177,81 +217,97 @@ const getLogger = ({ log, logger, verbose }: RunnerOption): Logger => { info: loggerObject.info.bind(loggerObject), warn: loggerObject.warn.bind(loggerObject), error: loggerObject.error.bind(loggerObject), - } -} + }; +}; export default async (options: RunnerOption): Promise => { - const logger = getLogger(options) - const db = Db((options as RunnerOptionClient).dbClient || (options as RunnerOptionUrl).databaseUrl, logger) + const logger = getLogger(options); + const db = Db( + (options as RunnerOptionClient).dbClient || + (options as RunnerOptionUrl).databaseUrl, + logger + ); try { - await db.createConnection() + await db.createConnection(); if (!options.noLock) { - await lock(db) + await lock(db); } if (options.schema) { - const schemas = getSchemas(options.schema) + const schemas = getSchemas(options.schema); if (options.createSchema) { - await Promise.all(schemas.map((schema) => db.query(`CREATE SCHEMA IF NOT EXISTS "${schema}"`))) + await Promise.all( + schemas.map((schema) => + db.query(`CREATE SCHEMA IF NOT EXISTS "${schema}"`) + ) + ); } - await db.query(`SET search_path TO ${schemas.map((s) => `"${s}"`).join(', ')}`) + await db.query( + `SET search_path TO ${schemas.map((s) => `"${s}"`).join(', ')}` + ); } if (options.migrationsSchema && options.createMigrationsSchema) { - await db.query(`CREATE SCHEMA IF NOT EXISTS "${options.migrationsSchema}"`) + await db.query( + `CREATE SCHEMA IF NOT EXISTS "${options.migrationsSchema}"` + ); } - await ensureMigrationsTable(db, options) + await ensureMigrationsTable(db, options); const [migrations, runNames] = await Promise.all([ loadMigrations(db, options, logger), getRunMigrations(db, options), - ]) + ]); if (options.checkOrder) { - checkOrder(runNames, migrations) + checkOrder(runNames, migrations); } - const toRun: Migration[] = getMigrationsToRun(options, runNames, migrations) + const toRun: Migration[] = getMigrationsToRun( + options, + runNames, + migrations + ); if (!toRun.length) { - logger.info('No migrations to run!') - return [] + logger.info('No migrations to run!'); + return []; } // TODO: add some fancy colors to logging - logger.info('> Migrating files:') + logger.info('> Migrating files:'); toRun.forEach((m) => { - logger.info(`> - ${m.name}`) - }) + logger.info(`> - ${m.name}`); + }); if (options.fake) { - await runMigrations(toRun, 'markAsRun', options.direction) + await runMigrations(toRun, 'markAsRun', options.direction); } else if (options.singleTransaction) { - await db.query('BEGIN') + await db.query('BEGIN'); try { - await runMigrations(toRun, 'apply', options.direction) - await db.query('COMMIT') + await runMigrations(toRun, 'apply', options.direction); + await db.query('COMMIT'); } catch (err) { - logger.warn('> Rolling back attempted migration ...') - await db.query('ROLLBACK') - throw err + logger.warn('> Rolling back attempted migration ...'); + await db.query('ROLLBACK'); + throw err; } } else { - await runMigrations(toRun, 'apply', options.direction) + await runMigrations(toRun, 'apply', options.direction); } return toRun.map((m) => ({ path: m.path, name: m.name, timestamp: m.timestamp, - })) + })); } finally { if (db.connected()) { if (!options.noLock) { - await unlock(db).catch((error) => logger.warn(error.message)) + await unlock(db).catch((error) => logger.warn(error.message)); } - db.close() + db.close(); } } -} +}; diff --git a/src/sqlMigration.ts b/src/sqlMigration.ts index 804604fa..83161134 100644 --- a/src/sqlMigration.ts +++ b/src/sqlMigration.ts @@ -1,34 +1,40 @@ -import fs from 'fs' -import { MigrationBuilderActions } from './types' +import fs from 'fs'; +import { MigrationBuilderActions } from './types'; -const { readFile } = fs.promises +const { readFile } = fs.promises; const createMigrationCommentRegex = (direction: 'up' | 'down') => - new RegExp(`^\\s*--[\\s-]*${direction}\\s+migration`, 'im') // eslint-disable-line security/detect-non-literal-regexp + new RegExp(`^\\s*--[\\s-]*${direction}\\s+migration`, 'im'); // eslint-disable-line security/detect-non-literal-regexp export const getActions = (content: string): MigrationBuilderActions => { - const upMigrationCommentRegex = createMigrationCommentRegex('up') - const downMigrationCommentRegex = createMigrationCommentRegex('down') + const upMigrationCommentRegex = createMigrationCommentRegex('up'); + const downMigrationCommentRegex = createMigrationCommentRegex('down'); - const upMigrationStart = content.search(upMigrationCommentRegex) - const downMigrationStart = content.search(downMigrationCommentRegex) + const upMigrationStart = content.search(upMigrationCommentRegex); + const downMigrationStart = content.search(downMigrationCommentRegex); const upSql = upMigrationStart >= 0 - ? content.substr(upMigrationStart, downMigrationStart < upMigrationStart ? undefined : downMigrationStart) - : content + ? content.substr( + upMigrationStart, + downMigrationStart < upMigrationStart ? undefined : downMigrationStart + ) + : content; const downSql = downMigrationStart >= 0 - ? content.substr(downMigrationStart, upMigrationStart < downMigrationStart ? undefined : upMigrationStart) - : undefined + ? content.substr( + downMigrationStart, + upMigrationStart < downMigrationStart ? undefined : upMigrationStart + ) + : undefined; return { up: (pgm) => pgm.sql(upSql), down: downSql === undefined ? false : (pgm) => pgm.sql(downSql), - } -} + }; +}; export default async (sqlPath: string) => { - const content = await readFile(sqlPath, 'utf-8') - return getActions(content) -} + const content = await readFile(sqlPath, 'utf-8'); + return getActions(content); +}; diff --git a/src/types.ts b/src/types.ts index 6a1968b8..3a792c56 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,137 +1,181 @@ -import { ClientBase, ClientConfig, QueryArrayResult, QueryResult, QueryArrayConfig, QueryConfig } from 'pg' -import { Name } from './operations/generalTypes' +import { + ClientBase, + ClientConfig, + QueryArrayConfig, + QueryArrayResult, + QueryConfig, + QueryResult, +} from 'pg'; +import * as domains from './operations/domainsTypes'; +import * as extensions from './operations/extensionsTypes'; +import * as functions from './operations/functionsTypes'; +import { Name } from './operations/generalTypes'; +import * as indexes from './operations/indexesTypes'; +import * as operators from './operations/operatorsTypes'; +import * as other from './operations/othersTypes'; +import PgLiteral from './operations/PgLiteral'; +import * as policies from './operations/policiesTypes'; +import * as roles from './operations/rolesTypes'; +import * as schemas from './operations/schemasTypes'; +import * as sequences from './operations/sequencesTypes'; +import * as tables from './operations/tablesTypes'; +import * as triggers from './operations/triggersTypes'; +import * as types from './operations/typesTypes'; +import * as mViews from './operations/viewsMaterializedTypes'; +import * as views from './operations/viewsTypes'; -import * as domains from './operations/domainsTypes' -import * as extensions from './operations/extensionsTypes' -import * as functions from './operations/functionsTypes' -import * as indexes from './operations/indexesTypes' -import * as operators from './operations/operatorsTypes' -import * as other from './operations/othersTypes' -import * as policies from './operations/policiesTypes' -import * as roles from './operations/rolesTypes' -import * as schemas from './operations/schemasTypes' -import * as sequences from './operations/sequencesTypes' -import * as tables from './operations/tablesTypes' -import * as triggers from './operations/triggersTypes' -import * as types from './operations/typesTypes' -import * as views from './operations/viewsTypes' -import * as mViews from './operations/viewsMaterializedTypes' -import PgLiteral from './operations/PgLiteral' - -export { ClientConfig, ConnectionConfig } from 'pg' +export { ClientConfig, ConnectionConfig } from 'pg'; // see ClientBase in @types/pg export interface DB { /* eslint-disable @typescript-eslint/no-explicit-any */ - query(queryConfig: QueryArrayConfig, values?: any[]): Promise - query(queryConfig: QueryConfig): Promise - query(queryTextOrConfig: string | QueryConfig, values?: any[]): Promise + query( + queryConfig: QueryArrayConfig, + values?: any[] + ): Promise; + query(queryConfig: QueryConfig): Promise; + query( + queryTextOrConfig: string | QueryConfig, + values?: any[] + ): Promise; - select(queryConfig: QueryArrayConfig, values?: any[]): Promise - select(queryConfig: QueryConfig): Promise - select(queryTextOrConfig: string | QueryConfig, values?: any[]): Promise + select(queryConfig: QueryArrayConfig, values?: any[]): Promise; + select(queryConfig: QueryConfig): Promise; + select( + queryTextOrConfig: string | QueryConfig, + values?: any[] + ): Promise; /* eslint-enable @typescript-eslint/no-explicit-any */ } export interface MigrationBuilder { - createExtension: (...args: Parameters) => void - dropExtension: (...args: Parameters) => void - addExtension: (...args: Parameters) => void - createTable: (...args: Parameters) => void - dropTable: (...args: Parameters) => void - renameTable: (...args: Parameters) => void - alterTable: (...args: Parameters) => void - addColumns: (...args: Parameters) => void - dropColumns: (...args: Parameters) => void - renameColumn: (...args: Parameters) => void - alterColumn: (...args: Parameters) => void - addColumn: (...args: Parameters) => void - dropColumn: (...args: Parameters) => void - addConstraint: (...args: Parameters) => void - dropConstraint: (...args: Parameters) => void - renameConstraint: (...args: Parameters) => void - createConstraint: (...args: Parameters) => void - createType: (...args: Parameters) => void - dropType: (...args: Parameters) => void - addType: (...args: Parameters) => void - renameType: (...args: Parameters) => void - renameTypeAttribute: (...args: Parameters) => void - renameTypeValue: (...args: Parameters) => void - addTypeAttribute: (...args: Parameters) => void - dropTypeAttribute: (...args: Parameters) => void - setTypeAttribute: (...args: Parameters) => void - addTypeValue: (...args: Parameters) => void - createIndex: (...args: Parameters) => void - dropIndex: (...args: Parameters) => void - addIndex: (...args: Parameters) => void - createRole: (...args: Parameters) => void - dropRole: (...args: Parameters) => void - alterRole: (...args: Parameters) => void - renameRole: (...args: Parameters) => void - createFunction: (...args: Parameters) => void - dropFunction: (...args: Parameters) => void - renameFunction: (...args: Parameters) => void - createTrigger: (...args: Parameters) => void - dropTrigger: (...args: Parameters) => void - renameTrigger: (...args: Parameters) => void - createSchema: (...args: Parameters) => void - dropSchema: (...args: Parameters) => void - renameSchema: (...args: Parameters) => void - createDomain: (...args: Parameters) => void - dropDomain: (...args: Parameters) => void - alterDomain: (...args: Parameters) => void - renameDomain: (...args: Parameters) => void - createSequence: (...args: Parameters) => void - dropSequence: (...args: Parameters) => void - alterSequence: (...args: Parameters) => void - renameSequence: (...args: Parameters) => void - createOperator: (...args: Parameters) => void - dropOperator: (...args: Parameters) => void - createOperatorClass: (...args: Parameters) => void - dropOperatorClass: (...args: Parameters) => void - renameOperatorClass: (...args: Parameters) => void - createOperatorFamily: (...args: Parameters) => void - dropOperatorFamily: (...args: Parameters) => void - renameOperatorFamily: (...args: Parameters) => void - addToOperatorFamily: (...args: Parameters) => void - removeFromOperatorFamily: (...args: Parameters) => void - createPolicy: (...args: Parameters) => void - dropPolicy: (...args: Parameters) => void - alterPolicy: (...args: Parameters) => void - renamePolicy: (...args: Parameters) => void - createView: (...args: Parameters) => void - dropView: (...args: Parameters) => void - alterView: (...args: Parameters) => void - alterViewColumn: (...args: Parameters) => void - renameView: (...args: Parameters) => void - createMaterializedView: (...args: Parameters) => void - dropMaterializedView: (...args: Parameters) => void - alterMaterializedView: (...args: Parameters) => void - renameMaterializedView: (...args: Parameters) => void - renameMaterializedViewColumn: (...args: Parameters) => void - refreshMaterializedView: (...args: Parameters) => void - sql: (...args: Parameters) => void - func: (sql: string) => PgLiteral - noTransaction: () => void - db: DB + createExtension: (...args: Parameters) => void; + dropExtension: (...args: Parameters) => void; + addExtension: (...args: Parameters) => void; + createTable: (...args: Parameters) => void; + dropTable: (...args: Parameters) => void; + renameTable: (...args: Parameters) => void; + alterTable: (...args: Parameters) => void; + addColumns: (...args: Parameters) => void; + dropColumns: (...args: Parameters) => void; + renameColumn: (...args: Parameters) => void; + alterColumn: (...args: Parameters) => void; + addColumn: (...args: Parameters) => void; + dropColumn: (...args: Parameters) => void; + addConstraint: (...args: Parameters) => void; + dropConstraint: (...args: Parameters) => void; + renameConstraint: (...args: Parameters) => void; + createConstraint: (...args: Parameters) => void; + createType: (...args: Parameters) => void; + dropType: (...args: Parameters) => void; + addType: (...args: Parameters) => void; + renameType: (...args: Parameters) => void; + renameTypeAttribute: (...args: Parameters) => void; + renameTypeValue: (...args: Parameters) => void; + addTypeAttribute: (...args: Parameters) => void; + dropTypeAttribute: (...args: Parameters) => void; + setTypeAttribute: (...args: Parameters) => void; + addTypeValue: (...args: Parameters) => void; + createIndex: (...args: Parameters) => void; + dropIndex: (...args: Parameters) => void; + addIndex: (...args: Parameters) => void; + createRole: (...args: Parameters) => void; + dropRole: (...args: Parameters) => void; + alterRole: (...args: Parameters) => void; + renameRole: (...args: Parameters) => void; + createFunction: (...args: Parameters) => void; + dropFunction: (...args: Parameters) => void; + renameFunction: (...args: Parameters) => void; + createTrigger: (...args: Parameters) => void; + dropTrigger: (...args: Parameters) => void; + renameTrigger: (...args: Parameters) => void; + createSchema: (...args: Parameters) => void; + dropSchema: (...args: Parameters) => void; + renameSchema: (...args: Parameters) => void; + createDomain: (...args: Parameters) => void; + dropDomain: (...args: Parameters) => void; + alterDomain: (...args: Parameters) => void; + renameDomain: (...args: Parameters) => void; + createSequence: (...args: Parameters) => void; + dropSequence: (...args: Parameters) => void; + alterSequence: (...args: Parameters) => void; + renameSequence: (...args: Parameters) => void; + createOperator: (...args: Parameters) => void; + dropOperator: (...args: Parameters) => void; + createOperatorClass: ( + ...args: Parameters + ) => void; + dropOperatorClass: (...args: Parameters) => void; + renameOperatorClass: ( + ...args: Parameters + ) => void; + createOperatorFamily: ( + ...args: Parameters + ) => void; + dropOperatorFamily: ( + ...args: Parameters + ) => void; + renameOperatorFamily: ( + ...args: Parameters + ) => void; + addToOperatorFamily: ( + ...args: Parameters + ) => void; + removeFromOperatorFamily: ( + ...args: Parameters + ) => void; + createPolicy: (...args: Parameters) => void; + dropPolicy: (...args: Parameters) => void; + alterPolicy: (...args: Parameters) => void; + renamePolicy: (...args: Parameters) => void; + createView: (...args: Parameters) => void; + dropView: (...args: Parameters) => void; + alterView: (...args: Parameters) => void; + alterViewColumn: (...args: Parameters) => void; + renameView: (...args: Parameters) => void; + createMaterializedView: ( + ...args: Parameters + ) => void; + dropMaterializedView: ( + ...args: Parameters + ) => void; + alterMaterializedView: ( + ...args: Parameters + ) => void; + renameMaterializedView: ( + ...args: Parameters + ) => void; + renameMaterializedViewColumn: ( + ...args: Parameters + ) => void; + refreshMaterializedView: ( + ...args: Parameters + ) => void; + sql: (...args: Parameters) => void; + func: (sql: string) => PgLiteral; + noTransaction: () => void; + db: DB; } -export type MigrationAction = (pgm: MigrationBuilder, run?: () => void) => Promise | void -export type Literal = (v: Name) => string -export type LogFn = (msg: string) => void -export type Logger = { debug?: LogFn; info: LogFn; warn: LogFn; error: LogFn } +export type MigrationAction = ( + pgm: MigrationBuilder, + run?: () => void +) => Promise | void; +export type Literal = (v: Name) => string; +export type LogFn = (msg: string) => void; +export type Logger = { debug?: LogFn; info: LogFn; warn: LogFn; error: LogFn }; export interface MigrationBuilderActions { - up?: MigrationAction | false - down?: MigrationAction | false - shorthands?: tables.ColumnDefinitions + up?: MigrationAction | false; + down?: MigrationAction | false; + shorthands?: tables.ColumnDefinitions; } export interface MigrationOptions { - typeShorthands?: tables.ColumnDefinitions - schemalize: Literal - literal: Literal - logger: Logger + typeShorthands?: tables.ColumnDefinitions; + schemalize: Literal; + literal: Literal; + logger: Logger; } // Note these currently don't contain the parameterized types like @@ -196,99 +240,99 @@ export enum PgType { XML = 'xml', // XML data } -export type MigrationDirection = 'up' | 'down' +export type MigrationDirection = 'up' | 'down'; export interface RunnerOptionConfig { /** * The table storing which migrations have been run. */ - migrationsTable: string + migrationsTable: string; /** * The schema storing table which migrations have been run. * * (defaults to same value as `schema`) */ - migrationsSchema?: string + migrationsSchema?: string; /** * The schema on which migration will be run. * * @default 'public' */ - schema?: string | string[] + schema?: string | string[]; /** * The directory containing your migration files. */ - dir: string + dir: string; /** * Check order of migrations before running them. */ - checkOrder?: boolean + checkOrder?: boolean; /** * Direction of migration-run. */ - direction: MigrationDirection + direction: MigrationDirection; /** * Number of migration to run. */ - count?: number + count?: number; /** * Treats `count` as timestamp. */ - timestamp?: boolean + timestamp?: boolean; /** * Regex pattern for file names to ignore (ignores files starting with `.` by default). */ - ignorePattern?: string + ignorePattern?: string; /** * Run only migration with this name. */ - file?: string - dryRun?: boolean + file?: string; + dryRun?: boolean; /** * Creates the configured schema if it doesn't exist. */ - createSchema?: boolean + createSchema?: boolean; /** * Creates the configured migration schema if it doesn't exist. */ - createMigrationsSchema?: boolean + createMigrationsSchema?: boolean; /** * Combines all pending migrations into a single transaction so that if any migration fails, all will be rolled back. * * @default true */ - singleTransaction?: boolean + singleTransaction?: boolean; /** * Disables locking mechanism and checks. */ - noLock?: boolean + noLock?: boolean; /** * Mark migrations as run without actually performing them (use with caution!). */ - fake?: boolean + fake?: boolean; /** * Runs [`decamelize`](https://github.com/sindresorhus/decamelize) on table/column/etc. names. */ - decamelize?: boolean + decamelize?: boolean; /** * Redirect log messages to this function, rather than `console`. */ - log?: LogFn + log?: LogFn; /** * Redirect messages to this logger object, rather than `console`. */ - logger?: Logger + logger?: Logger; /** * Print all debug messages like DB queries run (if you switch it on, it will disable `logger.debug` method). */ - verbose?: boolean + verbose?: boolean; } export interface RunnerOptionUrl { /** * Connection string or client config which is passed to [new pg.Client](https://node-postgres.com/api/client#constructor) */ - databaseUrl: string | ClientConfig + databaseUrl: string | ClientConfig; } export interface RunnerOptionClient { @@ -297,7 +341,8 @@ export interface RunnerOptionClient { * * Instance should be connected to DB and after finishing migration, user is responsible to close connection. */ - dbClient: ClientBase + dbClient: ClientBase; } -export type RunnerOption = RunnerOptionConfig & (RunnerOptionClient | RunnerOptionUrl) +export type RunnerOption = RunnerOptionConfig & + (RunnerOptionClient | RunnerOptionUrl); diff --git a/src/utils.ts b/src/utils.ts index 4098fdf5..30e6d960 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,108 +1,119 @@ -import decamelize from 'decamelize' -import { ColumnDefinitions, ColumnDefinition } from './operations/tablesTypes' -import { Name, Type, Value } from './operations/generalTypes' -import { MigrationOptions, Literal, RunnerOption } from './types' -import { FunctionParam, FunctionParamType } from './operations/functionsTypes' -import { PgLiteral } from '.' - -const identity = (v: T) => v -const quote = (str: string) => `"${str}"` - -export const createSchemalize = (shouldDecamelize: boolean, shouldQuote: boolean) => { - const transform = [shouldDecamelize ? decamelize : identity, shouldQuote ? quote : identity].reduce((acc, fn) => - fn === identity ? acc : (x: string) => acc(fn(x)), - ) +import decamelize from 'decamelize'; +import { PgLiteral } from '.'; +import { FunctionParam, FunctionParamType } from './operations/functionsTypes'; +import { Name, Type, Value } from './operations/generalTypes'; +import { ColumnDefinition, ColumnDefinitions } from './operations/tablesTypes'; +import { Literal, MigrationOptions, RunnerOption } from './types'; + +const identity = (v: T) => v; +const quote = (str: string) => `"${str}"`; + +export const createSchemalize = ( + shouldDecamelize: boolean, + shouldQuote: boolean +) => { + const transform = [ + shouldDecamelize ? decamelize : identity, + shouldQuote ? quote : identity, + ].reduce((acc, fn) => (fn === identity ? acc : (x: string) => acc(fn(x)))); return (v: Name) => { if (typeof v === 'object') { - const { schema, name } = v - return (schema ? `${transform(schema)}.` : '') + transform(name) + const { schema, name } = v; + return (schema ? `${transform(schema)}.` : '') + transform(name); } - return transform(v) - } -} + return transform(v); + }; +}; // credits to https://stackoverflow.com/a/12504061/4790644 export class StringIdGenerator { - private ids: number[] = [0] + private ids: number[] = [0]; // eslint-disable-next-line no-useless-constructor constructor(private readonly chars = 'abcdefghijklmnopqrstuvwxyz') {} next() { - const idsChars = this.ids.map((id) => this.chars[id]) - this.increment() - return idsChars.join('') + const idsChars = this.ids.map((id) => this.chars[id]); + this.increment(); + return idsChars.join(''); } private increment() { for (let i = this.ids.length - 1; i >= 0; i -= 1) { - this.ids[i] += 1 + this.ids[i] += 1; if (this.ids[i] < this.chars.length) { - return + return; } - this.ids[i] = 0 + this.ids[i] = 0; } - this.ids.unshift(0) + this.ids.unshift(0); } } const isPgLiteral = (val: unknown): val is PgLiteral => - typeof val === 'object' && val !== null && 'literal' in val && (val as { literal: unknown }).literal === true + typeof val === 'object' && + val !== null && + 'literal' in val && + (val as { literal: unknown }).literal === true; export const escapeValue = (val: Value): string | number => { if (val === null) { - return 'NULL' + return 'NULL'; } if (typeof val === 'boolean') { - return val.toString() + return val.toString(); } if (typeof val === 'string') { - let dollars: string - const ids = new StringIdGenerator() - let index: string + let dollars: string; + const ids = new StringIdGenerator(); + let index: string; do { - index = ids.next() - dollars = `$pg${index}$` - } while (val.indexOf(dollars) >= 0) - return `${dollars}${val}${dollars}` + index = ids.next(); + dollars = `$pg${index}$`; + } while (val.indexOf(dollars) >= 0); + return `${dollars}${val}${dollars}`; } if (typeof val === 'number') { - return val + return val; } if (Array.isArray(val)) { - const arrayStr = val.map(escapeValue).join(',').replace(/ARRAY/g, '') - return `ARRAY[${arrayStr}]` + const arrayStr = val.map(escapeValue).join(',').replace(/ARRAY/g, ''); + return `ARRAY[${arrayStr}]`; } if (isPgLiteral(val)) { - return val.value - } - return '' -} - -export const createTransformer = (literal: Literal) => (s: string, d?: { [key: string]: Name | Value }) => - Object.keys(d || {}).reduce((str: string, p) => { - const v = d?.[p] - return str.replace( - // eslint-disable-next-line security/detect-non-literal-regexp - new RegExp(`{${p}}`, 'g'), - // eslint-disable-next-line no-nested-ternary - v === undefined - ? '' - : typeof v === 'string' || (typeof v === 'object' && v !== null && 'name' in v) - ? literal(v) - : String(escapeValue(v)), - ) - }, s) + return val.value; + } + return ''; +}; + +export const createTransformer = + (literal: Literal) => (s: string, d?: { [key: string]: Name | Value }) => + Object.keys(d || {}).reduce((str: string, p) => { + const v = d?.[p]; + return str.replace( + // eslint-disable-next-line security/detect-non-literal-regexp + new RegExp(`{${p}}`, 'g'), + // eslint-disable-next-line no-nested-ternary + v === undefined + ? '' + : typeof v === 'string' || + (typeof v === 'object' && v !== null && 'name' in v) + ? literal(v) + : String(escapeValue(v)) + ); + }, s); export const getSchemas = (schema?: string | string[]): string[] => { const schemas = (Array.isArray(schema) ? schema : [schema]).filter( - (s): s is string => typeof s === 'string' && s.length > 0, - ) - return schemas.length > 0 ? schemas : ['public'] -} + (s): s is string => typeof s === 'string' && s.length > 0 + ); + return schemas.length > 0 ? schemas : ['public']; +}; export const getMigrationTableSchema = (options: RunnerOption): string => - options.migrationsSchema !== undefined ? options.migrationsSchema : getSchemas(options.schema)[0] + options.migrationsSchema !== undefined + ? options.migrationsSchema + : getSchemas(options.schema)[0]; const typeAdapters = { int: 'integer', @@ -111,82 +122,96 @@ const typeAdapters = { double: 'double precision', datetime: 'timestamp', bool: 'boolean', -} as const +} as const; const defaultTypeShorthands: ColumnDefinitions = { id: { type: 'serial', primaryKey: true }, // convenience type for serial primary keys -} +}; // some convenience adapters -- see above export const applyTypeAdapters = (type: string): string => - type in typeAdapters ? typeAdapters[type as keyof typeof typeAdapters] : type + type in typeAdapters ? typeAdapters[type as keyof typeof typeAdapters] : type; -const toType = (type: string | ColumnDefinition): ColumnDefinition => (typeof type === 'string' ? { type } : type) +const toType = (type: string | ColumnDefinition): ColumnDefinition => + typeof type === 'string' ? { type } : type; // eslint-disable-next-line @typescript-eslint/no-unused-vars -const removeType = ({ type, ...rest }: Partial) => rest +const removeType = ({ type, ...rest }: Partial) => rest; export const applyType = ( type: Type, - extendingTypeShorthands: ColumnDefinitions = {}, + extendingTypeShorthands: ColumnDefinitions = {} ): ColumnDefinition & FunctionParamType => { const typeShorthands: ColumnDefinitions = { ...defaultTypeShorthands, ...extendingTypeShorthands, - } - const options = toType(type) - let ext: ColumnDefinition | null = null - const types: string[] = [options.type] + }; + const options = toType(type); + let ext: ColumnDefinition | null = null; + const types: string[] = [options.type]; while (typeShorthands[types[types.length - 1]]) { ext = { ...toType(typeShorthands[types[types.length - 1]]), ...(ext === null ? {} : removeType(ext)), - } + }; if (types.includes(ext.type)) { - throw new Error(`Shorthands contain cyclic dependency: ${types.join(', ')}, ${ext.type}`) + throw new Error( + `Shorthands contain cyclic dependency: ${types.join(', ')}, ${ext.type}` + ); } else { - types.push(ext.type) + types.push(ext.type); } } return { ...ext, ...options, type: applyTypeAdapters(ext?.type ?? options.type), - } -} + }; +}; const formatParam = (mOptions: MigrationOptions) => (param: FunctionParam) => { - const { mode, name, type, default: defaultValue } = applyType(param, mOptions.typeShorthands) - const options: string[] = [] + const { + mode, + name, + type, + default: defaultValue, + } = applyType(param, mOptions.typeShorthands); + const options: string[] = []; if (mode) { - options.push(mode) + options.push(mode); } if (name) { - options.push(mOptions.literal(name)) + options.push(mOptions.literal(name)); } if (type) { - options.push(type) + options.push(type); } if (defaultValue) { - options.push(`DEFAULT ${escapeValue(defaultValue)}`) + options.push(`DEFAULT ${escapeValue(defaultValue)}`); } - return options.join(' ') -} + return options.join(' '); +}; -export const formatParams = (params: FunctionParam[], mOptions: MigrationOptions) => - `(${params.map(formatParam(mOptions)).join(', ')})` +export const formatParams = ( + params: FunctionParam[], + mOptions: MigrationOptions +) => `(${params.map(formatParam(mOptions)).join(', ')})`; -export const makeComment = (object: string, name: string, text?: string | null) => { - const cmt = escapeValue(text || null) - return `COMMENT ON ${object} ${name} IS ${cmt};` -} +export const makeComment = ( + object: string, + name: string, + text?: string | null +) => { + const cmt = escapeValue(text || null); + return `COMMENT ON ${object} ${name} IS ${cmt};`; +}; export const formatLines = (lines: string[], replace = ' ', separator = ',') => lines .map((line) => line.replace(/(?:\r\n|\r|\n)+/g, ' ')) .join(`${separator}\n`) - .replace(/^/gm, replace) + .replace(/^/gm, replace); export function intersection(list1: T[], list2: T[]): T[] { - return list1.filter((element) => list2.includes(element)) + return list1.filter((element) => list2.includes(element)); } diff --git a/test/1414549381268_names.js b/test/1414549381268_names.js index ccd4e7e7..64b1e40f 100644 --- a/test/1414549381268_names.js +++ b/test/1414549381268_names.js @@ -2,11 +2,11 @@ exports.up = (pgm, run) => { pgm.createTable('names', { id: 'id', name: { type: 'varchar(10)' }, - }) - run() -} + }); + run(); +}; exports.down = (pgm, run) => { - pgm.dropTable('names') - run() -} + pgm.dropTable('names'); + run(); +}; diff --git a/test/1414549381268_names_promise.js b/test/1414549381268_names_promise.js index 4ae19375..985d1c18 100644 --- a/test/1414549381268_names_promise.js +++ b/test/1414549381268_names_promise.js @@ -2,8 +2,8 @@ exports.up = (pgm) => { pgm.createTable('names', { id: 'id', name: { type: 'varchar(10)' }, - }) + }); return new Promise((resolve) => { - setTimeout(resolve, 10) - }) -} + setTimeout(resolve, 10); + }); +}; diff --git a/test/cockroach/004_table.js b/test/cockroach/004_table.js index ea8d9639..bca0b86c 100644 --- a/test/cockroach/004_table.js +++ b/test/cockroach/004_table.js @@ -7,7 +7,7 @@ exports.up = (pgm) => { notNull: true, default: pgm.func('current_timestamp'), }, - }) + }); pgm.createTable( 't2', { @@ -16,6 +16,6 @@ exports.up = (pgm) => { }, { ifNotExists: true, - }, - ) -} + } + ); +}; diff --git a/test/cockroach/006_table_rename.js b/test/cockroach/006_table_rename.js index b8ebc145..99958a4d 100644 --- a/test/cockroach/006_table_rename.js +++ b/test/cockroach/006_table_rename.js @@ -1,3 +1,3 @@ exports.up = (pgm) => { - pgm.renameTable('t2', 't2r') -} + pgm.renameTable('t2', 't2r'); +}; diff --git a/test/cockroach/008_column_drop.js b/test/cockroach/008_column_drop.js index 38d5ed12..e563ad34 100644 --- a/test/cockroach/008_column_drop.js +++ b/test/cockroach/008_column_drop.js @@ -1,9 +1,9 @@ exports.up = (pgm) => { - pgm.dropColumns('t1', 'string') -} + pgm.dropColumns('t1', 'string'); +}; exports.down = (pgm) => { pgm.addColumns('t1', { string: { type: 'text', notNull: false }, - }) -} + }); +}; diff --git a/test/cockroach/009_column.js b/test/cockroach/009_column.js index fdb49693..0a86b8dd 100644 --- a/test/cockroach/009_column.js +++ b/test/cockroach/009_column.js @@ -1,5 +1,5 @@ exports.up = (pgm) => { pgm.addColumns('t1', { nr: { type: 'integer', unique: true }, - }) -} + }); +}; diff --git a/test/cockroach/011_column_rename.js b/test/cockroach/011_column_rename.js index 7fc0f4ae..162b2ae0 100644 --- a/test/cockroach/011_column_rename.js +++ b/test/cockroach/011_column_rename.js @@ -1,3 +1,3 @@ exports.up = (pgm) => { - pgm.renameColumn('t1', 'nr', 'nmbr') -} + pgm.renameColumn('t1', 'nr', 'nmbr'); +}; diff --git a/test/cockroach/012_column_alter.js b/test/cockroach/012_column_alter.js index 5e7d9283..b708144d 100644 --- a/test/cockroach/012_column_alter.js +++ b/test/cockroach/012_column_alter.js @@ -1,11 +1,11 @@ exports.up = (pgm) => { pgm.alterColumn('t1', 'nmbr', { default: 10, - }) -} + }); +}; exports.down = (pgm) => { pgm.alterColumn('t1', 'nmbr', { default: null, - }) -} + }); +}; diff --git a/test/cockroach/014_add_constraint.js b/test/cockroach/014_add_constraint.js index 444f8a7b..98853266 100644 --- a/test/cockroach/014_add_constraint.js +++ b/test/cockroach/014_add_constraint.js @@ -1,11 +1,11 @@ -exports.constraint = 'chck_id' +exports.constraint = 'chck_id'; exports.up = (pgm) => { pgm.addConstraint('t1', exports.constraint, { check: 'id < 30', - }) -} + }); +}; exports.down = () => { // do nothing -} +}; diff --git a/test/cockroach/017_drop_constraint.js b/test/cockroach/017_drop_constraint.js index c91573af..8c78f4e7 100644 --- a/test/cockroach/017_drop_constraint.js +++ b/test/cockroach/017_drop_constraint.js @@ -1,9 +1,9 @@ -const constraint = require('./014_add_constraint') +const constraint = require('./014_add_constraint'); exports.up = (pgm) => { - pgm.dropConstraint('t1', constraint.constraint) -} + pgm.dropConstraint('t1', constraint.constraint); +}; exports.down = () => { // do nothing -} +}; diff --git a/test/cockroach/019_add_index.js b/test/cockroach/019_add_index.js index 58bfa2c8..74811237 100644 --- a/test/cockroach/019_add_index.js +++ b/test/cockroach/019_add_index.js @@ -1,3 +1,3 @@ exports.up = (pgm) => { - pgm.createIndex('t1', ['nmbr'], { unique: true, cascade: true }) -} + pgm.createIndex('t1', ['nmbr'], { unique: true, cascade: true }); +}; diff --git a/test/cockroach/020_create_index.js b/test/cockroach/020_create_index.js index 0a335c2d..b247caab 100644 --- a/test/cockroach/020_create_index.js +++ b/test/cockroach/020_create_index.js @@ -1,3 +1,3 @@ exports.up = (pgm) => { - pgm.createIndex('t1', ['nmbr'], { name: 'idx' }) -} + pgm.createIndex('t1', ['nmbr'], { name: 'idx' }); +}; diff --git a/test/cockroach/062_view.js b/test/cockroach/062_view.js index 55c40a5f..9d8aebae 100644 --- a/test/cockroach/062_view.js +++ b/test/cockroach/062_view.js @@ -1,5 +1,5 @@ exports.up = (pgm) => { - pgm.noTransaction() + pgm.noTransaction(); pgm.createTable('tv', { id: 'id', string: { type: 'text', notNull: true }, @@ -8,12 +8,12 @@ exports.up = (pgm) => { notNull: true, default: pgm.func('current_timestamp'), }, - }) + }); pgm.createView( 'v', { columns: ['id', 'str'], }, - 'SELECT id, string FROM tv', - ) -} + 'SELECT id, string FROM tv' + ); +}; diff --git a/test/cockroach/062_view_test.js b/test/cockroach/062_view_test.js index f0b8ff2b..709f338c 100644 --- a/test/cockroach/062_view_test.js +++ b/test/cockroach/062_view_test.js @@ -1,5 +1,5 @@ exports.up = (pgm) => { - pgm.sql('SELECT id, str FROM v') -} + pgm.sql('SELECT id, str FROM v'); +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/db-test.ts b/test/db-test.ts index 2c30a985..0b021f84 100644 --- a/test/db-test.ts +++ b/test/db-test.ts @@ -1,6 +1,6 @@ -import sinon, { SinonSandbox, SinonStub } from 'sinon' -import { expect } from 'chai' -import proxyquire from 'proxyquire' +import { expect } from 'chai'; +import proxyquire from 'proxyquire'; +import sinon, { SinonSandbox, SinonStub } from 'sinon'; class Client { /* eslint-disable */ @@ -18,120 +18,122 @@ class Client { const pgMock = { Client, -} +}; -const { default: Db } = proxyquire('../src/db', { pg: pgMock }) +const { default: Db } = proxyquire('../src/db', { pg: pgMock }); describe('lib/db', () => { - let sandbox: SinonSandbox - const log: typeof console.log = () => null - const client = new Client() + let sandbox: SinonSandbox; + const log: typeof console.log = () => null; + const client = new Client(); beforeEach(() => { - sandbox = sinon.createSandbox() - }) + sandbox = sinon.createSandbox(); + }); afterEach(() => { - sandbox.restore() - }) + sandbox.restore(); + }); describe('.constructor( connection )', () => { - let db: typeof Db + let db: typeof Db; afterEach(() => { if (db) { - db.close() + db.close(); } - }) + }); it('pg.Client should be called with connection string', () => { - const mocked = sandbox.stub(pgMock, 'Client').returns(client) - db = Db('connection_string') - expect(mocked).to.be.calledWith('connection_string') - }) + const mocked = sandbox.stub(pgMock, 'Client').returns(client); + db = Db('connection_string'); + expect(mocked).to.be.calledWith('connection_string'); + }); it('should use external client', () => { - const mockClient = new pgMock.Client() - const mocked = sandbox.stub(mockClient, 'query').returns(Promise.resolve()) + const mockClient = new pgMock.Client(); + const mocked = sandbox + .stub(mockClient, 'query') + .returns(Promise.resolve()); - db = Db(mockClient, log) + db = Db(mockClient, log); return db.query('query').then(() => { - expect(mocked.getCall(0).args[0]).to.equal('query') - }) - }) - }) + expect(mocked.getCall(0).args[0]).to.equal('query'); + }); + }); + }); describe('.query( query )', () => { - let db: typeof Db - let connectMock: SinonStub - let queryMock: SinonStub + let db: typeof Db; + let connectMock: SinonStub; + let queryMock: SinonStub; beforeEach(() => { - sandbox.stub(pgMock, 'Client').returns(client) - connectMock = sandbox.stub(client, 'connect').returns(Promise.resolve()) - queryMock = sandbox.stub(client, 'query').returns(Promise.resolve()) - db = Db(undefined, log) - }) + sandbox.stub(pgMock, 'Client').returns(client); + connectMock = sandbox.stub(client, 'connect').returns(Promise.resolve()); + queryMock = sandbox.stub(client, 'query').returns(Promise.resolve()); + db = Db(undefined, log); + }); afterEach(() => { - db.close() - }) + db.close(); + }); it('should call client.connect if this is the first query', () => { - connectMock.callsFake((fn) => fn()) - queryMock.returns(Promise.resolve()) + connectMock.callsFake((fn) => fn()); + queryMock.returns(Promise.resolve()); return db.query('query').then(() => { - expect(connectMock).to.be.calledOnce - }) - }) + expect(connectMock).to.be.calledOnce; + }); + }); it('should not call client.connect on subsequent queries', () => { - connectMock.callsFake((fn) => fn()) - queryMock.returns(Promise.resolve()) + connectMock.callsFake((fn) => fn()); + queryMock.returns(Promise.resolve()); return db .query('query_one') .then(() => db.query('query_two')) .then(() => { - expect(connectMock).to.be.calledOnce - }) - }) + expect(connectMock).to.be.calledOnce; + }); + }); it('should call client.query with query', () => { - connectMock.callsFake((fn) => fn()) - queryMock.returns(Promise.resolve()) + connectMock.callsFake((fn) => fn()); + queryMock.returns(Promise.resolve()); return db.query('query').then(() => { - expect(queryMock.getCall(0).args[0]).to.equal('query') - }) - }) + expect(queryMock.getCall(0).args[0]).to.equal('query'); + }); + }); it('should not call client.query if client.connect fails', () => { - const error = 'error' - connectMock.callsFake((fn) => fn(error)) + const error = 'error'; + connectMock.callsFake((fn) => fn(error)); return expect(db.query('query')) .to.eventually.be.rejectedWith(error) - .then(() => expect(queryMock).to.not.been.called) - }) + .then(() => expect(queryMock).to.not.been.called); + }); it('should resolve promise if query throws no error', () => { - connectMock.callsFake((fn) => fn()) - const result = 'result' - queryMock.returns(Promise.resolve(result)) - return expect(db.query('query')).to.eventually.equal(result) - }) + connectMock.callsFake((fn) => fn()); + const result = 'result'; + queryMock.returns(Promise.resolve(result)); + return expect(db.query('query')).to.eventually.equal(result); + }); it('should reject promise if query throws error', () => { - connectMock.callsFake((fn) => fn()) - const error = 'error' - queryMock.returns(Promise.reject(error)) - return expect(db.query('query')).to.eventually.be.rejectedWith(error) - }) - }) + connectMock.callsFake((fn) => fn()); + const error = 'error'; + queryMock.returns(Promise.reject(error)); + return expect(db.query('query')).to.eventually.be.rejectedWith(error); + }); + }); describe('.close()', () => { - let db: typeof Db + let db: typeof Db; beforeEach(() => { - sandbox.stub(pgMock, 'Client').returns(client) - sandbox.stub(client, 'end').returns(Promise.resolve()) - db = Db() - }) + sandbox.stub(pgMock, 'Client').returns(client); + sandbox.stub(client, 'end').returns(Promise.resolve()); + db = Db(); + }); afterEach(() => { - db.close() - }) + db.close(); + }); it('should call client.end', () => { - return db.close().then(() => expect(client.end).to.be.calledOnce) - }) - }) -}) + return db.close().then(() => expect(client.end).to.be.calledOnce); + }); + }); +}); diff --git a/test/indexes-test.ts b/test/indexes-test.ts index 17ccce5e..0ce6d808 100644 --- a/test/indexes-test.ts +++ b/test/indexes-test.ts @@ -1,18 +1,25 @@ -import { expect } from 'chai' -import * as Indexes from '../src/operations/indexes' -import { options1, options2 } from './utils' +import { expect } from 'chai'; +import * as Indexes from '../src/operations/indexes'; +import { options1, options2 } from './utils'; -type CreateIndexParams = Parameters> +type CreateIndexParams = Parameters>; describe('lib/operations/indexes', () => { describe('.create', () => { it('check schema not included in index name', () => { - const args: CreateIndexParams = [{ schema: 'mySchema', name: 'myTable' }, ['colA', 'colB']] - const sql1 = Indexes.createIndex(options1)(...args) - const sql2 = Indexes.createIndex(options2)(...args) - expect(sql1).to.equal('CREATE INDEX "myTable_colA_colB_index" ON "mySchema"."myTable" ("colA", "colB");') - expect(sql2).to.equal('CREATE INDEX "my_table_col_a_col_b_index" ON "my_schema"."my_table" ("col_a", "col_b");') - }) + const args: CreateIndexParams = [ + { schema: 'mySchema', name: 'myTable' }, + ['colA', 'colB'], + ]; + const sql1 = Indexes.createIndex(options1)(...args); + const sql2 = Indexes.createIndex(options2)(...args); + expect(sql1).to.equal( + 'CREATE INDEX "myTable_colA_colB_index" ON "mySchema"."myTable" ("colA", "colB");' + ); + expect(sql2).to.equal( + 'CREATE INDEX "my_table_col_a_col_b_index" ON "my_schema"."my_table" ("col_a", "col_b");' + ); + }); it('add opclass option (deprecated)', () => { const args: CreateIndexParams = [ @@ -24,36 +31,41 @@ describe('lib/operations/indexes', () => { opclass: 'someOpclass', where: 'some condition', }, - ] - const sql1 = Indexes.createIndex(options1)(...args) - const sql2 = Indexes.createIndex(options2)(...args) + ]; + const sql1 = Indexes.createIndex(options1)(...args); + const sql2 = Indexes.createIndex(options2)(...args); expect(sql1).to.equal( - 'CREATE INDEX "zIndex" ON "xTable" USING gist ("yName" "someOpclass") WHERE some condition;', - ) + 'CREATE INDEX "zIndex" ON "xTable" USING gist ("yName" "someOpclass") WHERE some condition;' + ); expect(sql2).to.equal( - 'CREATE INDEX "z_index" ON "x_table" USING gist ("y_name" "some_opclass") WHERE some condition;', - ) - }) + 'CREATE INDEX "z_index" ON "x_table" USING gist ("y_name" "some_opclass") WHERE some condition;' + ); + }); it('add opclass option', () => { const args: CreateIndexParams = [ 'xTable', - [{ name: 'yName', opclass: { schema: 'someSchema', name: 'someOpclass' } }], + [ + { + name: 'yName', + opclass: { schema: 'someSchema', name: 'someOpclass' }, + }, + ], { method: 'gist', name: 'zIndex', where: 'some condition', }, - ] - const sql1 = Indexes.createIndex(options1)(...args) - const sql2 = Indexes.createIndex(options2)(...args) + ]; + const sql1 = Indexes.createIndex(options1)(...args); + const sql2 = Indexes.createIndex(options2)(...args); expect(sql1).to.equal( - 'CREATE INDEX "zIndex" ON "xTable" USING gist ("yName" "someSchema"."someOpclass") WHERE some condition;', - ) + 'CREATE INDEX "zIndex" ON "xTable" USING gist ("yName" "someSchema"."someOpclass") WHERE some condition;' + ); expect(sql2).to.equal( - 'CREATE INDEX "z_index" ON "x_table" USING gist ("y_name" "some_schema"."some_opclass") WHERE some condition;', - ) - }) + 'CREATE INDEX "z_index" ON "x_table" USING gist ("y_name" "some_schema"."some_opclass") WHERE some condition;' + ); + }); it('add sort option', () => { const args: CreateIndexParams = [ @@ -64,19 +76,31 @@ describe('lib/operations/indexes', () => { name: 'zIndex', where: 'some condition', }, - ] - const sql1 = Indexes.createIndex(options1)(...args) - const sql2 = Indexes.createIndex(options2)(...args) - expect(sql1).to.equal('CREATE INDEX "zIndex" ON "xTable" USING gist ("yName" DESC) WHERE some condition;') - expect(sql2).to.equal('CREATE INDEX "z_index" ON "x_table" USING gist ("y_name" DESC) WHERE some condition;') - }) + ]; + const sql1 = Indexes.createIndex(options1)(...args); + const sql2 = Indexes.createIndex(options2)(...args); + expect(sql1).to.equal( + 'CREATE INDEX "zIndex" ON "xTable" USING gist ("yName" DESC) WHERE some condition;' + ); + expect(sql2).to.equal( + 'CREATE INDEX "z_index" ON "x_table" USING gist ("y_name" DESC) WHERE some condition;' + ); + }); it('add include option', () => { - const args: CreateIndexParams = ['xTable', ['yName'], { name: 'zIndex', include: 'someOtherColumn' }] - const sql1 = Indexes.createIndex(options1)(...args) - const sql2 = Indexes.createIndex(options2)(...args) - expect(sql1).to.equal('CREATE INDEX "zIndex" ON "xTable" ("yName") INCLUDE ("someOtherColumn");') - expect(sql2).to.equal('CREATE INDEX "z_index" ON "x_table" ("y_name") INCLUDE ("some_other_column");') - }) - }) -}) + const args: CreateIndexParams = [ + 'xTable', + ['yName'], + { name: 'zIndex', include: 'someOtherColumn' }, + ]; + const sql1 = Indexes.createIndex(options1)(...args); + const sql2 = Indexes.createIndex(options2)(...args); + expect(sql1).to.equal( + 'CREATE INDEX "zIndex" ON "xTable" ("yName") INCLUDE ("someOtherColumn");' + ); + expect(sql2).to.equal( + 'CREATE INDEX "z_index" ON "x_table" ("y_name") INCLUDE ("some_other_column");' + ); + }); + }); +}); diff --git a/test/migration-test.ts b/test/migration-test.ts index 9f7701f7..510662a2 100644 --- a/test/migration-test.ts +++ b/test/migration-test.ts @@ -1,114 +1,182 @@ /* eslint-disable no-unused-expressions */ -import sinon, { SinonSpy } from 'sinon' -import { expect } from 'chai' -import { RunnerOption, Logger } from '../src/types' -import { Migration, getTimestamp } from '../src/migration' -import { DBConnection } from '../src/db' +import { expect } from 'chai'; +import sinon, { SinonSpy } from 'sinon'; +import { DBConnection } from '../src/db'; +import { getTimestamp, Migration } from '../src/migration'; +import { Logger, RunnerOption } from '../src/types'; -const callbackMigration = '1414549381268_names.js' -const promiseMigration = '1414549381268_names_promise.js' -const migrationsTable = 'pgmigrations' +const callbackMigration = '1414549381268_names.js'; +const promiseMigration = '1414549381268_names_promise.js'; +const migrationsTable = 'pgmigrations'; -const actionsCallback = require(`./${callbackMigration}`) // eslint-disable-line import/no-dynamic-require,security/detect-non-literal-require,@typescript-eslint/no-var-requires -const actionsPromise = require(`./${promiseMigration}`) // eslint-disable-line import/no-dynamic-require,security/detect-non-literal-require,@typescript-eslint/no-var-requires +const actionsCallback = require(`./${callbackMigration}`); // eslint-disable-line import/no-dynamic-require,security/detect-non-literal-require,@typescript-eslint/no-var-requires +const actionsPromise = require(`./${promiseMigration}`); // eslint-disable-line import/no-dynamic-require,security/detect-non-literal-require,@typescript-eslint/no-var-requires describe('lib/migration', () => { - const dbMock = {} as DBConnection - const logger: Logger = { info: () => null, warn: () => null, error: () => null } - const options = { migrationsTable } as RunnerOption - let migration - let queryMock: SinonSpy + const dbMock = {} as DBConnection; + const logger: Logger = { + info: () => null, + warn: () => null, + error: () => null, + }; + const options = { migrationsTable } as RunnerOption; + let migration; + let queryMock: SinonSpy; beforeEach(() => { - queryMock = sinon.spy() - dbMock.query = queryMock - }) + queryMock = sinon.spy(); + dbMock.query = queryMock; + }); describe('getTimestamp', () => { it('Should get timestamp for normal timestamp', () => { - const now = Date.now() - expect(getTimestamp(logger, String(now))).to.eql(now) - }) + const now = Date.now(); + expect(getTimestamp(logger, String(now))).to.eql(now); + }); it('Should get timestamp for shortened iso format', () => { - const now = new Date() - expect(getTimestamp(logger, now.toISOString().replace(/[^\d]/g, ''))).to.eql(now.valueOf()) - }) - }) + const now = new Date(); + expect( + getTimestamp(logger, now.toISOString().replace(/[^\d]/g, '')) + ).to.eql(now.valueOf()); + }); + }); describe('self.applyUp', () => { it('normal operations: db.query should be called', () => { - migration = new Migration(dbMock, callbackMigration, actionsCallback, options, {}, logger) + migration = new Migration( + dbMock, + callbackMigration, + actionsCallback, + options, + {}, + logger + ); return migration.apply('up').then(() => { - expect(queryMock).to.be.called - }) - }) + expect(queryMock).to.be.called; + }); + }); it('normal operations: db.query should be called when returning promise', () => { - migration = new Migration(dbMock, promiseMigration, actionsPromise, options, {}, logger) + migration = new Migration( + dbMock, + promiseMigration, + actionsPromise, + options, + {}, + logger + ); return migration.apply('up').then(() => { - expect(queryMock).to.be.called - }) - }) + expect(queryMock).to.be.called; + }); + }); it('--dry-run option: db.query should not be called', () => { - migration = new Migration(dbMock, callbackMigration, actionsCallback, { ...options, dryRun: true }, {}, logger) + migration = new Migration( + dbMock, + callbackMigration, + actionsCallback, + { ...options, dryRun: true }, + {}, + logger + ); return migration.apply('up').then(() => { - expect(queryMock).to.not.be.called - }) - }) + expect(queryMock).to.not.be.called; + }); + }); it('should make proper SQL calls', () => { - migration = new Migration(dbMock, promiseMigration, actionsCallback, options, {}, logger) + migration = new Migration( + dbMock, + promiseMigration, + actionsCallback, + options, + {}, + logger + ); return migration.apply('up').then(() => { - expect(queryMock).to.have.callCount(4) - expect(queryMock.getCall(0).args[0]).to.equal('BEGIN;') - expect(queryMock.getCall(1).args[0]).to.include('CREATE TABLE') - expect(queryMock.getCall(2).args[0]).to.include(`INSERT INTO "public"."${migrationsTable}"`) - expect(queryMock.getCall(3).args[0]).to.equal('COMMIT;') - }) - }) + expect(queryMock).to.have.callCount(4); + expect(queryMock.getCall(0).args[0]).to.equal('BEGIN;'); + expect(queryMock.getCall(1).args[0]).to.include('CREATE TABLE'); + expect(queryMock.getCall(2).args[0]).to.include( + `INSERT INTO "public"."${migrationsTable}"` + ); + expect(queryMock.getCall(3).args[0]).to.equal('COMMIT;'); + }); + }); it('should fail with an error message if the migration is invalid', () => { - const invalidMigrationName = 'invalid-migration' - migration = new Migration(dbMock, invalidMigrationName, {}, options, {}, logger) - const direction = 'up' - let error + const invalidMigrationName = 'invalid-migration'; + migration = new Migration( + dbMock, + invalidMigrationName, + {}, + options, + {}, + logger + ); + const direction = 'up'; + let error; try { - migration.apply(direction) + migration.apply(direction); } catch (err) { - error = err + error = err; } // expecting outside the catch block ensures that the test will fail if the // an exception is not caught - expect(error.toString()).to.include(`${invalidMigrationName} exporting a '${direction}' function`) - }) - }) + expect(error.toString()).to.include( + `${invalidMigrationName} exporting a '${direction}' function` + ); + }); + }); describe('self.applyDown', () => { it('normal operations: db.query should be called', () => { - migration = new Migration(dbMock, callbackMigration, actionsCallback, options, {}, logger) + migration = new Migration( + dbMock, + callbackMigration, + actionsCallback, + options, + {}, + logger + ); return migration.apply('down').then(() => { - expect(queryMock).to.be.called - }) - }) + expect(queryMock).to.be.called; + }); + }); it('--dry-run option: db.query should not be called', () => { - migration = new Migration(dbMock, callbackMigration, actionsCallback, { ...options, dryRun: true }, {}, logger) + migration = new Migration( + dbMock, + callbackMigration, + actionsCallback, + { ...options, dryRun: true }, + {}, + logger + ); return migration.apply('down').then(() => { - expect(queryMock).to.not.be.called - }) - }) + expect(queryMock).to.not.be.called; + }); + }); it('should make proper SQL calls', () => { - migration = new Migration(dbMock, promiseMigration, actionsCallback, options, {}, logger) + migration = new Migration( + dbMock, + promiseMigration, + actionsCallback, + options, + {}, + logger + ); return migration.apply('down').then(() => { - expect(queryMock).to.have.callCount(4) - expect(queryMock.getCall(0).args[0]).to.equal('BEGIN;') - expect(queryMock.getCall(1).args[0]).to.include('DROP TABLE') - expect(queryMock.getCall(2).args[0]).to.include(`DELETE FROM "public"."${migrationsTable}"`) - expect(queryMock.getCall(3).args[0]).to.equal('COMMIT;') - }) - }) - }) -}) + expect(queryMock).to.have.callCount(4); + expect(queryMock.getCall(0).args[0]).to.equal('BEGIN;'); + expect(queryMock.getCall(1).args[0]).to.include('DROP TABLE'); + expect(queryMock.getCall(2).args[0]).to.include( + `DELETE FROM "public"."${migrationsTable}"` + ); + expect(queryMock.getCall(3).args[0]).to.equal('COMMIT;'); + }); + }); + }); +}); diff --git a/test/migrations/001_noop.js b/test/migrations/001_noop.js index 574a3053..e2e22bbd 100644 --- a/test/migrations/001_noop.js +++ b/test/migrations/001_noop.js @@ -1,2 +1,2 @@ // eslint-disable-next-line @typescript-eslint/no-empty-function -exports.up = () => {} +exports.up = () => {}; diff --git a/test/migrations/002_callback.js b/test/migrations/002_callback.js index 92e9d244..d3410877 100644 --- a/test/migrations/002_callback.js +++ b/test/migrations/002_callback.js @@ -1,3 +1,3 @@ exports.up = (pgm, done) => { - setTimeout(done, 10) -} + setTimeout(done, 10); +}; diff --git a/test/migrations/003_promise.js b/test/migrations/003_promise.js index 19ecc745..fff21951 100644 --- a/test/migrations/003_promise.js +++ b/test/migrations/003_promise.js @@ -1,4 +1,4 @@ exports.up = () => new Promise((resolve) => { - setTimeout(resolve, 10) - }) + setTimeout(resolve, 10); + }); diff --git a/test/migrations/004_table.js b/test/migrations/004_table.js index 831bdbe1..e5ff45f9 100644 --- a/test/migrations/004_table.js +++ b/test/migrations/004_table.js @@ -1,4 +1,4 @@ -exports.comment = 'comment on table t2' +exports.comment = 'comment on table t2'; exports.up = (pgm) => { pgm.createTable('t1', { @@ -9,7 +9,7 @@ exports.up = (pgm) => { notNull: true, default: pgm.func('current_timestamp'), }, - }) + }); pgm.createTable( 't2', { @@ -19,6 +19,6 @@ exports.up = (pgm) => { { ifNotExists: true, comment: exports.comment, - }, - ) -} + } + ); +}; diff --git a/test/migrations/005_table_test.js b/test/migrations/005_table_test.js index 3289fe10..530338c2 100644 --- a/test/migrations/005_table_test.js +++ b/test/migrations/005_table_test.js @@ -1,46 +1,48 @@ -const table = require('./004_table') +const table = require('./004_table'); -const schema = process.env.SCHEMA || 'public' +const schema = process.env.SCHEMA || 'public'; exports.up = async (pgm) => { const [{ comment }] = await pgm.db.select( `SELECT obj_description(c.oid) as "comment" FROM pg_class c join pg_namespace n ON (c.relnamespace = n.oid) - WHERE c.relname = 't2' and c.relkind = 'r' and n.nspname = '${schema}'`, - ) + WHERE c.relname = 't2' and c.relkind = 'r' and n.nspname = '${schema}'` + ); if (comment !== table.comment) { - throw new Error('Comment not set') + throw new Error('Comment not set'); } - await pgm.db.query('SAVEPOINT sp_reference;') + await pgm.db.query('SAVEPOINT sp_reference;'); try { - await pgm.db.query('INSERT INTO t2(id2) VALUES (1);') - throw 1 // eslint-disable-line no-throw-literal + await pgm.db.query('INSERT INTO t2(id2) VALUES (1);'); + throw 1; // eslint-disable-line no-throw-literal } catch (err) { if (err === 1) { - throw new Error('Missing reference clause') + throw new Error('Missing reference clause'); } - await pgm.db.query('ROLLBACK TO SAVEPOINT sp_reference;') + await pgm.db.query('ROLLBACK TO SAVEPOINT sp_reference;'); } - await pgm.db.query('SAVEPOINT sp_not_null;') + await pgm.db.query('SAVEPOINT sp_not_null;'); try { - await pgm.db.query('INSERT INTO t1(created) VALUES (current_timestamp); ') - throw 1 // eslint-disable-line no-throw-literal + await pgm.db.query('INSERT INTO t1(created) VALUES (current_timestamp); '); + throw 1; // eslint-disable-line no-throw-literal } catch (err) { if (err === 1) { - throw new Error('Missing not null clause') + throw new Error('Missing not null clause'); } - await pgm.db.query('ROLLBACK TO SAVEPOINT sp_not_null;') + await pgm.db.query('ROLLBACK TO SAVEPOINT sp_not_null;'); } const { rows: [{ id }], - } = await pgm.db.query("INSERT INTO t1(string) VALUES ('something') RETURNING id;") - await pgm.db.query(`INSERT INTO t2(id2) VALUES (${id});`) -} + } = await pgm.db.query( + "INSERT INTO t1(string) VALUES ('something') RETURNING id;" + ); + await pgm.db.query(`INSERT INTO t2(id2) VALUES (${id});`); +}; exports.down = (pgm) => { - pgm.sql('DELETE from t2') - pgm.sql('DELETE from t1') -} + pgm.sql('DELETE from t2'); + pgm.sql('DELETE from t1'); +}; diff --git a/test/migrations/006_table_rename.js b/test/migrations/006_table_rename.js index b8ebc145..99958a4d 100644 --- a/test/migrations/006_table_rename.js +++ b/test/migrations/006_table_rename.js @@ -1,3 +1,3 @@ exports.up = (pgm) => { - pgm.renameTable('t2', 't2r') -} + pgm.renameTable('t2', 't2r'); +}; diff --git a/test/migrations/007_table_rename_test.js b/test/migrations/007_table_rename_test.js index 4d369c05..ec517560 100644 --- a/test/migrations/007_table_rename_test.js +++ b/test/migrations/007_table_rename_test.js @@ -1,6 +1,8 @@ exports.up = (pgm) => pgm.db .query("INSERT INTO t1(string) VALUES ('something') RETURNING id;") - .then(({ rows: [{ id }] }) => pgm.db.query(`INSERT INTO t2r(id2) VALUES (${id});`)) + .then(({ rows: [{ id }] }) => + pgm.db.query(`INSERT INTO t2r(id2) VALUES (${id});`) + ); -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/008_column_drop.js b/test/migrations/008_column_drop.js index 38d5ed12..e563ad34 100644 --- a/test/migrations/008_column_drop.js +++ b/test/migrations/008_column_drop.js @@ -1,9 +1,9 @@ exports.up = (pgm) => { - pgm.dropColumns('t1', 'string') -} + pgm.dropColumns('t1', 'string'); +}; exports.down = (pgm) => { pgm.addColumns('t1', { string: { type: 'text', notNull: false }, - }) -} + }); +}; diff --git a/test/migrations/009_column.js b/test/migrations/009_column.js index 6862a939..3b67deff 100644 --- a/test/migrations/009_column.js +++ b/test/migrations/009_column.js @@ -1,5 +1,5 @@ exports.up = (pgm) => { pgm.addColumns('t1', { nr: { type: 'integer', unique: true, check: 'nr > 10' }, - }) -} + }); +}; diff --git a/test/migrations/010_column_test.js b/test/migrations/010_column_test.js index 65000d8b..088f3b2e 100644 --- a/test/migrations/010_column_test.js +++ b/test/migrations/010_column_test.js @@ -1,27 +1,27 @@ exports.up = async (pgm) => { - await pgm.db.query('SAVEPOINT sp_check;') + await pgm.db.query('SAVEPOINT sp_check;'); try { - await pgm.db.query('INSERT INTO t1(nr) VALUES (1);') - throw 1 // eslint-disable-line no-throw-literal + await pgm.db.query('INSERT INTO t1(nr) VALUES (1);'); + throw 1; // eslint-disable-line no-throw-literal } catch (err) { if (err === 1) { - throw new Error('Missing check clause') + throw new Error('Missing check clause'); } - await pgm.db.query('ROLLBACK TO SAVEPOINT sp_check;') + await pgm.db.query('ROLLBACK TO SAVEPOINT sp_check;'); } - await pgm.db.query('INSERT INTO t1(nr) VALUES (20);') + await pgm.db.query('INSERT INTO t1(nr) VALUES (20);'); - await pgm.db.query('SAVEPOINT sp_unique;') + await pgm.db.query('SAVEPOINT sp_unique;'); try { - await pgm.db.query('INSERT INTO t1(nr) VALUES (20);') - throw 1 // eslint-disable-line no-throw-literal + await pgm.db.query('INSERT INTO t1(nr) VALUES (20);'); + throw 1; // eslint-disable-line no-throw-literal } catch (err) { if (err === 1) { - throw new Error('Missing not unique clause') + throw new Error('Missing not unique clause'); } - await pgm.db.query('ROLLBACK TO SAVEPOINT sp_unique;') + await pgm.db.query('ROLLBACK TO SAVEPOINT sp_unique;'); } -} +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/011_column_rename.js b/test/migrations/011_column_rename.js index 7fc0f4ae..162b2ae0 100644 --- a/test/migrations/011_column_rename.js +++ b/test/migrations/011_column_rename.js @@ -1,3 +1,3 @@ exports.up = (pgm) => { - pgm.renameColumn('t1', 'nr', 'nmbr') -} + pgm.renameColumn('t1', 'nr', 'nmbr'); +}; diff --git a/test/migrations/012_column_alter.js b/test/migrations/012_column_alter.js index f4bec23b..86b70fe8 100644 --- a/test/migrations/012_column_alter.js +++ b/test/migrations/012_column_alter.js @@ -1,11 +1,11 @@ exports.up = (pgm) => { pgm.alterColumn('t1', 'nmbr', { type: 'smallint', - }) -} + }); +}; exports.down = (pgm) => { pgm.alterColumn('t1', 'nmbr', { type: 'integer', - }) -} + }); +}; diff --git a/test/migrations/013_column_alter_test.js b/test/migrations/013_column_alter_test.js index 362c5d54..28c51903 100644 --- a/test/migrations/013_column_alter_test.js +++ b/test/migrations/013_column_alter_test.js @@ -1,14 +1,14 @@ exports.up = async (pgm) => { - await pgm.db.query('SAVEPOINT sp_smallint;') + await pgm.db.query('SAVEPOINT sp_smallint;'); try { - await pgm.db.query('INSERT INTO t1(nmbr) VALUES (2147483647);') - throw 1 // eslint-disable-line no-throw-literal + await pgm.db.query('INSERT INTO t1(nmbr) VALUES (2147483647);'); + throw 1; // eslint-disable-line no-throw-literal } catch (err) { if (err === 1) { - throw new Error('Type not updated') + throw new Error('Type not updated'); } - await pgm.db.query('ROLLBACK TO SAVEPOINT sp_smallint;') + await pgm.db.query('ROLLBACK TO SAVEPOINT sp_smallint;'); } -} +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/014_add_constraint.js b/test/migrations/014_add_constraint.js index 01d7562e..ce2d3a0d 100644 --- a/test/migrations/014_add_constraint.js +++ b/test/migrations/014_add_constraint.js @@ -1,7 +1,7 @@ -exports.constraint = 'chck_nmbr' +exports.constraint = 'chck_nmbr'; exports.up = (pgm) => { pgm.addConstraint('t1', exports.constraint, { check: 'nmbr < 30', - }) -} + }); +}; diff --git a/test/migrations/015_add_constraint_test.js b/test/migrations/015_add_constraint_test.js index 39ff3d16..c475bde2 100644 --- a/test/migrations/015_add_constraint_test.js +++ b/test/migrations/015_add_constraint_test.js @@ -1,16 +1,16 @@ exports.up = async (pgm) => { - await pgm.db.query('SAVEPOINT sp_check;') + await pgm.db.query('SAVEPOINT sp_check;'); try { - await pgm.db.query('INSERT INTO t1(nmbr) VALUES (30);') - throw 1 // eslint-disable-line no-throw-literal + await pgm.db.query('INSERT INTO t1(nmbr) VALUES (30);'); + throw 1; // eslint-disable-line no-throw-literal } catch (err) { if (err === 1) { - throw new Error('Missing check clause') + throw new Error('Missing check clause'); } - await pgm.db.query('ROLLBACK TO SAVEPOINT sp_check;') + await pgm.db.query('ROLLBACK TO SAVEPOINT sp_check;'); } - await pgm.db.query('INSERT INTO t1(nmbr) VALUES (21);') -} + await pgm.db.query('INSERT INTO t1(nmbr) VALUES (21);'); +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/016_rename_constraint.js b/test/migrations/016_rename_constraint.js index 8a04c18c..a02585b1 100644 --- a/test/migrations/016_rename_constraint.js +++ b/test/migrations/016_rename_constraint.js @@ -1,7 +1,7 @@ -const constraint = require('./014_add_constraint') +const constraint = require('./014_add_constraint'); -exports.constraint = 'chck_nmbr_new' +exports.constraint = 'chck_nmbr_new'; exports.up = (pgm) => { - pgm.renameConstraint('t1', constraint.constraint, exports.constraint) -} + pgm.renameConstraint('t1', constraint.constraint, exports.constraint); +}; diff --git a/test/migrations/017_drop_constraint.js b/test/migrations/017_drop_constraint.js index 4a8bee6a..33cea907 100644 --- a/test/migrations/017_drop_constraint.js +++ b/test/migrations/017_drop_constraint.js @@ -1,11 +1,11 @@ -const constraint = require('./016_rename_constraint') +const constraint = require('./016_rename_constraint'); exports.up = (pgm) => { - pgm.dropConstraint('t1', constraint.constraint) -} + pgm.dropConstraint('t1', constraint.constraint); +}; exports.down = (pgm) => { pgm.addConstraint('t1', constraint.constraint, { check: 'true', - }) -} + }); +}; diff --git a/test/migrations/018_drop_constraint_test.js b/test/migrations/018_drop_constraint_test.js index d883932e..85887135 100644 --- a/test/migrations/018_drop_constraint_test.js +++ b/test/migrations/018_drop_constraint_test.js @@ -1,3 +1,3 @@ -exports.up = (pgm) => pgm.db.query('INSERT INTO t1(nmbr) VALUES (30);') +exports.up = (pgm) => pgm.db.query('INSERT INTO t1(nmbr) VALUES (30);'); -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/019_add_index.js b/test/migrations/019_add_index.js index 84da37d9..703d8306 100644 --- a/test/migrations/019_add_index.js +++ b/test/migrations/019_add_index.js @@ -1,3 +1,3 @@ exports.up = (pgm) => { - pgm.createIndex('t1', ['nmbr'], { unique: true }) -} + pgm.createIndex('t1', ['nmbr'], { unique: true }); +}; diff --git a/test/migrations/020_drop_index.js b/test/migrations/020_drop_index.js index 519c953d..8d49f9c7 100644 --- a/test/migrations/020_drop_index.js +++ b/test/migrations/020_drop_index.js @@ -1,6 +1,6 @@ exports.up = (pgm) => { - pgm.createIndex('t1', ['nmbr'], { name: 'idx' }) - pgm.dropIndex('t1', [], { name: 'idx' }) -} + pgm.createIndex('t1', ['nmbr'], { name: 'idx' }); + pgm.dropIndex('t1', [], { name: 'idx' }); +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/021_add_type.js b/test/migrations/021_add_type.js index 9de763c0..b8b06260 100644 --- a/test/migrations/021_add_type.js +++ b/test/migrations/021_add_type.js @@ -1,6 +1,6 @@ exports.up = (pgm) => { - pgm.createType('list', ['a', 'b', 'c']) + pgm.createType('list', ['a', 'b', 'c']); pgm.createType('obj', { id: 'integer', - }) -} + }); +}; diff --git a/test/migrations/022_add_type_test.js b/test/migrations/022_add_type_test.js index 6d8f8c6a..bebf2151 100644 --- a/test/migrations/022_add_type_test.js +++ b/test/migrations/022_add_type_test.js @@ -1,7 +1,7 @@ exports.up = (pgm) => { - pgm.sql('CREATE TEMPORARY TABLE t_list_1 (l list);') - pgm.sql("INSERT INTO t_list_1 (l) VALUES ('a');") - pgm.sql('select (ROW(1)::obj).id;') -} + pgm.sql('CREATE TEMPORARY TABLE t_list_1 (l list);'); + pgm.sql("INSERT INTO t_list_1 (l) VALUES ('a');"); + pgm.sql('select (ROW(1)::obj).id;'); +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/023_add_type_attribute.js b/test/migrations/023_add_type_attribute.js index 4ca80dde..0d6e30fc 100644 --- a/test/migrations/023_add_type_attribute.js +++ b/test/migrations/023_add_type_attribute.js @@ -1,3 +1,3 @@ exports.up = (pgm) => { - pgm.addTypeAttribute('obj', 'string', 'text') -} + pgm.addTypeAttribute('obj', 'string', 'text'); +}; diff --git a/test/migrations/024_add_type_attribute_test.js b/test/migrations/024_add_type_attribute_test.js index a3d99e84..95167bd8 100644 --- a/test/migrations/024_add_type_attribute_test.js +++ b/test/migrations/024_add_type_attribute_test.js @@ -1,5 +1,5 @@ exports.up = (pgm) => { - pgm.sql("select (ROW(1, 'x')::obj).string;") -} + pgm.sql("select (ROW(1, 'x')::obj).string;"); +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/025_set_type_attribute.js b/test/migrations/025_set_type_attribute.js index 633c82b5..9295fa5e 100644 --- a/test/migrations/025_set_type_attribute.js +++ b/test/migrations/025_set_type_attribute.js @@ -1,7 +1,7 @@ exports.up = (pgm) => { - pgm.setTypeAttribute('obj', 'id', 'smallint') -} + pgm.setTypeAttribute('obj', 'id', 'smallint'); +}; exports.down = (pgm) => { - pgm.setTypeAttribute('obj', 'id', 'integer') -} + pgm.setTypeAttribute('obj', 'id', 'integer'); +}; diff --git a/test/migrations/026_set_type_attribute_test.js b/test/migrations/026_set_type_attribute_test.js index bd72ce60..7af6462d 100644 --- a/test/migrations/026_set_type_attribute_test.js +++ b/test/migrations/026_set_type_attribute_test.js @@ -1,14 +1,14 @@ exports.up = async (pgm) => { - await pgm.db.query('SAVEPOINT sp_smallint;') + await pgm.db.query('SAVEPOINT sp_smallint;'); try { - await pgm.db.query("select (ROW(2147483647, 'x')::obj).id;") - throw 1 // eslint-disable-line no-throw-literal + await pgm.db.query("select (ROW(2147483647, 'x')::obj).id;"); + throw 1; // eslint-disable-line no-throw-literal } catch (err) { if (err === 1) { - throw new Error('Type not updated') + throw new Error('Type not updated'); } - await pgm.db.query('ROLLBACK TO SAVEPOINT sp_smallint;') + await pgm.db.query('ROLLBACK TO SAVEPOINT sp_smallint;'); } -} +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/027_add_type_value.js b/test/migrations/027_add_type_value.js index 7398f478..d60bca88 100644 --- a/test/migrations/027_add_type_value.js +++ b/test/migrations/027_add_type_value.js @@ -1,6 +1,6 @@ exports.up = (pgm) => { - pgm.noTransaction() - pgm.addTypeValue('list', 'd', { ifNotExists: true }) -} + pgm.noTransaction(); + pgm.addTypeValue('list', 'd', { ifNotExists: true }); +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/028_add_type_value_test.js b/test/migrations/028_add_type_value_test.js index 8f2e3613..7d7c0b9c 100644 --- a/test/migrations/028_add_type_value_test.js +++ b/test/migrations/028_add_type_value_test.js @@ -1,6 +1,6 @@ exports.up = (pgm) => { - pgm.sql('CREATE TEMPORARY TABLE t_list_2 (l list);') - pgm.sql("INSERT INTO t_list_2 (l) VALUES ('d');") -} + pgm.sql('CREATE TEMPORARY TABLE t_list_2 (l list);'); + pgm.sql("INSERT INTO t_list_2 (l) VALUES ('d');"); +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/029_rename_type_attribute.js b/test/migrations/029_rename_type_attribute.js index fd661dfc..afe369c2 100644 --- a/test/migrations/029_rename_type_attribute.js +++ b/test/migrations/029_rename_type_attribute.js @@ -1,3 +1,3 @@ exports.up = (pgm) => { - pgm.renameTypeAttribute('obj', 'string', 'str') -} + pgm.renameTypeAttribute('obj', 'string', 'str'); +}; diff --git a/test/migrations/030_rename_type_attribute_test.js b/test/migrations/030_rename_type_attribute_test.js index 3c431c59..55492736 100644 --- a/test/migrations/030_rename_type_attribute_test.js +++ b/test/migrations/030_rename_type_attribute_test.js @@ -1,5 +1,5 @@ exports.up = (pgm) => { - pgm.sql("select (ROW(1, 'x')::obj).str;") -} + pgm.sql("select (ROW(1, 'x')::obj).str;"); +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/031_drop_type_attribute.js b/test/migrations/031_drop_type_attribute.js index a0e47a3c..72b89c7f 100644 --- a/test/migrations/031_drop_type_attribute.js +++ b/test/migrations/031_drop_type_attribute.js @@ -1,7 +1,7 @@ exports.up = (pgm) => { - pgm.dropTypeAttribute('obj', 'str') -} + pgm.dropTypeAttribute('obj', 'str'); +}; exports.down = (pgm) => { - pgm.addTypeAttribute('obj', 'str', 'text') -} + pgm.addTypeAttribute('obj', 'str', 'text'); +}; diff --git a/test/migrations/032_drop_type_attribute_test.js b/test/migrations/032_drop_type_attribute_test.js index 50114d55..cfc90fec 100644 --- a/test/migrations/032_drop_type_attribute_test.js +++ b/test/migrations/032_drop_type_attribute_test.js @@ -1,14 +1,14 @@ exports.up = async (pgm) => { - await pgm.db.query('SAVEPOINT sp_attr;') + await pgm.db.query('SAVEPOINT sp_attr;'); try { - await pgm.db.query("select (ROW(1, 'x')::obj).str;") - throw 1 // eslint-disable-line no-throw-literal + await pgm.db.query("select (ROW(1, 'x')::obj).str;"); + throw 1; // eslint-disable-line no-throw-literal } catch (err) { if (err === 1) { - throw new Error('Attribute was not removed') + throw new Error('Attribute was not removed'); } - await pgm.db.query('ROLLBACK TO SAVEPOINT sp_attr;') + await pgm.db.query('ROLLBACK TO SAVEPOINT sp_attr;'); } -} +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/033_drop_type.js b/test/migrations/033_drop_type.js index 0386bea8..76ef955b 100644 --- a/test/migrations/033_drop_type.js +++ b/test/migrations/033_drop_type.js @@ -1,6 +1,6 @@ exports.up = (pgm) => { - pgm.createType('list_for_drop', ['a', 'b', 'c']) - pgm.dropType('list_for_drop') -} + pgm.createType('list_for_drop', ['a', 'b', 'c']); + pgm.dropType('list_for_drop'); +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/034_drop_type_test.js b/test/migrations/034_drop_type_test.js index 503f7c7e..5d2d548c 100644 --- a/test/migrations/034_drop_type_test.js +++ b/test/migrations/034_drop_type_test.js @@ -1,14 +1,14 @@ exports.up = async (pgm) => { - await pgm.db.query('SAVEPOINT sp_drop;') + await pgm.db.query('SAVEPOINT sp_drop;'); try { - await pgm.db.query('CREATE TEMPORARY TABLE t_list_3 (l list_for_drop);') - throw 1 // eslint-disable-line no-throw-literal + await pgm.db.query('CREATE TEMPORARY TABLE t_list_3 (l list_for_drop);'); + throw 1; // eslint-disable-line no-throw-literal } catch (err) { if (err === 1) { - throw new Error('Type was not removed') + throw new Error('Type was not removed'); } - await pgm.db.query('ROLLBACK TO SAVEPOINT sp_drop;') + await pgm.db.query('ROLLBACK TO SAVEPOINT sp_drop;'); } -} +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/035_role_add.js b/test/migrations/035_role_add.js index 39377bff..bfd16da9 100644 --- a/test/migrations/035_role_add.js +++ b/test/migrations/035_role_add.js @@ -1,3 +1,3 @@ exports.up = (pgm) => { - pgm.createRole('r', { password: 'p', login: true }) -} + pgm.createRole('r', { password: 'p', login: true }); +}; diff --git a/test/migrations/036_role_alter.js b/test/migrations/036_role_alter.js index 626109ee..cbecac4c 100644 --- a/test/migrations/036_role_alter.js +++ b/test/migrations/036_role_alter.js @@ -1,7 +1,7 @@ exports.up = (pgm) => { - pgm.alterRole('r', { login: false }) -} + pgm.alterRole('r', { login: false }); +}; exports.down = (pgm) => { - pgm.alterRole('r', { login: true }) -} + pgm.alterRole('r', { login: true }); +}; diff --git a/test/migrations/037_role_rename.js b/test/migrations/037_role_rename.js index 63d7ecda..13cc82c8 100644 --- a/test/migrations/037_role_rename.js +++ b/test/migrations/037_role_rename.js @@ -1,3 +1,3 @@ exports.up = (pgm) => { - pgm.renameRole('r', 'rx') -} + pgm.renameRole('r', 'rx'); +}; diff --git a/test/migrations/038_role_drop.js b/test/migrations/038_role_drop.js index 00ddd4bd..3c074d95 100644 --- a/test/migrations/038_role_drop.js +++ b/test/migrations/038_role_drop.js @@ -1,11 +1,11 @@ -const create = require('./035_role_add') -const rename = require('./037_role_rename') +const create = require('./035_role_add'); +const rename = require('./037_role_rename'); exports.up = (pgm) => { - pgm.dropRole('rx') -} + pgm.dropRole('rx'); +}; exports.down = (pgm) => { - create.up(pgm) - rename.up(pgm) -} + create.up(pgm); + rename.up(pgm); +}; diff --git a/test/migrations/039_function_create.js b/test/migrations/039_function_create.js index b93fba27..ca07f1d1 100644 --- a/test/migrations/039_function_create.js +++ b/test/migrations/039_function_create.js @@ -1,4 +1,4 @@ -exports.params = ['integer', { name: 'arg2', mode: 'in', type: 'integer' }] +exports.params = ['integer', { name: 'arg2', mode: 'in', type: 'integer' }]; exports.up = (pgm) => { pgm.createFunction( @@ -12,6 +12,6 @@ exports.up = (pgm) => { BEGIN return $1 + arg2; END; - `, - ) -} + ` + ); +}; diff --git a/test/migrations/040_function_rename.js b/test/migrations/040_function_rename.js index 614d82ce..7bf7ca38 100644 --- a/test/migrations/040_function_rename.js +++ b/test/migrations/040_function_rename.js @@ -1,5 +1,5 @@ -const { params } = require('./039_function_create') +const { params } = require('./039_function_create'); exports.up = (pgm) => { - pgm.renameFunction('f', params, 'add') -} + pgm.renameFunction('f', params, 'add'); +}; diff --git a/test/migrations/041_function_test.js b/test/migrations/041_function_test.js index 7e6dab40..24948d72 100644 --- a/test/migrations/041_function_test.js +++ b/test/migrations/041_function_test.js @@ -1,8 +1,8 @@ exports.up = async (pgm) => { - const [{ r }] = await pgm.db.select('SELECT add(1,2) as r') + const [{ r }] = await pgm.db.select('SELECT add(1,2) as r'); if (r !== 3) { - throw new Error('Function does not work') + throw new Error('Function does not work'); } -} +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/042_function_drop.js b/test/migrations/042_function_drop.js index 76c5f1b9..2f3af71b 100644 --- a/test/migrations/042_function_drop.js +++ b/test/migrations/042_function_drop.js @@ -1,11 +1,11 @@ -const create = require('./039_function_create') -const rename = require('./040_function_rename') +const create = require('./039_function_create'); +const rename = require('./040_function_rename'); exports.up = (pgm) => { - pgm.dropFunction('add', create.params) -} + pgm.dropFunction('add', create.params); +}; exports.down = (pgm) => { - create.up(pgm) - rename.up(pgm) -} + create.up(pgm); + rename.up(pgm); +}; diff --git a/test/migrations/043_trigger_create_rename.js b/test/migrations/043_trigger_create_rename.js index b71744d9..12c9b419 100644 --- a/test/migrations/043_trigger_create_rename.js +++ b/test/migrations/043_trigger_create_rename.js @@ -1,7 +1,7 @@ exports.up = (pgm) => { pgm.createTable('tt', { a: 'integer', - }) + }); pgm.createTrigger( 'tt', 't', @@ -16,8 +16,8 @@ BEGIN NEW.a := NEW.a + 1; return NEW; END; - `, - ) - pgm.renameTrigger('tt', 't', 'trig') - pgm.renameFunction('t', [], 'trig') -} + ` + ); + pgm.renameTrigger('tt', 't', 'trig'); + pgm.renameFunction('t', [], 'trig'); +}; diff --git a/test/migrations/044_trigger_test.js b/test/migrations/044_trigger_test.js index d205815e..70d4a074 100644 --- a/test/migrations/044_trigger_test.js +++ b/test/migrations/044_trigger_test.js @@ -1,8 +1,10 @@ exports.up = async (pgm) => { - const [{ a }] = await pgm.db.select('INSERT INTO tt (a) VALUES (1) RETURNING a') + const [{ a }] = await pgm.db.select( + 'INSERT INTO tt (a) VALUES (1) RETURNING a' + ); if (a !== 2) { - throw new Error('Trigger does not work') + throw new Error('Trigger does not work'); } -} +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/045_trigger_drop.js b/test/migrations/045_trigger_drop.js index 7babc221..7658f437 100644 --- a/test/migrations/045_trigger_drop.js +++ b/test/migrations/045_trigger_drop.js @@ -1,9 +1,9 @@ -const trigger = require('./043_trigger_create_rename') +const trigger = require('./043_trigger_create_rename'); exports.up = (pgm) => { - pgm.dropTrigger('tt', 'trig') - pgm.dropFunction('trig', []) - pgm.dropTable('tt') -} + pgm.dropTrigger('tt', 'trig'); + pgm.dropFunction('trig', []); + pgm.dropTable('tt'); +}; -exports.down = trigger.up +exports.down = trigger.up; diff --git a/test/migrations/046_domain_create_rename.js b/test/migrations/046_domain_create_rename.js index 1ee720dd..fd32c670 100644 --- a/test/migrations/046_domain_create_rename.js +++ b/test/migrations/046_domain_create_rename.js @@ -1,9 +1,9 @@ exports.up = (pgm) => { pgm.createDomain('d', 'integer', { check: 'VALUE BETWEEN 0 AND 10', - }) - pgm.renameDomain('d', 'dom') + }); + pgm.renameDomain('d', 'dom'); pgm.createTable('td', { d: 'dom', - }) -} + }); +}; diff --git a/test/migrations/047_domain_check.js b/test/migrations/047_domain_check.js index ca2a505e..77036138 100644 --- a/test/migrations/047_domain_check.js +++ b/test/migrations/047_domain_check.js @@ -1,14 +1,14 @@ exports.up = async (pgm) => { - await pgm.db.query('SAVEPOINT sp_check;') + await pgm.db.query('SAVEPOINT sp_check;'); try { - await pgm.db.query('INSERT INTO td (d) VALUES (11);') - throw 1 // eslint-disable-line no-throw-literal + await pgm.db.query('INSERT INTO td (d) VALUES (11);'); + throw 1; // eslint-disable-line no-throw-literal } catch (err) { if (err === 1) { - throw new Error('Check on domain was not set') + throw new Error('Check on domain was not set'); } - await pgm.db.query('ROLLBACK TO SAVEPOINT sp_check;') + await pgm.db.query('ROLLBACK TO SAVEPOINT sp_check;'); } -} +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/048_domain_drop.js b/test/migrations/048_domain_drop.js index f5696650..bc8bb5e8 100644 --- a/test/migrations/048_domain_drop.js +++ b/test/migrations/048_domain_drop.js @@ -1,8 +1,8 @@ -const domain = require('./046_domain_create_rename') +const domain = require('./046_domain_create_rename'); exports.up = (pgm) => { - pgm.dropTable('td') - pgm.dropDomain('dom') -} + pgm.dropTable('td'); + pgm.dropDomain('dom'); +}; -exports.down = domain.up +exports.down = domain.up; diff --git a/test/migrations/049_sequence_create_rename.js b/test/migrations/049_sequence_create_rename.js index fb763d89..020a95ea 100644 --- a/test/migrations/049_sequence_create_rename.js +++ b/test/migrations/049_sequence_create_rename.js @@ -1,7 +1,7 @@ exports.up = (pgm) => { - pgm.createSequence('s', { minvalue: 10 }) - pgm.renameSequence('s', 'seq') + pgm.createSequence('s', { minvalue: 10 }); + pgm.renameSequence('s', 'seq'); pgm.createTable('ts', { id: { type: 'integer', default: pgm.func("nextval('seq')") }, - }) -} + }); +}; diff --git a/test/migrations/050_sequence_test.js b/test/migrations/050_sequence_test.js index ea00a5a2..d0e59a04 100644 --- a/test/migrations/050_sequence_test.js +++ b/test/migrations/050_sequence_test.js @@ -1,8 +1,10 @@ exports.up = async (pgm) => { - const [{ id }] = await pgm.db.select('INSERT INTO ts DEFAULT VALUES RETURNING id;') + const [{ id }] = await pgm.db.select( + 'INSERT INTO ts DEFAULT VALUES RETURNING id;' + ); if (id !== 10) { - throw new Error('Bad sequence value') + throw new Error('Bad sequence value'); } -} +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/051_sequence_alter.js b/test/migrations/051_sequence_alter.js index ac1c5b70..16090e4d 100644 --- a/test/migrations/051_sequence_alter.js +++ b/test/migrations/051_sequence_alter.js @@ -1,5 +1,5 @@ exports.up = (pgm) => { - pgm.alterSequence('seq', { restart: 20 }) -} + pgm.alterSequence('seq', { restart: 20 }); +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/052_sequence_alter_test.js b/test/migrations/052_sequence_alter_test.js index f502b32f..20486eea 100644 --- a/test/migrations/052_sequence_alter_test.js +++ b/test/migrations/052_sequence_alter_test.js @@ -1,8 +1,10 @@ exports.up = async (pgm) => { - const [{ id }] = await pgm.db.select('INSERT INTO ts DEFAULT VALUES RETURNING id;') + const [{ id }] = await pgm.db.select( + 'INSERT INTO ts DEFAULT VALUES RETURNING id;' + ); if (id !== 20) { - throw new Error('Bad sequence value') + throw new Error('Bad sequence value'); } -} +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/053_sequence_drop.js b/test/migrations/053_sequence_drop.js index a82ad917..3e0769b6 100644 --- a/test/migrations/053_sequence_drop.js +++ b/test/migrations/053_sequence_drop.js @@ -1,8 +1,8 @@ -const sequence = require('./049_sequence_create_rename') +const sequence = require('./049_sequence_create_rename'); exports.up = (pgm) => { - pgm.dropTable('ts') - pgm.dropSequence('seq') -} + pgm.dropTable('ts'); + pgm.dropSequence('seq'); +}; -exports.down = sequence.up +exports.down = sequence.up; diff --git a/test/migrations/054_operator_create.js b/test/migrations/054_operator_create.js index 5dd18e5f..08346fc0 100644 --- a/test/migrations/054_operator_create.js +++ b/test/migrations/054_operator_create.js @@ -2,7 +2,7 @@ exports.up = (pgm) => { pgm.createType('complex', { r: 'integer', i: 'integer', - }) + }); pgm.createFunction( 'complex_add', ['complex', 'complex'], @@ -14,12 +14,12 @@ exports.up = (pgm) => { BEGIN return ROW($1.r + $2.r, $1.i + $2.i); END; - `, - ) + ` + ); pgm.createOperator('+', { left: 'complex', right: 'complex', procedure: 'complex_add', commutator: '+', - }) -} + }); +}; diff --git a/test/migrations/055_operator_test.js b/test/migrations/055_operator_test.js index 4d611a6f..ac569886 100644 --- a/test/migrations/055_operator_test.js +++ b/test/migrations/055_operator_test.js @@ -1,8 +1,10 @@ exports.up = async (pgm) => { - const [{ sum }] = await pgm.db.select('SELECT ROW(1,2)::complex + ROW(3,4)::complex as sum;') + const [{ sum }] = await pgm.db.select( + 'SELECT ROW(1,2)::complex + ROW(3,4)::complex as sum;' + ); if (sum !== '(4,6)') { - throw new Error('Bad sequence value') + throw new Error('Bad sequence value'); } -} +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/056_operator_drop.js b/test/migrations/056_operator_drop.js index 7f5b67eb..270953a3 100644 --- a/test/migrations/056_operator_drop.js +++ b/test/migrations/056_operator_drop.js @@ -1,9 +1,9 @@ -const operator = require('./054_operator_create') +const operator = require('./054_operator_create'); exports.up = (pgm) => { - pgm.dropOperator('+', { left: 'complex', right: 'complex' }) - pgm.dropFunction('complex_add', ['complex', 'complex']) - pgm.dropType('complex') -} + pgm.dropOperator('+', { left: 'complex', right: 'complex' }); + pgm.dropFunction('complex_add', ['complex', 'complex']); + pgm.dropType('complex'); +}; -exports.down = operator.up +exports.down = operator.up; diff --git a/test/migrations/057_policy_create.js b/test/migrations/057_policy_create.js index 594d930c..87f4ba24 100644 --- a/test/migrations/057_policy_create.js +++ b/test/migrations/057_policy_create.js @@ -1,38 +1,38 @@ -const schema = process.env.SCHEMA || 'public' +const schema = process.env.SCHEMA || 'public'; exports.up = (pgm) => { pgm.createTable('tp', { user_name: 'varchar(20)', - }) + }); pgm.alterTable('tp', { levelSecurity: 'enable', - }) - pgm.createRole('admin') - pgm.createRole('alice') + }); + pgm.createRole('admin'); + pgm.createRole('alice'); pgm.createPolicy('tp', 'p', { role: 'admin', using: 'true', check: 'true', - }) - pgm.renamePolicy('tp', 'p', 'admin_policy') + }); + pgm.renamePolicy('tp', 'p', 'admin_policy'); pgm.createPolicy('tp', 'user_select_policy', { command: 'SELECT', using: 'current_user = user_name', - }) + }); pgm.createPolicy('tp', 'user_update_policy', { command: 'UPDATE', using: 'current_user = user_name', check: 'current_user = user_name', - }) - pgm.sql(`GRANT USAGE ON SCHEMA "${schema}" TO PUBLIC`) - pgm.sql('GRANT ALL ON "tp" TO PUBLIC') -} + }); + pgm.sql(`GRANT USAGE ON SCHEMA "${schema}" TO PUBLIC`); + pgm.sql('GRANT ALL ON "tp" TO PUBLIC'); +}; exports.down = (pgm) => { - pgm.dropPolicy('tp', 'admin_policy') - pgm.dropPolicy('tp', 'user_select_policy') - pgm.dropPolicy('tp', 'user_update_policy') - pgm.dropTable('tp') - pgm.dropRole('admin') - pgm.dropRole('alice') -} + pgm.dropPolicy('tp', 'admin_policy'); + pgm.dropPolicy('tp', 'user_select_policy'); + pgm.dropPolicy('tp', 'user_update_policy'); + pgm.dropTable('tp'); + pgm.dropRole('admin'); + pgm.dropRole('alice'); +}; diff --git a/test/migrations/058_policy_test.js b/test/migrations/058_policy_test.js index 5726c760..35559a59 100644 --- a/test/migrations/058_policy_test.js +++ b/test/migrations/058_policy_test.js @@ -3,18 +3,18 @@ exports.up = async (pgm) => { pgm.db.query("INSERT INTO tp(user_name) VALUES ('admin');"), pgm.db.query("INSERT INTO tp(user_name) VALUES ('alice');"), pgm.db.query("INSERT INTO tp(user_name) VALUES ('bob');"), - ]) - await pgm.db.query('set role admin;') - const { length: adminLength } = await pgm.db.select('SELECT * FROM tp;') + ]); + await pgm.db.query('set role admin;'); + const { length: adminLength } = await pgm.db.select('SELECT * FROM tp;'); if (adminLength !== 3) { - throw new Error('Policy is not enforced') + throw new Error('Policy is not enforced'); } - await pgm.db.query('set role alice;') - const { length: aliceLength } = await pgm.db.select('SELECT * FROM tp;') + await pgm.db.query('set role alice;'); + const { length: aliceLength } = await pgm.db.select('SELECT * FROM tp;'); if (aliceLength !== 1) { - throw new Error('Policy is not enforced') + throw new Error('Policy is not enforced'); } - await pgm.db.query('reset role;') -} + await pgm.db.query('reset role;'); +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/059_policy_drop.js b/test/migrations/059_policy_drop.js index 9eac67d1..31a1d956 100644 --- a/test/migrations/059_policy_drop.js +++ b/test/migrations/059_policy_drop.js @@ -1,5 +1,5 @@ -const policy = require('./057_policy_create') +const policy = require('./057_policy_create'); -exports.up = policy.down +exports.up = policy.down; -exports.down = policy.up +exports.down = policy.up; diff --git a/test/migrations/060_column_comment.js b/test/migrations/060_column_comment.js index 0fe03c11..a857413e 100644 --- a/test/migrations/060_column_comment.js +++ b/test/migrations/060_column_comment.js @@ -1,10 +1,10 @@ -exports.comment = 'comment on column id' -const schema = 'test' -exports.table = { schema: 'test', name: 'tcc' } +exports.comment = 'comment on column id'; +const schema = 'test'; +exports.table = { schema: 'test', name: 'tcc' }; exports.up = (pgm) => { - pgm.createSchema(schema) + pgm.createSchema(schema); pgm.createTable(exports.table, { id: { type: 'id', comment: exports.comment }, - }) -} + }); +}; diff --git a/test/migrations/061_column_comment_test.js b/test/migrations/061_column_comment_test.js index 120eda80..575ccb78 100644 --- a/test/migrations/061_column_comment_test.js +++ b/test/migrations/061_column_comment_test.js @@ -1,7 +1,7 @@ const { comment, table: { schema, name }, -} = require('./060_column_comment') +} = require('./060_column_comment'); exports.up = async (pgm) => { const [{ description }] = await pgm.db.select( @@ -10,11 +10,11 @@ exports.up = async (pgm) => { join information_schema.columns c on (d.objsubid = c.ordinal_position) join pg_class t ON (t.relname = c.table_name and t.relkind = 'r' and d.objoid = t.oid) join pg_namespace n ON (t.relnamespace = n.oid and n.nspname = c.table_schema) - WHERE c.column_name = 'id' and c.table_schema = '${schema}' and c.table_name = '${name}';`, - ) + WHERE c.column_name = 'id' and c.table_schema = '${schema}' and c.table_name = '${name}';` + ); if (description !== comment) { - throw new Error('Comment not set') + throw new Error('Comment not set'); } -} +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/062_view.js b/test/migrations/062_view.js index e75c9e54..1e90f5e3 100644 --- a/test/migrations/062_view.js +++ b/test/migrations/062_view.js @@ -7,12 +7,12 @@ exports.up = (pgm) => { notNull: true, default: pgm.func('current_timestamp'), }, - }) + }); pgm.createView( 'v', { columns: ['id', 'str'], }, - 'SELECT id, string FROM tv', - ) -} + 'SELECT id, string FROM tv' + ); +}; diff --git a/test/migrations/063_view_test.js b/test/migrations/063_view_test.js index f0b8ff2b..709f338c 100644 --- a/test/migrations/063_view_test.js +++ b/test/migrations/063_view_test.js @@ -1,5 +1,5 @@ exports.up = (pgm) => { - pgm.sql('SELECT id, str FROM v') -} + pgm.sql('SELECT id, str FROM v'); +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/064_alter_view_column.js b/test/migrations/064_alter_view_column.js index 442b8b39..05357d45 100644 --- a/test/migrations/064_alter_view_column.js +++ b/test/migrations/064_alter_view_column.js @@ -1,7 +1,7 @@ exports.up = (pgm) => { - pgm.alterViewColumn('v', 'str', { default: 'some default value' }) -} + pgm.alterViewColumn('v', 'str', { default: 'some default value' }); +}; exports.down = (pgm) => { - pgm.alterViewColumn('v', 'str', { default: null }) -} + pgm.alterViewColumn('v', 'str', { default: null }); +}; diff --git a/test/migrations/065_materialized_view.js b/test/migrations/065_materialized_view.js index 43e5bec4..6e1cb632 100644 --- a/test/migrations/065_materialized_view.js +++ b/test/migrations/065_materialized_view.js @@ -7,7 +7,7 @@ exports.up = (pgm) => { notNull: true, default: pgm.func('current_timestamp'), }, - }) + }); pgm.createMaterializedView( 'mvx', { @@ -17,9 +17,9 @@ exports.up = (pgm) => { autovacuum_vacuum_threshold: 50, }, }, - 'SELECT id, string FROM tmv', - ) - pgm.renameMaterializedView('mvx', 'mv') - pgm.renameMaterializedViewColumn('mv', 'strx', 'str') - pgm.refreshMaterializedView('mv') -} + 'SELECT id, string FROM tmv' + ); + pgm.renameMaterializedView('mvx', 'mv'); + pgm.renameMaterializedViewColumn('mv', 'strx', 'str'); + pgm.refreshMaterializedView('mv'); +}; diff --git a/test/migrations/066_materialized_view_test.js b/test/migrations/066_materialized_view_test.js index ff258f9e..e60ef516 100644 --- a/test/migrations/066_materialized_view_test.js +++ b/test/migrations/066_materialized_view_test.js @@ -1,5 +1,5 @@ exports.up = (pgm) => { - pgm.sql('SELECT id, str FROM mv') -} + pgm.sql('SELECT id, str FROM mv'); +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/067_materialized_view_alter.js b/test/migrations/067_materialized_view_alter.js index b0d5a363..71b4df65 100644 --- a/test/migrations/067_materialized_view_alter.js +++ b/test/migrations/067_materialized_view_alter.js @@ -4,7 +4,7 @@ exports.up = (pgm) => { autovacuum_enabled: false, autovacuum_vacuum_threshold: 10, }, - }) -} + }); +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/068_extension.js b/test/migrations/068_extension.js index ed98a0ef..b5df1910 100644 --- a/test/migrations/068_extension.js +++ b/test/migrations/068_extension.js @@ -1,8 +1,8 @@ exports.up = (pgm) => { - pgm.createExtension('uuid-ossp', { ifNotExists: true }) - pgm.dropExtension('uuid-ossp') - pgm.createExtension('uuid-ossp') - pgm.dropExtension('uuid-ossp') -} + pgm.createExtension('uuid-ossp', { ifNotExists: true }); + pgm.dropExtension('uuid-ossp'); + pgm.createExtension('uuid-ossp'); + pgm.dropExtension('uuid-ossp'); +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/069_comments.js b/test/migrations/069_comments.js index 7c55f5a3..a52a2e5c 100644 --- a/test/migrations/069_comments.js +++ b/test/migrations/069_comments.js @@ -1,6 +1,6 @@ exports.up = (pgm) => { - pgm.createTable('test-comment', {}, { comment: "table's comment" }) - pgm.dropTable('test-comment') -} + pgm.createTable('test-comment', {}, { comment: "table's comment" }); + pgm.dropTable('test-comment'); +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/070_extension_schema.js b/test/migrations/070_extension_schema.js index 207a7133..eeeb0d71 100644 --- a/test/migrations/070_extension_schema.js +++ b/test/migrations/070_extension_schema.js @@ -1,4 +1,4 @@ exports.up = (pgm) => { - pgm.createSchema('extension-test') - pgm.createExtension('ltree', { schema: 'extension-test' }) -} + pgm.createSchema('extension-test'); + pgm.createExtension('ltree', { schema: 'extension-test' }); +}; diff --git a/test/migrations/071_constraint_name_for_foreign_key.js b/test/migrations/071_constraint_name_for_foreign_key.js index 0f16c2fd..11883171 100644 --- a/test/migrations/071_constraint_name_for_foreign_key.js +++ b/test/migrations/071_constraint_name_for_foreign_key.js @@ -1,5 +1,5 @@ exports.up = (pgm) => { - pgm.createTable('ft1', { id: 'id' }) + pgm.createTable('ft1', { id: 'id' }); pgm.createTable('ft2', { id: { type: 'integer', @@ -7,6 +7,6 @@ exports.up = (pgm) => { references: 'ft1', referencesConstraintName: 'my_constraint_name', }, - }) - pgm.renameConstraint('ft2', 'my_constraint_name', 'better_constraint_name') -} + }); + pgm.renameConstraint('ft2', 'my_constraint_name', 'better_constraint_name'); +}; diff --git a/test/migrations/072_alter_column_comment.js b/test/migrations/072_alter_column_comment.js index f991171f..3add03bb 100644 --- a/test/migrations/072_alter_column_comment.js +++ b/test/migrations/072_alter_column_comment.js @@ -1,15 +1,15 @@ -exports.comment = 'This is my comment' -const schema = 'comment_schema' -exports.table = { schema, name: 't' } +exports.comment = 'This is my comment'; +const schema = 'comment_schema'; +exports.table = { schema, name: 't' }; exports.up = (pgm) => { - pgm.createSchema(schema) - pgm.createTable(exports.table, { id: 'id' }) - pgm.alterColumn(exports.table, 'id', { type: 'text' }) - pgm.alterColumn(exports.table, 'id', { comment: exports.comment }) -} + pgm.createSchema(schema); + pgm.createTable(exports.table, { id: 'id' }); + pgm.alterColumn(exports.table, 'id', { type: 'text' }); + pgm.alterColumn(exports.table, 'id', { comment: exports.comment }); +}; exports.down = (pgm) => { - pgm.dropTable(exports.table) - pgm.dropSchema(schema) -} + pgm.dropTable(exports.table); + pgm.dropSchema(schema); +}; diff --git a/test/migrations/073_alter_column_comment_test.js b/test/migrations/073_alter_column_comment_test.js index 82e8c6f1..fe679bde 100644 --- a/test/migrations/073_alter_column_comment_test.js +++ b/test/migrations/073_alter_column_comment_test.js @@ -1,7 +1,7 @@ const { table: { schema, name }, comment, -} = require('./072_alter_column_comment') +} = require('./072_alter_column_comment'); exports.up = async (pgm) => { const [{ description }] = await pgm.db.select( @@ -10,11 +10,11 @@ exports.up = async (pgm) => { join information_schema.columns c on (d.objsubid = c.ordinal_position) join pg_class t ON (t.relname = c.table_name and t.relkind = 'r' and d.objoid = t.oid) join pg_namespace n ON (t.relnamespace = n.oid and n.nspname = c.table_schema) - WHERE c.column_name = 'id' and c.table_schema = '${schema}' and c.table_name = '${name}';`, - ) + WHERE c.column_name = 'id' and c.table_schema = '${schema}' and c.table_name = '${name}';` + ); if (description !== comment) { - throw new Error('Comment not set') + throw new Error('Comment not set'); } -} +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/074_rename_type_value.js b/test/migrations/074_rename_type_value.js index 5983abc3..3ee5de5d 100644 --- a/test/migrations/074_rename_type_value.js +++ b/test/migrations/074_rename_type_value.js @@ -1,22 +1,24 @@ const getMajorVersion = async (pgm) => { - const [{ server_version: version }] = await pgm.db.select(`SHOW "server_version"`) - const [major] = version.split('.') - return Number(major) -} + const [{ server_version: version }] = await pgm.db.select( + `SHOW "server_version"` + ); + const [major] = version.split('.'); + return Number(major); +}; -const isSupportedVersion = (major) => major >= 10 +const isSupportedVersion = (major) => major >= 10; exports.up = async (pgm) => { - const major = await getMajorVersion(pgm) + const major = await getMajorVersion(pgm); if (isSupportedVersion(major)) { - pgm.createType('list2', ['a', 'd', 'c']) - pgm.renameTypeValue('list2', 'd', 'b') + pgm.createType('list2', ['a', 'd', 'c']); + pgm.renameTypeValue('list2', 'd', 'b'); } -} +}; exports.down = async (pgm) => { - const major = await getMajorVersion(pgm) + const major = await getMajorVersion(pgm); if (isSupportedVersion(major)) { - pgm.dropType('list2') + pgm.dropType('list2'); } -} +}; diff --git a/test/migrations/075_drop_index_schema.js b/test/migrations/075_drop_index_schema.js index 4f3599f3..6354688b 100644 --- a/test/migrations/075_drop_index_schema.js +++ b/test/migrations/075_drop_index_schema.js @@ -1,9 +1,9 @@ exports.up = (pgm) => { - const schema = 'foo' - const tableName = { schema, name: 'bar' } - const columnName = 'baz' + const schema = 'foo'; + const tableName = { schema, name: 'bar' }; + const columnName = 'baz'; - pgm.createSchema(schema) + pgm.createSchema(schema); pgm.createTable(tableName, { foo_id: { type: 'serial', @@ -13,12 +13,12 @@ exports.up = (pgm) => { type: 'integer', notNull: true, }, - }) - pgm.createIndex(tableName, columnName) + }); + pgm.createIndex(tableName, columnName); - pgm.dropIndex(tableName, columnName) - pgm.dropTable(tableName) - pgm.dropSchema(schema) -} + pgm.dropIndex(tableName, columnName); + pgm.dropTable(tableName); + pgm.dropSchema(schema); +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/076_create_table_like.js b/test/migrations/076_create_table_like.js index 74267073..76bd2f29 100644 --- a/test/migrations/076_create_table_like.js +++ b/test/migrations/076_create_table_like.js @@ -10,8 +10,8 @@ exports.up = (pgm) => { excluding: ['INDEXES', 'STORAGE'], }, }, - }, - ) -} + } + ); +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/077_create_table_generated_column.js b/test/migrations/077_create_table_generated_column.js index e0c1086a..9d2aac77 100644 --- a/test/migrations/077_create_table_generated_column.js +++ b/test/migrations/077_create_table_generated_column.js @@ -1,13 +1,15 @@ const getMajorVersion = async (pgm) => { - const [{ server_version: version }] = await pgm.db.select(`SHOW "server_version"`) - const [major] = version.split('.') - return Number(major) -} + const [{ server_version: version }] = await pgm.db.select( + `SHOW "server_version"` + ); + const [major] = version.split('.'); + return Number(major); +}; -const isSupportedVersion = (major) => major >= 10 +const isSupportedVersion = (major) => major >= 10; exports.up = async (pgm) => { - const major = await getMajorVersion(pgm) + const major = await getMajorVersion(pgm); if (isSupportedVersion(major)) { pgm.createTable('t_generated', { id: 'id', @@ -19,14 +21,14 @@ exports.up = async (pgm) => { increment: 2, }, }, - }) - pgm.sql('INSERT INTO "t_generated" DEFAULT VALUES') + }); + pgm.sql('INSERT INTO "t_generated" DEFAULT VALUES'); } -} +}; exports.down = async (pgm) => { - const major = await getMajorVersion(pgm) + const major = await getMajorVersion(pgm); if (isSupportedVersion(major)) { - pgm.dropTable('t_generated') + pgm.dropTable('t_generated'); } -} +}; diff --git a/test/migrations/078_add_column_if_not_exists.js b/test/migrations/078_add_column_if_not_exists.js index 8de50bcc..5319dc10 100644 --- a/test/migrations/078_add_column_if_not_exists.js +++ b/test/migrations/078_add_column_if_not_exists.js @@ -4,18 +4,18 @@ exports.up = (pgm) => { { string: { type: 'text' }, }, - { ifNotExists: true }, - ) + { ifNotExists: true } + ); pgm.addColumns( 't1', { string: { type: 'text' }, }, - { ifNotExists: true }, - ) -} + { ifNotExists: true } + ); +}; exports.down = (pgm) => { - pgm.dropColumns('t1', 'string') -} + pgm.dropColumns('t1', 'string'); +}; diff --git a/test/migrations/079_drop_index_schema.js b/test/migrations/079_drop_index_schema.js index 3fa02d17..6a9eeb8a 100644 --- a/test/migrations/079_drop_index_schema.js +++ b/test/migrations/079_drop_index_schema.js @@ -1,10 +1,10 @@ exports.up = (pgm) => { - const schema = 'a.b::c' - const tableName = { schema, name: 'bar' } - const columnName = 'baz' - const indexName = 'idx' + const schema = 'a.b::c'; + const tableName = { schema, name: 'bar' }; + const columnName = 'baz'; + const indexName = 'idx'; - pgm.createSchema(schema) + pgm.createSchema(schema); pgm.createTable(tableName, { foo_id: { type: 'serial', @@ -14,12 +14,12 @@ exports.up = (pgm) => { type: 'integer', notNull: true, }, - }) - pgm.createIndex(tableName, columnName, { name: indexName }) + }); + pgm.createIndex(tableName, columnName, { name: indexName }); - pgm.dropIndex(tableName, columnName, { name: indexName }) - pgm.dropTable(tableName) - pgm.dropSchema(schema) -} + pgm.dropIndex(tableName, columnName, { name: indexName }); + pgm.dropTable(tableName); + pgm.dropSchema(schema); +}; -exports.down = () => null +exports.down = () => null; diff --git a/test/migrations/080_create_table_generated_column_take_2.js b/test/migrations/080_create_table_generated_column_take_2.js index 685629cc..ca96a407 100644 --- a/test/migrations/080_create_table_generated_column_take_2.js +++ b/test/migrations/080_create_table_generated_column_take_2.js @@ -1,14 +1,16 @@ const getMajorVersion = async (pgm) => { - const [{ server_version: version }] = await pgm.db.select(`SHOW "server_version"`) - const [major] = version.split('.') - return Number(major) -} + const [{ server_version: version }] = await pgm.db.select( + `SHOW "server_version"` + ); + const [major] = version.split('.'); + return Number(major); +}; -const isSupportedSequenceGeneratedVersion = (major) => major >= 10 -const isSupportedExpressionGeneratedVersion = (major) => major >= 12 +const isSupportedSequenceGeneratedVersion = (major) => major >= 10; +const isSupportedExpressionGeneratedVersion = (major) => major >= 12; exports.up = async (pgm) => { - const major = await getMajorVersion(pgm) + const major = await getMajorVersion(pgm); if (isSupportedSequenceGeneratedVersion(major)) { pgm.createTable('t_sequenceGenerated', { id: 'id', @@ -20,8 +22,8 @@ exports.up = async (pgm) => { increment: 2, }, }, - }) - pgm.sql('INSERT INTO "t_sequenceGenerated" DEFAULT VALUES') + }); + pgm.sql('INSERT INTO "t_sequenceGenerated" DEFAULT VALUES'); } if (isSupportedExpressionGeneratedVersion(major)) { pgm.createTable('t_expressionGenerated', { @@ -31,17 +33,17 @@ exports.up = async (pgm) => { notNull: true, expressionGenerated: 'id + 1', }, - }) - pgm.sql('INSERT INTO "t_expressionGenerated" DEFAULT VALUES') + }); + pgm.sql('INSERT INTO "t_expressionGenerated" DEFAULT VALUES'); } -} +}; exports.down = async (pgm) => { - const major = await getMajorVersion(pgm) + const major = await getMajorVersion(pgm); if (isSupportedSequenceGeneratedVersion(major)) { - pgm.dropTable('t_sequenceGenerated') + pgm.dropTable('t_sequenceGenerated'); } if (isSupportedExpressionGeneratedVersion(major)) { - pgm.dropTable('t_expressionGenerated') + pgm.dropTable('t_expressionGenerated'); } -} +}; diff --git a/test/migrations/081_temporary_table.js b/test/migrations/081_temporary_table.js index afd69cdc..87e30ffe 100644 --- a/test/migrations/081_temporary_table.js +++ b/test/migrations/081_temporary_table.js @@ -1,18 +1,18 @@ -exports.comment = 'comment on table t2' +exports.comment = 'comment on table t2'; exports.up = (pgm) => { - pgm.createTable('tmp', { id: 'id' }, { temporary: true }) -} + pgm.createTable('tmp', { id: 'id' }, { temporary: true }); +}; exports.down = async (pgm) => { - await pgm.db.query('SAVEPOINT sp_temp_table;') + await pgm.db.query('SAVEPOINT sp_temp_table;'); try { - await pgm.db.query('DROP TABLE "tmp"') - throw 1 // eslint-disable-line no-throw-literal + await pgm.db.query('DROP TABLE "tmp"'); + throw 1; // eslint-disable-line no-throw-literal } catch (err) { if (err === 1) { - throw new Error('Missing TEMPORARY clause') + throw new Error('Missing TEMPORARY clause'); } - await pgm.db.query('ROLLBACK TO SAVEPOINT sp_temp_table;') + await pgm.db.query('ROLLBACK TO SAVEPOINT sp_temp_table;'); } -} +}; diff --git a/test/migrations/082_view_options.js b/test/migrations/082_view_options.js index e9a534d2..2c0e0ce4 100644 --- a/test/migrations/082_view_options.js +++ b/test/migrations/082_view_options.js @@ -7,7 +7,7 @@ exports.up = (pgm) => { notNull: true, default: pgm.func('current_timestamp'), }, - }) + }); pgm.createView( 'vo', { @@ -16,21 +16,21 @@ exports.up = (pgm) => { check_option: 'LOCAL', }, }, - 'SELECT id, string FROM tvo', - ) + 'SELECT id, string FROM tvo' + ); pgm.alterView('vo', { options: { check_option: 'CASCADED', }, - }) + }); pgm.alterView('vo', { options: { check_option: null, }, - }) -} + }); +}; exports.down = (pgm) => { - pgm.dropView('vo') - pgm.dropTable('tvo') -} + pgm.dropView('vo'); + pgm.dropTable('tvo'); +}; diff --git a/test/migrations/083_alter_column_sequence.js b/test/migrations/083_alter_column_sequence.js index cbe40287..d21d4831 100644 --- a/test/migrations/083_alter_column_sequence.js +++ b/test/migrations/083_alter_column_sequence.js @@ -1,23 +1,27 @@ const getMajorVersion = async (pgm) => { - const [{ server_version: version }] = await pgm.db.select(`SHOW "server_version"`) - const [major] = version.split('.') - return Number(major) -} + const [{ server_version: version }] = await pgm.db.select( + `SHOW "server_version"` + ); + const [major] = version.split('.'); + return Number(major); +}; -const isSupportedVersion = (major) => major >= 10 +const isSupportedVersion = (major) => major >= 10; exports.up = async (pgm) => { - const major = await getMajorVersion(pgm) + const major = await getMajorVersion(pgm); if (isSupportedVersion(major)) { - pgm.createTable('t083', { id: { type: 'integer', notNull: true } }) - pgm.alterColumn('t083', 'id', { sequenceGenerated: { precedence: 'ALWAYS' } }) - pgm.alterColumn('t083', 'id', { sequenceGenerated: null }) + pgm.createTable('t083', { id: { type: 'integer', notNull: true } }); + pgm.alterColumn('t083', 'id', { + sequenceGenerated: { precedence: 'ALWAYS' }, + }); + pgm.alterColumn('t083', 'id', { sequenceGenerated: null }); } -} +}; exports.down = async (pgm) => { - const major = await getMajorVersion(pgm) + const major = await getMajorVersion(pgm); if (isSupportedVersion(major)) { - pgm.dropTable('t083') + pgm.dropTable('t083'); } -} +}; diff --git a/test/migrations/084_drop_unique_index.js b/test/migrations/084_drop_unique_index.js index 371a74dd..3351772c 100644 --- a/test/migrations/084_drop_unique_index.js +++ b/test/migrations/084_drop_unique_index.js @@ -2,11 +2,11 @@ exports.up = (pgm) => { pgm.createTable('t_uniq_index', { id: 'serial', name: 'text', - }) - pgm.createIndex('t_uniq_index', ['name'], { unique: true }) -} + }); + pgm.createIndex('t_uniq_index', ['name'], { unique: true }); +}; exports.down = (pgm) => { - pgm.dropIndex('t_uniq_index', ['name'], { unique: true }) - pgm.dropTable('t_uniq_index') -} + pgm.dropIndex('t_uniq_index', ['name'], { unique: true }); + pgm.dropTable('t_uniq_index'); +}; diff --git a/test/roles-test.ts b/test/roles-test.ts index 0cacc0c8..ba19779c 100644 --- a/test/roles-test.ts +++ b/test/roles-test.ts @@ -1,18 +1,18 @@ -import { expect } from 'chai' -import * as Roles from '../src/operations/roles' -import { options1, options2 } from './utils' +import { expect } from 'chai'; +import * as Roles from '../src/operations/roles'; +import { options1, options2 } from './utils'; describe('lib/operations/roles', () => { describe('.create', () => { it('check defaults', () => { - const sql1 = Roles.createRole(options1)('roleTest') - const sql2 = Roles.createRole(options2)('roleTest') + const sql1 = Roles.createRole(options1)('roleTest'); + const sql2 = Roles.createRole(options2)('roleTest'); expect(sql1).to.equal( - 'CREATE ROLE "roleTest" WITH NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION;', - ) + 'CREATE ROLE "roleTest" WITH NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION;' + ); expect(sql2).to.equal( - 'CREATE ROLE "role_test" WITH NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION;', - ) - }) - }) -}) + 'CREATE ROLE "role_test" WITH NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION;' + ); + }); + }); +}); diff --git a/test/sqlMigration-test.ts b/test/sqlMigration-test.ts index 2be62421..faf4fa07 100644 --- a/test/sqlMigration-test.ts +++ b/test/sqlMigration-test.ts @@ -1,105 +1,105 @@ -import sinon from 'sinon' -import { expect } from 'chai' -import { getActions } from '../src/sqlMigration' +import { expect } from 'chai'; +import sinon from 'sinon'; +import { getActions } from '../src/sqlMigration'; /* eslint-disable no-unused-expressions */ describe('lib/sqlMigration', () => { describe('getActions', () => { it('without comments', () => { - const content = 'SELECT 1 FROM something' - const { up, down } = getActions(content) - expect(up).to.exist - expect(down).to.be.false + const content = 'SELECT 1 FROM something'; + const { up, down } = getActions(content); + expect(up).to.exist; + expect(down).to.be.false; - const sql = sinon.spy() - expect(up({ sql })).to.not.exist - expect(sql.called).to.be.true - expect(sql.lastCall.args[0].trim()).to.eql(content.trim()) - }) + const sql = sinon.spy(); + expect(up({ sql })).to.not.exist; + expect(sql.called).to.be.true; + expect(sql.lastCall.args[0].trim()).to.eql(content.trim()); + }); it('with up comment', () => { const content = ` -- Up Migration SELECT 1 FROM something -` - const { up, down } = getActions(content) - expect(up).to.exist - expect(down).to.be.false +`; + const { up, down } = getActions(content); + expect(up).to.exist; + expect(down).to.be.false; - const sql = sinon.spy() - expect(up({ sql })).to.not.exist - expect(sql.called).to.be.true - expect(sql.lastCall.args[0].trim()).to.eql(content.trim()) - }) + const sql = sinon.spy(); + expect(up({ sql })).to.not.exist; + expect(sql.called).to.be.true; + expect(sql.lastCall.args[0].trim()).to.eql(content.trim()); + }); it('with both comments', () => { const upMigration = ` -- Up Migration -SELECT 1 FROM something` +SELECT 1 FROM something`; const downMigration = ` -- Down Migration -SELECT 2 FROM something` - const content = `${upMigration}${downMigration}` - const { up, down } = getActions(content) - expect(up).to.exist - expect(down).to.exist +SELECT 2 FROM something`; + const content = `${upMigration}${downMigration}`; + const { up, down } = getActions(content); + expect(up).to.exist; + expect(down).to.exist; - const upSql = sinon.spy() - expect(up({ sql: upSql })).to.not.exist - expect(upSql.called).to.be.true - expect(upSql.lastCall.args[0].trim()).to.eql(upMigration.trim()) + const upSql = sinon.spy(); + expect(up({ sql: upSql })).to.not.exist; + expect(upSql.called).to.be.true; + expect(upSql.lastCall.args[0].trim()).to.eql(upMigration.trim()); - const downSql = sinon.spy() - expect(down({ sql: downSql })).to.not.exist - expect(downSql.called).to.be.true - expect(downSql.lastCall.args[0].trim()).to.eql(downMigration.trim()) - }) + const downSql = sinon.spy(); + expect(down({ sql: downSql })).to.not.exist; + expect(downSql.called).to.be.true; + expect(downSql.lastCall.args[0].trim()).to.eql(downMigration.trim()); + }); it('with both comments in reverse order', () => { const upMigration = ` -- Up Migration -SELECT 1 FROM something` +SELECT 1 FROM something`; const downMigration = ` -- Down Migration -SELECT 2 FROM something` - const content = `${downMigration}${upMigration}` - const { up, down } = getActions(content) - expect(up).to.exist - expect(down).to.exist +SELECT 2 FROM something`; + const content = `${downMigration}${upMigration}`; + const { up, down } = getActions(content); + expect(up).to.exist; + expect(down).to.exist; - const upSql = sinon.spy() - expect(up({ sql: upSql })).to.not.exist - expect(upSql.called).to.be.true - expect(upSql.lastCall.args[0].trim()).to.eql(upMigration.trim()) + const upSql = sinon.spy(); + expect(up({ sql: upSql })).to.not.exist; + expect(upSql.called).to.be.true; + expect(upSql.lastCall.args[0].trim()).to.eql(upMigration.trim()); - const downSql = sinon.spy() - expect(down({ sql: downSql })).to.not.exist - expect(downSql.called).to.be.true - expect(downSql.lastCall.args[0].trim()).to.eql(downMigration.trim()) - }) + const downSql = sinon.spy(); + expect(down({ sql: downSql })).to.not.exist; + expect(downSql.called).to.be.true; + expect(downSql.lastCall.args[0].trim()).to.eql(downMigration.trim()); + }); it('with both comments with some chars added', () => { const upMigration = ` -- - up Migration to do Up migration -SELECT 1 FROM something` +SELECT 1 FROM something`; const downMigration = ` -- -- -- Down migration to bring DB down -SELECT 2 FROM something` - const content = `${upMigration}${downMigration}` - const { up, down } = getActions(content) - expect(up).to.exist - expect(down).to.exist +SELECT 2 FROM something`; + const content = `${upMigration}${downMigration}`; + const { up, down } = getActions(content); + expect(up).to.exist; + expect(down).to.exist; - const upSql = sinon.spy() - expect(up({ sql: upSql })).to.not.exist - expect(upSql.called).to.be.true - expect(upSql.lastCall.args[0].trim()).to.eql(upMigration.trim()) + const upSql = sinon.spy(); + expect(up({ sql: upSql })).to.not.exist; + expect(upSql.called).to.be.true; + expect(upSql.lastCall.args[0].trim()).to.eql(upMigration.trim()); - const downSql = sinon.spy() - expect(down({ sql: downSql })).to.not.exist - expect(downSql.called).to.be.true - expect(downSql.lastCall.args[0].trim()).to.eql(downMigration.trim()) - }) - }) -}) + const downSql = sinon.spy(); + expect(down({ sql: downSql })).to.not.exist; + expect(downSql.called).to.be.true; + expect(downSql.lastCall.args[0].trim()).to.eql(downMigration.trim()); + }); + }); +}); diff --git a/test/tables-test.ts b/test/tables-test.ts index 18190d7e..1c6f7c2a 100644 --- a/test/tables-test.ts +++ b/test/tables-test.ts @@ -1,60 +1,63 @@ -import { expect } from 'chai' -import * as Tables from '../src/operations/tables' -import { options1, options2 } from './utils' +import { expect } from 'chai'; +import * as Tables from '../src/operations/tables'; +import { options1, options2 } from './utils'; -type CreateTableParams = Parameters> -type DropColumnsParams = Parameters> -type AddConstraintParams = Parameters> +type CreateTableParams = Parameters>; +type DropColumnsParams = Parameters>; +type AddConstraintParams = Parameters>; describe('lib/operations/tables', () => { describe('.create', () => { it('check schemas can be used', () => { - const args: CreateTableParams = [{ schema: 'mySchema', name: 'myTableName' }, { idColumn: 'serial' }] - const sql1 = Tables.createTable(options1)(...args) - const sql2 = Tables.createTable(options2)(...args) + const args: CreateTableParams = [ + { schema: 'mySchema', name: 'myTableName' }, + { idColumn: 'serial' }, + ]; + const sql1 = Tables.createTable(options1)(...args); + const sql2 = Tables.createTable(options2)(...args); expect(sql1).to.equal(`CREATE TABLE "mySchema"."myTableName" ( "idColumn" serial -);`) +);`); expect(sql2).to.equal(`CREATE TABLE "my_schema"."my_table_name" ( "id_column" serial -);`) - }) +);`); + }); it('check shorthands work', () => { - const args: CreateTableParams = ['myTableName', { idColumn: 'id' }] - const sql1 = Tables.createTable(options1)(...args) - const sql2 = Tables.createTable(options2)(...args) + const args: CreateTableParams = ['myTableName', { idColumn: 'id' }]; + const sql1 = Tables.createTable(options1)(...args); + const sql2 = Tables.createTable(options2)(...args); expect(sql1).to.equal(`CREATE TABLE "myTableName" ( "idColumn" serial PRIMARY KEY -);`) +);`); expect(sql2).to.equal(`CREATE TABLE "my_table_name" ( "id_column" serial PRIMARY KEY -);`) - }) +);`); + }); it('check custom shorthands can be used', () => { - const args: CreateTableParams = ['myTableName', { idColumn: 'idTest' }] + const args: CreateTableParams = ['myTableName', { idColumn: 'idTest' }]; const sql1 = Tables.createTable({ ...options1, typeShorthands: { ...options1.typeShorthands, idTest: { type: 'uuid', primaryKey: true }, }, - })(...args) + })(...args); const sql2 = Tables.createTable({ ...options2, typeShorthands: { ...options2.typeShorthands, idTest: { type: 'uuid', primaryKey: true }, }, - })(...args) + })(...args); expect(sql1).to.equal(`CREATE TABLE "myTableName" ( "idColumn" uuid PRIMARY KEY -);`) +);`); expect(sql2).to.equal(`CREATE TABLE "my_table_name" ( "id_column" uuid PRIMARY KEY -);`) - }) +);`); + }); it('check schemas can be used for foreign keys', () => { const args: CreateTableParams = [ @@ -65,16 +68,16 @@ describe('lib/operations/tables', () => { references: { schema: 'schemaA', name: 'tableB' }, }, }, - ] - const sql1 = Tables.createTable(options1)(...args) - const sql2 = Tables.createTable(options2)(...args) + ]; + const sql1 = Tables.createTable(options1)(...args); + const sql2 = Tables.createTable(options2)(...args); expect(sql1).to.equal(`CREATE TABLE "myTableName" ( "parentId" integer REFERENCES "schemaA"."tableB" -);`) +);`); expect(sql2).to.equal(`CREATE TABLE "my_table_name" ( "parent_id" integer REFERENCES "schema_a"."table_b" -);`) - }) +);`); + }); it('check match clause can be used for foreign keys', () => { const args: CreateTableParams = [ @@ -86,16 +89,16 @@ describe('lib/operations/tables', () => { match: 'SIMPLE', }, }, - ] - const sql1 = Tables.createTable(options1)(...args) - const sql2 = Tables.createTable(options2)(...args) + ]; + const sql1 = Tables.createTable(options1)(...args); + const sql2 = Tables.createTable(options2)(...args); expect(sql1).to.equal(`CREATE TABLE "myTableName" ( "parentId" integer REFERENCES "schemaA"."tableB" MATCH SIMPLE -);`) +);`); expect(sql2).to.equal(`CREATE TABLE "my_table_name" ( "parent_id" integer REFERENCES "schema_a"."table_b" MATCH SIMPLE -);`) - }) +);`); + }); it('check defining column can be used for foreign keys', () => { const args: CreateTableParams = [ @@ -103,16 +106,16 @@ describe('lib/operations/tables', () => { { parentId: { type: 'integer', references: 'schemaA.tableB(idColumn)' }, }, - ] - const sql1 = Tables.createTable(options1)(...args) - const sql2 = Tables.createTable(options2)(...args) + ]; + const sql1 = Tables.createTable(options1)(...args); + const sql2 = Tables.createTable(options2)(...args); expect(sql1).to.equal(`CREATE TABLE "myTableName" ( "parentId" integer REFERENCES schemaA.tableB(idColumn) -);`) +);`); expect(sql2).to.equal(`CREATE TABLE "my_table_name" ( "parent_id" integer REFERENCES schemaA.tableB(idColumn) -);`) - }) +);`); + }); it('check multicolumn primary key name does not include schema', () => { const args: CreateTableParams = [ @@ -121,20 +124,20 @@ describe('lib/operations/tables', () => { colA: { type: 'integer', primaryKey: true }, colB: { type: 'varchar', primaryKey: true }, }, - ] - const sql1 = Tables.createTable(options1)(...args) - const sql2 = Tables.createTable(options2)(...args) + ]; + const sql1 = Tables.createTable(options1)(...args); + const sql2 = Tables.createTable(options2)(...args); expect(sql1).to.equal(`CREATE TABLE "mySchema"."myTableName" ( "colA" integer, "colB" varchar, CONSTRAINT "myTableName_pkey" PRIMARY KEY ("colA", "colB") -);`) +);`); expect(sql2).to.equal(`CREATE TABLE "my_schema"."my_table_name" ( "col_a" integer, "col_b" varchar, CONSTRAINT "my_table_name_pkey" PRIMARY KEY ("col_a", "col_b") -);`) - }) +);`); + }); it('check table references work correctly', () => { const args: CreateTableParams = [ @@ -153,20 +156,20 @@ describe('lib/operations/tables', () => { ], }, }, - ] - const sql1 = Tables.createTable(options1)(...args) - const sql2 = Tables.createTable(options2)(...args) + ]; + const sql1 = Tables.createTable(options1)(...args); + const sql2 = Tables.createTable(options2)(...args); expect(sql1).to.equal(`CREATE TABLE "myTableName" ( "colA" integer, "colB" varchar, CONSTRAINT "myTableName_fk_colA_colB" FOREIGN KEY ("colA", "colB") REFERENCES otherTable (A, B) -);`) +);`); expect(sql2).to.equal(`CREATE TABLE "my_table_name" ( "col_a" integer, "col_b" varchar, CONSTRAINT "my_table_name_fk_col_a_col_b" FOREIGN KEY ("col_a", "col_b") REFERENCES otherTable (A, B) -);`) - }) +);`); + }); it('check table unique constraint work correctly', () => { const args: CreateTableParams = [ @@ -180,20 +183,20 @@ describe('lib/operations/tables', () => { unique: ['colA', 'colB'], }, }, - ] - const sql1 = Tables.createTable(options1)(...args) - const sql2 = Tables.createTable(options2)(...args) + ]; + const sql1 = Tables.createTable(options1)(...args); + const sql2 = Tables.createTable(options2)(...args); expect(sql1).to.equal(`CREATE TABLE "myTableName" ( "colA" integer, "colB" varchar, CONSTRAINT "myTableName_uniq_colA_colB" UNIQUE ("colA", "colB") -);`) +);`); expect(sql2).to.equal(`CREATE TABLE "my_table_name" ( "col_a" integer, "col_b" varchar, CONSTRAINT "my_table_name_uniq_col_a_col_b" UNIQUE ("col_a", "col_b") -);`) - }) +);`); + }); it('check table unique constraint work correctly for string', () => { const args: CreateTableParams = [ @@ -207,20 +210,20 @@ describe('lib/operations/tables', () => { unique: 'colA', }, }, - ] - const sql1 = Tables.createTable(options1)(...args) - const sql2 = Tables.createTable(options2)(...args) + ]; + const sql1 = Tables.createTable(options1)(...args); + const sql2 = Tables.createTable(options2)(...args); expect(sql1).to.equal(`CREATE TABLE "myTableName" ( "colA" integer, "colB" varchar, CONSTRAINT "myTableName_uniq_colA" UNIQUE ("colA") -);`) +);`); expect(sql2).to.equal(`CREATE TABLE "my_table_name" ( "col_a" integer, "col_b" varchar, CONSTRAINT "my_table_name_uniq_col_a" UNIQUE ("col_a") -);`) - }) +);`); + }); it('check table unique constraint work correctly for array of arrays', () => { const args: CreateTableParams = [ @@ -235,24 +238,24 @@ describe('lib/operations/tables', () => { unique: [['colA', 'colB'], 'colC'], }, }, - ] - const sql1 = Tables.createTable(options1)(...args) - const sql2 = Tables.createTable(options2)(...args) + ]; + const sql1 = Tables.createTable(options1)(...args); + const sql2 = Tables.createTable(options2)(...args); expect(sql1).to.equal(`CREATE TABLE "myTableName" ( "colA" integer, "colB" varchar, "colC" varchar, CONSTRAINT "myTableName_uniq_colA_colB" UNIQUE ("colA", "colB"), CONSTRAINT "myTableName_uniq_colC" UNIQUE ("colC") -);`) +);`); expect(sql2).to.equal(`CREATE TABLE "my_table_name" ( "col_a" integer, "col_b" varchar, "col_c" varchar, CONSTRAINT "my_table_name_uniq_col_a_col_b" UNIQUE ("col_a", "col_b"), CONSTRAINT "my_table_name_uniq_col_c" UNIQUE ("col_c") -);`) - }) +);`); + }); it('creates comments on foreign keys', () => { const args: CreateTableParams = [ @@ -269,20 +272,20 @@ describe('lib/operations/tables', () => { }, }, }, - ] - const sql1 = Tables.createTable(options1)(...args) - const sql2 = Tables.createTable(options2)(...args) + ]; + const sql1 = Tables.createTable(options1)(...args); + const sql2 = Tables.createTable(options2)(...args); expect(sql1).to.equal(`CREATE TABLE "myTableName" ( "colA" integer, CONSTRAINT "myTableName_fk_colA" FOREIGN KEY ("colA") REFERENCES "otherTable" ); -COMMENT ON CONSTRAINT "myTableName_fk_colA" ON "myTableName" IS $pga$example comment$pga$;`) +COMMENT ON CONSTRAINT "myTableName_fk_colA" ON "myTableName" IS $pga$example comment$pga$;`); expect(sql2).to.equal(`CREATE TABLE "my_table_name" ( "col_a" integer, CONSTRAINT "my_table_name_fk_col_a" FOREIGN KEY ("col_a") REFERENCES "other_table" ); -COMMENT ON CONSTRAINT "my_table_name_fk_col_a" ON "my_table_name" IS $pga$example comment$pga$;`) - }) +COMMENT ON CONSTRAINT "my_table_name_fk_col_a" ON "my_table_name" IS $pga$example comment$pga$;`); + }); it('creates comments on column foreign keys', () => { const args: CreateTableParams = [ @@ -300,22 +303,22 @@ COMMENT ON CONSTRAINT "my_table_name_fk_col_a" ON "my_table_name" IS $pga$exampl referencesConstraintComment: 'fk b comment', }, }, - ] - const sql1 = Tables.createTable(options1)(...args) - const sql2 = Tables.createTable(options2)(...args) + ]; + const sql1 = Tables.createTable(options1)(...args); + const sql2 = Tables.createTable(options2)(...args); expect(sql1).to.equal(`CREATE TABLE "myTableName" ( "colA" integer CONSTRAINT "myTableName_fk_colA" REFERENCES otherTable (a), "colB" integer CONSTRAINT "fkColB" REFERENCES "otherTableTwo" ); COMMENT ON CONSTRAINT "myTableName_fk_colA" ON "myTableName" IS $pga$fk a comment$pga$; -COMMENT ON CONSTRAINT "fkColB" ON "myTableName" IS $pga$fk b comment$pga$;`) +COMMENT ON CONSTRAINT "fkColB" ON "myTableName" IS $pga$fk b comment$pga$;`); expect(sql2).to.equal(`CREATE TABLE "my_table_name" ( "col_a" integer CONSTRAINT "my_table_name_fk_col_a" REFERENCES otherTable (a), "col_b" integer CONSTRAINT "fk_col_b" REFERENCES "other_table_two" ); COMMENT ON CONSTRAINT "my_table_name_fk_col_a" ON "my_table_name" IS $pga$fk a comment$pga$; -COMMENT ON CONSTRAINT "fk_col_b" ON "my_table_name" IS $pga$fk b comment$pga$;`) - }) +COMMENT ON CONSTRAINT "fk_col_b" ON "my_table_name" IS $pga$fk b comment$pga$;`); + }); it('creates no comments on unnamed constraints', () => { const args: CreateTableParams = [ @@ -329,46 +332,58 @@ COMMENT ON CONSTRAINT "fk_col_b" ON "my_table_name" IS $pga$fk b comment$pga$;`) comment: 'example comment', }, }, - ] - expect(() => Tables.createTable(options1)(...args)).to.throw('cannot comment on unspecified constraints') - expect(() => Tables.createTable(options2)(...args)).to.throw('cannot comment on unspecified constraints') - }) - }) + ]; + expect(() => Tables.createTable(options1)(...args)).to.throw( + 'cannot comment on unspecified constraints' + ); + expect(() => Tables.createTable(options2)(...args)).to.throw( + 'cannot comment on unspecified constraints' + ); + }); + }); describe('.dropColumns', () => { it('check multiple columns can be dropped', () => { - const args: DropColumnsParams = ['myTableName', ['colC1', 'colC2']] - const sql1 = Tables.dropColumns(options1)(...args) - const sql2 = Tables.dropColumns(options2)(...args) + const args: DropColumnsParams = ['myTableName', ['colC1', 'colC2']]; + const sql1 = Tables.dropColumns(options1)(...args); + const sql2 = Tables.dropColumns(options2)(...args); expect(sql1).to.equal(`ALTER TABLE "myTableName" DROP "colC1", - DROP "colC2";`) + DROP "colC2";`); expect(sql2).to.equal(`ALTER TABLE "my_table_name" DROP "col_c1", - DROP "col_c2";`) - }) - }) + DROP "col_c2";`); + }); + }); describe('.addConstraint', () => { it('works with strings', () => { - const args: AddConstraintParams = ['myTableName', 'myConstraintName', 'CHECK name IS NOT NULL'] - const sql1 = Tables.addConstraint(options1)(...args) - const sql2 = Tables.addConstraint(options2)(...args) + const args: AddConstraintParams = [ + 'myTableName', + 'myConstraintName', + 'CHECK name IS NOT NULL', + ]; + const sql1 = Tables.addConstraint(options1)(...args); + const sql2 = Tables.addConstraint(options2)(...args); expect(sql1).to.equal(`ALTER TABLE "myTableName" - ADD CONSTRAINT "myConstraintName" CHECK name IS NOT NULL;`) + ADD CONSTRAINT "myConstraintName" CHECK name IS NOT NULL;`); expect(sql2).to.equal(`ALTER TABLE "my_table_name" - ADD CONSTRAINT "my_constraint_name" CHECK name IS NOT NULL;`) - }) + ADD CONSTRAINT "my_constraint_name" CHECK name IS NOT NULL;`); + }); it('does not add contraint name if not defined', () => { - const args: AddConstraintParams = ['myTableName', null, 'CHECK name IS NOT NULL'] - const sql1 = Tables.addConstraint(options1)(...args) - const sql2 = Tables.addConstraint(options2)(...args) + const args: AddConstraintParams = [ + 'myTableName', + null, + 'CHECK name IS NOT NULL', + ]; + const sql1 = Tables.addConstraint(options1)(...args); + const sql2 = Tables.addConstraint(options2)(...args); expect(sql1).to.equal(`ALTER TABLE "myTableName" - ADD CHECK name IS NOT NULL;`) + ADD CHECK name IS NOT NULL;`); expect(sql2).to.equal(`ALTER TABLE "my_table_name" - ADD CHECK name IS NOT NULL;`) - }) + ADD CHECK name IS NOT NULL;`); + }); it('can create comments', () => { const args: AddConstraintParams = [ @@ -378,15 +393,15 @@ COMMENT ON CONSTRAINT "fk_col_b" ON "my_table_name" IS $pga$fk b comment$pga$;`) primaryKey: 'colA', comment: 'this is an important primary key', }, - ] - const sql1 = Tables.addConstraint(options1)(...args) - const sql2 = Tables.addConstraint(options2)(...args) + ]; + const sql1 = Tables.addConstraint(options1)(...args); + const sql2 = Tables.addConstraint(options2)(...args); expect(sql1).to.equal(`ALTER TABLE "myTableName" ADD CONSTRAINT "myConstraintName" PRIMARY KEY ("colA"); -COMMENT ON CONSTRAINT "myConstraintName" ON "myTableName" IS $pga$this is an important primary key$pga$;`) +COMMENT ON CONSTRAINT "myConstraintName" ON "myTableName" IS $pga$this is an important primary key$pga$;`); expect(sql2).to.equal(`ALTER TABLE "my_table_name" ADD CONSTRAINT "my_constraint_name" PRIMARY KEY ("col_a"); -COMMENT ON CONSTRAINT "my_constraint_name" ON "my_table_name" IS $pga$this is an important primary key$pga$;`) - }) - }) -}) +COMMENT ON CONSTRAINT "my_constraint_name" ON "my_table_name" IS $pga$this is an important primary key$pga$;`); + }); + }); +}); diff --git a/test/ts/customRunner.ts b/test/ts/customRunner.ts index 10a60ce3..07ed5916 100644 --- a/test/ts/customRunner.ts +++ b/test/ts/customRunner.ts @@ -1,14 +1,16 @@ -import { resolve } from 'path' -import { Client } from 'pg' -import runner, { RunnerOption } from '../../dist' +import { resolve } from 'path'; +import { Client } from 'pg'; +import runner, { RunnerOption } from '../../dist'; type TestOptions = { - count?: number - expectedUpLength?: number - expectedDownLength?: number -} + count?: number; + expectedUpLength?: number; + expectedDownLength?: number; +}; -type Options = ({ databaseUrl: string } & TestOptions) | ({ dbClient: Client } & TestOptions) +type Options = + | ({ databaseUrl: string } & TestOptions) + | ({ dbClient: Client } & TestOptions); /* eslint-disable no-console */ // eslint-disable-next-line import/prefer-default-export @@ -19,31 +21,35 @@ export const run = async (options: Options): Promise => { expectedUpLength: 2, expectedDownLength: 2, ...options, - } + }; try { const upResult = await runner({ ...opts, direction: 'up', - }) + }); if (upResult.length !== opts.expectedUpLength) { - console.error(`There should be exactly ${opts.expectedUpLength} migrations processed`) - return false + console.error( + `There should be exactly ${opts.expectedUpLength} migrations processed` + ); + return false; } - console.log('Up success') - console.log(upResult) + console.log('Up success'); + console.log(upResult); const downResult = await runner({ ...opts, direction: 'down', - }) + }); if (downResult.length !== opts.expectedDownLength) { - console.error(`There should be exactly ${opts.expectedDownLength} migrations processed`) - return false + console.error( + `There should be exactly ${opts.expectedDownLength} migrations processed` + ); + return false; } - console.log('Down success') - console.log(downResult) - return true + console.log('Down success'); + console.log(downResult); + return true; } catch (err) { - console.error(err) - return false + console.error(err); + return false; } -} +}; diff --git a/test/ts/customRunnerDBClient.ts b/test/ts/customRunnerDBClient.ts index 5d933adb..fd678890 100644 --- a/test/ts/customRunnerDBClient.ts +++ b/test/ts/customRunnerDBClient.ts @@ -1,13 +1,13 @@ -import { Client } from 'pg' -import { run } from './customRunner' +import { Client } from 'pg'; +import { run } from './customRunner'; async function start() { - process.exitCode = 1 - const dbClient = new Client(process.env.DATABASE_URL) - await dbClient.connect() - const result = await run({ dbClient, count: Infinity }) + process.exitCode = 1; + const dbClient = new Client(process.env.DATABASE_URL); + await dbClient.connect(); + const result = await run({ dbClient, count: Infinity }); // dbClient.end() - process.exit(result === true ? 0 : 1) + process.exit(result === true ? 0 : 1); } -start() +start(); diff --git a/test/ts/customRunnerDBUrl.ts b/test/ts/customRunnerDBUrl.ts index 71f12ac6..b2398cab 100644 --- a/test/ts/customRunnerDBUrl.ts +++ b/test/ts/customRunnerDBUrl.ts @@ -1,9 +1,12 @@ -import { run } from './customRunner' +import { run } from './customRunner'; async function start() { - process.exitCode = 1 - const result = await run({ databaseUrl: String(process.env.DATABASE_URL), count: Infinity }) - process.exit(result === true ? 0 : 1) + process.exitCode = 1; + const result = await run({ + databaseUrl: String(process.env.DATABASE_URL), + count: Infinity, + }); + process.exit(result === true ? 0 : 1); } -start() +start(); diff --git a/test/ts/customRunnerUndefCount.ts b/test/ts/customRunnerUndefCount.ts index 71b43821..56a1aadf 100644 --- a/test/ts/customRunnerUndefCount.ts +++ b/test/ts/customRunnerUndefCount.ts @@ -1,13 +1,13 @@ -import { run } from './customRunner' +import { run } from './customRunner'; async function start() { - process.exitCode = 1 + process.exitCode = 1; const result = await run({ databaseUrl: String(process.env.DATABASE_URL), expectedUpLength: 2, expectedDownLength: 1, - }) - process.exit(result === true ? 0 : 1) + }); + process.exit(result === true ? 0 : 1); } -start() +start(); diff --git a/test/ts/migrations/1-test-migration.ts b/test/ts/migrations/1-test-migration.ts index 9d46687c..c17ade4f 100644 --- a/test/ts/migrations/1-test-migration.ts +++ b/test/ts/migrations/1-test-migration.ts @@ -1,6 +1,6 @@ -import { MigrationBuilder, ColumnDefinitions } from '../../../dist' +import { ColumnDefinitions, MigrationBuilder } from '../../../dist'; -export const shorthands: ColumnDefinitions | undefined = undefined +export const shorthands: ColumnDefinitions | undefined = undefined; export async function up(pgm: MigrationBuilder): Promise { pgm.createTable('t1', { @@ -11,7 +11,7 @@ export async function up(pgm: MigrationBuilder): Promise { notNull: true, default: pgm.func('current_timestamp'), }, - }) + }); pgm.createTable('t2', { id: 'id', @@ -21,5 +21,5 @@ export async function up(pgm: MigrationBuilder): Promise { notNull: true, default: { literal: true, value: 'current_timestamp' }, }, - }) + }); } diff --git a/test/ts/migrations/2-test-migration.ts b/test/ts/migrations/2-test-migration.ts index 68240beb..8bbc22d9 100644 --- a/test/ts/migrations/2-test-migration.ts +++ b/test/ts/migrations/2-test-migration.ts @@ -1,6 +1,6 @@ -import { MigrationBuilder, ColumnDefinitions } from '../../../dist' +import { ColumnDefinitions, MigrationBuilder } from '../../../dist'; -export const shorthands: ColumnDefinitions | undefined = undefined +export const shorthands: ColumnDefinitions | undefined = undefined; export async function up(pgm: MigrationBuilder): Promise { pgm.createTable('t3', { @@ -11,5 +11,5 @@ export async function up(pgm: MigrationBuilder): Promise { notNull: true, default: pgm.func('current_timestamp'), }, - }) + }); } diff --git a/test/utils-test.ts b/test/utils-test.ts index ba3c0958..6ca113e0 100644 --- a/test/utils-test.ts +++ b/test/utils-test.ts @@ -1,145 +1,155 @@ -import { expect } from 'chai' -import { escapeValue, applyType, createSchemalize, createTransformer, StringIdGenerator } from '../src/utils' -import { ColumnDefinitions } from '../src/operations/tablesTypes' -import PgLiteral from '../src/operations/PgLiteral' -import { PgLiteralValue } from '../src/operations/generalTypes' +import { expect } from 'chai'; +import { PgLiteralValue } from '../src/operations/generalTypes'; +import PgLiteral from '../src/operations/PgLiteral'; +import { ColumnDefinitions } from '../src/operations/tablesTypes'; +import { + applyType, + createSchemalize, + createTransformer, + escapeValue, + StringIdGenerator, +} from '../src/utils'; describe('lib/utils', () => { describe('.escapeValue', () => { it("parse null to 'NULL'", () => { - const value = null + const value = null; - expect(escapeValue(value)).to.equal('NULL') - }) + expect(escapeValue(value)).to.equal('NULL'); + }); it('parse boolean to string', () => { - const value = true + const value = true; - expect(escapeValue(value)).to.equal('true') - }) + expect(escapeValue(value)).to.equal('true'); + }); it('escape string', () => { - const value = '#escape_me' + const value = '#escape_me'; - expect(escapeValue(value)).to.equal('$pga$#escape_me$pga$') - }) + expect(escapeValue(value)).to.equal('$pga$#escape_me$pga$'); + }); it('keep number as is', () => { - const value = 77.7 + const value = 77.7; - expect(escapeValue(value)).to.equal(77.7) - }) + expect(escapeValue(value)).to.equal(77.7); + }); it('parse array to ARRAY constructor syntax string', () => { - const value = [[1], [2]] - const value2 = [['a'], ['b']] + const value = [[1], [2]]; + const value2 = [['a'], ['b']]; - expect(escapeValue(value)).to.equal('ARRAY[[1],[2]]') - expect(escapeValue(value2)).to.equal('ARRAY[[$pga$a$pga$],[$pga$b$pga$]]') - }) + expect(escapeValue(value)).to.equal('ARRAY[[1],[2]]'); + expect(escapeValue(value2)).to.equal( + 'ARRAY[[$pga$a$pga$],[$pga$b$pga$]]' + ); + }); it('parse PgLiteral to unescaped string', () => { - const value = PgLiteral.create('@l| { - const value: PgLiteralValue = { literal: true, value: '@l| { - const value = PgLiteral.create('@l| { - const value = undefined + const value = undefined; - expect(escapeValue(value)).to.equal('') - }) - }) + expect(escapeValue(value)).to.equal(''); + }); + }); describe('.applyType', () => { it('convert string', () => { - const type = 'type' + const type = 'type'; - expect(applyType(type)).to.eql({ type }) - }) + expect(applyType(type)).to.eql({ type }); + }); it('apply id shorthand', () => { - expect(applyType('id')).to.eql({ type: 'serial', primaryKey: true }) - }) + expect(applyType('id')).to.eql({ type: 'serial', primaryKey: true }); + }); it('apply shorthand', () => { - const shorthandName = 'type' - const shorthandDefinition = { type: 'integer', defaultValue: 1 } - expect(applyType(shorthandName, { [shorthandName]: shorthandDefinition })).to.eql(shorthandDefinition) - }) + const shorthandName = 'type'; + const shorthandDefinition = { type: 'integer', defaultValue: 1 }; + expect( + applyType(shorthandName, { [shorthandName]: shorthandDefinition }) + ).to.eql(shorthandDefinition); + }); it('apply recursive shorthand', () => { const shorthands: ColumnDefinitions = { ref: { type: `integer`, onDelete: `CASCADE` }, user: { type: `ref`, references: `users` }, - } + }; expect(applyType('user', shorthands)).to.eql({ type: `integer`, onDelete: `CASCADE`, references: `users`, - }) - }) + }); + }); it('detect cycle in recursive shorthand', () => { const shorthands: ColumnDefinitions = { ref: { type: `user`, onDelete: `CASCADE` }, user: { type: `ref`, references: `users` }, - } - expect(() => applyType('user', shorthands)).to.throw() - }) - }) + }; + expect(() => applyType('user', shorthands)).to.throw(); + }); + }); describe('.createTransformer', () => { it('handle string and Name', () => { - const t = createTransformer(createSchemalize(true, true)) + const t = createTransformer(createSchemalize(true, true)); expect( t('CREATE INDEX {string} ON {name} (id);', { string: 'string', name: { schema: 'schema', name: 'name' }, - }), - ).to.equal('CREATE INDEX "string" ON "schema"."name" (id);') - }) + }) + ).to.equal('CREATE INDEX "string" ON "schema"."name" (id);'); + }); it('Do not escape PgLiteral', () => { - const t = createTransformer(createSchemalize(true, true)) + const t = createTransformer(createSchemalize(true, true)); expect( t('INSERT INTO s (id) VALUES {values};', { values: new PgLiteral(['s1', 's2'].map((e) => `('${e}')`).join(', ')), - }), - ).to.equal("INSERT INTO s (id) VALUES ('s1'), ('s2');") - }) + }) + ).to.equal("INSERT INTO s (id) VALUES ('s1'), ('s2');"); + }); it('Can use number', () => { - const t = createTransformer(createSchemalize(true, true)) + const t = createTransformer(createSchemalize(true, true)); expect( t('INSERT INTO s (id) VALUES ({values});', { values: 1, - }), - ).to.equal('INSERT INTO s (id) VALUES (1);') - }) - }) + }) + ).to.equal('INSERT INTO s (id) VALUES (1);'); + }); + }); describe('.StringIdGenerator', () => { it('generates correct sequence', () => { - const chars = 'abcd' + const chars = 'abcd'; - const ids = new StringIdGenerator(chars) + const ids = new StringIdGenerator(chars); const results = [ 'a', 'b', @@ -165,10 +175,10 @@ describe('lib/utils', () => { 'aab', 'aac', 'aad', - ] + ]; results.forEach((res) => { - expect(ids.next()).to.equal(res) - }) - }) - }) -}) + expect(ids.next()).to.equal(res); + }); + }); + }); +}); diff --git a/test/utils.ts b/test/utils.ts index bd8e6209..0259e83d 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -1,16 +1,16 @@ -import { createSchemalize } from '../src/utils' -import { MigrationOptions } from '../src/types' +import { MigrationOptions } from '../src/types'; +import { createSchemalize } from '../src/utils'; export const options1: MigrationOptions = { typeShorthands: {}, schemalize: createSchemalize(false, false), literal: createSchemalize(false, true), logger: console, -} +}; export const options2: MigrationOptions = { typeShorthands: {}, schemalize: createSchemalize(true, false), literal: createSchemalize(true, true), logger: console, -} +};