cob-cli 2.27.1 → 2.29.0

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.
@@ -17,9 +17,9 @@ async function customize(filter, args) {
17
17
  checkVersion();
18
18
  if (!args.force) await checkWorkingCopyCleanliness();
19
19
 
20
- let repo = await getCustomizationRepo(filter,args);
21
- if (!args.local) await getCustomizationFiles(repo);
22
- await applyCustomization(repo);
20
+ let customizationRepo = await getCustomizationRepo(filter,args);
21
+ if (!args.local) await getCustomizationFiles(customizationRepo);
22
+ await applyCustomization(customizationRepo);
23
23
 
24
24
  console.log( colors.green("\nDone"), "\nCheck changes to your git working tree and try:" );
25
25
  console.log( "\tcob-cli test\n" );
@@ -39,7 +39,7 @@ async function getCustomizationRepo(filter, args) {
39
39
  if (args.local) {
40
40
  customizationRepos = JSON.parse(fs.readFileSync(cacheCustomizations))
41
41
  if (filter) {
42
- customizationRepos = customizationRepos.filter(repo => repo.name.indexOf(filter) != -1)
42
+ customizationRepos = customizationRepos.filter(customizationRepo => customizationRepo.name.indexOf(filter) != -1)
43
43
  }
44
44
  } else {
45
45
  // Get list of relevant customizations from github
@@ -59,8 +59,8 @@ async function getCustomizationRepo(filter, args) {
59
59
  throw new Error("\nError: ".red + " incompatible options, --local AND --cache\n");
60
60
  } else if(args.cache) {
61
61
  console.log("Caching all customizations...");
62
- for( let repo of customizationRepos) {
63
- await getCustomizationFiles(repo);
62
+ for( let customizationRepo of customizationRepos) {
63
+ await getCustomizationFiles(customizationRepo);
64
64
  }
65
65
  fs.writeFileSync( cacheCustomizations,
66
66
  JSON.stringify(customizationRepos, null, 2),
@@ -75,47 +75,47 @@ async function getCustomizationRepo(filter, args) {
75
75
  type: "list",
76
76
  name: "customization",
77
77
  message: "What customization do you want to apply?",
78
- choices: customizationRepos.map((repo) => repo.name).sort(),
78
+ choices: customizationRepos.map((customizationRepo) => customizationRepo.name).sort(),
79
79
  },
80
80
  ]);
81
81
 
82
- //Return the full repo info
83
- return customizationRepos.find((repo) => repo.name == answer.customization);
82
+ //Return the full customizationRepo info
83
+ return customizationRepos.find((customizationRepo) => customizationRepo.name == answer.customization);
84
84
  }
85
85
 
86
86
  /* ************************************************************************ */
87
- async function getCustomizationFiles(repo) {
87
+ async function getCustomizationFiles(customizationRepo) {
88
88
  const { xdgData } = await import("xdg-basedir");
89
89
  const baseDir = process.cwd();
90
90
  const cacheDir = path.resolve(xdgData,"cob-cli")
91
91
  if (!fs.existsSync(cacheDir)) fs.mkdirSync(cacheDir, { recursive: true });
92
92
 
93
93
  process.chdir(cacheDir);
94
- if (!fs.existsSync(path.resolve(cacheDir,repo.name))) {
95
- console.log(" git " + repo.ssh_url);
96
- await git().clone(repo.ssh_url);
94
+ if (!fs.existsSync(path.resolve(cacheDir,customizationRepo.name))) {
95
+ console.log(" git " + customizationRepo.ssh_url);
96
+ await git().clone(customizationRepo.ssh_url);
97
97
  } else {
98
- console.log(" git pull " + repo.ssh_url);
99
- process.chdir(repo.name);
98
+ console.log(" git pull " + customizationRepo.ssh_url);
99
+ process.chdir(customizationRepo.name);
100
100
  await git().pull();
101
101
  }
102
102
  process.chdir(baseDir);
103
103
  }
104
104
 
105
105
  /* ************************************************************************ */
106
- async function applyCustomization(repo) {
107
- console.log("\nApplying " + repo.name + " customization ...");
106
+ async function applyCustomization(customizationRepo) {
107
+ console.log("\nApplying " + customizationRepo.name + " customization ...");
108
108
 
109
109
  // Get customization info from convention defined file (customize.js)
110
110
  const { xdgData } = await import("xdg-basedir");
111
- const customizationPath = path.resolve( xdgData, "cob-cli", repo.name);
111
+ const customizationPath = path.resolve( xdgData, "cob-cli", customizationRepo.name);
112
112
  const customizationFile = path.resolve( customizationPath, "customize.js");
113
113
  if (!fs.existsSync(customizationFile))
114
114
  throw new Error("\nError: ".red + " no customize.js file found\n");
115
115
 
116
116
  let customization = (await import(customizationFile)).default;
117
117
 
118
- // Asks options, if configuration exists
118
+ // Asks questions, if configuration exists
119
119
  let answers = {};
120
120
  if (customization.questions) {
121
121
  answers = await inquirer.prompt(customization.questions);
@@ -123,23 +123,32 @@ async function applyCustomization(repo) {
123
123
 
124
124
  // Apply specific customization, if it exists, otherwise use default actions
125
125
  if (customization.actions) {
126
- customization.actions(repo.name, options, copy, mergeFiles);
126
+ customization.actions(customizationRepo.name, answers, copyAndMerge);
127
127
  } else {
128
128
  // Default actions
129
- await copy(customizationPath, process.cwd(), answers);
130
- await mergeFiles(repo.name);
129
+ copyAndMerge(customizationRepo.name, answers);
131
130
  }
132
131
 
133
132
  // Update customizations.json file
134
- updateCustomizationsVersions(repo.name, customization.version);
133
+ updateCustomizationsVersions(customizationRepo.name, customization.version);
135
134
  }
136
135
 
137
136
  /* ************************************************************************ */
138
- async function copy(source, target, substitutions = {}) {
137
+ async function copyAndMerge(customizationRepoName, substitutions = {}) {
139
138
  // https://www.npmtrends.com/copyfiles-vs-cpx-vs-ncp-vs-npm-build-tools
140
139
  // https://www.npmjs.com/package/ncp
141
140
  // https://www.npmjs.com/package/copyfiles
142
141
 
142
+ let source
143
+ if(customizationRepoName.indexOf("/") == 0) {
144
+ // Based of customizationRepoName starting with "/" we assume this is already a fullpath
145
+ source = customizationRepoName;
146
+ } else {
147
+ // Otherwise assume customizationRepoName on standard cob-cli xdgData path
148
+ const { xdgData } = await import("xdg-basedir");
149
+ source = path.resolve( xdgData, "cob-cli", customizationRepoName);
150
+ }
151
+
143
152
  console.log(" Copying template files ...");
144
153
 
145
154
  let excludedFiles = RegExp(
@@ -154,30 +163,53 @@ async function copy(source, target, substitutions = {}) {
154
163
  ")"
155
164
  );
156
165
 
157
- // Source is on cob-cli repo and Destination on the server repo
158
- await ncp(
166
+ // Source is on cob-cli customizationRepo and Destination on the server repo
167
+ const target = process.cwd() // Always copy to directory where command is being executed, ie, the root directory of the server repo
168
+ const substitutionRegex = /__(((?!word).)*)__/g;
169
+ ncp(
159
170
  source,
160
171
  target,
161
172
  {
162
173
  clobber: true,
163
174
  filter: (src) => src.match(excludedFiles) == null,
164
- // TODO: comentado porque não funciona a copiar os ficheiros binários (em concreto as font no template/dashboards/dash)
165
- // transform(read, write) {
166
- // const replaceVars = new Transform({
167
- // transform: (chunk, encoding, done) => done(null,chunk.toString().replace(/__.+__/g, m => substitutions[m]))
168
- // })
169
- // read.pipe(replaceVars).pipe(write)
170
- // }
175
+ rename: function(target) {
176
+ // Don't rename __MERGE__ templates, they will be handled by the merge method
177
+ if (target.match(/__MERGE__/)) return target;
178
+
179
+ //get finalTarget from target with any existing substitution
180
+ const finalTarget = target.replace(substitutionRegex, (match,g1) => substitutions[g1] ? substitutions[g1] : match);
181
+
182
+ //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
183
+ if (!fs.existsSync(path.dirname(finalTarget))) {
184
+ fs.mkdirSync(path.dirname(finalTarget), { recursive: true })
185
+ fs.rmdirSync(target.substring(0,target.lastIndexOf("__")+2), { recursive: true,force: false }) //NOTE: won't handle more than 1 substitution on the same dirpath
186
+ }
187
+ return finalTarget;
188
+ },
189
+ transform(read, write) {
190
+ const replaceVarsTransformFunction = new Transform({
191
+ transform: (chunk, encoding, done) => {
192
+ if(/\ufffd/.test(chunk) === true) {
193
+ // If chunk is binary don't change anything
194
+ done(null, chunk)
195
+ } else {
196
+ // Otherwise change any existing substitution
197
+ done(null,chunk.toString().replace(substitutionRegex, (match,g1) => substitutions[g1] ? substitutions[g1] : match))
198
+ }
199
+ }
200
+ })
201
+ read.pipe(replaceVarsTransformFunction).pipe(write)
202
+ }
171
203
  },
172
- (error) => error && error.map((e) => e.message).join("\n")
173
- );
174
-
175
- const dryrun = await fg(["**/*__*__*"], { onlyFiles: false, dot: true }); //Just to give time for OS to stabilize
176
- const files = await fg(["**/*__*__*"], { onlyFiles: false, dot: true });
177
- for(let file of files.filter(name => name.indexOf("node_modules") == -1)) {
178
- if (file.match(/__MERGE__/)) return;
179
- fs.renameSync( file, file.replace(/__(.+)__/g, (match,g1) => substitutions[g1]) );
180
- }
204
+ (error) => {
205
+ // If no error occurred then proced with merging files
206
+ if(!error) {
207
+ mergeFiles(customizationRepoName);
208
+ } else {
209
+ throw new Error(error.map((e) => e.message).join("\n"))
210
+ }
211
+ }
212
+ )
181
213
  }
182
214
 
183
215
  /* ************************************************************************ */
@@ -198,6 +230,7 @@ async function mergeFiles(block) {
198
230
  }
199
231
  let prodFileContent = fs.readFileSync(prodFile).toString();
200
232
  let mergeFileContent = fs.readFileSync(mergeFile).toString();
233
+ // With comments we support JS, CSS, GROOVY
201
234
  let startStr = "/* COB-CLI START " + blockMark + " */\n";
202
235
  let endStr = "\n/* COB-CLI END " + blockMark + " */\n";
203
236
 
@@ -224,14 +257,12 @@ async function mergeFiles(block) {
224
257
  /* ************************************************************************ */
225
258
  function updateCustomizationsVersions(customizationKey, version) {
226
259
  const customizationsVersionsFile = "customizations.json";
227
- let customizationsVersions;
228
- try {
260
+ let customizationsVersions = {};
261
+ if(fs.existsSync(customizationsVersionsFile)) {
229
262
  const customizationsVersionsRawData = fs.readFileSync(customizationsVersionsFile);
230
263
  customizationsVersions = JSON.parse(customizationsVersionsRawData);
231
- } catch (err) {
232
- customizationsVersions = {};
233
264
  }
234
- customizationsVersions[customizationKey] = version;
265
+ customizationsVersions = {[customizationKey]: version, ...customizationsVersions}
235
266
 
236
267
  fs.writeFileSync(
237
268
  customizationsVersionsFile,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cob-cli",
3
- "version": "2.27.1",
3
+ "version": "2.29.0",
4
4
  "description": "A command line utility to help Cult of Bits partners develop with higher speed and reusing common code and best practices.",
5
5
  "preferGlobal": true,
6
6
  "repository": {