33import { createInterface } from 'node:readline/promises' ;
44import { stdin as input , stdout as output } from 'node:process' ;
55import { spawnSync } from 'node:child_process' ;
6- import { readFileSync , writeFileSync } from 'node:fs' ;
6+ import { readFileSync } from 'node:fs' ;
77import path from 'node:path' ;
88import { fileURLToPath } from 'node:url' ;
99
@@ -29,12 +29,23 @@ function run(cmd, args, opts = {}) {
2929 return ( res . stdout || '' ) . trim ( ) ;
3030}
3131
32- function readPackageJson ( ) {
33- return JSON . parse ( readFileSync ( packageJsonPath , 'utf8' ) ) ;
32+ function ensureVersionAvailableOnNpm ( pkgName , version ) {
33+ const result = spawnSync ( 'npm' , [ 'view' , `${ pkgName } @${ version } ` , 'version' ] , {
34+ cwd : repoRoot ,
35+ stdio : [ 'ignore' , 'pipe' , 'pipe' ] ,
36+ encoding : 'utf8' ,
37+ } ) ;
38+ if ( result . status === 0 ) throw new Error ( `${ pkgName } @${ version } is already published on npm.` ) ;
39+
40+ const output = `${ result . stdout || '' } \n${ result . stderr || '' } ` ;
41+ if ( ! / E 4 0 4 | 4 0 4 N o t F o u n d / i. test ( output ) ) {
42+ if ( output . trim ( ) ) console . error ( output . trim ( ) ) ;
43+ throw new Error ( `Could not verify npm availability for ${ pkgName } @${ version } .` ) ;
44+ }
3445}
3546
36- function writePackageJson ( pkg ) {
37- writeFileSync ( packageJsonPath , ` ${ JSON . stringify ( pkg , null , 2 ) } \n` , 'utf8' ) ;
47+ function readPackageJson ( ) {
48+ return JSON . parse ( readFileSync ( packageJsonPath , 'utf8' ) ) ;
3849}
3950
4051function parseSemver ( v ) {
@@ -74,14 +85,16 @@ async function main() {
7485
7586 console . log ( `Current version: ${ current } ` ) ;
7687 console . log ( 'Select release type:' ) ;
88+ console . log ( '0) release current prepared version' ) ;
7789 console . log ( '1) patch' ) ;
7890 console . log ( '2) minor' ) ;
7991 console . log ( '3) major' ) ;
8092 console . log ( '4) custom' ) ;
8193
8294 const choice = ( await rl . question ( 'Choice [1]: ' ) ) . trim ( ) || '1' ;
8395 let nextVersion ;
84- if ( choice === '1' ) nextVersion = bump ( current , 'patch' ) ;
96+ if ( choice === '0' ) nextVersion = current ;
97+ else if ( choice === '1' ) nextVersion = bump ( current , 'patch' ) ;
8598 else if ( choice === '2' ) nextVersion = bump ( current , 'minor' ) ;
8699 else if ( choice === '3' ) nextVersion = bump ( current , 'major' ) ;
87100 else if ( choice === '4' ) {
@@ -104,12 +117,23 @@ async function main() {
104117 ensureCleanGit ( ) ;
105118 ensureMainBranch ( ) ;
106119 run ( 'git' , [ 'pull' , '--rebase' ] ) ;
120+ ensureVersionAvailableOnNpm ( pkg . name , nextVersion ) ;
107121
108- pkg . version = nextVersion ;
109- writePackageJson ( pkg ) ;
122+ if ( nextVersion !== current ) {
123+ run ( 'npm' , [ 'version' , nextVersion , '--no-git-tag-version' ] ) ;
124+ }
125+
126+ run ( 'npm' , [ 'ci' ] ) ;
127+ run ( 'npm' , [ 'test' ] ) ;
128+ run ( 'npm' , [ 'run' , 'typecheck' ] ) ;
129+ run ( 'npm' , [ 'audit' ] ) ;
130+ run ( 'npm' , [ 'pack' , '--dry-run' ] ) ;
131+ run ( 'npm' , [ 'run' , 'verify:release' , '--' , tag ] ) ;
110132
111- run ( 'git' , [ 'add' , 'package.json' , '.github/workflows/release.yml' , 'scripts/release.mjs' ] ) ;
112- run ( 'git' , [ 'commit' , '-m' , `chore(release): v${ nextVersion } ` ] ) ;
133+ if ( nextVersion !== current ) {
134+ run ( 'git' , [ 'add' , 'package.json' , 'package-lock.json' ] ) ;
135+ run ( 'git' , [ 'commit' , '-m' , `chore(release): v${ nextVersion } ` ] ) ;
136+ }
113137 run ( 'git' , [ 'tag' , '-a' , tag , '-m' , tag ] ) ;
114138 run ( 'git' , [ 'push' , 'origin' , 'HEAD' ] ) ;
115139 run ( 'git' , [ 'push' , 'origin' , tag ] ) ;
0 commit comments