Skip to content

Commit 02f03e3

Browse files
committed
fix: improve types
1 parent b76e448 commit 02f03e3

5 files changed

Lines changed: 71 additions & 60 deletions

File tree

package-lock.json

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
"@yeoman/conflicter": "^3.0.0",
6262
"@yeoman/namespace": "^1.0.1",
6363
"@yeoman/transform": "^2.1.0",
64-
"@yeoman/types": "^1.6.0",
64+
"@yeoman/types": "^1.7.1",
6565
"arrify": "^3.0.0",
6666
"chalk": "^5.5.0",
6767
"commander": "^14.0.0",
@@ -109,8 +109,8 @@
109109
"yeoman-test": "^10.1.1"
110110
},
111111
"peerDependencies": {
112-
"@yeoman/types": "^1.1.1",
113-
"mem-fs": "^4.0.0"
112+
"@yeoman/types": "^1.7.1",
113+
"mem-fs": "^4.1.2"
114114
},
115115
"engines": {
116116
"node": "^20.17.0 || >=22.9.0"

src/environment-base.ts

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type {
99
BaseEnvironment,
1010
BaseEnvironmentOptions,
1111
BaseGenerator,
12-
BaseGeneratorConstructor,
12+
BaseGeneratorConstructorMeta,
1313
BaseGeneratorMeta,
1414
ComposeOptions,
1515
GeneratorMeta,
@@ -293,11 +293,12 @@ export default class EnvironmentBase extends EventEmitter implements BaseEnviron
293293
* @param namespaceOrPath
294294
* @return the generator registered under the namespace
295295
*/
296-
async get<C extends BaseGeneratorConstructor = BaseGeneratorConstructor>(
296+
get<G extends BaseGenerator = BaseGenerator>(
297297
namespaceOrPath: string | YeomanNamespace,
298-
): Promise<C | undefined> {
299-
const meta = await this.findMeta(namespaceOrPath);
300-
return meta?.importGenerator() as Promise<C>;
298+
):
299+
| Promise<(GetGeneratorConstructor<G> & BaseGeneratorConstructorMeta) | undefined>
300+
| ((GetGeneratorConstructor<G> & BaseGeneratorConstructorMeta) | undefined) {
301+
return this.findMeta(namespaceOrPath)?.importGenerator();
301302
}
302303

303304
/**
@@ -312,22 +313,21 @@ export default class EnvironmentBase extends EventEmitter implements BaseEnviron
312313
* @return The instantiated generator
313314
*/
314315
async create<G extends BaseGenerator = BaseGenerator>(
315-
namespaceOrPath: string | GetGeneratorConstructor<G>,
316+
namespaceOrPath: string | (GetGeneratorConstructor<G> & Partial<BaseGeneratorConstructorMeta>),
316317
instantiateOptions?: InstantiateOptions<G>,
317318
): Promise<G>;
318319
create<G extends BaseGenerator = BaseGenerator>(
319-
namespaceOrPath: string | GetGeneratorConstructor<G>,
320+
namespaceOrPath: string | (GetGeneratorConstructor<G> & Partial<BaseGeneratorConstructorMeta>),
320321
...arguments_: any[]
321322
): Promise<G> | G {
322-
let constructor;
323323
const namespace = typeof namespaceOrPath === 'string' ? toNamespace(namespaceOrPath) : undefined;
324324

325-
const checkGenerator = (Generator: any) => {
325+
const checkGenerator = <const T extends Partial<BaseGeneratorConstructorMeta>>(Generator?: T): T => {
326326
const generatorNamespace = Generator?.namespace;
327-
if (namespace && generatorNamespace !== namespace.namespace && generatorNamespace !== UNKNOWN_NAMESPACE) {
327+
if (namespace && generatorNamespace && generatorNamespace !== namespace.namespace && generatorNamespace !== UNKNOWN_NAMESPACE) {
328328
// Update namespace object in case of aliased namespace.
329329
try {
330-
namespace.namespace = Generator.namespace;
330+
namespace.namespace = generatorNamespace;
331331
} catch {
332332
// Invalid namespace can be aliased to a valid one.
333333
}
@@ -350,32 +350,23 @@ export default class EnvironmentBase extends EventEmitter implements BaseEnviron
350350
return Generator;
351351
};
352352

353-
if (typeof namespaceOrPath !== 'string') {
354-
return this.instantiate(checkGenerator(namespaceOrPath), ...arguments_);
355-
}
356-
357353
if (typeof namespaceOrPath === 'string') {
358354
const meta = this.findMeta(namespaceOrPath);
359-
constructor = meta?.importGenerator();
355+
const constructor = meta?.importGenerator();
360356
if (namespace && !constructor) {
361357
// Await this.lookupLocalNamespaces(namespace);
362358
// constructor = await this.get(namespace);
363359
}
364360

365-
if (constructor) {
366-
if ((constructor as any).then) {
367-
return constructor.then(g => {
368-
(g as any)._meta = meta;
369-
return this.instantiate(checkGenerator(g), ...arguments_);
370-
});
371-
}
372-
(constructor as any)._meta = meta;
361+
if (constructor && 'then' in constructor) {
362+
return constructor.then(g => {
363+
return this.instantiate(checkGenerator(g), ...arguments_);
364+
});
373365
}
366+
return this.instantiate(checkGenerator(constructor), ...arguments_);
374367
} else {
375-
constructor = namespaceOrPath;
368+
return this.instantiate(checkGenerator(namespaceOrPath), ...arguments_);
376369
}
377-
378-
return this.instantiate(checkGenerator(constructor), ...arguments_);
379370
}
380371

381372
/**
@@ -389,9 +380,12 @@ export default class EnvironmentBase extends EventEmitter implements BaseEnviron
389380
generator: GetGeneratorConstructor<G>,
390381
instantiateOptions?: InstantiateOptions<G>,
391382
): Promise<G>;
392-
instantiate<G extends BaseGenerator = BaseGenerator>(constructor: GetGeneratorConstructor<G>, ...arguments_: any[]): Promise<G> | G {
383+
instantiate<G extends BaseGenerator = BaseGenerator>(
384+
constructor: GetGeneratorConstructor<G> & Partial<BaseGeneratorConstructorMeta>,
385+
...arguments_: any[]
386+
): Promise<G> | G {
393387
const composeOptions = arguments_.length > 0 ? (getInstantiateOptions(...arguments_) as InstantiateOptions<G>) : {};
394-
const { namespace = UNKNOWN_NAMESPACE, resolved = UNKNOWN_RESOLVED, _meta } = constructor as any;
388+
const { namespace = UNKNOWN_NAMESPACE, resolved = UNKNOWN_RESOLVED, _meta } = constructor;
395389
const environmentOptions = { env: this, resolved, namespace };
396390
const generator = new constructor(composeOptions.generatorArgs ?? [], {
397391
...this.sharedOptions,
@@ -836,7 +830,8 @@ export default class EnvironmentBase extends EventEmitter implements BaseEnviron
836830
return new Promise<void>((resolve, reject) => {
837831
Object.assign(this.options, removePropertiesWithNullishValues(pick(options, ['skipInstall', 'nodePackageManager'])));
838832
this.logCwd = options.logCwd ?? this.logCwd;
839-
this.conflicterOptions = pick(defaults({}, this.options, options), ['force', 'bail', 'ignoreWhitespace', 'dryRun', 'skipYoResolve']);
833+
const conflicterOptionsProperties = ['force', 'bail', 'ignoreWhitespace', 'dryRun', 'skipYoResolve'];
834+
this.conflicterOptions = defaults({}, pick(this.options, conflicterOptionsProperties), pick(options, conflicterOptionsProperties));
840835
this.conflicterOptions.cwd = this.logCwd;
841836

842837
this.queueCommit();

src/environment-full.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { createHash } from 'node:crypto';
22
import { join, resolve } from 'node:path';
3-
import type { BaseGeneratorConstructor, InputOutputAdapter } from '@yeoman/types';
3+
import type { BaseGeneratorConstructor, BaseGeneratorOptions, GeneratorEnvironmentOptions, InputOutputAdapter } from '@yeoman/types';
44
import { type YeomanNamespace, requireNamespace, toNamespace } from '@yeoman/namespace';
55
import { flyImport } from 'fly-import';
66
import { defaults, pick, uniq } from 'lodash-es';
@@ -337,13 +337,12 @@ class FullEnvironment extends EnvironmentBase {
337337
* on the provided arguments, options and the list of registered generators.
338338
*
339339
* When the environment was unable to resolve a generator, an error is raised.
340-
*
341-
* @param {String|Array} args
342-
* @param {Object} [options]
343340
*/
344-
async run(arguments_?: string[], options?: any) {
341+
async run(
342+
arguments_?: string | string[],
343+
options: EnvironmentOptions & BaseGeneratorOptions & Partial<GeneratorEnvironmentOptions> = {},
344+
) {
345345
arguments_ = Array.isArray(arguments_) ? arguments_ : splitArgumentsFromString(arguments_ as unknown as string);
346-
options = { ...options };
347346

348347
let name = arguments_.shift();
349348
if (!name) {
@@ -366,10 +365,7 @@ class FullEnvironment extends EnvironmentBase {
366365

367366
const generator = await this.create(name, {
368367
generatorArgs: arguments_,
369-
generatorOptions: {
370-
...options,
371-
initialGenerator: true,
372-
},
368+
generatorOptions: options,
373369
});
374370

375371
if (options.help) {

src/store.ts

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@ import { pathToFileURL } from 'node:url';
22
import { extname, join } from 'node:path';
33
import { createRequire } from 'node:module';
44
import { toNamespace } from '@yeoman/namespace';
5-
import type { BaseEnvironment, BaseGeneratorMeta, GeneratorMeta, GetGeneratorConstructor } from '@yeoman/types';
5+
import type {
6+
BaseEnvironment,
7+
BaseGenerator,
8+
BaseGeneratorConstructorMeta,
9+
BaseGeneratorMeta,
10+
GeneratorMeta,
11+
GetGeneratorConstructor,
12+
} from '@yeoman/types';
613
import createDebug from 'debug';
714

815
const debug = createDebug('yeoman:environment:store');
@@ -68,7 +75,12 @@ export default class Store {
6875
}
6976

7077
let importPromise: Promise<unknown> | undefined;
71-
const importGenerator = () => {
78+
// eslint-disable-next-line prefer-const
79+
let generatorMeta: (GeneratorMeta & M) | undefined;
80+
81+
const importGenerator: GeneratorMeta['importGenerator'] = <G extends BaseGenerator>():
82+
| Promise<GetGeneratorConstructor<G> & BaseGeneratorConstructorMeta>
83+
| (GetGeneratorConstructor<G> & BaseGeneratorConstructorMeta) => {
7284
const handleImport = () => {
7385
if (importModule && !Generator) {
7486
const maybeModule = importModule();
@@ -84,18 +96,21 @@ export default class Store {
8496
}
8597
};
8698

87-
const handleModule = () => {
99+
const handleModule = <G extends BaseGenerator>():
100+
| Promise<GetGeneratorConstructor<G> & BaseGeneratorConstructorMeta>
101+
| (GetGeneratorConstructor<G> & BaseGeneratorConstructorMeta) => {
88102
const factory = this.getFactory(Generator);
89103
if (typeof factory === 'function') {
90104
importPromise = factory(this.environment);
91105
return Promise.resolve(importPromise).then((mod: any) => {
92-
Generator = this._getGenerator(mod, meta);
106+
const generator = this._getGenerator<G>(mod, meta, generatorMeta);
107+
Generator = generator;
93108
importPromise = undefined;
94-
return Generator;
109+
return generator;
95110
});
96111
}
97112

98-
return this._getGenerator(Generator, meta);
113+
return this._getGenerator<G>(Generator, meta, generatorMeta);
99114
};
100115

101116
if (importPromise) {
@@ -109,12 +124,12 @@ export default class Store {
109124
return handleModule();
110125
};
111126

112-
const instantiate = async (arguments_: string[] = [], options: any = {}) =>
113-
this.environment.instantiate(await importGenerator(), { generatorArgs: arguments_, generatorOptions: options });
114-
const instantiateHelp = async () => instantiate([], { help: true });
127+
const instantiate: GeneratorMeta['instantiate'] = async <G extends BaseGenerator>(arguments_: string[] = [], options: any = {}) =>
128+
this.environment.instantiate<G>(await importGenerator<G>(), { generatorArgs: arguments_, generatorOptions: options });
129+
const instantiateHelp: GeneratorMeta['instantiateHelp'] = async () => instantiate([], { help: true });
115130
const { packageNamespace } = toNamespace(meta.namespace) ?? {};
116131

117-
const generatorMeta = {
132+
generatorMeta = {
118133
...meta,
119134
importGenerator,
120135
importModule,
@@ -229,13 +244,18 @@ export default class Store {
229244
return module.createGenerator ?? module.default?.createGenerator ?? module.default?.default?.createGenerator;
230245
}
231246

232-
private _getGenerator(module: any, meta: BaseGeneratorMeta) {
247+
private _getGenerator<G extends BaseGenerator>(
248+
module: any,
249+
meta: BaseGeneratorMeta,
250+
generatorMeta: BaseGeneratorMeta | undefined,
251+
): GetGeneratorConstructor<G> & BaseGeneratorConstructorMeta {
233252
const Generator = module.default?.default ?? module.default ?? module;
234253
if (typeof Generator !== 'function') {
235254
throw new TypeError("The generator doesn't provide a constructor.");
236255
}
237256

238257
Object.assign(Generator, meta);
258+
Generator._meta = generatorMeta;
239259
return Generator;
240260
}
241261
}

0 commit comments

Comments
 (0)