pg-migrations
Advanced tools
Comparing version 0.0.1 to 0.1.0
@@ -17,2 +17,8 @@ #!/usr/bin/env node | ||
const info = require('../package.json'); | ||
function list(str) { | ||
if (typeof str === 'string') { | ||
return str.split(/\s*,\s*/g); | ||
} | ||
return []; | ||
} | ||
program | ||
@@ -27,3 +33,4 @@ .version(info.version) | ||
.option('-P, --prompt-password', 'prompt for database password') | ||
.option('-s, --generate-script', 'output sql script instead of executing the migration'); | ||
.option('-s, --generate-script', 'output sql script instead of executing the migration') | ||
.option('--context [contexts]', 'changeset contexts to execute'); | ||
program.parse(process.argv); | ||
@@ -48,2 +55,5 @@ const processCommand = function processCommand(schema, ...args) { | ||
} | ||
if (this.context) { | ||
this.context = list(this.context); | ||
} | ||
if (this.promptPassword) { | ||
@@ -63,6 +73,6 @@ const prompt = new Promise((resolve, reject) => { | ||
if (this.generateScript) { | ||
console.log(yield migration.generateScript(repo)); | ||
console.log(yield migration.generateScript(repo, { context: this.context })); | ||
} | ||
else { | ||
const changes = yield migration.execute(repo); | ||
const changes = yield migration.execute(repo, { context: this.context }); | ||
console.log(`${changes.length} ${changes.length === 1 ? 'change' : 'changes'} applied`); | ||
@@ -69,0 +79,0 @@ } |
import Changeset from './changeset'; | ||
import ChangelogRepository from './data/changelog-repository'; | ||
export interface IOptions { | ||
context?: string[]; | ||
} | ||
export default class Migration { | ||
changesets: Changeset[]; | ||
constructor(); | ||
execute(repository: ChangelogRepository): Promise<Changeset[]>; | ||
generateScript(repository: ChangelogRepository): Promise<string>; | ||
execute(repository: ChangelogRepository, options?: IOptions): Promise<Changeset[]>; | ||
generateScript(repository: ChangelogRepository, options?: IOptions): Promise<string>; | ||
static load(filename: string): Promise<Migration>; | ||
private validate(repository); | ||
private filterChangesets(repository, options); | ||
} |
@@ -33,2 +33,10 @@ "use strict"; | ||
} | ||
function listContainsAny(list1, list2) { | ||
for (const item of list1) { | ||
if (list2.indexOf(item) !== -1) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
class Migration { | ||
@@ -38,3 +46,3 @@ constructor() { | ||
} | ||
execute(repository) { | ||
execute(repository, options) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
@@ -46,8 +54,7 @@ const hasLock = yield repository.aquireLock(); | ||
try { | ||
const validation = yield this.validate(repository); | ||
const changesetsToExecute = validation.filter((v) => v.validation.shouldExecute).map((r) => r.changeset); | ||
for (const changeset of changesetsToExecute) { | ||
const changesets = yield this.filterChangesets(repository, options); | ||
for (const changeset of changesets) { | ||
yield repository.executeChangeset(changeset); | ||
} | ||
return changesetsToExecute; | ||
return changesets; | ||
} | ||
@@ -59,7 +66,6 @@ finally { | ||
} | ||
generateScript(repository) { | ||
generateScript(repository, options) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const validation = yield this.validate(repository); | ||
const changesetsToExecute = validation.filter((v) => v.validation.shouldExecute).map((r) => r.changeset); | ||
return changesetsToExecute.map((c) => `-- ${c.formatName()}\n${c.script}`).join('\n\n'); | ||
const changesets = yield this.filterChangesets(repository, options); | ||
return changesets.map((c) => `-- ${c.formatName()}\n${c.script}`).join('\n\n'); | ||
}); | ||
@@ -93,3 +99,3 @@ } | ||
} | ||
validate(repository) { | ||
filterChangesets(repository, options) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
@@ -102,3 +108,5 @@ const validation = yield Promise.all(this.changesets.map((changeset) => __awaiter(this, void 0, void 0, function* () { | ||
}))); | ||
const messages = validation.filter((v) => v.validation.messages.length) | ||
const { context = null } = options || {}; | ||
const messages = validation | ||
.filter((v) => v.validation.messages.length) | ||
.map((v) => `${v.changeset.formatName()}\n${v.validation.messages.map((m) => ` ${m}`).join('\n')}`); | ||
@@ -109,3 +117,7 @@ const statements = []; | ||
} | ||
return validation; | ||
return validation.filter((v) => v.validation.shouldExecute) | ||
.filter((v) => !context | ||
|| !v.changeset.context | ||
|| listContainsAny(v.changeset.context.split(/\s*,\s*/), context)) | ||
.map((v) => v.changeset); | ||
}); | ||
@@ -112,0 +124,0 @@ } |
{ | ||
"name": "pg-migrations", | ||
"version": "0.0.1", | ||
"version": "0.1.0", | ||
"description": "Postgres database migration utility", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
@@ -11,2 +11,63 @@ # Postgres Migrations | ||
## Why? | ||
`liquibase` provides many ways of managing migrations including `xml`, `json`, `yaml`, and `sql` formats for multiple database engines. However, these options can add to complexity, and unfortunately requires `java` to run. | ||
The purpose of `pg-migrations` is to provide a simpler way (with fewer options) for managing `postgresql` database migrations without requiring `java`. | ||
## How it works | ||
`pg-migrations` works with either a *schema* configuration file (either `yaml`, or `json`), or a directory. | ||
### Schema configuration file | ||
The schema configuration file lists all the files to execute as part of the migration. Files can be defined as `glob` expressions and files matching the `glob` expression are executed in *alpha numeric* order (i.e. `1` < `2` < `10`). | ||
Example schema configuration file (`example/database/schema.yml`): | ||
```yaml | ||
files: | ||
- '**/*.sql' | ||
``` | ||
### Directory | ||
When a directory is used as an input to the migration, it effectively uses the same configuration as provided above (i.e. executes all `sql` files in the directory in *alpha numeric* order). | ||
### Migration file format | ||
A migration file must start with `--migration` on the first line and contains one or many `changeset`s (`sql` statements) preceded by a `--changeset` comment. | ||
### Changeset comment format | ||
A `changeset` comment takes the following format: | ||
```sql | ||
--changeset [changeset name] [type:<once|always|change>] [context:<comma,separated,list>] | ||
``` | ||
Where: | ||
* `changeset name` - (optional) name of the changeset, must be unique within the file | ||
* `type` - (optional) execution type of the changeset, must be either execute `once`, `always`, or on `change` | ||
* defaults to `once` | ||
* note that a `once` migration script cannot be modified after it has already been executed (will result in an error on subsequent migrations) | ||
* `context` - (optional) list of contexts that the changeset should be executed under | ||
* default behaviour is to execute under *all* contexts | ||
* context is specified using the `--context` command line argument, the omission of the `--context` argument implies all contexts will be executed | ||
Example: | ||
```sql | ||
--migration | ||
--changeset create table | ||
create table my_table ( | ||
val text | ||
); | ||
--changeset test data context:test | ||
insert into my_table (val) | ||
values ('test data'); | ||
``` | ||
## Usage | ||
@@ -28,2 +89,3 @@ | ||
-s, --generate-script output sql script instead of executing the migration | ||
--context [contexts] changeset contexts to execute | ||
``` | ||
@@ -30,0 +92,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
44497
569
96