fg-devkit 1.1.0 → 1.2.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.
package/README.md CHANGED
@@ -45,6 +45,13 @@ pnpm exec fgd typecheck
45
45
  pnpm exec fgd typecheck-watch
46
46
  ```
47
47
 
48
+ To remove redundant tooling dependencies from a consuming repo:
49
+
50
+ ```bash
51
+ pnpm exec fgd prune-consumer-deps
52
+ pnpm install
53
+ ```
54
+
48
55
  ## tsconfig in consuming repos
49
56
 
50
57
  Use `fgd sync-project-configs` (or `fgd sync-tooling-configs`) to write the local `tsconfig.json` template from `fg-devkit`.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/tsconfig",
3
- "extends": "@vue/tsconfig/tsconfig.dom.json",
3
+ "extends": "./tsconfig.vue-dom.json",
4
4
  "compilerOptions": {
5
5
  "target": "ES2022",
6
6
  "lib": ["ES2022", "DOM", "DOM.Iterable"],
@@ -16,10 +16,7 @@
16
16
  "allowSyntheticDefaultImports": true,
17
17
  "noUnusedLocals": true,
18
18
  "noUnusedParameters": true,
19
- "preserveSymlinks": false,
20
- "paths": {
21
- "@/*": ["./src/*"]
22
- }
19
+ "preserveSymlinks": false
23
20
  },
24
21
  "vueCompilerOptions": {
25
22
  "strictTemplates": true,
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "compilerOptions": {
4
+ "noEmit": true,
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "resolveJsonModule": true,
8
+ "allowImportingTsExtensions": true,
9
+ "moduleDetection": "force",
10
+ "jsx": "preserve",
11
+ "jsxImportSource": "vue",
12
+ "noImplicitThis": true,
13
+ "strict": true,
14
+ "verbatimModuleSyntax": true,
15
+ "target": "ESNext",
16
+ "useDefineForClassFields": true,
17
+ "esModuleInterop": true,
18
+ "forceConsistentCasingInFileNames": true,
19
+ "libReplacement": false,
20
+ "skipLibCheck": true
21
+ }
22
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "extends": "./tsconfig.vue-base.json",
4
+ "compilerOptions": {
5
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
6
+ "types": []
7
+ }
8
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fg-devkit",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Shared configs, scripts, and DX tooling for Vue / TypeScript frontend repos",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -24,6 +24,7 @@
24
24
  "./scripts/sync-vscode-settings.mjs": "./scripts/sync-vscode-settings.mjs",
25
25
  "./scripts/sync-tooling-configs.mjs": "./scripts/sync-tooling-configs.mjs",
26
26
  "./scripts/sync-project-configs.mjs": "./scripts/sync-project-configs.mjs",
27
+ "./scripts/prune-consumer-deps.mjs": "./scripts/prune-consumer-deps.mjs",
27
28
  "./scripts/check-dependency-policy.mjs": "./scripts/check-dependency-policy.mjs",
28
29
  "./scripts/sync-dependency-policy.mjs": "./scripts/sync-dependency-policy.mjs",
29
30
  "./scripts/resolve-dependency-policy-path.mjs": "./scripts/resolve-dependency-policy-path.mjs",
@@ -48,12 +49,18 @@
48
49
  "typescript",
49
50
  "vue"
50
51
  ],
52
+ "config": {
53
+ "commitizen": {
54
+ "path": "./scripts/cz/cz-adapter.cjs"
55
+ }
56
+ },
51
57
  "dependencies": {
52
58
  "@intlify/eslint-plugin-vue-i18n": "4.3.0",
53
59
  "@typescript-eslint/eslint-plugin": "8.58.2",
54
60
  "@typescript-eslint/parser": "8.58.2",
55
61
  "@vitest/eslint-plugin": "1.6.16",
56
62
  "@vue/eslint-config-prettier": "10.2.0",
63
+ "@vue/tsconfig": "0.9.1",
57
64
  "commitizen": "4.3.1",
58
65
  "eslint": "10.2.1",
59
66
  "eslint-plugin-prettier": "5.5.5",
@@ -4,6 +4,7 @@
4
4
  */
5
5
  module.exports = {
6
6
  prompter(cz, commit) {
7
+ const defaultType = process.env.FG_DEVKIT_CZ_DEFAULT_TYPE;
7
8
  const types = [
8
9
  { value: "feat", name: "feat(scope): Added" },
9
10
  { value: "fix", name: "fix(scope): Fixed" },
@@ -22,6 +23,7 @@ module.exports = {
22
23
  name: "change_type",
23
24
  message: "Select the type of change you are committing",
24
25
  choices: types,
26
+ default: defaultType && types.some((t) => t.value === defaultType) ? defaultType : undefined,
25
27
  },
26
28
  {
27
29
  type: "input",
@@ -8,8 +8,9 @@
8
8
  * pnpm exec fg-devkit sync-project-configs (VS Code + tooling sync; overwrites config files)
9
9
  * pnpm exec fg-devkit sync-tooling-configs (tooling sync only; overwrites config files)
10
10
  * pnpm exec fg-devkit sync-vscode-settings
11
+ * pnpm exec fg-devkit prune-consumer-deps [--dry-run]
11
12
  * pnpm exec fg-devkit create-release [patch|minor|major]
12
- * pnpm exec fg-devkit commit [cz-args...] (Commitizen; uses package.json config.commitizen.path)
13
+ * pnpm exec fg-devkit commit [cz-args...] (Commitizen; uses fg-devkit bundled cz adapter)
13
14
  * pnpm exec fg-devkit commit-vuln (staged package.json version bumps → vuln() commit)
14
15
  * pnpm exec fg-devkit lint [eslint-args...] (run ESLint with fg-devkit bundled packages)
15
16
  * pnpm exec fg-devkit lint-fix [eslint-args...] (same as lint plus --fix)
@@ -102,21 +103,40 @@ async function promptReleaseType(rl) {
102
103
 
103
104
  /**
104
105
  * Run Commitizen from fg-devkit's bundled dependency set.
105
- * Uses the consuming repo's config.commitizen.path when present.
106
+ * Always forces fg-devkit's bundled cz adapter so it stays interactive.
106
107
  */
107
- function runCommitizen(args = []) {
108
- let gitCzBin
108
+ function runCommitizen(args = [], extraEnv = {}) {
109
+ let bootstrapBin
110
+ let commitizenPkgDir
111
+ const adapterPath = path.join(scriptDir, 'cz', 'cz-adapter.cjs')
109
112
  try {
110
- gitCzBin = require.resolve('commitizen/bin/git-cz')
113
+ bootstrapBin = require.resolve('commitizen/dist/cli/git-cz.js')
114
+ commitizenPkgDir = path.dirname(require.resolve('commitizen/package.json'))
111
115
  } catch {
112
116
  console.error('[fg-devkit] Could not resolve bundled commitizen. Reinstall fg-devkit and retry.')
113
117
  return 1
114
118
  }
115
119
 
116
- const r = spawnSync(process.execPath, [gitCzBin, ...args], {
120
+ const launcher = `
121
+ const { bootstrap } = require(${JSON.stringify(bootstrapBin)});
122
+ const argv = ['node', 'git-cz', ...JSON.parse(process.env.FG_DEVKIT_CZ_ARGS || '[]')];
123
+ bootstrap(
124
+ {
125
+ cliPath: ${JSON.stringify(commitizenPkgDir)},
126
+ config: { path: ${JSON.stringify(adapterPath)} },
127
+ },
128
+ argv
129
+ );
130
+ `
131
+
132
+ const r = spawnSync(process.execPath, ['-e', launcher], {
117
133
  stdio: 'inherit',
118
134
  cwd: process.cwd(),
119
- env: process.env,
135
+ env: {
136
+ ...process.env,
137
+ FG_DEVKIT_CZ_ARGS: JSON.stringify(args),
138
+ ...extraEnv,
139
+ },
120
140
  })
121
141
  if (r.error) {
122
142
  console.error('[fg-devkit]', r.error.message)
@@ -200,6 +220,7 @@ const DIRECT_COMMANDS = {
200
220
  'sync-project-configs': 'sync-project-configs.mjs',
201
221
  'sync-tooling-configs': 'sync-tooling-configs.mjs',
202
222
  'sync-vscode-settings': 'sync-vscode-settings.mjs',
223
+ 'prune-consumer-deps': 'prune-consumer-deps.mjs',
203
224
  }
204
225
 
205
226
  function printHelp() {
@@ -212,9 +233,10 @@ Commands:
212
233
  sync-project-configs VS Code + tooling sync (overwrites config files)
213
234
  sync-tooling-configs Tooling sync only (overwrites config files)
214
235
  sync-vscode-settings Copy shared VS Code settings into .vscode/settings.json
236
+ prune-consumer-deps [--dry-run] Remove consumer tooling deps bundled by fg-devkit
215
237
  create-release [bump] Version bump, git push, GitHub release (patch|minor|major; omit = prompt)
216
238
  (alias: createRelease)
217
- commit [args...] Commitizen (git-cz); uses config.commitizen.path in package.json
239
+ commit [args...] Commitizen (git-cz) with fg-devkit bundled adapter
218
240
  commit-vuln Commit staged dependency bumps as vuln() (alias: vuln-commit)
219
241
  lint [eslint-args...] Run ESLint using fg-devkit bundled ESLint stack
220
242
  lint-fix [eslint-args...] Run ESLint with --fix using fg-devkit bundled ESLint stack
@@ -259,7 +281,12 @@ const MENU = [
259
281
  {
260
282
  key: '6',
261
283
  label: 'Commit vulnerability (Commitizen)',
262
- run: () => runNode('vuln-commit.mjs'),
284
+ run: () => runCommitizen([], { FG_DEVKIT_CZ_DEFAULT_TYPE: 'vuln' }),
285
+ },
286
+ {
287
+ key: '7',
288
+ label: 'Remove deps unnecessary deps in package.json',
289
+ run: () => runNode('prune-consumer-deps.mjs'),
263
290
  },
264
291
  ]
265
292
 
@@ -287,27 +314,29 @@ async function runInteractiveMenu() {
287
314
  return 1
288
315
  }
289
316
 
290
- let exitCode = 0
291
- try {
292
- let out
293
- if (item.key === '4') {
294
- const bumpType = await promptReleaseType(rl)
295
- if (!bumpType) {
296
- return 0
297
- }
298
- out = runReleaseScript([bumpType])
299
- } else {
300
- out = item.run()
301
- }
302
- if (typeof out === 'object' && out !== null && typeof out.then === 'function') {
303
- exitCode = await out
304
- } else if (typeof out === 'number') {
305
- exitCode = out
317
+ let out
318
+ if (item.key === '4') {
319
+ const bumpType = await promptReleaseType(rl)
320
+ if (!bumpType) {
321
+ rl.close()
322
+ return 0
306
323
  }
307
- } finally {
324
+ // Close menu readline before spawning interactive child processes.
325
+ rl.close()
326
+ out = runReleaseScript([bumpType])
327
+ } else {
328
+ // Close menu readline before spawning interactive child processes.
308
329
  rl.close()
330
+ out = item.run()
331
+ }
332
+
333
+ if (typeof out === 'object' && out !== null && typeof out.then === 'function') {
334
+ return await out
335
+ }
336
+ if (typeof out === 'number') {
337
+ return out
309
338
  }
310
- return exitCode
339
+ return 0
311
340
  }
312
341
 
313
342
  async function main() {
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Removes tooling dependencies from a consuming repo that are now bundled by fg-devkit.
4
+ *
5
+ * By default this script edits package.json in the current working directory and removes
6
+ * known ESLint/Prettier/TypeScript/Commitizen packages from dependencies/devDependencies.
7
+ *
8
+ * Usage:
9
+ * node node_modules/fg-devkit/scripts/prune-consumer-deps.mjs
10
+ * pnpm exec fg-devkit prune-consumer-deps
11
+ * pnpm exec fg-devkit prune-consumer-deps --dry-run
12
+ */
13
+
14
+ import fs from 'node:fs'
15
+ import path from 'node:path'
16
+
17
+ const BUNDLED_TOOLING_PACKAGES = new Set([
18
+ '@intlify/eslint-plugin-vue-i18n',
19
+ '@typescript-eslint/eslint-plugin',
20
+ '@typescript-eslint/parser',
21
+ '@vitest/eslint-plugin',
22
+ '@vue/eslint-config-prettier',
23
+ '@vue/tsconfig',
24
+ 'commitizen',
25
+ 'eslint',
26
+ 'eslint-plugin-prettier',
27
+ 'eslint-plugin-vue',
28
+ 'prettier',
29
+ 'typescript',
30
+ 'vue-eslint-parser',
31
+ 'vue-tsc',
32
+ ])
33
+
34
+ function readPackageJson(packageJsonPath) {
35
+ if (!fs.existsSync(packageJsonPath)) {
36
+ console.error(`[prune-consumer-deps] No package.json found at ${packageJsonPath}`)
37
+ process.exit(1)
38
+ }
39
+ try {
40
+ return JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
41
+ } catch (err) {
42
+ console.error(`[prune-consumer-deps] Failed to parse package.json: ${err.message}`)
43
+ process.exit(1)
44
+ }
45
+ }
46
+
47
+ function removeFromSection(pkg, sectionName, removed) {
48
+ const section = pkg[sectionName]
49
+ if (!section || typeof section !== 'object') {
50
+ return
51
+ }
52
+ for (const name of Object.keys(section)) {
53
+ if (BUNDLED_TOOLING_PACKAGES.has(name)) {
54
+ removed.push(`${sectionName}.${name}@${section[name]}`)
55
+ delete section[name]
56
+ }
57
+ }
58
+ if (Object.keys(section).length === 0) {
59
+ delete pkg[sectionName]
60
+ }
61
+ }
62
+
63
+ function main() {
64
+ const dryRun = process.argv.includes('--dry-run')
65
+ const projectRoot = process.cwd()
66
+ const packageJsonPath = path.join(projectRoot, 'package.json')
67
+ const pkg = readPackageJson(packageJsonPath)
68
+
69
+ const removed = []
70
+ removeFromSection(pkg, 'dependencies', removed)
71
+ removeFromSection(pkg, 'devDependencies', removed)
72
+
73
+ if (removed.length === 0) {
74
+ console.log('[prune-consumer-deps] No bundled tooling dependencies found to remove.')
75
+ return
76
+ }
77
+
78
+ console.log('[prune-consumer-deps] Removed entries:')
79
+ for (const line of removed) {
80
+ console.log(` - ${line}`)
81
+ }
82
+
83
+ if (dryRun) {
84
+ console.log('\n[prune-consumer-deps] Dry run only; package.json was not modified.')
85
+ return
86
+ }
87
+
88
+ fs.writeFileSync(packageJsonPath, `${JSON.stringify(pkg, null, 2)}\n`, 'utf8')
89
+ console.log('\n[prune-consumer-deps] Updated package.json. Run pnpm install to refresh lockfile.')
90
+ }
91
+
92
+ main()