murmuration 1.0.22 → 1.0.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -2
- package/bin/migrate/customMigration.js +42 -0
- package/bin/migrate/migrations.js +45 -24
- package/bin/migrate/operation/applyMigrations.js +2 -2
- package/bin/migrate.js +8 -1
- package/index.js +4 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,8 +4,8 @@ Database connections, transactions and migrations.
|
|
|
4
4
|
|
|
5
5
|
There are two specific packages that you should make use of instead this one:
|
|
6
6
|
|
|
7
|
-
* [
|
|
8
|
-
* [
|
|
7
|
+
* [Murmuration-MariaDB](https://github.com/djalbat/murmuration-mariadb)
|
|
8
|
+
* [Murmuration-PostGreSQL](https://github.com/djalbat/murmuration-postgresql)
|
|
9
9
|
|
|
10
10
|
This readme file largely pertains to both, although there are also specific instructions given in readme file for each.
|
|
11
11
|
|
|
@@ -255,6 +255,58 @@ Migrations must obviously never, ever be changed once they have been committed.
|
|
|
255
255
|
|
|
256
256
|
If used with care, this migration functionality is wholly effective in the aforementioned use case of a single database instance allied with one or possibly many application instances.
|
|
257
257
|
|
|
258
|
+
### Custom migrations
|
|
259
|
+
|
|
260
|
+
As well as migrations based on SQL files it is possible to add custom migrations. These are identified by custom text files that sit next to the SQL files in the migrations directory. They must have the following format:
|
|
261
|
+
|
|
262
|
+
```
|
|
263
|
+
12-CUSTOM.txt
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
That is, the file name must start with a contiguous version number followed by a hyphen, but end with `CUSTOM` and have a `.txt` extension. Any other format will be ignored and will also lead to all further migrations being ignored. The contents of these files can be left empty or can contain information pertinent to the custom migration.
|
|
267
|
+
|
|
268
|
+
To create a custom migration, extend the CustomMigration class and fill out the `apply()` method as needed. This example requires the CustomMigration class from the Murmuration-PostGreSQL package but the same holds for the Murmuration-MariaDB package:
|
|
269
|
+
|
|
270
|
+
```
|
|
271
|
+
const { CustomMigration } = require("murmuration-postgresql");
|
|
272
|
+
|
|
273
|
+
class IdentifierCustomMigration extends CustomMigration {
|
|
274
|
+
apply(connection, callback) {
|
|
275
|
+
...
|
|
276
|
+
|
|
277
|
+
callback(error);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
static fromFilePath(filePath) {
|
|
281
|
+
const identifierCustomMigration = new IdentifierCustomMigration(filePath);
|
|
282
|
+
|
|
283
|
+
return identifierCustomMigration;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
Note that the `apply()` method takes `connection` and `callback` arguments. The latter must be called with a boolean `error` argument when the migration completes. Also note the format of the static `fromFilePath()` factory method. The file path of the text file is available via a standard `getFilePath()` method, by the way.
|
|
288
|
+
|
|
289
|
+
Custom migrations must be collected together into a map, the keys of which are precisely the file names of the custom text files in the migrations SQL directory. For example:
|
|
290
|
+
|
|
291
|
+
```
|
|
292
|
+
const IdentifierCustomMigration = rquire("./identifierCustomMigration");
|
|
293
|
+
|
|
294
|
+
const CustomMigrationMap = {
|
|
295
|
+
"13-CUSTOM.txt" : IdentifierCustomMigration
|
|
296
|
+
};
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
This map should be passed as an optional third argument to the `migrate()` function as follows:
|
|
300
|
+
|
|
301
|
+
```
|
|
302
|
+
migrate(configuration, migrationsDirectoryPath, CustomMigrationMap (error) => {
|
|
303
|
+
|
|
304
|
+
...
|
|
305
|
+
});
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
It is possible to use the same custom migration class for multiple custom migrations with the contents of the custom text files dictating the behaviours of at each invocation.
|
|
309
|
+
|
|
258
310
|
## Contact
|
|
259
311
|
|
|
260
312
|
- james.smith@djalbat.com
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { arrayUtilities } = require("necessary");
|
|
4
|
+
|
|
5
|
+
const { second } = arrayUtilities;
|
|
6
|
+
|
|
7
|
+
class CustomMigration {
|
|
8
|
+
constructor(filePath) {
|
|
9
|
+
this.filePath = filePath;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
getFilePath() {
|
|
13
|
+
return this.filePath;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getVersion() {
|
|
17
|
+
const matches = this.filePath.match(/(\d+)-.+$/),
|
|
18
|
+
secondMatch = second(matches),
|
|
19
|
+
version = secondMatch; ///
|
|
20
|
+
|
|
21
|
+
return version;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
apply(connection, callback) {
|
|
25
|
+
const log = connection.getLog(),
|
|
26
|
+
version = this.getVersion();
|
|
27
|
+
|
|
28
|
+
log.info(`Applying custom migration version ${version}...`);
|
|
29
|
+
|
|
30
|
+
const error = true;
|
|
31
|
+
|
|
32
|
+
callback(error);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static fromFilePath(filePath) {
|
|
36
|
+
const customMigration = new CustomMigration(filePath);
|
|
37
|
+
|
|
38
|
+
return customMigration;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = CustomMigration;
|
|
@@ -18,33 +18,54 @@ class Migrations {
|
|
|
18
18
|
return migration;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
static
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
21
|
+
static fromCustomMigrationMapAndMigrationsDirectoryPath(CustomMigrationMap, migrationsDirectoryPath) {
|
|
22
|
+
const map = {},
|
|
23
|
+
entryNames = readDirectory(migrationsDirectoryPath),
|
|
24
|
+
sqlFileNames = sqlFileNamesFromEntryNames(entryNames),
|
|
25
|
+
customTextFileNames = customTextFileNamesFromEEntryNames(entryNames);
|
|
26
|
+
|
|
27
|
+
sqlFileNames.forEach((sqlFileName) => {
|
|
28
|
+
const filePath = concatenatePaths(migrationsDirectoryPath, sqlFileName),
|
|
29
|
+
migration = Migration.fromFilePath(filePath),
|
|
30
|
+
version = migration.getVersion();
|
|
31
|
+
|
|
32
|
+
map[version] = migration;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
customTextFileNames.forEach((customTextFileName) => {
|
|
36
|
+
const filePath = concatenatePaths(migrationsDirectoryPath, customTextFileName),
|
|
37
|
+
CustomMigration = CustomMigrationMap[customTextFileName],
|
|
38
|
+
customMigration = CustomMigration.fromFilePath(filePath),
|
|
39
|
+
migration = customMigration, ///
|
|
40
|
+
version = migration.getVersion();
|
|
41
|
+
|
|
42
|
+
map[version] = migration;
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const migrations = new Migrations(map);
|
|
45
46
|
|
|
46
47
|
return migrations;
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
module.exports = Migrations;
|
|
52
|
+
|
|
53
|
+
function customTextFileNamesFromEEntryNames(entryNames) { return fileNamesFromEntryNames(entryNames, (entryName) => /.+CUSTOM\.txt$/.test(entryName)); }
|
|
54
|
+
|
|
55
|
+
function sqlFileNamesFromEntryNames(entryNames) { return fileNamesFromEntryNames(entryNames, (entryName) => /.+\.sql$/.test(entryName)); }
|
|
56
|
+
|
|
57
|
+
function fileNamesFromEntryNames(entryNames, test) {
|
|
58
|
+
const fileNames = entryNames.reduce((fileNames, entryName) => {
|
|
59
|
+
const entryNameSQLFileName = test(entryName);
|
|
60
|
+
|
|
61
|
+
if (entryNameSQLFileName) {
|
|
62
|
+
const fileName = entryName;
|
|
63
|
+
|
|
64
|
+
fileNames.push(fileName);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return fileNames;
|
|
68
|
+
}, []);
|
|
69
|
+
|
|
70
|
+
return fileNames;
|
|
71
|
+
}
|
|
@@ -11,8 +11,8 @@ const { first } = arrayUtilities,
|
|
|
11
11
|
{ whilst } = asynchronousUtilities;
|
|
12
12
|
|
|
13
13
|
function applyMigrationsOperation(next, done, context) {
|
|
14
|
-
const { configuration, migrationsDirectoryPath } = context,
|
|
15
|
-
migrations = Migrations.
|
|
14
|
+
const { configuration, CustomMigrationMap, migrationsDirectoryPath } = context,
|
|
15
|
+
migrations = Migrations.fromCustomMigrationMapAndMigrationsDirectoryPath(CustomMigrationMap, migrationsDirectoryPath),
|
|
16
16
|
{ log } = configuration;
|
|
17
17
|
|
|
18
18
|
if (log) {
|
package/bin/migrate.js
CHANGED
|
@@ -7,7 +7,13 @@ const { asynchronousUtilities } = require("necessary");
|
|
|
7
7
|
|
|
8
8
|
const { sequence } = asynchronousUtilities;
|
|
9
9
|
|
|
10
|
-
function migrate(configuration, migrationsDirectoryPath, callback) {
|
|
10
|
+
function migrate(configuration, migrationsDirectoryPath, CustomMigrationMap, callback) {
|
|
11
|
+
if (callback === undefined) {
|
|
12
|
+
callback = CustomMigrationMap; ///
|
|
13
|
+
|
|
14
|
+
CustomMigrationMap = {};
|
|
15
|
+
}
|
|
16
|
+
|
|
11
17
|
const callbacks = [
|
|
12
18
|
initialiseOperation,
|
|
13
19
|
applyMigrationsOperation
|
|
@@ -16,6 +22,7 @@ function migrate(configuration, migrationsDirectoryPath, callback) {
|
|
|
16
22
|
context = {
|
|
17
23
|
error,
|
|
18
24
|
configuration,
|
|
25
|
+
CustomMigrationMap,
|
|
19
26
|
migrationsDirectoryPath
|
|
20
27
|
};
|
|
21
28
|
|
package/index.js
CHANGED
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
const migrate = require("./bin/migrate"),
|
|
4
4
|
database = require("./bin/database"),
|
|
5
5
|
defaultLog = require("./bin/defaultLog"),
|
|
6
|
-
transaction = require("./bin/transaction")
|
|
6
|
+
transaction = require("./bin/transaction"),
|
|
7
|
+
CustomMigration = require("./bin/migrate/customMigration");
|
|
7
8
|
|
|
8
9
|
module.exports = {
|
|
9
10
|
migrate,
|
|
10
11
|
database,
|
|
11
12
|
defaultLog,
|
|
12
|
-
transaction
|
|
13
|
+
transaction,
|
|
14
|
+
CustomMigration
|
|
13
15
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "murmuration",
|
|
3
3
|
"author": "James Smith",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.29",
|
|
5
5
|
"license": "MIT, Anti-996",
|
|
6
6
|
"homepage": "https://github.com/djalbat/murmuration",
|
|
7
7
|
"description": "Database connections, transactions and migrations.",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"url": "https://github.com/djalbat/murmuration"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"necessary": "^11.0.
|
|
13
|
+
"necessary": "^11.0.40"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {},
|
|
16
16
|
"scripts": {}
|