fg-devkit 1.7.3 → 1.7.4

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.
package/README.md CHANGED
@@ -45,6 +45,24 @@ pnpm exec fgd typecheck
45
45
  pnpm exec fgd typecheck-watch
46
46
  ```
47
47
 
48
+ ## Bundled Fallow (dead code analysis)
49
+
50
+ `fg-devkit` also ships Fallow for dead code analysis in consuming repos.
51
+
52
+ Run dead code analysis via CLI:
53
+
54
+ ```bash
55
+ pnpm exec fgd dead-code
56
+ ```
57
+
58
+ Or run Fallow directly with custom args:
59
+
60
+ ```bash
61
+ pnpm exec fgd fallow dead-code --json
62
+ ```
63
+
64
+ When you run `fgd sync-tooling-configs` (or `fgd sync-project-configs`), fg-devkit also writes a shared `.fallowrc.json` to the consuming repo.
65
+
48
66
  To remove redundant tooling dependencies from a consuming repo:
49
67
 
50
68
  ```bash
@@ -136,6 +154,33 @@ export default {
136
154
  ...basePrettierConfig,
137
155
  }
138
156
  ```
157
+
158
+ ## Local development with pnpm link
159
+
160
+ Use this flow to test local `fg-devkit` changes in a consuming repo.
161
+
162
+ In this repo (`fg-devkit`):
163
+
164
+ ```bash
165
+ pnpm install
166
+ pnpm link --global
167
+ ```
168
+
169
+ In the consuming repo:
170
+
171
+ ```bash
172
+ pnpm link --global fg-devkit
173
+ pnpm install
174
+ pnpm exec fgd --help
175
+ ```
176
+
177
+ To remove the global link in a consuming repo:
178
+
179
+ ```bash
180
+ pnpm unlink fg-devkit
181
+ pnpm install
182
+ ```
183
+
139
184
  ## Install CLI in this repo
140
185
 
141
186
  1) Add this to your shell config (`~/.zshrc`) and update `FGD_DEVKIT_PATH`:
@@ -0,0 +1,13 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/fallow-rs/fallow/main/schema.json",
3
+ "ignorePatterns": [
4
+ "**/*.d.ts",
5
+ "**/*.generated.*",
6
+ "dist/**",
7
+ "build/**",
8
+ "coverage/**",
9
+ "src/style.css",
10
+ "index.html"
11
+ ],
12
+ "publicPackages": ["fds-vue-core"]
13
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fg-devkit",
3
- "version": "1.7.3",
3
+ "version": "1.7.4",
4
4
  "description": "Shared configs, scripts, and DX tooling for Vue / TypeScript frontend repos",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -72,6 +72,8 @@
72
72
  }
73
73
  },
74
74
  "dependencies": {
75
+ "@inquirer/confirm": "^6.0.12",
76
+ "@inquirer/select": "^5.1.4",
75
77
  "@intlify/eslint-plugin-vue-i18n": "4.3.0",
76
78
  "@typescript-eslint/eslint-plugin": "8.58.2",
77
79
  "@typescript-eslint/parser": "8.58.2",
@@ -83,6 +85,7 @@
83
85
  "eslint": "10.2.1",
84
86
  "eslint-plugin-prettier": "5.5.5",
85
87
  "eslint-plugin-vue": "10.8.0",
88
+ "fallow": "^2.52.2",
86
89
  "lefthook": "2.1.6",
87
90
  "npm-check-updates": "21.0.3",
88
91
  "prettier": "3.8.3",
@@ -34,7 +34,7 @@
34
34
  "@tanstack/vue-query-devtools": "6.1.24",
35
35
  "@types/node": "22.16.5",
36
36
  "@vitejs/plugin-vue": "6.0.6",
37
- "fg-devkit": "1.7.3",
37
+ "fg-devkit": "1.7.4",
38
38
  "start-server-and-test": "2.1.3",
39
39
  "tailwindcss": "4.2.4",
40
40
  "tsx": "4.21.0",
@@ -28,6 +28,8 @@
28
28
  * pnpm exec fg-devkit format-check [prettier-args...] (same as format plus --check)
29
29
  * pnpm exec fg-devkit typecheck [vue-tsc-args...] (run vue-tsc with fg-devkit bundled package)
30
30
  * pnpm exec fg-devkit typecheck-watch [vue-tsc-args...] (same as typecheck plus --watch)
31
+ * pnpm exec fg-devkit fallow [fallow-args...] (run Fallow with fg-devkit bundled package)
32
+ * pnpm exec fg-devkit dead-code [fallow-args...] (same as: fallow dead-code [args...])
31
33
  * pnpm exec fg-devkit poeditor-download [args...] (download translations using poeditor/.poeditor.json + env token)
32
34
  * pnpm exec fg-devkit poeditor-upload [args...] (upload translations using poeditor/.poeditor.json + env token)
33
35
  * Interactive menu (no subcommand):
@@ -405,6 +407,37 @@ function runBundledTypeScript(args = []) {
405
407
  return r.status ?? 1
406
408
  }
407
409
 
410
+ /** Run Fallow from fg-devkit's bundled dependency set. */
411
+ function runBundledFallow(args = []) {
412
+ let fallowBin
413
+ try {
414
+ const fallowPkgJson = require.resolve('fallow/package.json', {
415
+ paths: [fgRoot, process.cwd()],
416
+ })
417
+ const fallowPkgRoot = path.dirname(fallowPkgJson)
418
+ fallowBin = path.join(fallowPkgRoot, 'bin', 'fallow')
419
+ if (!fs.existsSync(fallowBin)) {
420
+ throw new Error('fallow bin not found')
421
+ }
422
+ } catch {
423
+ console.error('[fg-devkit] Could not resolve bundled fallow.')
424
+ console.error('[fg-devkit] Run pnpm install in fg-devkit and in the linked consumer, then retry.')
425
+ return 1
426
+ }
427
+
428
+ const r = spawnSync(process.execPath, [fallowBin, ...args], {
429
+ stdio: 'inherit',
430
+ cwd: process.cwd(),
431
+ env: process.env,
432
+ })
433
+ if (r.error) {
434
+ console.error('[fg-devkit] Could not run bundled fallow.')
435
+ console.error('[fg-devkit]', r.error.message)
436
+ return 1
437
+ }
438
+ return r.status ?? 1
439
+ }
440
+
408
441
  /** Map subcommand name → script file (extra argv after subcommand is forwarded). */
409
442
  const DIRECT_COMMANDS = {
410
443
  'check-deps': 'check-dependency-policy.mjs',
@@ -461,6 +494,8 @@ Commands:
461
494
  format-check [prettier-args...] Run Prettier with --check using fg-devkit bundled package
462
495
  typecheck [vue-tsc-args...] Run vue-tsc using fg-devkit bundled package
463
496
  typecheck-watch [vue-tsc-args...] Run vue-tsc with --watch using fg-devkit bundled package
497
+ fallow [fallow-args...] Run Fallow using fg-devkit bundled package
498
+ dead-code [fallow-args...] Run Fallow dead code analysis (shortcut for: fallow dead-code)
464
499
  poeditor-download [args...] Download locale files via PoEditor (reads poeditor/.poeditor.json by default)
465
500
  poeditor-upload [args...] Upload locale file via PoEditor (reads poeditor/.poeditor.json by default)
466
501
  scaffold-vue <target-dir> [--name …] [--slug …] [--force] …
@@ -488,7 +523,7 @@ const MENU = [
488
523
  },
489
524
  {
490
525
  key: '3',
491
- label: 'Sync configs (vscode, eslint, prettier, tsconfig)',
526
+ label: 'Sync configs (vscode, eslint, prettier, tsconfig, fallow)',
492
527
  run: () => runNode('sync-project-configs.mjs'),
493
528
  },
494
529
  {
@@ -536,6 +571,11 @@ const MENU = [
536
571
  label: 'Sync .cursor core coding standards',
537
572
  run: () => runNode('sync-core-coding-standards.mjs'),
538
573
  },
574
+ {
575
+ key: '13',
576
+ label: 'Fallow analysis',
577
+ run: () => 0,
578
+ },
539
579
  ]
540
580
 
541
581
  const MAINTAINER_MENU = [
@@ -633,6 +673,38 @@ async function runInteractiveMenu() {
633
673
  // Close menu readline before spawning interactive child processes.
634
674
  rl.close()
635
675
  out = runReleaseScript([bumpType])
676
+ } else if (item.key === '13') {
677
+ let subChoice = 'cancel'
678
+ let selectPrompt = null
679
+ try {
680
+ const inquirerSelect = await import('@inquirer/select')
681
+ selectPrompt = inquirerSelect.default
682
+ } catch {
683
+ // Optional dependency; fail with a clear message if not available.
684
+ }
685
+
686
+ if (selectPrompt) {
687
+ // Close menu readline before running interactive child prompt.
688
+ rl.close()
689
+ subChoice = await selectPrompt({
690
+ message: 'Fallow — choose analysis',
691
+ choices: [
692
+ { name: 'dead code', value: 'dead-code' },
693
+ { name: 'Cancel', value: 'cancel' },
694
+ ],
695
+ default: 'dead-code',
696
+ })
697
+ } else {
698
+ rl.close()
699
+ console.error('[fg-devkit] Option 13 requires @inquirer/select but it is not available.')
700
+ console.error('[fg-devkit] Run pnpm install in your project and try again.')
701
+ return 1
702
+ }
703
+
704
+ if (subChoice === 'cancel') {
705
+ return 0
706
+ }
707
+ out = runBundledFallow([subChoice])
636
708
  } else {
637
709
  // Close menu readline before spawning interactive child processes.
638
710
  rl.close()
@@ -705,6 +777,14 @@ async function main() {
705
777
  process.exitCode = runBundledTypeScript(rest.length > 0 ? ['--watch', ...rest] : ['--noEmit', '--watch', '-p', 'tsconfig.json'])
706
778
  return
707
779
  }
780
+ if (sub === 'fallow') {
781
+ process.exitCode = runBundledFallow(rest)
782
+ return
783
+ }
784
+ if (sub === 'dead-code') {
785
+ process.exitCode = runBundledFallow(['dead-code', ...rest])
786
+ return
787
+ }
708
788
  const script = DIRECT_COMMANDS[sub]
709
789
  if (!script) {
710
790
  console.error(`[fg-devkit] Unknown command: ${sub}`)
@@ -4,6 +4,7 @@
4
4
  * - prettier.config.js — overwritten from fg-devkit prettier sync template
5
5
  * - eslint.config.js — overwritten from fg-devkit eslint sync template
6
6
  * - tsconfig.json — overwritten from fg-devkit tsconfig app sync template
7
+ * - .fallowrc.json — overwritten from fg-devkit fallow sync template
7
8
  *
8
9
  * This command is intentionally deterministic: each run rewrites files to the shared templates.
9
10
  *
@@ -46,10 +47,11 @@ if (!fgRoot) {
46
47
  const prettierSrc = path.join(fgRoot, 'configs', 'prettier.sync-stub.js')
47
48
  const eslintStubSrc = path.join(fgRoot, 'configs', 'eslint.sync-stub.js')
48
49
  const tsconfigSrc = path.join(fgRoot, 'configs', 'tsconfig.app.sync.json')
50
+ const fallowConfigSrc = path.join(fgRoot, 'configs', 'fallowrc.sync-stub.json')
49
51
 
50
- if (!fs.existsSync(prettierSrc) || !fs.existsSync(eslintStubSrc) || !fs.existsSync(tsconfigSrc)) {
52
+ if (!fs.existsSync(prettierSrc) || !fs.existsSync(eslintStubSrc) || !fs.existsSync(tsconfigSrc) || !fs.existsSync(fallowConfigSrc)) {
51
53
  console.error(
52
- '[sync-tooling] Missing prettier.sync-stub.js, eslint.sync-stub.js, or tsconfig.app.sync.json inside fg-devkit package.',
54
+ '[sync-tooling] Missing prettier.sync-stub.js, eslint.sync-stub.js, tsconfig.app.sync.json, or fallowrc.sync-stub.json inside fg-devkit package.',
53
55
  )
54
56
  process.exit(1)
55
57
  }
@@ -58,7 +60,8 @@ try {
58
60
  fs.copyFileSync(prettierSrc, path.join(projectRoot, 'prettier.config.js'))
59
61
  fs.copyFileSync(eslintStubSrc, path.join(projectRoot, 'eslint.config.js'))
60
62
  fs.copyFileSync(tsconfigSrc, path.join(projectRoot, 'tsconfig.json'))
61
- console.log('[sync-tooling] Updated prettier.config.js, eslint.config.js, and tsconfig.json.')
63
+ fs.copyFileSync(fallowConfigSrc, path.join(projectRoot, '.fallowrc.json'))
64
+ console.log('[sync-tooling] Updated prettier.config.js, eslint.config.js, tsconfig.json, and .fallowrc.json.')
62
65
  } catch (err) {
63
66
  console.error(`[sync-tooling] ${err.message}`)
64
67
  process.exit(1)