fg-devkit 1.12.6 → 1.12.7

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,6 +1,12 @@
1
1
  {
2
2
  "toolchain": {
3
- "packageManager": "pnpm@11.9.0"
3
+ "packageManager": "pnpm@11.9.0",
4
+ "node": {
5
+ "nvmrc": "22",
6
+ "engines": ">=22.13.0",
7
+ "jenkinsImage": "node22",
8
+ "dockerTag": "22-alpine"
9
+ }
4
10
  },
5
11
  "managedDependencies": {
6
12
  "dependencies": {
@@ -8,13 +14,13 @@
8
14
  "@lexical/html": "0.30.0",
9
15
  "@lexical/list": "0.30.0",
10
16
  "@lexical/rich-text": "0.30.0",
11
- "@piwikpro/vue-piwik-pro": "1.7.0",
12
- "@sentry/browser": "10.60.0",
17
+ "@piwikpro/vue-piwik-pro": "1.7.1",
18
+ "@sentry/browser": "10.68.0",
13
19
  "@sentry/tracing": "7.120.4",
14
- "@sentry/vue": "10.60.0",
15
- "@sentry/wasm": "10.60.0",
16
- "@tailwindcss/postcss": "4.3.1",
17
- "@tanstack/vue-query": "5.101.1",
20
+ "@sentry/vue": "10.68.0",
21
+ "@sentry/wasm": "10.68.0",
22
+ "@tailwindcss/postcss": "4.3.3",
23
+ "@tanstack/vue-query": "5.101.4",
18
24
  "@types/leaflet": "1.9.21",
19
25
  "@unhead/vue": "2.0.5",
20
26
  "@vue-leaflet/vue-leaflet": "0.10.1",
@@ -25,23 +31,23 @@
25
31
  "chart.js": "4.5.1",
26
32
  "content-disposition-header": "0.6.0",
27
33
  "date-fns": "4.4.0",
28
- "element-plus": "2.14.2",
29
- "fds-vue-core": "8.2.1",
34
+ "element-plus": "2.14.3",
35
+ "fds-vue-core": "8.3.0",
30
36
  "imask": "7.6.1",
31
37
  "leaflet": "1.9.4",
32
38
  "lexical": "0.30.0",
33
39
  "lodash": "4.18.1",
34
40
  "lodash-es": "4.18.1",
35
- "markdown-it": "14.2.0",
41
+ "markdown-it": "14.3.0",
36
42
  "pinia": "3.0.4",
37
- "playwright": "1.61.0",
43
+ "playwright": "1.62.0",
38
44
  "quill": "2.0.3",
39
45
  "randexp": "0.5.3",
40
46
  "register-service-worker": "1.7.2",
41
47
  "vega-embed": "7.1.0",
42
48
  "vega-lite": "6.4.3",
43
- "vue-chartjs": "5.3.3",
44
- "vue-i18n": "11.4.6",
49
+ "vue-chartjs": "5.3.4",
50
+ "vue-i18n": "11.4.8",
45
51
  "vue-quilly": "1.1.6",
46
52
  "vue-router": "4.6.3",
47
53
  "vue3-touch-keyboard": "1.3.9",
@@ -53,47 +59,47 @@
53
59
  "@chromatic-com/storybook": "5.2.1",
54
60
  "@eslint/js": "9.39.1",
55
61
  "@intlify/unplugin-vue-i18n": "11.2.4",
56
- "@playwright/test": "1.61.0",
57
- "@storybook/addon-a11y": "10.4.6",
58
- "@storybook/addon-docs": "10.4.6",
59
- "@storybook/addon-vitest": "10.4.6",
60
- "@storybook/vue3": "10.4.6",
61
- "@storybook/vue3-vite": "10.4.6",
62
- "@tanstack/vue-query-devtools": "6.1.35",
62
+ "@playwright/test": "1.62.0",
63
+ "@storybook/addon-a11y": "10.5.4",
64
+ "@storybook/addon-docs": "10.5.4",
65
+ "@storybook/addon-vitest": "10.5.4",
66
+ "@storybook/vue3": "10.5.4",
67
+ "@storybook/vue3-vite": "10.5.4",
68
+ "@tanstack/vue-query-devtools": "6.1.38",
63
69
  "@tsconfig/node22": "22.0.5",
64
70
  "@types/lodash-es": "4.17.12",
65
71
  "@types/node": "22.16.5",
66
72
  "@vitest/browser": "3.2.4",
67
- "@vue/compiler-dom": "3.5.38",
73
+ "@vue/compiler-dom": "3.5.40",
68
74
  "@vue/eslint-config-standard": "8.0.1",
69
- "@vue/server-renderer": "3.5.38",
75
+ "@vue/server-renderer": "3.5.40",
70
76
  "@vue/test-utils": "2.4.11",
71
77
  "@vuepic/vue-datepicker": "6.0.3",
72
78
  "arg": "5.0.2",
73
79
  "babel-eslint": "10.1.0",
74
- "eslint-plugin-storybook": "10.4.6",
80
+ "eslint-plugin-storybook": "10.5.4",
75
81
  "globals": "15.11.0",
76
82
  "jsdom": "26.1.0",
77
- "postcss": "8.5.15",
78
- "sass": "1.101.0",
83
+ "postcss": "8.5.23",
84
+ "sass": "1.102.0",
79
85
  "start-server-and-test": "2.1.3",
80
- "storybook": "10.4.6",
81
- "tsx": "4.22.4",
82
- "vega": "6.2.0",
86
+ "storybook": "10.5.4",
87
+ "tsx": "4.23.1",
88
+ "vega": "6.3.1",
83
89
  "vite-plugin-dts": "4.5.4",
84
- "vite-plugin-vue-devtools": "8.1.3",
85
- "vitest": "4.1.9",
90
+ "vite-plugin-vue-devtools": "8.2.1",
91
+ "vitest": "4.1.10",
86
92
  "yaml": "2.9.0"
87
93
  }
88
94
  },
89
95
  "managedAnywhere": {
90
- "@tailwindcss/vite": "4.3.1",
91
- "@vitejs/plugin-vue": "6.0.7",
96
+ "@tailwindcss/vite": "4.3.3",
97
+ "@vitejs/plugin-vue": "6.0.8",
92
98
  "axios": "1.18.1",
93
99
  "dotenv": "16.4.5",
94
100
  "qrcode.vue": "3.10.0",
95
- "tailwindcss": "4.3.1",
101
+ "tailwindcss": "4.3.3",
96
102
  "vite": "7.3.5",
97
- "vue": "3.5.38"
103
+ "vue": "3.5.40"
98
104
  }
99
105
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fg-devkit",
3
- "version": "1.12.6",
3
+ "version": "1.12.7",
4
4
  "description": "Shared configs, scripts, and DX tooling for Vue / TypeScript frontend repos",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -34,7 +34,23 @@
34
34
  "./scripts/fleet-vulns.mjs": "./scripts/fleet-vulns.mjs",
35
35
  "./scripts/fleet-bump-fg-devkit.mjs": "./scripts/fleet-bump-fg-devkit.mjs",
36
36
  "./scripts/bump-pnpm-toolchain.mjs": "./scripts/bump-pnpm-toolchain.mjs",
37
- "./scripts/fleet-vue-repos.mjs": "./scripts/fleet-vue-repos.mjs",
37
+ "./scripts/bump-node-toolchain.mjs": "./scripts/bump-node-toolchain.mjs",
38
+ "./scripts/sync-node-toolchain.mjs": "./scripts/sync-node-toolchain.mjs",
39
+ "./scripts/node-toolchain-sync.mjs": "./scripts/node-toolchain-sync.mjs",
40
+ "./scripts/fleet-project-repos.mjs": "./scripts/fleet-project-repos.mjs",
41
+ "./scripts/fleet-repo-picker.mjs": "./scripts/fleet-repo-picker.mjs",
42
+ "./scripts/sync-pnpm-toolchain.mjs": "./scripts/sync-pnpm-toolchain.mjs",
43
+ "./scripts/pnpm-toolchain-sync.mjs": "./scripts/pnpm-toolchain-sync.mjs",
44
+ "./scripts/fleet-git-pull.mjs": "./scripts/fleet-git-pull.mjs",
45
+ "./scripts/fleet-git-pull-scoped.mjs": "./scripts/fleet-git-pull-scoped.mjs",
46
+ "./scripts/git-pull-fleet-common.mjs": "./scripts/git-pull-fleet-common.mjs",
47
+ "./scripts/git-fleet-common.mjs": "./scripts/git-fleet-common.mjs",
48
+ "./scripts/git-commit-push-fleet-common.mjs": "./scripts/git-commit-push-fleet-common.mjs",
49
+ "./scripts/fleet-git-commit-push.mjs": "./scripts/fleet-git-commit-push.mjs",
50
+ "./scripts/fleet-git-commit-push-scoped.mjs": "./scripts/fleet-git-commit-push-scoped.mjs",
51
+ "./scripts/git-discard-fleet-common.mjs": "./scripts/git-discard-fleet-common.mjs",
52
+ "./scripts/fleet-git-discard.mjs": "./scripts/fleet-git-discard.mjs",
53
+ "./scripts/fleet-git-discard-scoped.mjs": "./scripts/fleet-git-discard-scoped.mjs",
38
54
  "./scripts/policy-upgrade.mjs": "./scripts/policy-upgrade.mjs",
39
55
  "./scripts/policy-upgrade-commit.mjs": "./scripts/policy-upgrade-commit.mjs",
40
56
  "./scripts/audit-override-commit.mjs": "./scripts/audit-override-commit.mjs",
@@ -70,7 +86,7 @@
70
86
  ".cursor/rules/core-coding-standards.mdc"
71
87
  ],
72
88
  "engines": {
73
- "node": "^20.19.0 || >=22.12.0"
89
+ "node": ">=22.13.0"
74
90
  },
75
91
  "keywords": [
76
92
  "eslint",
@@ -85,6 +101,7 @@
85
101
  }
86
102
  },
87
103
  "dependencies": {
104
+ "@inquirer/checkbox": "4.3.2",
88
105
  "@inquirer/confirm": "6.1.1",
89
106
  "@inquirer/input": "5.1.2",
90
107
  "@inquirer/select": "5.2.1",
@@ -109,8 +126,7 @@
109
126
  "vue-tsc": "3.3.5"
110
127
  },
111
128
  "devDependencies": {
112
- "cz-git": "^1.13.1",
113
- "czg": "^1.13.1"
114
- },
115
- "scripts": {}
129
+ "cz-git": "1.13.1",
130
+ "czg": "1.13.1"
131
+ }
116
132
  }
@@ -15,30 +15,33 @@
15
15
  "poeditor:upload": "pnpm exec fg-devkit poeditor-upload"
16
16
  },
17
17
  "dependencies": {
18
- "@tailwindcss/postcss": "4.3.1",
19
- "@tailwindcss/vite": "4.3.1",
20
- "@tanstack/vue-query": "5.101.1",
18
+ "@tailwindcss/postcss": "4.3.3",
19
+ "@tailwindcss/vite": "4.3.3",
20
+ "@tanstack/vue-query": "5.101.4",
21
21
  "axios": "1.18.1",
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.2.1",
25
+ "fds-vue-core": "8.3.0",
26
26
  "pinia": "3.0.4",
27
27
  "qrcode.vue": "3.10.0",
28
- "vue": "3.5.38",
29
- "vue-i18n": "11.4.6",
28
+ "vue": "3.5.40",
29
+ "vue-i18n": "11.4.8",
30
30
  "vue-router": "4.6.3"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@intlify/unplugin-vue-i18n": "11.2.4",
34
- "@tanstack/vue-query-devtools": "6.1.35",
34
+ "@tanstack/vue-query-devtools": "6.1.38",
35
35
  "@types/node": "22.16.5",
36
- "@vitejs/plugin-vue": "6.0.7",
37
- "fg-devkit": "1.12.6",
36
+ "@vitejs/plugin-vue": "6.0.8",
37
+ "fg-devkit": "1.12.7",
38
38
  "start-server-and-test": "2.1.3",
39
- "tailwindcss": "4.3.1",
40
- "tsx": "4.22.4",
39
+ "tailwindcss": "4.3.3",
40
+ "tsx": "4.23.1",
41
41
  "vite": "7.3.5"
42
42
  },
43
- "packageManager": "pnpm@11.9.0"
43
+ "packageManager": "pnpm@11.9.0",
44
+ "engines": {
45
+ "node": ">=22.13.0"
46
+ }
44
47
  }
@@ -0,0 +1,260 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Maintainer: sync Node toolchain across fg-devkit and fleet repositories.
4
+ *
5
+ * Steps in fg-devkit:
6
+ * 1. Resolve node policy from CLI or fg-devkit .nvmrc + package.json engines
7
+ * 2. Write policy.toolchain.node to dependency policy file
8
+ * 3. Sync fg-devkit repo (scaffold Dockerfile.local included via repo walk)
9
+ *
10
+ * Steps per project under projects-root (unless --skip-fleet):
11
+ * 1. sync-node-toolchain against this checkout's policy file
12
+ *
13
+ * Usage (from fg-devkit repository root):
14
+ * pnpm exec fg-devkit bump-node-toolchain [nvmrc-version] [projects-root] [options]
15
+ *
16
+ * Options:
17
+ * --dry-run Print planned changes without writing files
18
+ * --skip-fleet Only update fg-devkit and policy file
19
+ * --engines=RANGE Override engines range (e.g. >=22.13.0); omit to keep policy/fg-devkit value
20
+ * --no-engines Do not set engines.node in package.json files
21
+ * --pick Interactive checkbox to choose fleet repositories (default when TTY)
22
+ * --all Run on all fleet repositories without prompting
23
+ * --only=a,b Run only on matching repos (basename or path under projects root)
24
+ *
25
+ * Examples:
26
+ * pnpm exec fg-devkit bump-node-toolchain
27
+ * pnpm exec fg-devkit bump-node-toolchain 22
28
+ * pnpm exec fg-devkit bump-node-toolchain --dry-run
29
+ * pnpm exec fg-devkit bump-node-toolchain --skip-fleet
30
+ */
31
+
32
+ import fs from 'node:fs'
33
+ import path from 'node:path'
34
+ import { fileURLToPath } from 'node:url'
35
+
36
+ import {
37
+ DEFAULT_NODE_TOOLCHAIN_EXCLUDE,
38
+ collectFleetProjectRepos,
39
+ } from './fleet-project-repos.mjs'
40
+ import { parseFleetSelectionFlags, resolveFleetRepos } from './fleet-repo-picker.mjs'
41
+ import {
42
+ formatNodeNvmrc,
43
+ readFgDevkitNodePolicy,
44
+ resolveExpectedNodePolicy,
45
+ } from './dependency-policy-toolchain.mjs'
46
+ import { syncNodeToolchainInRepo } from './node-toolchain-sync.mjs'
47
+ import { resolveDependencyPolicyPath } from './resolve-dependency-policy-path.mjs'
48
+
49
+ const scriptDir = path.dirname(fileURLToPath(import.meta.url))
50
+ const fgDevkitRoot = path.resolve(scriptDir, '..')
51
+ const fgDevkitPkgPath = path.join(fgDevkitRoot, 'package.json')
52
+ const policyPath = resolveDependencyPolicyPath(scriptDir, fgDevkitRoot, [])
53
+
54
+ const cliArgs = process.argv.slice(2)
55
+ const dryRun = cliArgs.includes('--dry-run')
56
+ const skipFleet = cliArgs.includes('--skip-fleet')
57
+ const noEngines = cliArgs.includes('--no-engines')
58
+ const enginesArg = cliArgs.find((a) => a.startsWith('--engines='))?.slice('--engines='.length)
59
+ const { pick, all, only, filteredArgs: positionalArgs } = parseFleetSelectionFlags(cliArgs)
60
+
61
+ function readJson(jsonPath) {
62
+ return JSON.parse(fs.readFileSync(jsonPath, 'utf8'))
63
+ }
64
+
65
+ function assertFgDevkitMaintainerContext() {
66
+ if (path.resolve(process.cwd()) !== fgDevkitRoot) {
67
+ console.error('[bump-node-toolchain] Run from the fg-devkit repository root.')
68
+ process.exit(1)
69
+ }
70
+ try {
71
+ const pkg = readJson(fgDevkitPkgPath)
72
+ if (pkg?.name !== 'fg-devkit') {
73
+ console.error('[bump-node-toolchain] package.json name must be fg-devkit.')
74
+ process.exit(1)
75
+ }
76
+ } catch {
77
+ console.error('[bump-node-toolchain] Could not read fg-devkit package.json.')
78
+ process.exit(1)
79
+ }
80
+ }
81
+
82
+ function runStep(label, fn) {
83
+ console.log(`\n[bump-node-toolchain] ${label}`)
84
+ return fn()
85
+ }
86
+
87
+ function updatePolicyNodeToolchain(nvmrcArg) {
88
+ const policy = readJson(policyPath)
89
+ const fromFgDevkit = readFgDevkitNodePolicy(fgDevkitRoot)
90
+ if (!fromFgDevkit && !nvmrcArg) {
91
+ console.error('[bump-node-toolchain] No .nvmrc in fg-devkit and no version argument provided.')
92
+ process.exit(1)
93
+ }
94
+
95
+ const nvmrc = formatNodeNvmrc(nvmrcArg ?? fromFgDevkit.nvmrc)
96
+ const engines = noEngines
97
+ ? null
98
+ : enginesArg ?? fromFgDevkit?.engines ?? policy.toolchain?.node?.engines ?? `>=${nvmrc}.0`
99
+
100
+ const nextNode = {
101
+ nvmrc,
102
+ ...(engines ? { engines } : {}),
103
+ jenkinsImage: `node${nvmrc.split('.')[0]}`,
104
+ dockerTag: `${nvmrc.split('.')[0]}-alpine`,
105
+ }
106
+
107
+ const next = {
108
+ ...policy,
109
+ toolchain: {
110
+ ...(policy.toolchain ?? {}),
111
+ node: nextNode,
112
+ },
113
+ }
114
+
115
+ const current = policy.toolchain?.node
116
+ const changed =
117
+ !current ||
118
+ current.nvmrc !== nextNode.nvmrc ||
119
+ current.engines !== nextNode.engines ||
120
+ current.jenkinsImage !== nextNode.jenkinsImage ||
121
+ current.dockerTag !== nextNode.dockerTag
122
+
123
+ if (changed) {
124
+ if (dryRun) {
125
+ console.log(`[bump-node-toolchain] DRY RUN policy toolchain.node -> ${JSON.stringify(nextNode)}`)
126
+ } else {
127
+ fs.writeFileSync(policyPath, `${JSON.stringify(next, null, 2)}\n`)
128
+ console.log(`[bump-node-toolchain] Updated policy toolchain.node -> ${JSON.stringify(nextNode)}`)
129
+ }
130
+ } else {
131
+ console.log(`[bump-node-toolchain] Policy toolchain.node already ${JSON.stringify(nextNode)}`)
132
+ }
133
+
134
+ return next
135
+ }
136
+
137
+ function syncFgDevkitFiles(policy) {
138
+ if (dryRun) {
139
+ const changes = syncNodeToolchainInRepo(fgDevkitRoot, policy, { dryRun: true, fgDevkitRoot })
140
+ for (const change of changes) {
141
+ console.log(`[bump-node-toolchain] DRY RUN fg-devkit: ${change}`)
142
+ }
143
+ return
144
+ }
145
+
146
+ const nvmrc = resolveExpectedNodePolicy(policy, fgDevkitRoot)?.nvmrc
147
+ if (nvmrc) {
148
+ fs.writeFileSync(path.join(fgDevkitRoot, '.nvmrc'), `${nvmrc}\n`)
149
+ }
150
+
151
+ const pkg = readJson(fgDevkitPkgPath)
152
+ const engines = resolveExpectedNodePolicy(policy, fgDevkitRoot)?.engines
153
+ if (engines) {
154
+ pkg.engines = { ...(pkg.engines ?? {}), node: engines }
155
+ fs.writeFileSync(fgDevkitPkgPath, `${JSON.stringify(pkg, null, 2)}\n`)
156
+ }
157
+
158
+ const changes = syncNodeToolchainInRepo(fgDevkitRoot, policy, { fgDevkitRoot })
159
+ for (const change of changes) {
160
+ console.log(`[bump-node-toolchain] fg-devkit: ${change}`)
161
+ }
162
+ }
163
+
164
+ function syncFleetRepo(repoDir, projectsRoot, policy) {
165
+ const label = path.relative(projectsRoot, repoDir).split(path.sep).join('/') || path.basename(repoDir)
166
+ if (dryRun) {
167
+ const changes = syncNodeToolchainInRepo(repoDir, policy, { dryRun: true, fgDevkitRoot })
168
+ if (changes.length === 0) {
169
+ console.log(`[bump-node-toolchain] DRY RUN ${label}: already matches`)
170
+ return 0
171
+ }
172
+ for (const change of changes) {
173
+ console.log(`[bump-node-toolchain] DRY RUN ${label}: ${change}`)
174
+ }
175
+ return 0
176
+ }
177
+
178
+ const changes = syncNodeToolchainInRepo(repoDir, policy, { fgDevkitRoot })
179
+ if (changes.length === 0) {
180
+ console.log(`[bump-node-toolchain] OK ${label} (no changes)`)
181
+ return 0
182
+ }
183
+ for (const change of changes) {
184
+ console.log(`[bump-node-toolchain] ${label}: ${change}`)
185
+ }
186
+ console.log(`[bump-node-toolchain] OK ${label}`)
187
+ return 0
188
+ }
189
+
190
+ async function main() {
191
+ assertFgDevkitMaintainerContext()
192
+
193
+ const nvmrcArg = positionalArgs.find((a) => /^\d/.test(a))
194
+ const projectsRootArg = positionalArgs.find((a) => a !== nvmrcArg)
195
+ const projectsRoot = projectsRootArg
196
+ ? path.resolve(process.cwd(), projectsRootArg)
197
+ : path.resolve(fgDevkitRoot, '..')
198
+
199
+ const policy = runStep('Update dependency policy', () => updatePolicyNodeToolchain(nvmrcArg))
200
+ const nodePolicy = resolveExpectedNodePolicy(policy, fgDevkitRoot)
201
+ console.log(`[bump-node-toolchain] target=${JSON.stringify(nodePolicy)}`)
202
+ console.log(`[bump-node-toolchain] policy=${policyPath}`)
203
+
204
+ runStep('Sync fg-devkit', () => syncFgDevkitFiles(policy))
205
+
206
+ if (skipFleet) {
207
+ console.log('\n[bump-node-toolchain] Done (--skip-fleet). Commit fg-devkit and policy changes.')
208
+ process.exit(0)
209
+ }
210
+
211
+ if (!fs.existsSync(projectsRoot)) {
212
+ console.error(`[bump-node-toolchain] projects root not found: ${projectsRoot}`)
213
+ process.exit(1)
214
+ }
215
+
216
+ const allRepos = collectFleetProjectRepos(projectsRoot, { exclude: DEFAULT_NODE_TOOLCHAIN_EXCLUDE })
217
+ if (allRepos.length === 0) {
218
+ console.log(`[bump-node-toolchain] No project repositories under ${projectsRoot}`)
219
+ process.exit(0)
220
+ }
221
+
222
+ const repos = await resolveFleetRepos(allRepos, projectsRoot, {
223
+ pick,
224
+ only,
225
+ all,
226
+ message: 'Select projects to sync Node toolchain',
227
+ })
228
+
229
+ console.log(`\n[bump-node-toolchain] Fleet repositories=${repos.length}/${allRepos.length}`)
230
+ console.log(`[bump-node-toolchain] projectsRoot=${projectsRoot}`)
231
+
232
+ let failures = 0
233
+ for (const repoDir of repos) {
234
+ const label = path.relative(projectsRoot, repoDir).split(path.sep).join('/') || path.basename(repoDir)
235
+ console.log(`\n[bump-node-toolchain] Fleet: ${label}`)
236
+ try {
237
+ const code = syncFleetRepo(repoDir, projectsRoot, policy)
238
+ if (code !== 0) {
239
+ failures += 1
240
+ }
241
+ } catch (err) {
242
+ console.error(`[bump-node-toolchain] FAIL ${label}:`, err)
243
+ failures += 1
244
+ }
245
+ }
246
+
247
+ console.log(`\n[bump-node-toolchain] Done: fleet ok=${repos.length - failures}, failed=${failures}`)
248
+ if (failures > 0) {
249
+ process.exit(1)
250
+ }
251
+
252
+ if (!dryRun) {
253
+ console.log('[bump-node-toolchain] Commit changes in fg-devkit, policy, and each updated repo.')
254
+ }
255
+ }
256
+
257
+ main().catch((err) => {
258
+ console.error('[bump-node-toolchain]', err)
259
+ process.exit(1)
260
+ })
@@ -8,10 +8,9 @@
8
8
  * 3. Sync dependency policy toolchain, scaffold/vue, and Dockerfile.local
9
9
  * 4. corepack prepare + pnpm install
10
10
  *
11
- * Steps per Vue consumer repo under projects-root (unless --skip-fleet):
12
- * 1. sync-deps against this checkout's policy file (works before fg-devkit is published)
13
- * 2. corepack prepare + pnpm install
14
- * 3. check-deps against the same policy file
11
+ * Steps per pnpm repo under projects-root (unless --skip-fleet):
12
+ * Vue + fg-devkit consumers: sync-deps, corepack prepare, pnpm install, check-deps
13
+ * Other pnpm repos: sync packageManager (+ Dockerfile pnpm pins), corepack prepare, pnpm install
15
14
  *
16
15
  * Usage (from fg-devkit repository root):
17
16
  * pnpm exec fg-devkit bump-pnpm-toolchain [version] [projects-root] [options]
@@ -20,6 +19,9 @@
20
19
  * --dry-run Print planned steps without changing files or running install
21
20
  * --skip-fleet Only update fg-devkit (policy, scaffold, local install)
22
21
  * --skip-install Skip corepack prepare and pnpm install
22
+ * --pick Interactive checkbox to choose fleet repositories (default when TTY)
23
+ * --all Run on all fleet repositories without prompting
24
+ * --only=a,b Run only on matching repos (basename or path under projects root)
23
25
  *
24
26
  * Examples:
25
27
  * pnpm exec fg-devkit bump-pnpm-toolchain
@@ -34,7 +36,12 @@ import { spawnSync } from 'node:child_process'
34
36
  import { fileURLToPath } from 'node:url'
35
37
 
36
38
  import { formatPnpmPackageManager } from './dependency-policy-toolchain.mjs'
37
- import { collectFleetVueRepos } from './fleet-vue-repos.mjs'
39
+ import { collectFleetPnpmRepos } from './fleet-project-repos.mjs'
40
+ import { parseFleetSelectionFlags, resolveFleetRepos } from './fleet-repo-picker.mjs'
41
+ import {
42
+ isVueFgDevkitConsumerRepo,
43
+ syncPnpmToolchainInRepo,
44
+ } from './pnpm-toolchain-sync.mjs'
38
45
  import { resolveDependencyPolicyPath } from './resolve-dependency-policy-path.mjs'
39
46
  import { syncScaffoldVueDepsFromPolicy } from './sync-scaffold-vue-deps.mjs'
40
47
 
@@ -47,7 +54,8 @@ const cliArgs = process.argv.slice(2)
47
54
  const dryRun = cliArgs.includes('--dry-run')
48
55
  const skipFleet = cliArgs.includes('--skip-fleet')
49
56
  const skipInstall = cliArgs.includes('--skip-install')
50
- const positionalArgs = cliArgs.filter((a) => !a.startsWith('-'))
57
+ const { pick, all, only, filteredArgs: positionalArgs } = parseFleetSelectionFlags(cliArgs)
58
+ let projectsRoot = path.resolve(fgDevkitRoot, '..')
51
59
 
52
60
  function readJson(jsonPath) {
53
61
  return JSON.parse(fs.readFileSync(jsonPath, 'utf8'))
@@ -152,50 +160,69 @@ function updateFgDevkitPackageManager(packageManager) {
152
160
  }
153
161
 
154
162
  function syncFleetRepo(repoDir, repoName, packageManager) {
163
+ const policyManaged = isVueFgDevkitConsumerRepo(repoDir)
164
+ const relDir = path.relative(projectsRoot, repoDir)
165
+ const label = relDir === '' || relDir === '.' ? repoName : relDir
166
+
155
167
  if (dryRun) {
156
- console.log(`[bump-pnpm-toolchain] DRY RUN ${repoName}: sync-deps ${policyPath}`)
157
- console.log(`[bump-pnpm-toolchain] DRY RUN ${repoName}: corepack prepare ${packageManager}`)
158
- console.log(`[bump-pnpm-toolchain] DRY RUN ${repoName}: pnpm install`)
159
- console.log(`[bump-pnpm-toolchain] DRY RUN ${repoName}: check-deps ${policyPath}`)
168
+ if (policyManaged) {
169
+ console.log(`[bump-pnpm-toolchain] DRY RUN ${label}: sync-deps ${policyPath}`)
170
+ } else {
171
+ console.log(`[bump-pnpm-toolchain] DRY RUN ${label}: sync packageManager -> ${packageManager}`)
172
+ }
173
+ console.log(`[bump-pnpm-toolchain] DRY RUN ${label}: corepack prepare ${packageManager}`)
174
+ console.log(`[bump-pnpm-toolchain] DRY RUN ${label}: pnpm install`)
175
+ if (policyManaged) {
176
+ console.log(`[bump-pnpm-toolchain] DRY RUN ${label}: check-deps ${policyPath}`)
177
+ }
160
178
  return 0
161
179
  }
162
180
 
163
- const syncCode = runNodeScript('sync-dependency-policy.mjs', [policyPath], repoDir)
164
- if (syncCode !== 0) {
165
- console.error(`[bump-pnpm-toolchain] FAIL ${repoName}: sync-deps exited with code ${syncCode}`)
166
- return syncCode
181
+ if (policyManaged) {
182
+ const syncCode = runNodeScript('sync-dependency-policy.mjs', [policyPath], repoDir)
183
+ if (syncCode !== 0) {
184
+ console.error(`[bump-pnpm-toolchain] FAIL ${label}: sync-deps exited with code ${syncCode}`)
185
+ return syncCode
186
+ }
187
+ } else {
188
+ const changes = syncPnpmToolchainInRepo(repoDir, packageManager)
189
+ for (const change of changes) {
190
+ console.log(`[bump-pnpm-toolchain] ${label}: ${change}`)
191
+ }
167
192
  }
168
193
 
169
194
  if (!skipInstall) {
170
195
  const corepackCode = runCorepackPrepare(packageManager, repoDir)
171
196
  if (corepackCode !== 0) {
172
- console.error(`[bump-pnpm-toolchain] FAIL ${repoName}: corepack prepare exited with code ${corepackCode}`)
197
+ console.error(`[bump-pnpm-toolchain] FAIL ${label}: corepack prepare exited with code ${corepackCode}`)
173
198
  return corepackCode
174
199
  }
175
200
 
176
201
  const installCode = runPnpmInstall(repoDir)
177
202
  if (installCode !== 0) {
178
- console.error(`[bump-pnpm-toolchain] FAIL ${repoName}: pnpm install exited with code ${installCode}`)
203
+ console.error(`[bump-pnpm-toolchain] FAIL ${label}: pnpm install exited with code ${installCode}`)
179
204
  return installCode
180
205
  }
181
206
  }
182
207
 
183
- const checkCode = runNodeScript('check-dependency-policy.mjs', [policyPath], repoDir)
184
- if (checkCode !== 0) {
185
- console.error(`[bump-pnpm-toolchain] FAIL ${repoName}: check-deps exited with code ${checkCode}`)
186
- return checkCode
208
+ if (policyManaged) {
209
+ const checkCode = runNodeScript('check-dependency-policy.mjs', [policyPath], repoDir)
210
+ if (checkCode !== 0) {
211
+ console.error(`[bump-pnpm-toolchain] FAIL ${label}: check-deps exited with code ${checkCode}`)
212
+ return checkCode
213
+ }
187
214
  }
188
215
 
189
- console.log(`[bump-pnpm-toolchain] OK ${repoName}`)
216
+ console.log(`[bump-pnpm-toolchain] OK ${label}`)
190
217
  return 0
191
218
  }
192
219
 
193
- function main() {
220
+ async function main() {
194
221
  assertFgDevkitMaintainerContext()
195
222
 
196
223
  const versionArg = positionalArgs.find((a) => /^(pnpm@)?\d/.test(a))
197
224
  const projectsRootArg = positionalArgs.find((a) => a !== versionArg)
198
- const projectsRoot = projectsRootArg
225
+ projectsRoot = projectsRootArg
199
226
  ? path.resolve(process.cwd(), projectsRootArg)
200
227
  : path.resolve(fgDevkitRoot, '..')
201
228
 
@@ -248,13 +275,20 @@ function main() {
248
275
  process.exit(1)
249
276
  }
250
277
 
251
- const repos = collectFleetVueRepos(projectsRoot)
252
- if (repos.length === 0) {
253
- console.log(`[bump-pnpm-toolchain] No Vue repositories with fg-devkit under ${projectsRoot}`)
278
+ const allRepos = collectFleetPnpmRepos(projectsRoot)
279
+ if (allRepos.length === 0) {
280
+ console.log(`[bump-pnpm-toolchain] No pnpm repositories under ${projectsRoot}`)
254
281
  process.exit(0)
255
282
  }
256
283
 
257
- console.log(`\n[bump-pnpm-toolchain] Fleet repositories=${repos.length}`)
284
+ const repos = await resolveFleetRepos(allRepos, projectsRoot, {
285
+ pick,
286
+ only,
287
+ all,
288
+ message: 'Select pnpm repositories to update',
289
+ })
290
+
291
+ console.log(`\n[bump-pnpm-toolchain] Fleet repositories=${repos.length}/${allRepos.length}`)
258
292
 
259
293
  let failures = 0
260
294
  for (const repoDir of repos) {
@@ -278,4 +312,7 @@ function main() {
278
312
  }
279
313
  }
280
314
 
281
- main()
315
+ main().catch((err) => {
316
+ console.error('[bump-pnpm-toolchain]', err)
317
+ process.exit(1)
318
+ })