yeoman-environment 4.0.0-alpha.5 → 4.0.0-alpha.6

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.
Files changed (73) hide show
  1. package/bin/bin.cjs +4 -0
  2. package/dist/cli/index.d.ts +1 -0
  3. package/dist/cli/index.js +18 -15
  4. package/dist/cli/utils.d.ts +8 -0
  5. package/dist/cli/utils.js +6 -7
  6. package/dist/commands.d.ts +23 -0
  7. package/dist/commands.js +45 -0
  8. package/dist/commit.d.ts +17 -0
  9. package/dist/commit.js +22 -0
  10. package/dist/composed-store.d.ts +26 -0
  11. package/dist/composed-store.js +68 -0
  12. package/dist/constants.d.ts +3 -0
  13. package/dist/constants.js +17 -0
  14. package/dist/environment-base.d.ts +259 -0
  15. package/dist/environment-base.js +638 -0
  16. package/dist/environment-full.d.ts +115 -0
  17. package/dist/environment-full.js +321 -0
  18. package/dist/generator-lookup.d.ts +56 -0
  19. package/dist/generator-lookup.js +97 -0
  20. package/dist/index.d.ts +10 -0
  21. package/dist/index.js +9 -5
  22. package/dist/module-lookup.d.ts +59 -0
  23. package/dist/module-lookup.js +227 -0
  24. package/dist/package-manager.d.ts +18 -0
  25. package/dist/package-manager.js +52 -69
  26. package/dist/store.d.ts +66 -0
  27. package/dist/store.js +76 -47
  28. package/dist/util/command.d.ts +34 -0
  29. package/dist/util/command.js +32 -17
  30. package/dist/util/namespace.d.ts +26 -0
  31. package/dist/util/namespace.js +56 -190
  32. package/dist/util/resolve.d.ts +6 -0
  33. package/dist/util/resolve.js +40 -0
  34. package/dist/util/util.d.ts +7 -0
  35. package/dist/util/util.js +24 -23
  36. package/package.json +20 -33
  37. package/readme.md +2 -3
  38. package/dist/adapter.js +0 -97
  39. package/dist/adapter.js.map +0 -1
  40. package/dist/cli/index.js.map +0 -1
  41. package/dist/cli/utils.js.map +0 -1
  42. package/dist/command.js +0 -74
  43. package/dist/command.js.map +0 -1
  44. package/dist/composability.js +0 -78
  45. package/dist/composability.js.map +0 -1
  46. package/dist/environment.js +0 -1221
  47. package/dist/environment.js.map +0 -1
  48. package/dist/generator-features.js +0 -69
  49. package/dist/generator-features.js.map +0 -1
  50. package/dist/index.js.map +0 -1
  51. package/dist/namespace-composability.js +0 -340
  52. package/dist/namespace-composability.js.map +0 -1
  53. package/dist/package-manager.js.map +0 -1
  54. package/dist/resolver.js +0 -421
  55. package/dist/resolver.js.map +0 -1
  56. package/dist/spawn-command.js +0 -30
  57. package/dist/spawn-command.js.map +0 -1
  58. package/dist/store.js.map +0 -1
  59. package/dist/util/binary-diff.js +0 -36
  60. package/dist/util/binary-diff.js.map +0 -1
  61. package/dist/util/command.js.map +0 -1
  62. package/dist/util/conflicter.js +0 -346
  63. package/dist/util/conflicter.js.map +0 -1
  64. package/dist/util/esm.js +0 -22
  65. package/dist/util/esm.js.map +0 -1
  66. package/dist/util/log.js +0 -165
  67. package/dist/util/log.js.map +0 -1
  68. package/dist/util/namespace.js.map +0 -1
  69. package/dist/util/repository.js +0 -223
  70. package/dist/util/repository.js.map +0 -1
  71. package/dist/util/transform.js +0 -149
  72. package/dist/util/transform.js.map +0 -1
  73. package/dist/util/util.js.map +0 -1
@@ -1,1221 +0,0 @@
1
- import fs from 'node:fs';
2
- import path, { isAbsolute } from 'node:path';
3
- import EventEmitter from 'node:events';
4
- import crypto from 'node:crypto';
5
- import { pathToFileURL } from 'node:url';
6
- import { createRequire } from 'node:module';
7
- import process from 'node:process';
8
- import chalk from 'chalk';
9
- import _, { defaults, findLast, last, pick, uniq } from 'lodash-es';
10
- import GroupedQueue from 'grouped-queue';
11
- import escapeStrRe from 'escape-string-regexp';
12
- import untildify from 'untildify';
13
- import { create as createMemFs } from 'mem-fs';
14
- import { create as createMemFsEditor } from 'mem-fs-editor';
15
- import createdLogger from 'debug';
16
- import isScoped from 'is-scoped';
17
- import npmlog from 'npmlog';
18
- import slash from 'slash';
19
- import { TrackerGroup } from 'are-we-there-yet';
20
- import { pipeline, transform } from 'p-transform';
21
- // eslint-disable-next-line n/file-extension-in-import
22
- import { isFilePending } from 'mem-fs-editor/state';
23
- // eslint-disable-next-line n/file-extension-in-import
24
- import { createCommitTransform } from 'mem-fs-editor/transform';
25
- import Store from './store.js';
26
- import composability from './composability.js';
27
- import resolver from './resolver.js';
28
- import TerminalAdapter from './adapter.js';
29
- import YeomanRepository from './util/repository.js';
30
- import Conflicter from './util/conflicter.js';
31
- import YeomanCommand from './util/command.js';
32
- import { toNamespace } from './util/namespace.js';
33
- import { createConflicterCheckTransform, createConflicterStatusTransform, createYoRcTransform, createYoResolveTransform, } from './util/transform.js';
34
- import commandMixin from './command.js';
35
- import generatorFeaturesMixin from './generator-features.js';
36
- import packageManagerMixin from './package-manager.js';
37
- import spawnCommandMixin from './spawn-command.js';
38
- import namespaceCompasibilityMixin from './namespace-composability.js';
39
- // eslint-disable-next-line import/order
40
- import { requireOrImport } from './util/esm.js';
41
- const debug = createdLogger('yeoman:environment');
42
- const require = createRequire(import.meta.url);
43
- const ENVIRONMENT_VERSION = require('../package.json').version;
44
- /**
45
- * Two-step argument splitting function that first splits arguments in quotes,
46
- * and then splits up the remaining arguments if they are not part of a quote.
47
- */
48
- function splitArgsFromString(argsString) {
49
- let result = [];
50
- if (!argsString) {
51
- return result;
52
- }
53
- const quoteSeparatedArgs = argsString.split(/("[^"]*")/).filter(Boolean);
54
- for (const arg of quoteSeparatedArgs) {
55
- if (arg.match('\u0022')) {
56
- result.push(arg.replace(/"/g, ''));
57
- }
58
- else {
59
- result = result.concat(arg.trim().split(' '));
60
- }
61
- }
62
- return result;
63
- }
64
- /**
65
- * Hint of generator module name
66
- */
67
- function getGeneratorHint(namespace) {
68
- if (isScoped(namespace)) {
69
- const splitName = namespace.split('/');
70
- return `${splitName[0]}/generator-${splitName[1]}`;
71
- }
72
- return `generator-${namespace}`;
73
- }
74
- const mixins = [commandMixin, generatorFeaturesMixin, packageManagerMixin];
75
- const Base = mixins.reduce((a, b) => b(a), EventEmitter);
76
- class Environment extends Base {
77
- static get UNKNOWN_NAMESPACE() {
78
- return 'unknownnamespace';
79
- }
80
- static get UNKNOWN_RESOLVED() {
81
- return 'unknown';
82
- }
83
- static get queues() {
84
- return [
85
- 'environment:run',
86
- 'initializing',
87
- 'prompting',
88
- 'configuring',
89
- 'default',
90
- 'writing',
91
- 'transform',
92
- 'conflicts',
93
- 'environment:conflicts',
94
- 'install',
95
- 'end',
96
- ];
97
- }
98
- static get lookups() {
99
- return ['.', 'generators', 'lib/generators', 'dist/generators'];
100
- }
101
- /**
102
- * Make sure the Environment present expected methods if an old version is
103
- * passed to a Generator.
104
- * @param {Environment} env
105
- * @return {Environment} The updated env
106
- */
107
- static enforceUpdate(env) {
108
- if (!env.adapter) {
109
- env.adapter = new TerminalAdapter();
110
- }
111
- if (!env.runLoop) {
112
- env.runLoop = new GroupedQueue(Environment.queues, false);
113
- }
114
- if (!env.sharedFs) {
115
- env.sharedFs = createMemFs();
116
- }
117
- if (!env.fs) {
118
- env.fs = createMemFsEditor(env.sharedFs);
119
- }
120
- return env;
121
- }
122
- /**
123
- * Prepare a commander instance for cli support.
124
- *
125
- * @param {Class} GeneratorClass - Generator to create Command
126
- * @return {Command} Return a Command instance
127
- */
128
- static prepareCommand(GeneratorClass, command = new YeomanCommand()) {
129
- command = Base.addEnvironmentOptions(command);
130
- return Environment.prepareGeneratorCommand(command, GeneratorClass);
131
- }
132
- /**
133
- * Prepare a commander instance for cli support.
134
- *
135
- * @param {Command} command - Command to be prepared
136
- * @param {Class} GeneratorClass - Generator to create Command
137
- * @return {Command} return command
138
- */
139
- static prepareGeneratorCommand(command, GeneratorClass, namespace) {
140
- const generator = new GeneratorClass([], { help: true, env: {} });
141
- Base.addGeneratorOptions(command, generator);
142
- command.action(async function () {
143
- let rootCommand = this;
144
- while (rootCommand.parent) {
145
- rootCommand = rootCommand.parent;
146
- }
147
- command.env = await Environment.createEnv(rootCommand.opts());
148
- rootCommand.emit('yeoman:environment', command.env);
149
- if (namespace) {
150
- await command.env.run([namespace, ...(this.args || [])], this.opts());
151
- return command.env;
152
- }
153
- const generator = await command.env.instantiate(GeneratorClass, this.args, this.opts());
154
- await command.env.queueGenerator(generator);
155
- await command.env.start();
156
- return command.env;
157
- });
158
- return command;
159
- }
160
- /**
161
- * Factory method to create an environment instance. Take same parameters as the
162
- * Environment constructor.
163
- *
164
- * @deprecated
165
- * @param {string[]} [args] - arguments.
166
- * @param {object} [options] - Environment options.
167
- * @param {Adapter} [adapter] - Terminal adapter.
168
- *
169
- * @return {Environment} a new Environment instance
170
- */
171
- static createEnv(args, options, adapter) {
172
- if (args && !Array.isArray(args)) {
173
- options = args;
174
- }
175
- options = options || {};
176
- return new Environment(options, adapter);
177
- }
178
- /**
179
- * Factory method to create an environment instance. Take same parameters as the
180
- * Environment constructor.
181
- *
182
- * @param {String} version - Version of the Environment
183
- * @param {...any} args - Same arguments as {@link Environment}#createEnv.
184
- * @return {Environment} a new Environment instance
185
- */
186
- static async createEnvWithVersion(version, ...args) {
187
- const repository = new YeomanRepository();
188
- const installedVersion = repository.verifyInstalledVersion('yeoman-environment', version);
189
- if (!installedVersion) {
190
- await repository.installPackage('yeoman-environment', version);
191
- }
192
- const VersionedEnvironment = repository.requireModule('yeoman-environment', version);
193
- return VersionedEnvironment.createEnv(...args);
194
- }
195
- /**
196
- * Convert a generators namespace to its name
197
- *
198
- * @param {String} namespace
199
- * @return {String}
200
- */
201
- static namespaceToName(namespace) {
202
- return namespace.split(':')[0];
203
- }
204
- /**
205
- * Lookup for a specific generator.
206
- *
207
- * @param {String} namespace
208
- * @param {Object} [options]
209
- * @param {Boolean} [options.localOnly=false] - Set true to skip lookups of
210
- * globally-installed generators.
211
- * @param {Boolean} [options.packagePath=false] - Set true to return the package
212
- * path instead of generators file.
213
- * @param {Boolean} [options.singleResult=true] - Set false to return multiple values.
214
- * @return {String} generator
215
- */
216
- static lookupGenerator(namespace, options) {
217
- options =
218
- typeof options === 'boolean'
219
- ? { singleResult: true, localOnly: options }
220
- : { singleResult: !(options && options.multiple), ...options };
221
- options.filePatterns = options.filePatterns || Environment.lookups.map(prefix => path.join(prefix, '*/index.{js,ts}'));
222
- const name = Environment.namespaceToName(namespace);
223
- options.packagePatterns = options.packagePatterns || getGeneratorHint(name);
224
- const envProt = Environment.prototype;
225
- options.npmPaths = options.npmPaths || envProt.getNpmPaths(options.localOnly).reverse();
226
- options.packagePatterns = options.packagePatterns || 'generator-*';
227
- options.packagePaths = options.packagePaths || resolver.packageLookup.findPackagesIn(options.npmPaths, options.packagePatterns);
228
- let paths = options.singleResult ? undefined : [];
229
- resolver.packageLookup.sync(options, module => {
230
- const filename = module.filePath;
231
- const fileNS = envProt.namespace(filename, Environment.lookups);
232
- if (namespace === fileNS || (options.packagePath && namespace === Environment.namespaceToName(fileNS))) {
233
- // Version 2.6.0 returned pattern instead of modulePath for options.packagePath
234
- const returnPath = options.packagePath
235
- ? module.packagePath
236
- : options.generatorPath
237
- ? path.posix.join(filename, '../../')
238
- : filename;
239
- if (options.singleResult) {
240
- paths = returnPath;
241
- return true;
242
- }
243
- paths.push(returnPath);
244
- }
245
- return false;
246
- });
247
- if (options.singleResult) {
248
- return paths && isAbsolute(paths) ? pathToFileURL(paths).toString() : paths;
249
- }
250
- return paths.map(gen => (isAbsolute(gen) ? pathToFileURL(gen).toString() : gen));
251
- }
252
- /**
253
- * @classdesc `Environment` object is responsible of handling the lifecyle and bootstrap
254
- * of generators in a specific environment (your app).
255
- *
256
- * It provides a high-level API to create and run generators, as well as further
257
- * tuning where and how a generator is resolved.
258
- *
259
- * An environment is created using a list of `arguments` and a Hash of
260
- * `options`. Usually, this is the list of arguments you get back from your CLI
261
- * options parser.
262
- *
263
- * An optional adapter can be passed to provide interaction in non-CLI environment
264
- * (e.g. IDE plugins), otherwise a `TerminalAdapter` is instantiated by default
265
- *
266
- * @constructor
267
- * @implements {import('@yeoman/types').BaseEnvironment}
268
- * @mixes env/resolver
269
- * @mixes env/composability
270
- * @param {String|Array} args
271
- * @param {Object} opts
272
- * @param {Boolean} [opts.experimental]
273
- * @param {Object} [opts.sharedOptions]
274
- * @param {Console} [opts.console]
275
- * @param {Stream} [opts.stdin]
276
- * @param {Stream} [opts.stdout]
277
- * @param {Stream} [opts.stderr]
278
- * @param {TerminalAdapter} [adapter] - A TerminalAdapter instance or another object
279
- * implementing this adapter interface. This is how
280
- * you'd interface Yeoman with a GUI or an editor.
281
- */
282
- constructor(options, adapter) {
283
- super();
284
- this.setMaxListeners(100);
285
- this.options = options || {};
286
- this.adapter =
287
- adapter ||
288
- new TerminalAdapter({
289
- console: this.options.console,
290
- stdin: this.options.stdin,
291
- stderr: this.options.stderr,
292
- });
293
- this.cwd = this.options.cwd || process.cwd();
294
- this.cwd = path.resolve(this.cwd);
295
- this.logCwd = this.options.logCwd || this.cwd;
296
- this.store = new Store();
297
- this.command = this.options.command;
298
- this.runLoop = new GroupedQueue(Environment.queues, false);
299
- this.sharedFs = this.options.sharedFs || createMemFs();
300
- // Each composed generator might set listeners on these shared resources. Let's make sure
301
- // Node won't complain about event listeners leaks.
302
- this.runLoop.setMaxListeners(0);
303
- this.sharedFs.setMaxListeners(0);
304
- this.fs = createMemFsEditor(this.sharedFs);
305
- this.lookups = Environment.lookups;
306
- this.aliases = [];
307
- this.alias(/^([^:]+)$/, '$1:app');
308
- // Used sharedOptions from options if exists.
309
- this.sharedOptions = this.options.sharedOptions || {};
310
- // Remove Unecessary sharedOptions from options
311
- delete this.options.sharedOptions;
312
- // Create a default sharedData.
313
- this.sharedOptions.sharedData = this.sharedOptions.sharedData || {};
314
- // Pass forwardErrorToEnvironment to generators.
315
- this.sharedOptions.forwardErrorToEnvironment = false;
316
- this.repository = new YeomanRepository({
317
- repositoryPath: this.options.yeomanRepository,
318
- arboristRegistry: this.options.arboristRegistry,
319
- });
320
- if (!this.options.experimental) {
321
- for (const value of process.argv) {
322
- if (value === '--experimental') {
323
- this.options.experimental = true;
324
- debug('Set environment as experimental');
325
- }
326
- }
327
- }
328
- this.loadSharedOptions(this.options);
329
- if (this.sharedOptions.skipLocalCache === undefined) {
330
- this.sharedOptions.skipLocalCache = true;
331
- }
332
- // Store the generators by paths and uniqueBy feature.
333
- this._generatorsForPath = {};
334
- this._generators = {};
335
- // Store the YeomanCompose by paths and uniqueBy feature.
336
- this._composeStore = {};
337
- this.enableConflicterIgnore = true;
338
- }
339
- /**
340
- * Load options passed to the Generator that should be used by the Environment.
341
- *
342
- * @param {Object} options
343
- */
344
- loadEnvironmentOptions(options) {
345
- const environmentOptions = pick(options, ['skipInstall', 'nodePackageManager']);
346
- defaults(this.options, environmentOptions);
347
- return environmentOptions;
348
- }
349
- /**
350
- * Load options passed to the Environment that should be forwarded to the Generator.
351
- *
352
- * @param {Object} options
353
- */
354
- loadSharedOptions(options) {
355
- const optionsToShare = pick(options, [
356
- 'skipInstall',
357
- 'forceInstall',
358
- 'skipCache',
359
- 'skipLocalCache',
360
- 'skipParseOptions',
361
- 'localConfigOnly',
362
- 'askAnswered',
363
- ]);
364
- Object.assign(this.sharedOptions, optionsToShare);
365
- return optionsToShare;
366
- }
367
- /**
368
- * @deprecated
369
- * Error handler taking `err` instance of Error.
370
- *
371
- * The `error` event is emitted with the error object, if no `error` listener
372
- * is registered, then we throw the error.
373
- *
374
- * @param {Object} err
375
- * @return {Error} err
376
- */
377
- error(error) {
378
- throw error instanceof Error ? error : new Error(error);
379
- }
380
- /**
381
- * Outputs the general help and usage. Optionally, if generators have been
382
- * registered, the list of available generators is also displayed.
383
- *
384
- * @param {String} name
385
- */
386
- help(name = 'init') {
387
- const out = [
388
- 'Usage: :binary: GENERATOR [args] [options]',
389
- '',
390
- 'General options:',
391
- " --help # Print generator's options and usage",
392
- ' -f, --force # Overwrite files that already exist',
393
- '',
394
- 'Please choose a generator below.',
395
- '',
396
- ];
397
- const ns = this.namespaces();
398
- const groups = {};
399
- for (const namespace of ns) {
400
- const base = namespace.split(':')[0];
401
- if (!groups[base]) {
402
- groups[base] = [];
403
- }
404
- groups[base].push(namespace);
405
- }
406
- for (const key of Object.keys(groups).sort()) {
407
- const group = groups[key];
408
- if (group.length > 0) {
409
- out.push('', key.charAt(0).toUpperCase() + key.slice(1));
410
- }
411
- for (const ns of groups[key]) {
412
- out.push(` ${ns}`);
413
- }
414
- }
415
- return out.join('\n').replace(/:binary:/g, name);
416
- }
417
- /**
418
- * Registers a specific `generator` to this environment. This generator is stored under
419
- * provided namespace, or a default namespace format if none if available.
420
- *
421
- * @param {String} name - Filepath to the a generator or a npm package name
422
- * @param {String} namespace - Namespace under which register the generator (optional)
423
- * @param {String} packagePath - PackagePath to the generator npm package (optional)
424
- * @return {Object} environment - This environment
425
- */
426
- register(name, namespace, packagePath) {
427
- if (typeof name !== 'string') {
428
- throw new TypeError('You must provide a generator name to register.');
429
- }
430
- const modulePath = this.resolveModulePath(name);
431
- namespace = namespace || this.namespace(modulePath);
432
- if (!namespace) {
433
- throw new Error('Unable to determine namespace.');
434
- }
435
- // Generator is already registered and matches the current namespace.
436
- if (this.store._meta[namespace] && this.store._meta[namespace].resolved === modulePath) {
437
- return this;
438
- }
439
- this.store.add(namespace, modulePath, modulePath, packagePath);
440
- const packageNS = Environment.namespaceToName(namespace);
441
- this.store.addPackageNS(packageNS);
442
- if (packagePath) {
443
- this.store.addPackage(packageNS, packagePath);
444
- }
445
- debug('Registered %s (%s) on package %s (%s)', namespace, modulePath, packageNS, packagePath);
446
- return this;
447
- }
448
- /**
449
- * Register a stubbed generator to this environment. This method allow to register raw
450
- * functions under the provided namespace. `registerStub` will enforce the function passed
451
- * to extend the Base generator automatically.
452
- *
453
- * @param {Function} Generator - A Generator constructor or a simple function
454
- * @param {String} namespace - Namespace under which register the generator
455
- * @param {String} [resolved] - The file path to the generator
456
- * @param {String} [packagePath] - The generator's package path
457
- * @return {this}
458
- */
459
- registerStub(Generator, namespace, resolved = Environment.UNKNOWN_RESOLVED, packagePath = undefined) {
460
- if (typeof Generator !== 'function' && typeof Generator.createGenerator !== 'function') {
461
- throw new TypeError('You must provide a stub function to register.');
462
- }
463
- if (typeof namespace !== 'string') {
464
- throw new TypeError('You must provide a namespace to register.');
465
- }
466
- this.store.add(namespace, Generator, resolved, packagePath);
467
- const packageNS = Environment.namespaceToName(namespace);
468
- this.store.addPackageNS(packageNS);
469
- if (packagePath) {
470
- this.store.addPackage(packageNS, packagePath);
471
- }
472
- debug('Registered %s (%s) on package (%s)', namespace, resolved, packagePath);
473
- return this;
474
- }
475
- /**
476
- * Returns the list of registered namespace.
477
- * @return {Array}
478
- */
479
- namespaces() {
480
- return this.store.namespaces();
481
- }
482
- /**
483
- * Returns the environment or dependency version.
484
- * @param {String} packageName - Module to get version.
485
- * @return {String} Environment version.
486
- */
487
- getVersion(packageName) {
488
- if (packageName && packageName !== 'yeoman-environment') {
489
- try {
490
- return require(`${packageName}/package.json`).version;
491
- }
492
- catch {
493
- return undefined;
494
- }
495
- }
496
- return ENVIRONMENT_VERSION;
497
- }
498
- /**
499
- * Returns stored generators meta
500
- * @return {Object}
501
- */
502
- getGeneratorsMeta() {
503
- return this.store.getGeneratorsMeta();
504
- }
505
- /**
506
- * Returns stored generators meta
507
- * @param {string} namespace
508
- * @return {any}
509
- */
510
- getGeneratorMeta(namespace) {
511
- const meta = this.store.getMeta(namespace) || this.store.getMeta(this.alias(namespace));
512
- if (!meta) {
513
- return;
514
- }
515
- const { importGenerator, resolved } = meta;
516
- const importModule = async () => requireOrImport(resolved);
517
- const importGeneratorClass = async () => this._findGeneratorClass(await importGenerator(), meta);
518
- const instantiate = async (args, options) => this.instantiate(await importGeneratorClass(), args, options);
519
- const instantiateHelp = async () => instantiate([], { help: true });
520
- const newMeta = {
521
- ...meta,
522
- importModule,
523
- importGeneratorClass,
524
- instantiate,
525
- instantiateHelp,
526
- };
527
- return newMeta;
528
- }
529
- /**
530
- * Get registered generators names
531
- *
532
- * @return {Array}
533
- */
534
- getGeneratorNames() {
535
- return uniq(Object.keys(this.getGeneratorsMeta()).map(namespace => Environment.namespaceToName(namespace)));
536
- }
537
- /**
538
- * Verify if a package namespace already have been registered.
539
- *
540
- * @param {String} [packageNS] - namespace of the package.
541
- * @return {boolean} - true if any generator of the package has been registered
542
- */
543
- isPackageRegistered(packageNS) {
544
- const registeredPackages = this.getRegisteredPackages();
545
- return registeredPackages.includes(packageNS) || registeredPackages.includes(this.alias(packageNS).split(':', 2)[0]);
546
- }
547
- /**
548
- * Get all registered packages namespaces.
549
- *
550
- * @return {Array} - array of namespaces.
551
- */
552
- getRegisteredPackages() {
553
- return this.store.getPackagesNS();
554
- }
555
- /**
556
- * Get last added path for a namespace
557
- *
558
- * @param {String} - namespace
559
- * @return {String} - path of the package
560
- */
561
- async getPackagePath(namespace) {
562
- if (namespace.includes(':')) {
563
- const generator = (await this.get(namespace)) || {};
564
- return generator.packagePath;
565
- }
566
- const packagePaths = this.getPackagePaths(namespace) || [];
567
- return packagePaths[0];
568
- }
569
- /**
570
- * Get paths for a namespace
571
- *
572
- * @param {String} - namespace
573
- * @return {Array} - array of paths.
574
- */
575
- getPackagePaths(namespace) {
576
- return this.store.getPackagesPaths()[namespace] || this.store.getPackagesPaths()[Environment.namespaceToName(this.alias(namespace))];
577
- }
578
- /**
579
- * Get a single generator from the registered list of generators. The lookup is
580
- * based on generator's namespace, "walking up" the namespaces until a matching
581
- * is found. Eg. if an `angular:common` namespace is registered, and we try to
582
- * get `angular:common:all` then we get `angular:common` as a fallback (unless
583
- * an `angular:common:all` generator is registered).
584
- *
585
- * @param {String} namespaceOrPath
586
- * @return {import('@yeoman/api').BaseGenerator|Promise<import('@yeoman/api').BaseGenerator>|null} - the generator registered under the namespace
587
- */
588
- async get(namespaceOrPath) {
589
- // Stop the recursive search if nothing is left
590
- if (!namespaceOrPath) {
591
- return;
592
- }
593
- const parsed = toNamespace(namespaceOrPath);
594
- if (parsed && this.getByNamespace) {
595
- return this.getByNamespace(parsed);
596
- }
597
- let namespace = namespaceOrPath;
598
- // Legacy yeoman-generator `#hookFor()` function is passing the generator path as part
599
- // of the namespace. If we find a path delimiter in the namespace, then ignore the
600
- // last part of the namespace.
601
- const parts = namespaceOrPath.split(':');
602
- const maybePath = last(parts);
603
- if (parts.length > 1 && /[/\\]/.test(maybePath)) {
604
- parts.pop();
605
- // We also want to remove the drive letter on windows
606
- if (maybePath.includes('\\') && last(parts).length === 1) {
607
- parts.pop();
608
- }
609
- namespace = parts.join(':');
610
- }
611
- const generator = (await this.store.get(namespace)) ??
612
- (await this.store.get(this.alias(namespace))) ??
613
- // Namespace is empty if namespaceOrPath contains a win32 absolute path of the form 'C:\path\to\generator'.
614
- // for this reason we pass namespaceOrPath to the getByPath function.
615
- (await this.getByPath(namespaceOrPath));
616
- return this._findGeneratorClass(generator);
617
- }
618
- /**
619
- * Get a generator by path instead of namespace.
620
- * @param {String} path
621
- * @return {Generator|null} - the generator found at the location
622
- */
623
- async getByPath(path) {
624
- if (fs.existsSync(path)) {
625
- const namespace = this.namespace(path);
626
- this.register(path, namespace);
627
- return this.get(namespace);
628
- }
629
- }
630
- /**
631
- * Find generator's class constructor.
632
- * @private
633
- * @param {Object} Generator - Object containing the class.
634
- * @return {Function} Generator's constructor.
635
- */
636
- async _findGeneratorClass(Generator, meta = Generator) {
637
- if (!Generator) {
638
- return Generator;
639
- }
640
- if (Array.isArray(Generator)) {
641
- meta = Generator[1];
642
- Generator = Generator[0];
643
- }
644
- if (typeof Generator.default === 'function') {
645
- Generator.default.resolved = meta.resolved;
646
- Generator.default.namespace = meta.namespace;
647
- Generator.default.packagePath = meta.packagePath;
648
- return Generator.default;
649
- }
650
- if (typeof Generator.createGenerator === 'function') {
651
- const maybeGenerator = await Generator.createGenerator(this);
652
- maybeGenerator.resolved = meta.resolved;
653
- maybeGenerator.namespace = meta.namespace;
654
- maybeGenerator.packagePath = meta.packagePath;
655
- return maybeGenerator;
656
- }
657
- if (typeof Generator !== 'function') {
658
- throw new TypeError("The generator doesn't provides a constructor.");
659
- }
660
- return Generator;
661
- }
662
- /**
663
- * Create is the Generator factory. It takes a namespace to lookup and optional
664
- * hash of options, that lets you define `arguments` and `options` to
665
- * instantiate the generator with.
666
- *
667
- * An error is raised on invalid namespace.
668
- *
669
- * @param {String} namespaceOrPath
670
- * @param {Array} [args]
671
- * @param {Object} [options]
672
- * @return {Generator} The instantiated generator
673
- */
674
- async create(namespaceOrPath, args, options) {
675
- if (!Array.isArray(args) && typeof args === 'object') {
676
- options = args.options || args;
677
- args = args.arguments || args.args || [];
678
- }
679
- else {
680
- args = Array.isArray(args) ? args : splitArgsFromString(args);
681
- options = options || {};
682
- }
683
- const namespace = toNamespace(namespaceOrPath);
684
- let maybeGenerator;
685
- if (namespace && this.getByNamespace) {
686
- maybeGenerator = await this.getByNamespace(namespace);
687
- if (!maybeGenerator) {
688
- this.lookupLocalNamespaces(namespace);
689
- maybeGenerator = await this.getByNamespace(namespace);
690
- }
691
- }
692
- const checkGenerator = Generator => {
693
- if (namespace &&
694
- Generator &&
695
- Generator.namespace &&
696
- Generator.namespace !== namespace.namespace &&
697
- Generator.namespace !== Environment.UNKNOWN_NAMESPACE) {
698
- // Update namespace object in case of aliased namespace.
699
- try {
700
- namespace.namespace = Generator.namespace;
701
- }
702
- catch {
703
- // Invalid namespace can be aliased to a valid one.
704
- }
705
- }
706
- if (typeof Generator !== 'function') {
707
- const generatorHint = namespace ? namespace.generatorHint : getGeneratorHint(namespaceOrPath);
708
- throw new Error(chalk.red("You don't seem to have a generator with the name “" + namespaceOrPath + '” installed.') +
709
- '\n' +
710
- 'But help is on the way:\n\n' +
711
- 'You can see available generators via ' +
712
- chalk.yellow('npm search yeoman-generator') +
713
- ' or via ' +
714
- chalk.yellow('http://yeoman.io/generators/') +
715
- '. \n' +
716
- 'Install them with ' +
717
- chalk.yellow(`npm install ${generatorHint}`) +
718
- '.\n\n' +
719
- 'To see all your installed generators run ' +
720
- chalk.yellow('yo --generators') +
721
- '. ' +
722
- 'Adding the ' +
723
- chalk.yellow('--help') +
724
- ' option will also show subgenerators. \n\n' +
725
- 'If ' +
726
- chalk.yellow('yo') +
727
- ' cannot find the generator, run ' +
728
- chalk.yellow('yo doctor') +
729
- ' to troubleshoot your system.');
730
- }
731
- return Generator;
732
- };
733
- maybeGenerator = maybeGenerator || this.get(namespaceOrPath);
734
- return this.instantiate(checkGenerator(await maybeGenerator), args, options);
735
- }
736
- /**
737
- * Instantiate a Generator with metadatas
738
- *
739
- * @param {Class<Generator>} generator Generator class
740
- * @param {Array} [args] Arguments to pass the instance
741
- * @param {Object} [options] Options to pass the instance
742
- * @return {Generator} The instantiated generator
743
- */
744
- async instantiate(Generator, args, options) {
745
- if (!Array.isArray(args) && typeof args === 'object') {
746
- options = args.options || args;
747
- args = args.arguments || args.args || [];
748
- }
749
- else {
750
- args = Array.isArray(args) ? args : splitArgsFromString(args);
751
- options = options || {};
752
- }
753
- const { namespace = Environment.UNKNOWN_NAMESPACE } = Generator;
754
- const environmentOptions = {
755
- env: this,
756
- resolved: Generator.resolved || Environment.UNKNOWN_RESOLVED,
757
- namespace,
758
- };
759
- const generator = new Generator(args, {
760
- ...this.sharedOptions,
761
- ...options,
762
- ...environmentOptions,
763
- });
764
- generator._environmentOptions = {
765
- ...this.options,
766
- ...this.sharedOptions,
767
- ...environmentOptions,
768
- };
769
- if (!options.help && generator._postConstruct) {
770
- await generator._postConstruct();
771
- }
772
- return generator;
773
- }
774
- /**
775
- * Compose with the generator.
776
- *
777
- * @param {String} namespaceOrPath
778
- * @param {Array} [args]
779
- * @param {Object} [options]
780
- * @param {Boolean} [schedule]
781
- * @return {Generator} The instantiated generator or the singleton instance.
782
- */
783
- async composeWith(generator, args, options, schedule = true) {
784
- if (typeof args === 'boolean') {
785
- schedule = args;
786
- args = undefined;
787
- options = undefined;
788
- }
789
- else if (typeof options === 'boolean') {
790
- schedule = options;
791
- options = undefined;
792
- }
793
- const generatorInstance = await this.create(generator, args, options);
794
- return this.queueGenerator(generatorInstance, schedule);
795
- }
796
- /**
797
- * @private
798
- */
799
- getGeneratorsForPath(generatorRoot = this.cwd) {
800
- this._generatorsForPath[generatorRoot] = this._generatorsForPath[generatorRoot] || {};
801
- return this._generatorsForPath[generatorRoot];
802
- }
803
- /**
804
- * @private
805
- */
806
- getGenerator(uniqueBy, generatorRoot = this.cwd) {
807
- if (this._generators[uniqueBy]) {
808
- return this._generators[uniqueBy];
809
- }
810
- return this.getGeneratorsForPath(generatorRoot)[uniqueBy];
811
- }
812
- /**
813
- * @private
814
- */
815
- getAllGenerators() {
816
- return Object.fromEntries([
817
- ...Object.entries(this._generators),
818
- ...Object.entries(this._generatorsForPath).flatMap(([root, generatorStore]) => Object.entries(generatorStore).map(([namespace, generator]) => [`${root}#${namespace}`, generator])),
819
- ]);
820
- }
821
- /**
822
- * @private
823
- */
824
- setGenerator(uniqueBy, generator) {
825
- if (generator.features && generator.features.uniqueGlobally) {
826
- this._generators[uniqueBy] = generator;
827
- }
828
- else {
829
- this.getGeneratorsForPath(generator.destinationRoot())[uniqueBy] = generator;
830
- }
831
- return generator;
832
- }
833
- /**
834
- * Queue generator run (queue itself tasks).
835
- *
836
- * @param {Generator} generator Generator instance
837
- * @param {boolean} [schedule=false] Whether to schedule the generator run.
838
- * @return {Generator} The generator or singleton instance.
839
- */
840
- async queueGenerator(generator, schedule = false) {
841
- const generatorFeatures = generator.getFeatures ? generator.getFeatures() : {};
842
- let uniqueBy;
843
- let rootUniqueBy;
844
- let namespaceToEmit;
845
- if (generatorFeatures) {
846
- uniqueBy = generatorFeatures.uniqueBy;
847
- namespaceToEmit = uniqueBy;
848
- if (!generatorFeatures.uniqueGlobally) {
849
- rootUniqueBy = generator.destinationRoot();
850
- }
851
- }
852
- if (!uniqueBy) {
853
- const { namespace } = generator.options;
854
- const instanceId = crypto.randomBytes(20).toString('hex');
855
- let namespaceDefinition = toNamespace(namespace);
856
- if (namespaceDefinition) {
857
- namespaceDefinition = namespaceDefinition.with({ instanceId });
858
- uniqueBy = namespaceDefinition.id;
859
- namespaceToEmit = namespaceDefinition.namespace;
860
- }
861
- else {
862
- uniqueBy = `${namespace}#${instanceId}`;
863
- namespaceToEmit = namespace;
864
- }
865
- }
866
- const existing = this.getGenerator(uniqueBy, rootUniqueBy);
867
- if (existing) {
868
- debug(`Using existing generator for namespace ${uniqueBy}`);
869
- return existing;
870
- }
871
- this.setGenerator(uniqueBy, generator);
872
- this.emit('compose', namespaceToEmit, generator);
873
- this.emit(`compose:${namespaceToEmit}`, generator);
874
- const runGenerator = async () => {
875
- if (generator.queueTasks) {
876
- // Generator > 5
877
- this.once('run', () => generator.emit('run'));
878
- this.once('end', () => generator.emit('end'));
879
- await generator.queueTasks();
880
- return;
881
- }
882
- if (!generator.options.forwardErrorToEnvironment) {
883
- generator.on('error', error => this.emit('error', error));
884
- }
885
- generator.promise = generator.run();
886
- };
887
- if (schedule) {
888
- this.queueTask('environment:run', () => runGenerator());
889
- }
890
- else {
891
- await runGenerator();
892
- }
893
- return generator;
894
- }
895
- /**
896
- * Tries to locate and run a specific generator. The lookup is done depending
897
- * on the provided arguments, options and the list of registered generators.
898
- *
899
- * When the environment was unable to resolve a generator, an error is raised.
900
- *
901
- * @param {String|Array} args
902
- * @param {Object} [options]
903
- */
904
- async run(args, options, done) {
905
- if (done || typeof options === 'function' || typeof args === 'function') {
906
- throw new Error('Callback support have been removed.');
907
- }
908
- args = Array.isArray(args) ? args : splitArgsFromString(args);
909
- options = { ...options };
910
- const name = args.shift();
911
- if (!name) {
912
- throw new Error('Must provide at least one argument, the generator namespace to invoke.');
913
- }
914
- this.loadEnvironmentOptions(options);
915
- const instantiateAndRun = async () => {
916
- const generator = await this.create(name, args, {
917
- ...options,
918
- initialGenerator: true,
919
- });
920
- if (options.help) {
921
- console.log(generator.help());
922
- return undefined;
923
- }
924
- return this.runGenerator(generator);
925
- };
926
- if (this.options.experimental && !this.get(name)) {
927
- debug(`Generator ${name} was not found, trying to install it`);
928
- try {
929
- await this.prepareEnvironment(name);
930
- }
931
- catch { }
932
- }
933
- return instantiateAndRun();
934
- }
935
- /**
936
- * Start Environment queue
937
- * @param {Object} options - Conflicter options.
938
- */
939
- start(options) {
940
- return new Promise((resolve, reject) => {
941
- if (this.conflicter === undefined) {
942
- const conflicterOptions = pick(defaults({}, this.options, options), [
943
- 'force',
944
- 'bail',
945
- 'ignoreWhitespace',
946
- 'dryRun',
947
- 'skipYoResolve',
948
- 'logCwd',
949
- ]);
950
- conflicterOptions.cwd = conflicterOptions.logCwd;
951
- this.conflicter = new Conflicter(this.adapter, conflicterOptions);
952
- this.queueConflicter();
953
- this.queuePackageManagerInstall();
954
- }
955
- /*
956
- * Listen to errors and reject if emmited.
957
- * Some cases the generator relied at the behavior that the running process
958
- * would be killed if an error is thrown to environment.
959
- * Make sure to not rely on that behavior.
960
- */
961
- this.on('error', error => {
962
- reject(error);
963
- });
964
- /*
965
- * For backward compatibility
966
- */
967
- this.on('generator:reject', error => {
968
- reject(error);
969
- });
970
- this.on('generator:resolve', error => {
971
- resolve(error);
972
- });
973
- this.runLoop.on('error', error => {
974
- this.emit('error', error);
975
- this.adapter.close();
976
- });
977
- this.runLoop.on('paused', () => {
978
- this.emit('paused');
979
- });
980
- this.once('end', () => {
981
- resolve();
982
- });
983
- /* If runLoop has ended, the environment has ended too. */
984
- this.runLoop.once('end', () => {
985
- this.emit('end');
986
- });
987
- this.emit('run');
988
- this.runLoop.start();
989
- });
990
- }
991
- /**
992
- * Convenience method to run the generator with callbackWrapper.
993
- * See https://github.com/yeoman/environment/pull/101
994
- *
995
- * @param {Object} generator
996
- */
997
- async runGenerator(generator) {
998
- generator = await generator;
999
- generator = await this.queueGenerator(generator);
1000
- this.compatibilityMode = generator.queueTasks ? false : 'v4';
1001
- this._rootGenerator = this._rootGenerator || generator;
1002
- return this.start(generator.options);
1003
- }
1004
- /**
1005
- * Get the first generator that was queued to run in this environment.
1006
- *
1007
- * @return {Generator} generator queued to run in this environment.
1008
- */
1009
- rootGenerator() {
1010
- return this._rootGenerator;
1011
- }
1012
- /**
1013
- * Given a String `filepath`, tries to figure out the relative namespace.
1014
- *
1015
- * ### Examples:
1016
- *
1017
- * this.namespace('backbone/all/index.js');
1018
- * // => backbone:all
1019
- *
1020
- * this.namespace('generator-backbone/model');
1021
- * // => backbone:model
1022
- *
1023
- * this.namespace('backbone.js');
1024
- * // => backbone
1025
- *
1026
- * this.namespace('generator-mocha/backbone/model/index.js');
1027
- * // => mocha:backbone:model
1028
- *
1029
- * @param {String} filepath
1030
- * @param {Array} lookups paths
1031
- */
1032
- namespace(filepath, lookups = this.lookups) {
1033
- if (!filepath) {
1034
- throw new Error('Missing namespace');
1035
- }
1036
- // Normalize path
1037
- let ns = slash(filepath);
1038
- // Ignore path before latest node_modules
1039
- const REPOSITORY_PATH = '/node_modules/';
1040
- if (ns.includes(REPOSITORY_PATH)) {
1041
- ns = ns.slice(ns.lastIndexOf(REPOSITORY_PATH) + REPOSITORY_PATH.length, ns.length);
1042
- }
1043
- // Cleanup extension and normalize path for differents OS
1044
- const parsed = path.parse(ns);
1045
- ns = parsed.dir ? `${parsed.dir}/${parsed.name}` : parsed.name;
1046
- // Sort lookups by length so biggest are removed first
1047
- const nsLookups = _([...lookups, '..'])
1048
- .map(found => slash(found))
1049
- .sortBy('length')
1050
- .value()
1051
- .reverse();
1052
- // If `ns` contains a lookup dir in its path, remove it.
1053
- for (let lookup of nsLookups) {
1054
- // Only match full directory (begin with leading slash or start of input, end with trailing slash)
1055
- lookup = new RegExp(`(?:/|^)${escapeStrRe(lookup)}(?=/)`, 'g');
1056
- ns = ns.replace(lookup, '');
1057
- }
1058
- const folders = ns.split('/');
1059
- const scope = findLast(folders, folder => folder.indexOf('@') === 0);
1060
- // Cleanup `ns` from unwanted parts and then normalize slashes to `:`
1061
- ns = ns
1062
- .replace(/\/\//g, '') // Remove double `/`
1063
- .replace(/(.*generator-)/, '') // Remove before `generator-`
1064
- .replace(/\/(index|main)$/, '') // Remove `/index` or `/main`
1065
- .replace(/^\//, '') // Remove leading `/`
1066
- .replace(/\/+/g, ':'); // Replace slashes by `:`
1067
- if (scope) {
1068
- ns = `${scope}/${ns}`;
1069
- }
1070
- debug('Resolve namespaces for %s: %s', filepath, ns);
1071
- return ns;
1072
- }
1073
- /**
1074
- * Resolve a module path
1075
- * @param {String} moduleId - Filepath or module name
1076
- * @return {String} - The resolved path leading to the module
1077
- */
1078
- resolveModulePath(moduleId) {
1079
- if (moduleId[0] === '.') {
1080
- moduleId = path.resolve(moduleId);
1081
- }
1082
- moduleId = untildify(moduleId);
1083
- moduleId = path.normalize(moduleId);
1084
- if (path.extname(moduleId) === '') {
1085
- moduleId += path.sep;
1086
- }
1087
- let resolved;
1088
- // Win32: moduleId is resolving as moduleId.js or moduleId.json instead of moduleId/index.js, workaround it.
1089
- if (process.platform === 'win32' && path.extname(moduleId) === '') {
1090
- try {
1091
- resolved = require.resolve(path.join(moduleId, 'index'));
1092
- }
1093
- catch { }
1094
- }
1095
- return resolved || require.resolve(moduleId);
1096
- }
1097
- /**
1098
- * Apply transform streams to file in MemFs.
1099
- * @param {Transform[]} transformStreams - transform streams to be applied.
1100
- * @param {Stream} [stream] - files stream, defaults to this.sharedFs.stream().
1101
- * @return {Promise<void>}
1102
- */
1103
- async applyTransforms(transformStreams, options = {}) {
1104
- const { streamOptions = { filter: file => isFilePending(file) }, stream = this.sharedFs.stream(streamOptions), name = 'Transforming', } = options;
1105
- let { log = true } = options;
1106
- if (log) {
1107
- npmlog.tracker = new TrackerGroup();
1108
- npmlog.enableProgress();
1109
- log = npmlog.newItem(name);
1110
- }
1111
- if (!Array.isArray(transformStreams)) {
1112
- transformStreams = [transformStreams];
1113
- }
1114
- await pipeline(stream, ...transformStreams, transform(file => {
1115
- if (log) {
1116
- log.completeWork(10);
1117
- npmlog.info('Completed', path.relative(this.logCwd, file.path));
1118
- }
1119
- }, 'environment:log'));
1120
- if (log) {
1121
- log.finish();
1122
- npmlog.disableProgress();
1123
- }
1124
- }
1125
- /**
1126
- * Commits the MemFs to the disc.
1127
- * @param {Stream} [stream] - files stream, defaults to this.sharedFs.stream().
1128
- * @return {Promise}
1129
- */
1130
- commitSharedFs(stream = this.sharedFs.stream({ filter: file => isFilePending(file) })) {
1131
- debug('committing files');
1132
- const conflicterStatus = {};
1133
- if (this.enableConflicterIgnore) {
1134
- conflicterStatus.fs = this.fs;
1135
- }
1136
- return this.fs.commit([
1137
- createYoResolveTransform(this.conflicter),
1138
- createYoRcTransform(),
1139
- createConflicterCheckTransform(this.conflicter, conflicterStatus),
1140
- createConflicterStatusTransform(),
1141
- // Use custom commit transform due to out of order transform.
1142
- createCommitTransform(this.fs),
1143
- ], stream);
1144
- }
1145
- /**
1146
- * Queue environment's commit task.
1147
- */
1148
- queueConflicter() {
1149
- const queueCommit = () => {
1150
- debug('Queueing conflicts task');
1151
- this.queueTask('environment:conflicts', async () => {
1152
- let customCommitTask = this.findGeneratorCustomCommitTask();
1153
- if (customCommitTask !== undefined && customCommitTask) {
1154
- if (typeof customCommitTask !== 'function') {
1155
- // There is a custom commit task or just disabled
1156
- return;
1157
- }
1158
- }
1159
- else {
1160
- // Using default commit task
1161
- customCommitTask = this.commitSharedFs.bind(this);
1162
- }
1163
- await customCommitTask();
1164
- if (this.enableConflicterIgnore) {
1165
- debug('Adding queueCommit event listener');
1166
- this.sharedFs.once('change', queueCommit);
1167
- }
1168
- }, {
1169
- once: 'write memory fs to disk',
1170
- });
1171
- };
1172
- queueCommit();
1173
- }
1174
- /**
1175
- * Queue environment's package manager install task.
1176
- */
1177
- queuePackageManagerInstall() {
1178
- this.queueTask('install', () => this.packageManagerInstallTask(), { once: 'package manager install' });
1179
- }
1180
- /**
1181
- * Queue tasks
1182
- * @param {string} priority
1183
- * @param {(...args: any[]) => void | Promise<void>} task
1184
- * @param {{ once?: string, startQueue?: boolean }} [options]
1185
- */
1186
- queueTask(priority, task, options) {
1187
- return new Promise((resolve, reject) => {
1188
- this.runLoop.add(priority, async (done, stop) => {
1189
- try {
1190
- const result = await task();
1191
- done(result);
1192
- resolve(result);
1193
- }
1194
- catch (error) {
1195
- stop(error);
1196
- reject(error);
1197
- }
1198
- }, {
1199
- once: options.once,
1200
- run: options.startQueue ?? false,
1201
- });
1202
- });
1203
- }
1204
- /**
1205
- * Add priority
1206
- * @param {string} priority
1207
- * @param {string} [before]
1208
- */
1209
- addPriority(priority, before) {
1210
- if (this.runLoop.queueNames.includes(priority)) {
1211
- return;
1212
- }
1213
- this.runLoop.addSubQueue(priority, before);
1214
- }
1215
- }
1216
- Object.assign(Environment.prototype, resolver);
1217
- Object.assign(Environment.prototype, composability);
1218
- Object.assign(Environment.prototype, spawnCommandMixin);
1219
- Object.assign(Environment.prototype, namespaceCompasibilityMixin);
1220
- export default Environment;
1221
- //# sourceMappingURL=environment.js.map