fg-devkit 1.12.12 → 1.12.14

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
@@ -132,6 +132,12 @@ Upgrade policy versions interactively:
132
132
  pnpm exec fgd policy-upgrade
133
133
  ```
134
134
 
135
+ Sync dependency policy, run pnpm install, and auto-commit (`chore(repo): sync dependency policy`):
136
+
137
+ ```bash
138
+ pnpm exec fgd sync-deps-commit
139
+ ```
140
+
135
141
  Upgrade one package.json dependency and auto-commit (`dep(package): bump to version`):
136
142
 
137
143
  ```bash
@@ -32,7 +32,7 @@
32
32
  "content-disposition-header": "0.6.0",
33
33
  "date-fns": "4.4.0",
34
34
  "element-plus": "2.14.3",
35
- "fds-vue-core": "8.4.1",
35
+ "fds-vue-core": "8.4.3",
36
36
  "imask": "7.6.1",
37
37
  "leaflet": "1.9.4",
38
38
  "lexical": "0.49.0",
@@ -69,7 +69,7 @@
69
69
  "@tsconfig/node22": "22.0.5",
70
70
  "@types/lodash-es": "4.17.12",
71
71
  "@types/node": "22.16.5",
72
- "@vitest/browser": "3.2.4",
72
+ "@vitest/browser": "4.1.10",
73
73
  "@vue/compiler-dom": "3.5.41",
74
74
  "@vue/eslint-config-standard": "8.0.1",
75
75
  "@vue/server-renderer": "3.5.41",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fg-devkit",
3
- "version": "1.12.12",
3
+ "version": "1.12.14",
4
4
  "description": "Shared configs, scripts, and DX tooling for Vue / TypeScript frontend repos",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -56,6 +56,7 @@
56
56
  "./scripts/audit-override-commit.mjs": "./scripts/audit-override-commit.mjs",
57
57
  "./scripts/check-dependency-policy.mjs": "./scripts/check-dependency-policy.mjs",
58
58
  "./scripts/sync-dependency-policy.mjs": "./scripts/sync-dependency-policy.mjs",
59
+ "./scripts/sync-dependency-policy-commit.mjs": "./scripts/sync-dependency-policy-commit.mjs",
59
60
  "./scripts/resolve-dependency-policy-path.mjs": "./scripts/resolve-dependency-policy-path.mjs",
60
61
  "./scripts/refresh-dependency-policy-from-repos.mjs": "./scripts/refresh-dependency-policy-from-repos.mjs",
61
62
  "./scripts/sync-scaffold-vue-deps.mjs": "./scripts/sync-scaffold-vue-deps.mjs",
@@ -22,7 +22,7 @@
22
22
  "content-disposition-header": "0.6.0",
23
23
  "date-fns": "4.4.0",
24
24
  "dotenv": "16.4.5",
25
- "fds-vue-core": "8.4.1",
25
+ "fds-vue-core": "8.4.3",
26
26
  "pinia": "3.0.4",
27
27
  "qrcode.vue": "3.10.0",
28
28
  "vue": "3.5.41",
@@ -34,7 +34,7 @@
34
34
  "@tanstack/vue-query-devtools": "6.1.38",
35
35
  "@types/node": "22.16.5",
36
36
  "@vitejs/plugin-vue": "6.0.8",
37
- "fg-devkit": "1.12.12",
37
+ "fg-devkit": "1.12.14",
38
38
  "tailwindcss": "4.3.3",
39
39
  "tsx": "4.23.9",
40
40
  "vite": "7.3.5"
@@ -5,6 +5,7 @@
5
5
  * Non-interactive (for scripts and automation):
6
6
  * pnpm exec fg-devkit check-deps [policy-file]
7
7
  * pnpm exec fg-devkit sync-deps [policy-file]
8
+ * pnpm exec fg-devkit sync-deps-commit [policy-file]
8
9
  * pnpm exec fg-devkit policy-outdated [policy-file]
9
10
  * pnpm exec fg-devkit policy-vulns [policy-file]
10
11
  * pnpm exec fg-devkit repo-vulns
@@ -458,6 +459,7 @@ function runSyncConfigTarget(target) {
458
459
  const DIRECT_COMMANDS = {
459
460
  'check-deps': 'check-dependency-policy.mjs',
460
461
  'sync-deps': 'sync-dependency-policy.mjs',
462
+ 'sync-deps-commit': 'sync-dependency-policy-commit.mjs',
461
463
  'policy-outdated': 'policy-outdated.mjs',
462
464
  'policy-vulns': 'policy-vulns.mjs',
463
465
  'repo-vulns': 'repo-vulns.mjs',
@@ -498,6 +500,7 @@ function printHelp() {
498
500
  Commands:
499
501
  check-deps [policy-file] Validate package.json + pins + toolchain against policy
500
502
  sync-deps [policy-file] Align declared versions, packageManager, and Node toolchain to policy
503
+ sync-deps-commit [policy-file] Sync dependency policy, pnpm install, then auto-commit
501
504
  policy-outdated [policy-file] Show outdated policy packages via pnpm outdated
502
505
  policy-vulns [policy-file] Check all policy packages together (including transitives) via pnpm audit
503
506
  repo-vulns Check all repo dependencies for vulnerabilities via pnpm audit
@@ -781,7 +784,7 @@ async function runInteractiveMenu() {
781
784
  message: 'Dependecy policy',
782
785
  choices: [
783
786
  { name: 'Check', value: 'check' },
784
- { name: 'Sync', value: 'sync' },
787
+ { name: 'Sync and auto-commit', value: 'sync-commit' },
785
788
  { name: 'Upgrade one package.json package and auto-commit', value: 'upgrade-commit' },
786
789
  { name: 'Fix one vulnerability override and auto-commit', value: 'audit-override-commit' },
787
790
  { name: 'Cancel', value: 'cancel' },
@@ -791,7 +794,9 @@ async function runInteractiveMenu() {
791
794
  })
792
795
  if (choice === 'cancel') continue
793
796
  if (choice === 'check') return runSelectedAction(() => runNode('check-dependency-policy.mjs'))
794
- if (choice === 'sync') return runSelectedAction(() => runNode('sync-dependency-policy.mjs'))
797
+ if (choice === 'sync-commit') {
798
+ return runSelectedAction(() => runNode('sync-dependency-policy-commit.mjs'))
799
+ }
795
800
  if (choice === 'audit-override-commit') {
796
801
  return runSelectedAction(() => runNode('audit-override-commit.mjs'))
797
802
  }
@@ -87,6 +87,21 @@ function collectPackageVersionChanges(beforePackage, afterPackage) {
87
87
  return changed
88
88
  }
89
89
 
90
+ /** ncu can upgrade package.json `packageManager` (e.g. pnpm@x.y.z); treat as one bump. */
91
+ function collectPackageManagerChange(beforePackage, afterPackage) {
92
+ const before = beforePackage.packageManager
93
+ const after = afterPackage.packageManager
94
+ if (after === undefined || after === before) {
95
+ return null
96
+ }
97
+ const match = typeof after === 'string' ? after.match(/^pnpm@(.+)$/i) : null
98
+ return {
99
+ name: 'pnpm',
100
+ from: before ?? '(missing)',
101
+ to: match ? match[1] : after,
102
+ }
103
+ }
104
+
90
105
  function main() {
91
106
  if (!fs.existsSync(packageJsonPath)) {
92
107
  console.error(`[policy-upgrade-commit] package.json not found at ${packageJsonPath}`)
@@ -115,6 +130,11 @@ function main() {
115
130
  }
116
131
 
117
132
  const changed = collectPackageVersionChanges(beforePackage, afterPackage)
133
+ const packageManagerChange = collectPackageManagerChange(beforePackage, afterPackage)
134
+ if (packageManagerChange) {
135
+ changed.push(packageManagerChange)
136
+ }
137
+
118
138
  if (changed.length === 0) {
119
139
  console.log('[policy-upgrade-commit] No package version changes detected in package.json.')
120
140
  process.exit(0)
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Sync dependency policy into the consumer repo, run pnpm install, then auto-commit.
4
+ *
5
+ * Usage:
6
+ * pnpm exec fg-devkit sync-deps-commit [policy-file]
7
+ */
8
+
9
+ import fs from 'node:fs'
10
+ import path from 'node:path'
11
+ import { fileURLToPath } from 'node:url'
12
+ import { spawnSync } from 'node:child_process'
13
+
14
+ const cwd = process.cwd()
15
+ const scriptDir = path.dirname(fileURLToPath(import.meta.url))
16
+ const syncScriptPath = path.join(scriptDir, 'sync-dependency-policy.mjs')
17
+ const commitMessage = 'chore(repo): sync dependency policy'
18
+
19
+ function runSync(args) {
20
+ const result = spawnSync(process.execPath, [syncScriptPath, ...args], {
21
+ encoding: 'utf8',
22
+ cwd,
23
+ env: process.env,
24
+ })
25
+ if (result.stdout) process.stdout.write(result.stdout)
26
+ if (result.stderr) process.stderr.write(result.stderr)
27
+ if (result.error) {
28
+ console.error('[sync-deps-commit]', result.error.message)
29
+ return { status: 1, stdout: '' }
30
+ }
31
+ return { status: result.status ?? 1, stdout: result.stdout ?? '' }
32
+ }
33
+
34
+ function runPnpm(args) {
35
+ const result = spawnSync('pnpm', args, {
36
+ stdio: 'inherit',
37
+ cwd,
38
+ env: process.env,
39
+ })
40
+ if (result.error) {
41
+ console.error('[sync-deps-commit]', result.error.message)
42
+ return 1
43
+ }
44
+ return result.status ?? 1
45
+ }
46
+
47
+ function runGit(args, options = {}) {
48
+ const result = spawnSync('git', args, {
49
+ stdio: options.capture ? 'pipe' : 'inherit',
50
+ encoding: options.capture ? 'utf8' : undefined,
51
+ cwd,
52
+ env: process.env,
53
+ })
54
+ if (result.error) {
55
+ console.error('[sync-deps-commit]', result.error.message)
56
+ return { status: 1, stdout: '' }
57
+ }
58
+ return { status: result.status ?? 1, stdout: result.stdout ?? '' }
59
+ }
60
+
61
+ function listTrackedFiles() {
62
+ const result = runGit(['ls-files', '-z'], { capture: true })
63
+ if (result.status !== 0) return []
64
+ return result.stdout.split('\0').filter(Boolean)
65
+ }
66
+
67
+ function isSyncRelatedPath(filePath) {
68
+ const base = path.basename(filePath)
69
+ if (
70
+ base === 'package.json' ||
71
+ base === 'pnpm-lock.yaml' ||
72
+ base === 'pnpm-workspace.yaml' ||
73
+ base === '.nvmrc' ||
74
+ base === '.node-version' ||
75
+ base === 'Dockerfile' ||
76
+ base === 'Dockerfile.local' ||
77
+ base === 'Jenkinsfile'
78
+ ) {
79
+ return true
80
+ }
81
+ if (filePath.includes(`${path.sep}.github${path.sep}workflows${path.sep}`) || filePath.startsWith('.github/workflows/')) {
82
+ return /\.(ya?ml)$/i.test(base)
83
+ }
84
+ return base.endsWith('.sh')
85
+ }
86
+
87
+ function fileDiffersFromHead(filePath) {
88
+ const absolutePath = path.join(cwd, filePath)
89
+ if (!fs.existsSync(absolutePath)) return false
90
+
91
+ const tracked = runGit(['ls-files', '--error-unmatch', '--', filePath], { capture: true })
92
+ if (tracked.status !== 0) {
93
+ return true
94
+ }
95
+
96
+ const diff = runGit(['diff', '--quiet', 'HEAD', '--', filePath], { capture: true })
97
+ return diff.status !== 0
98
+ }
99
+
100
+ function stageExistingFiles(files) {
101
+ const existingFiles = files.filter((filePath) => fs.existsSync(path.join(cwd, filePath)))
102
+ if (existingFiles.length === 0) return 0
103
+ return runGit(['add', '--', ...existingFiles]).status
104
+ }
105
+
106
+ function main() {
107
+ const syncResult = runSync(process.argv.slice(2))
108
+ if (syncResult.status !== 0) {
109
+ process.exit(syncResult.status)
110
+ }
111
+
112
+ if (syncResult.stdout.includes('already match dependency policy')) {
113
+ console.log('[sync-deps-commit] Nothing to install or commit.')
114
+ process.exit(0)
115
+ }
116
+
117
+ const installExitCode = runPnpm(['install'])
118
+ if (installExitCode !== 0) {
119
+ process.exit(installExitCode)
120
+ }
121
+
122
+ const candidateFiles = new Set([
123
+ 'package.json',
124
+ 'pnpm-lock.yaml',
125
+ 'pnpm-workspace.yaml',
126
+ '.nvmrc',
127
+ '.node-version',
128
+ 'Dockerfile',
129
+ 'Dockerfile.local',
130
+ 'Jenkinsfile',
131
+ ])
132
+ for (const filePath of listTrackedFiles()) {
133
+ if (isSyncRelatedPath(filePath)) {
134
+ candidateFiles.add(filePath)
135
+ }
136
+ }
137
+
138
+ const filesToStage = [...candidateFiles].filter((filePath) => fileDiffersFromHead(filePath))
139
+ if (filesToStage.length === 0) {
140
+ console.log('[sync-deps-commit] No sync-related changes to commit.')
141
+ process.exit(0)
142
+ }
143
+
144
+ const stageExitCode = stageExistingFiles(filesToStage)
145
+ if (stageExitCode !== 0) {
146
+ process.exit(stageExitCode)
147
+ }
148
+
149
+ console.log(`[sync-deps-commit] Staged ${filesToStage.length} file(s)`)
150
+ console.log(`[sync-deps-commit] Auto-committing: ${commitMessage}`)
151
+ process.exit(runGit(['commit', '-m', commitMessage]).status)
152
+ }
153
+
154
+ main()