Skip to content

Commit 8999993

Browse files
committed
refactor: add full TypeScript types to core script files
1 parent 693225f commit 8999993

File tree

12 files changed

+327
-112
lines changed

12 files changed

+327
-112
lines changed

scripts/clean.mts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,21 @@ const rootPath = path.resolve(
2323
/**
2424
* Clean specific directories.
2525
*/
26-
async function cleanDirectories(tasks, options = {}) {
26+
interface CleanTask {
27+
name: string
28+
pattern?: string
29+
patterns?: string[]
30+
}
31+
32+
async function cleanDirectories(
33+
tasks: CleanTask[],
34+
options: { quiet?: boolean } = {},
35+
): Promise<number> {
2736
const { quiet = false } = options
2837

2938
for (const task of tasks) {
3039
const { name, pattern, patterns } = task
31-
const patternsToDelete = patterns || [pattern]
40+
const patternsToDelete = patterns ?? (pattern ? [pattern] : [])
3241

3342
if (!quiet) {
3443
logger.progress(`Cleaning ${name}`)

scripts/constants/paths.mts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ import process from 'node:process'
1212
/**
1313
* Normalize path separators for cross-platform compatibility.
1414
*/
15-
function normalizePath(p) {
15+
function normalizePath(p: string): string {
1616
return p.split(path.sep).join(path.posix.sep)
1717
}
1818

1919
/**
2020
* Find project root by looking for pnpm-workspace.yaml.
2121
*/
22-
function findProjectRoot() {
22+
function findProjectRoot(): string {
2323
let currentPath = process.cwd()
2424
const root = path.parse(currentPath).root
2525

scripts/constants/utils.mts

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,44 +20,44 @@ import {
2020
/**
2121
* Get cached default which command options with augmented PATH.
2222
*/
23-
let _defaultWhichOptions
24-
export function getDefaultWhichOptions() {
23+
let _defaultWhichOptions: { path: string } | undefined
24+
export function getDefaultWhichOptions(): { path: string } {
2525
if (_defaultWhichOptions === undefined) {
2626
_defaultWhichOptions = {
2727
__proto__: null,
28-
path: `${ROOT_NODE_MODULES_BIN_PATH}${path.delimiter}${process.env.PATH}`,
29-
}
28+
path: `${ROOT_NODE_MODULES_BIN_PATH}${path.delimiter}${process.env['PATH']}`,
29+
} as { path: string }
3030
}
31-
return _defaultWhichOptions
31+
return _defaultWhichOptions!
3232
}
3333

3434
/**
3535
* Get root LICENSE file content.
3636
*/
37-
let _licenseContent
38-
export function getLicenseContent() {
37+
let _licenseContent: string | undefined
38+
export function getLicenseContent(): string {
3939
if (_licenseContent === undefined) {
4040
_licenseContent = fs.readFileSync(ROOT_LICENSE_PATH, 'utf8')
4141
}
42-
return _licenseContent
42+
return _licenseContent!
4343
}
4444

4545
/**
4646
* Get git executable path.
4747
*/
48-
let _gitExecPath
49-
export function getGitExecPath() {
48+
let _gitExecPath: string | undefined
49+
export function getGitExecPath(): string {
5050
if (_gitExecPath === undefined) {
5151
_gitExecPath = which.sync('git', getDefaultWhichOptions())
5252
}
53-
return _gitExecPath
53+
return _gitExecPath!
5454
}
5555

5656
/**
5757
* Get tsx executable path.
5858
*/
59-
let _tsxExecPath
60-
export function getTsxExecPath() {
59+
let _tsxExecPath: string | undefined
60+
export function getTsxExecPath(): string {
6161
if (_tsxExecPath === undefined) {
6262
const tsxPath = path.join(ROOT_NODE_MODULES_BIN_PATH, 'tsx')
6363
if (fs.existsSync(tsxPath)) {
@@ -66,14 +66,14 @@ export function getTsxExecPath() {
6666
_tsxExecPath = which.sync('tsx', getDefaultWhichOptions())
6767
}
6868
}
69-
return _tsxExecPath
69+
return _tsxExecPath!
7070
}
7171

7272
/**
7373
* Parse gitignore file and return ignore patterns.
7474
*/
75-
let _gitIgnorePatterns
76-
export function getGitIgnorePatterns() {
75+
let _gitIgnorePatterns: string[] | undefined
76+
export function getGitIgnorePatterns(): string[] {
7777
if (_gitIgnorePatterns === undefined) {
7878
const gitignorePath = path.join(ROOT_PATH, '.gitignore')
7979
const content = fs.readFileSync(gitignorePath, 'utf8')
@@ -82,14 +82,14 @@ export function getGitIgnorePatterns() {
8282
.map(line => line.trim())
8383
.filter(line => line && !line.startsWith('#'))
8484
}
85-
return _gitIgnorePatterns
85+
return _gitIgnorePatterns!
8686
}
8787

8888
/**
8989
* Get merged ignore globs from gitignore and standard exclusions.
9090
*/
91-
let _ignoreGlobs
92-
export function getIgnoreGlobs() {
91+
let _ignoreGlobs: readonly string[] | undefined
92+
export function getIgnoreGlobs(): readonly string[] {
9393
if (_ignoreGlobs === undefined) {
9494
_ignoreGlobs = Object.freeze([
9595
...new Set([
@@ -107,7 +107,7 @@ export function getIgnoreGlobs() {
107107
]),
108108
])
109109
}
110-
return _ignoreGlobs
110+
return _ignoreGlobs!
111111
}
112112

113113
/**

scripts/fix.mts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,16 @@ import { spawn } from '@socketsecurity/lib/spawn'
1717
const WIN32 = process.platform === 'win32'
1818
const logger = getDefaultLogger()
1919

20-
async function run(cmd, args, { label, required = true } = {}) {
20+
interface RunOptions {
21+
label?: string
22+
required?: boolean
23+
}
24+
25+
async function run(
26+
cmd: string,
27+
args: string[],
28+
{ label, required = true }: RunOptions = {},
29+
): Promise<number> {
2130
try {
2231
const result = await spawn(cmd, args, {
2332
shell: WIN32,

scripts/lint.mts

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const CONFIG_PATTERNS = [
4141
/**
4242
* Get oxfmt exclude patterns from .oxfmtrc.json.
4343
*/
44-
function getOxfmtExcludePatterns() {
44+
function getOxfmtExcludePatterns(): string[] {
4545
try {
4646
const oxfmtConfigPath = path.join(process.cwd(), '.oxfmtrc.json')
4747
if (!existsSync(oxfmtConfigPath)) {
@@ -59,7 +59,7 @@ function getOxfmtExcludePatterns() {
5959
/**
6060
* Check if a file matches any of the exclude patterns.
6161
*/
62-
function isExcludedByOxfmt(file, excludePatterns) {
62+
function isExcludedByOxfmt(file: string, excludePatterns: string[]): boolean {
6363
for (const pattern of excludePatterns) {
6464
// Convert glob pattern to regex-like matching.
6565
// Support **/ for directory wildcards and * for filename wildcards.
@@ -82,7 +82,10 @@ function isExcludedByOxfmt(file, excludePatterns) {
8282
/**
8383
* Check if we should run all linters based on changed files.
8484
*/
85-
function shouldRunAllLinters(changedFiles) {
85+
function shouldRunAllLinters(changedFiles: string[]): {
86+
runAll: boolean
87+
reason?: string
88+
} {
8689
for (const file of changedFiles) {
8790
// Core library files
8891
if (CORE_FILES.has(file)) {
@@ -103,7 +106,7 @@ function shouldRunAllLinters(changedFiles) {
103106
/**
104107
* Filter files to only those that should be linted.
105108
*/
106-
function filterLintableFiles(files) {
109+
function filterLintableFiles(files: string[]): string[] {
107110
// Only include extensions actually supported by oxfmt/oxlint
108111
const lintableExtensions = new Set([
109112
'.js',
@@ -139,18 +142,27 @@ function filterLintableFiles(files) {
139142
* @param {{ stderr?: string }} result
140143
* @returns {boolean}
141144
*/
142-
function isOxfmtNoFilesResult(result) {
145+
function isOxfmtNoFilesResult(result: { stderr?: string }): boolean {
143146
const { stderr } = result
144147
return (
145-
stderr?.includes('Expected at least one target file') ||
146-
stderr?.includes('No files were processed in the specified paths')
148+
(stderr?.includes('Expected at least one target file') ||
149+
stderr?.includes('No files were processed in the specified paths')) ??
150+
false
147151
)
148152
}
149153

150154
/**
151155
* Run linters on specific files.
152156
*/
153-
async function runLintOnFiles(files, options = {}) {
157+
interface LintOptions {
158+
fix?: boolean
159+
quiet?: boolean
160+
}
161+
162+
async function runLintOnFiles(
163+
files: string[],
164+
options: LintOptions = {},
165+
): Promise<number> {
154166
const { fix = false, quiet = false } = options
155167

156168
if (!files.length) {
@@ -217,7 +229,7 @@ async function runLintOnFiles(files, options = {}) {
217229
/**
218230
* Run linters on all files.
219231
*/
220-
async function runLintOnAll(options = {}) {
232+
async function runLintOnAll(options: LintOptions = {}): Promise<number> {
221233
const { fix = false, quiet = false } = options
222234

223235
if (!quiet) {
@@ -272,7 +284,21 @@ async function runLintOnAll(options = {}) {
272284
/**
273285
* Get files to lint based on options.
274286
*/
275-
async function getFilesToLint(options) {
287+
interface GetFilesToLintOptions {
288+
all?: boolean
289+
changed?: boolean
290+
staged?: boolean
291+
}
292+
293+
interface FilesToLintResult {
294+
files: string[] | 'all' | undefined
295+
reason?: string
296+
mode: string
297+
}
298+
299+
async function getFilesToLint(
300+
options: GetFilesToLintOptions,
301+
): Promise<FilesToLintResult> {
276302
const { all, changed, staged } = options
277303

278304
// If --all, return early
@@ -308,7 +334,7 @@ async function getFilesToLint(options) {
308334

309335
// Check if we should run all based on changed files
310336
const { reason, runAll } = shouldRunAllLinters(changedFiles)
311-
if (runAll) {
337+
if (runAll && reason) {
312338
return { files: 'all', reason, mode: 'all' }
313339
}
314340

@@ -318,7 +344,7 @@ async function getFilesToLint(options) {
318344
return { files: undefined, reason: 'no lintable files changed', mode }
319345
}
320346

321-
return { files: lintableFiles, reason: undefined, mode }
347+
return { files: lintableFiles, mode }
322348
}
323349

324350
async function main(): Promise<void> {
@@ -381,6 +407,7 @@ async function main(): Promise<void> {
381407
}
382408

383409
const quiet = isQuiet(values)
410+
const fix = Boolean(values['fix'])
384411

385412
if (!quiet) {
386413
printHeader('Lint Runner')
@@ -396,7 +423,7 @@ async function main(): Promise<void> {
396423
logger.step('Linting specified files')
397424
}
398425
exitCode = await runLintOnFiles(files, {
399-
fix: values.fix,
426+
fix,
400427
quiet,
401428
})
402429
} else {
@@ -414,7 +441,7 @@ async function main(): Promise<void> {
414441
logger.step(`Linting all files (${reason})`)
415442
}
416443
exitCode = await runLintOnAll({
417-
fix: values.fix,
444+
fix,
418445
quiet,
419446
})
420447
} else {
@@ -423,7 +450,7 @@ async function main(): Promise<void> {
423450
logger.step(`Linting ${modeText} files`)
424451
}
425452
exitCode = await runLintOnFiles(files, {
426-
fix: values.fix,
453+
fix,
427454
quiet,
428455
})
429456
}

scripts/publish.mts

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { existsSync } from 'node:fs'
77
import path from 'node:path'
88
import { fileURLToPath } from 'node:url'
99

10+
import type { SpawnOptions } from '@socketsecurity/lib/spawn'
11+
1012
import { parseArgs } from '@socketsecurity/lib/argv/parse'
1113
import { getDefaultLogger } from '@socketsecurity/lib/logger'
1214
import { spawn } from '@socketsecurity/lib/spawn'
@@ -21,7 +23,11 @@ const WIN32 = process.platform === 'win32'
2123
/**
2224
* Run a command with spawn.
2325
*/
24-
async function runCommand(command, args = [], options = {}) {
26+
async function runCommand(
27+
command: string,
28+
args: string[] = [],
29+
options: SpawnOptions = {},
30+
): Promise<number> {
2531
const result = await spawn(command, args, {
2632
stdio: 'inherit',
2733
cwd: rootPath,
@@ -34,7 +40,7 @@ async function runCommand(command, args = [], options = {}) {
3440
/**
3541
* Validate that build artifacts exist.
3642
*/
37-
async function validateBuildArtifacts() {
43+
async function validateBuildArtifacts(): Promise<boolean> {
3844
logger.step('Validating build artifacts')
3945

4046
// Check for registry package dist directory
@@ -59,7 +65,15 @@ async function validateBuildArtifacts() {
5965
* Publish packages using the complex multi-package flow.
6066
* Delegates to scripts/npm/publish-npm-packages.mjs.
6167
*/
62-
async function publishComplex(options = {}) {
68+
interface PublishOptions {
69+
force?: boolean
70+
forcePublish?: boolean
71+
forceRegistry?: boolean
72+
skipNpmPackages?: boolean
73+
tag?: string
74+
}
75+
76+
async function publishComplex(options: PublishOptions = {}): Promise<boolean> {
6377
const {
6478
force = false,
6579
forcePublish = false,
@@ -194,13 +208,23 @@ async function main(): Promise<void> {
194208
}
195209

196210
// Publish using complex flow (delegates to package-npm-publish script)
197-
const publishSuccess = await publishComplex({
198-
force: values.force,
199-
forcePublish: values['force-publish'],
200-
forceRegistry: values['force-registry'],
201-
skipNpmPackages: values['skip-npm-packages'],
202-
tag: values.tag,
203-
})
211+
const publishOpts: PublishOptions = {}
212+
if (values['force']) {
213+
publishOpts.force = true
214+
}
215+
if (values['force-publish']) {
216+
publishOpts.forcePublish = true
217+
}
218+
if (values['force-registry']) {
219+
publishOpts.forceRegistry = true
220+
}
221+
if (values['skip-npm-packages']) {
222+
publishOpts.skipNpmPackages = true
223+
}
224+
if (values['tag']) {
225+
publishOpts.tag = values['tag'] as string
226+
}
227+
const publishSuccess = await publishComplex(publishOpts)
204228

205229
if (!publishSuccess && !values.force) {
206230
logger.error('Publish failed')

0 commit comments

Comments
 (0)