3 const fs
= require('fs');
4 const path
= require('path');
7 * Utility functions for wrangling schema migrations.
11 * @typedef {Object} SchemaVersionObject
12 * @property {Number} major
13 * @property {Number} minor
14 * @property {Number} patch
19 * Split a dotted version string into parts.
21 * @returns {SchemaVersionObject}
23 function schemaVersionStringToObject(v
) {
24 const [ major
, minor
, patch
] = v
.split('.', 3).map((x
) => parseInt(x
, 10));
25 return { major
, minor
, patch
};
30 * Render a version object numerically.
31 * @param {SchemaVersionObject} v
34 function schemaVersionObjectToNumber(v
) {
36 return parseInt(v
.major
) * vScale
* vScale
+ parseInt(v
.minor
) * vScale
+ parseInt(v
.patch
);
41 * Convert dotted version string into number.
45 function schemaVersionStringToNumber(v
) {
46 return schemaVersionObjectToNumber(schemaVersionStringToObject(v
));
51 * Version string comparison, for sorting.
56 function schemaVersionStringCmp(a
, b
) {
57 return schemaVersionStringToNumber(a
) - schemaVersionStringToNumber(b
);
62 * Check if an entry in a directory is a directory containing a migration file.
63 * @param {String} schemaDir
64 * @param {String} name
67 function isSchemaMigrationDirectory(schemaDir
, name
) {
68 // eslint-disable-next-line security/detect-non-literal-fs-filename
69 const nameStat
= fs
.statSync(path
.join(schemaDir
, name
));
70 if (nameStat
.isDirectory()) {
73 // eslint-disable-next-line security/detect-non-literal-fs-filename
74 applyStat
= fs
.statSync(path
.join(schemaDir
, name
, 'apply.sql'));
75 return applyStat
.isFile();
85 * Return an array of schema migration directory names within engineDir.
86 * @param {String} engineDir
89 function allSchemaVersions(engineDir
) {
90 const schemaDir
= path
.join(engineDir
, 'sql', 'schema');
91 // eslint-disable-next-line security/detect-non-literal-fs-filename
92 const availableVersions
= fs
.readdirSync(schemaDir
).filter((d
) => isSchemaMigrationDirectory(schemaDir
, d
));
93 availableVersions
.sort(schemaVersionStringCmp
);
94 return availableVersions
;
99 * Return an array of schema migration directory names within engineDir,
100 * which are within supported range, and are greater than the current
101 * @param {String} engineDir
102 * @param {SchemaVersionObject} current
103 * @param {Object} supported
104 * @param {SchemaVersionObject} supported.min
105 * @param {SchemaVersionObject} supported.max
106 * @returns {String[]}
108 function unappliedSchemaVersions(engineDir
, current
, supported
) {
109 const min
= schemaVersionObjectToNumber(supported
.min
);
110 const max
= schemaVersionObjectToNumber(supported
.max
);
111 const cur
= schemaVersionObjectToNumber(current
);
112 const available
= allSchemaVersions(engineDir
);
113 return available
.filter((a
) => {
114 a
= schemaVersionStringToNumber(a
);
115 return a
>= min
&& a
<= max
&& a
> cur
;
121 schemaVersionStringToObject
,
122 schemaVersionObjectToNumber
,
123 schemaVersionStringToNumber
,
124 schemaVersionStringCmp
,
125 isSchemaMigrationDirectory
,
127 unappliedSchemaVersions
,