fg-devkit 1.7.14 → 1.8.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,5 +1,7 @@
1
1
  pre-commit:
2
2
  commands:
3
+ audit:
4
+ run: zsh -lc "pnpm audit"
3
5
  lint-check:
4
6
  run: zsh -lc "node ./node_modules/fg-devkit/scripts/fg-devkit.mjs lint ."
5
7
  typecheck:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fg-devkit",
3
- "version": "1.7.14",
3
+ "version": "1.8.0",
4
4
  "description": "Shared configs, scripts, and DX tooling for Vue / TypeScript frontend repos",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -19,7 +19,6 @@
19
19
  "./vscode-settings.json": "./configs/vscode-settings.json",
20
20
  "./dependency-policy.vue-workspace.json": "./configs/dependency-policy.vue-workspace.json",
21
21
  "./vuln-commit": "./scripts/vuln-commit.mjs",
22
- "./cz-adapter": "./scripts/cz/cz-adapter.cjs",
23
22
  "./cz-config": "./scripts/cz/.cz-config.cjs",
24
23
  "./scripts/sync-peers-from-dev.mjs": "./scripts/sync-peers-from-dev.mjs",
25
24
  "./scripts/sync-vscode-settings.mjs": "./scripts/sync-vscode-settings.mjs",
@@ -47,7 +46,6 @@
47
46
  "./scripts/scaffold-vue.mjs": "./scripts/scaffold-vue.mjs",
48
47
  "./scripts/fg-devkit.mjs": "./scripts/fg-devkit.mjs",
49
48
  "./scripts/release.sh": "./scripts/release.sh",
50
- "./scripts/cz/cz-adapter.cjs": "./scripts/cz/cz-adapter.cjs",
51
49
  "./scripts/cz/.cz-config.cjs": "./scripts/cz/.cz-config.cjs",
52
50
  "./cursor-rules/core-coding-standards.mdc": "./.cursor/rules/core-coding-standards.mdc"
53
51
  },
@@ -69,11 +67,13 @@
69
67
  ],
70
68
  "config": {
71
69
  "commitizen": {
72
- "path": "./scripts/cz/cz-adapter.cjs"
70
+ "path": "node_modules/cz-git",
71
+ "czConfig": "./scripts/cz/.cz-config.cjs"
73
72
  }
74
73
  },
75
74
  "dependencies": {
76
75
  "@inquirer/confirm": "^6.0.12",
76
+ "@inquirer/input": "^5.0.12",
77
77
  "@inquirer/select": "^5.1.4",
78
78
  "@intlify/eslint-plugin-vue-i18n": "4.3.0",
79
79
  "@typescript-eslint/eslint-plugin": "8.58.2",
@@ -82,7 +82,6 @@
82
82
  "@vue/eslint-config-prettier": "10.2.0",
83
83
  "@vue/eslint-config-typescript": "14.7.0",
84
84
  "@vue/tsconfig": "0.9.1",
85
- "commitizen": "4.3.1",
86
85
  "eslint": "10.2.1",
87
86
  "eslint-plugin-prettier": "5.5.5",
88
87
  "eslint-plugin-vue": "10.8.0",
@@ -94,5 +93,9 @@
94
93
  "vue-eslint-parser": "10.4.0",
95
94
  "vue-tsc": "3.2.7"
96
95
  },
96
+ "devDependencies": {
97
+ "cz-git": "^1.13.1",
98
+ "czg": "^1.13.1"
99
+ },
97
100
  "scripts": {}
98
101
  }
@@ -34,7 +34,7 @@
34
34
  "@tanstack/vue-query-devtools": "6.1.28",
35
35
  "@types/node": "22.16.5",
36
36
  "@vitejs/plugin-vue": "6.0.6",
37
- "fg-devkit": "1.7.14",
37
+ "fg-devkit": "1.8.0",
38
38
  "start-server-and-test": "2.1.3",
39
39
  "tailwindcss": "4.2.4",
40
40
  "tsx": "4.21.0",
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Commitizen configuration (legacy path): commit types, prompts, and message limits.
3
- * Used when tooling points commitizen at this file instead of the cz-adapter prompter.
2
+ * cz-git config used by fg-devkit commit flows.
3
+ * Keep this in czrc-compatible shape for `czg --config`.
4
4
  */
5
5
  module.exports = {
6
6
  types: [
@@ -11,16 +11,19 @@ module.exports = {
11
11
  { value: 'chore', name: 'chore(scope): Changed' },
12
12
  { value: 'dep', name: 'dep(scope): Dependencies (single package or batch)' },
13
13
  { value: 'vuln', name: 'vuln(scope): Security dependency update (single package or batch)' },
14
- { value: 'fix(security)', name: 'fix(security): Security' }
14
+ { value: 'fix(security)', name: 'fix(security): Security' },
15
15
  ],
16
16
  allowCustomScopes: true,
17
+ allowEmptyScopes: false,
17
18
  allowBreakingChanges: [],
18
- skipQuestions: ['footer', 'breaking'],
19
- subjectLimit: 120,
19
+ skipQuestions: ['breaking', 'footer', 'issues', 'issuePrefixes'],
20
+ maxSubjectLength: 120,
21
+ breaklineChar: '|',
22
+ useEmoji: false,
20
23
  messages: {
21
24
  type: 'Select the type of change you are committing:',
22
25
  customScope: 'Packages (for dep/vuln) or scope:',
23
26
  subject: 'Commit subject (imperative, no trailing period):',
24
- body: "Optional body (use '|' for newline):"
25
- }
27
+ body: "Optional body (use '|' for newline):",
28
+ },
26
29
  }
@@ -21,7 +21,7 @@
21
21
  * pnpm exec fg-devkit prune-consumer-deps [--dry-run]
22
22
  * pnpm exec fg-devkit full-consumer-setup
23
23
  * pnpm exec fg-devkit create-release [patch|minor|major]
24
- * pnpm exec fg-devkit commit [cz-args...] (Commitizen; uses fg-devkit bundled cz adapter)
24
+ * pnpm exec fg-devkit commit [cz-args...] (czg/cz-git with fg-devkit bundled config)
25
25
  * pnpm exec fg-devkit commit-vuln (staged package.json version bumps → vuln() commit)
26
26
  * pnpm exec fg-devkit lint [eslint-args...] (run ESLint with fg-devkit bundled packages)
27
27
  * pnpm exec fg-devkit lint-fix [eslint-args...] (same as lint plus --fix)
@@ -171,41 +171,132 @@ function runMaintainerAuditAll() {
171
171
  }
172
172
 
173
173
  /**
174
- * Run Commitizen from fg-devkit's bundled dependency set.
175
- * Always forces fg-devkit's bundled cz adapter so it stays interactive.
174
+ * Prompt for a conventional commit message with fg-devkit's legacy question flow,
175
+ * then run `git commit` directly.
176
176
  */
177
- function runCommitizen(args = [], extraEnv = {}) {
178
- let bootstrapBin
179
- let commitizenPkgDir
180
- const adapterPath = path.join(scriptDir, 'cz', 'cz-adapter.cjs')
177
+ async function runCzg(args = [], extraEnv = {}) {
178
+ let selectPrompt
179
+ let inputPrompt
181
180
  try {
182
- bootstrapBin = require.resolve('commitizen/dist/cli/git-cz.js')
183
- commitizenPkgDir = path.dirname(require.resolve('commitizen/package.json'))
181
+ const inquirerSelect = await import('@inquirer/select')
182
+ const inquirerInput = await import('@inquirer/input')
183
+ selectPrompt = inquirerSelect.default
184
+ inputPrompt = inquirerInput.default
184
185
  } catch {
185
- console.error('[fg-devkit] Could not resolve bundled commitizen. Reinstall fg-devkit and retry.')
186
+ console.error('[fg-devkit] Could not resolve @inquirer/select or @inquirer/input. Reinstall fg-devkit and retry.')
186
187
  return 1
187
188
  }
188
189
 
189
- const launcher = `
190
- const { bootstrap } = require(${JSON.stringify(bootstrapBin)});
191
- const argv = ['node', 'git-cz', ...JSON.parse(process.env.FG_DEVKIT_CZ_ARGS || '[]')];
192
- bootstrap(
193
- {
194
- cliPath: ${JSON.stringify(commitizenPkgDir)},
195
- config: { path: ${JSON.stringify(adapterPath)} },
196
- },
197
- argv
198
- );
199
- `
190
+ const types = [
191
+ { value: 'feat', name: 'feat(scope): Added' },
192
+ { value: 'fix', name: 'fix(scope): Fixed' },
193
+ { value: 'perf', name: 'perf(scope): Performance' },
194
+ { value: 'refactor', name: 'refactor(scope): Changed' },
195
+ { value: 'chore', name: 'chore(scope): Changed' },
196
+ { value: 'docs', name: 'docs(scope): Documentation' },
197
+ { value: 'dep', name: 'dep(scope): Dependencies (single package or batch)' },
198
+ { value: 'vuln', name: 'vuln(scope): Security dependency update (single package or batch)' },
199
+ { value: 'fix(security)', name: 'fix(security): Security' },
200
+ ]
201
+
202
+ const defaultType = process.env.FG_DEVKIT_CZ_DEFAULT_TYPE
203
+ const defaultPackages = process.env.FG_DEVKIT_CZ_DEFAULT_PACKAGES
204
+ const defaultDepVersion = process.env.FG_DEVKIT_CZ_DEFAULT_DEP_VERSION
205
+ const defaultDepChangeKind = process.env.FG_DEVKIT_CZ_DEFAULT_DEP_CHANGE_KIND
206
+
207
+ const ask = async (message, cfg = {}) => {
208
+ const value = await inputPrompt({
209
+ message,
210
+ default: cfg.defaultValue,
211
+ validate: cfg.validate,
212
+ })
213
+ return value.trim()
214
+ }
215
+
216
+ const selectedType = await selectPrompt({
217
+ message: 'Select the type of change you are committing',
218
+ choices: types,
219
+ default: defaultType && types.some((t) => t.value === defaultType) ? defaultType : undefined,
220
+ })
221
+
222
+ let scope = ''
223
+ let packages = ''
224
+ let depChangeKind = ''
225
+ let depVersion = ''
226
+ let vulnChangeKind = ''
227
+ let vulnTargetVersion = ''
228
+ let shortcutId = ''
229
+ let subject = ''
230
+ const isDepOrVuln = selectedType === 'dep' || selectedType === 'vuln'
231
+
232
+ if (isDepOrVuln) {
233
+ packages = await ask('Packages:', { defaultValue: selectedType === 'dep' ? defaultPackages : undefined })
234
+ if (!packages && selectedType === 'dep' && defaultPackages) {
235
+ packages = defaultPackages
236
+ }
237
+ } else {
238
+ scope = await ask('Scope:')
239
+ }
240
+
241
+ if (selectedType === 'vuln') {
242
+ vulnChangeKind = await selectPrompt({
243
+ message: 'Vulnerability change type:',
244
+ choices: [
245
+ { value: 'override', name: 'override' },
246
+ { value: 'bump', name: 'bump' },
247
+ ],
248
+ default: 'override',
249
+ })
250
+ while (!vulnTargetVersion) {
251
+ vulnTargetVersion = await ask('Target version/range (e.g. 5.2.2 or >=5.2.2):', {
252
+ validate: (value) => (value?.trim() ? true : 'Provide a target version/range'),
253
+ })
254
+ }
255
+ }
256
+
257
+ if (selectedType === 'dep') {
258
+ depChangeKind = await selectPrompt({
259
+ message: 'Dependency change type:',
260
+ choices: [
261
+ { value: 'new', name: 'new package' },
262
+ { value: 'update', name: 'updated package' },
263
+ { value: 'remove', name: 'removed package' },
264
+ ],
265
+ default:
266
+ defaultDepChangeKind && ['new', 'update', 'remove'].includes(defaultDepChangeKind)
267
+ ? defaultDepChangeKind
268
+ : 'update',
269
+ })
270
+ depVersion = await ask('Version (x.y.z):', {
271
+ defaultValue: defaultDepVersion,
272
+ validate: (value) => (/^\d+\.\d+\.\d+$/.test(value?.trim() ?? '') ? true : 'Use format x.y.z'),
273
+ })
274
+ }
275
+
276
+ if (!isDepOrVuln) {
277
+ shortcutId = await ask('Shortcut ID digits only (optional, e.g. 1234):')
278
+ subject = await ask('Commit subject (imperative, no trailing period):', {
279
+ validate: (value) => (value?.trim() ? true : 'Commit subject is required'),
280
+ })
281
+ }
200
282
 
201
- const r = spawnSync(process.execPath, ['-e', launcher], {
283
+ const body = await ask("Optional body (use '|' for newline):")
284
+
285
+ const scopeValue = isDepOrVuln ? packages : scope
286
+ const needsEmptyParens = isDepOrVuln && !scopeValue
287
+ const scopePart = scopeValue ? `(${scopeValue})` : needsEmptyParens ? '()' : ''
288
+ const shortcutPart = shortcutId ? ` [sc-${shortcutId}]` : ''
289
+ const bodyPart = body ? `\n\n${body.split('|').join('\n')}` : ''
290
+ const depSubject =
291
+ depChangeKind === 'new' ? `add ${depVersion}` : depChangeKind === 'remove' ? `yeet ${depVersion}` : `bump to ${depVersion}`
292
+ const vulnSubject = vulnChangeKind === 'override' ? `override ${vulnTargetVersion}` : `bump to ${vulnTargetVersion}`
293
+ const finalSubject = selectedType === 'dep' ? depSubject : selectedType === 'vuln' ? vulnSubject : subject
294
+ const commitMessage = `${selectedType}${scopePart}: ${finalSubject}${shortcutPart}${bodyPart}`
295
+
296
+ const r = spawnSync('git', ['commit', ...args, '-m', commitMessage], {
202
297
  stdio: 'inherit',
203
298
  cwd: process.cwd(),
204
- env: {
205
- ...process.env,
206
- FG_DEVKIT_CZ_ARGS: JSON.stringify(args),
207
- ...extraEnv,
208
- },
299
+ env: { ...process.env, ...extraEnv },
209
300
  })
210
301
  if (r.error) {
211
302
  console.error('[fg-devkit]', r.error.message)
@@ -404,7 +495,7 @@ Commands:
404
495
  full-consumer-setup Run: step 7 -> scripts -> lefthook -> step 3 -> step 2 -> pnpm install
405
496
  create-release [bump] Version bump, git push, GitHub release (patch|minor|major; omit = prompt)
406
497
  (alias: createRelease)
407
- commit [args...] Commitizen (git-cz) with fg-devkit bundled adapter
498
+ commit [args...] czg/cz-git with fg-devkit bundled config
408
499
  commit-vuln Commit staged dependency bumps as vuln() (alias: vuln-commit)
409
500
  lint [eslint-args...] Run ESLint using fg-devkit bundled ESLint stack
410
501
  lint-fix [eslint-args...] Run ESLint with --fix using fg-devkit bundled ESLint stack
@@ -540,7 +631,7 @@ async function runInteractiveMenu() {
540
631
  loop: false,
541
632
  })
542
633
  if (choice === 'cancel') continue
543
- return runSelectedAction(() => (choice === 'commit' ? runCommitizen() : runNode('vuln-commit.mjs')))
634
+ return runSelectedAction(() => (choice === 'commit' ? runCzg() : runNode('vuln-commit.mjs')))
544
635
  }
545
636
 
546
637
  if (group === 'release') {
@@ -718,7 +809,7 @@ async function main() {
718
809
  return
719
810
  }
720
811
  if (sub === 'commit') {
721
- process.exitCode = runCommitizen(rest)
812
+ process.exitCode = await runCzg(rest)
722
813
  return
723
814
  }
724
815
  if (sub === 'commit-vuln' || sub === 'vuln-commit' || sub === 'commit:vuln') {
@@ -3,7 +3,7 @@
3
3
  * Removes tooling dependencies from a consuming repo that are now bundled by fg-devkit.
4
4
  *
5
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.
6
+ * known ESLint/Prettier/TypeScript/cz-git tooling packages from dependencies/devDependencies.
7
7
  *
8
8
  * Usage:
9
9
  * node node_modules/fg-devkit/scripts/prune-consumer-deps.mjs
@@ -24,6 +24,8 @@ const BUNDLED_TOOLING_PACKAGES = new Set([
24
24
  '@vue/tsconfig',
25
25
  '@rushstack/eslint-patch',
26
26
  'commitizen',
27
+ 'cz-git',
28
+ 'czg',
27
29
  'eslint',
28
30
  'eslint-plugin-prettier',
29
31
  'eslint-plugin-vue',
@@ -1,127 +0,0 @@
1
- /**
2
- * Custom Commitizen adapter: interactive prompts for type, scope, dep/vuln flows, and message body.
3
- * Builds the final conventional commit string and passes it to commit().
4
- */
5
- module.exports = {
6
- prompter(cz, commit) {
7
- const defaultType = process.env.FG_DEVKIT_CZ_DEFAULT_TYPE;
8
- const defaultPackages = process.env.FG_DEVKIT_CZ_DEFAULT_PACKAGES;
9
- const defaultDepVersion = process.env.FG_DEVKIT_CZ_DEFAULT_DEP_VERSION;
10
- const defaultDepChangeKind = process.env.FG_DEVKIT_CZ_DEFAULT_DEP_CHANGE_KIND;
11
- const types = [
12
- { value: "feat", name: "feat(scope): Added" },
13
- { value: "fix", name: "fix(scope): Fixed" },
14
- { value: "perf", name: "perf(scope): Performance" },
15
- { value: "refactor", name: "refactor(scope): Changed" },
16
- { value: "chore", name: "chore(scope): Changed" },
17
- { value: "docs", name: "docs(scope): Documentation" },
18
- { value: "dep", name: "dep(scope): Dependencies (single package or batch)" },
19
- { value: "vuln", name: "vuln(scope): Security dependency update (single package or batch)" },
20
- { value: "fix(security)", name: "fix(security): Security" },
21
- ];
22
-
23
- const questions = [
24
- {
25
- type: "list",
26
- name: "change_type",
27
- message: "Select the type of change you are committing",
28
- choices: types,
29
- default: defaultType && types.some((t) => t.value === defaultType) ? defaultType : undefined,
30
- },
31
- {
32
- type: "input",
33
- name: "scope",
34
- when: (answers) => !["dep", "vuln"].includes(answers.change_type),
35
- message: "Scope:",
36
- },
37
- {
38
- type: "input",
39
- name: "packages",
40
- when: (answers) => ["dep", "vuln"].includes(answers.change_type),
41
- message: "Packages:",
42
- default: defaultType === "dep" && defaultPackages ? defaultPackages : undefined,
43
- },
44
- {
45
- type: "list",
46
- name: "vuln_change_kind",
47
- when: (answers) => answers.change_type === "vuln",
48
- message: "Vulnerability change type:",
49
- choices: [
50
- { value: "override", name: "override" },
51
- { value: "bump", name: "bump" },
52
- ],
53
- },
54
- {
55
- type: "input",
56
- name: "vuln_target_version",
57
- when: (answers) => answers.change_type === "vuln",
58
- message: "Target version/range (e.g. 5.2.2 or >=5.2.2):",
59
- validate: (value) => (value && value.trim() ? true : "Provide a target version/range"),
60
- },
61
- {
62
- type: "list",
63
- name: "dep_change_kind",
64
- when: (answers) => answers.change_type === "dep",
65
- message: "Dependency change type:",
66
- choices: [
67
- { value: "new", name: "new package" },
68
- { value: "update", name: "updated package" },
69
- { value: "remove", name: "removed package" },
70
- ],
71
- default:
72
- defaultType === "dep" && ["new", "update", "remove"].includes(defaultDepChangeKind)
73
- ? defaultDepChangeKind
74
- : "update",
75
- },
76
- {
77
- type: "input",
78
- name: "dep_version",
79
- when: (answers) => answers.change_type === "dep",
80
- message: "Version (x.y.z):",
81
- default: defaultType === "dep" && defaultDepVersion ? defaultDepVersion : undefined,
82
- validate: (value) => (/^\d+\.\d+\.\d+$/.test(value) ? true : "Use format x.y.z"),
83
- },
84
- {
85
- type: "input",
86
- name: "shortcut_id",
87
- when: (answers) => !["dep", "vuln"].includes(answers.change_type),
88
- message: "Shortcut ID digits only (optional, e.g. 1234):",
89
- },
90
- {
91
- type: "input",
92
- name: "message",
93
- when: (answers) => !["dep", "vuln"].includes(answers.change_type),
94
- message: "Commit subject (imperative, no trailing period):",
95
- },
96
- {
97
- type: "input",
98
- name: "body",
99
- message: "Optional body (use '|' for newline):",
100
- },
101
- ];
102
-
103
- cz.prompt(questions).then((answers) => {
104
- const type = answers.change_type;
105
- const scopeValue = ["dep", "vuln"].includes(type) ? answers.packages : answers.scope;
106
- const needsEmptyParens = ["dep", "vuln"].includes(type) && !scopeValue;
107
- const scopePart = scopeValue ? `(${scopeValue})` : needsEmptyParens ? "()" : "";
108
- const shortcutPart = answers.shortcut_id ? ` [sc-${answers.shortcut_id}]` : "";
109
- const bodyPart = answers.body ? `\n\n${answers.body.split("|").join("\n")}` : "";
110
- const depSubject =
111
- answers.dep_change_kind === "new"
112
- ? `add ${answers.dep_version}`
113
- : answers.dep_change_kind === "remove"
114
- ? `yeet ${answers.dep_version}`
115
- : `bump to ${answers.dep_version}`;
116
- const vulnSubject =
117
- type === "vuln"
118
- ? answers.vuln_change_kind === "override"
119
- ? `override ${answers.vuln_target_version}`
120
- : `bump to ${answers.vuln_target_version}`
121
- : "";
122
- const subject = type === "dep" ? depSubject : type === "vuln" ? vulnSubject : answers.message;
123
- const commitMessage = `${type}${scopePart}: ${subject}${shortcutPart}${bodyPart}`;
124
- commit(commitMessage);
125
- });
126
- },
127
- };