1+ #!/usr/bin/env bun
2+
3+ import fs from 'fs' ;
4+ import path from 'path' ;
5+
6+ const rootDir = path . resolve ( import . meta. dir , '..' ) ;
7+ const BACKUP_DIR = path . join ( rootDir , '.package-backups' ) ;
8+
9+ interface PackageJson {
10+ name : string ;
11+ version : string ;
12+ dependencies ?: Record < string , string > ;
13+ devDependencies ?: Record < string , string > ;
14+ peerDependencies ?: Record < string , string > ;
15+ optionalDependencies ?: Record < string , string > ;
16+ }
17+
18+ interface WorkspacePackageInfo {
19+ version : string ;
20+ path : string ;
21+ }
22+
23+ interface RootPackageJson extends PackageJson {
24+ workspaces ?: {
25+ packages ?: string [ ] ;
26+ catalog ?: Record < string , string > ;
27+ } ;
28+ }
29+
30+ function readJSON < T = any > ( filePath : string ) : T {
31+ return JSON . parse ( fs . readFileSync ( filePath , 'utf8' ) ) ;
32+ }
33+
34+ function writeJSON ( filePath : string , data : any ) : void {
35+ fs . writeFileSync ( filePath , JSON . stringify ( data , null , 4 ) + '\n' ) ;
36+ }
37+
38+ function getWorkspacePackages ( ) : Map < string , WorkspacePackageInfo > {
39+ const packages = new Map < string , WorkspacePackageInfo > ( ) ;
40+ const packagesDir = path . join ( rootDir , 'packages' ) ;
41+
42+ const dirs = fs . readdirSync ( packagesDir )
43+ . filter ( dir => fs . statSync ( path . join ( packagesDir , dir ) ) . isDirectory ( ) ) ;
44+
45+ for ( const dir of dirs ) {
46+ const pkgPath = path . join ( packagesDir , dir , 'package.json' ) ;
47+ if ( fs . existsSync ( pkgPath ) ) {
48+ const pkg = readJSON < PackageJson > ( pkgPath ) ;
49+ packages . set ( pkg . name , {
50+ version : pkg . version ,
51+ path : pkgPath
52+ } ) ;
53+ }
54+ }
55+
56+ return packages ;
57+ }
58+
59+ function getCatalogVersions ( ) : Record < string , string > {
60+ const rootPkg = readJSON < RootPackageJson > ( path . join ( rootDir , 'package.json' ) ) ;
61+ return rootPkg . workspaces ?. catalog || { } ;
62+ }
63+
64+ function resolveWorkspaceVersion ( depName : string , workspacePackages : Map < string , WorkspacePackageInfo > ) : string | null {
65+ const pkg = workspacePackages . get ( depName ) ;
66+ return pkg ? pkg . version : null ;
67+ }
68+
69+ function resolveCatalogVersion ( depName : string , catalogVersions : Record < string , string > ) : string | null {
70+ return catalogVersions [ depName ] || null ;
71+ }
72+
73+ function backupPackageJson ( filePath : string ) : void {
74+ if ( ! fs . existsSync ( BACKUP_DIR ) ) {
75+ fs . mkdirSync ( BACKUP_DIR , { recursive : true } ) ;
76+ }
77+
78+ const relativePath = path . relative ( rootDir , filePath ) ;
79+ const backupPath = path . join ( BACKUP_DIR , relativePath ) ;
80+ const backupDir = path . dirname ( backupPath ) ;
81+
82+ if ( ! fs . existsSync ( backupDir ) ) {
83+ fs . mkdirSync ( backupDir , { recursive : true } ) ;
84+ }
85+
86+ fs . copyFileSync ( filePath , backupPath ) ;
87+ }
88+
89+ function processPackageJson (
90+ pkgPath : string ,
91+ workspacePackages : Map < string , WorkspacePackageInfo > ,
92+ catalogVersions : Record < string , string >
93+ ) : boolean {
94+ const pkg = readJSON < PackageJson > ( pkgPath ) ;
95+ let modified = false ;
96+
97+ backupPackageJson ( pkgPath ) ;
98+
99+ const processDeps = ( deps ?: Record < string , string > ) => {
100+ if ( ! deps ) return ;
101+
102+ for ( const [ name , version ] of Object . entries ( deps ) ) {
103+ if ( version === 'workspace:*' ) {
104+ const resolvedVersion = resolveWorkspaceVersion ( name , workspacePackages ) ;
105+ if ( resolvedVersion ) {
106+ deps [ name ] = `^${ resolvedVersion } ` ;
107+ modified = true ;
108+ console . log ( ` ✓ Resolved ${ name } : workspace:* → ^${ resolvedVersion } ` ) ;
109+ } else {
110+ console . warn ( ` ⚠ Could not resolve workspace version for ${ name } ` ) ;
111+ }
112+ } else if ( version === 'catalog:' ) {
113+ const resolvedVersion = resolveCatalogVersion ( name , catalogVersions ) ;
114+ if ( resolvedVersion ) {
115+ deps [ name ] = resolvedVersion ;
116+ modified = true ;
117+ console . log ( ` ✓ Resolved ${ name } : catalog: → ${ resolvedVersion } ` ) ;
118+ } else {
119+ console . warn ( ` ⚠ Could not resolve catalog version for ${ name } ` ) ;
120+ }
121+ }
122+ }
123+ } ;
124+
125+ processDeps ( pkg . dependencies ) ;
126+ processDeps ( pkg . devDependencies ) ;
127+ processDeps ( pkg . peerDependencies ) ;
128+ processDeps ( pkg . optionalDependencies ) ;
129+
130+ if ( modified ) {
131+ writeJSON ( pkgPath , pkg ) ;
132+ console . log ( ` ✅ Updated ${ path . relative ( rootDir , pkgPath ) } ` ) ;
133+ }
134+
135+ return modified ;
136+ }
137+
138+ function main ( ) : void {
139+ console . log ( '🔧 Preparing packages for publishing...\n' ) ;
140+
141+ const workspacePackages = getWorkspacePackages ( ) ;
142+ const catalogVersions = getCatalogVersions ( ) ;
143+
144+ console . log ( `📦 Found ${ workspacePackages . size } workspace packages` ) ;
145+ console . log ( `📚 Found ${ Object . keys ( catalogVersions ) . length } catalog entries\n` ) ;
146+
147+ let packagesModified = 0 ;
148+
149+ for ( const [ name , info ] of workspacePackages ) {
150+ console . log ( `Processing ${ name } ...` ) ;
151+ if ( processPackageJson ( info . path , workspacePackages , catalogVersions ) ) {
152+ packagesModified ++ ;
153+ }
154+ console . log ( '' ) ;
155+ }
156+
157+ console . log ( `✅ Prepared ${ packagesModified } packages for publishing` ) ;
158+ console . log ( `📁 Backups saved to ${ path . relative ( rootDir , BACKUP_DIR ) } ` ) ;
159+ }
160+
161+ try {
162+ main ( ) ;
163+ } catch ( error ) {
164+ console . error ( '❌ Error preparing packages:' , error instanceof Error ? error . message : error ) ;
165+ process . exit ( 1 ) ;
166+ }
0 commit comments