Skip to content

Commit df2fa2d

Browse files
committed
extract lookupGenerator
1 parent 751d3d5 commit df2fa2d

File tree

4 files changed

+72
-72
lines changed

4 files changed

+72
-72
lines changed

src/environment.js

-55
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
import EventEmitter from 'node:events';
2-
import path, { isAbsolute } from 'node:path';
3-
import { pathToFileURL } from 'node:url';
42
import { requireNamespace, toNamespace } from '@yeoman/namespace';
53
import { defaults, pick, uniq } from 'lodash-es';
64
import createdLogger from 'debug';
7-
import { findPackagesIn, getNpmPaths, moduleLookupSync } from './module-lookup.js';
8-
import { asNamespace, defaultLookups } from './util/namespace.js';
95

106
const debug = createdLogger('yeoman:environment');
117

@@ -47,57 +43,6 @@ function splitArgsFromString(argsString) {
4743
*
4844
*/
4945
export default class Environment extends EventEmitter {
50-
/**
51-
* Lookup for a specific generator.
52-
*
53-
* @param {String} namespace
54-
* @param {Object} [options]
55-
* @param {Boolean} [options.localOnly=false] - Set true to skip lookups of
56-
* globally-installed generators.
57-
* @param {Boolean} [options.packagePath=false] - Set true to return the package
58-
* path instead of generators file.
59-
* @param {Boolean} [options.singleResult=true] - Set false to return multiple values.
60-
* @return {String} generator
61-
*/
62-
static lookupGenerator(namespace, options) {
63-
options =
64-
typeof options === 'boolean'
65-
? { singleResult: true, localOnly: options }
66-
: { singleResult: !(options && options.multiple), ...options };
67-
68-
options.filePatterns = options.filePatterns || defaultLookups.map(prefix => path.join(prefix, '*/index.{js,ts}'));
69-
options.packagePatterns = options.packagePatterns || toNamespace(namespace)?.generatorHint;
70-
71-
options.npmPaths = options.npmPaths || getNpmPaths({ localOnly: options.localOnly, filePaths: false }).reverse();
72-
options.packagePatterns = options.packagePatterns || 'generator-*';
73-
options.packagePaths = options.packagePaths || findPackagesIn(options.npmPaths, options.packagePatterns);
74-
75-
let paths = options.singleResult ? undefined : [];
76-
moduleLookupSync(options, ({ files, packagePath }) => {
77-
for (const filename of files) {
78-
const fileNS = asNamespace(filename, { lookups: defaultLookups });
79-
const ns = toNamespace(fileNS);
80-
if (namespace === fileNS || (options.packagePath && namespace === ns?.packageNamespace)) {
81-
// Version 2.6.0 returned pattern instead of modulePath for options.packagePath
82-
const returnPath = options.packagePath ? packagePath : options.generatorPath ? path.posix.join(filename, '../../') : filename;
83-
if (options.singleResult) {
84-
paths = returnPath;
85-
return filename;
86-
}
87-
88-
paths.push(returnPath);
89-
}
90-
}
91-
return undefined;
92-
});
93-
94-
if (options.singleResult) {
95-
return paths && isAbsolute(paths) ? pathToFileURL(paths).toString() : paths;
96-
}
97-
98-
return paths.map(gen => (isAbsolute(gen) ? pathToFileURL(gen).toString() : gen));
99-
}
100-
10146
/**
10247
* @protected
10348
* Load options passed to the Generator that should be used by the Environment.

src/generator-lookup.ts

+57-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import { extname } from 'node:path';
1+
import { extname, isAbsolute, join, posix } from 'node:path';
2+
import { pathToFileURL } from 'node:url';
23
import { type LookupOptions as LookupOptionsApi } from '@yeoman/types';
3-
import { type ModuleLookupOptions, moduleLookupSync } from './module-lookup.js';
4-
import { defaultLookups } from './util/namespace.js';
4+
import { requireNamespace, toNamespace } from '@yeoman/namespace';
5+
import { type ModuleLookupOptions, moduleLookupSync, getNpmPaths, findPackagesIn } from './module-lookup.js';
6+
import { asNamespace, defaultLookups } from './util/namespace.js';
57

68
export type LookupOptions = LookupOptionsApi &
79
ModuleLookupOptions & {
@@ -61,3 +63,55 @@ export async function lookupGenerators(options: LookupOptions = {}, register?: (
6163
return undefined;
6264
});
6365
}
66+
67+
/**
68+
* Lookup for a specific generator.
69+
*
70+
* @param {String} namespace
71+
* @param {Object} [options]
72+
* @param {Boolean} [options.localOnly=false] - Set true to skip lookups of
73+
* globally-installed generators.
74+
* @param {Boolean} [options.packagePath=false] - Set true to return the package
75+
* path instead of generators file.
76+
* @param {Boolean} [options.singleResult=true] - Set false to return multiple values.
77+
* @return {String} generator
78+
*/
79+
export function lookupGenerator(namespace: string, options?: ModuleLookupOptions & { packagePath?: boolean; generatorPath?: boolean }) {
80+
options = typeof options === 'boolean' ? { localOnly: options } : options ?? {};
81+
options.singleResult = options.singleResult ?? true;
82+
83+
options.filePatterns = options.filePatterns ?? defaultLookups.map(prefix => join(prefix, '*/index.{js,ts}'));
84+
const ns = requireNamespace(namespace);
85+
options.packagePatterns = options.packagePatterns ?? [ns.generatorHint];
86+
87+
options.npmPaths = options.npmPaths ?? getNpmPaths({ localOnly: options.localOnly }).reverse();
88+
options.packagePatterns = options.packagePatterns ?? ['generator-*'];
89+
options.packagePaths = options.packagePaths ?? findPackagesIn(options.npmPaths, options.packagePatterns);
90+
91+
let paths: string[] | string | undefined = options.singleResult ? undefined : [];
92+
moduleLookupSync(options, ({ files, packagePath }) => {
93+
for (const filename of files) {
94+
const fileNs = asNamespace(filename, { lookups: defaultLookups });
95+
const ns = toNamespace(fileNs);
96+
if (namespace === fileNs || (options!.packagePath && namespace === ns?.packageNamespace)) {
97+
// Version 2.6.0 returned pattern instead of modulePath for options.packagePath
98+
const returnPath = options!.packagePath ? packagePath : options!.generatorPath ? posix.join(filename, '../../') : filename;
99+
if (options!.singleResult) {
100+
paths = returnPath;
101+
return filename;
102+
}
103+
104+
(paths as string[]).push(returnPath);
105+
}
106+
}
107+
108+
return undefined;
109+
});
110+
111+
if (options.singleResult) {
112+
const generatorPath = paths as unknown as string;
113+
return generatorPath && isAbsolute(generatorPath) ? pathToFileURL(generatorPath).toString() : generatorPath;
114+
}
115+
116+
return paths!.map(gen => (isAbsolute(gen) ? pathToFileURL(gen).toString() : gen));
117+
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Environment from '../../../../src/index.js';
2-
const maybeGenerator = await import(Environment.lookupGenerator('dummy:app'));
1+
import { lookupGenerator } from '../../../../src/generator-lookup.js';
2+
const maybeGenerator = await import(lookupGenerator('dummy:app'));
33
const Generator = maybeGenerator.default ?? maybeGenerator;
44
export default class extends Generator {};

test/resolver.js

+13-12
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import slash from 'slash';
1111
import Environment from '../src/index.js';
1212
import { execaOutput } from '../src/util/util.js';
1313
import { findPackagesIn, getNpmPaths } from '../src/module-lookup.js';
14+
import { lookupGenerator } from '../src/generator-lookup.js';
1415

1516
const require = createRequire(import.meta.url);
1617

@@ -749,34 +750,34 @@ describe('Environment Resolver', async function () {
749750

750751
describe('Find generator', async () => {
751752
it('Scoped lookup', async () => {
752-
const modulePath = Environment.lookupGenerator('@dummyscope/scoped:app');
753+
const modulePath = lookupGenerator('@dummyscope/scoped:app');
753754
assert.ok(modulePath.endsWith('node_modules/@dummyscope/generator-scoped/app/index.js'));
754-
const packagePath = Environment.lookupGenerator('@dummyscope/scoped:app', { packagePath: true });
755+
const packagePath = lookupGenerator('@dummyscope/scoped:app', { packagePath: true });
755756
assert.ok(packagePath.endsWith('node_modules/@dummyscope/generator-scoped'));
756757
});
757758
it('Lookup', async () => {
758-
const modulePath = Environment.lookupGenerator('extend:support');
759+
const modulePath = lookupGenerator('extend:support');
759760
assert.ok(modulePath.endsWith('node_modules/generator-extend/support/index.js'));
760761

761-
const packagePath = Environment.lookupGenerator('extend:support', {
762+
const packagePath = lookupGenerator('extend:support', {
762763
packagePath: true,
763764
});
764-
const packagePath3 = Environment.lookupGenerator('extend', {
765+
const packagePath3 = lookupGenerator('extend', {
765766
packagePath: true,
766767
});
767768
assert.ok(packagePath.endsWith('node_modules/generator-extend'));
768769
assert.ok(packagePath3.endsWith('node_modules/generator-extend'));
769770
});
770771
it('Module Lookup', async () => {
771-
const modulePath = Environment.lookupGenerator('module:app');
772+
const modulePath = lookupGenerator('module:app');
772773
assert.ok(modulePath.endsWith('node_modules/generator-module/generators/app/index.js'), modulePath);
773774

774-
const packagePath = Environment.lookupGenerator('module:app', {
775+
const packagePath = lookupGenerator('module:app', {
775776
packagePath: true,
776777
});
777778
assert.ok(packagePath.endsWith('node_modules/generator-module'), packagePath);
778779

779-
const generatorPath = Environment.lookupGenerator('module:app', {
780+
const generatorPath = lookupGenerator('module:app', {
780781
generatorPath: true,
781782
});
782783
assert.ok(generatorPath.endsWith('node_modules/generator-module/generators/'), generatorPath);
@@ -811,17 +812,17 @@ describe('Environment Resolver', async function () {
811812

812813
describe('Find generator', async () => {
813814
it('Module Lookup', async () => {
814-
const modulePath = Environment.lookupGenerator('module:app');
815+
const modulePath = lookupGenerator('module:app');
815816
assert.ok(modulePath.endsWith('node_modules/generator-module/generators/app/index.js'));
816817

817-
const multiplePath = Environment.lookupGenerator('module:app', {
818-
multiple: true,
818+
const multiplePath = lookupGenerator('module:app', {
819+
singleResult: false,
819820
});
820821
assert.equal(multiplePath.length, 2);
821822
assert.ok(multiplePath[0].endsWith('lookup-custom/node_modules/generator-module/generators/app/index.js'));
822823
assert.ok(multiplePath[1].endsWith('lookup-custom/node_modules/foo/node_modules/generator-module/generators/app/index.js'));
823824

824-
const multiplePath2 = Environment.lookupGenerator('module:app', {
825+
const multiplePath2 = lookupGenerator('module:app', {
825826
singleResult: false,
826827
});
827828
assert.equal(multiplePath2.length, 2);

0 commit comments

Comments
 (0)