@@ -38,9 +38,11 @@ async function main(): Promise<void> {
3838 await Promise . all ( manifests . packageJson . map ( file => updatePackageJson ( file , version ) ) ) ;
3939 await Promise . all ( manifests . cargoToml . map ( file => updateCargoToml ( file , version ) ) ) ;
4040
41+ const publishableTypeScriptPackages = await getPublishableTypeScriptPackages ( manifests . packageJson ) ;
42+
4143 await createAndPushCommit ( version ) ;
4244
43- await runCommand ( 'pnpm' , [ 'publish' ] , path . join ( repoRoot , 'typescript' ) ) ;
45+ await publishTypeScriptPackages ( publishableTypeScriptPackages , version ) ;
4446 await runCommand ( 'cargo' , [ 'publish' ] , path . join ( repoRoot , 'rust' ) ) ;
4547}
4648
@@ -156,6 +158,92 @@ async function updateCargoToml(filePath: string, version: string): Promise<void>
156158 console . log ( `Updated ${ relative ( filePath ) } to ${ version } ` ) ;
157159}
158160
161+ type PublishablePackage = {
162+ name : string ;
163+ directory : string ;
164+ } ;
165+
166+ async function getPublishableTypeScriptPackages ( packageJsonPaths : string [ ] ) : Promise < PublishablePackage [ ] > {
167+ const tsRoot = path . join ( repoRoot , 'typescript' ) ;
168+ const packages : PublishablePackage [ ] = [ ] ;
169+
170+ for ( const filePath of packageJsonPaths ) {
171+ const isTypeScriptPackage =
172+ filePath === path . join ( tsRoot , 'package.json' ) ||
173+ filePath . startsWith ( `${ tsRoot } ${ path . sep } ` ) ;
174+
175+ if ( ! isTypeScriptPackage ) {
176+ continue ;
177+ }
178+
179+ const raw = await fs . readFile ( filePath , 'utf8' ) ;
180+ let parsed : unknown ;
181+
182+ try {
183+ parsed = JSON . parse ( raw ) ;
184+ } catch ( error ) {
185+ throw new Error ( `Failed to parse JSON in ${ relative ( filePath ) } : ${ ( error as Error ) . message } ` ) ;
186+ }
187+
188+ if ( ! parsed || typeof parsed !== 'object' ) {
189+ throw new Error ( `Unexpected JSON shape in ${ relative ( filePath ) } (expected object)` ) ;
190+ }
191+
192+ const pkg = parsed as { name ?: unknown ; private ?: unknown } ;
193+
194+ if ( pkg . private === true ) {
195+ continue ;
196+ }
197+
198+ if ( typeof pkg . name !== 'string' || pkg . name . length === 0 ) {
199+ console . warn ( `Skipping ${ relative ( filePath ) } (missing package name)` ) ;
200+ continue ;
201+ }
202+
203+ packages . push ( {
204+ name : pkg . name ,
205+ directory : path . dirname ( filePath )
206+ } ) ;
207+ }
208+
209+ return packages ;
210+ }
211+
212+ async function publishTypeScriptPackages ( packages : PublishablePackage [ ] , version : string ) : Promise < void > {
213+ if ( packages . length === 0 ) {
214+ console . warn ( 'No publishable TypeScript packages found, skipping npm publish' ) ;
215+ return ;
216+ }
217+
218+ const tag = version . includes ( '-rc.' ) ? 'rc' : 'latest' ;
219+
220+ for ( const pkg of packages ) {
221+ console . log ( `Preparing to publish ${ pkg . name } @${ version } from ${ relative ( pkg . directory ) } ` ) ;
222+
223+ if ( await packageVersionExists ( pkg . name , version ) ) {
224+ console . log ( `Skipping ${ pkg . name } @${ version } (already published)` ) ;
225+ continue ;
226+ }
227+
228+ await runCommand (
229+ 'pnpm' ,
230+ [ '--filter' , pkg . name , 'publish' , '--access' , 'public' , '--tag' , tag ] ,
231+ path . join ( repoRoot , 'typescript' )
232+ ) ;
233+ }
234+
235+ console . log ( `Published TypeScript packages with tag '${ tag } '` ) ;
236+ }
237+
238+ async function packageVersionExists ( name : string , version : string ) : Promise < boolean > {
239+ try {
240+ await captureCommand ( 'npm' , [ 'view' , `${ name } @${ version } ` , 'version' ] , repoRoot ) ;
241+ return true ;
242+ } catch {
243+ return false ;
244+ }
245+ }
246+
159247async function runCommand ( command : string , args : string [ ] , cwd : string ) : Promise < void > {
160248 console . log ( `Running ${ command } ${ args . join ( ' ' ) } in ${ relative ( cwd ) } ` ) ;
161249
0 commit comments