yeoman-generator 7.3.2 → 7.4.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.
@@ -1,7 +1,7 @@
1
1
  import { type CopyOptions, type MemFsEditor } from 'mem-fs-editor';
2
2
  import type { Data as TemplateData, Options as TemplateOptions } from 'ejs';
3
3
  import type { OverloadParameters, OverloadReturnType } from '../types-utils.js';
4
- import type BaseGenerator from '../generator.js';
4
+ import type { BaseGenerator } from '../generator.js';
5
5
  export type Template<D extends TemplateData, G> = {
6
6
  /**
7
7
  * Template file, absolute or relative to templatePath().
@@ -1,4 +1,4 @@
1
- /* eslint max-params: [1, 5] */
1
+ /* eslint max-params: [1, 6] */
2
2
  import assert from 'node:assert';
3
3
  function applyToFirstStringArg(customizer, args) {
4
4
  args[0] = Array.isArray(args[0]) ? args[0].map(arg => customizer(arg)) : customizer(args[0]);
@@ -28,9 +28,7 @@ export class FsMixin {
28
28
  */
29
29
  copyTemplate(...args) {
30
30
  const [from, to, options = {}, ...remaining] = args;
31
- options.fromBasePath = options.fromBasePath ?? this.templatePath();
32
- // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression
33
- return this.fs.copy(from, this.destinationPath(to), options, ...remaining);
31
+ return this.fs.copy(from, this.destinationPath(to), { fromBasePath: this.templatePath(), ...options }, ...remaining);
34
32
  }
35
33
  /**
36
34
  * Copy file from templates folder to destination folder.
@@ -55,7 +53,6 @@ export class FsMixin {
55
53
  * mem-fs-editor method's shortcut, for more information see [mem-fs-editor]{@link https://github.com/SBoudrias/mem-fs-editor}.
56
54
  * Shortcut for this.fs!.readJSON(this.destinationPath(filepath)).
57
55
  */
58
- // eslint-disable-next-line @typescript-eslint/naming-convention
59
56
  readDestinationJSON(...args) {
60
57
  return this.fs.readJSON(...applyToFirstStringArg(this.destinationPath.bind(this), args));
61
58
  }
@@ -72,7 +69,6 @@ export class FsMixin {
72
69
  * mem-fs-editor method's shortcut, for more information see [mem-fs-editor]{@link https://github.com/SBoudrias/mem-fs-editor}.
73
70
  * Shortcut for this.fs!.writeJSON(this.destinationPath(filepath)).
74
71
  */
75
- // eslint-disable-next-line @typescript-eslint/naming-convention
76
72
  writeDestinationJSON(...args) {
77
73
  return this.fs.writeJSON(...applyToFirstStringArg(this.destinationPath.bind(this), args));
78
74
  }
@@ -82,7 +78,6 @@ export class FsMixin {
82
78
  * Shortcut for this.fs!.delete(this.destinationPath(filepath)).
83
79
  */
84
80
  deleteDestination(...args) {
85
- // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression
86
81
  return this.fs.delete(...applyToFirstStringArg(this.destinationPath.bind(this), args));
87
82
  }
88
83
  /**
@@ -92,9 +87,7 @@ export class FsMixin {
92
87
  */
93
88
  copyDestination(...args) {
94
89
  const [from, to, options = {}, ...remaining] = args;
95
- options.fromBasePath = options.fromBasePath ?? this.destinationPath();
96
- // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression
97
- return this.fs.copy(from, this.destinationPath(to), options, ...remaining);
90
+ return this.fs.copy(from, this.destinationPath(to), { fromBasePath: this.destinationPath(), ...options }, ...remaining);
98
91
  }
99
92
  /**
100
93
  * Move file from destination folder to another destination folder.
@@ -102,10 +95,8 @@ export class FsMixin {
102
95
  * Shortcut for this.fs!.move(this.destinationPath(from), this.destinationPath(to)).
103
96
  */
104
97
  moveDestination(...args) {
105
- const [from, to, options = {}, ...remaining] = args;
106
- options.fromBasePath = options.fromBasePath ?? this.destinationPath();
107
- // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression
108
- return this.fs.move(from, this.destinationPath(to), options, ...remaining);
98
+ const [from, to, options, ...remaining] = args;
99
+ return this.fs.move(from, this.destinationPath(to), { fromBasePath: this.destinationPath(), ...options }, ...remaining);
109
100
  }
110
101
  /**
111
102
  * Exists file on destination folder.
@@ -133,7 +124,10 @@ export class FsMixin {
133
124
  const templatePath = this.templatePath(...source);
134
125
  destination = Array.isArray(destination) ? destination : [destination];
135
126
  const destinationPath = this.destinationPath(...destination);
136
- this.fs.copyTpl(templatePath, destinationPath, templateData, templateOptions, copyOptions);
127
+ this.fs.copyTpl(templatePath, destinationPath, templateData, templateOptions, {
128
+ fromBasePath: this.templatePath(),
129
+ ...copyOptions,
130
+ });
137
131
  }
138
132
  /**
139
133
  * Copy a template from templates folder to the destination.
@@ -153,7 +147,10 @@ export class FsMixin {
153
147
  const templatePath = this.templatePath(...source);
154
148
  destination = Array.isArray(destination) ? destination : [destination];
155
149
  const destinationPath = this.destinationPath(...destination);
156
- return this.fs.copyTplAsync(templatePath, destinationPath, templateData, templateOptions, copyOptions);
150
+ return this.fs.copyTplAsync(templatePath, destinationPath, templateData, templateOptions, {
151
+ fromBasePath: this.templatePath(),
152
+ ...copyOptions,
153
+ });
157
154
  }
158
155
  /**
159
156
  * Copy templates from templates folder to the destination.
@@ -166,7 +163,10 @@ export class FsMixin {
166
163
  for (const template of templates) {
167
164
  const { templateData: eachData = templateData, source, destination } = template;
168
165
  if (!template.when || template.when(eachData, this)) {
169
- this.renderTemplate(source, destination, eachData, template.templateOptions, template.copyOptions);
166
+ this.renderTemplate(source, destination, eachData, template.templateOptions, {
167
+ fromBasePath: this.templatePath(),
168
+ ...template.copyOptions,
169
+ });
170
170
  }
171
171
  }
172
172
  }
@@ -184,9 +184,12 @@ export class FsMixin {
184
184
  return Promise.all(templates.map(async (template) => {
185
185
  const { templateData: eachData = templateData, source, destination } = template;
186
186
  if (!template.when || template.when(eachData, this)) {
187
- return this.renderTemplateAsync(source, destination, eachData, template.templateOptions, template.copyOptions);
187
+ return this.renderTemplateAsync(source, destination, eachData, template.templateOptions, {
188
+ fromBasePath: this.templatePath(),
189
+ ...template.copyOptions,
190
+ });
188
191
  }
189
- return undefined;
192
+ return;
190
193
  }));
191
194
  }
192
195
  /**
@@ -1,5 +1,5 @@
1
1
  import type { ArgumentSpec, CliOptionSpec } from '../types.js';
2
- import type BaseGenerator from '../generator.js';
2
+ import type { BaseGenerator } from '../generator.js';
3
3
  export declare class HelpMixin {
4
4
  readonly _options: Record<string, CliOptionSpec>;
5
5
  readonly _arguments: ArgumentSpec[];
@@ -18,7 +18,7 @@ export class HelpMixin {
18
18
  help() {
19
19
  const filepath = path.resolve(this.sourceRoot(), '../USAGE');
20
20
  const exists = fs.existsSync(filepath);
21
- let out = ['Usage:', ' ' + this.usage(), ''];
21
+ let out = ['Usage:', ` ${this.usage()}`, ''];
22
22
  // Build options
23
23
  if (Object.keys(this._options).length > 0) {
24
24
  out = [...out, 'Options:', this.optionsHelp(), ''];
@@ -44,12 +44,12 @@ export class HelpMixin {
44
44
  let name = this._namespace;
45
45
  let args = '';
46
46
  if (this._arguments.length > 0) {
47
- args = this._arguments.map(arg => formatArg(arg)).join(' ') + ' ';
47
+ args = `${this._arguments.map(arg => formatArg(arg)).join(' ')} `;
48
48
  }
49
49
  name = name.replace(/^yeoman:/, '');
50
50
  let out = `yo ${name} ${args}${options}`;
51
51
  if (this.description) {
52
- out += '\n\n' + this.description;
52
+ out += `\n\n${this.description}`;
53
53
  }
54
54
  return out;
55
55
  }
@@ -1,7 +1,7 @@
1
1
  import type { BaseGenerator, GetGeneratorOptions } from '@yeoman/types';
2
2
  import { type FileTransform } from 'mem-fs';
3
3
  import { type MemFsEditorFile } from 'mem-fs-editor';
4
- import type { Task, TaskOptions, BaseOptions, Priority, ComposeOptions, GeneratorPipelineOptions } from '../types.js';
4
+ import type { BaseOptions, ComposeOptions, GeneratorPipelineOptions, Priority, Task, TaskOptions } from '../types.js';
5
5
  import type Generator from '../index.js';
6
6
  import type BaseGeneratorImpl from '../generator.js';
7
7
  type TaskStatus = {
@@ -83,7 +83,7 @@ export declare abstract class TasksMixin {
83
83
  * @param args: Task arguments.
84
84
  * @param taskStatus.
85
85
  */
86
- executeTask(this: BaseGeneratorImpl, task: Task, args?: any[] | ((generator: Generator<BaseOptions, import("../types.js").BaseFeatures>) => any[]), taskStatus?: TaskStatus | undefined): Promise<void>;
86
+ executeTask(this: BaseGeneratorImpl, task: Task, args?: any[] | ((generator: Generator) => any[]), taskStatus?: TaskStatus | undefined): Promise<void>;
87
87
  /**
88
88
  * Ignore cancellable tasks.
89
89
  */
@@ -1,13 +1,11 @@
1
- /* eslint-disable @typescript-eslint/member-ordering */
2
1
  import { dirname, isAbsolute, resolve as pathResolve, relative } from 'node:path';
3
2
  import { pathToFileURL } from 'node:url';
4
3
  import { createRequire } from 'node:module';
5
- import { Duplex } from 'node:stream';
4
+ import { Transform } from 'node:stream';
6
5
  import { stat } from 'node:fs/promises';
7
6
  import createDebug from 'debug';
8
7
  import { toNamespace } from '@yeoman/namespace';
9
8
  import { isFileTransform } from 'mem-fs';
10
- // eslint-disable-next-line n/file-extension-in-import
11
9
  import { isFilePending } from 'mem-fs-editor/state';
12
10
  const debug = createDebug('yeoman:generator');
13
11
  // Ensure a prototype method is a candidate run by default
@@ -180,14 +178,9 @@ export class TasksMixin {
180
178
  const methods = Object.keys(this.getTaskSourcesPropertyDescriptors());
181
179
  let validMethods = methods.filter(method => methodIsValid(method));
182
180
  const { taskPrefix } = this.features;
183
- if (taskPrefix) {
184
- validMethods = validMethods
185
- .filter(method => method.startsWith(taskPrefix))
186
- .map(method => method.slice(taskPrefix.length));
187
- }
188
- else {
189
- validMethods = validMethods.filter(method => !method.startsWith('#'));
190
- }
181
+ validMethods = taskPrefix
182
+ ? validMethods.filter(method => method.startsWith(taskPrefix)).map(method => method.slice(taskPrefix.length))
183
+ : validMethods.filter(method => !method.startsWith('#'));
191
184
  if (this.features.tasksMatchingPriority) {
192
185
  const queueNames = Object.keys(this._queues);
193
186
  validMethods = validMethods.filter(method => queueNames.includes(method));
@@ -344,7 +337,6 @@ export class TasksMixin {
344
337
  }
345
338
  this.queueOwnTasks({ auto: true });
346
339
  }
347
- // eslint-disable-next-line max-params
348
340
  async composeWith(generator, args, options, immediately = false) {
349
341
  if (Array.isArray(generator)) {
350
342
  const generators = [];
@@ -412,9 +404,10 @@ export class TasksMixin {
412
404
  try {
413
405
  generatorFile = await this.resolveGeneratorPath(generator.path ?? generator.Generator.resolved);
414
406
  }
415
- catch { }
407
+ catch {
408
+ // Ignore error
409
+ }
416
410
  const resolved = generatorFile ?? generator.path ?? generator.Generator.resolved;
417
- // eslint-disable-next-line @typescript-eslint/naming-convention
418
411
  return this.composeLocallyWithOptions({ Generator: generator.Generator, resolved }, composeOptions);
419
412
  }
420
413
  if (skipEnvRegister || isAbsolute(generator) || generator.startsWith('.')) {
@@ -426,14 +419,19 @@ export class TasksMixin {
426
419
  try {
427
420
  generator = await this.resolveGeneratorPath(generator);
428
421
  }
429
- catch { }
422
+ catch {
423
+ // Ignore error
424
+ }
430
425
  }
431
426
  return this.env.composeWith(generator, composeOptions);
432
427
  }
433
428
  async composeLocallyWithOptions({ Generator, resolved = Generator.resolved }, options = {}) {
429
+ if (!resolved) {
430
+ throw new Error('Generator path property is not a string');
431
+ }
434
432
  const generatorNamespace = this.env.namespace(resolved);
435
433
  const findGenerator = async () => {
436
- const generatorImport = await import(resolved);
434
+ const generatorImport = await import(pathToFileURL(resolved).href);
437
435
  const getFactory = (module) => module.createGenerator ?? module.default?.createGenerator ?? module.default?.default?.createGenerator;
438
436
  const factory = getFactory(generatorImport);
439
437
  if (factory) {
@@ -441,7 +439,12 @@ export class TasksMixin {
441
439
  }
442
440
  return typeof generatorImport.default === 'function' ? generatorImport.default : generatorImport;
443
441
  };
444
- Generator = Generator ?? (await findGenerator());
442
+ try {
443
+ Generator = Generator ?? (await findGenerator());
444
+ }
445
+ catch {
446
+ throw new Error('Missing Generator property');
447
+ }
445
448
  Generator.namespace = generatorNamespace;
446
449
  Generator.resolved = resolved;
447
450
  return this.env.composeWith(Generator, options);
@@ -457,11 +460,13 @@ export class TasksMixin {
457
460
  generatorResolvedFile = generatorFile;
458
461
  }
459
462
  }
460
- catch { }
463
+ catch {
464
+ // Ignore error
465
+ }
461
466
  if (!generatorResolvedFile) {
462
467
  // Resolve the generator file.
463
468
  // Use import.resolve when stable.
464
- generatorResolvedFile = pathToFileURL(createRequire(import.meta.url).resolve(generatorFile)).href;
469
+ generatorResolvedFile = createRequire(import.meta.url).resolve(generatorFile);
465
470
  }
466
471
  return generatorResolvedFile;
467
472
  }
@@ -479,11 +484,12 @@ export class TasksMixin {
479
484
  filter = pendingFiles ? isFilePending : passedFilter;
480
485
  }
481
486
  const { env } = this;
482
- await env.adapter.progress(async ({ step }) => env.sharedFs.pipeline({ filter, ...memFsPipelineOptions }, ...transforms, Duplex.from(async function* (generator) {
483
- for await (const file of generator) {
487
+ await env.adapter.progress(async ({ step }) => env.sharedFs.pipeline({ filter, ...memFsPipelineOptions }, ...transforms, new Transform({
488
+ objectMode: true,
489
+ transform(file, _encoding, callback) {
484
490
  step('Completed', relative(env.logCwd, file.path));
485
- yield file;
486
- }
491
+ callback(null, file);
492
+ },
487
493
  })), { disabled, name });
488
494
  }
489
495
  /**
@@ -23,7 +23,6 @@ export class PackageJsonMixin {
23
23
  : dependencies;
24
24
  return Object.fromEntries(await Promise.all(
25
25
  // Make sure to convert empty string too
26
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
27
26
  Object.entries(depMap).map(async ([pkg, version]) => [pkg, version || (await latestVersion(pkg))])));
28
27
  }
29
28
  /**
@@ -1,5 +1,4 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
- import { type Options as ExecaOptions, type ExecaChildProcess, type SyncOptions, type ExecaSyncReturnValue } from 'execa';
1
+ import { type ExecaChildProcess, type Options as ExecaOptions, type ExecaSyncReturnValue, type SyncOptions } from 'execa';
3
2
  export declare class SpawnCommandMixin {
4
3
  /**
5
4
  * Normalize a command across OS and spawn it (asynchronously).
@@ -1,4 +1,4 @@
1
- import { execa, execaSync, execaCommand, execaCommandSync, } from 'execa';
1
+ import { execa, execaCommand, execaCommandSync, execaSync, } from 'execa';
2
2
  export class SpawnCommandMixin {
3
3
  spawnCommand(command, args, opt) {
4
4
  if (Array.isArray(args) || (opt && args === undefined)) {
package/dist/constants.js CHANGED
@@ -1,3 +1,2 @@
1
- // eslint-disable-next-line @typescript-eslint/naming-convention
2
1
  export const DESTINATION_ROOT_CHANGE_EVENT = 'destinationRootChange';
3
2
  export const requiredEnvironmentVersion = '4.0.0-rc.0';
@@ -1,11 +1,10 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
1
  import { EventEmitter } from 'node:events';
3
2
  import * as _ from 'lodash-es';
4
3
  import createDebug from 'debug';
5
4
  import { type MemFsEditor } from 'mem-fs-editor';
6
5
  import { type YeomanNamespace } from '@yeoman/namespace';
7
6
  import type { BaseEnvironment, BaseGenerator as GeneratorApi, Logger, QueuedAdapter } from '@yeoman/types';
8
- import type { ArgumentSpec, BaseOptions, BaseFeatures, CliOptionSpec, Priority } from './types.js';
7
+ import type { ArgumentSpec, BaseFeatures, BaseOptions, CliOptionSpec, Priority } from './types.js';
9
8
  import type { PromptAnswers, PromptQuestions, QuestionRegistrationOptions } from './questions.js';
10
9
  import Storage, { type StorageOptions } from './util/storage.js';
11
10
  import { FsMixin } from './actions/fs.js';
package/dist/generator.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import fs, { readFileSync } from 'node:fs';
2
- import path, { dirname, resolve as pathResolve, join as pathJoin } from 'node:path';
2
+ import path, { dirname, join as pathJoin, resolve as pathResolve } from 'node:path';
3
3
  import os from 'node:os';
4
4
  import { EventEmitter } from 'node:events';
5
5
  import { fileURLToPath } from 'node:url';
6
6
  import * as _ from 'lodash-es';
7
- import semver from 'semver';
7
+ import { lte as semverLte } from 'semver';
8
8
  import { readPackageUpSync } from 'read-package-up';
9
9
  import chalk from 'chalk';
10
10
  import minimist from 'minimist';
@@ -22,15 +22,11 @@ import { GitMixin } from './actions/user.js';
22
22
  import { TasksMixin } from './actions/lifecycle.js';
23
23
  const _filename = fileURLToPath(import.meta.url);
24
24
  const _dirname = dirname(_filename);
25
- // eslint-disable-next-line @typescript-eslint/naming-convention
26
25
  const EMPTY = '@@_YEOMAN_EMPTY_MARKER_@@';
27
- // eslint-disable-next-line @typescript-eslint/naming-convention
28
26
  const ENV_VER_WITH_VER_API = '2.9.0';
29
27
  const packageJson = JSON.parse(readFileSync(pathJoin(_dirname, '../package.json'), 'utf8'));
30
28
  // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
31
- export class BaseGenerator
32
- // eslint-disable-next-line unicorn/prefer-event-target
33
- extends EventEmitter {
29
+ export class BaseGenerator extends EventEmitter {
34
30
  options;
35
31
  _initOptions;
36
32
  _args;
@@ -76,7 +72,6 @@ export class BaseGenerator
76
72
  _running = false;
77
73
  features;
78
74
  yoGeneratorVersion = packageJson.version;
79
- // eslint-disable-next-line complexity
80
75
  constructor(args, options, features) {
81
76
  super();
82
77
  const actualArgs = Array.isArray(args) ? args : [];
@@ -86,7 +81,6 @@ export class BaseGenerator
86
81
  // Load parameters
87
82
  this._args = actualArgs;
88
83
  this.options = generatorOptions;
89
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
90
84
  this.features = actualFeatures ?? {};
91
85
  // Initialize properties
92
86
  this._options = {};
@@ -218,20 +212,19 @@ export class BaseGenerator
218
212
  }
219
213
  console.warn(`It's not possible to check version with running Environment less than ${ENV_VER_WITH_VER_API}`);
220
214
  console.warn('Some features may be missing');
221
- if (semver.lte(versionToCheck, '2.8.1')) {
215
+ if (semverLte(versionToCheck, '2.8.1')) {
222
216
  return undefined;
223
217
  }
224
218
  return false;
225
219
  }
226
220
  const runningVersion = this.env.getVersion(packageDependency);
227
- if (runningVersion !== undefined && semver.lte(versionToCheck, runningVersion)) {
221
+ if (runningVersion !== undefined && semverLte(versionToCheck, runningVersion)) {
228
222
  return true;
229
223
  }
230
224
  // Version cannot be checked
231
225
  if (runningVersion === undefined) {
232
226
  return true;
233
227
  }
234
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
235
228
  if (this.options.ignoreVersionCheck || warning) {
236
229
  console.warn(`Current ${packageDependency} is not compatible with current generator, min required: ${versionToCheck} current version: ${runningVersion}. Some features may be missing, try updating reinstalling 'yo'.`);
237
230
  return false;
@@ -357,7 +350,7 @@ export class BaseGenerator
357
350
  }
358
351
  const spec = typeof name === 'object'
359
352
  ? name
360
- : { hide: false, type: Boolean, description: 'Description for ' + name, ...config, name };
353
+ : { hide: false, type: Boolean, description: `Description for ${name}`, ...config, name };
361
354
  const specName = spec.name;
362
355
  // Check whether boolean option is invalid (starts with no-)
363
356
  const boolOptionRegex = /^no-/;
@@ -366,7 +359,7 @@ export class BaseGenerator
366
359
  throw new Error([
367
360
  `Option name ${chalk.yellow(specName)} cannot start with ${chalk.red('no-')}\n`,
368
361
  `Option name prefixed by ${chalk.yellow('--no')} are parsed as implicit`,
369
- ` boolean. To use ${chalk.yellow('--' + specName)} as an option, use\n`,
362
+ ` boolean. To use ${chalk.yellow(`--${specName}`)} as an option, use\n`,
370
363
  chalk.cyan(` this.option('${simpleName}', {type: Boolean})`),
371
364
  ].join(''));
372
365
  }
@@ -449,7 +442,6 @@ export class BaseGenerator
449
442
  for (const [name, option] of Object.entries(parsedOptions)) {
450
443
  // Manually set value as undefined if it should be.
451
444
  if (option === EMPTY) {
452
- // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
453
445
  delete parsedOptions[name];
454
446
  }
455
447
  else if (this._options[name] && option !== undefined) {
@@ -471,7 +463,7 @@ export class BaseGenerator
471
463
  }
472
464
  }
473
465
  else if (config.type === Array) {
474
- value = parsedOptions._.slice(index, parsedOptions._.length);
466
+ value = parsedOptions._.slice(index);
475
467
  }
476
468
  else {
477
469
  value = config.type(parsedOptions._[index]);
@@ -637,7 +629,7 @@ export class BaseGenerator
637
629
  * @return joined path
638
630
  */
639
631
  templatePath(...dest) {
640
- let filepath = path.join.apply(path, dest);
632
+ let filepath = path.join(...dest);
641
633
  if (!path.isAbsolute(filepath)) {
642
634
  filepath = path.join(this.sourceRoot(), filepath);
643
635
  }
@@ -649,7 +641,7 @@ export class BaseGenerator
649
641
  * @return joined path
650
642
  */
651
643
  destinationPath(...dest) {
652
- let filepath = path.join.apply(path, dest);
644
+ let filepath = path.join(...dest);
653
645
  if (!path.isAbsolute(filepath)) {
654
646
  filepath = path.join(this.destinationRoot(), filepath);
655
647
  }
@@ -665,7 +657,7 @@ export class BaseGenerator
665
657
  */
666
658
  determineAppname() {
667
659
  const appName = this.packageJson.get('name') ?? path.basename(this.destinationRoot());
668
- return appName.replaceAll(/[^\w\s]+?/g, ' ');
660
+ return appName.replaceAll(/[^\s\w]+?/g, ' ');
669
661
  }
670
662
  }
671
663
  applyMixins(BaseGenerator, [FsMixin, HelpMixin, PackageJsonMixin, SpawnCommandMixin, GitMixin, TasksMixin]);
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import { type SimpleGit } from 'simple-git';
2
2
  import { BaseGenerator } from './generator.js';
3
3
  import type { BaseFeatures, BaseOptions } from './types.js';
4
4
  export type * from './types.js';
5
+ export type * from './questions.js';
5
6
  export type * from './util/storage.js';
6
7
  export { default as Storage } from './util/storage.js';
7
8
  export default class Generator<O extends BaseOptions = BaseOptions, F extends BaseFeatures = BaseFeatures> extends BaseGenerator<O, F> {
package/dist/index.js CHANGED
@@ -25,7 +25,6 @@ export default class Generator extends BaseGenerator {
25
25
  if (!this._simpleGit) {
26
26
  this._simpleGit = simpleGit({ baseDir: this.destinationPath() }).env({
27
27
  ...process.env,
28
- // eslint-disable-next-line @typescript-eslint/naming-convention
29
28
  LANG: 'en',
30
29
  });
31
30
  this.on(DESTINATION_ROOT_CHANGE_EVENT, () => {
@@ -1,4 +1,3 @@
1
- /* eslint-disable @typescript-eslint/naming-convention */
2
1
  /**
3
2
  * https://github.com/microsoft/TypeScript/issues/14107#issuecomment-1146738780
4
3
  */
@@ -7,7 +7,7 @@ import type Storage from './storage.js';
7
7
  * @param questions Original prompt questions
8
8
  * @return Prompt questions array with prefilled values.
9
9
  */
10
- export declare const prefillQuestions: <A extends import("inquirer").Answers = import("inquirer").Answers>(store: Storage, questions: PromptQuestion<A>[]) => PromptQuestion<A>[];
10
+ export declare const prefillQuestions: <A extends PromptAnswers = PromptAnswers>(store: Storage, questions: Array<PromptQuestion<A>>) => PromptQuestion<A>[];
11
11
  /**
12
12
  * Store the answers in the global store
13
13
  *
@@ -1,5 +1,4 @@
1
1
  import assert from 'node:assert';
2
- // eslint-disable-next-line @typescript-eslint/promise-function-async
3
2
  const getChoices = (question) => {
4
3
  if (question.type === 'list') {
5
4
  return question.choices;
@@ -13,7 +12,7 @@ const getChoices = (question) => {
13
12
  if (question.type === 'rawlist') {
14
13
  return question.choices;
15
14
  }
16
- return undefined;
15
+ return;
17
16
  };
18
17
  /**
19
18
  * Returns the default value for a checkbox
@@ -1,14 +1,14 @@
1
1
  import assert from 'node:assert';
2
- import { cloneDeep, defaults as setDefaults, merge, get, set } from 'lodash-es';
2
+ import { cloneDeep, get, merge, set, defaults as setDefaults } from 'lodash-es';
3
3
  import sortKeys from 'sort-keys';
4
4
  /**
5
5
  * Proxy handler for Storage
6
6
  */
7
7
  const proxyHandler = {
8
- get(storage, property, receiver) {
8
+ get(storage, property, _receiver) {
9
9
  return storage.get(property);
10
10
  },
11
- set(storage, property, value, receiver) {
11
+ set(storage, property, value, _receiver) {
12
12
  if (typeof property === 'string') {
13
13
  storage.set(property, value);
14
14
  return true;
@@ -220,7 +220,6 @@ class Storage {
220
220
  */
221
221
  delete(key) {
222
222
  const store = this._store;
223
- // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
224
223
  delete store[key];
225
224
  this._persist(store);
226
225
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yeoman-generator",
3
- "version": "7.3.2",
3
+ "version": "7.4.0",
4
4
  "description": "Rails-inspired generator system that provides scaffolding for your apps",
5
5
  "keywords": [
6
6
  "development",
@@ -44,22 +44,22 @@
44
44
  "doc:generate": "jsdoc -c jsdoc.json -d $npm_package_config_doc_path$DOC_FOLDER",
45
45
  "doc:prettier": "prettier $npm_package_config_doc_path$DOC_FOLDER --write --ignore-path .prettierignore-doc",
46
46
  "prepare": "npm run build",
47
- "pretest": "xo",
48
- "test": "c8 esmocha --forbid-only"
47
+ "pretest": "eslint . && npm run build",
48
+ "test": "vitest run --coverage"
49
49
  },
50
50
  "config": {
51
51
  "doc_path": "../yeoman-generator-doc/"
52
52
  },
53
53
  "dependencies": {
54
54
  "@types/lodash-es": "^4.17.9",
55
- "@types/node": "^18.18.5",
55
+ "@types/node": ">=18.18.5",
56
56
  "@yeoman/namespace": "^1.0.0",
57
57
  "chalk": "^5.3.0",
58
58
  "debug": "^4.1.1",
59
59
  "execa": "^8.0.1",
60
- "github-username": "^7.0.0",
60
+ "github-username": "^8.0.0",
61
61
  "json-schema": "^0.4.0",
62
- "latest-version": "^7.0.0",
62
+ "latest-version": "^9.0.0",
63
63
  "lodash-es": "^4.17.21",
64
64
  "mem-fs-editor": "^11.0.1",
65
65
  "minimist": "^1.2.8",
@@ -72,39 +72,32 @@
72
72
  "devDependencies": {
73
73
  "@types/debug": "^4.1.9",
74
74
  "@types/ejs": "^3.1.4",
75
- "@types/inquirer": "^9.0.4",
75
+ "@types/json-schema": "^7.0.15",
76
76
  "@types/minimist": "^1.2.3",
77
77
  "@types/semver": "^7.5.3",
78
78
  "@types/sinon": "^17.0.1",
79
79
  "@types/text-table": "^0.2.3",
80
- "@yeoman/adapter": "^1.4.0",
81
- "@yeoman/transform": "^1.2.0",
82
- "c8": "^8.0.1",
80
+ "@vitest/coverage-v8": "^2.1.8",
81
+ "@yeoman/adapter": "^2.0.0",
82
+ "@yeoman/eslint": "^0.2.0",
83
+ "@yeoman/transform": "^2.0.0",
83
84
  "cpy-cli": "^5.0.0",
84
85
  "ejs": "^3.1.9",
85
- "esmocha": "^1.0.1",
86
- "inquirer": "^9.2.11",
86
+ "inquirer": "^12.0.0",
87
87
  "jsdoc": "^4.0.2",
88
- "nock": "^13.3.4",
89
88
  "prettier": "^3.0.3",
90
89
  "prettier-plugin-packagejson": "^2.4.6",
91
- "sinon": "^18.0.0",
92
- "tui-jsdoc-template": "^1.2.2",
90
+ "sinon": "^19.0.0",
91
+ "type-fest": "^4.26.1",
93
92
  "typescript": "^5.2.2",
94
- "xo": "^0.56.0",
93
+ "vitest": "^2.1.8",
95
94
  "yeoman-assert": "^3.1.1",
96
- "yeoman-environment": "^4.0.0",
97
- "yeoman-test": "^8.1.0"
95
+ "yeoman-environment": "^4.4.1",
96
+ "yeoman-test": "^10.0.1"
98
97
  },
99
98
  "peerDependencies": {
100
99
  "@yeoman/types": "^1.1.1",
101
- "mem-fs": "^4.0.0",
102
- "yeoman-environment": "^4.0.0"
103
- },
104
- "peerDependenciesMeta": {
105
- "yeoman-environment": {
106
- "optional": true
107
- }
100
+ "mem-fs": "^4.0.0"
108
101
  },
109
102
  "engines": {
110
103
  "node": "^18.17.0 || >=20.5.0"