@rtorcato/js-tooling 2.12.0 → 2.13.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.
@@ -7,6 +7,7 @@ import { generateCommitlintConfig, generateHuskyConfig, generatePrePushHook, } f
7
7
  import { generateGitHubActions } from '../generators/github-actions.js';
8
8
  import { generateESLintConfig, generatePrettierConfig } from '../generators/linting.js';
9
9
  import { ensureEnginesNode, generateCodeowners, generateEditorConfig, generateKnipConfig, generateNvmrc, generateSizeLimitConfig, } from '../generators/misc.js';
10
+ import { generateConfigs } from '../generators/index.js';
10
11
  import { composeVerifyScriptFromPkg } from '../generators/package-json.js';
11
12
  import { generateCodeQLWorkflow, generateDependabotConfig } from '../generators/security.js';
12
13
  import { generateVitestConfig } from '../generators/testing.js';
@@ -15,6 +16,7 @@ import { copyPreset } from '../utils/copy-preset.js';
15
16
  import { LOCKFILE_NAME, readLockfile, updateLockfileConfig, writeLockfile, } from '../utils/lockfile.js';
16
17
  import { runDoctor } from './doctor.js';
17
18
  import { declinedInLock, lockfilePatchForTarget } from './fix-targets.js';
19
+ import { computeFileList } from './setup-presets.js';
18
20
  function inferProjectConfig(pkg) {
19
21
  const deps = {
20
22
  ...(pkg?.dependencies ?? {}),
@@ -479,6 +481,60 @@ export async function fixCommand(target, options = {}) {
479
481
  console.log();
480
482
  return;
481
483
  }
484
+ if (options.resync) {
485
+ if (target) {
486
+ console.error(chalk.red('\n❌ --resync cannot be combined with a [target] argument\n'));
487
+ process.exit(1);
488
+ }
489
+ const resyncLock = await readLockfile(targetDir);
490
+ if (!resyncLock) {
491
+ if (json) {
492
+ console.log(JSON.stringify({ directory: targetDir, error: 'no-lockfile', hint: 'run `fix lockfile` first' }, null, 2));
493
+ }
494
+ else {
495
+ console.error(chalk.red(`\n❌ No ${LOCKFILE_NAME} found — run \`fix lockfile\` first to record choices\n`));
496
+ }
497
+ process.exit(1);
498
+ }
499
+ const files = computeFileList(resyncLock.config);
500
+ if (!silent) {
501
+ console.log(chalk.cyan(`\n🔄 Resync from ${LOCKFILE_NAME} (${files.length} files in scope)\n`));
502
+ }
503
+ if (dryRun) {
504
+ if (json) {
505
+ console.log(JSON.stringify({ directory: targetDir, mode: 'resync', dryRun: true, files }, null, 2));
506
+ }
507
+ else {
508
+ for (const f of files)
509
+ console.log(chalk.cyan(` [dry-run] would write: ${f}`));
510
+ console.log();
511
+ }
512
+ return;
513
+ }
514
+ if (!assumeYes) {
515
+ const { confirm } = await inquirer.prompt([
516
+ {
517
+ type: 'confirm',
518
+ name: 'confirm',
519
+ message: `Re-scaffold ${files.length} file(s) from ${LOCKFILE_NAME}? Generators preserve existing customizations where possible, but README.md will be rewritten.`,
520
+ default: false,
521
+ },
522
+ ]);
523
+ if (!confirm) {
524
+ console.log(chalk.gray(' skipped\n'));
525
+ return;
526
+ }
527
+ }
528
+ await generateConfigs(resyncLock.config, targetDir);
529
+ await writeLockfile(targetDir, resyncLock.config);
530
+ if (json) {
531
+ console.log(JSON.stringify({ directory: targetDir, mode: 'resync', dryRun: false, files }, null, 2));
532
+ }
533
+ else {
534
+ console.log(chalk.green(` ✅ resynced ${files.length} file(s)\n`));
535
+ }
536
+ return;
537
+ }
482
538
  const pkg = await readPackageJson(targetDir);
483
539
  const lock = await readLockfile(targetDir);
484
540
  const results = await runDoctor(targetDir);
package/dist/cli/index.js CHANGED
@@ -222,12 +222,14 @@ program
222
222
  .option('--dry-run', 'Print what would change without writing files')
223
223
  .option('--json', 'Emit machine-readable JSON output (implies --yes)')
224
224
  .option('--list', 'List all registered fix targets and exit')
225
+ .option('--resync', 'Re-scaffold every file recorded in .js-tooling.json')
225
226
  .action((target, options) => fixCommand(target, {
226
227
  directory: options.directory,
227
228
  yes: options.yes,
228
229
  dryRun: options.dryRun,
229
230
  json: options.json,
230
231
  list: options.list,
232
+ resync: options.resync,
231
233
  }));
232
234
  program.hook('preAction', async (_, actionCommand) => {
233
235
  const name = actionCommand.name();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rtorcato/js-tooling",
3
- "version": "2.12.0",
3
+ "version": "2.13.0",
4
4
  "description": "JavaScript and TypeScript tooling for Node.js, React, Next.js, and Vitest.",
5
5
  "type": "module",
6
6
  "keywords": [