fg-devkit 1.7.3 → 1.7.5
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 +45 -0
- package/configs/fallowrc.sync-stub.json +13 -0
- package/package.json +4 -1
- package/scaffold/vue/package.json +1 -1
- package/scripts/fg-devkit.mjs +320 -171
- package/scripts/sync-tooling-configs.mjs +6 -3
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
|
+
"version": "1.7.5",
|
|
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",
|
package/scripts/fg-devkit.mjs
CHANGED
|
@@ -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):
|
|
@@ -40,10 +42,8 @@
|
|
|
40
42
|
|
|
41
43
|
import { spawnSync } from 'node:child_process'
|
|
42
44
|
import fs from 'node:fs'
|
|
43
|
-
import readline from 'node:readline/promises'
|
|
44
45
|
import path from 'node:path'
|
|
45
46
|
import { fileURLToPath } from 'node:url'
|
|
46
|
-
import { stdin as input, stdout as output } from 'node:process'
|
|
47
47
|
import { createRequire } from 'node:module'
|
|
48
48
|
|
|
49
49
|
const scriptDir = path.dirname(fileURLToPath(import.meta.url))
|
|
@@ -269,30 +269,6 @@ function runMaintainerAuditAll() {
|
|
|
269
269
|
return runNode('repo-vulns.mjs')
|
|
270
270
|
}
|
|
271
271
|
|
|
272
|
-
/** Prompt release type in CLI before invoking release.sh to avoid a "stuck" terminal feeling. */
|
|
273
|
-
async function promptReleaseType(rl) {
|
|
274
|
-
console.log('\nSelect release type:')
|
|
275
|
-
console.log(' 1) patch')
|
|
276
|
-
console.log(' 2) minor')
|
|
277
|
-
console.log(' 3) major')
|
|
278
|
-
console.log(' 0) Cancel\n')
|
|
279
|
-
const choice = (await rl.question('Release type [1-3] (default: 1): ')).trim() || '1'
|
|
280
|
-
if (choice === '0') {
|
|
281
|
-
return null
|
|
282
|
-
}
|
|
283
|
-
if (choice === '1') {
|
|
284
|
-
return 'patch'
|
|
285
|
-
}
|
|
286
|
-
if (choice === '2') {
|
|
287
|
-
return 'minor'
|
|
288
|
-
}
|
|
289
|
-
if (choice === '3') {
|
|
290
|
-
return 'major'
|
|
291
|
-
}
|
|
292
|
-
console.error('[fg-devkit] Invalid release type selection.')
|
|
293
|
-
return null
|
|
294
|
-
}
|
|
295
|
-
|
|
296
272
|
/**
|
|
297
273
|
* Run Commitizen from fg-devkit's bundled dependency set.
|
|
298
274
|
* Always forces fg-devkit's bundled cz adapter so it stays interactive.
|
|
@@ -340,6 +316,18 @@ bootstrap(
|
|
|
340
316
|
|
|
341
317
|
/** Run ESLint from fg-devkit's bundled dependency set. */
|
|
342
318
|
function runBundledEslint(args = []) {
|
|
319
|
+
const hasExplicitConfig = args.some((arg) => arg === '--config' || arg === '-c' || arg.startsWith('--config='))
|
|
320
|
+
const hasLocalFlatConfig =
|
|
321
|
+
fs.existsSync(path.join(process.cwd(), 'eslint.config.js')) ||
|
|
322
|
+
fs.existsSync(path.join(process.cwd(), 'eslint.config.mjs')) ||
|
|
323
|
+
fs.existsSync(path.join(process.cwd(), 'eslint.config.cjs'))
|
|
324
|
+
|
|
325
|
+
if (!hasExplicitConfig && !hasLocalFlatConfig) {
|
|
326
|
+
console.error('[fg-devkit] Missing eslint.config.js|mjs|cjs in current directory.')
|
|
327
|
+
console.error('[fg-devkit] Run "fgd sync-project-configs" or "fgd sync-tooling-configs" and retry.')
|
|
328
|
+
return 1
|
|
329
|
+
}
|
|
330
|
+
|
|
343
331
|
let eslintBin
|
|
344
332
|
try {
|
|
345
333
|
const eslintPkgPath = require.resolve('eslint/package.json')
|
|
@@ -405,6 +393,65 @@ function runBundledTypeScript(args = []) {
|
|
|
405
393
|
return r.status ?? 1
|
|
406
394
|
}
|
|
407
395
|
|
|
396
|
+
/** Run Fallow from fg-devkit's bundled dependency set. */
|
|
397
|
+
function runBundledFallow(args = []) {
|
|
398
|
+
let fallowBin
|
|
399
|
+
try {
|
|
400
|
+
const fallowPkgJson = require.resolve('fallow/package.json', {
|
|
401
|
+
paths: [fgRoot, process.cwd()],
|
|
402
|
+
})
|
|
403
|
+
const fallowPkgRoot = path.dirname(fallowPkgJson)
|
|
404
|
+
fallowBin = path.join(fallowPkgRoot, 'bin', 'fallow')
|
|
405
|
+
if (!fs.existsSync(fallowBin)) {
|
|
406
|
+
throw new Error('fallow bin not found')
|
|
407
|
+
}
|
|
408
|
+
} catch {
|
|
409
|
+
console.error('[fg-devkit] Could not resolve bundled fallow.')
|
|
410
|
+
console.error('[fg-devkit] Run pnpm install in fg-devkit and in the linked consumer, then retry.')
|
|
411
|
+
return 1
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const r = spawnSync(process.execPath, [fallowBin, ...args], {
|
|
415
|
+
stdio: 'inherit',
|
|
416
|
+
cwd: process.cwd(),
|
|
417
|
+
env: process.env,
|
|
418
|
+
})
|
|
419
|
+
if (r.error) {
|
|
420
|
+
console.error('[fg-devkit] Could not run bundled fallow.')
|
|
421
|
+
console.error('[fg-devkit]', r.error.message)
|
|
422
|
+
return 1
|
|
423
|
+
}
|
|
424
|
+
return r.status ?? 1
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function syncFileFromTemplate(relativeSourcePath, targetPath) {
|
|
428
|
+
const sourcePath = path.join(fgRoot, relativeSourcePath)
|
|
429
|
+
if (!fs.existsSync(sourcePath)) {
|
|
430
|
+
console.error(`[fg-devkit] Missing template: ${sourcePath}`)
|
|
431
|
+
return 1
|
|
432
|
+
}
|
|
433
|
+
try {
|
|
434
|
+
fs.copyFileSync(sourcePath, path.join(process.cwd(), targetPath))
|
|
435
|
+
console.log(`[fg-devkit] Synced ${targetPath}`)
|
|
436
|
+
return 0
|
|
437
|
+
} catch (err) {
|
|
438
|
+
console.error(`[fg-devkit] Failed to sync ${targetPath}: ${err.message}`)
|
|
439
|
+
return 1
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
function runSyncConfigTarget(target) {
|
|
444
|
+
if (target === 'vscode') return runNode('sync-vscode-settings.mjs')
|
|
445
|
+
if (target === 'eslint') return syncFileFromTemplate('configs/eslint.sync-stub.js', 'eslint.config.js')
|
|
446
|
+
if (target === 'prettier') return syncFileFromTemplate('configs/prettier.sync-stub.js', 'prettier.config.js')
|
|
447
|
+
if (target === 'tsconfig') return syncFileFromTemplate('configs/tsconfig.app.sync.json', 'tsconfig.json')
|
|
448
|
+
if (target === 'fallow') return syncFileFromTemplate('configs/fallowrc.sync-stub.json', '.fallowrc.json')
|
|
449
|
+
if (target === 'cursor') return runNode('sync-core-coding-standards.mjs')
|
|
450
|
+
if (target === 'all') return runNode('sync-project-configs.mjs')
|
|
451
|
+
console.error(`[fg-devkit] Unknown config sync target: ${target}`)
|
|
452
|
+
return 1
|
|
453
|
+
}
|
|
454
|
+
|
|
408
455
|
/** Map subcommand name → script file (extra argv after subcommand is forwarded). */
|
|
409
456
|
const DIRECT_COMMANDS = {
|
|
410
457
|
'check-deps': 'check-dependency-policy.mjs',
|
|
@@ -461,6 +508,8 @@ Commands:
|
|
|
461
508
|
format-check [prettier-args...] Run Prettier with --check using fg-devkit bundled package
|
|
462
509
|
typecheck [vue-tsc-args...] Run vue-tsc using fg-devkit bundled package
|
|
463
510
|
typecheck-watch [vue-tsc-args...] Run vue-tsc with --watch using fg-devkit bundled package
|
|
511
|
+
fallow [fallow-args...] Run Fallow using fg-devkit bundled package
|
|
512
|
+
dead-code [fallow-args...] Run Fallow dead code analysis (shortcut for: fallow dead-code)
|
|
464
513
|
poeditor-download [args...] Download locale files via PoEditor (reads poeditor/.poeditor.json by default)
|
|
465
514
|
poeditor-upload [args...] Upload locale file via PoEditor (reads poeditor/.poeditor.json by default)
|
|
466
515
|
scaffold-vue <target-dir> [--name …] [--slug …] [--force] …
|
|
@@ -468,119 +517,12 @@ Commands:
|
|
|
468
517
|
sync-scaffold-vue-deps [policy-file]
|
|
469
518
|
Align scaffold/vue/package.json versions to the dependency policy
|
|
470
519
|
|
|
471
|
-
With no command, opens an interactive menu.
|
|
520
|
+
With no command, opens an interactive Inquirer menu.
|
|
472
521
|
|
|
473
522
|
Options:
|
|
474
523
|
-h, --help Show this help`)
|
|
475
524
|
}
|
|
476
525
|
|
|
477
|
-
/** Numbered actions shown in the interactive menu (keys must match user input). */
|
|
478
|
-
const MENU = [
|
|
479
|
-
{
|
|
480
|
-
key: '1',
|
|
481
|
-
label: 'Check dependency policy',
|
|
482
|
-
run: () => runNode('check-dependency-policy.mjs'),
|
|
483
|
-
},
|
|
484
|
-
{
|
|
485
|
-
key: '2',
|
|
486
|
-
label: 'Sync dependency policy',
|
|
487
|
-
run: () => runNode('sync-dependency-policy.mjs'),
|
|
488
|
-
},
|
|
489
|
-
{
|
|
490
|
-
key: '3',
|
|
491
|
-
label: 'Sync configs (vscode, eslint, prettier, tsconfig)',
|
|
492
|
-
run: () => runNode('sync-project-configs.mjs'),
|
|
493
|
-
},
|
|
494
|
-
{
|
|
495
|
-
key: '4',
|
|
496
|
-
label: 'Create release',
|
|
497
|
-
run: () => runReleaseScript(),
|
|
498
|
-
},
|
|
499
|
-
{
|
|
500
|
-
key: '5',
|
|
501
|
-
label: 'Commit (Commitizen)',
|
|
502
|
-
run: () => runCommitizen(),
|
|
503
|
-
},
|
|
504
|
-
{
|
|
505
|
-
key: '6',
|
|
506
|
-
label: 'Commit vulnerability (Commitizen)',
|
|
507
|
-
run: () => runCommitizen([], { FG_DEVKIT_CZ_DEFAULT_TYPE: 'vuln' }),
|
|
508
|
-
},
|
|
509
|
-
{
|
|
510
|
-
key: '7',
|
|
511
|
-
label: 'Remove unnecessary deps in package.json',
|
|
512
|
-
run: () => runNode('prune-consumer-deps.mjs'),
|
|
513
|
-
},
|
|
514
|
-
{
|
|
515
|
-
key: '8',
|
|
516
|
-
label: 'Full consumer setup (7 -> scripts -> lefthook -> 3 -> 2 -> pnpm install)',
|
|
517
|
-
run: () => runFullConsumerSetup(),
|
|
518
|
-
},
|
|
519
|
-
{
|
|
520
|
-
key: '9',
|
|
521
|
-
label: 'Setup lefthook (migrate from husky/lint-staged)',
|
|
522
|
-
run: () => runSetupLefthook(),
|
|
523
|
-
},
|
|
524
|
-
{
|
|
525
|
-
key: '10',
|
|
526
|
-
label: 'PoEditor: Download translations',
|
|
527
|
-
run: () => runNode('poeditor-download.mjs'),
|
|
528
|
-
},
|
|
529
|
-
{
|
|
530
|
-
key: '11',
|
|
531
|
-
label: 'PoEditor: Upload translations',
|
|
532
|
-
run: () => runNode('poeditor-upload.mjs'),
|
|
533
|
-
},
|
|
534
|
-
{
|
|
535
|
-
key: '12',
|
|
536
|
-
label: 'Sync .cursor core coding standards',
|
|
537
|
-
run: () => runNode('sync-core-coding-standards.mjs'),
|
|
538
|
-
},
|
|
539
|
-
]
|
|
540
|
-
|
|
541
|
-
const MAINTAINER_MENU = [
|
|
542
|
-
{
|
|
543
|
-
key: 'm1',
|
|
544
|
-
label: 'Maintainer: Show outdated dependency policy packages',
|
|
545
|
-
run: () => runNode('policy-outdated.mjs'),
|
|
546
|
-
},
|
|
547
|
-
{
|
|
548
|
-
key: 'm2',
|
|
549
|
-
label: 'Maintainer: Upgrade dependency policy (interactive)',
|
|
550
|
-
run: () => runNode('policy-upgrade.mjs'),
|
|
551
|
-
},
|
|
552
|
-
{
|
|
553
|
-
key: 'm3',
|
|
554
|
-
label: 'Maintainer: Refresh dependency policy from repos (and scaffold/vue package.json)',
|
|
555
|
-
run: () => runNode('refresh-dependency-policy-from-repos.mjs'),
|
|
556
|
-
},
|
|
557
|
-
{
|
|
558
|
-
key: 'm4',
|
|
559
|
-
label: 'Maintainer: Upgrade one policy package, stage, and auto-commit',
|
|
560
|
-
run: () => runMaintainerPolicyUpgradeAndCommit(),
|
|
561
|
-
},
|
|
562
|
-
{
|
|
563
|
-
key: 'm5',
|
|
564
|
-
label: 'Maintainer: Check policy vulnerabilities (audit)',
|
|
565
|
-
run: () => runNode('policy-vulns.mjs'),
|
|
566
|
-
},
|
|
567
|
-
{
|
|
568
|
-
key: 'm6',
|
|
569
|
-
label: 'Maintainer: Check fg-devkit repo vulnerabilities',
|
|
570
|
-
run: () => runMaintainerAuditAll(),
|
|
571
|
-
},
|
|
572
|
-
{
|
|
573
|
-
key: 'm7',
|
|
574
|
-
label: 'Maintainer: Check vulnerabilities across all Vue repos',
|
|
575
|
-
run: () => runNode('fleet-vulns.mjs'),
|
|
576
|
-
},
|
|
577
|
-
{
|
|
578
|
-
key: 'm8',
|
|
579
|
-
label: 'Maintainer: Bump fg-devkit in all Vue repos, run sync-deps, and pnpm install',
|
|
580
|
-
run: () => runNode('fleet-bump-fg-devkit.mjs'),
|
|
581
|
-
},
|
|
582
|
-
]
|
|
583
|
-
|
|
584
526
|
function isFgDevkitMaintainerContext() {
|
|
585
527
|
if (path.resolve(process.cwd()) !== fgRoot) {
|
|
586
528
|
return false
|
|
@@ -598,53 +540,252 @@ function isFgDevkitMaintainerContext() {
|
|
|
598
540
|
}
|
|
599
541
|
|
|
600
542
|
async function runInteractiveMenu() {
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
543
|
+
let selectPrompt
|
|
544
|
+
try {
|
|
545
|
+
const inquirerSelect = await import('@inquirer/select')
|
|
546
|
+
selectPrompt = inquirerSelect.default
|
|
547
|
+
} catch {
|
|
548
|
+
console.error('[fg-devkit] Interactive menu requires @inquirer/select but it is not available.')
|
|
549
|
+
console.error('[fg-devkit] Run pnpm install in your project and try again.')
|
|
550
|
+
return 1
|
|
609
551
|
}
|
|
610
|
-
console.log(' 0) Exit\n')
|
|
611
|
-
|
|
612
|
-
const choice = (await rl.question('Number: ')).trim()
|
|
613
552
|
|
|
614
|
-
|
|
615
|
-
|
|
553
|
+
const runSelectedAction = async (action) => {
|
|
554
|
+
const out = action()
|
|
555
|
+
if (typeof out === 'object' && out !== null && typeof out.then === 'function') {
|
|
556
|
+
return await out
|
|
557
|
+
}
|
|
558
|
+
if (typeof out === 'number') {
|
|
559
|
+
return out
|
|
560
|
+
}
|
|
616
561
|
return 0
|
|
617
562
|
}
|
|
618
563
|
|
|
619
|
-
const
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
564
|
+
const maintainerOnly = () => {
|
|
565
|
+
if (!isFgDevkitMaintainerContext()) {
|
|
566
|
+
console.error('[fg-devkit] Maintainer actions are only available in the fg-devkit repository root.')
|
|
567
|
+
return 1
|
|
568
|
+
}
|
|
569
|
+
return 0
|
|
624
570
|
}
|
|
625
571
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
572
|
+
const groups = [
|
|
573
|
+
{
|
|
574
|
+
name: '1) Create commit',
|
|
575
|
+
value: 'commit',
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
name: '2) Create release',
|
|
579
|
+
value: 'release',
|
|
580
|
+
},
|
|
581
|
+
{
|
|
582
|
+
name: '3) Lint and typecheck',
|
|
583
|
+
value: 'lint-typecheck',
|
|
584
|
+
},
|
|
585
|
+
{
|
|
586
|
+
name: '4) Poeditor',
|
|
587
|
+
value: 'poeditor',
|
|
588
|
+
},
|
|
589
|
+
{
|
|
590
|
+
name: '5) Dependecy policy',
|
|
591
|
+
value: 'dependency-policy',
|
|
592
|
+
},
|
|
593
|
+
{
|
|
594
|
+
name: '6) Sync configs',
|
|
595
|
+
value: 'sync-configs',
|
|
596
|
+
},
|
|
597
|
+
{
|
|
598
|
+
name: '7) Setup',
|
|
599
|
+
value: 'setup',
|
|
600
|
+
},
|
|
601
|
+
{
|
|
602
|
+
name: '8) Fallow analysis',
|
|
603
|
+
value: 'fallow-analysis',
|
|
604
|
+
},
|
|
605
|
+
{
|
|
606
|
+
name: '9) Maintainer',
|
|
607
|
+
value: 'maintainer',
|
|
608
|
+
},
|
|
609
|
+
{
|
|
610
|
+
name: '10) Exit',
|
|
611
|
+
value: 'exit',
|
|
612
|
+
},
|
|
613
|
+
]
|
|
614
|
+
|
|
615
|
+
while (true) {
|
|
616
|
+
const group = await selectPrompt({
|
|
617
|
+
message: `fg-devkit — choose a task (cwd: ${process.cwd()})`,
|
|
618
|
+
choices: groups,
|
|
619
|
+
loop: false,
|
|
620
|
+
})
|
|
621
|
+
if (group === 'exit') return 0
|
|
622
|
+
|
|
623
|
+
if (group === 'commit') {
|
|
624
|
+
const choice = await selectPrompt({
|
|
625
|
+
message: 'Create commit',
|
|
626
|
+
choices: [
|
|
627
|
+
{ name: 'Commit', value: 'commit' },
|
|
628
|
+
{ name: 'Commit vulnerability', value: 'commit-vuln' },
|
|
629
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
630
|
+
],
|
|
631
|
+
default: 'commit',
|
|
632
|
+
loop: false,
|
|
633
|
+
})
|
|
634
|
+
if (choice === 'cancel') continue
|
|
635
|
+
return runSelectedAction(() => (choice === 'commit' ? runCommitizen() : runNode('vuln-commit.mjs')))
|
|
632
636
|
}
|
|
633
|
-
// Close menu readline before spawning interactive child processes.
|
|
634
|
-
rl.close()
|
|
635
|
-
out = runReleaseScript([bumpType])
|
|
636
|
-
} else {
|
|
637
|
-
// Close menu readline before spawning interactive child processes.
|
|
638
|
-
rl.close()
|
|
639
|
-
out = item.run()
|
|
640
|
-
}
|
|
641
637
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
638
|
+
if (group === 'release') {
|
|
639
|
+
const releaseChoice = await selectPrompt({
|
|
640
|
+
message: 'Create release',
|
|
641
|
+
choices: [
|
|
642
|
+
{ name: 'Patch', value: 'patch' },
|
|
643
|
+
{ name: 'Minor', value: 'minor' },
|
|
644
|
+
{ name: 'Major', value: 'major' },
|
|
645
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
646
|
+
],
|
|
647
|
+
default: 'patch',
|
|
648
|
+
loop: false,
|
|
649
|
+
})
|
|
650
|
+
if (releaseChoice === 'cancel') continue
|
|
651
|
+
return runSelectedAction(() => runReleaseScript([releaseChoice]))
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
if (group === 'lint-typecheck') {
|
|
655
|
+
const choice = await selectPrompt({
|
|
656
|
+
message: 'Lint and typecheck',
|
|
657
|
+
choices: [
|
|
658
|
+
{ name: 'Lint and typecheck', value: 'both' },
|
|
659
|
+
{ name: 'Lint', value: 'lint' },
|
|
660
|
+
{ name: 'Typecheck', value: 'typecheck' },
|
|
661
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
662
|
+
],
|
|
663
|
+
default: 'both',
|
|
664
|
+
loop: false,
|
|
665
|
+
})
|
|
666
|
+
if (choice === 'cancel') continue
|
|
667
|
+
if (choice === 'lint') return runSelectedAction(() => runBundledEslint(['.']))
|
|
668
|
+
if (choice === 'typecheck') {
|
|
669
|
+
return runSelectedAction(() => runBundledTypeScript(['--noEmit', '-p', 'tsconfig.json']))
|
|
670
|
+
}
|
|
671
|
+
const lintCode = runBundledEslint(['.'])
|
|
672
|
+
if (lintCode !== 0) return lintCode
|
|
673
|
+
return runSelectedAction(() => runBundledTypeScript(['--noEmit', '-p', 'tsconfig.json']))
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
if (group === 'poeditor') {
|
|
677
|
+
const choice = await selectPrompt({
|
|
678
|
+
message: 'Poeditor',
|
|
679
|
+
choices: [
|
|
680
|
+
{ name: 'Download', value: 'download' },
|
|
681
|
+
{ name: 'Upload', value: 'upload' },
|
|
682
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
683
|
+
],
|
|
684
|
+
default: 'download',
|
|
685
|
+
loop: false,
|
|
686
|
+
})
|
|
687
|
+
if (choice === 'cancel') continue
|
|
688
|
+
return runSelectedAction(() => runNode(choice === 'download' ? 'poeditor-download.mjs' : 'poeditor-upload.mjs'))
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
if (group === 'dependency-policy') {
|
|
692
|
+
const choice = await selectPrompt({
|
|
693
|
+
message: 'Dependecy policy',
|
|
694
|
+
choices: [
|
|
695
|
+
{ name: 'Check', value: 'check' },
|
|
696
|
+
{ name: 'Sync', value: 'sync' },
|
|
697
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
698
|
+
],
|
|
699
|
+
default: 'check',
|
|
700
|
+
loop: false,
|
|
701
|
+
})
|
|
702
|
+
if (choice === 'cancel') continue
|
|
703
|
+
return runSelectedAction(() =>
|
|
704
|
+
runNode(choice === 'check' ? 'check-dependency-policy.mjs' : 'sync-dependency-policy.mjs'),
|
|
705
|
+
)
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
if (group === 'sync-configs') {
|
|
709
|
+
const choice = await selectPrompt({
|
|
710
|
+
message: 'Sync configs',
|
|
711
|
+
choices: [
|
|
712
|
+
{ name: 'vscode', value: 'vscode' },
|
|
713
|
+
{ name: 'eslint', value: 'eslint' },
|
|
714
|
+
{ name: 'prettier', value: 'prettier' },
|
|
715
|
+
{ name: 'tsconfig', value: 'tsconfig' },
|
|
716
|
+
{ name: 'Fallow', value: 'fallow' },
|
|
717
|
+
{ name: 'Cursor', value: 'cursor' },
|
|
718
|
+
{ name: 'All', value: 'all' },
|
|
719
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
720
|
+
],
|
|
721
|
+
default: 'all',
|
|
722
|
+
loop: false,
|
|
723
|
+
})
|
|
724
|
+
if (choice === 'cancel') continue
|
|
725
|
+
return runSelectedAction(() => runSyncConfigTarget(choice))
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
if (group === 'setup') {
|
|
729
|
+
const choice = await selectPrompt({
|
|
730
|
+
message: 'Setup',
|
|
731
|
+
choices: [
|
|
732
|
+
{ name: 'Lefthook', value: 'lefthook' },
|
|
733
|
+
{ name: 'Full consumer setup', value: 'full-consumer-setup' },
|
|
734
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
735
|
+
],
|
|
736
|
+
default: 'lefthook',
|
|
737
|
+
loop: false,
|
|
738
|
+
})
|
|
739
|
+
if (choice === 'cancel') continue
|
|
740
|
+
return runSelectedAction(() => (choice === 'lefthook' ? runSetupLefthook() : runFullConsumerSetup()))
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
if (group === 'fallow-analysis') {
|
|
744
|
+
const choice = await selectPrompt({
|
|
745
|
+
message: 'Fallow analysis',
|
|
746
|
+
choices: [
|
|
747
|
+
{ name: 'dead code', value: 'dead-code' },
|
|
748
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
749
|
+
],
|
|
750
|
+
default: 'dead-code',
|
|
751
|
+
loop: false,
|
|
752
|
+
})
|
|
753
|
+
if (choice === 'cancel') continue
|
|
754
|
+
return runSelectedAction(() => runBundledFallow([choice]))
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
if (group === 'maintainer') {
|
|
758
|
+
const choice = await selectPrompt({
|
|
759
|
+
message: 'Maintainer',
|
|
760
|
+
choices: [
|
|
761
|
+
{ name: 'Show outdated dependency policy packages', value: 'm1' },
|
|
762
|
+
{ name: 'Upgrade dependency policy (interactive)', value: 'm2' },
|
|
763
|
+
{ name: 'Refresh dependency policy from repos (and scaffold/vue package.json)', value: 'm3' },
|
|
764
|
+
{ name: 'Upgrade one policy package, stage, and auto-commit', value: 'm4' },
|
|
765
|
+
{ name: 'Check policy vulnerabilities (audit)', value: 'm5' },
|
|
766
|
+
{ name: 'Check fg-devkit repo vulnerabilities', value: 'm6' },
|
|
767
|
+
{ name: 'Check vulnerabilities across all Vue repos', value: 'm7' },
|
|
768
|
+
{ name: 'Bump fg-devkit in all Vue repos, run sync-deps, and pnpm install', value: 'm8' },
|
|
769
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
770
|
+
],
|
|
771
|
+
default: 'm1',
|
|
772
|
+
loop: false,
|
|
773
|
+
})
|
|
774
|
+
if (choice === 'cancel') continue
|
|
775
|
+
const maintainerCode = maintainerOnly()
|
|
776
|
+
if (maintainerCode !== 0) return maintainerCode
|
|
777
|
+
if (choice === 'm1') return runSelectedAction(() => runNode('policy-outdated.mjs'))
|
|
778
|
+
if (choice === 'm2') return runSelectedAction(() => runNode('policy-upgrade.mjs'))
|
|
779
|
+
if (choice === 'm3') return runSelectedAction(() => runNode('refresh-dependency-policy-from-repos.mjs'))
|
|
780
|
+
if (choice === 'm4') return runSelectedAction(() => runMaintainerPolicyUpgradeAndCommit())
|
|
781
|
+
if (choice === 'm5') return runSelectedAction(() => runNode('policy-vulns.mjs'))
|
|
782
|
+
if (choice === 'm6') return runSelectedAction(() => runMaintainerAuditAll())
|
|
783
|
+
if (choice === 'm7') return runSelectedAction(() => runNode('fleet-vulns.mjs'))
|
|
784
|
+
if (choice === 'm8') return runSelectedAction(() => runNode('fleet-bump-fg-devkit.mjs'))
|
|
785
|
+
return 1
|
|
786
|
+
}
|
|
647
787
|
}
|
|
788
|
+
|
|
648
789
|
return 0
|
|
649
790
|
}
|
|
650
791
|
|
|
@@ -705,6 +846,14 @@ async function main() {
|
|
|
705
846
|
process.exitCode = runBundledTypeScript(rest.length > 0 ? ['--watch', ...rest] : ['--noEmit', '--watch', '-p', 'tsconfig.json'])
|
|
706
847
|
return
|
|
707
848
|
}
|
|
849
|
+
if (sub === 'fallow') {
|
|
850
|
+
process.exitCode = runBundledFallow(rest)
|
|
851
|
+
return
|
|
852
|
+
}
|
|
853
|
+
if (sub === 'dead-code') {
|
|
854
|
+
process.exitCode = runBundledFallow(['dead-code', ...rest])
|
|
855
|
+
return
|
|
856
|
+
}
|
|
708
857
|
const script = DIRECT_COMMANDS[sub]
|
|
709
858
|
if (!script) {
|
|
710
859
|
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,
|
|
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
|
-
|
|
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)
|