yeoman-environment 2.5.0 → 2.6.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.
package/lib/adapter.js CHANGED
@@ -53,9 +53,14 @@ class TerminalAdapter {
53
53
  *
54
54
  * @param {string} actual
55
55
  * @param {string} expected
56
+ * @param {Array} changes returned by diff.
56
57
  */
57
- diff(actual, expected) {
58
- let msg = diff.diffLines(actual, expected).map(str => {
58
+ diff(actual, expected, changes) {
59
+ if (Array.isArray(actual)) {
60
+ changes = actual;
61
+ }
62
+ changes = changes || diff.diffLines(actual, expected);
63
+ let msg = changes.map(str => {
59
64
  if (str.added) {
60
65
  return this._colorLines('Added', str.value);
61
66
  }
@@ -159,14 +159,22 @@ class Environment extends EventEmitter {
159
159
  * Lookup for a specific generator.
160
160
  *
161
161
  * @param {String} namespace
162
+ * @param {Object} [options]
163
+ * @param {Boolean|Object} [options.localOnly=false] - Set true to skip lookups of
164
+ * globally-installed generators.
165
+ * @param {Boolean|Object} [options.packagePath=false] - Set true to return the package
166
+ * path instead of generators file.
162
167
  * @return {String} generator
163
168
  */
164
- static lookupGenerator(namespace, localOnly = false) {
169
+ static lookupGenerator(namespace, options = {}) {
170
+ if (typeof options === 'boolean') {
171
+ options = {localOnly: options};
172
+ }
165
173
  const name = Environment.namespaceToName(namespace);
166
174
  const generatorHint = getGeneratorHint(name);
167
175
  const envProt = Environment.prototype;
168
176
 
169
- const generatorsModules = envProt.findGeneratorsIn(envProt.getNpmPaths(localOnly).reverse(), generatorHint);
177
+ const generatorsModules = envProt.findGeneratorsIn(envProt.getNpmPaths(options.localOnly).reverse(), generatorHint);
170
178
  const patterns = [];
171
179
 
172
180
  for (const lookup of Environment.lookups) {
@@ -178,6 +186,9 @@ class Environment extends EventEmitter {
178
186
  for (const pattern of patterns) {
179
187
  for (const filename of globby.sync('*/index.js', {cwd: pattern, absolute: true, deep: 1})) {
180
188
  if (namespace === envProt.namespace(filename, Environment.lookups)) {
189
+ if (options.packagePath) {
190
+ return pattern;
191
+ }
181
192
  return filename;
182
193
  }
183
194
  }
@@ -283,9 +294,10 @@ class Environment extends EventEmitter {
283
294
  *
284
295
  * @param {String} name - Filepath to the a generator or a npm package name
285
296
  * @param {String} namespace - Namespace under which register the generator (optional)
286
- * @return {String} namespace - Namespace assigned to the registered generator
297
+ * @param {String} packagePath - PackagePath to the generator npm package (optional)
298
+ * @return {Object} environment - This environment
287
299
  */
288
- register(name, namespace) {
300
+ register(name, namespace, packagePath) {
289
301
  if (typeof name !== 'string') {
290
302
  return this.error(new Error('You must provide a generator name to register.'));
291
303
  }
@@ -297,9 +309,12 @@ class Environment extends EventEmitter {
297
309
  return this.error(new Error('Unable to determine namespace.'));
298
310
  }
299
311
 
300
- this.store.add(namespace, modulePath);
312
+ this.store.add(namespace, modulePath, undefined, packagePath);
313
+ if (packagePath) {
314
+ this.store.addPackage(Environment.namespaceToName(namespace), packagePath);
315
+ }
301
316
 
302
- debug('Registered %s (%s)', namespace, modulePath);
317
+ debug('Registered %s (%s) on package (%s)', namespace, modulePath, packagePath);
303
318
  return this;
304
319
  }
305
320
 
@@ -311,9 +326,10 @@ class Environment extends EventEmitter {
311
326
  * @param {Function} Generator - A Generator constructor or a simple function
312
327
  * @param {String} namespace - Namespace under which register the generator
313
328
  * @param {String} [resolved] - The file path to the generator
329
+ * @param {String} [packagePath] - The generator's package path
314
330
  * @return {this}
315
331
  */
316
- registerStub(Generator, namespace, resolved) {
332
+ registerStub(Generator, namespace, resolved, packagePath) {
317
333
  if (typeof Generator !== 'function') {
318
334
  return this.error(new Error('You must provide a stub function to register.'));
319
335
  }
@@ -322,8 +338,12 @@ class Environment extends EventEmitter {
322
338
  return this.error(new Error('You must provide a namespace to register.'));
323
339
  }
324
340
 
325
- this.store.add(namespace, Generator, resolved);
341
+ this.store.add(namespace, Generator, resolved, packagePath);
342
+ if (packagePath) {
343
+ this.store.addPackage(Environment.namespaceToName(namespace), packagePath);
344
+ }
326
345
 
346
+ debug('Registered %s (%s) on package (%s)', namespace, resolved, packagePath);
327
347
  return this;
328
348
  }
329
349
 
@@ -352,6 +372,32 @@ class Environment extends EventEmitter {
352
372
  return _.uniq(Object.keys(this.getGeneratorsMeta()).map(Environment.namespaceToName));
353
373
  }
354
374
 
375
+ /**
376
+ * Get last added path for a namespace
377
+ *
378
+ * @param {String} - namespace
379
+ * @return {String} - path of the package
380
+ */
381
+ getPackagePath(namespace) {
382
+ if (namespace.includes(':')) {
383
+ const generator = this.get(namespace) || {};
384
+ return generator.packagePath;
385
+ }
386
+ const packagePaths = this.getPackagePaths(namespace) || [];
387
+ return packagePaths[0];
388
+ }
389
+
390
+ /**
391
+ * Get paths for a namespace
392
+ *
393
+ * @param {String} - namespace
394
+ * @return {Array} - array of paths.
395
+ */
396
+ getPackagePaths(namespace) {
397
+ return this.store.getPackagesPaths()[namespace] ||
398
+ this.store.getPackagesPaths()[Environment.namespaceToName(this.alias(namespace))];
399
+ }
400
+
355
401
  /**
356
402
  * Get a single generator from the registered list of generators. The lookup is
357
403
  * based on generator's namespace, "walking up" the namespaces until a matching
package/lib/resolver.js CHANGED
@@ -41,17 +41,13 @@ resolver.lookup = function (localOnly = false, cb) {
41
41
  }
42
42
 
43
43
  const generatorsModules = this.findGeneratorsIn(this.getNpmPaths(localOnly).reverse());
44
- const patterns = [];
45
44
 
46
45
  for (const lookup of this.lookups) {
47
46
  for (const modulePath of generatorsModules) {
48
- patterns.push(path.join(modulePath, lookup));
49
- }
50
- }
51
-
52
- for (const pattern of patterns) {
53
- for (const filename of globby.sync('*/index.js', {cwd: pattern, absolute: true, deep: 1})) {
54
- this._tryRegistering(filename);
47
+ const pattern = path.join(modulePath, lookup);
48
+ for (const filename of globby.sync('*/index.js', {cwd: pattern, absolute: true, deep: 1})) {
49
+ this._tryRegistering(filename, modulePath);
50
+ }
55
51
  }
56
52
  }
57
53
 
@@ -112,7 +108,7 @@ resolver.findGeneratorsIn = function (searchPaths, pattern = 'generator-*') {
112
108
  * @private
113
109
  * @param {String} generatorReference A generator reference, usually a file path.
114
110
  */
115
- resolver._tryRegistering = function (generatorReference) {
111
+ resolver._tryRegistering = function (generatorReference, packagePath) {
116
112
  let namespace;
117
113
  const realPath = fs.realpathSync(generatorReference);
118
114
 
@@ -123,7 +119,7 @@ resolver._tryRegistering = function (generatorReference) {
123
119
  namespace = this.namespace(generatorReference);
124
120
  }
125
121
 
126
- this.register(realPath, namespace);
122
+ this.register(realPath, namespace, packagePath);
127
123
  } catch (err) {
128
124
  console.error('Unable to register %s (Error: %s)', generatorReference, err.message);
129
125
  }
package/lib/store.js CHANGED
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ const debug = require('debug')('yeoman:environment:store');
4
+
3
5
  /**
4
6
  * The Generator store
5
7
  * This is used to store generator (npm packages) reference and instantiate them when
@@ -11,27 +13,31 @@ class Store {
11
13
  constructor() {
12
14
  this._generators = {};
13
15
  this._meta = {};
16
+ // Store packages paths by ns
17
+ this._packagesPaths = {};
14
18
  }
15
19
 
16
20
  /**
17
21
  * Store a module under the namespace key
18
22
  * @param {String} namespace - The key under which the generator can be retrieved
19
23
  * @param {String|Function} generator - A generator module or a module path
24
+ * @param {String} packagePath - PackagePath to the generator npm package (optional)
20
25
  * @param {String} [resolved] - The file path to the generator (used only if generator is a module)
21
26
  */
22
- add(namespace, generator, resolved) {
27
+ add(namespace, generator, resolved, packagePath) {
23
28
  if (typeof generator === 'string') {
24
- this._storeAsPath(namespace, generator);
29
+ this._storeAsPath(namespace, generator, packagePath);
25
30
  return;
26
31
  }
27
32
 
28
- this._storeAsModule(namespace, generator, resolved);
33
+ this._storeAsModule(namespace, generator, resolved, packagePath);
29
34
  }
30
35
 
31
- _storeAsPath(namespace, path) {
36
+ _storeAsPath(namespace, path, packagePath) {
32
37
  this._meta[namespace] = {
33
38
  resolved: path,
34
- namespace
39
+ namespace,
40
+ packagePath
35
41
  };
36
42
 
37
43
  Object.defineProperty(this._generators, namespace, {
@@ -44,10 +50,11 @@ class Store {
44
50
  });
45
51
  }
46
52
 
47
- _storeAsModule(namespace, Generator, resolved = 'unknown') {
53
+ _storeAsModule(namespace, Generator, resolved = 'unknown', packagePath) {
48
54
  this._meta[namespace] = {
49
55
  resolved,
50
- namespace
56
+ namespace,
57
+ packagePath
51
58
  };
52
59
 
53
60
  this._generators[namespace] = Generator;
@@ -83,6 +90,39 @@ class Store {
83
90
  getGeneratorsMeta() {
84
91
  return this._meta;
85
92
  }
93
+
94
+ /**
95
+ * Store a package under the namespace key
96
+ * @param {String} namespace - The key under which the generator can be retrieved
97
+ * @param {String} path - The package path
98
+ * @param {String} [generatorNS] - Namespace of a generator to register.
99
+ */
100
+ addPackage(packageNS, packagePath) {
101
+ if (this._packagesPaths[packageNS]) {
102
+ // Yo environment allows overriding, so the last added has preference.
103
+ if (this._packagesPaths[packageNS][0] !== packagePath) {
104
+ const packagePaths = this._packagesPaths[packageNS];
105
+ debug('Overriding a package with namespace %s and path %s, with path %s',
106
+ packageNS, this._packagesPaths[packageNS][0], packagePath);
107
+ // Remove old packagePath
108
+ const index = packagePaths.indexOf(packagePath);
109
+ if (index > -1) {
110
+ packagePaths.splice(index, 1);
111
+ }
112
+ packagePaths.splice(0, 0, packagePath);
113
+ }
114
+ } else {
115
+ this._packagesPaths[packageNS] = [packagePath];
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Get the stored packages namespaces with paths.
121
+ * @return {Object} Stored packages namespaces with paths.
122
+ */
123
+ getPackagesPaths() {
124
+ return this._packagesPaths;
125
+ }
86
126
  }
87
127
 
88
128
  module.exports = Store;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yeoman-environment",
3
- "version": "2.5.0",
3
+ "version": "2.6.0",
4
4
  "description": "Handles the lifecyle and bootstrapping of generators in a specific environment",
5
5
  "homepage": "http://yeoman.io",
6
6
  "author": "Yeoman",