11/**
2- * @fileoverview Build script for the CLI.
3- * Orchestrates the complete build process:
4- * - Cleans dist directory
5- * - Compiles source with Rollup
6- * - Builds Ink components
7- * - Generates TypeScript declarations
8- *
9- * Usage:
10- * node scripts/build.mjs [--src-only|--types-only|--ink-only]
2+ * @fileoverview Unified build runner with flag-based configuration.
3+ * Orchestrates the complete build process with flexible options.
114 */
125
6+ import { existsSync } from 'node:fs'
7+ import path from 'node:path'
8+ import { fileURLToPath } from 'node:url'
139import { parseArgs } from 'node:util'
1410
15- import { logger } from '@socketsecurity/registry/lib/logger '
11+ import colors from 'yoctocolors-cjs '
1612
17- import { runSequence } from './utils/run-command.mjs'
13+ import { runCommand , runSequence } from './utils/run-command.mjs'
14+
15+ const __dirname = path . dirname ( fileURLToPath ( import . meta. url ) )
16+ const rootPath = path . join ( __dirname , '..' )
17+
18+ // Simple clean logging without prefixes
19+ const log = {
20+ info : msg => console . log ( msg ) ,
21+ error : msg => console . error ( `${ colors . red ( '✗' ) } ${ msg } ` ) ,
22+ success : msg => console . log ( `${ colors . green ( '✓' ) } ${ msg } ` ) ,
23+ step : msg => console . log ( `\n${ msg } ` ) ,
24+ substep : msg => console . log ( ` ${ msg } ` ) ,
25+ progress : msg => {
26+ // Write progress message without newline for in-place updates
27+ process . stdout . write ( ` ∴ ${ msg } ` )
28+ } ,
29+ done : msg => {
30+ // Clear current line and write success message
31+ // Carriage return + clear line
32+ process . stdout . write ( '\r\x1b[K' )
33+ console . log ( ` ${ colors . green ( '✓' ) } ${ msg } ` )
34+ } ,
35+ failed : msg => {
36+ // Clear current line and write failure message
37+ // Carriage return + clear line
38+ process . stdout . write ( '\r\x1b[K' )
39+ console . log ( ` ${ colors . red ( '✗' ) } ${ msg } ` )
40+ }
41+ }
42+
43+ /**
44+ * Build source code with Rollup.
45+ */
46+ async function buildSource ( options = { } ) {
47+ const { quiet = false } = options
48+
49+ if ( ! quiet ) {
50+ log . progress ( 'Building source code' )
51+ }
52+
53+ const exitCode = await runSequence ( [
54+ { args : [ 'run' , 'clean:dist' ] , command : 'pnpm' } ,
55+ {
56+ args : [ 'exec' , 'rollup' , '-c' , '.config/rollup.dist.config.mjs' ] ,
57+ command : 'pnpm' ,
58+ } ,
59+ ] )
60+
61+ if ( exitCode !== 0 ) {
62+ if ( ! quiet ) {
63+ log . failed ( 'Source build failed' )
64+ }
65+ return exitCode
66+ }
67+
68+ if ( ! quiet ) {
69+ log . done ( 'Source build complete' )
70+ }
71+
72+ return 0
73+ }
74+
75+ /**
76+ * Build TypeScript declarations.
77+ */
78+ async function buildTypes ( options = { } ) {
79+ const { quiet = false } = options
80+
81+ if ( ! quiet ) {
82+ log . progress ( 'Building TypeScript declarations' )
83+ }
84+
85+ const exitCode = await runSequence ( [
86+ { args : [ 'run' , 'clean:dist:types' ] , command : 'pnpm' } ,
87+ {
88+ args : [ 'exec' , 'tsgo' , '--project' , 'tsconfig.dts.json' ] ,
89+ command : 'pnpm' ,
90+ } ,
91+ ] )
92+
93+ if ( exitCode !== 0 ) {
94+ if ( ! quiet ) {
95+ log . failed ( 'Type declarations build failed' )
96+ }
97+ return exitCode
98+ }
99+
100+ if ( ! quiet ) {
101+ log . done ( 'Type declarations built' )
102+ }
103+
104+ return 0
105+ }
106+
107+ /**
108+ * Watch mode for development.
109+ */
110+ async function watchBuild ( options = { } ) {
111+ const { quiet = false } = options
112+
113+ if ( ! quiet ) {
114+ log . step ( 'Starting watch mode' )
115+ log . substep ( 'Watching for file changes...' )
116+ }
117+
118+ const exitCode = await runCommand (
119+ 'pnpm' ,
120+ [ 'exec' , 'rollup' , '-c' , '.config/rollup.dist.config.mjs' , '--watch' ] ,
121+ {
122+ stdio : 'inherit'
123+ }
124+ )
125+
126+ return exitCode
127+ }
128+
129+ /**
130+ * Check if build is needed.
131+ */
132+ function isBuildNeeded ( ) {
133+ const distPath = path . join ( rootPath , 'dist' , 'index.js' )
134+ const distTypesPath = path . join ( rootPath , 'dist' , 'types' , 'index.d.ts' )
135+
136+ return ! existsSync ( distPath ) || ! existsSync ( distTypesPath )
137+ }
18138
19139async function main ( ) {
20140 try {
141+ // Parse arguments
21142 const { values } = parseArgs ( {
22143 options : {
23- 'src-only' : { type : 'boolean' , default : false } ,
24- 'types-only' : { type : 'boolean' , default : false } ,
144+ help : {
145+ type : 'boolean' ,
146+ default : false ,
147+ } ,
148+ src : {
149+ type : 'boolean' ,
150+ default : false ,
151+ } ,
152+ types : {
153+ type : 'boolean' ,
154+ default : false ,
155+ } ,
156+ watch : {
157+ type : 'boolean' ,
158+ default : false ,
159+ } ,
160+ needed : {
161+ type : 'boolean' ,
162+ default : false ,
163+ } ,
164+ silent : {
165+ type : 'boolean' ,
166+ default : false ,
167+ } ,
168+ quiet : {
169+ type : 'boolean' ,
170+ default : false ,
171+ } ,
25172 } ,
173+ allowPositionals : false ,
26174 strict : false ,
27175 } )
28176
29- const srcOnly = values [ 'src-only' ]
30- const typesOnly = values [ 'types-only' ]
31-
32- if ( typesOnly ) {
33- logger . log ( 'Building TypeScript declarations only...' )
34- const exitCode = await runSequence ( [
35- { args : [ 'run' , 'clean:dist:types' ] , command : 'pnpm' } ,
36- {
37- args : [ 'exec' , 'tsgo' , '--project' , 'tsconfig.dts.json' ] ,
38- command : 'pnpm' ,
39- } ,
40- ] )
41- process . exitCode = exitCode
177+ // Show help if requested
178+ if ( values . help ) {
179+ console . log ( 'Socket PackageURL Build Runner' )
180+ console . log ( '\nUsage: pnpm build [options]' )
181+ console . log ( '\nOptions:' )
182+ console . log ( ' --help Show this help message' )
183+ console . log ( ' --src Build source code only' )
184+ console . log ( ' --types Build TypeScript declarations only' )
185+ console . log ( ' --watch Watch mode for development' )
186+ console . log ( ' --needed Only build if dist files are missing' )
187+ console . log ( ' --quiet, --silent Suppress progress messages' )
188+ console . log ( '\nExamples:' )
189+ console . log ( ' pnpm build # Full build (source + types)' )
190+ console . log ( ' pnpm build --src # Build source only' )
191+ console . log ( ' pnpm build --types # Build types only' )
192+ console . log ( ' pnpm build --watch # Watch mode' )
193+ console . log ( ' pnpm build --needed # Build only if needed' )
194+ process . exitCode = 0
42195 return
43196 }
44197
45- if ( srcOnly ) {
46- logger . log ( 'Building source only...' )
47- const exitCode = await runSequence ( [
48- { args : [ 'run' , 'clean:dist' ] , command : 'pnpm' } ,
49- {
50- args : [ 'exec' , 'rollup' , '-c' , '.config/rollup.dist.config.mjs' ] ,
51- command : 'pnpm' ,
52- } ,
53- ] )
54- process . exitCode = exitCode
198+ // Handle aliases
199+ const quiet = values . quiet || values . silent
200+
201+ // Check if build is needed
202+ if ( values . needed && ! isBuildNeeded ( ) ) {
203+ if ( ! quiet ) {
204+ log . info ( 'Build artifacts exist, skipping build' )
205+ }
206+ process . exitCode = 0
55207 return
56208 }
57209
58- // Build both src and types
59- logger . log ( 'Building CLI (source + types)...' )
210+ if ( ! quiet ) {
211+ console . log ( '═══════════════════════════════════════════════════════' )
212+ console . log ( ' Socket PackageURL Build Runner' )
213+ console . log ( '═══════════════════════════════════════════════════════' )
214+ }
60215
61- // Build src
62- const srcExitCode = await runSequence ( [
63- { args : [ 'run' , 'clean:dist' ] , command : 'pnpm' } ,
64- {
65- args : [ 'exec' , 'rollup' , '-c' , '.config/rollup.dist.config.mjs' ] ,
66- command : 'pnpm' ,
67- } ,
68- ] )
216+ let exitCode = 0
69217
70- if ( srcExitCode !== 0 ) {
71- process . exitCode = srcExitCode
72- return
218+ // Handle watch mode
219+ if ( values . watch ) {
220+ exitCode = await watchBuild ( { quiet } )
221+ }
222+ // Build types only
223+ else if ( values . types && ! values . src ) {
224+ if ( ! quiet ) {
225+ log . step ( 'Building TypeScript declarations only' )
226+ }
227+ exitCode = await buildTypes ( { quiet } )
73228 }
229+ // Build source only
230+ else if ( values . src && ! values . types ) {
231+ if ( ! quiet ) {
232+ log . step ( 'Building source only' )
233+ }
234+ exitCode = await buildSource ( { quiet } )
235+ }
236+ // Build everything (default)
237+ else {
238+ if ( ! quiet ) {
239+ log . step ( 'Building package (source + types)' )
240+ }
74241
75- // Build types
76- const typesExitCode = await runSequence ( [
77- { args : [ 'run' , 'clean:dist:types' ] , command : 'pnpm' } ,
78- {
79- args : [ 'exec' , 'tsgo' , '--project' , 'tsconfig.dts.json' ] ,
80- command : 'pnpm' ,
81- } ,
82- ] )
242+ // Build source first
243+ exitCode = await buildSource ( { quiet } )
244+ if ( exitCode !== 0 ) {
245+ if ( ! quiet ) {
246+ log . error ( 'Build failed' )
247+ }
248+ process . exitCode = exitCode
249+ return
250+ }
83251
84- process . exitCode = typesExitCode
252+ // Then build types
253+ exitCode = await buildTypes ( { quiet } )
254+ }
255+
256+ if ( exitCode !== 0 ) {
257+ if ( ! quiet ) {
258+ log . error ( 'Build failed' )
259+ }
260+ process . exitCode = exitCode
261+ } else {
262+ if ( ! quiet ) {
263+ console . log ( '\n═══════════════════════════════════════════════════════' )
264+ log . success ( 'Build completed successfully!' )
265+ console . log ( '═══════════════════════════════════════════════════════' )
266+ }
267+ }
85268 } catch ( error ) {
86- logger . error ( ' Build failed:' , error . message )
269+ log . error ( ` Build runner failed: ${ error . message } ` )
87270 process . exitCode = 1
88271 }
89272}
90273
91- main ( ) . catch ( console . error )
274+ main ( ) . catch ( console . error )
0 commit comments