Skip to content

Commit 2f1c135

Browse files
committed
refactor: extract package.json scripts to .mjs files
Replace inline shell scripts with Node.js .mjs files for better customization, maintainability, and cross-platform compatibility. New scripts: - scripts/build.mjs: Build orchestration with --src-only, --types-only flags - scripts/clean.mjs: Clean artifacts with granular flags - scripts/check.mjs: Run quality checks (lint fix, ESLint, TypeScript) - scripts/lint-fix.mjs: Sequential linter execution - scripts/coverage.mjs: Coverage collection with flags - scripts/utils/: Shared command execution and utility functions Benefits: - Easier to add conditional logic and custom flags - Better error handling with proper exit codes - Cross-platform compatibility (no shell-specific syntax) - Improved maintainability and testability Pattern follows socket-cli and socket-registry implementations.
1 parent c905bfb commit 2f1c135

File tree

10 files changed

+609
-15
lines changed

10 files changed

+609
-15
lines changed

package.json

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,31 +29,31 @@
2929
},
3030
"sideEffects": false,
3131
"scripts": {
32-
"check": "run-p -c --aggregate-output check:*",
32+
"check": "node scripts/check.mjs",
3333
"lint-ci": "pnpm run check:lint",
3434
"check:lint": "eslint --config .config/eslint.config.mjs --report-unused-disable-directives .",
3535
"check:lint:fix": "pnpm run check:lint --fix",
36-
"build": "pnpm run build:dist",
37-
"build:dist": "pnpm run build:dist:src && pnpm run build:dist:types",
38-
"build:dist:src": "pnpm run clean:dist && rollup -c .config/rollup.dist.config.mjs",
39-
"build:dist:types": "pnpm run clean:dist:types && tsgo --project tsconfig.dts.json",
36+
"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",
4040
"check:tsc": "tsgo --noEmit -p .config/tsconfig.check.json",
41-
"clean:dist": "del-cli 'dist' '**/*.tsbuildinfo'",
42-
"clean:dist:types": "del-cli 'dist/types'",
43-
"clean": "run-s -c clean:*",
44-
"clean:cache": "del-cli '**/.cache'",
45-
"clean:coverage": "del-cli 'coverage'",
46-
"clean:node_modules": "del-cli '**/node_modules'",
47-
"coverage": "run-s coverage:*",
48-
"coverage:test": "run-s pretest:unit test:unit:coverage",
41+
"clean:dist": "node scripts/clean.mjs --dist",
42+
"clean:dist:types": "node scripts/clean.mjs --dist-types",
43+
"clean": "node scripts/clean.mjs",
44+
"clean:cache": "node scripts/clean.mjs --cache",
45+
"clean:coverage": "node scripts/clean.mjs --coverage",
46+
"clean:node_modules": "node scripts/clean.mjs --node-modules",
47+
"coverage": "node scripts/coverage.mjs",
48+
"coverage:test": "node scripts/coverage.mjs --code-only",
4949
"coverage:percent": "node scripts/get-coverage-percentage.mjs",
5050
"coverage:type": "type-coverage",
5151
"coverage:type:verbose": "type-coverage --detail",
52-
"fix": "run-s lint:fix check:lint:fix",
52+
"fix": "node scripts/lint-fix.mjs",
5353
"knip:dependencies": "knip --dependencies",
5454
"knip:exports": "knip --include exports,duplicates",
5555
"lint": "oxlint -c=.config/.oxlintrc.json --ignore-path=.oxlintignore --tsconfig=tsconfig.json .",
56-
"lint:fix": "run-s -c lint:fix:*",
56+
"lint:fix": "node scripts/lint-fix.mjs",
5757
"lint:fix:oxlint": "oxlint -c=.config/.oxlintrc.json --ignore-path=.oxlintignore --tsconfig=tsconfig.json --quiet --fix . | dev-null",
5858
"lint:fix:biome": "biome format --log-level=none --fix . | dev-null",
5959
"lint:fix:eslint": "eslint --config .config/eslint.config.mjs --report-unused-disable-directives --fix . | dev-null",

scripts/build.mjs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/**
2+
* @fileoverview Build script for socket-packageurl-js.
3+
* Orchestrates the complete build process:
4+
* - Cleans dist directory
5+
* - Compiles source with Rollup
6+
* - Generates TypeScript declarations
7+
*
8+
* Usage:
9+
* node scripts/build.mjs [--src-only|--types-only]
10+
*/
11+
12+
import { parseArgs } from 'node:util'
13+
14+
import { logger } from '@socketsecurity/registry/lib/logger'
15+
16+
import { runSequence } from './utils/run-command.mjs'
17+
18+
async function main() {
19+
try {
20+
const { values } = parseArgs({
21+
options: {
22+
'src-only': { type: 'boolean', default: false },
23+
'types-only': { type: 'boolean', default: false },
24+
},
25+
strict: false,
26+
})
27+
28+
const srcOnly = values['src-only']
29+
const typesOnly = values['types-only']
30+
31+
if (typesOnly) {
32+
logger.log('Building TypeScript declarations only...')
33+
const exitCode = await runSequence([
34+
{ args: ['run', 'clean:dist:types'], command: 'pnpm' },
35+
{ args: ['--project', 'tsconfig.dts.json'], command: 'tsgo' },
36+
])
37+
process.exitCode = exitCode
38+
return
39+
}
40+
41+
if (srcOnly) {
42+
logger.log('Building source only...')
43+
const exitCode = await runSequence([
44+
{ args: ['run', 'clean:dist'], command: 'pnpm' },
45+
{
46+
args: ['-c', '.config/rollup.dist.config.mjs'],
47+
command: 'rollup',
48+
},
49+
])
50+
process.exitCode = exitCode
51+
return
52+
}
53+
54+
// Build both src and types
55+
logger.log('Building package (source + types)...')
56+
57+
// Build src
58+
const srcExitCode = await runSequence([
59+
{ args: ['run', 'clean:dist'], command: 'pnpm' },
60+
{
61+
args: ['-c', '.config/rollup.dist.config.mjs'],
62+
command: 'rollup',
63+
},
64+
])
65+
66+
if (srcExitCode !== 0) {
67+
process.exitCode = srcExitCode
68+
return
69+
}
70+
71+
// Build types
72+
const typesExitCode = await runSequence([
73+
{ args: ['run', 'clean:dist:types'], command: 'pnpm' },
74+
{ args: ['--project', 'tsconfig.dts.json'], command: 'tsgo' },
75+
])
76+
77+
process.exitCode = typesExitCode
78+
} catch (error) {
79+
logger.error('Build failed:', error.message)
80+
process.exitCode = 1
81+
}
82+
}
83+
84+
main()

scripts/check.mjs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* @fileoverview Check script for socket-packageurl-js.
3+
* Runs all quality checks:
4+
* 1. Auto-fix linting issues
5+
* 2. ESLint check
6+
* 3. TypeScript type check
7+
*
8+
* Usage:
9+
* node scripts/check.mjs
10+
*/
11+
12+
import { logger } from '@socketsecurity/registry/lib/logger'
13+
14+
import { runSequence } from './utils/run-command.mjs'
15+
16+
async function main() {
17+
try {
18+
logger.log('Running checks...')
19+
20+
const exitCode = await runSequence([
21+
{ args: ['run', 'fix'], command: 'pnpm' },
22+
{
23+
args: [
24+
'--config',
25+
'.config/eslint.config.mjs',
26+
'--report-unused-disable-directives',
27+
'.',
28+
],
29+
command: 'eslint',
30+
},
31+
{ args: ['--noEmit', '-p', '.config/tsconfig.check.json'], command: 'tsgo' },
32+
])
33+
34+
if (exitCode !== 0) {
35+
logger.error('Some checks failed')
36+
process.exitCode = exitCode
37+
} else {
38+
logger.log('All checks passed')
39+
}
40+
} catch (error) {
41+
logger.error('Check failed:', error.message)
42+
process.exitCode = 1
43+
}
44+
}
45+
46+
main()

scripts/clean.mjs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/**
2+
* @fileoverview Clean script for socket-packageurl-js.
3+
* Removes build artifacts, caches, and other generated files.
4+
*
5+
* Usage:
6+
* node scripts/clean.mjs [options]
7+
*
8+
* Options:
9+
* --cache Clean cache directories only
10+
* --dist Clean dist directory only
11+
* --dist-types Clean dist/types only
12+
* --coverage Clean coverage directory only
13+
* --node-modules Clean node_modules
14+
* --all Clean everything (default)
15+
*/
16+
17+
import { parseArgs } from 'node:util'
18+
19+
import { logger } from '@socketsecurity/registry/lib/logger'
20+
21+
import { runCommand } from './utils/run-command.mjs'
22+
23+
async function main() {
24+
try {
25+
const { values } = parseArgs({
26+
options: {
27+
all: { type: 'boolean', default: false },
28+
cache: { type: 'boolean', default: false },
29+
coverage: { type: 'boolean', default: false },
30+
dist: { type: 'boolean', default: false },
31+
'dist-types': { type: 'boolean', default: false },
32+
'node-modules': { type: 'boolean', default: false },
33+
},
34+
strict: false,
35+
})
36+
37+
// If no specific option is provided, clean everything
38+
const cleanAll =
39+
values.all ||
40+
(!values.cache &&
41+
!values.coverage &&
42+
!values.dist &&
43+
!values['dist-types'] &&
44+
!values['node-modules'])
45+
46+
const tasks = []
47+
48+
if (cleanAll || values.cache) {
49+
tasks.push({ name: 'cache', pattern: '**/.cache' })
50+
}
51+
52+
if (cleanAll || values.coverage) {
53+
tasks.push({ name: 'coverage', pattern: 'coverage' })
54+
}
55+
56+
if (cleanAll || values.dist) {
57+
tasks.push({
58+
name: 'dist',
59+
pattern: 'dist **/*.tsbuildinfo',
60+
})
61+
}
62+
63+
if (!cleanAll && values['dist-types']) {
64+
tasks.push({ name: 'dist/types', pattern: 'dist/types' })
65+
}
66+
67+
if (values['node-modules']) {
68+
tasks.push({ name: 'node_modules', pattern: '**/node_modules' })
69+
}
70+
71+
if (tasks.length === 0) {
72+
logger.log('Nothing to clean')
73+
return
74+
}
75+
76+
logger.log('Cleaning...')
77+
let hadError = false
78+
79+
for (const task of tasks) {
80+
logger.log(` - ${task.name}`)
81+
// eslint-disable-next-line no-await-in-loop
82+
const exitCode = await runCommand('del-cli', [task.pattern], {
83+
stdio: 'pipe',
84+
})
85+
if (exitCode !== 0) {
86+
hadError = true
87+
}
88+
}
89+
90+
if (hadError) {
91+
process.exitCode = 1
92+
} else {
93+
logger.log('Clean complete')
94+
}
95+
} catch (error) {
96+
logger.error('Clean failed:', error.message)
97+
process.exitCode = 1
98+
}
99+
}
100+
101+
main()

scripts/coverage.mjs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/**
2+
* @fileoverview Coverage script for socket-packageurl-js.
3+
* Collects both code coverage and type coverage.
4+
*
5+
* Usage:
6+
* node scripts/coverage.mjs [--code-only|--type-only|--percent]
7+
*/
8+
9+
import { parseArgs } from 'node:util'
10+
11+
import { logger } from '@socketsecurity/registry/lib/logger'
12+
13+
import { runSequence } from './utils/run-command.mjs'
14+
15+
async function main() {
16+
try {
17+
const { values } = parseArgs({
18+
options: {
19+
'code-only': { type: 'boolean', default: false },
20+
percent: { type: 'boolean', default: false },
21+
'type-only': { type: 'boolean', default: false },
22+
},
23+
strict: false,
24+
})
25+
26+
if (values.percent) {
27+
// Just get coverage percentage
28+
const exitCode = await runSequence([
29+
{ args: ['scripts/get-coverage-percentage.mjs'], command: 'node' },
30+
])
31+
process.exitCode = exitCode
32+
return
33+
}
34+
35+
if (values['type-only']) {
36+
logger.log('Collecting type coverage...')
37+
const exitCode = await runSequence([
38+
{ args: [], command: 'type-coverage' },
39+
])
40+
process.exitCode = exitCode
41+
return
42+
}
43+
44+
if (values['code-only']) {
45+
logger.log('Collecting code coverage...')
46+
const exitCode = await runSequence([
47+
{ args: ['run', 'pretest:unit'], command: 'pnpm' },
48+
{
49+
args: ['run', 'test:unit:coverage'],
50+
command: 'pnpm',
51+
},
52+
])
53+
process.exitCode = exitCode
54+
return
55+
}
56+
57+
// Collect both code and type coverage
58+
logger.log('Collecting coverage (code + type)...')
59+
60+
const codeExitCode = await runSequence([
61+
{ args: ['run', 'pretest:unit'], command: 'pnpm' },
62+
{
63+
args: ['run', 'test:unit:coverage'],
64+
command: 'pnpm',
65+
},
66+
])
67+
68+
if (codeExitCode !== 0) {
69+
process.exitCode = codeExitCode
70+
return
71+
}
72+
73+
const typeExitCode = await runSequence([
74+
{ args: [], command: 'type-coverage' },
75+
])
76+
77+
process.exitCode = typeExitCode
78+
} catch (error) {
79+
logger.error('Coverage collection failed:', error.message)
80+
process.exitCode = 1
81+
}
82+
}
83+
84+
main()

0 commit comments

Comments
 (0)