Skip to content

Commit 82c1b10

Browse files
committed
Unify scripts with flag-based configuration from socket-packageurl-js
- Add unified lint.mjs with flags (--changed, --staged, --fix) - Add unified test.mjs with flags (--fast, --cover, --staged) - Add unified build.mjs with flags (--src, --types, --watch, --needed) - Replace test-affected with test-changed - Replace affected-test-mapper with changed-test-mapper - Update .husky/pre-commit to use --staged - Remove old script variations from package.json - All scripts now support --help, --quiet/--silent - Fix all lint errors
1 parent 2f6a668 commit 82c1b10

31 files changed

+1552
-927
lines changed

.husky/pre-commit

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
if [ -z "${DISABLE_PRECOMMIT_LINT}" ]; then
2-
pnpm run lint-staged
2+
pnpm lint --staged
33
else
44
echo "Skipping lint due to DISABLE_PRECOMMIT_LINT env var"
55
fi
66

77
if [ -z "${DISABLE_PRECOMMIT_TEST}" ]; then
8-
pnpm run test-pre-commit
8+
dotenvx -q run -f .env.precommit -- pnpm test --staged
99
else
1010
echo "Skipping testing due to DISABLE_PRECOMMIT_TEST env var"
1111
fi

package.json

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@
3434
},
3535
"scripts": {
3636
"build": "node scripts/build.mjs",
37-
"build:dist": "node scripts/build.mjs",
38-
"build:dist:src": "node scripts/build.mjs --src-only",
39-
"build:dist:types": "node scripts/build.mjs --types-only",
4037
"build:ink": "node scripts/build.mjs --ink-only",
4138
"build:sea": "node scripts/build-sea.mjs",
4239
"build:sea:stub": "rollup -c .config/rollup.sea.config.mjs",
@@ -52,7 +49,7 @@
5249
"check:lint": "node scripts/lint-affected.mjs --all",
5350
"check:tsc": "tsgo --noEmit",
5451
"check-ci": "pnpm run check:lint",
55-
"lint": "node scripts/lint-affected.mjs",
52+
"lint": "node scripts/lint.mjs",
5653
"lint-ci": "pnpm run check:lint",
5754
"type-ci": "pnpm run check:tsc",
5855
"coverage": "node scripts/coverage.mjs",
@@ -65,24 +62,18 @@
6562
"clean:dist": "node scripts/clean.mjs --dist",
6663
"clean:dist:types": "node scripts/clean.mjs --dist-types",
6764
"clean:node_modules": "node scripts/clean.mjs --node-modules",
68-
"fix": "node scripts/lint-affected.mjs --fix",
65+
"fix": "node scripts/lint.mjs --fix",
6966
"knip:dependencies": "knip --config .config/knip.json --dependencies",
7067
"knip:exports": "knip --config .config/knip.json --include exports,duplicates",
7168
"lint-staged": "lint-staged",
7269
"precommit": "lint-staged",
7370
"prepare": "husky",
74-
"pretest:unit": "dotenvx -q run -f .env.test -- pnpm run build",
7571
"bs": "pnpm run build:dist:src; pnpm exec socket --",
7672
"s": "pnpm exec socket --",
77-
"test": "run-s check test:*",
78-
"test:affected": "node scripts/test-affected.mjs",
79-
"test:unit": "dotenvx -q run -f .env.test -- pnpm vitest run --config .config/vitest.config.mts",
80-
"test:unit:update": "dotenvx -q run -f .env.test -- pnpm vitest run --config .config/vitest.config.mts --update",
81-
"test:unit:coverage": "dotenvx -q run -f .env.test -- pnpm vitest run --config .config/vitest.config.mts --coverage",
73+
"test": "node scripts/test.mjs",
8274
"test:validate": "node scripts/validate-tests.mjs",
8375
"test:wrapper": "node scripts/test-wrapper.mjs",
8476
"test-ci": "run-s test:*",
85-
"test-pre-commit": "dotenvx -q run -f .env.precommit -- node scripts/test-affected.mjs --staged",
8677
"testu": "dotenvx -q run -f .env.test -- run-s pretest:unit; pnpm run test:unit:update --",
8778
"testuf": "dotenvx -q run -f .env.test -- pnpm run test:unit:update --",
8879
"update": "run-p --aggregate-output update:*",

scripts/build.mjs

Lines changed: 243 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,274 @@
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'
139
import { 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

19139
async 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

Comments
 (0)