yeoman-environment 8.2.0 → 8.3.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/dist/cli/utils.js CHANGED
@@ -1,11 +1,14 @@
1
1
  import { requireNamespace } from '@yeoman/namespace';
2
- import { groupBy } from 'lodash-es';
3
2
  import createLogger from 'debug';
4
3
  import { createEnv as createEnvironment } from "../index.js";
5
4
  const debug = createLogger('yeoman:yoe');
6
5
  export const printGroupedGenerator = (generators) => {
7
- const grouped = groupBy(generators, 'packagePath');
8
- for (const [packagePath, group] of Object.entries(grouped)) {
6
+ const grouped = new Map();
7
+ for (const generator of generators) {
8
+ const packagePath = String(generator.packagePath);
9
+ grouped.set(packagePath, [...(grouped.get(packagePath) ?? []), generator]);
10
+ }
11
+ for (const [packagePath, group] of grouped) {
9
12
  const namespace = requireNamespace(group[0].namespace);
10
13
  console.log(` ${namespace.packageNamespace} at ${packagePath}`);
11
14
  for (const generator of group) {
@@ -47,6 +47,15 @@ export type EnvironmentOptions = ConflicterOptions & BaseEnvironmentOptions & Om
47
47
  */
48
48
  store?: Store;
49
49
  };
50
+ /** The options to instantiate a generator with, and the namespace it was asked with. */
51
+ type EnvironmentInstantiateOptions<G extends BaseGenerator = BaseGenerator> = InstantiateOptions<G> & {
52
+ /**
53
+ * The namespace the generator is created for, complete with its version, instance id, methods and flags
54
+ * (`namespace@semver@#id+method?`), passed to the generator as the `namespaceId` option. The `namespace` option
55
+ * stays the one of the generator, without them.
56
+ */
57
+ namespaceId?: string;
58
+ };
50
59
  /**
51
60
  * Copy and remove null and undefined values
52
61
  * @param object
@@ -122,7 +131,7 @@ export default class EnvironmentBase extends EventEmitter implements BaseEnviron
122
131
  * @param instantiateOptions
123
132
  * @return The instantiated generator
124
133
  */
125
- instantiate<G extends BaseGenerator = BaseGenerator>(generator: GetGeneratorConstructor<G>, instantiateOptions?: InstantiateOptions<G>): Promise<G>;
134
+ instantiate<G extends BaseGenerator = BaseGenerator>(generator: GetGeneratorConstructor<G>, instantiateOptions?: EnvironmentInstantiateOptions<G>): Promise<G>;
126
135
  /**
127
136
  * @protected
128
137
  * Compose with the generator.
@@ -314,3 +323,4 @@ export default class EnvironmentBase extends EventEmitter implements BaseEnviron
314
323
  */
315
324
  getContextMap(key: string, factory?: () => Map<string, any>): Map<string, any>;
316
325
  }
326
+ export {};
@@ -13,7 +13,6 @@ import { filePipeline, transform } from '@yeoman/transform';
13
13
  import { toNamespace } from '@yeoman/namespace';
14
14
  import chalk from 'chalk';
15
15
  import {} from '@yeoman/conflicter';
16
- import { defaults, pick } from 'lodash-es';
17
16
  import { ComposedStore } from "./composed-store.js";
18
17
  import Store, {} from "./store.js";
19
18
  import {} from "./generator-lookup.js";
@@ -21,7 +20,7 @@ import { UNKNOWN_NAMESPACE, UNKNOWN_RESOLVED, defaultQueues } from "./constants.
21
20
  import { resolveModulePath } from "./util/resolve.js";
22
21
  import { commitSharedFsTask } from "./commit.js";
23
22
  import { packageManagerInstallTask } from "./package-manager.js";
24
- import { splitArgsFromString as splitArgumentsFromString } from "./util/util.js";
23
+ import { defaults, pick, splitArgsFromString as splitArgumentsFromString } from "./util/util.js";
25
24
  const require = createRequire(import.meta.url);
26
25
  const ENVIRONMENT_VERSION = require('../package.json').version;
27
26
  const debug = createdLogger('yeoman:environment');
@@ -228,6 +227,17 @@ export default class EnvironmentBase extends EventEmitter {
228
227
  }
229
228
  return Generator;
230
229
  };
230
+ const instantiate = (Generator) => {
231
+ const checked = checkGenerator(Generator);
232
+ if (!namespace) {
233
+ return this.instantiate(checked, ...arguments_);
234
+ }
235
+ // Read after checkGenerator, which updates the namespace to the one of an aliased generator.
236
+ return this.instantiate(checked, {
237
+ ...getInstantiateOptions(...arguments_),
238
+ namespaceId: namespace.complete,
239
+ });
240
+ };
231
241
  if (typeof namespaceOrPath === 'string') {
232
242
  const meta = this.findMeta(namespaceOrPath);
233
243
  const constructor = meta?.importGenerator();
@@ -236,14 +246,12 @@ export default class EnvironmentBase extends EventEmitter {
236
246
  // constructor = await this.get(namespace);
237
247
  }
238
248
  if (constructor && 'then' in constructor) {
239
- return constructor.then(g => {
240
- return this.instantiate(checkGenerator(g), ...arguments_);
241
- });
249
+ return constructor.then(g => instantiate(g));
242
250
  }
243
- return this.instantiate(checkGenerator(constructor), ...arguments_);
251
+ return instantiate(constructor);
244
252
  }
245
253
  else {
246
- return this.instantiate(checkGenerator(namespaceOrPath), ...arguments_);
254
+ return instantiate(namespaceOrPath);
247
255
  }
248
256
  }
249
257
  instantiate(constructor, ...arguments_) {
@@ -251,7 +259,8 @@ export default class EnvironmentBase extends EventEmitter {
251
259
  const { namespace = UNKNOWN_NAMESPACE, resolved = UNKNOWN_RESOLVED } = constructor;
252
260
  // The generator class keeps the meta of the store, which may be shared: the generator gets the one of this environment.
253
261
  const _meta = this.bindMeta(constructor._meta);
254
- const environmentOptions = { env: this, resolved, namespace, _meta };
262
+ const { namespaceId } = composeOptions;
263
+ const environmentOptions = { env: this, resolved, namespace, _meta, ...(namespaceId && { namespaceId }) };
255
264
  const generator = new constructor(composeOptions.generatorArgs ?? [], {
256
265
  ...this.sharedOptions,
257
266
  ...composeOptions.generatorOptions,
@@ -8,13 +8,13 @@ declare class FullEnvironment extends EnvironmentBase {
8
8
  *
9
9
  * @param {Object} options
10
10
  */
11
- loadEnvironmentOptions(options: EnvironmentOptions): Pick<EnvironmentOptions, "skipInstall" | "nodePackageManager">;
11
+ loadEnvironmentOptions(options: EnvironmentOptions): Record<string, any>;
12
12
  /**
13
13
  * Load options passed to the Environment that should be forwarded to the Generator.
14
14
  *
15
15
  * @param {Object} options
16
16
  */
17
- loadSharedOptions(options: EnvironmentOptions): Pick<EnvironmentOptions, "askAnswered" | "skipInstall" | "forceInstall" | "skipCache" | "skipLocalCache" | "skipParseOptions" | "localConfigOnly">;
17
+ loadSharedOptions(options: EnvironmentOptions): Record<string, any>;
18
18
  /**
19
19
  * @protected
20
20
  * Outputs the general help and usage. Optionally, if generators have been
@@ -2,12 +2,11 @@ import { createHash } from 'node:crypto';
2
2
  import { join, resolve } from 'node:path';
3
3
  import { requireNamespace, toNamespace } from '@yeoman/namespace';
4
4
  import { flyImport } from 'fly-import';
5
- import { defaults, pick, uniq } from 'lodash-es';
6
5
  import { valid } from 'semver';
7
6
  import {} from "./generator-lookup.js";
8
7
  import YeomanCommand from "./util/command.js";
9
8
  import EnvironmentBase, {} from "./environment-base.js";
10
- import { splitArgsFromString as splitArgumentsFromString } from "./util/util.js";
9
+ import { defaults, pick, splitArgsFromString as splitArgumentsFromString } from "./util/util.js";
11
10
  import { nestedGeneratorsFolder } from "./util/namespace.js";
12
11
  class FullEnvironment extends EnvironmentBase {
13
12
  constructor(options = {}, adapterCompat) {
@@ -109,7 +108,7 @@ class FullEnvironment extends EnvironmentBase {
109
108
  * @return {Array}
110
109
  */
111
110
  getGeneratorNames() {
112
- return uniq(Object.keys(this.getGeneratorsMeta()).map(namespace => toNamespace(namespace)?.packageNamespace));
111
+ return [...new Set(Object.keys(this.getGeneratorsMeta()).map(namespace => toNamespace(namespace)?.packageNamespace))];
113
112
  }
114
113
  /**
115
114
  * Get last added path for a namespace
@@ -3,7 +3,6 @@ import { delimiter, dirname, join, resolve, sep } from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
4
  import process from 'node:process';
5
5
  import arrify from 'arrify';
6
- import { compact, uniq } from 'lodash-es';
7
6
  import { globbySync } from 'globby';
8
7
  import slash from 'slash';
9
8
  import createdLogger from 'debug';
@@ -141,7 +140,7 @@ export function getNpmPaths(options = {}) {
141
140
  if (!options.localOnly) {
142
141
  paths = paths.concat(getGlobalNpmPaths(options.filterPaths));
143
142
  }
144
- return uniq(paths);
143
+ return [...new Set(paths)];
145
144
  }
146
145
  /**
147
146
  * Get the local npm lookup directories
@@ -161,7 +160,7 @@ function getLocalNpmPaths() {
161
160
  }
162
161
  paths.push(lookup);
163
162
  });
164
- return uniq(paths.toReversed());
163
+ return [...new Set(paths.toReversed())];
165
164
  }
166
165
  /**
167
166
  * Get the global npm lookup directories
@@ -197,7 +196,7 @@ function getGlobalNpmPaths(filterPaths = true) {
197
196
  // because of bugs in the parseable implementation of `ls` command and mostly
198
197
  // performance issues. So, we go with our best bet for now.
199
198
  if (process.env.NODE_PATH) {
200
- paths = compact(process.env.NODE_PATH.split(delimiter)).concat(paths);
199
+ paths = process.env.NODE_PATH.split(delimiter).filter(Boolean).concat(paths);
201
200
  }
202
201
  // Global node_modules should be 4 or 2 directory up this one (most of the time)
203
202
  // Ex: /usr/another_global/node_modules/yeoman-denerator/node_modules/yeoman-environment/lib (1 level dependency)
@@ -228,5 +227,5 @@ function getGlobalNpmPaths(filterPaths = true) {
228
227
  if (process.argv[1]) {
229
228
  paths.push(...filterValidNpmPath(join(dirname(process.argv[1]), '../..'), !filterPaths));
230
229
  }
231
- return uniq(paths.filter(Boolean).toReversed());
230
+ return [...new Set(paths.filter(Boolean).toReversed())];
232
231
  }
@@ -1,6 +1,6 @@
1
1
  import { parse, posix } from 'node:path';
2
2
  import slash from 'slash';
3
- import { escapeRegExp, findLast } from 'lodash-es';
3
+ import { escapeRegExp } from "./util.js";
4
4
  /** The folder holding the generators nested in a generator. */
5
5
  export const nestedGeneratorsFolder = 'generators';
6
6
  /**
@@ -56,7 +56,7 @@ export const asNamespace = (filepath, { lookups = defaultLookups, nestedGenerato
56
56
  ns = ns.replaceAll(new RegExp(`(?:/|^)${escapeRegExp(lookup)}(?=/)`, 'g'), '');
57
57
  }
58
58
  const folders = ns.split('/');
59
- const scope = findLast(folders, folder => folder.startsWith('@'));
59
+ const scope = folders.findLast(folder => folder.startsWith('@'));
60
60
  // Cleanup `ns` from unwanted parts and then normalize slashes to `:`
61
61
  ns = ns
62
62
  .replaceAll('//', '') // Remove double `/`
@@ -4,3 +4,16 @@ export declare const execaOutput: (cmg: string, arguments_: string[]) => string
4
4
  * and then splits up the remaining arguments if they are not part of a quote.
5
5
  */
6
6
  export declare function splitArgsFromString(argumentsString: string | string[]): string[];
7
+ /**
8
+ * The properties of an object present in it (own or inherited), like lodash `pick`.
9
+ */
10
+ export declare const pick: (object: object | undefined, keys: readonly string[]) => Record<string, any>;
11
+ /**
12
+ * Assign to the target the properties of the sources it has as undefined, the first source first, like lodash
13
+ * `defaults`.
14
+ */
15
+ export declare const defaults: <T extends object>(target: T, ...sources: Array<object | undefined>) => T;
16
+ /**
17
+ * Escape the characters with a meaning in a regular expression, like lodash `escapeRegExp`.
18
+ */
19
+ export declare const escapeRegExp: (value: string) => string;
package/dist/util/util.js CHANGED
@@ -34,3 +34,27 @@ export function splitArgsFromString(argumentsString) {
34
34
  }
35
35
  return result;
36
36
  }
37
+ /**
38
+ * The properties of an object present in it (own or inherited), like lodash `pick`.
39
+ */
40
+ export const pick = (object, keys) => Object.fromEntries(object ? keys.filter(key => key in object).map(key => [key, object[key]]) : []);
41
+ /**
42
+ * Assign to the target the properties of the sources it has as undefined, the first source first, like lodash
43
+ * `defaults`.
44
+ */
45
+ export const defaults = (target, ...sources) => {
46
+ for (const source of sources) {
47
+ if (!source)
48
+ continue;
49
+ for (const key in source) {
50
+ if (target[key] === undefined) {
51
+ target[key] = source[key];
52
+ }
53
+ }
54
+ }
55
+ return target;
56
+ };
57
+ /**
58
+ * Escape the characters with a meaning in a regular expression, like lodash `escapeRegExp`.
59
+ */
60
+ export const escapeRegExp = (value) => value.replaceAll(/[\\^$.*+?()[\]{}|]/g, String.raw `\$&`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yeoman-environment",
3
- "version": "8.2.0",
3
+ "version": "8.3.0",
4
4
  "description": "Handles the lifecyle and bootstrapping of generators in a specific environment",
5
5
  "keywords": [
6
6
  "development",
@@ -72,7 +72,6 @@
72
72
  "globby": "^16.2.4",
73
73
  "grouped-queue": "^2.1.0",
74
74
  "locate-path": "^8.0.0",
75
- "lodash-es": "^4.18.1",
76
75
  "mem-fs": "^6.0.0",
77
76
  "mem-fs-editor": "^12.0.9",
78
77
  "semver": "^7.8.5",
@@ -82,7 +81,6 @@
82
81
  },
83
82
  "devDependencies": {
84
83
  "@types/debug": "^4.1.13",
85
- "@types/lodash-es": "^4.17.12",
86
84
  "@types/node": "^26.4.1",
87
85
  "@types/semver": "^7.8.0",
88
86
  "@yeoman/eslint": "1.1.0",