cob-cli 2.39.6 → 2.39.8
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/lib/commands/customize.js +101 -101
- package/package.json +1 -1
|
@@ -10,12 +10,13 @@ const { Transform } = require("stream");
|
|
|
10
10
|
const fs = require("fs-extra");
|
|
11
11
|
|
|
12
12
|
const customizationsVersionsFile = "customizations.json";
|
|
13
|
+
const filesToMerge = [] ; // don't move this to the copyAndMerge method; it will behave erratically
|
|
13
14
|
|
|
14
15
|
/* ************************************************************************ */
|
|
15
16
|
async function customize(filter, args) {
|
|
16
17
|
try {
|
|
17
18
|
console.log("Customize...");
|
|
18
|
-
|
|
19
|
+
|
|
19
20
|
if (args.cache && (filter || args.local || args.update)) throw new Error("\nError: ".red + " incompatible options. Use --cache as single argument\n");
|
|
20
21
|
if (args.update && filter ) throw new Error("\nError: ".red + " incompatible options. Use --update without a <filter> \n");
|
|
21
22
|
|
|
@@ -28,13 +29,13 @@ async function customize(filter, args) {
|
|
|
28
29
|
if(args.cache) {
|
|
29
30
|
console.log( colors.green("\nDone"), " - All configuration were downloaded to your local cache and you can now use the --local flag for any customization" );
|
|
30
31
|
// For --cache argument all work is done, just return
|
|
31
|
-
return
|
|
32
|
+
return
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
await applyCustomizations(customizations)
|
|
35
36
|
|
|
36
37
|
console.log( colors.green("\nDone"), "\nCheck changes to your git working tree and try:" );
|
|
37
|
-
console.log( "\tcob-cli test\n" );
|
|
38
|
+
console.log( "\tcob-cli test\n" );
|
|
38
39
|
} catch (err) {
|
|
39
40
|
console.error("\n", err.message);
|
|
40
41
|
}
|
|
@@ -45,7 +46,7 @@ module.exports = customize;
|
|
|
45
46
|
async function getCustomizationsList(filter, args) {
|
|
46
47
|
const { xdgData } = await import("xdg-basedir");
|
|
47
48
|
const cacheCustomizationsFile = path.resolve(xdgData,"cob-cli","customizations.json")
|
|
48
|
-
|
|
49
|
+
|
|
49
50
|
let customizationRepos;
|
|
50
51
|
let customizationNameQuery = "customize. " + (filter ? filter : "");
|
|
51
52
|
if (args.local) {
|
|
@@ -53,7 +54,7 @@ async function getCustomizationsList(filter, args) {
|
|
|
53
54
|
if (filter) {
|
|
54
55
|
customizationRepos = customizationRepos.filter(customizationRepo => customizationRepo.name.indexOf(filter) != -1)
|
|
55
56
|
}
|
|
56
|
-
} else {
|
|
57
|
+
} else {
|
|
57
58
|
// Get list of relevant customizations from github
|
|
58
59
|
const response = await axios.get( "https://api.github.com/search/repositories?q=" + customizationNameQuery + "+in:name+org:cob", { headers: { Accept: "application/json", "Accept-Encoding": "identity" } } )
|
|
59
60
|
customizationRepos = response.data.items
|
|
@@ -64,7 +65,7 @@ async function getCustomizationsList(filter, args) {
|
|
|
64
65
|
|
|
65
66
|
//Filter customizations according to argument flags
|
|
66
67
|
let relevantRepoNames = [];
|
|
67
|
-
|
|
68
|
+
|
|
68
69
|
if (args.update) {
|
|
69
70
|
// If --update then filter is existing customizations
|
|
70
71
|
let customizationsVersions = {};
|
|
@@ -75,23 +76,23 @@ async function getCustomizationsList(filter, args) {
|
|
|
75
76
|
relevantRepoNames = Object.keys(customizationsVersions)
|
|
76
77
|
|
|
77
78
|
} else if (!args.cache) {
|
|
78
|
-
// Otherwise, if not --cache, asks for customizations to apply
|
|
79
|
+
// Otherwise, if not --cache, asks for customizations to apply
|
|
79
80
|
let answer = await inquirer.prompt([
|
|
80
81
|
{
|
|
81
82
|
type: "checkbox",
|
|
82
83
|
name: "customizations",
|
|
83
84
|
message: "What customization do you want to apply?",
|
|
84
85
|
choices: customizationRepos.map((customizationRepo) => customizationRepo.name).sort(),
|
|
85
|
-
validate: (answers) => answers.length > 0
|
|
86
|
+
validate: (answers) => answers.length > 0
|
|
86
87
|
},
|
|
87
88
|
]);
|
|
88
89
|
relevantRepoNames = answer.customizations
|
|
89
90
|
}
|
|
90
|
-
|
|
91
|
+
|
|
91
92
|
//Return the full customizationRepo info for relevant repos
|
|
92
93
|
return customizationRepos
|
|
93
|
-
|
|
94
|
-
|
|
94
|
+
.sort( (c1, c2) => c1.name > c2.name)
|
|
95
|
+
.filter( customizationRepo => relevantRepoNames.length == 0 || relevantRepoNames.indexOf(customizationRepo.name) >= 0);
|
|
95
96
|
}
|
|
96
97
|
|
|
97
98
|
/* ************************************************************************ */
|
|
@@ -101,11 +102,11 @@ async function downloadCustomizationFiles(customizationRepos, args) {
|
|
|
101
102
|
const cacheDir = path.resolve(xdgData,"cob-cli")
|
|
102
103
|
if (!fs.existsSync(cacheDir)) fs.mkdirSync(cacheDir, { recursive: true });
|
|
103
104
|
|
|
104
|
-
if(args.cache) {
|
|
105
|
+
if(args.cache) {
|
|
105
106
|
const cacheCustomizationsFile = path.resolve(cacheDir, "customizations.json")
|
|
106
107
|
fs.writeFileSync(cacheCustomizationsFile, JSON.stringify(customizationRepos, null, 2), (err) => {
|
|
107
|
-
|
|
108
|
-
|
|
108
|
+
if(err) throw new Error("\nError: ".red + " problem writing " + cacheCustomizationsFile + ":", err.message);
|
|
109
|
+
}
|
|
109
110
|
);
|
|
110
111
|
}
|
|
111
112
|
|
|
@@ -130,9 +131,9 @@ async function downloadCustomizationFiles(customizationRepos, args) {
|
|
|
130
131
|
/* ************************************************************************ */
|
|
131
132
|
async function applyCustomizations(customizationRepos) {
|
|
132
133
|
console.log("\n Applying " + customizationRepos.map( c => colors.blue(c.name)) + " customization ...");
|
|
133
|
-
|
|
134
|
+
|
|
134
135
|
const { xdgData } = await import("xdg-basedir");
|
|
135
|
-
for (let customizationRepo of customizationRepos) {
|
|
136
|
+
for (let customizationRepo of customizationRepos) {
|
|
136
137
|
const customizationDir = path.resolve( xdgData, "cob-cli", customizationRepo.name);
|
|
137
138
|
const customizationFile = path.resolve( customizationDir, "customize.js");
|
|
138
139
|
if (!fs.existsSync(customizationFile)) throw new Error("\nError: ".red + " no customize.js file found\n");
|
|
@@ -163,47 +164,48 @@ function copyAndMerge(customizationRepoName, source, substitutions = {}) {
|
|
|
163
164
|
console.log("\n Copying template files for " + colors.blue(customizationRepoName) + "...");
|
|
164
165
|
|
|
165
166
|
let excludedFiles = RegExp(
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
167
|
+
"(" +
|
|
168
|
+
source + "/\\.git.*" +
|
|
169
|
+
"|" +
|
|
170
|
+
source + "/.*\\.DS_Store" +
|
|
171
|
+
"|" +
|
|
172
|
+
source + "/README.*" +
|
|
173
|
+
"|" +
|
|
174
|
+
source + "/customize.js" +
|
|
175
|
+
"|" +
|
|
176
|
+
source + ".*/node_modules/" +
|
|
177
|
+
")"
|
|
175
178
|
);
|
|
176
179
|
|
|
177
180
|
// Source is on cob-cli customizationRepo and Destination on the server repo
|
|
178
181
|
const target = process.cwd() // Always copy to directory where command is being executed, ie, the root directory of the server repo
|
|
179
182
|
const substitutionRegex = /__(((?!word).)*)__/g;
|
|
180
|
-
let filesToMerge = []
|
|
181
183
|
ncp(
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
184
|
+
source,
|
|
185
|
+
target,
|
|
186
|
+
{
|
|
187
|
+
clobber: true,
|
|
188
|
+
filter: (src) => src.match(excludedFiles) == null,
|
|
187
189
|
rename: function(target) {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
190
|
+
// Don't rename __MERGE__ templates, they will be handled by the merge method
|
|
191
|
+
if (target.match(/__MERGE__/)) {
|
|
192
|
+
const newTmpName = target.replace(/__MERGE__/, customizationRepoName+"__MERGE__")
|
|
193
|
+
filesToMerge.push(newTmpName)
|
|
194
|
+
return newTmpName
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
//get finalTarget from target with any existing substitution
|
|
198
|
+
const finalTarget = target.replace(substitutionRegex, (match,g1) => substitutions[g1] ? substitutions[g1] : match);
|
|
199
|
+
|
|
200
|
+
//if the directory of finalTarget doesn't exists it means that a replacement ocurred on the dirpath (ie, there was a /__.+__/ was on the dirpath), in which case we need to create the desired directory and remove the one just created by ncp
|
|
201
|
+
if (!fs.existsSync(path.dirname(finalTarget))) {
|
|
202
|
+
fs.mkdirSync(path.dirname(finalTarget), { recursive: true })
|
|
203
|
+
fs.rmdirSync(target.substring(0,target.lastIndexOf("__")+2), { recursive: true,force: false }) //NOTE: won't handle more than 1 substitution on the same dirpath
|
|
204
|
+
}
|
|
205
|
+
return finalTarget;
|
|
206
|
+
},
|
|
207
|
+
transform(read, write) {
|
|
208
|
+
const replaceVarsTransformFunction = new Transform({
|
|
207
209
|
transform: (chunk, encoding, done) => {
|
|
208
210
|
if(/\ufffd/.test(chunk) === true) {
|
|
209
211
|
// If chunk is binary don't change anything
|
|
@@ -213,66 +215,64 @@ function copyAndMerge(customizationRepoName, source, substitutions = {}) {
|
|
|
213
215
|
done(null,chunk.toString().replace(substitutionRegex, (match,g1) => substitutions[g1] ? substitutions[g1] : match))
|
|
214
216
|
}
|
|
215
217
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
mergeFiles(customizationRepoName, file)
|
|
218
|
+
})
|
|
219
|
+
read.pipe(replaceVarsTransformFunction).pipe(write)
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
(error) => {
|
|
223
|
+
if(error) {
|
|
224
|
+
console.log(error.map((e) => e.message).join("\n"))
|
|
225
|
+
} else {
|
|
226
|
+
while(filesToMerge.length > 0) {
|
|
227
|
+
let file = filesToMerge.pop();
|
|
228
|
+
//Allow a little time for file to be written to disk
|
|
229
|
+
setTimeout( () => mergeFiles(customizationRepoName, file), 200)
|
|
229
230
|
}
|
|
230
|
-
}
|
|
231
|
+
}
|
|
231
232
|
}
|
|
232
|
-
}
|
|
233
233
|
)
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
/* ************************************************************************ */
|
|
237
237
|
function mergeFiles(block,mergeFile) {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
238
|
+
if (!fs.existsSync(mergeFile)) {
|
|
239
|
+
//Already processed
|
|
240
|
+
return
|
|
241
|
+
}
|
|
242
242
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
243
|
+
let prodFileRexp = new RegExp(block + "__MERGE__.");
|
|
244
|
+
let prodFile = mergeFile.replace(prodFileRexp, "");
|
|
245
|
+
let blockMark = block == undefined ? "" : block;
|
|
246
|
+
if (!fs.existsSync(prodFile)) {
|
|
247
|
+
// If prod file does not exist creates it
|
|
248
|
+
console.log(" Creating " + prodFile);
|
|
249
|
+
fs.closeSync(fs.openSync(prodFile, "w"));
|
|
250
|
+
} else {
|
|
251
|
+
console.log(" Merging " + prodFile + " " + block);
|
|
252
|
+
}
|
|
253
|
+
let prodFileContent = fs.readFileSync(prodFile).toString();
|
|
254
|
+
let mergeFileContent = fs.readFileSync(mergeFile).toString();
|
|
255
|
+
// With comments we support JS, CSS, GROOVY
|
|
256
|
+
let startStr = "/* COB-CLI START " + blockMark + " */";
|
|
257
|
+
let endStr = "\n/* COB-CLI END " + blockMark + " */";
|
|
258
|
+
|
|
259
|
+
if (prodFileContent.indexOf(startStr) < 0) {
|
|
260
|
+
// If previous customization does not exist
|
|
261
|
+
prodFileContent = startStr + "\n" + mergeFileContent + endStr + "\n" + prodFileContent;
|
|
262
|
+
} else {
|
|
263
|
+
// If previous customization exists
|
|
264
|
+
let beforeMerge = prodFileContent.indexOf(startStr);
|
|
265
|
+
let afterMerge = prodFileContent.indexOf(endStr) + endStr.length;
|
|
266
|
+
prodFileContent =
|
|
267
267
|
prodFileContent.substring(0, beforeMerge) +
|
|
268
268
|
startStr + "\n" +
|
|
269
269
|
mergeFileContent +
|
|
270
270
|
endStr +
|
|
271
271
|
prodFileContent.substring(afterMerge);
|
|
272
|
-
|
|
273
|
-
|
|
272
|
+
}
|
|
273
|
+
fs.writeFileSync(prodFile, prodFileContent);
|
|
274
274
|
|
|
275
|
-
|
|
275
|
+
fs.unlinkSync(mergeFile);
|
|
276
276
|
}
|
|
277
277
|
|
|
278
278
|
/* ************************************************************************ */
|
|
@@ -289,10 +289,10 @@ function updateCustomizationsVersions(customizationKey, version) {
|
|
|
289
289
|
}
|
|
290
290
|
|
|
291
291
|
fs.writeFileSync(
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
292
|
+
customizationsVersionsFile,
|
|
293
|
+
JSON.stringify(customizationsVersions, null, 2),
|
|
294
|
+
(err) => {
|
|
295
|
+
if (err) console.log( "Error writing " + customizationsVersionsFile + ":", err.message );
|
|
296
|
+
}
|
|
297
297
|
);
|
|
298
298
|
}
|
package/package.json
CHANGED