yeoman-environment 8.3.0 → 8.5.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.
Files changed (46) hide show
  1. package/dist/{util → cli}/command.d.ts +1 -1
  2. package/dist/{commands.d.ts → cli/commands.d.ts} +1 -1
  3. package/dist/{commands.js → cli/commands.js} +3 -3
  4. package/dist/cli/index.js +4 -4
  5. package/dist/cli/utils.d.ts +1 -1
  6. package/dist/cli/utils.js +2 -2
  7. package/dist/{commit.d.ts → environment/commit.d.ts} +2 -2
  8. package/dist/{commit.js → environment/commit.js} +2 -2
  9. package/dist/{environment-base.d.ts → environment/environment-base.d.ts} +4 -5
  10. package/dist/{environment-base.js → environment/environment-base.js} +6 -8
  11. package/dist/{environment-full.d.ts → environment/environment-full.d.ts} +1 -1
  12. package/dist/{environment-full.js → environment/environment-full.js} +4 -4
  13. package/dist/{package-manager.js → environment/package-manager.js} +4 -3
  14. package/dist/{util → environment}/resolve.js +1 -1
  15. package/dist/index.d.ts +10 -10
  16. package/dist/index.js +9 -10
  17. package/dist/store/index.d.ts +5 -0
  18. package/dist/store/index.js +6 -0
  19. package/dist/store/lookup-generator.d.ts +26 -0
  20. package/dist/store/lookup-generator.js +32 -0
  21. package/dist/{generator-lookup.d.ts → store/lookup.d.ts} +0 -24
  22. package/dist/{generator-lookup.js → store/lookup.js} +3 -32
  23. package/dist/{module-lookup.js → store/module-lookup.js} +2 -2
  24. package/dist/{util → store}/namespace.js +1 -1
  25. package/dist/store/public.d.ts +1 -0
  26. package/dist/store/public.js +2 -0
  27. package/dist/{store.d.ts → store/store.d.ts} +5 -1
  28. package/dist/{store.js → store/store.js} +37 -4
  29. package/dist/util/args.d.ts +5 -0
  30. package/dist/util/args.js +23 -0
  31. package/dist/util/exec.d.ts +5 -0
  32. package/dist/util/exec.js +19 -0
  33. package/dist/util/object.d.ts +9 -0
  34. package/dist/util/object.js +20 -0
  35. package/dist/util/regexp.d.ts +4 -0
  36. package/dist/util/regexp.js +4 -0
  37. package/package.json +8 -4
  38. package/dist/util/util.d.ts +0 -19
  39. package/dist/util/util.js +0 -60
  40. /package/dist/{util → cli}/command.js +0 -0
  41. /package/dist/{composed-store.d.ts → environment/composed-store.d.ts} +0 -0
  42. /package/dist/{composed-store.js → environment/composed-store.js} +0 -0
  43. /package/dist/{package-manager.d.ts → environment/package-manager.d.ts} +0 -0
  44. /package/dist/{util → environment}/resolve.d.ts +0 -0
  45. /package/dist/{module-lookup.d.ts → store/module-lookup.d.ts} +0 -0
  46. /package/dist/{util → store}/namespace.d.ts +0 -0
@@ -1,5 +1,5 @@
1
1
  import { Command, Option } from 'commander';
2
- import type BaseEnvironment from '../environment-base.ts';
2
+ import type BaseEnvironment from '../environment/environment-base.ts';
3
3
  export default class YeomanCommand extends Command {
4
4
  #private;
5
5
  env?: BaseEnvironment;
@@ -1,5 +1,5 @@
1
1
  import type { BaseGeneratorConstructor } from '@yeoman/types';
2
- import YeomanCommand from './util/command.ts';
2
+ import YeomanCommand from './command.ts';
3
3
  export type CommandPreparation = {
4
4
  resolved?: string;
5
5
  command?: YeomanCommand;
@@ -1,5 +1,5 @@
1
- import YeomanCommand, { addEnvironmentOptions } from "./util/command.js";
2
- import { createEnv as createEnvironment } from "./index.js";
1
+ import YeomanCommand, { addEnvironmentOptions } from "./command.js";
2
+ import Environment from "../environment/environment-full.js";
3
3
  /**
4
4
  * Prepare a commander instance for cli support.
5
5
  *
@@ -8,7 +8,7 @@ import { createEnv as createEnvironment } from "./index.js";
8
8
  * @return {Command} return command
9
9
  */
10
10
  export const prepareGeneratorCommand = async ({ command = addEnvironmentOptions(new YeomanCommand()), resolved, generator, namespace, }) => {
11
- const environment = createEnvironment();
11
+ const environment = new Environment();
12
12
  let meta;
13
13
  if (generator && namespace) {
14
14
  meta = environment.register(generator, { namespace, resolved });
package/dist/cli/index.js CHANGED
@@ -2,8 +2,8 @@ import { readFileSync } from 'node:fs';
2
2
  import process from 'node:process';
3
3
  import { dirname, resolve } from 'node:path';
4
4
  import { fileURLToPath } from 'node:url';
5
- import YeomanCommand, { addEnvironmentOptions } from "../util/command.js";
6
- import { createEnv as createEnvironment } from "../index.js";
5
+ import YeomanCommand, { addEnvironmentOptions } from "./command.js";
6
+ import Environment from "../environment/environment-full.js";
7
7
  import { environmentAction, printGroupedGenerator } from "./utils.js";
8
8
  const program = new YeomanCommand();
9
9
  const packageJson = JSON.parse(readFileSync(resolve(dirname(fileURLToPath(import.meta.url)), '../../package.json')).toString());
@@ -21,14 +21,14 @@ program
21
21
  .command('find')
22
22
  .description('Find installed generators')
23
23
  .action(async () => {
24
- const environment = createEnvironment();
24
+ const environment = new Environment();
25
25
  printGroupedGenerator(await environment.lookup());
26
26
  });
27
27
  program
28
28
  .command('list')
29
29
  .description('List generators available to be used')
30
30
  .action(async () => {
31
- const environment = createEnvironment();
31
+ const environment = new Environment();
32
32
  await environment.lookup();
33
33
  printGroupedGenerator(Object.values(environment.getGeneratorsMeta()));
34
34
  });
@@ -1,5 +1,5 @@
1
1
  import type { BaseGeneratorMeta } from '@yeoman/types';
2
- import type YeomanCommand from '../util/command.ts';
2
+ import type YeomanCommand from './command.ts';
3
3
  export declare const printGroupedGenerator: (generators: BaseGeneratorMeta[]) => void;
4
4
  /**
5
5
  * @param {string} generatorNamespace
package/dist/cli/utils.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { requireNamespace } from '@yeoman/namespace';
2
2
  import createLogger from 'debug';
3
- import { createEnv as createEnvironment } from "../index.js";
3
+ import Environment from "../environment/environment-full.js";
4
4
  const debug = createLogger('yeoman:yoe');
5
5
  export const printGroupedGenerator = (generators) => {
6
6
  const grouped = new Map();
@@ -30,7 +30,7 @@ export const environmentAction = async function (generatorNamespace, options, co
30
30
  if (!generatorNamespace) {
31
31
  return;
32
32
  }
33
- const environment = createEnvironment({ ...options, command: this });
33
+ const environment = new Environment({ ...options, command: this });
34
34
  this.env = environment;
35
35
  await environment.lookupLocalPackages();
36
36
  return environment.execute(generatorNamespace, command.args.splice(1));
@@ -1,7 +1,7 @@
1
1
  import type { InputOutputAdapter } from '@yeoman/types';
2
- import { type ConflicterOptions } from '@yeoman/conflicter';
2
+ import type { ConflicterOptions } from '@yeoman/conflicter';
3
3
  import type { Store } from 'mem-fs';
4
- import { type MemFsEditorFile } from 'mem-fs-editor';
4
+ import type { MemFsEditorFile } from 'mem-fs-editor';
5
5
  /**
6
6
  * Commits the MemFs to the disc.
7
7
  */
@@ -1,6 +1,4 @@
1
- import { createConflicterTransform, createYoResolveTransform, forceYoFiles } from '@yeoman/conflicter';
2
1
  import createdLogger from 'debug';
3
- import {} from 'mem-fs-editor';
4
2
  import { createCommitTransform } from 'mem-fs-editor/transform';
5
3
  import { isFilePending } from 'mem-fs-editor/state';
6
4
  const debug = createdLogger('yeoman:environment:commit');
@@ -9,5 +7,7 @@ const debug = createdLogger('yeoman:environment:commit');
9
7
  */
10
8
  export const commitSharedFsTask = async ({ adapter, conflicterOptions, sharedFs, }) => {
11
9
  debug('Running commitSharedFsTask');
10
+ // The conflicter is loaded by the commit only.
11
+ const { createConflicterTransform, createYoResolveTransform, forceYoFiles } = await import('@yeoman/conflicter');
12
12
  await sharedFs.pipeline({ filter: (file) => isFilePending(file) || file.path.endsWith('.yo-resolve') }, createYoResolveTransform(), forceYoFiles(), createConflicterTransform(adapter, conflicterOptions), createCommitTransform());
13
13
  };
@@ -2,16 +2,15 @@ import EventEmitter from 'node:events';
2
2
  import { QueuedAdapter, type TerminalAdapterOptions } from '@yeoman/adapter';
3
3
  import type { ApplyTransformsOptions, BaseEnvironment, BaseEnvironmentOptions, BaseGenerator, BaseGeneratorConstructorMeta, BaseGeneratorMeta, ComposeOptions, GeneratorMeta, GetGeneratorConstructor, InputOutputAdapter, InstantiateOptions, LookupGeneratorMeta } from '@yeoman/types';
4
4
  import { type Store as MemFs } from 'mem-fs';
5
- import { type MemFsEditorFile } from 'mem-fs-editor';
5
+ import type { MemFsEditorFile } from 'mem-fs-editor';
6
6
  import { FlyRepository } from 'fly-import';
7
7
  import GroupedQueue from 'grouped-queue';
8
8
  import { type FilePipelineTransform } from '@yeoman/transform';
9
9
  import { type YeomanNamespace } from '@yeoman/namespace';
10
- import { type ConflicterOptions } from '@yeoman/conflicter';
10
+ import type { ConflicterOptions } from '@yeoman/conflicter';
11
11
  import { ComposedStore } from './composed-store.ts';
12
- import Store, { type StoreGeneratorMeta, type StoreSharedLookupOptions } from './store.ts';
13
- import type YeomanCommand from './util/command.ts';
14
- import { type LookupOptions } from './generator-lookup.ts';
12
+ import { type LookupOptions, Store, type StoreGeneratorMeta, type StoreSharedLookupOptions } from '../store/index.ts';
13
+ import type YeomanCommand from '../cli/command.ts';
15
14
  import { type InstallTask } from './package-manager.ts';
16
15
  export type EnvironmentLookupOptions = LookupOptions & {
17
16
  /** Add a scope to the namespace if there is no scope */
@@ -4,7 +4,6 @@ import { isAbsolute, join, relative, resolve } from 'node:path';
4
4
  import process from 'node:process';
5
5
  import { QueuedAdapter } from '@yeoman/adapter';
6
6
  import { create as createMemFs } from 'mem-fs';
7
- import {} from 'mem-fs-editor';
8
7
  import { FlyRepository } from 'fly-import';
9
8
  import createdLogger from 'debug';
10
9
  import GroupedQueue from 'grouped-queue';
@@ -12,17 +11,16 @@ import { isFilePending } from 'mem-fs-editor/state';
12
11
  import { filePipeline, transform } from '@yeoman/transform';
13
12
  import { toNamespace } from '@yeoman/namespace';
14
13
  import chalk from 'chalk';
15
- import {} from '@yeoman/conflicter';
16
14
  import { ComposedStore } from "./composed-store.js";
17
- import Store, {} from "./store.js";
18
- import {} from "./generator-lookup.js";
19
- import { UNKNOWN_NAMESPACE, UNKNOWN_RESOLVED, defaultQueues } from "./constants.js";
20
- import { resolveModulePath } from "./util/resolve.js";
15
+ import { Store } from "../store/index.js";
16
+ import { UNKNOWN_NAMESPACE, UNKNOWN_RESOLVED, defaultQueues } from "../constants.js";
17
+ import { resolveModulePath } from "./resolve.js";
21
18
  import { commitSharedFsTask } from "./commit.js";
22
19
  import { packageManagerInstallTask } from "./package-manager.js";
23
- import { defaults, pick, splitArgsFromString as splitArgumentsFromString } from "./util/util.js";
20
+ import { splitArgsFromString as splitArgumentsFromString } from "../util/args.js";
21
+ import { defaults, pick } from "../util/object.js";
24
22
  const require = createRequire(import.meta.url);
25
- const ENVIRONMENT_VERSION = require('../package.json').version;
23
+ const ENVIRONMENT_VERSION = require('../../package.json').version;
26
24
  const debug = createdLogger('yeoman:environment');
27
25
  const getInstantiateOptions = (firstArg, generatorOptions) => {
28
26
  // First argument can be an array of string, a string, a ComposeOptions, a GeneratorOptions, old variant of ComposeOptions.
@@ -1,6 +1,6 @@
1
1
  import type { BaseGeneratorConstructor, BaseGeneratorOptions, GeneratorEnvironmentOptions, GeneratorMeta } from '@yeoman/types';
2
- import { type LookupOptions } from './generator-lookup.ts';
3
2
  import EnvironmentBase, { type EnvironmentOptions } from './environment-base.ts';
3
+ import { type LookupOptions } from '../store/index.ts';
4
4
  declare class FullEnvironment extends EnvironmentBase {
5
5
  constructor(options?: EnvironmentOptions);
6
6
  /**
@@ -3,11 +3,11 @@ import { join, resolve } from 'node:path';
3
3
  import { requireNamespace, toNamespace } from '@yeoman/namespace';
4
4
  import { flyImport } from 'fly-import';
5
5
  import { valid } from 'semver';
6
- import {} from "./generator-lookup.js";
7
- import YeomanCommand from "./util/command.js";
6
+ import YeomanCommand from "../cli/command.js";
8
7
  import EnvironmentBase, {} from "./environment-base.js";
9
- import { defaults, pick, splitArgsFromString as splitArgumentsFromString } from "./util/util.js";
10
- import { nestedGeneratorsFolder } from "./util/namespace.js";
8
+ import { splitArgsFromString as splitArgumentsFromString } from "../util/args.js";
9
+ import { defaults, pick } from "../util/object.js";
10
+ import { nestedGeneratorsFolder } from "../store/index.js";
11
11
  class FullEnvironment extends EnvironmentBase {
12
12
  constructor(options = {}, adapterCompat) {
13
13
  if (adapterCompat) {
@@ -1,7 +1,5 @@
1
1
  import { join, resolve } from 'node:path';
2
2
  import createdLogger from 'debug';
3
- import { whichPackageManager } from 'which-package-manager';
4
- import { execa } from 'execa';
5
3
  const debug = createdLogger('yeoman:environment:package-manager');
6
4
  /**
7
5
  * Executes package manager install.
@@ -56,7 +54,9 @@ Changes to package.json were detected.`);
56
54
  `);
57
55
  return false;
58
56
  }
59
- let packageManagerName = nodePackageManager ?? (await whichPackageManager({ cwd: packageJsonLocation }));
57
+ // which-package-manager and execa are loaded by an install only.
58
+ let packageManagerName = nodePackageManager ??
59
+ (await import('which-package-manager').then(({ whichPackageManager }) => whichPackageManager({ cwd: packageJsonLocation })));
60
60
  const execPackageManager = async () => {
61
61
  if (!packageManagerName) {
62
62
  packageManagerName = 'npm';
@@ -68,6 +68,7 @@ Changes to package.json were detected.`);
68
68
  }
69
69
  adapter.log(`
70
70
  Running ${packageManagerName} install for you to install the required dependencies.`);
71
+ const { execa } = await import('execa');
71
72
  await execa(packageManagerName, ['install'], { stdio: 'inherit', cwd: packageJsonLocation });
72
73
  return true;
73
74
  };
@@ -2,7 +2,7 @@ import { dirname, extname, join, normalize, resolve, sep } from 'node:path';
2
2
  import { realpathSync, statSync } from 'node:fs';
3
3
  import untildify from 'untildify';
4
4
  import { locatePathSync } from 'locate-path';
5
- import { defaultExtensions } from "../generator-lookup.js";
5
+ import { defaultExtensions } from "../store/index.js";
6
6
  /**
7
7
  * Resolve a module path
8
8
  * @param specifier - Filepath or module name
package/dist/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
- import { type EnvironmentOptions } from './environment-base.ts';
2
- import Environment from './environment-full.ts';
3
- export { default } from './environment-full.ts';
4
- export { default as EnvironmentBase, type EnvironmentOptions } from './environment-base.ts';
5
- export { default as Store, type StoreEnvironmentOptions, type StoreGeneratorMeta, type StoreLookupGeneratorMeta, type StoreLookupOptions, type StoreSharedLookupOptions, } from './store.ts';
1
+ import type { EnvironmentOptions } from './environment/environment-base.ts';
2
+ import Environment from './environment/environment-full.ts';
3
+ export { default } from './environment/environment-full.ts';
4
+ export { default as EnvironmentBase, type EnvironmentOptions } from './environment/environment-base.ts';
5
+ export { Store, type StoreEnvironmentOptions, type StoreGeneratorMeta, type StoreLookupGeneratorMeta, type StoreLookupOptions, type StoreSharedLookupOptions, } from './store/index.ts';
6
6
  export declare const createEnv: (options?: EnvironmentOptions) => Environment;
7
7
  export declare const enforceUpdate: () => void;
8
- export { type CommandPreparation, prepareCommand, prepareGeneratorCommand } from './commands.ts';
9
- export { addEnvironmentOptions } from './util/command.ts';
10
- export { type InstallTask, type PackageManagerInstallTaskOptions, packageManagerInstallTask } from './package-manager.ts';
11
- export { commitSharedFsTask } from './commit.ts';
12
- export { lookupGenerator } from './generator-lookup.ts';
8
+ export { type CommandPreparation, prepareCommand, prepareGeneratorCommand } from './cli/commands.ts';
9
+ export { addEnvironmentOptions } from './cli/command.ts';
10
+ export { type InstallTask, type PackageManagerInstallTaskOptions, packageManagerInstallTask } from './environment/package-manager.ts';
11
+ export { commitSharedFsTask } from './environment/commit.ts';
12
+ export { lookupGenerator } from './store/index.ts';
package/dist/index.js CHANGED
@@ -1,14 +1,13 @@
1
- import {} from "./environment-base.js";
2
- import Environment from "./environment-full.js";
3
- export { default } from "./environment-full.js";
4
- export { default as EnvironmentBase } from "./environment-base.js";
1
+ import Environment from "./environment/environment-full.js";
2
+ export { default } from "./environment/environment-full.js";
3
+ export { default as EnvironmentBase } from "./environment/environment-base.js";
5
4
  // Experimental: the Store API is not stable yet.
6
- export { default as Store, } from "./store.js";
5
+ export { Store, } from "./store/index.js";
7
6
  export const createEnv = (options) => new Environment(options);
8
7
  // Backward compatibility
9
8
  export const enforceUpdate = () => { };
10
- export { prepareCommand, prepareGeneratorCommand } from "./commands.js";
11
- export { addEnvironmentOptions } from "./util/command.js";
12
- export { packageManagerInstallTask } from "./package-manager.js";
13
- export { commitSharedFsTask } from "./commit.js";
14
- export { lookupGenerator } from "./generator-lookup.js";
9
+ export { prepareCommand, prepareGeneratorCommand } from "./cli/commands.js";
10
+ export { addEnvironmentOptions } from "./cli/command.js";
11
+ export { packageManagerInstallTask } from "./environment/package-manager.js";
12
+ export { commitSharedFsTask } from "./environment/commit.js";
13
+ export { lookupGenerator } from "./store/index.js";
@@ -0,0 +1,5 @@
1
+ export { default as Store, type StoreEnvironmentOptions, type StoreGeneratorMeta, type StoreLookupGeneratorMeta, type StoreLookupOptions, type StoreSharedLookupOptions, } from './store.ts';
2
+ export { type LookupOptions, defaultExtensions, lookupGeneratorsSync } from './lookup.ts';
3
+ export { lookupGenerator } from './lookup-generator.ts';
4
+ export { type ModuleLookupOptions, findPackagesIn, getNpmPaths, moduleLookupSync } from './module-lookup.ts';
5
+ export { asNamespace, defaultLookups, nestedGeneratorsFolder, withNestedLookups } from './namespace.ts';
@@ -0,0 +1,6 @@
1
+ // The store and its lookups, for the modules of the package: public.ts is the module of yeoman-environment/store.
2
+ export { default as Store, } from "./store.js";
3
+ export { defaultExtensions, lookupGeneratorsSync } from "./lookup.js";
4
+ export { lookupGenerator } from "./lookup-generator.js";
5
+ export { findPackagesIn, getNpmPaths, moduleLookupSync } from "./module-lookup.js";
6
+ export { asNamespace, defaultLookups, nestedGeneratorsFolder, withNestedLookups } from "./namespace.js";
@@ -0,0 +1,26 @@
1
+ import { type ModuleLookupOptions } from './module-lookup.ts';
2
+ import type { LookupOptions } from './lookup.ts';
3
+ /**
4
+ * Lookup for a specific generator.
5
+ *
6
+ * @param {String} namespace
7
+ * @param {Object} [options]
8
+ * @param {Boolean} [options.localOnly=false] - Set true to skip lookups of
9
+ * globally-installed generators.
10
+ * @param {Boolean} [options.packagePath=false] - Set true to return the package
11
+ * path instead of generators file.
12
+ * @param {Boolean} [options.singleResult=true] - Set false to return multiple values.
13
+ * @return {String} generator
14
+ */
15
+ export declare function lookupGenerator(namespace: string, options?: ModuleLookupOptions & Pick<LookupOptions, 'nestedGenerators'> & {
16
+ packagePath?: boolean;
17
+ generatorPath?: boolean;
18
+ } & {
19
+ singleResult?: true;
20
+ }): string;
21
+ export declare function lookupGenerator(namespace: string, options?: ModuleLookupOptions & Pick<LookupOptions, 'nestedGenerators'> & {
22
+ packagePath?: boolean;
23
+ generatorPath?: boolean;
24
+ } & {
25
+ singleResult: false;
26
+ }): string[];
@@ -0,0 +1,32 @@
1
+ import { isAbsolute, join, posix } from 'node:path';
2
+ import { pathToFileURL } from 'node:url';
3
+ import { requireNamespace, toNamespace } from '@yeoman/namespace';
4
+ import { findPackagesIn, getNpmPaths } from "./module-lookup.js";
5
+ import { defaultLookups, withNestedLookups } from "./namespace.js";
6
+ import Store from "./store.js";
7
+ export function lookupGenerator(namespace, options) {
8
+ options = typeof options === 'boolean' ? { localOnly: options } : (options ?? {});
9
+ const { packagePath: returnPackagePath, generatorPath: returnGeneratorPath, singleResult = true, ...lookupOptions } = options;
10
+ const ns = requireNamespace(namespace);
11
+ lookupOptions.packagePatterns = lookupOptions.packagePatterns ?? [ns.generatorHint];
12
+ if (!lookupOptions.packagePaths) {
13
+ // Looking the npm paths up runs the package managers, skip it when the packages are given.
14
+ lookupOptions.npmPaths = lookupOptions.npmPaths ?? getNpmPaths({ localOnly: lookupOptions.localOnly }).toReversed();
15
+ lookupOptions.packagePaths = findPackagesIn(lookupOptions.npmPaths, lookupOptions.packagePatterns);
16
+ }
17
+ // The generators are looked up by a store of their own, which keeps the ones asked for.
18
+ const generators = new Store().lookupSync({
19
+ filePatterns: withNestedLookups(defaultLookups, lookupOptions.nestedGenerators).map(prefix => join(prefix, '*/index.{js,ts}')),
20
+ reverse: false,
21
+ ...lookupOptions,
22
+ lookups: defaultLookups,
23
+ singleResult,
24
+ filter: generator => generator.namespace === namespace || Boolean(returnPackagePath && toNamespace(generator.namespace)?.packageNamespace === namespace),
25
+ });
26
+ const paths = generators.map(({ filePath, packagePath }) => {
27
+ // Version 2.6.0 returned pattern instead of modulePath for options.packagePath
28
+ const returnPath = returnPackagePath ? packagePath : returnGeneratorPath ? posix.join(filePath, '../../') : filePath;
29
+ return isAbsolute(returnPath) ? pathToFileURL(returnPath).toString() : returnPath;
30
+ });
31
+ return singleResult ? paths[0] : paths;
32
+ }
@@ -42,28 +42,4 @@ export declare function lookupGeneratorsSync(options?: LookupOptions, register?:
42
42
  filePath: string;
43
43
  packagePath: string;
44
44
  }[];
45
- /**
46
- * Lookup for a specific generator.
47
- *
48
- * @param {String} namespace
49
- * @param {Object} [options]
50
- * @param {Boolean} [options.localOnly=false] - Set true to skip lookups of
51
- * globally-installed generators.
52
- * @param {Boolean} [options.packagePath=false] - Set true to return the package
53
- * path instead of generators file.
54
- * @param {Boolean} [options.singleResult=true] - Set false to return multiple values.
55
- * @return {String} generator
56
- */
57
- export declare function lookupGenerator(namespace: string, options?: ModuleLookupOptions & Pick<LookupOptions, 'nestedGenerators'> & {
58
- packagePath?: boolean;
59
- generatorPath?: boolean;
60
- } & {
61
- singleResult?: true;
62
- }): string;
63
- export declare function lookupGenerator(namespace: string, options?: ModuleLookupOptions & Pick<LookupOptions, 'nestedGenerators'> & {
64
- packagePath?: boolean;
65
- generatorPath?: boolean;
66
- } & {
67
- singleResult: false;
68
- }): string[];
69
45
  export {};
@@ -1,9 +1,6 @@
1
- import { extname, isAbsolute, join, posix } from 'node:path';
2
- import { pathToFileURL } from 'node:url';
3
- import { requireNamespace, toNamespace } from '@yeoman/namespace';
4
- import { findPackagesIn, getNpmPaths, moduleLookupSync } from "./module-lookup.js";
5
- import { defaultLookups, withNestedLookups } from "./util/namespace.js";
6
- import Store from "./store.js";
1
+ import { extname } from 'node:path';
2
+ import { moduleLookupSync } from "./module-lookup.js";
3
+ import { defaultLookups, withNestedLookups } from "./namespace.js";
7
4
  export const defaultExtensions = ['.ts', '.cts', '.mts', '.js', '.cjs', '.mjs'];
8
5
  /**
9
6
  * Search for generators and their sub generators.
@@ -52,29 +49,3 @@ export function lookupGeneratorsSync(options = {}, register) {
52
49
  return;
53
50
  });
54
51
  }
55
- export function lookupGenerator(namespace, options) {
56
- options = typeof options === 'boolean' ? { localOnly: options } : (options ?? {});
57
- const { packagePath: returnPackagePath, generatorPath: returnGeneratorPath, singleResult = true, ...lookupOptions } = options;
58
- const ns = requireNamespace(namespace);
59
- lookupOptions.packagePatterns = lookupOptions.packagePatterns ?? [ns.generatorHint];
60
- if (!lookupOptions.packagePaths) {
61
- // Looking the npm paths up runs the package managers, skip it when the packages are given.
62
- lookupOptions.npmPaths = lookupOptions.npmPaths ?? getNpmPaths({ localOnly: lookupOptions.localOnly }).toReversed();
63
- lookupOptions.packagePaths = findPackagesIn(lookupOptions.npmPaths, lookupOptions.packagePatterns);
64
- }
65
- // The generators are looked up by a store of their own, which keeps the ones asked for.
66
- const generators = new Store().lookupSync({
67
- filePatterns: withNestedLookups(defaultLookups, lookupOptions.nestedGenerators).map(prefix => join(prefix, '*/index.{js,ts}')),
68
- reverse: false,
69
- ...lookupOptions,
70
- lookups: defaultLookups,
71
- singleResult,
72
- filter: generator => generator.namespace === namespace || Boolean(returnPackagePath && toNamespace(generator.namespace)?.packageNamespace === namespace),
73
- });
74
- const paths = generators.map(({ filePath, packagePath }) => {
75
- // Version 2.6.0 returned pattern instead of modulePath for options.packagePath
76
- const returnPath = returnPackagePath ? packagePath : returnGeneratorPath ? posix.join(filePath, '../../') : filePath;
77
- return isAbsolute(returnPath) ? pathToFileURL(returnPath).toString() : returnPath;
78
- });
79
- return singleResult ? paths[0] : paths;
80
- }
@@ -6,10 +6,10 @@ import arrify from 'arrify';
6
6
  import { globbySync } from 'globby';
7
7
  import slash from 'slash';
8
8
  import createdLogger from 'debug';
9
- import { execaOutput } from "./util/util.js";
9
+ import { execaOutput } from "../util/exec.js";
10
10
  const __filename = fileURLToPath(import.meta.url);
11
11
  const __dirname = dirname(__filename);
12
- const PROJECT_ROOT = join(__dirname, '..');
12
+ const PROJECT_ROOT = join(__dirname, '../..');
13
13
  const PACKAGE_NAME_PATTERN = [JSON.parse(readFileSync(join(PROJECT_ROOT, 'package.json')).toString()).name];
14
14
  const win32 = process.platform === 'win32';
15
15
  const nvm = process.env.NVM_HOME;
@@ -1,6 +1,6 @@
1
1
  import { parse, posix } from 'node:path';
2
2
  import slash from 'slash';
3
- import { escapeRegExp } from "./util.js";
3
+ import { escapeRegExp } from "../util/regexp.js";
4
4
  /** The folder holding the generators nested in a generator. */
5
5
  export const nestedGeneratorsFolder = 'generators';
6
6
  /**
@@ -0,0 +1 @@
1
+ export { default, default as Store, type StoreEnvironmentOptions, type StoreGeneratorMeta, type StoreLookupGeneratorMeta, type StoreLookupOptions, type StoreSharedLookupOptions, } from './store.ts';
@@ -0,0 +1,2 @@
1
+ // The module of yeoman-environment/store: the store alone, without the environment.
2
+ export { default, default as Store, } from "./store.js";
@@ -1,5 +1,5 @@
1
1
  import type { BaseEnvironment, BaseGenerator, BaseGeneratorConstructorMeta, BaseGeneratorMeta, GeneratorMeta, GetGeneratorConstructor } from '@yeoman/types';
2
- import { type LookupOptions } from './generator-lookup.ts';
2
+ import { type LookupOptions } from './lookup.ts';
3
3
  type FoundGenerator = {
4
4
  namespace: string;
5
5
  /** Path of the generator as it was found, `resolved` is its real path. */
@@ -37,6 +37,10 @@ export type StoreLookupGeneratorMeta = FoundGenerator & ((StoreGeneratorMeta & {
37
37
  export type StoreGeneratorMeta = Omit<GeneratorMeta, 'importGenerator' | 'instantiate' | 'instantiateHelp'> & {
38
38
  /** Require the module `require(meta.resolved)`, throws if the module cannot be required synchronously. */
39
39
  requireModule?: () => unknown;
40
+ /** Require the sibling module of the name, like `command.ts` next to `index.ts`, `undefined` if missing. */
41
+ requireSibling?: (name: string) => unknown;
42
+ /** Import the sibling module of the name, like `requireSibling` for a module that can not be required. */
43
+ importSibling?: (name: string) => Promise<unknown>;
40
44
  importGenerator: <G extends BaseGenerator = BaseGenerator>(options?: StoreEnvironmentOptions) => Promise<GetGeneratorConstructor<G> & BaseGeneratorConstructorMeta> | (GetGeneratorConstructor<G> & BaseGeneratorConstructorMeta);
41
45
  instantiate: <G extends BaseGenerator = BaseGenerator>(arguments_?: string[], options?: any, environmentOptions?: StoreEnvironmentOptions) => Promise<G>;
42
46
  instantiateHelp: <G extends BaseGenerator = BaseGenerator>(options?: StoreEnvironmentOptions) => Promise<G>;
@@ -7,19 +7,51 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
7
7
  return path;
8
8
  };
9
9
  import { pathToFileURL } from 'node:url';
10
- import { basename, extname, join, relative } from 'node:path';
10
+ import { basename, dirname, extname, join, relative } from 'node:path';
11
11
  import { createRequire } from 'node:module';
12
- import { readFileSync, realpathSync } from 'node:fs';
12
+ import { existsSync, readFileSync, realpathSync } from 'node:fs';
13
13
  import { namespaceFromPackageName, toNamespace } from '@yeoman/namespace';
14
14
  import createDebug from 'debug';
15
- import { lookupGeneratorsSync } from "./generator-lookup.js";
16
- import { asNamespace, defaultLookups } from "./util/namespace.js";
15
+ import { lookupGeneratorsSync } from "./lookup.js";
16
+ import { asNamespace, defaultLookups } from "./namespace.js";
17
17
  const debug = createDebug('yeoman:environment:store');
18
18
  const require = createRequire(import.meta.url);
19
19
  // The operations of a meta, kept on the meta itself: the meta of a clone has the operations of the meta it was cloned from.
20
20
  const operationsKey = Symbol('operations');
21
21
  const setOperations = (meta, operations) => Object.defineProperty(meta, operationsKey, { value: operations });
22
22
  const getOperations = (meta) => meta[operationsKey];
23
+ /** The functions loading the modules next to a generator module, with its extension. */
24
+ const createSiblingFunctions = (resolved) => {
25
+ if (typeof resolved !== 'string' || !extname(resolved)) {
26
+ return {};
27
+ }
28
+ const folder = dirname(resolved);
29
+ const extension = extname(resolved);
30
+ const siblingPath = (name) => {
31
+ const filePath = join(folder, `${name}${extension}`);
32
+ return existsSync(filePath) ? filePath : undefined;
33
+ };
34
+ const requireSibling = (name) => {
35
+ const filePath = siblingPath(name);
36
+ return filePath ? require(filePath) : undefined;
37
+ };
38
+ const importSibling = async (name) => {
39
+ const filePath = siblingPath(name);
40
+ if (!filePath) {
41
+ return undefined;
42
+ }
43
+ try {
44
+ return require(filePath);
45
+ }
46
+ catch (error) {
47
+ if (error.code === 'ERR_REQUIRE_ESM' || error.code === 'ERR_REQUIRE_ASYNC_MODULE') {
48
+ return import(__rewriteRelativeImportExtension(pathToFileURL(filePath).href));
49
+ }
50
+ throw error;
51
+ }
52
+ };
53
+ return { requireSibling, importSibling };
54
+ };
23
55
  /** The namespace of a generator package, like `@scope/foo` for `@scope/generator-foo`, undefined for another name. */
24
56
  const namespaceOfPackage = (packageName) => {
25
57
  try {
@@ -222,6 +254,7 @@ export default class Store {
222
254
  generatorMeta = {
223
255
  ...meta,
224
256
  ...this.createMetaFunctions(operations, () => this.environment),
257
+ ...createSiblingFunctions(meta.resolved),
225
258
  requireModule,
226
259
  importModule,
227
260
  getPackageJson,
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Two-step argument splitting function that first splits arguments in quotes,
3
+ * and then splits up the remaining arguments if they are not part of a quote.
4
+ */
5
+ export declare function splitArgsFromString(argumentsString: string | string[]): string[];
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Two-step argument splitting function that first splits arguments in quotes,
3
+ * and then splits up the remaining arguments if they are not part of a quote.
4
+ */
5
+ export function splitArgsFromString(argumentsString) {
6
+ if (Array.isArray(argumentsString)) {
7
+ return argumentsString;
8
+ }
9
+ let result = [];
10
+ if (!argumentsString) {
11
+ return result;
12
+ }
13
+ const quoteSeparatedArguments = argumentsString.split(/("[^"]*")/).filter(Boolean);
14
+ for (const argument of quoteSeparatedArguments) {
15
+ if (argument.includes('"')) {
16
+ result.push(argument.replaceAll('"', ''));
17
+ }
18
+ else {
19
+ result = result.concat(argument.trim().split(' '));
20
+ }
21
+ }
22
+ return result;
23
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * The output of a command, `undefined` when it fails. execa is loaded at the first command only: a lookup given the
3
+ * paths of its packages runs none, and the store does not load it.
4
+ */
5
+ export declare const execaOutput: (cmg: string, arguments_: string[]) => string | undefined;
@@ -0,0 +1,19 @@
1
+ import { createRequire } from 'node:module';
2
+ const require = createRequire(import.meta.url);
3
+ /**
4
+ * The output of a command, `undefined` when it fails. execa is loaded at the first command only: a lookup given the
5
+ * paths of its packages runs none, and the store does not load it.
6
+ */
7
+ export const execaOutput = (cmg, arguments_) => {
8
+ try {
9
+ const { execaSync } = require('execa');
10
+ const { failed, stdout } = execaSync(cmg, arguments_, { encoding: 'utf8' });
11
+ if (!failed) {
12
+ return stdout;
13
+ }
14
+ }
15
+ catch {
16
+ // ignore error
17
+ }
18
+ return;
19
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The properties of an object present in it (own or inherited), like lodash `pick`.
3
+ */
4
+ export declare const pick: (object: object | undefined, keys: readonly string[]) => Record<string, any>;
5
+ /**
6
+ * Assign to the target the properties of the sources it has as undefined, the first source first, like lodash
7
+ * `defaults`.
8
+ */
9
+ export declare const defaults: <T extends object>(target: T, ...sources: Array<object | undefined>) => T;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The properties of an object present in it (own or inherited), like lodash `pick`.
3
+ */
4
+ export const pick = (object, keys) => Object.fromEntries(object ? keys.filter(key => key in object).map(key => [key, object[key]]) : []);
5
+ /**
6
+ * Assign to the target the properties of the sources it has as undefined, the first source first, like lodash
7
+ * `defaults`.
8
+ */
9
+ export const defaults = (target, ...sources) => {
10
+ for (const source of sources) {
11
+ if (!source)
12
+ continue;
13
+ for (const key in source) {
14
+ if (target[key] === undefined) {
15
+ target[key] = source[key];
16
+ }
17
+ }
18
+ }
19
+ return target;
20
+ };
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Escape the characters with a meaning in a regular expression, like lodash `escapeRegExp`.
3
+ */
4
+ export declare const escapeRegExp: (value: string) => string;
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Escape the characters with a meaning in a regular expression, like lodash `escapeRegExp`.
3
+ */
4
+ 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.3.0",
3
+ "version": "8.5.0",
4
4
  "description": "Handles the lifecyle and bootstrapping of generators in a specific environment",
5
5
  "keywords": [
6
6
  "development",
@@ -28,6 +28,10 @@
28
28
  "types": "./dist/index.d.js",
29
29
  "default": "./dist/index.js"
30
30
  },
31
+ "./store": {
32
+ "types": "./dist/store/public.d.ts",
33
+ "default": "./dist/store/public.js"
34
+ },
31
35
  "./package.json": "./package.json"
32
36
  },
33
37
  "main": "./dist/index.js",
@@ -52,7 +56,7 @@
52
56
  "fix": "eslint --fix && prettier . --write",
53
57
  "prepare": "npm run build",
54
58
  "pretest": "eslint && prettier . --check && tsc",
55
- "test": "c8 --include 'src/**' esmocha --forbid-only"
59
+ "test": "exnode --coverage"
56
60
  },
57
61
  "config": {
58
62
  "doc_path": "./yeoman-environment-doc"
@@ -84,9 +88,9 @@
84
88
  "@types/node": "^26.4.1",
85
89
  "@types/semver": "^7.8.0",
86
90
  "@yeoman/eslint": "1.1.0",
87
- "c8": "^12.0.0",
88
91
  "eslint": "10.10.0",
89
- "esmocha": "^5.0.0",
92
+ "expect-node": "^0.3.3",
93
+ "jest-snapshot": "^30.5.2",
90
94
  "jsdoc": "^4.0.5",
91
95
  "prettier": "3.9.6",
92
96
  "prettier-plugin-packagejson": "^3.0.2",
@@ -1,19 +0,0 @@
1
- export declare const execaOutput: (cmg: string, arguments_: string[]) => string | undefined;
2
- /**
3
- * Two-step argument splitting function that first splits arguments in quotes,
4
- * and then splits up the remaining arguments if they are not part of a quote.
5
- */
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 DELETED
@@ -1,60 +0,0 @@
1
- import { execaSync } from 'execa';
2
- export const execaOutput = (cmg, arguments_) => {
3
- try {
4
- const { failed, stdout } = execaSync(cmg, arguments_, { encoding: 'utf8' });
5
- if (!failed) {
6
- return stdout;
7
- }
8
- }
9
- catch {
10
- // ignore error
11
- }
12
- return;
13
- };
14
- /**
15
- * Two-step argument splitting function that first splits arguments in quotes,
16
- * and then splits up the remaining arguments if they are not part of a quote.
17
- */
18
- export function splitArgsFromString(argumentsString) {
19
- if (Array.isArray(argumentsString)) {
20
- return argumentsString;
21
- }
22
- let result = [];
23
- if (!argumentsString) {
24
- return result;
25
- }
26
- const quoteSeparatedArguments = argumentsString.split(/("[^"]*")/).filter(Boolean);
27
- for (const argument of quoteSeparatedArguments) {
28
- if (argument.includes('"')) {
29
- result.push(argument.replaceAll('"', ''));
30
- }
31
- else {
32
- result = result.concat(argument.trim().split(' '));
33
- }
34
- }
35
- return result;
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 `\$&`);
File without changes
File without changes
File without changes