1- import { defineConfig , mergeConfig , type Plugin } from 'vite' ;
2- import { libraryNodeBuildConfig } from '@internals/vite' ;
1+ import { readFileSync , writeFileSync } from 'node:fs' ;
32import { builtinModules } from 'node:module' ;
43import { createHash } from 'node:crypto' ;
5- import { readFileSync , writeFileSync } from 'node:fs' ;
4+ import { defineConfig , mergeConfig , type Plugin } from 'vite' ;
5+ import { libraryNodeBuildConfig } from '@internals/vite' ;
6+ import semanticRelease from 'semantic-release' ;
67
78const NODE_BUILT_IN_MODULES = builtinModules . filter ( m => ! m . startsWith ( '_' ) ) ;
89NODE_BUILT_IN_MODULES . push ( ...NODE_BUILT_IN_MODULES . map ( m => `node:${ m } ` ) ) ;
910
10- function buildChecksumPlugin ( ) : Plugin {
11- return {
12- name : 'build-checksum' ,
13- closeBundle ( ) {
14- const file = 'dist/index.js' ;
15- const content = readFileSync ( file , 'utf-8' ) ;
16- const hash = createHash ( 'sha256' ) . update ( content ) . digest ( 'hex' ) . slice ( 0 , 12 ) ;
17- writeFileSync ( file , content . replaceAll ( '__NVE_BUILD_CHECKSUM__' , hash ) ) ;
18- writeFileSync ( 'dist/manifest.json' , JSON . stringify ( { sha : hash } ) ) ;
19- }
20- } ;
21- }
22-
2311export default defineConfig ( ( ) => {
2412 const libConfig = libraryNodeBuildConfig ;
2513 if ( libConfig . build ?. rolldownOptions ?. external ) {
@@ -33,6 +21,64 @@ export default defineConfig(() => {
3321 build : {
3422 ssr : true // trick vite to build with node deps
3523 } ,
36- plugins : [ buildChecksumPlugin ( ) ]
24+ plugins : [ buildBinaryVersionPlugin ( ) ]
3725 } ) ;
3826} ) ;
27+
28+ function buildBinaryVersionPlugin ( ) : Plugin {
29+ return {
30+ name : 'build-binary-version' ,
31+ async closeBundle ( ) {
32+ let content = readFileSync ( 'dist/index.js' , 'utf-8' ) ;
33+ const hash = createHash ( 'sha256' ) . update ( content ) . digest ( 'hex' ) . slice ( 0 , 12 ) ;
34+ content = content . replaceAll ( '__NVE_BUILD_CHECKSUM__' , hash ) ;
35+
36+ if ( process . env . CI ) {
37+ const releaseVersion = await getNextReleaseVersion ( ) ;
38+ content = content . replaceAll ( '0.0.0' , releaseVersion ) ;
39+ }
40+
41+ writeFileSync ( 'dist/index.js' , content ) ;
42+ writeFileSync ( 'dist/manifest.json' , JSON . stringify ( { sha : hash } ) ) ;
43+ }
44+ } ;
45+ }
46+
47+ /**
48+ * This pre-computes the next release version. This is only needed for the CLI
49+ * package since semantic release can't modify the version of the binaries after they are built.
50+ */
51+ async function getNextReleaseVersion ( ) {
52+ const releaseResult = await semanticRelease (
53+ {
54+ dryRun : true ,
55+ branches : [ 'main' ] ,
56+ plugins : [
57+ [
58+ '@semantic-release/commit-analyzer' ,
59+ {
60+ releaseRules : [
61+ // Catch-all first: suppress default rules (false acts as baseline)
62+ { breaking : true , release : false } ,
63+ { type : 'feat' , release : false } ,
64+ { type : 'fix' , release : false } ,
65+ { type : 'perf' , release : false } ,
66+ { type : 'revert' , release : false } ,
67+ { type : 'chore' , release : false } ,
68+ // Scope-matched rules last: override false for matching scope
69+ { breaking : true , scope : 'cli' , release : 'major' } ,
70+ { type : 'feat' , scope : 'cli' , release : 'minor' } ,
71+ { type : 'fix' , scope : 'cli' , release : 'patch' }
72+ ]
73+ }
74+ ]
75+ ]
76+ } ,
77+ {
78+ cwd : process . cwd ( ) ,
79+ env : process . env
80+ }
81+ ) ;
82+
83+ return releaseResult ? releaseResult . nextRelease . version : '0.0.0' ;
84+ }
0 commit comments