-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
217 lines (198 loc) · 7.4 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
'use strict';
const fs = require('fs');
const Glob = require('glob').Glob;
const utils = require('./utils');
/**
* @typedef {Object} opts
* @property {string|number} indent - The type of indent spacing to use in task manifests.
* @property {boolean} quiet - Set to true to suppress log output.
* @property {string} versionPropertyType - Controls what type of property the task version values will be set to.
* @property {string} type - The version type to bump.
*/
/**
* @typedef {Object} BumpedFileResult
* @property {string} filePath - The path to the task manifest file.
* @property {string} initialVersion - The original version contained in the task manifest file.
* @property {string} bumpedVersion - The bumped version of the file now in the task manifest file.
*/
/**
* @typedef {Object} BumpedTask
* @property {string} filePath - The path to the task manifest file.
* @property {string} initialVersion - The original version contained in the task manifest file.
* @property {string} bumpedVersion - The bumped version of the file now in the task manifest file.
* @property {object} task - The JSON object representation of the task manifest file contents.
*/
/**
* @typedef {Object} Task
* @property {{ Major: number|string, Minor: number|string, Patch: number|string }} version - The version of the task.
*/
/**
* @typedef {Object} TaskManifestFile
* @property {string} filePath - The path to the task manifest file.
* @property {string} fileContents - The contents of the task manifest file.
*/
/**
* @typedef {Object} BumpResult
* @property {BumpedFileResult[]} bumpedFiles - The details of each bumped task manifest file
* @property {string} bumpType - The type of version bump that was used.
*/
/**
* Helper function that builds an Error with an aggregated error message.
* @private
*
* @param {string} baseErrorMessage - The base error message to use.
* @param {Error} err - The original error encountered.
* @returns {Error}
*/
const buildError = (baseErrorMessage, err) => {
const errorMessageDetails = (err && err.message) ? err.message : 'unknown';
const errorMessage = `${baseErrorMessage}${errorMessageDetails}`;
return new Error(errorMessage);
};
/**
* Helper function for validating the file globs.
* @param {string[]} fileGlobs - The set of file globs.
*
* @private
* @returns {boolean}
*/
const validateFileGlobs = (fileGlobs) => {
return (fileGlobs && Array.isArray(fileGlobs) && fileGlobs.length >= 1);
};
/**
* Helper function for writing the updated task back to manifest file.
* @param {BumpedTask} bumpedTask - The bumped task.
* @param {opts} opts - The provided bump options.
*
* @private
* @returns {Promise<BumpedFileResult>}
*/
const writeBumpedTaskToFile = (bumpedTask, opts) => new Promise((resolve, reject) => {
fs.writeFile(bumpedTask.filePath, JSON.stringify(bumpedTask.task, null, opts.indent), err => {
if (!err) {
const filePath = bumpedTask.filePath;
const initialVersion = bumpedTask.initialVersion;
const bumpedVersion = bumpedTask.bumpedVersion;
resolve({ filePath, initialVersion, bumpedVersion });
} else {
reject(err);
}
});
});
/**
* Helper function for updating a task manifest.
* @param {TaskManifestFile} taskManifestFile - The task manifest file
* @param {opts} opts - The provided bump options.
*
* @private
* @returns {Promise<BumpedTask>}
*/
const bumpTaskObjects = (taskManifestFile, opts) => new Promise((resolve, reject) => {
try {
const task = JSON.parse(taskManifestFile.fileContents);
const initialVersion = utils.getTaskVersion(task);
const bumpedVersion = utils.bumpVersion(task, initialVersion, opts);
const filePath = taskManifestFile.filePath;
resolve({ filePath, task, initialVersion, bumpedVersion });
} catch (err) {
reject(err);
}
});
/**
* Reads the contents of a task manifest file from disk.
*
* @param {string} filePath - The path to the task manifest file.
* @returns {TaskManifestFile}
*/
const readTaskManifestFile = (filePath) => new Promise((resolve, reject) => {
fs.readFile(filePath, { encoding: 'utf-8' }, (fileErr, fileContents) => {
if (!fileErr) {
resolve({ filePath, fileContents});
} else {
reject(fileErr);
}
});
});
/**
* Helper function for bumping task manifest files.
* @private
*
* @param {string[]} filePaths - The task manifest file paths.
* @param {opts} opts - The bumping options
*
* @returns {Promise<BumpedFileResult>[]}
*/
const bumpTaskManifests = (filePaths, opts) => new Promise((resolve, reject) => {
Promise.all(filePaths.map(filePath => readTaskManifestFile(filePath)))
.then(manifests => Promise.all(manifests.map(manifest => bumpTaskObjects(manifest, opts)))
.then(bumpedTasks => Promise.all(bumpedTasks.map(bumpedTask => writeBumpedTaskToFile(bumpedTask, opts)))
.then(result => resolve(result))))
.catch(err => reject(err));
});
/**
* Helper function for bumping a glob of task manifest files.
* @private
*
* @param {string} fileGlob - Glob of task manifest files.
* @param {opts} opts - The bumping options
*
* @returns {Promise<BumpedFileResult[]>[]}
*/
const bumpTaskGlob = (fileGlob, opts) => new Promise((resolve, reject) => {
const glob = new Glob(fileGlob);
glob.on('end', matches => bumpTaskManifests(matches, opts)
.then(result => resolve(result))
.catch(err => reject(err))
);
glob.on('error', err => reject(buildError('Failed to match glob. Error details: ', err)));
});
/**
* Bumps the versions contained inside task manifest files.
*
* @param {string[]} fileGlobs - The file globs for the task manifests to be bumped.
* @param {opts} [opts] - The bumping options
*
* @returns {Promise<BumpResult>}
*/
const bumpTaskManifestFiles = (fileGlobs, opts) => new Promise((resolve, reject) => {
if (!validateFileGlobs(fileGlobs)) {
return reject(new Error('Invalid arguments. Valid array of glob of task manifests must be specified'));
}
const options = utils.validateOptions(opts);
Promise.all(fileGlobs.map(fileGlob => bumpTaskGlob(fileGlob, options)))
.then(bumpedFiles => resolve({ bumpedFiles: [].concat(...bumpedFiles), bumpType: options.type }))
.catch(err => reject(buildError('Fatal error occurred while attempting to bump file. Details: ', err)));
});
/**
* Bumps the version of the provided task.
* @param {Task} task - The task to bump.
* @param {string} [bumpType] - The version bump type.
*
* @throws {Error} - Will throw an error if the provided task is not valid.
*/
const bumpTask = (task, bumpType) => {
const opts = { type: bumpType };
utils.validateReleaseType(opts);
const initialVersion = utils.getTaskVersion(task);
utils.bumpVersion(task, initialVersion, opts);
};
/**
* Bumps the version of the provided tasks.
* @param {Task[]} tasks - The tasks to bump.
* @param {string} [bumpType] - The version bump type.
*
* @throws {TypeError} - Will throw an error if the provided tasks parameter is not a valid array of tasks.
*/
const bumpTasks = (tasks, bumpType) => {
if (!tasks || !Array.isArray(tasks)) {
throw new TypeError('Invalid argument. First parameter must be valid array of tasks.');
}
tasks.forEach(task => {
bumpTask(task, bumpType);
});
};
module.exports = {
bumpTask,
bumpTasks,
bumpTaskManifestFiles
};