yeoman-environment 4.0.0-beta.0 → 4.0.0-beta.2

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/dist/commit.js CHANGED
@@ -1,15 +1,18 @@
1
1
  import { createConflicterTransform, createYoResolveTransform, forceYoFiles } from '@yeoman/conflicter';
2
+ import createdLogger from 'debug';
2
3
  import { create as createMemFsEditor } from 'mem-fs-editor';
3
4
  // eslint-disable-next-line n/file-extension-in-import
4
5
  import { isFilePending } from 'mem-fs-editor/state';
5
6
  // eslint-disable-next-line n/file-extension-in-import
6
7
  import { createCommitTransform } from 'mem-fs-editor/transform';
8
+ const debug = createdLogger('yeoman:environment:commit');
7
9
  /**
8
10
  * Commits the MemFs to the disc.
9
11
  * @param {Stream} [stream] - files stream, defaults to this.sharedFs.stream().
10
12
  * @return {Promise}
11
13
  */
12
14
  export const commitSharedFsTask = ({ adapter, conflicterOptions, sharedFs, stream, }) => {
15
+ debug('Running commitSharedFsTask');
13
16
  const fs = createMemFsEditor(sharedFs);
14
17
  stream = stream ?? fs.store.stream({ filter: file => isFilePending(file) });
15
18
  return fs.commit([
@@ -4,23 +4,23 @@ export declare class ComposedStore {
4
4
  private readonly generators;
5
5
  private readonly uniqueByPathMap;
6
6
  private readonly uniqueGloballyMap;
7
- private readonly uniqueFeatures;
8
7
  constructor({ log }?: {
9
8
  log?: Logger;
10
9
  });
11
- get customCommitTask(): true | (() => Promise<void>) | undefined;
12
- get customInstallTask(): true | (() => Promise<void>) | undefined;
10
+ get customCommitTask(): any;
11
+ get customInstallTask(): any;
13
12
  getGenerators(): Record<string, BaseGenerator>;
14
- addGenerator(generator: any): {
13
+ addGenerator(generator: BaseGenerator): {
15
14
  uniqueBy: any;
15
+ identifier: any;
16
16
  added: boolean;
17
17
  generator: BaseGenerator | undefined;
18
- identifier?: undefined;
19
18
  } | {
20
19
  identifier: any;
21
20
  added: boolean;
22
- generator: any;
21
+ generator: BaseGenerator;
23
22
  uniqueBy?: undefined;
24
23
  };
25
24
  getUniqueByPathMap(root: string): Map<string, BaseGenerator>;
25
+ private getFeature;
26
26
  }
@@ -1,26 +1,26 @@
1
1
  import crypto from 'node:crypto';
2
2
  import { toNamespace } from '@yeoman/namespace';
3
- const uniqueFeatureValues = ['customCommitTask', 'customInstallTask'];
3
+ import createdLogger from 'debug';
4
+ const debug = createdLogger('yeoman:environment:composed-store');
4
5
  export class ComposedStore {
5
6
  log;
6
7
  generators = {};
7
8
  uniqueByPathMap = new Map();
8
9
  uniqueGloballyMap = new Map();
9
- uniqueFeatures = new Map();
10
10
  constructor({ log } = {}) {
11
11
  this.log = log;
12
12
  }
13
13
  get customCommitTask() {
14
- return this.uniqueFeatures.get('customCommitTask');
14
+ return this.getFeature('customCommitTask');
15
15
  }
16
16
  get customInstallTask() {
17
- return this.uniqueFeatures.get('customInstallTask');
17
+ return this.getFeature('customInstallTask');
18
18
  }
19
19
  getGenerators() {
20
20
  return { ...this.generators };
21
21
  }
22
22
  addGenerator(generator) {
23
- const features = generator.getFeatures?.() ?? {};
23
+ const { features = generator.getFeatures?.() ?? {} } = generator;
24
24
  let { uniqueBy } = features;
25
25
  const { uniqueGlobally } = features;
26
26
  let identifier = uniqueBy;
@@ -41,21 +41,9 @@ export class ComposedStore {
41
41
  const generatorRoot = generator.destinationRoot();
42
42
  const uniqueByMap = uniqueGlobally ? this.uniqueGloballyMap : this.getUniqueByPathMap(generatorRoot);
43
43
  if (uniqueByMap.has(uniqueBy)) {
44
- return { uniqueBy, added: false, generator: uniqueByMap.get(uniqueBy) };
44
+ return { uniqueBy, identifier, added: false, generator: uniqueByMap.get(uniqueBy) };
45
45
  }
46
46
  uniqueByMap.set(uniqueBy, generator);
47
- for (const featureName of uniqueFeatureValues) {
48
- const feature = features[featureName];
49
- if (feature) {
50
- const existingFeature = this.uniqueFeatures.get(feature);
51
- if (typeof existingFeature !== 'function') {
52
- this.uniqueFeatures.set(featureName, feature);
53
- }
54
- else if (typeof feature === 'function') {
55
- this.log?.info?.(`Multiple ${featureName} tasks found. Using the first.`);
56
- }
57
- }
58
- }
59
47
  this.generators[uniqueGlobally ? uniqueBy : `${generatorRoot}#${uniqueBy}`] = generator;
60
48
  return { identifier, added: true, generator };
61
49
  }
@@ -65,4 +53,22 @@ export class ComposedStore {
65
53
  }
66
54
  return this.uniqueByPathMap.get(root);
67
55
  }
56
+ getFeature(featureName) {
57
+ const providedFeatures = Object.entries(this.generators)
58
+ .map(([generatorId, generator]) => {
59
+ const { features = generator.getFeatures?.() } = generator;
60
+ const feature = features?.[featureName];
61
+ return feature ? [generatorId, feature] : undefined;
62
+ })
63
+ .filter(Boolean);
64
+ if (providedFeatures.length > 0) {
65
+ if (providedFeatures.length > 1) {
66
+ this.log?.info?.(`Multiple ${featureName} tasks found (${providedFeatures.map(([generatorId]) => generatorId).join(', ')}). Using the first.`);
67
+ }
68
+ const [generatorId, feature] = providedFeatures[0];
69
+ debug(`Feature ${featureName} provided by ${generatorId}`);
70
+ return feature;
71
+ }
72
+ return undefined;
73
+ }
68
74
  }
@@ -526,12 +526,14 @@ export default class EnvironmentBase extends EventEmitter {
526
526
  * would be killed if an error is thrown to environment.
527
527
  * Make sure to not rely on that behavior.
528
528
  */
529
- this.on('error', error => {
530
- reject(error);
529
+ this.on('error', async (error) => {
531
530
  this.runLoop.pause();
531
+ await this.adapter.onIdle?.();
532
+ reject(error);
532
533
  this.adapter.close();
533
534
  });
534
- this.once('end', () => {
535
+ this.once('end', async () => {
536
+ await this.adapter.onIdle?.();
535
537
  resolve();
536
538
  this.adapter.close();
537
539
  });
@@ -568,13 +570,15 @@ export default class EnvironmentBase extends EventEmitter {
568
570
  const queueCommit = () => {
569
571
  debug('Queueing conflicts task');
570
572
  this.queueTask('environment:conflicts', async () => {
573
+ debug('Running conflicts');
571
574
  const { customCommitTask = () => commitSharedFsTask(this) } = this.composedStore;
572
- if (typeof customCommitTask !== 'function') {
573
- // There is a custom commit task or just disabled
574
- return;
575
+ if (typeof customCommitTask === 'function') {
576
+ await customCommitTask();
575
577
  }
576
- await customCommitTask();
577
- debug('Adding queueCommit event listener');
578
+ else {
579
+ debug('Ignoring commit, custom commit was provided');
580
+ }
581
+ debug('Adding queueCommit listener');
578
582
  this.sharedFs.once('change', queueCommit);
579
583
  }, {
580
584
  once: 'write memory fs to disk',
@@ -602,6 +606,10 @@ export default class EnvironmentBase extends EventEmitter {
602
606
  nodePackageManager,
603
607
  customInstallTask,
604
608
  });
609
+ memFs.once('change', file => {
610
+ if (file === join(this.cwd, 'package.json'))
611
+ this.queuePackageManagerInstall();
612
+ });
605
613
  }, { once: 'package manager install' });
606
614
  }
607
615
  /**
@@ -1,6 +1,6 @@
1
1
  import { join, resolve } from 'node:path';
2
2
  import createdLogger from 'debug';
3
- import preferredPm from 'preferred-pm';
3
+ import { whichPackageManager } from 'which-package-manager';
4
4
  import { execa } from 'execa';
5
5
  const debug = createdLogger('yeoman:environment:package-manager');
6
6
  /**
@@ -15,6 +15,7 @@ const debug = createdLogger('yeoman:environment:package-manager');
15
15
 
16
16
  */
17
17
  export async function packageManagerInstallTask({ memFs, packageJsonLocation, customInstallTask, adapter, nodePackageManager, skipInstall, }) {
18
+ debug('Running packageManagerInstallTask');
18
19
  packageJsonLocation = resolve(packageJsonLocation);
19
20
  /**
20
21
  * @private
@@ -52,8 +53,7 @@ Changes to package.json were detected.`);
52
53
  `);
53
54
  return false;
54
55
  }
55
- // eslint-disable-next-line unicorn/no-await-expression-member
56
- let packageManagerName = nodePackageManager ?? (await preferredPm(packageJsonLocation))?.name;
56
+ let packageManagerName = nodePackageManager ?? (await whichPackageManager({ cwd: packageJsonLocation }));
57
57
  const execPackageManager = async () => {
58
58
  if (!packageManagerName) {
59
59
  packageManagerName = 'npm';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yeoman-environment",
3
- "version": "4.0.0-beta.0",
3
+ "version": "4.0.0-beta.2",
4
4
  "description": "Handles the lifecyle and bootstrapping of generators in a specific environment",
5
5
  "keywords": [
6
6
  "development",
@@ -73,10 +73,10 @@
73
73
  "lodash-es": "^4.17.21",
74
74
  "mem-fs": "^3.0.0",
75
75
  "mem-fs-editor": "^10.0.1",
76
- "preferred-pm": "^3.0.3",
77
76
  "semver": "^7.5.0",
78
77
  "slash": "^5.0.1",
79
- "untildify": "^5.0.0"
78
+ "untildify": "^5.0.0",
79
+ "which-package-manager": "^0.0.1"
80
80
  },
81
81
  "devDependencies": {
82
82
  "@types/debug": "^4.1.8",