cob-cli 2.39.5 → 2.39.7
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 +102 -103
- 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,67 +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
|
-
|
|
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)
|
|
230
|
+
}
|
|
228
231
|
}
|
|
229
232
|
}
|
|
230
|
-
}
|
|
231
233
|
)
|
|
232
234
|
}
|
|
233
235
|
|
|
234
236
|
/* ************************************************************************ */
|
|
235
237
|
function mergeFiles(block,mergeFile) {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
238
|
+
if (!fs.existsSync(mergeFile)) {
|
|
239
|
+
//Already processed
|
|
240
|
+
return
|
|
241
|
+
}
|
|
240
242
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
let beforeMerge = prodFileContent.indexOf(startStr);
|
|
266
|
-
let afterMerge = prodFileContent.indexOf(endStr) + endStr.length;
|
|
267
|
-
prodFileContent =
|
|
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 =
|
|
268
267
|
prodFileContent.substring(0, beforeMerge) +
|
|
269
|
-
startStr +
|
|
268
|
+
startStr + "\n" +
|
|
270
269
|
mergeFileContent +
|
|
271
270
|
endStr +
|
|
272
271
|
prodFileContent.substring(afterMerge);
|
|
273
|
-
|
|
274
|
-
|
|
272
|
+
}
|
|
273
|
+
fs.writeFileSync(prodFile, prodFileContent);
|
|
275
274
|
|
|
276
|
-
|
|
275
|
+
fs.unlinkSync(mergeFile);
|
|
277
276
|
}
|
|
278
277
|
|
|
279
278
|
/* ************************************************************************ */
|
|
@@ -290,10 +289,10 @@ function updateCustomizationsVersions(customizationKey, version) {
|
|
|
290
289
|
}
|
|
291
290
|
|
|
292
291
|
fs.writeFileSync(
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
292
|
+
customizationsVersionsFile,
|
|
293
|
+
JSON.stringify(customizationsVersions, null, 2),
|
|
294
|
+
(err) => {
|
|
295
|
+
if (err) console.log( "Error writing " + customizationsVersionsFile + ":", err.message );
|
|
296
|
+
}
|
|
298
297
|
);
|
|
299
298
|
}
|
package/package.json
CHANGED