11import { execSync } from 'child_process'
2- import * as fs from 'fs'
3- import * as path from 'path'
4- import * as readline from 'readline'
5- import { fileURLToPath } from 'url'
6-
7- const __filename = fileURLToPath ( import . meta. url )
8- const __dirname = path . dirname ( __filename )
2+ import fs from 'fs'
3+ import path from 'path'
4+ import readline from 'readline'
95
106// 配置项
117const COMMIT_MESSAGE = 'chore: update package version'
12- const pluginsPath = path . resolve ( __dirname , '../../' )
13- const pluginProjectPrefix = 'nfp-'
14- const currentPath = path . resolve ( __dirname , '../' )
8+ const PROJECT_PATH = process . cwd ( )
9+ const PLUGINS_PATH = path . resolve ( PROJECT_PATH , '../' )
10+ const PLUGIN_PROJECT_PREFIX = 'nfp-'
1511
1612interface PackageJson {
1713 name : string
@@ -41,7 +37,7 @@ function askQuestion(query: string): Promise<string> {
4137
4238// 读取当前项目的包版本
4339function readCurrentPackageVersions ( packageNames : string [ ] ) : PackageVersions {
44- const packageJsonPath = path . join ( currentPath , 'package.json' )
40+ const packageJsonPath = path . join ( PROJECT_PATH , 'package.json' )
4541 const packageJson : PackageJson = JSON . parse ( fs . readFileSync ( packageJsonPath , 'utf8' ) )
4642
4743 const versions : PackageVersions = { }
@@ -78,12 +74,12 @@ function readCurrentPackageVersions(packageNames: string[]): PackageVersions {
7874function getPluginProjects ( ) : string [ ] {
7975 const pluginsList : string [ ] = [ ]
8076
81- fs . readdirSync ( pluginsPath ) . forEach ( file => {
82- const fullPath = path . join ( pluginsPath , file )
77+ fs . readdirSync ( PLUGINS_PATH ) . forEach ( file => {
78+ const fullPath = path . join ( PLUGINS_PATH , file )
8379 if (
8480 fs . statSync ( fullPath ) . isDirectory ( ) &&
85- file . startsWith ( pluginProjectPrefix ) &&
86- fullPath !== currentPath
81+ file . startsWith ( PLUGIN_PROJECT_PREFIX ) &&
82+ fullPath !== PROJECT_PATH
8783 ) {
8884 pluginsList . push ( fullPath )
8985 }
@@ -159,6 +155,60 @@ function checkAndUpdatePlugin(
159155 return false
160156}
161157
158+ // 检查并删除插件的指定包
159+ function checkAndRemovePackages ( pluginPath : string , packageNames : string [ ] ) : boolean {
160+ const packageJsonPath = path . join ( pluginPath , 'package.json' )
161+
162+ if ( ! fs . existsSync ( packageJsonPath ) ) {
163+ console . warn ( `[WARNING] package.json not found in ${ pluginPath } ` )
164+ return false
165+ }
166+
167+ const packageJson : PackageJson = JSON . parse ( fs . readFileSync ( packageJsonPath , 'utf8' ) )
168+ let hasChanges = false
169+ const removals : string [ ] = [ ]
170+
171+ // 检查并删除dependencies中的包
172+ if ( packageJson . dependencies ) {
173+ packageNames . forEach ( packageName => {
174+ if ( packageJson . dependencies ! [ packageName ] ) {
175+ removals . push ( ` ${ packageName } (from dependencies)` )
176+ delete packageJson . dependencies ! [ packageName ]
177+ hasChanges = true
178+ }
179+ } )
180+ }
181+
182+ // 检查并删除devDependencies中的包
183+ if ( packageJson . devDependencies ) {
184+ packageNames . forEach ( packageName => {
185+ if ( packageJson . devDependencies ! [ packageName ] ) {
186+ removals . push ( ` ${ packageName } (from devDependencies)` )
187+ delete packageJson . devDependencies ! [ packageName ]
188+ hasChanges = true
189+ }
190+ } )
191+ }
192+
193+ if ( hasChanges ) {
194+ console . log ( `[INFO] Removals for ${ path . basename ( pluginPath ) } :` )
195+ removals . forEach ( removal => console . log ( removal ) )
196+
197+ // 更新版本号
198+ const currentVersion = packageJson . version
199+ const newVersion = incrementVersion ( currentVersion )
200+ packageJson . version = newVersion
201+ console . log ( `[INFO] Version: ${ currentVersion } -> ${ newVersion } ` )
202+
203+ // 写入package.json
204+ fs . writeFileSync ( packageJsonPath , JSON . stringify ( packageJson , null , 2 ) + '\n' )
205+
206+ return true
207+ }
208+
209+ return false
210+ }
211+
162212// 版本号递增
163213function incrementVersion ( version : string ) : string {
164214 const parts = version . split ( '.' )
@@ -236,36 +286,64 @@ function gitPush(pluginPath: string): void {
236286
237287// 主函数
238288async function main ( ) {
239- console . log ( '[INFO] Package Update Tool for All Plugins\n' )
289+ console . log ( '[INFO] Package Management Tool for All Plugins\n' )
290+
291+ // 询问用户选择操作模式
292+ const mode = await askQuestion ( 'Choose mode (update/remove): ' )
293+ const isRemoveMode = mode . trim ( ) . toLowerCase ( ) === 'remove'
294+
295+ if ( ! isRemoveMode && mode . trim ( ) . toLowerCase ( ) !== 'update' ) {
296+ console . error ( '[ERROR] Invalid mode. Please choose "update" or "remove"' )
297+ process . exit ( 1 )
298+ }
299+
300+ console . log ( `\n[INFO] Mode: ${ isRemoveMode ? 'REMOVE' : 'UPDATE' } \n` )
240301
241302 // 询问用户输入包名
242303 const input = await askQuestion (
243- 'Enter package names (space-separated, leave empty for all packages): '
304+ isRemoveMode
305+ ? 'Enter package names to remove (space-separated): '
306+ : 'Enter package names (space-separated, leave empty for all packages): '
244307 )
245308 const packageNames = input
246309 . trim ( )
247310 . split ( / \s + / )
248311 . filter ( name => name . length > 0 )
249312
313+ if ( isRemoveMode && packageNames . length === 0 ) {
314+ console . error ( '[ERROR] Please specify at least one package name to remove' )
315+ process . exit ( 1 )
316+ }
317+
250318 console . log (
251319 `\n[INFO] Target packages: ${ packageNames . length === 0 ? 'ALL' : packageNames . join ( ', ' ) } \n`
252320 )
253321
254- // 读取目标版本
255- const targetVersions = readCurrentPackageVersions ( packageNames )
322+ let commitMessage = COMMIT_MESSAGE
256323
257- if ( Object . keys ( targetVersions ) . length === 0 ) {
258- console . error ( '[ERROR] No packages found to update' )
259- process . exit ( 1 )
260- }
324+ if ( isRemoveMode ) {
325+ // 删除模式
326+ commitMessage = 'chore: remove packages'
327+ console . log ( '[INFO] Packages to remove:' )
328+ packageNames . forEach ( name => console . log ( ` ${ name } ` ) )
329+ console . log ( '' )
330+ } else {
331+ // 更新模式
332+ const targetVersions = readCurrentPackageVersions ( packageNames )
261333
262- console . log ( '[INFO] Target versions:' )
263- Object . entries ( targetVersions ) . forEach ( ( [ name , version ] ) => {
264- console . log ( ` ${ name } : ${ version } ` )
265- } )
266- console . log ( '' )
334+ if ( Object . keys ( targetVersions ) . length === 0 ) {
335+ console . error ( '[ERROR] No packages found to update' )
336+ process . exit ( 1 )
337+ }
338+
339+ console . log ( '[INFO] Target versions:' )
340+ Object . entries ( targetVersions ) . forEach ( ( [ name , version ] ) => {
341+ console . log ( ` ${ name } : ${ version } ` )
342+ } )
343+ console . log ( '' )
344+ }
267345
268- console . log ( `[INFO] Commit message: ${ COMMIT_MESSAGE } \n` )
346+ console . log ( `[INFO] Commit message: ${ commitMessage } \n` )
269347
270348 // 获取所有插件项目
271349 const pluginsList = getPluginProjects ( )
@@ -277,25 +355,32 @@ async function main() {
277355 for ( const pluginPath of pluginsList ) {
278356 console . log ( `\n[INFO] Checking ${ path . basename ( pluginPath ) } ...` )
279357
280- const needsUpdate = checkAndUpdatePlugin ( pluginPath , targetVersions )
358+ let needsUpdate = false
359+
360+ if ( isRemoveMode ) {
361+ needsUpdate = checkAndRemovePackages ( pluginPath , packageNames )
362+ } else {
363+ const targetVersions = readCurrentPackageVersions ( packageNames )
364+ needsUpdate = checkAndUpdatePlugin ( pluginPath , targetVersions )
365+ }
281366
282367 if ( needsUpdate ) {
283368 // 读取更新后的版本
284369 const packageJsonPath = path . join ( pluginPath , 'package.json' )
285370 const packageJson : PackageJson = JSON . parse ( fs . readFileSync ( packageJsonPath , 'utf8' ) )
286371 pluginsNeedUpdate . push ( { path : pluginPath , version : packageJson . version } )
287- console . log ( `[SUCCESS] ${ path . basename ( pluginPath ) } marked for update` )
372+ console . log ( `[SUCCESS] ${ path . basename ( pluginPath ) } marked for ${ isRemoveMode ? 'removal' : ' update' } ` )
288373 } else {
289- console . log ( `[INFO] ${ path . basename ( pluginPath ) } is up to date` )
374+ console . log ( `[INFO] ${ path . basename ( pluginPath ) } ${ isRemoveMode ? 'does not have these packages' : ' is up to date' } ` )
290375 }
291376 }
292377
293378 if ( pluginsNeedUpdate . length === 0 ) {
294- console . log ( ' \n[INFO] All plugins are up to date. No updates needed.' )
379+ console . log ( ` \n[INFO] No plugins need ${ isRemoveMode ? 'package removal' : 'updates' } .` )
295380 return
296381 }
297382
298- console . log ( `\n[INFO] ${ pluginsNeedUpdate . length } plugins need updates\n` )
383+ console . log ( `\n[INFO] ${ pluginsNeedUpdate . length } plugins need ${ isRemoveMode ? 'package removal' : ' updates' } \n` )
299384
300385 const pluginsReadyToPush : string [ ] = [ ]
301386
@@ -311,7 +396,7 @@ async function main() {
311396 runBunInstall ( pluginPath )
312397
313398 // 3. Git提交和创建tag
314- gitCommitAndTag ( pluginPath , COMMIT_MESSAGE , version )
399+ gitCommitAndTag ( pluginPath , commitMessage , version )
315400
316401 pluginsReadyToPush . push ( pluginPath )
317402 console . log ( `[SUCCESS] ${ path . basename ( pluginPath ) } prepared successfully` )
0 commit comments