diff --git a/.config/tsconfig.check.json b/.config/tsconfig.check.json index e93c38c8d..1416f8f2d 100644 --- a/.config/tsconfig.check.json +++ b/.config/tsconfig.check.json @@ -5,6 +5,7 @@ }, "include": [ "../packages/cli/src/**/*.mts", + "../packages/cli/src/**/*.d.ts", "../packages/cli/*.config.mts", "../packages/cli/.config/*.mts" ], diff --git a/.github/workflows/provenance.yml b/.github/workflows/provenance.yml index 90c4f35d8..1bbc3bfb6 100644 --- a/.github/workflows/provenance.yml +++ b/.github/workflows/provenance.yml @@ -63,7 +63,7 @@ jobs: - name: Generate platform matrix id: matrix run: | - MATRIX=$(node scripts/get-platform-matrix.mjs) + MATRIX=$(node scripts/get-platform-matrix.mts) echo "matrix=$MATRIX" >> $GITHUB_OUTPUT - name: Upload CLI bundle @@ -195,7 +195,7 @@ jobs: set -euo pipefail # Get platform targets from single source of truth. - PLATFORMS_STR=$(node scripts/get-platform-targets.mjs) + PLATFORMS_STR=$(node scripts/get-platform-targets.mts) read -ra PLATFORMS <<< "$PLATFORMS_STR" for target in "${PLATFORMS[@]}"; do @@ -227,7 +227,7 @@ jobs: if [ -n "$LIBC" ]; then LIBC_FLAG="--libc=$LIBC" fi - node scripts/prepublish-socketbin.mjs \ + node scripts/prepublish-socketbin.mts \ --platform="$PLATFORM" --arch="$ARCH" $LIBC_FLAG --prod \ --version="$VERSION" --method=sea @@ -253,7 +253,7 @@ jobs: TAG: ${{ steps.version.outputs.cli_tag }} run: | PKG_DIR="packages/package-builder/build/prod/out/cli" - node scripts/prepare-package-for-publish.mjs "$PKG_DIR" "$VERSION" + node scripts/prepare-package-for-publish.mts "$PKG_DIR" "$VERSION" cd "$PKG_DIR" npm publish --provenance --access public --no-git-checks --tag "$TAG" @@ -264,7 +264,7 @@ jobs: TAG: ${{ steps.version.outputs.cli_tag }} run: | PKG_DIR="packages/package-builder/build/prod/out/cli-with-sentry" - node scripts/prepare-package-for-publish.mjs "$PKG_DIR" "$VERSION" + node scripts/prepare-package-for-publish.mts "$PKG_DIR" "$VERSION" cd "$PKG_DIR" npm publish --provenance --access public --no-git-checks --tag "$TAG" @@ -276,7 +276,7 @@ jobs: TAG: ${{ steps.version.outputs.cli_tag }} run: | PKG_DIR="packages/package-builder/build/prod/out/socket" - node scripts/prepare-package-for-publish.mjs "$PKG_DIR" "$VERSION" + node scripts/prepare-package-for-publish.mts "$PKG_DIR" "$VERSION" cd "$PKG_DIR" npm publish --provenance --access public --no-git-checks --tag "$TAG" @@ -285,7 +285,7 @@ jobs: if: ${{ inputs.iocraft }} run: | echo "Downloading iocraft .node binaries for all platforms..." - node scripts/download-iocraft-binaries.mjs + node scripts/download-iocraft-binaries.mts # Copy iocraft binaries to package directories. - name: Copy iocraft binaries to packages @@ -295,7 +295,7 @@ jobs: set -euo pipefail # Get platform targets from single source of truth. - PLATFORMS_STR=$(node scripts/get-platform-targets.mjs) + PLATFORMS_STR=$(node scripts/get-platform-targets.mts) read -ra PLATFORMS <<< "$PLATFORMS_STR" for target in "${PLATFORMS[@]}"; do @@ -320,7 +320,7 @@ jobs: TAG: ${{ steps.version.outputs.iocraft_tag }} run: | PKG_DIR="packages/package-builder/build/prod/out/socketaddon-iocraft" - node scripts/prepare-package-for-publish.mjs "$PKG_DIR" "$VERSION" + node scripts/prepare-package-for-publish.mts "$PKG_DIR" "$VERSION" cd "$PKG_DIR" npm publish --provenance --access public --no-git-checks --tag "$TAG" @@ -334,7 +334,7 @@ jobs: set -euo pipefail # Get platform targets from single source of truth. - PLATFORMS_STR=$(node scripts/get-platform-targets.mjs) + PLATFORMS_STR=$(node scripts/get-platform-targets.mts) read -ra PLATFORMS <<< "$PLATFORMS_STR" for target in "${PLATFORMS[@]}"; do @@ -343,7 +343,7 @@ jobs: PKG_DIR="packages/package-builder/build/prod/out/socketaddon-iocraft-${target}" # Prepare package. - node scripts/prepare-package-for-publish.mjs "$PKG_DIR" "$VERSION" + node scripts/prepare-package-for-publish.mts "$PKG_DIR" "$VERSION" # Publish. cd "$PKG_DIR" diff --git a/.gitignore b/.gitignore index 0da4c3ab5..082c46aa5 100644 --- a/.gitignore +++ b/.gitignore @@ -136,3 +136,4 @@ packages/socket/*.png !docs/build/ !packages/package-builder/templates/**/*.d.ts !src/types/**/*.d.ts +!packages/*/src/types/**/*.d.ts diff --git a/package.json b/package.json index f871442b9..de7527ce7 100644 --- a/package.json +++ b/package.json @@ -9,31 +9,31 @@ }, "scripts": { "// Build": "", - "build": "node scripts/build.mjs", - "build:force": "node scripts/build.mjs --force", + "build": "node scripts/build.mts", + "build:force": "node scripts/build.mts --force", "build:cli": "pnpm --filter @socketsecurity/cli run build", "build:watch": "pnpm --filter @socketsecurity/cli run build:watch", "build:sea": "pnpm --filter @socketsecurity/cli run build:sea", "build:js": "pnpm --filter @socketsecurity/cli run build:js", "dev": "pnpm run build:watch", - "prebuild": "node scripts/setup.mjs --restore-cache --quiet", + "prebuild": "node scripts/setup.mts --restore-cache --quiet", "// Quality Checks": "", - "check": "node scripts/check.mjs", - "check:all": "node scripts/check.mjs --all", - "fix": "node scripts/fix.mjs", - "fix:all": "node scripts/fix.mjs --all", - "lint": "node scripts/lint.mjs", - "lint:all": "node scripts/lint.mjs --all", + "check": "node scripts/check.mts", + "check:all": "node scripts/check.mts --all", + "fix": "node scripts/fix.mts", + "fix:all": "node scripts/fix.mts --all", + "lint": "node scripts/lint.mts", + "lint:all": "node scripts/lint.mts --all", "format": "oxfmt --write .", "format:check": "oxfmt --check .", "// Claude": "", "claude": "pnpm --filter @socketsecurity/cli run claude --", "// Type Checking": "", - "type": "node scripts/type.mjs", - "type:all": "node scripts/type.mjs", + "type": "node scripts/type.mts", + "type:all": "node scripts/type.mts", "// Testing": "", - "test": "node scripts/test-monorepo.mjs", - "test:all": "node scripts/test-monorepo.mjs --all", + "test": "node scripts/test-monorepo.mts", + "test:all": "node scripts/test-monorepo.mts --all", "test:unit": "pnpm --filter @socketsecurity/cli run test:unit", "pretest:all": "pnpm run build", "testu": "pnpm --filter @socketsecurity/cli run test:unit:update", @@ -42,12 +42,12 @@ "security": "agentshield scan && { command -v zizmor >/dev/null && zizmor .github/ || echo 'zizmor not installed — run pnpm run setup to install'; }", "// Maintenance": "", "clean": "pnpm --filter \"./packages/**\" run clean", - "clean:cache": "node scripts/clean-cache.mjs", - "clean:cache:all": "node scripts/clean-cache.mjs --all", - "update": "node scripts/update.mjs", + "clean:cache": "node scripts/clean-cache.mts", + "clean:cache:all": "node scripts/clean-cache.mts --all", + "update": "node scripts/update.mts", "// Setup": "", - "setup": "node scripts/setup.mjs", - "postinstall": "node scripts/setup.mjs --install --quiet", + "setup": "node scripts/setup.mts", + "postinstall": "node scripts/setup.mts --install --quiet", "prepare": "husky", "pretest": "pnpm run build:cli" }, diff --git a/packages/build-infra/lib/esbuild-helpers.mjs b/packages/build-infra/lib/esbuild-helpers.mts similarity index 100% rename from packages/build-infra/lib/esbuild-helpers.mjs rename to packages/build-infra/lib/esbuild-helpers.mts diff --git a/packages/build-infra/lib/esbuild-plugin-unicode-transform.mjs b/packages/build-infra/lib/esbuild-plugin-unicode-transform.mts similarity index 88% rename from packages/build-infra/lib/esbuild-plugin-unicode-transform.mjs rename to packages/build-infra/lib/esbuild-plugin-unicode-transform.mts index 1f9c7d686..c54d8cf86 100644 --- a/packages/build-infra/lib/esbuild-plugin-unicode-transform.mjs +++ b/packages/build-infra/lib/esbuild-plugin-unicode-transform.mts @@ -12,7 +12,9 @@ * } */ -import { transformUnicodePropertyEscapes } from './unicode-property-escape-transform.mjs' +import type { PluginBuild, BuildResult } from 'esbuild' + +import { transformUnicodePropertyEscapes } from './unicode-property-escape-transform.mts' /** * Create esbuild plugin for Unicode property escape transformations. @@ -22,8 +24,8 @@ import { transformUnicodePropertyEscapes } from './unicode-property-escape-trans export function unicodeTransformPlugin() { return { name: 'unicode-transform', - setup(build) { - build.onEnd(result => { + setup(build: PluginBuild) { + build.onEnd((result: BuildResult) => { const outputs = result.outputFiles if (!outputs || !outputs.length) { return diff --git a/packages/build-infra/lib/extraction-cache.mjs b/packages/build-infra/lib/extraction-cache.mts similarity index 100% rename from packages/build-infra/lib/extraction-cache.mjs rename to packages/build-infra/lib/extraction-cache.mts diff --git a/packages/build-infra/lib/github-error-utils.mjs b/packages/build-infra/lib/github-error-utils.mts similarity index 100% rename from packages/build-infra/lib/github-error-utils.mjs rename to packages/build-infra/lib/github-error-utils.mts diff --git a/packages/build-infra/lib/github-releases.mjs b/packages/build-infra/lib/github-releases.mts similarity index 100% rename from packages/build-infra/lib/github-releases.mjs rename to packages/build-infra/lib/github-releases.mts diff --git a/packages/build-infra/lib/platform-targets.mjs b/packages/build-infra/lib/platform-targets.mts similarity index 98% rename from packages/build-infra/lib/platform-targets.mjs rename to packages/build-infra/lib/platform-targets.mts index 5d5d18410..579168bd1 100644 --- a/packages/build-infra/lib/platform-targets.mjs +++ b/packages/build-infra/lib/platform-targets.mts @@ -193,11 +193,9 @@ export function parsePlatformTarget(target) { // Handle standard platform-arch. const parts = target.split('-') if (parts.length === 2) { - let [platform, arch] = parts + const [rawPlatform, arch] = parts // Normalize 'win' to 'win32' for internal use. - if (platform === 'win') { - platform = 'win32' - } + const platform = rawPlatform === 'win' ? 'win32' : rawPlatform if (VALID_PLATFORMS.includes(platform) && VALID_ARCHS.includes(arch)) { return { arch, platform } } diff --git a/packages/build-infra/lib/unicode-property-escape-transform.mjs b/packages/build-infra/lib/unicode-property-escape-transform.mts similarity index 97% rename from packages/build-infra/lib/unicode-property-escape-transform.mjs rename to packages/build-infra/lib/unicode-property-escape-transform.mts index ca076581b..ec47e3d60 100644 --- a/packages/build-infra/lib/unicode-property-escape-transform.mjs +++ b/packages/build-infra/lib/unicode-property-escape-transform.mts @@ -13,7 +13,7 @@ import { getDefaultLogger } from '@socketsecurity/lib/logger' const logger = getDefaultLogger() const traverse = - typeof traverseImport === 'function' ? traverseImport : traverseImport.default + typeof traverseImport === 'function' ? traverseImport : (traverseImport as any).default /** * Map of Unicode property escapes to explicit character ranges. @@ -140,7 +140,7 @@ export const unicodePropertyMap = { /** * Check if a regex pattern has unsupported Unicode features. */ -function hasUnsupportedUnicodeFeatures(pattern) { +function hasUnsupportedUnicodeFeatures(pattern: string) { // Check for \u{} escapes (require /u flag). if (/\\u\{[0-9a-fA-F]+\}/.test(pattern)) { return true @@ -155,7 +155,7 @@ function hasUnsupportedUnicodeFeatures(pattern) { /** * Transform a regex pattern by replacing \p{Property} with character classes. */ -function transformRegexPattern(pattern) { +function transformRegexPattern(pattern: string) { let transformed = pattern // Replace \p{Property} with character class equivalents. @@ -176,7 +176,7 @@ function transformRegexPattern(pattern) { * When we get a pattern from Babel's StringLiteral.value, backslashes are interpreted. * But when writing back into source code, we need to re-escape them. */ -function escapeForStringLiteral(str) { +function escapeForStringLiteral(str: string) { return ( str // Backslash must be doubled. @@ -196,7 +196,7 @@ function escapeForStringLiteral(str) { * @param {string} content - Source code to transform * @returns {string} Transformed source code */ -export function transformUnicodePropertyEscapes(content) { +export function transformUnicodePropertyEscapes(content: string) { let ast try { ast = parse(content, { @@ -205,14 +205,14 @@ export function transformUnicodePropertyEscapes(content) { }) } catch (e) { // If parsing fails, return content unchanged. - logger.warn('Failed to parse code for Unicode transform:', e.message) + logger.warn('Failed to parse code for Unicode transform:', e instanceof Error ? e.message : e) return content } const s = new MagicString(content) traverse(ast, { - RegExpLiteral(path) { + RegExpLiteral(path: any) { const { node } = path const { flags, pattern } = node const { end, start } = node @@ -280,7 +280,7 @@ export function transformUnicodePropertyEscapes(content) { } }, - NewExpression(path) { + NewExpression(path: any) { const { node } = path // Check if this is a RegExp constructor. diff --git a/packages/build-infra/package.json b/packages/build-infra/package.json index fbcf59474..9a962386f 100644 --- a/packages/build-infra/package.json +++ b/packages/build-infra/package.json @@ -5,13 +5,13 @@ "private": true, "type": "module", "exports": { - "./lib/esbuild-helpers": "./lib/esbuild-helpers.mjs", - "./lib/esbuild-plugin-unicode-transform": "./lib/esbuild-plugin-unicode-transform.mjs", - "./lib/extraction-cache": "./lib/extraction-cache.mjs", - "./lib/github-error-utils": "./lib/github-error-utils.mjs", - "./lib/github-releases": "./lib/github-releases.mjs", - "./lib/platform-targets": "./lib/platform-targets.mjs", - "./lib/unicode-property-escape-transform": "./lib/unicode-property-escape-transform.mjs" + "./lib/esbuild-helpers": "./lib/esbuild-helpers.mts", + "./lib/esbuild-plugin-unicode-transform": "./lib/esbuild-plugin-unicode-transform.mts", + "./lib/extraction-cache": "./lib/extraction-cache.mts", + "./lib/github-error-utils": "./lib/github-error-utils.mts", + "./lib/github-releases": "./lib/github-releases.mts", + "./lib/platform-targets": "./lib/platform-targets.mts", + "./lib/unicode-property-escape-transform": "./lib/unicode-property-escape-transform.mts" }, "dependencies": { "@babel/parser": "catalog:", diff --git a/packages/cli/.config/esbuild.build.mjs b/packages/cli/.config/esbuild.build.mts similarity index 62% rename from packages/cli/.config/esbuild.build.mjs rename to packages/cli/.config/esbuild.build.mts index b662f3ee6..6f4d41950 100644 --- a/packages/cli/.config/esbuild.build.mjs +++ b/packages/cli/.config/esbuild.build.mts @@ -3,18 +3,20 @@ * Builds all variants (CLI bundle + entry point) in parallel. * * Usage: - * node .config/esbuild.build.mjs # Build all variants - * node .config/esbuild.build.mjs cli # Build CLI bundle - * node .config/esbuild.build.mjs index # Build entry point + * node .config/esbuild.build.mts # Build all variants + * node .config/esbuild.build.mts cli # Build CLI bundle + * node .config/esbuild.build.mts index # Build entry point */ import { fileURLToPath } from 'node:url' import { getDefaultLogger } from '@socketsecurity/lib/logger' -import { runBuild } from '../scripts/esbuild-utils.mjs' -import cliConfig from './esbuild.cli.mjs' -import indexConfig from './esbuild.index.mjs' +import type { BuildOptions } from 'esbuild' + +import { runBuild } from '../scripts/esbuild-utils.mts' +import cliConfig from './esbuild.cli.mts' +import indexConfig from './esbuild.index.mts' const logger = getDefaultLogger() @@ -34,13 +36,14 @@ async function main() { return } + const configRecord = CONFIGS as unknown as Record const targets = variant === 'all' - ? Object.entries(CONFIGS) - : [[variant, CONFIGS[variant]]] + ? Object.entries(configRecord) + : [[variant, configRecord[variant]]] const results = await Promise.allSettled( - targets.map(({ 0: name, 1: config }) => runBuild(config, name)), + targets.map(({ 0: name, 1: config }) => runBuild(config as BuildOptions, name as string)), ) const failed = results.filter(r => r.status === 'rejected') if (failed.length > 0) { diff --git a/packages/cli/.config/esbuild.cli.mjs b/packages/cli/.config/esbuild.cli.mts similarity index 85% rename from packages/cli/.config/esbuild.cli.mjs rename to packages/cli/.config/esbuild.cli.mts index f6ea19897..af30ac0f6 100644 --- a/packages/cli/.config/esbuild.cli.mjs +++ b/packages/cli/.config/esbuild.cli.mts @@ -8,6 +8,8 @@ import { existsSync } from 'node:fs' import path from 'node:path' import { fileURLToPath } from 'node:url' +import type { BuildOptions, PluginBuild, OnResolveArgs } from 'esbuild' + import { IMPORT_META_URL_BANNER } from 'build-infra/lib/esbuild-helpers' import { unicodeTransformPlugin } from 'build-infra/lib/esbuild-plugin-unicode-transform' @@ -16,7 +18,7 @@ import { envVarReplacementPlugin, getInlinedEnvVars, runBuild, -} from '../scripts/esbuild-utils.mjs' +} from '../scripts/esbuild-utils.mts' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const rootPath = path.join(__dirname, '..') @@ -26,7 +28,7 @@ const inlinedEnvVars = getInlinedEnvVars() // Matches ./external/, ../external/, ../../external/, etc. (forward and back slashes). const socketLibExternalPathRegExp = /^(?:\.[/\\]|(?:\.\.[/\\])+)external[/\\]/ -function findSocketLibPath(importerPath) { +function findSocketLibPath(importerPath: string) { const match = importerPath.match(/^(.*\/@socketsecurity\/lib)\b/) if (match) { return match[1] @@ -38,9 +40,11 @@ function findSocketLibPath(importerPath) { return null } -function resolveSocketLibExternal(socketLibPath, packageName) { +function resolveSocketLibExternal(socketLibPath: string, packageName: string) { if (packageName.startsWith('@')) { - const [scope, name] = packageName.split('/') + const parts = packageName.split('/') + const scope = parts[0]! + const name = parts[1]! const p = path.join(socketLibPath, 'dist', 'external', scope, `${name}.js`) return existsSync(p) ? p : null } @@ -54,7 +58,7 @@ function resolveSocketLibExternal(socketLibPath, packageName) { } -const config = { +const config: BuildOptions = { entryPoints: [path.join(rootPath, 'src/cli-dispatch.mts')], bundle: true, outfile: path.join(rootPath, 'build/cli.js'), @@ -87,8 +91,8 @@ const config = { envVarReplacementPlugin(inlinedEnvVars), { name: 'resolve-socket-lib-internals', - setup(build) { - function resolveConstant(args, strip) { + setup(build: PluginBuild) { + function resolveConstant(args: OnResolveArgs, strip: RegExp) { if (!args.importer.includes('/socket-lib/dist/')) { return null } @@ -105,15 +109,15 @@ const config = { return existsSync(p) ? { path: p } : null } - build.onResolve({ filter: /^\.\.\/constants\// }, args => + build.onResolve({ filter: /^\.\.\/constants\// }, (args: OnResolveArgs) => resolveConstant(args, /^\.\.\/constants\//), ) - build.onResolve({ filter: /^\.\.\/\.\.\/constants\// }, args => + build.onResolve({ filter: /^\.\.\/\.\.\/constants\// }, (args: OnResolveArgs) => resolveConstant(args, /^\.\.\/\.\.\/constants\//), ) - build.onResolve({ filter: socketLibExternalPathRegExp }, args => { + build.onResolve({ filter: socketLibExternalPathRegExp }, (args: OnResolveArgs) => { if (!args.importer.includes('@socketsecurity/lib/dist/')) { return null } @@ -128,7 +132,7 @@ const config = { return p ? { path: p } : null }) - build.onResolve({ filter: /^(@[^/]+\/[^/]+|[^./][^/]*)/ }, args => { + build.onResolve({ filter: /^(@[^/]+\/[^/]+|[^./][^/]*)/ }, (args: OnResolveArgs) => { if (!args.importer.includes('/socket-lib/dist/')) { return null } @@ -138,7 +142,7 @@ const config = { } const packageName = args.path.startsWith('@') ? args.path.split('/').slice(0, 2).join('/') - : args.path.split('/')[0] + : args.path.split('/')[0]! const p = resolveSocketLibExternal(socketLibPath, packageName) return p ? { path: p } : null }) @@ -147,9 +151,9 @@ const config = { { name: 'stub-problematic-packages', - setup(build) { + setup(build: PluginBuild) { // Stub iconv-lite and encoding to avoid bundling issues. - build.onResolve({ filter: /^(iconv-lite|encoding)(\/|$)/ }, args => { + build.onResolve({ filter: /^(iconv-lite|encoding)(\/|$)/ }, (args: OnResolveArgs) => { return { path: args.path, namespace: 'stub', @@ -167,10 +171,10 @@ const config = { { name: 'ignore-unsupported-files', - setup(build) { + setup(build: PluginBuild) { // Prevent bundling @npmcli/arborist from workspace node_modules. // This includes the main package and all subpaths like /lib/edge.js. - build.onResolve({ filter: /@npmcli\/arborist/ }, args => { + build.onResolve({ filter: /@npmcli\/arborist/ }, (args: OnResolveArgs) => { // Only redirect if it's not already coming from socket-lib's external bundle. if (args.importer.includes('/socket-lib/dist/')) { return null @@ -179,7 +183,7 @@ const config = { }) // Mark node-gyp as external (used by arborist but optionally resolved). - build.onResolve({ filter: /node-gyp/ }, args => { + build.onResolve({ filter: /node-gyp/ }, (args: OnResolveArgs) => { return { path: args.path, external: true } }) }, diff --git a/packages/cli/.config/esbuild.index.mjs b/packages/cli/.config/esbuild.index.mts similarity index 94% rename from packages/cli/.config/esbuild.index.mjs rename to packages/cli/.config/esbuild.index.mts index 3499d65c9..87c61db15 100644 --- a/packages/cli/.config/esbuild.index.mjs +++ b/packages/cli/.config/esbuild.index.mts @@ -9,7 +9,7 @@ import { fileURLToPath } from 'node:url' import { createIndexConfig, runBuild, -} from '../scripts/esbuild-utils.mjs' +} from '../scripts/esbuild-utils.mts' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const rootPath = path.resolve(__dirname, '..') diff --git a/packages/cli/package.json b/packages/cli/package.json index ba46ce8a8..7162bd0e2 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -18,21 +18,21 @@ "logo-light.png" ], "scripts": { - "build": "node --max-old-space-size=8192 --import=./scripts/load.mjs scripts/build.mjs", - "build:force": "node --max-old-space-size=8192 --import=./scripts/load.mjs scripts/build.mjs --force", - "build:watch": "node --max-old-space-size=8192 --import=./scripts/load.mjs scripts/build.mjs --watch", - "restore-cache": "node --import=./scripts/load.mjs scripts/restore-cache.mjs", - "build:sea": "node --max-old-space-size=8192 --import=./scripts/load.mjs scripts/build-sea.mjs", - "build:js": "node scripts/build-js.mjs", + "build": "node --max-old-space-size=8192 --import=./scripts/load.mts scripts/build.mts", + "build:force": "node --max-old-space-size=8192 --import=./scripts/load.mts scripts/build.mts --force", + "build:watch": "node --max-old-space-size=8192 --import=./scripts/load.mts scripts/build.mts --watch", + "restore-cache": "node --import=./scripts/load.mts scripts/restore-cache.mts", + "build:sea": "node --max-old-space-size=8192 --import=./scripts/load.mts scripts/build-sea.mts", + "build:js": "node scripts/build-js.mts", "dev:watch": "pnpm run build:watch", - "check": "node ../../scripts/check.mjs", + "check": "node ../../scripts/check.mts", "check-ci": "pnpm run check", "lint": "oxlint -c ../../.oxlintrc.json", "lint-ci": "pnpm run lint", "type": "tsc --noEmit", "type-ci": "pnpm run type", - "sync-checksums": "node scripts/sync-checksums.mjs", - "cover": "node --import=./scripts/load.mjs scripts/cover.mjs", + "sync-checksums": "node scripts/sync-checksums.mts", + "cover": "node --import=./scripts/load.mts scripts/cover.mts", "clean": "run-p -c --aggregate-output clean:*", "clean:binject": "del-cli 'build/binject'", "clean:cache": "del-cli '**/.cache'", @@ -49,22 +49,22 @@ "dev:npm": "cross-env SOCKET_CLI_MODE=npm node --experimental-strip-types src/cli-dispatch.mts", "dev:npx": "cross-env SOCKET_CLI_MODE=npx node --experimental-strip-types src/cli-dispatch.mts", "e2e-tests": "dotenvx -q run -f .env.test -- vitest run --config vitest.e2e.config.mts", - "e2e:js": "node scripts/e2e.mjs --js", - "e2e:sea": "node scripts/e2e.mjs --sea", - "e2e:all": "node scripts/e2e.mjs --all", + "e2e:js": "node scripts/e2e.mts --js", + "e2e:sea": "node scripts/e2e.mts --sea", + "e2e:all": "node scripts/e2e.mts --all", "test": "run-s check test:*", "test:prepare": "dotenvx -q run -f .env.test -- pnpm build && del-cli 'test/**/node_modules'", - "test:unit": "node --import=./scripts/load.mjs scripts/test-wrapper.mjs", - "test:unit:update": "node --import=./scripts/load.mjs scripts/test-wrapper.mjs --update", - "test:unit:coverage": "node --import=./scripts/load.mjs scripts/test-wrapper.mjs --coverage", - "test:validate": "node --import=./scripts/load.mjs scripts/validate-tests.mjs", + "test:unit": "node --import=./scripts/load.mts scripts/test-wrapper.mts", + "test:unit:update": "node --import=./scripts/load.mts scripts/test-wrapper.mts --update", + "test:unit:coverage": "node --import=./scripts/load.mts scripts/test-wrapper.mts --coverage", + "test:validate": "node --import=./scripts/load.mts scripts/validate-tests.mts", "test-ci": "run-s test:*", "test-pre-commit": "cross-env PRE_COMMIT=1 pnpm test", - "update": "node ../../scripts/update.mjs", - "verify": "node scripts/verify-package.mjs", - "wasm": "node scripts/wasm.mjs", - "wasm:build": "node scripts/wasm.mjs --build", - "wasm:download": "node scripts/wasm.mjs --download" + "update": "node ../../scripts/update.mts", + "verify": "node scripts/verify-package.mts", + "wasm": "node scripts/wasm.mts", + "wasm:build": "node scripts/wasm.mts --build", + "wasm:download": "node scripts/wasm.mts --download" }, "devDependencies": { "@babel/generator": "catalog:", diff --git a/packages/cli/scripts/build-js.mjs b/packages/cli/scripts/build-js.mts similarity index 92% rename from packages/cli/scripts/build-js.mjs rename to packages/cli/scripts/build-js.mts index 8dfdc7c9e..ceec839fe 100644 --- a/packages/cli/scripts/build-js.mjs +++ b/packages/cli/scripts/build-js.mts @@ -16,7 +16,7 @@ async function main() { logger.step('Building CLI bundle') const buildResult = await spawn( 'node', - ['--max-old-space-size=8192', '.config/esbuild.build.mjs', 'cli'], + ['--max-old-space-size=8192', '.config/esbuild.build.mts', 'cli'], { stdio: 'inherit' }, ) if (!buildResult) { @@ -36,7 +36,7 @@ async function main() { logger.step('Validating bundle') const validateResult = await spawn( 'node', - ['scripts/validate-bundle.mjs'], + ['scripts/validate-bundle.mts'], { stdio: 'inherit' }, ) if (validateResult.code !== 0) { diff --git a/packages/cli/scripts/build-sea.mjs b/packages/cli/scripts/build-sea.mts similarity index 98% rename from packages/cli/scripts/build-sea.mjs rename to packages/cli/scripts/build-sea.mts index 4b0091873..ec99e1a3b 100644 --- a/packages/cli/scripts/build-sea.mjs +++ b/packages/cli/scripts/build-sea.mts @@ -21,13 +21,13 @@ import { fileURLToPath } from 'node:url' import { getDefaultLogger } from '@socketsecurity/lib/logger' import { parsePlatformArgs } from 'build-infra/lib/platform-targets' -import { getSocketbinBinaryPath } from 'package-builder/scripts/paths.mjs' +import { getSocketbinBinaryPath } from 'package-builder/scripts/paths.mts' -import { buildTarget } from './sea-build-utils/orchestration.mjs' +import { buildTarget } from './sea-build-utils/orchestration.mts' import { getBuildTargets, getDefaultNodeVersion, -} from './sea-build-utils/targets.mjs' +} from './sea-build-utils/targets.mts' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const rootPath = path.join(__dirname, '..') diff --git a/packages/cli/scripts/build.mjs b/packages/cli/scripts/build.mts similarity index 97% rename from packages/cli/scripts/build.mjs rename to packages/cli/scripts/build.mts index e85991aa8..9386a5d6c 100644 --- a/packages/cli/scripts/build.mjs +++ b/packages/cli/scripts/build.mts @@ -107,7 +107,7 @@ async function main() { // Start esbuild in watch mode. const watchResult = await spawn( 'node', - [...NODE_MEMORY_FLAGS, '.config/esbuild.cli.mjs', '--watch'], + [...NODE_MEMORY_FLAGS, '.config/esbuild.cli.mts', '--watch'], { shell: WIN32, stdio: 'inherit', @@ -157,11 +157,11 @@ async function main() { } const parallelPrep = await Promise.allSettled([ - spawn('node', ['scripts/generate-packages.mjs'], { + spawn('node', ['scripts/generate-packages.mts'], { shell: WIN32, stdio: 'inherit', }).then(result => ({ name: 'Generate Packages', result })), - spawn('node', [...NODE_MEMORY_FLAGS, 'scripts/download-assets.mjs'], { + spawn('node', [...NODE_MEMORY_FLAGS, 'scripts/download-assets.mts'], { shell: WIN32, stdio: 'inherit', }).then(result => ({ name: 'Download Assets', result })), @@ -213,7 +213,7 @@ async function main() { const buildResult = await spawn( 'node', - [...NODE_MEMORY_FLAGS, '.config/esbuild.build.mjs', 'all'], + [...NODE_MEMORY_FLAGS, '.config/esbuild.build.mts', 'all'], { shell: WIN32, stdio: 'inherit', diff --git a/packages/cli/scripts/constants/build.mjs b/packages/cli/scripts/constants/build.mts similarity index 100% rename from packages/cli/scripts/constants/build.mjs rename to packages/cli/scripts/constants/build.mts diff --git a/packages/cli/scripts/constants/env.mjs b/packages/cli/scripts/constants/env.mts similarity index 100% rename from packages/cli/scripts/constants/env.mjs rename to packages/cli/scripts/constants/env.mts diff --git a/packages/cli/scripts/constants/external-tools-platforms.mjs b/packages/cli/scripts/constants/external-tools-platforms.mts similarity index 100% rename from packages/cli/scripts/constants/external-tools-platforms.mjs rename to packages/cli/scripts/constants/external-tools-platforms.mts diff --git a/packages/cli/scripts/constants/packages.mjs b/packages/cli/scripts/constants/packages.mts similarity index 100% rename from packages/cli/scripts/constants/packages.mjs rename to packages/cli/scripts/constants/packages.mts diff --git a/packages/cli/scripts/constants/paths.mjs b/packages/cli/scripts/constants/paths.mts similarity index 98% rename from packages/cli/scripts/constants/paths.mjs rename to packages/cli/scripts/constants/paths.mts index a47e5f8ce..c9549340e 100644 --- a/packages/cli/scripts/constants/paths.mjs +++ b/packages/cli/scripts/constants/paths.mts @@ -9,7 +9,7 @@ import { PACKAGE_JSON, PNPM_LOCK_YAML, SOCKET_REGISTRY_PACKAGE_NAME, -} from './packages.mjs' +} from './packages.mts' // Compute root path from this file's location. const __dirname = path.dirname(fileURLToPath(import.meta.url)) diff --git a/packages/cli/scripts/constants/platform-mappings.mjs b/packages/cli/scripts/constants/platform-mappings.mts similarity index 100% rename from packages/cli/scripts/constants/platform-mappings.mjs rename to packages/cli/scripts/constants/platform-mappings.mts diff --git a/packages/cli/scripts/constants/versions.mjs b/packages/cli/scripts/constants/versions.mts similarity index 100% rename from packages/cli/scripts/constants/versions.mjs rename to packages/cli/scripts/constants/versions.mts diff --git a/packages/cli/scripts/cover.mjs b/packages/cli/scripts/cover.mts similarity index 99% rename from packages/cli/scripts/cover.mjs rename to packages/cli/scripts/cover.mts index 3e5630da9..23461d250 100644 --- a/packages/cli/scripts/cover.mjs +++ b/packages/cli/scripts/cover.mts @@ -3,7 +3,7 @@ * Standardized across all socket-* repositories. * * Usage: - * node scripts/cover.mjs [options] + * node scripts/cover.mts [options] * * Options: * --quiet Suppress progress output diff --git a/packages/cli/scripts/download-assets.mjs b/packages/cli/scripts/download-assets.mts similarity index 96% rename from packages/cli/scripts/download-assets.mjs rename to packages/cli/scripts/download-assets.mts index 5e512f95b..4e642896a 100644 --- a/packages/cli/scripts/download-assets.mjs +++ b/packages/cli/scripts/download-assets.mts @@ -3,10 +3,10 @@ * Downloads and extracts all required assets from socket-btm GitHub releases. * * Usage: - * node scripts/download-assets.mjs [asset-names...] [options] - * node scripts/download-assets.mjs # Download all assets (parallel) - * node scripts/download-assets.mjs models # Download specific assets (parallel) - * node scripts/download-assets.mjs --no-parallel # Download all assets (sequential) + * node scripts/download-assets.mts [asset-names...] [options] + * node scripts/download-assets.mts # Download all assets (parallel) + * node scripts/download-assets.mts models # Download specific assets (parallel) + * node scripts/download-assets.mts --no-parallel # Download all assets (sequential) * * Assets: * binject - Binary injection tool diff --git a/packages/cli/scripts/e2e.mjs b/packages/cli/scripts/e2e.mts similarity index 95% rename from packages/cli/scripts/e2e.mjs rename to packages/cli/scripts/e2e.mts index d6d5a7b61..57f4a2715 100644 --- a/packages/cli/scripts/e2e.mjs +++ b/packages/cli/scripts/e2e.mts @@ -13,7 +13,7 @@ import { WIN32 } from '@socketsecurity/lib/constants/platform' import { getDefaultLogger } from '@socketsecurity/lib/logger' import { spawn } from '@socketsecurity/lib/spawn' -import { EnvironmentVariables } from './environment-variables.mjs' +import { EnvironmentVariables } from './environment-variables.mts' const logger = getDefaultLogger() @@ -147,7 +147,7 @@ async function runVitest(binaryType) { { env: { ...process.env, - // Automatically enable tests when explicitly running e2e.mjs. + // Automatically enable tests when explicitly running e2e.mts. RUN_E2E_TESTS: '1', // Load external tool versions (INLINED_* env vars). ...externalToolVersions, @@ -170,9 +170,9 @@ async function main() { logger.error('Invalid or missing flag') logger.log('') logger.log('Usage:') - logger.log(' node scripts/e2e.mjs --js # Test JS binary') - logger.log(' node scripts/e2e.mjs --sea # Test SEA binary') - logger.log(' node scripts/e2e.mjs --all # Test all binaries') + logger.log(' node scripts/e2e.mts --js # Test JS binary') + logger.log(' node scripts/e2e.mts --sea # Test SEA binary') + logger.log(' node scripts/e2e.mts --all # Test all binaries') logger.log('') throw new Error('Invalid or missing flag') } diff --git a/packages/cli/scripts/environment-variables.mjs b/packages/cli/scripts/environment-variables.mts similarity index 96% rename from packages/cli/scripts/environment-variables.mjs rename to packages/cli/scripts/environment-variables.mts index 6fcec9ae6..850dbfd6a 100644 --- a/packages/cli/scripts/environment-variables.mjs +++ b/packages/cli/scripts/environment-variables.mts @@ -3,11 +3,11 @@ * Single source of truth for all inlined environment variables. * * This module consolidates environment variable loading that was previously duplicated between: - * - esbuild-utils.mjs (full build-time inlining with 18 variables) - * - test-wrapper.mjs (partial test environment with 4 variables) + * - esbuild-utils.mts (full build-time inlining with 18 variables) + * - test-wrapper.mts (partial test environment with 4 variables) * * Usage: - * import { EnvironmentVariables } from './environment-variables.mjs' + * import { EnvironmentVariables } from './environment-variables.mts' * const vars = EnvironmentVariables.load() * const defines = EnvironmentVariables.getDefineEntries(vars) * const testVars = EnvironmentVariables.getTestVariables(vars) @@ -19,7 +19,7 @@ import path from 'node:path' import { randomUUID } from 'node:crypto' import { fileURLToPath } from 'node:url' -import { getPackageOutDir } from 'package-builder/scripts/paths.mjs' +import { getPackageOutDir } from 'package-builder/scripts/paths.mts' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const rootPath = path.join(__dirname, '..') @@ -64,7 +64,7 @@ export class EnvironmentVariables { /** * Helper to get external tool version with validation. */ - function getExternalToolVersion(key, field = 'version') { + function getExternalToolVersion(key: string, field = 'version') { const tool = externalTools[key] if (!tool) { throw new Error( @@ -187,11 +187,11 @@ export class EnvironmentVariables { * @param {Object} [vars] - Pre-loaded variables (optional, will load if not provided) * @returns {Record} Object with env var names as keys and JSON-stringified values */ - static getDefineEntries(vars) { + static getDefineEntries(vars?: Record) { const envVars = vars || EnvironmentVariables.load() // Convert all values to JSON-stringified format for esbuild. - const defines = {} + const defines: Record = {} for (const [key, value] of Object.entries(envVars)) { defines[key] = JSON.stringify(value) } diff --git a/packages/cli/scripts/esbuild-utils.mjs b/packages/cli/scripts/esbuild-utils.mts similarity index 88% rename from packages/cli/scripts/esbuild-utils.mjs rename to packages/cli/scripts/esbuild-utils.mts index 9b31bf0a0..0d2c0c6ac 100644 --- a/packages/cli/scripts/esbuild-utils.mjs +++ b/packages/cli/scripts/esbuild-utils.mts @@ -5,19 +5,16 @@ import { mkdirSync, writeFileSync } from 'node:fs' import path from 'node:path' -import { fileURLToPath } from 'node:url' +import type { BuildOptions, PluginBuild, BuildResult } from 'esbuild' import { build } from 'esbuild' import { getDefaultLogger } from '@socketsecurity/lib/logger' -import { EnvironmentVariables } from './environment-variables.mjs' +import { EnvironmentVariables } from './environment-variables.mts' const logger = getDefaultLogger() -const __dirname = path.dirname(fileURLToPath(import.meta.url)) -const rootPath = path.join(__dirname, '..') - /** * Create a standard index loader config. * @param {Object} options - Configuration options @@ -26,11 +23,11 @@ const rootPath = path.join(__dirname, '..') * @param {boolean} [options.minify=false] - Whether to minify output * @returns {Object} esbuild configuration object */ -export function createIndexConfig({ entryPoint, minify = false, outfile }) { +export function createIndexConfig({ entryPoint, minify = false, outfile }: { entryPoint: string; minify?: boolean; outfile: string }) { // Get inlined environment variables for build-time constant replacement. const inlinedEnvVars = getInlinedEnvVars() - const config = { + const config: BuildOptions = { banner: { js: '#!/usr/bin/env node', }, @@ -67,8 +64,8 @@ export function createIndexConfig({ entryPoint, minify = false, outfile }) { * Helper to create both dot and bracket notation define keys. * This ensures esbuild can replace both forms of process.env access. */ -export function createDefineEntries(envVars) { - const entries = {} +export function createDefineEntries(envVars: Record) { + const entries: Record = {} for (const [key, value] of Object.entries(envVars)) { // Dot notation: process.env.KEY entries[`process.env.${key}`] = value @@ -82,11 +79,11 @@ export function createDefineEntries(envVars) { * esbuild plugin to replace env vars after bundling (handles mangled identifiers). * This is necessary because esbuild's define doesn't catch all forms after minification. */ -export function envVarReplacementPlugin(envVars) { +export function envVarReplacementPlugin(envVars: Record) { return { name: 'env-var-replacement', - setup(build) { - build.onEnd(result => { + setup(build: PluginBuild) { + build.onEnd((result: BuildResult) => { const outputs = result.outputFiles if (!outputs || outputs.length === 0) { return @@ -135,7 +132,7 @@ export function getInlinedEnvVars() { * @param {Object} config - esbuild configuration object * @param {string} [description] - Description logged before/after build */ -export async function runBuild(config, description = 'Build') { +export async function runBuild(config: BuildOptions, description = 'Build') { try { if (description) { logger.info(`Building: ${description}`) diff --git a/packages/cli/scripts/generate-packages.mjs b/packages/cli/scripts/generate-packages.mts similarity index 93% rename from packages/cli/scripts/generate-packages.mjs rename to packages/cli/scripts/generate-packages.mts index 30832ea71..b885fe353 100644 --- a/packages/cli/scripts/generate-packages.mjs +++ b/packages/cli/scripts/generate-packages.mts @@ -15,8 +15,8 @@ const packageBuilderScripts = path.resolve( ) const scripts = [ - path.join(packageBuilderScripts, 'generate-cli-packages.mjs'), - path.join(packageBuilderScripts, 'generate-socketbin-packages.mjs'), + path.join(packageBuilderScripts, 'generate-cli-packages.mts'), + path.join(packageBuilderScripts, 'generate-socketbin-packages.mts'), ] for (const script of scripts) { diff --git a/packages/cli/scripts/integration.mjs b/packages/cli/scripts/integration.mts similarity index 93% rename from packages/cli/scripts/integration.mjs rename to packages/cli/scripts/integration.mts index 99b94acb2..f7d630558 100644 --- a/packages/cli/scripts/integration.mjs +++ b/packages/cli/scripts/integration.mts @@ -13,7 +13,7 @@ import { WIN32 } from '@socketsecurity/lib/constants/platform' import { getDefaultLogger } from '@socketsecurity/lib/logger' import { spawn } from '@socketsecurity/lib/spawn' -import { EnvironmentVariables } from './environment-variables.mjs' +import { EnvironmentVariables } from './environment-variables.mts' const logger = getDefaultLogger() const __dirname = path.dirname(fileURLToPath(import.meta.url)) @@ -109,7 +109,7 @@ async function runVitest(binaryType) { cwd: ROOT_DIR, env: { ...process.env, - // Automatically enable tests when explicitly running integration.mjs. + // Automatically enable tests when explicitly running integration.mts. RUN_INTEGRATION_TESTS: '1', // Inject external tool versions (normally inlined at build time). ...externalToolVersions, @@ -130,10 +130,10 @@ async function main() { logger.error('Invalid or missing flag') logger.log('') logger.log('Usage:') - logger.log(' node scripts/integration.mjs --js # Test JS distribution') - logger.log(' node scripts/integration.mjs --sea # Test SEA binary') + logger.log(' node scripts/integration.mts --js # Test JS distribution') + logger.log(' node scripts/integration.mts --sea # Test SEA binary') logger.log( - ' node scripts/integration.mjs --all # Test all distributions', + ' node scripts/integration.mts --all # Test all distributions', ) logger.log('') process.exitCode = 1 diff --git a/packages/cli/scripts/load.mjs b/packages/cli/scripts/load.mts similarity index 91% rename from packages/cli/scripts/load.mjs rename to packages/cli/scripts/load.mts index 2703b3a0b..9e12154d5 100644 --- a/packages/cli/scripts/load.mjs +++ b/packages/cli/scripts/load.mts @@ -5,7 +5,7 @@ * Previously handled local package aliasing, now isolated to use published packages only. * * Usage: - * node --import=./scripts/load.mjs script.mjs + * node --import=./scripts/load.mts script.mts */ // Export a no-op resolve function for compatibility. diff --git a/packages/cli/scripts/restore-cache.mjs b/packages/cli/scripts/restore-cache.mts similarity index 99% rename from packages/cli/scripts/restore-cache.mjs rename to packages/cli/scripts/restore-cache.mts index ec1952abc..eefb1086c 100644 --- a/packages/cli/scripts/restore-cache.mjs +++ b/packages/cli/scripts/restore-cache.mts @@ -3,7 +3,7 @@ * This is a nice-to-have optimization that speeds up first build after clone. * * Usage: - * node scripts/restore-cache.mjs [options] + * node scripts/restore-cache.mts [options] * * Options: * --quiet Suppress progress output. diff --git a/packages/cli/scripts/sea-build-utils/builder.mjs b/packages/cli/scripts/sea-build-utils/builder.mts similarity index 98% rename from packages/cli/scripts/sea-build-utils/builder.mjs rename to packages/cli/scripts/sea-build-utils/builder.mts index ee555b7ea..8fb7ff673 100644 --- a/packages/cli/scripts/sea-build-utils/builder.mjs +++ b/packages/cli/scripts/sea-build-utils/builder.mts @@ -19,9 +19,9 @@ import { detectMusl, downloadBinject, getLatestBinjectVersion, -} from '../utils/asset-manager-compat.mjs' -import { getRootPath, logger } from './downloads.mjs' -import { SOCKET_CLI_SEA_BUILD_DIR } from '../constants/paths.mjs' +} from '../utils/asset-manager-compat.mts' +import { getRootPath, logger } from './downloads.mts' +import { SOCKET_CLI_SEA_BUILD_DIR } from '../constants/paths.mts' // ============================================================================= // Section 1: SEA Configuration Generation. diff --git a/packages/cli/scripts/sea-build-utils/downloads.mjs b/packages/cli/scripts/sea-build-utils/downloads.mts similarity index 99% rename from packages/cli/scripts/sea-build-utils/downloads.mjs rename to packages/cli/scripts/sea-build-utils/downloads.mts index a7d81212c..cdffbba16 100644 --- a/packages/cli/scripts/sea-build-utils/downloads.mjs +++ b/packages/cli/scripts/sea-build-utils/downloads.mts @@ -22,8 +22,8 @@ import { getDefaultLogger } from '@socketsecurity/lib/logger' import { normalizePath } from '@socketsecurity/lib/paths/normalize' import { spawn } from '@socketsecurity/lib/spawn' -import { ARCH_MAP, PLATFORM_MAP } from '../constants/platform-mappings.mjs' -import { PLATFORM_MAP_TOOLS } from '../constants/external-tools-platforms.mjs' +import { ARCH_MAP, PLATFORM_MAP } from '../constants/platform-mappings.mts' +import { PLATFORM_MAP_TOOLS } from '../constants/external-tools-platforms.mts' // ============================================================================= // Section 1: Constants and Utilities. @@ -76,11 +76,11 @@ export function getRootPath() { * DEPRECATED: downloadNodeBinary and downloadBinject have been moved to AssetManager. * * Use the following instead: - * - import { downloadNodeBinary } from '../utils/asset-manager-compat.mjs' - * - import { downloadBinject } from '../utils/asset-manager-compat.mjs' + * - import { downloadNodeBinary } from '../utils/asset-manager-compat.mts' + * - import { downloadBinject } from '../utils/asset-manager-compat.mts' * - * These functions are now implemented in scripts/utils/asset-manager.mjs - * with backward-compatible wrappers in scripts/utils/asset-manager-compat.mjs. + * These functions are now implemented in scripts/utils/asset-manager.mts + * with backward-compatible wrappers in scripts/utils/asset-manager-compat.mts. * * The AssetManager provides unified binary download functionality with: * - Platform/arch normalization. @@ -278,7 +278,7 @@ export async function downloadExternalTools(platform, arch, isMusl = false) { } // Platform-specific binary mappings imported from centralized constant. - // See scripts/constants/external-tools-platforms.mjs for the full mapping. + // See scripts/constants/external-tools-platforms.mts for the full mapping. const toolsForPlatform = PLATFORM_MAP_TOOLS[platformArch] if (!toolsForPlatform) { diff --git a/packages/cli/scripts/sea-build-utils/npm-packages.mjs b/packages/cli/scripts/sea-build-utils/npm-packages.mts similarity index 99% rename from packages/cli/scripts/sea-build-utils/npm-packages.mjs rename to packages/cli/scripts/sea-build-utils/npm-packages.mts index 6f8a58623..df6ebaf47 100644 --- a/packages/cli/scripts/sea-build-utils/npm-packages.mjs +++ b/packages/cli/scripts/sea-build-utils/npm-packages.mts @@ -15,7 +15,7 @@ import { getDefaultLogger } from '@socketsecurity/lib/logger' import { normalizePath } from '@socketsecurity/lib/paths/normalize' import { spawn } from '@socketsecurity/lib/spawn' -import { getRootPath } from './downloads.mjs' +import { getRootPath } from './downloads.mts' const logger = getDefaultLogger() @@ -114,7 +114,7 @@ async function downloadNpmPackage(packageSpec, targetDir, expectedIntegrity) { * - synp: yarn.lock to package-lock.json converter. * * Note: socket-patch was migrated from npm to GitHub releases in v2.0.0. - * It's now bundled as a standalone Rust binary via downloads.mjs. + * It's now bundled as a standalone Rust binary via downloads.mts. * * Directory Structure: * / diff --git a/packages/cli/scripts/sea-build-utils/orchestration.mjs b/packages/cli/scripts/sea-build-utils/orchestration.mts similarity index 96% rename from packages/cli/scripts/sea-build-utils/orchestration.mjs rename to packages/cli/scripts/sea-build-utils/orchestration.mts index 40e26cab6..dcb9e3f6d 100644 --- a/packages/cli/scripts/sea-build-utils/orchestration.mjs +++ b/packages/cli/scripts/sea-build-utils/orchestration.mts @@ -9,9 +9,9 @@ import path from 'node:path' import { safeDelete, safeMkdir } from '@socketsecurity/lib/fs' import { normalizePath } from '@socketsecurity/lib/paths/normalize' -import { generateSeaConfig, injectSeaBlob } from './builder.mjs' -import { downloadNodeBinary } from '../utils/asset-manager-compat.mjs' -import { downloadExternalTools, logger } from './downloads.mjs' +import { generateSeaConfig, injectSeaBlob } from './builder.mts' +import { downloadNodeBinary } from '../utils/asset-manager-compat.mts' +import { downloadExternalTools, logger } from './downloads.mts' /** * Build a single SEA target for a specific platform. diff --git a/packages/cli/scripts/sea-build-utils/targets.mjs b/packages/cli/scripts/sea-build-utils/targets.mts similarity index 99% rename from packages/cli/scripts/sea-build-utils/targets.mjs rename to packages/cli/scripts/sea-build-utils/targets.mts index f9245c358..3d344d50e 100644 --- a/packages/cli/scripts/sea-build-utils/targets.mjs +++ b/packages/cli/scripts/sea-build-utils/targets.mts @@ -7,7 +7,7 @@ import { logTransientErrorHelp } from 'build-infra/lib/github-error-utils' import { httpRequest } from '@socketsecurity/lib/http-request' -import { getAuthHeaders } from './downloads.mjs' +import { getAuthHeaders } from './downloads.mts' /** * Generate build targets for different platforms. diff --git a/packages/cli/scripts/setup-iocraft-dev.mjs b/packages/cli/scripts/setup-iocraft-dev.mts similarity index 99% rename from packages/cli/scripts/setup-iocraft-dev.mjs rename to packages/cli/scripts/setup-iocraft-dev.mts index 11d134c4a..31bbba84f 100644 --- a/packages/cli/scripts/setup-iocraft-dev.mjs +++ b/packages/cli/scripts/setup-iocraft-dev.mts @@ -3,7 +3,7 @@ * @fileoverview Setup script to install iocraft dev build into node_modules for local testing. * * This simulates `npm install` of unpublished @socketaddon/iocraft packages. - * Run before testing TUI renderers locally: node scripts/setup-iocraft-dev.mjs + * Run before testing TUI renderers locally: node scripts/setup-iocraft-dev.mts */ import { copyFileSync, existsSync, mkdirSync } from 'node:fs' diff --git a/packages/cli/scripts/sync-checksums.mjs b/packages/cli/scripts/sync-checksums.mts similarity index 99% rename from packages/cli/scripts/sync-checksums.mjs rename to packages/cli/scripts/sync-checksums.mts index db070e00a..c2bad102e 100644 --- a/packages/cli/scripts/sync-checksums.mjs +++ b/packages/cli/scripts/sync-checksums.mts @@ -8,7 +8,7 @@ * 3. Updates bundle-tools.json with the new checksums * * Usage: - * node scripts/sync-checksums.mjs [--tool=] [--force] [--dry-run] + * node scripts/sync-checksums.mts [--tool=] [--force] [--dry-run] * * Options: * --tool= Only sync specific tool diff --git a/packages/cli/scripts/test-asset-manager.mjs b/packages/cli/scripts/test-asset-manager.mts similarity index 97% rename from packages/cli/scripts/test-asset-manager.mjs rename to packages/cli/scripts/test-asset-manager.mts index 7861380d3..31fb40679 100644 --- a/packages/cli/scripts/test-asset-manager.mjs +++ b/packages/cli/scripts/test-asset-manager.mts @@ -10,11 +10,11 @@ */ import { existsSync } from 'node:fs' -import { AssetManager } from './utils/asset-manager.mjs' +import { AssetManager } from './utils/asset-manager.mts' import { downloadBinject, downloadNodeBinary, -} from './utils/asset-manager-compat.mjs' +} from './utils/asset-manager-compat.mts' const logger = { error: (...args) => console.error('❌', ...args), diff --git a/packages/cli/scripts/test-download-external-tools.mjs b/packages/cli/scripts/test-download-external-tools.mts similarity index 100% rename from packages/cli/scripts/test-download-external-tools.mjs rename to packages/cli/scripts/test-download-external-tools.mts diff --git a/packages/cli/scripts/test-entry.mjs b/packages/cli/scripts/test-entry.mts similarity index 100% rename from packages/cli/scripts/test-entry.mjs rename to packages/cli/scripts/test-entry.mts diff --git a/packages/cli/scripts/test-iocraft-layout.mjs b/packages/cli/scripts/test-iocraft-layout.mts similarity index 97% rename from packages/cli/scripts/test-iocraft-layout.mjs rename to packages/cli/scripts/test-iocraft-layout.mts index afa1bdbe4..97b95e543 100644 --- a/packages/cli/scripts/test-iocraft-layout.mjs +++ b/packages/cli/scripts/test-iocraft-layout.mts @@ -5,7 +5,7 @@ * ISSUE: Layout properties (flex_direction, border_style, etc.) are not being * applied during rendering. * - * Run: node scripts/test-iocraft-layout.mjs + * Run: node scripts/test-iocraft-layout.mts */ import { createRequire } from 'node:module' diff --git a/packages/cli/scripts/test-sea.mjs b/packages/cli/scripts/test-sea.mts similarity index 97% rename from packages/cli/scripts/test-sea.mjs rename to packages/cli/scripts/test-sea.mts index 48a18f44b..b800977f3 100644 --- a/packages/cli/scripts/test-sea.mjs +++ b/packages/cli/scripts/test-sea.mts @@ -3,9 +3,9 @@ * Consolidates test-sea-standalone, test-sea-vfs, and test-sea-with-tools. * * Usage: - * node scripts/test-sea.mjs --mode=standalone - * node scripts/test-sea.mjs --mode=vfs - * node scripts/test-sea.mjs --mode=with-tools + * node scripts/test-sea.mts --mode=standalone + * node scripts/test-sea.mts --mode=vfs + * node scripts/test-sea.mts --mode=with-tools */ import { spawn as nodeSpawn } from 'node:child_process' @@ -75,7 +75,7 @@ async function loadToolPaths() { if (!existsSync(toolPathsFile)) { console.error(`Tool paths not found: ${toolPathsFile}`) - console.error('Run: node scripts/test-download-external-tools.mjs') + console.error('Run: node scripts/test-download-external-tools.mts') throw new Error('Tool paths not found') } @@ -86,7 +86,7 @@ async function loadToolPaths() { console.error( `Failed to parse tool paths from ${toolPathsFile}: ${e.message}`, ) - console.error('Run: node scripts/test-download-external-tools.mjs') + console.error('Run: node scripts/test-download-external-tools.mts') throw new Error('Invalid tool paths JSON') } return { platform, toolPaths: toolPathsData.tools } @@ -181,7 +181,7 @@ async function runStandaloneMode(platform, toolPaths) { const totalToolSize = await displayToolInfo(toolPaths) // Setup output. - const entryPoint = path.join(__dirname, 'test-entry.mjs') + const entryPoint = path.join(__dirname, 'test-entry.mts') const outputDir = path.join(__dirname, '../dist/sea-test') await fs.mkdir(outputDir, { recursive: true }) const outputPath = path.join(outputDir, `socket-standalone-${platform}`) @@ -300,7 +300,7 @@ async function runVfsMode(platform) { console.log('') // Create minimal SEA config (no assets). - const entryPoint = path.join(__dirname, 'test-entry.mjs') + const entryPoint = path.join(__dirname, 'test-entry.mts') const configPath = path.join(outputDir, 'sea-config-vfs.json') const blobPath = path.join(outputDir, 'sea-blob-vfs.blob') @@ -431,14 +431,14 @@ async function runWithToolsMode(platform, toolPaths) { // Dynamic import Socket modules. const { getDefaultLogger } = await import('@socketsecurity/lib/logger') - const { injectSeaBlob } = await import('./sea-build-utils/builder.mjs') - const { downloadNodeBinary } = await import('./sea-build-utils/downloads.mjs') + const { injectSeaBlob } = await import('./sea-build-utils/builder.mts') + const { downloadNodeBinary } = await import('./sea-build-utils/downloads.mts') const logger = getDefaultLogger() const totalToolSize = await displayToolInfo(toolPaths) // Setup output. - const entryPoint = path.join(__dirname, 'test-entry.mjs') + const entryPoint = path.join(__dirname, 'test-entry.mts') const outputDir = path.join(__dirname, '../dist/sea-test') await fs.mkdir(outputDir, { recursive: true }) const outputPath = path.join(outputDir, `socket-with-tools-${platform}`) diff --git a/packages/cli/scripts/test-wrapper.mjs b/packages/cli/scripts/test-wrapper.mts similarity index 98% rename from packages/cli/scripts/test-wrapper.mjs rename to packages/cli/scripts/test-wrapper.mts index fb7b9032f..6be04b8f9 100644 --- a/packages/cli/scripts/test-wrapper.mjs +++ b/packages/cli/scripts/test-wrapper.mts @@ -19,7 +19,7 @@ import { WIN32 } from '@socketsecurity/lib/constants/platform' import { getDefaultLogger } from '@socketsecurity/lib/logger' import { spawn } from '@socketsecurity/lib/spawn' -import { EnvironmentVariables } from './environment-variables.mjs' +import { EnvironmentVariables } from './environment-variables.mts' const logger = getDefaultLogger() const __dirname = path.dirname(fileURLToPath(import.meta.url)) diff --git a/packages/cli/scripts/utils/asset-manager-compat.mjs b/packages/cli/scripts/utils/asset-manager-compat.mts similarity index 94% rename from packages/cli/scripts/utils/asset-manager-compat.mjs rename to packages/cli/scripts/utils/asset-manager-compat.mts index 839f99eed..13f331c83 100644 --- a/packages/cli/scripts/utils/asset-manager-compat.mjs +++ b/packages/cli/scripts/utils/asset-manager-compat.mts @@ -1,6 +1,6 @@ /** * @fileoverview Backward-compatible wrappers for AssetManager. - * Maintains existing API signatures from sea-build-utils/downloads.mjs + * Maintains existing API signatures from sea-build-utils/downloads.mts * while using the unified AssetManager internally. * * Phase 1 of AssetManager migration - provides drop-in replacements @@ -9,7 +9,7 @@ import { existsSync, readFileSync } from 'node:fs' -import { AssetManager } from './asset-manager.mjs' +import { AssetManager } from './asset-manager.mts' // Cache for libc detection (only need to check once per process). let cachedLibc @@ -76,7 +76,7 @@ export function detectMusl() { /** * Shared AssetManager instance for all wrapper functions. - * Uses default configuration matching downloads.mjs behavior. + * Uses default configuration matching downloads.mts behavior. */ const assetManager = new AssetManager({ cacheEnabled: true, @@ -85,7 +85,7 @@ const assetManager = new AssetManager({ /** * Download Node.js binary for a specific platform (backward-compatible wrapper). - * Maintains exact API signature from sea-build-utils/downloads.mjs. + * Maintains exact API signature from sea-build-utils/downloads.mts. * * @param {string} version - Node.js version tag suffix (e.g., "20251213-7cf90d2"). * @param {string} platform - Platform identifier (darwin, linux, win32). @@ -110,7 +110,7 @@ export async function downloadNodeBinary(version, platform, arch, libc) { /** * Download binject binary for the current platform (backward-compatible wrapper). - * Maintains exact API signature from sea-build-utils/downloads.mjs. + * Maintains exact API signature from sea-build-utils/downloads.mts. * * @param {string} version - Binject version (e.g., "1.0.0"). * @returns {Promise} Absolute path to downloaded binject binary. @@ -140,7 +140,7 @@ export async function downloadBinject(version) { * Returns the version string (e.g., "1.0.0"). * * Note: This function currently delegates to the original implementation - * in sea-build-utils/downloads.mjs. Future enhancement: move to AssetManager. + * in sea-build-utils/downloads.mts. Future enhancement: move to AssetManager. * * @returns {Promise} Binject version string. * @throws {Error} When socket-btm releases cannot be fetched. @@ -153,6 +153,6 @@ export async function getLatestBinjectVersion() { // Delegate to original implementation for now. // TODO: Move this to AssetManager in Phase 4. const { getLatestBinjectVersion: getLatest } = - await import('../sea-build-utils/downloads.mjs') + await import('../sea-build-utils/downloads.mts') return getLatest() } diff --git a/packages/cli/scripts/utils/asset-manager.mjs b/packages/cli/scripts/utils/asset-manager.mts similarity index 99% rename from packages/cli/scripts/utils/asset-manager.mjs rename to packages/cli/scripts/utils/asset-manager.mts index 8b3657f17..45676eab5 100644 --- a/packages/cli/scripts/utils/asset-manager.mjs +++ b/packages/cli/scripts/utils/asset-manager.mts @@ -1,6 +1,6 @@ /** * @fileoverview Unified asset manager for socket-btm releases. - * Consolidates download functionality from download-assets.mjs and sea-build-utils/downloads.mjs. + * Consolidates download functionality from download-assets.mts and sea-build-utils/downloads.mts. * * This module provides: * - Unified binary downloads (node-smol, binject) @@ -23,7 +23,7 @@ import { safeDelete, safeMkdir } from '@socketsecurity/lib/fs' import { getDefaultLogger } from '@socketsecurity/lib/logger' import { normalizePath } from '@socketsecurity/lib/paths/normalize' -import { ARCH_MAP, PLATFORM_MAP } from '../constants/platform-mappings.mjs' +import { ARCH_MAP, PLATFORM_MAP } from '../constants/platform-mappings.mts' // ============================================================================= // Constants and Utilities. diff --git a/packages/cli/scripts/utils/changed-test-mapper.mjs b/packages/cli/scripts/utils/changed-test-mapper.mts similarity index 100% rename from packages/cli/scripts/utils/changed-test-mapper.mjs rename to packages/cli/scripts/utils/changed-test-mapper.mts diff --git a/packages/cli/scripts/utils/fs.mjs b/packages/cli/scripts/utils/fs.mts similarity index 100% rename from packages/cli/scripts/utils/fs.mjs rename to packages/cli/scripts/utils/fs.mts diff --git a/packages/cli/scripts/utils/patches.mjs b/packages/cli/scripts/utils/patches.mts similarity index 100% rename from packages/cli/scripts/utils/patches.mjs rename to packages/cli/scripts/utils/patches.mts diff --git a/packages/cli/scripts/utils/socket-btm-releases.mjs b/packages/cli/scripts/utils/socket-btm-releases.mts similarity index 100% rename from packages/cli/scripts/utils/socket-btm-releases.mjs rename to packages/cli/scripts/utils/socket-btm-releases.mts diff --git a/packages/cli/scripts/validate-bundle.mjs b/packages/cli/scripts/validate-bundle.mts similarity index 100% rename from packages/cli/scripts/validate-bundle.mjs rename to packages/cli/scripts/validate-bundle.mts diff --git a/packages/cli/scripts/validate-tests.mjs b/packages/cli/scripts/validate-tests.mts similarity index 100% rename from packages/cli/scripts/validate-tests.mjs rename to packages/cli/scripts/validate-tests.mts diff --git a/packages/cli/scripts/verify-package.mjs b/packages/cli/scripts/verify-package.mts similarity index 100% rename from packages/cli/scripts/verify-package.mjs rename to packages/cli/scripts/verify-package.mts diff --git a/packages/cli/scripts/wasm.mjs b/packages/cli/scripts/wasm.mts similarity index 95% rename from packages/cli/scripts/wasm.mjs rename to packages/cli/scripts/wasm.mts index 8386278fe..69b7ee470 100644 --- a/packages/cli/scripts/wasm.mjs +++ b/packages/cli/scripts/wasm.mts @@ -11,10 +11,10 @@ * - --help: Show this help message * * USAGE: - * node scripts/wasm.mjs --build # Production build - * node scripts/wasm.mjs --build --dev # Fast dev build - * node scripts/wasm.mjs --download - * node scripts/wasm.mjs --help + * node scripts/wasm.mts --build # Production build + * node scripts/wasm.mts --build --dev # Fast dev build + * node scripts/wasm.mts --download + * node scripts/wasm.mts --help */ import { existsSync, promises as fs } from 'node:fs' @@ -77,20 +77,20 @@ Commands: --help Show this help message Usage: - node scripts/wasm.mjs --build # Production build - node scripts/wasm.mjs --build --dev # Fast dev build - node scripts/wasm.mjs --download - node scripts/wasm.mjs --help + node scripts/wasm.mts --build # Production build + node scripts/wasm.mts --build --dev # Fast dev build + node scripts/wasm.mts --download + node scripts/wasm.mts --help Examples: # Build from source for production - node scripts/wasm.mjs --build + node scripts/wasm.mts --build # Fast dev build for iteration (3-5x faster) - node scripts/wasm.mjs --build --dev + node scripts/wasm.mts --build --dev # Download pre-built bundle (for quick setup) - node scripts/wasm.mjs --download + node scripts/wasm.mts --download Optimizations: - Cargo profiles: dev-wasm (fast) vs release (optimized) @@ -143,8 +143,8 @@ async function buildWasm() { } logger.info('╚═══════════════════════════════════════════════════╝\n') - const convertScript = path.join(__dirname, 'wasm', 'convert-codet5.mjs') - const buildScript = path.join(__dirname, 'wasm', 'build-unified-wasm.mjs') + const convertScript = path.join(__dirname, 'wasm', 'convert-codet5.mts') + const buildScript = path.join(__dirname, 'wasm', 'build-unified-wasm.mts') // Step 1: Convert CodeT5 models to INT4. logger.info('Step 1: Converting CodeT5 models to ONNX INT4...\n') @@ -255,7 +255,7 @@ async function getLatestWasmRelease() { logger.error(' Failed to fetch release information') logger.error(`Error: ${e.message}`) logger.error('\nTry building from source instead:') - logger.error('node scripts/wasm.mjs --build\n') + logger.error('node scripts/wasm.mts --build\n') throw new Error('Failed to fetch release information') } } @@ -290,7 +290,7 @@ async function downloadFile(url, outputPath, expectedSize) { logger.error(' Download failed') logger.error(`Error: ${e.message}`) logger.error('\nTry building from source instead:') - logger.error('node scripts/wasm.mjs --build\n') + logger.error('node scripts/wasm.mts --build\n') throw new Error('Download failed') } } diff --git a/packages/cli/src/types/babel-traverse.d.ts b/packages/cli/src/types/babel-traverse.d.ts new file mode 100644 index 000000000..46b73097f --- /dev/null +++ b/packages/cli/src/types/babel-traverse.d.ts @@ -0,0 +1,19 @@ +/** + * @fileoverview Type declarations for @babel/traverse module. + */ + +declare module '@babel/traverse' { + import type { File } from '@babel/types' + + interface NodePath { + node: T + } + + interface TraverseOptions { + [key: string]: ((path: NodePath) => void) | undefined + } + + function traverse(ast: File, opts: TraverseOptions): void + + export default traverse +} diff --git a/packages/cli/src/utils/dlx/vfs-extract.mts b/packages/cli/src/utils/dlx/vfs-extract.mts index e64955802..e6d235fc0 100644 --- a/packages/cli/src/utils/dlx/vfs-extract.mts +++ b/packages/cli/src/utils/dlx/vfs-extract.mts @@ -10,7 +10,7 @@ * * Build-time package preparation: * npm packages use @npmcli/arborist to download complete packages with node_modules/ - * and all production dependencies. See scripts/sea-build-utils/npm-packages.mjs: + * and all production dependencies. See scripts/sea-build-utils/npm-packages.mts: * * ```javascript * import { Arborist } from '@npmcli/arborist' diff --git a/packages/cli/vitest.config.mts b/packages/cli/vitest.config.mts index 5cd5ba707..691e311a6 100644 --- a/packages/cli/vitest.config.mts +++ b/packages/cli/vitest.config.mts @@ -3,7 +3,7 @@ import os from 'node:os' import { defineConfig } from 'vitest/config' const isCoverageEnabled = - process.env.npm_lifecycle_event === 'cover' || + process.env['npm_lifecycle_event'] === 'cover' || process.argv.includes('--coverage') // Detect if running in CI. @@ -41,7 +41,7 @@ export default defineConfig({ '**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build,eslint,prettier}.config.*', // Exclude E2E tests from regular test runs. '**/*.e2e.test.mts', - // Exclude integration tests (run separately via scripts/integration.mjs). + // Exclude integration tests (run separately via scripts/integration.mts). 'test/integration/**', // Exclude iocraft-dependent tests in CI (requires native module). ...(isCI @@ -56,37 +56,29 @@ export default defineConfig({ ], reporters: ['default'], setupFiles: ['./test/setup.mts'], - // Use threads for better performance + // Use threads for better performance. pool: 'threads', - poolOptions: { - threads: { - singleThread: false, - // Maximize parallel execution to offset isolate: true performance cost. - // Use CPU count for better hardware utilization. - // Reduce threads on macOS CI to prevent memory exhaustion (SIGABRT). - maxThreads: getMaxThreads(), - minThreads: isCoverageEnabled - ? 1 - : Math.min(2, Math.floor(getMaxThreads() / 2)), - // IMPORTANT: Changed to isolate: true to fix worker thread termination issues. - // - // Previous configuration (isolate: false) caused "Terminating worker thread" - // errors due to resource cleanup issues when tests completed. - // - // Tradeoff Analysis: - // - isolate: true = Full isolation, slower, but reliable cleanup - // - isolate: false = Shared worker context, faster, but cleanup issues - // - // We choose isolate: true to ensure: - // 1. Clean worker thread termination without errors - // 2. Reliable test execution in CI environments - // 3. Proper resource cleanup between tests - // 4. No "Terminating worker thread" errors - // - // Performance impact is acceptable for reliability. - isolate: true, - }, - }, + // Maximize parallel execution to offset isolate: true performance cost. + // Use CPU count for better hardware utilization. + // Reduce threads on macOS CI to prevent memory exhaustion (SIGABRT). + maxWorkers: getMaxThreads(), + // IMPORTANT: Changed to isolate: true to fix worker thread termination issues. + // + // Previous configuration (isolate: false) caused "Terminating worker thread" + // errors due to resource cleanup issues when tests completed. + // + // Tradeoff Analysis: + // - isolate: true = Full isolation, slower, but reliable cleanup + // - isolate: false = Shared worker context, faster, but cleanup issues + // + // We choose isolate: true to ensure: + // 1. Clean worker thread termination without errors + // 2. Reliable test execution in CI environments + // 3. Proper resource cleanup between tests + // 4. No "Terminating worker thread" errors + // + // Performance impact is acceptable for reliability. + isolate: true, testTimeout: 30_000, hookTimeout: 30_000, // Enable file-level parallelization for better performance. @@ -121,7 +113,6 @@ export default defineConfig({ '/test/**', ], include: ['src/**/*.mts', 'src/**/*.ts'], - all: true, clean: true, skipFull: false, ignoreClassMethods: ['constructor'], diff --git a/packages/cli/vitest.e2e.config.mts b/packages/cli/vitest.e2e.config.mts index a03c8a079..1bbdbe34e 100644 --- a/packages/cli/vitest.e2e.config.mts +++ b/packages/cli/vitest.e2e.config.mts @@ -20,15 +20,9 @@ export default defineConfig({ setupFiles: ['./test/setup.mts'], // Use threads for better performance. pool: 'threads', - poolOptions: { - threads: { - singleThread: false, - maxThreads: os.cpus().length, - minThreads: Math.min(4, os.cpus().length), - // E2E tests need full isolation for clean execution. - isolate: true, - }, - }, + maxWorkers: os.cpus().length, + // E2E tests need full isolation for clean execution. + isolate: true, // E2E tests need longer timeouts for spawning processes. testTimeout: 60_000, hookTimeout: 60_000, diff --git a/packages/cli/vitest.integration.config.mts b/packages/cli/vitest.integration.config.mts index 9782c3b48..2a3f903a2 100644 --- a/packages/cli/vitest.integration.config.mts +++ b/packages/cli/vitest.integration.config.mts @@ -19,14 +19,8 @@ export default defineConfig({ reporters: ['default'], setupFiles: ['./test/setup.mts'], pool: 'threads', - poolOptions: { - threads: { - singleThread: false, - maxThreads: os.cpus().length, - minThreads: Math.min(2, Math.floor(os.cpus().length / 2)), - isolate: true, - }, - }, + maxWorkers: os.cpus().length, + isolate: true, testTimeout: 60_000, // Integration tests may take longer. hookTimeout: 30_000, fileParallelism: true, diff --git a/packages/package-builder/package.json b/packages/package-builder/package.json index fd866d087..2bfb863d9 100644 --- a/packages/package-builder/package.json +++ b/packages/package-builder/package.json @@ -8,11 +8,11 @@ "./scripts/*": "./scripts/*" }, "scripts": { - "generate:all": "node scripts/generate-all.mjs", - "generate:cli": "node scripts/generate-cli-packages.mjs", - "generate:cli-sentry": "node scripts/generate-cli-sentry-package.mjs", - "generate:socketaddon": "node scripts/generate-socketaddon-packages.mjs", - "generate:socketbin": "node scripts/generate-socketbin-packages.mjs" + "generate:all": "node scripts/generate-all.mts", + "generate:cli": "node scripts/generate-cli-packages.mts", + "generate:cli-sentry": "node scripts/generate-cli-sentry-package.mts", + "generate:socketaddon": "node scripts/generate-socketaddon-packages.mts", + "generate:socketbin": "node scripts/generate-socketbin-packages.mts" }, "dependencies": { "@socketsecurity/lib": "catalog:", diff --git a/packages/package-builder/scripts/generate-all.mjs b/packages/package-builder/scripts/generate-all.mts similarity index 87% rename from packages/package-builder/scripts/generate-all.mjs rename to packages/package-builder/scripts/generate-all.mts index ba904ea20..8c2a6d6a2 100644 --- a/packages/package-builder/scripts/generate-all.mjs +++ b/packages/package-builder/scripts/generate-all.mts @@ -3,7 +3,7 @@ * Runs all package generation scripts in sequence. * * Usage: - * node scripts/generate-all.mjs. + * node scripts/generate-all.mts. */ import path from 'node:path' @@ -50,9 +50,9 @@ async function main() { logger.log('═'.repeat(50)) // Run all generation scripts in sequence. - await runScript('generate-cli-packages.mjs', 'CLI packages') - await runScript('generate-socketaddon-packages.mjs', 'Socketaddon packages') - await runScript('generate-socketbin-packages.mjs', 'Socketbin packages') + await runScript('generate-cli-packages.mts', 'CLI packages') + await runScript('generate-socketaddon-packages.mts', 'Socketaddon packages') + await runScript('generate-socketbin-packages.mts', 'Socketbin packages') logger.log('') logger.log('═'.repeat(50)) diff --git a/packages/package-builder/scripts/generate-cli-packages.mjs b/packages/package-builder/scripts/generate-cli-packages.mts similarity index 92% rename from packages/package-builder/scripts/generate-cli-packages.mjs rename to packages/package-builder/scripts/generate-cli-packages.mts index 047a49155..212f14b32 100644 --- a/packages/package-builder/scripts/generate-cli-packages.mjs +++ b/packages/package-builder/scripts/generate-cli-packages.mts @@ -3,7 +3,7 @@ * Creates the standard CLI, CLI-with-Sentry, and socket packages. * * Usage: - * node scripts/generate-cli-packages.mjs + * node scripts/generate-cli-packages.mts */ import { getDefaultLogger } from '@socketsecurity/lib/logger' @@ -13,8 +13,8 @@ import { CLI_TEMPLATE_DIR, SOCKET_TEMPLATE_DIR, getPackageOutDir, -} from './paths.mjs' -import { copyDirectory } from './utils.mjs' +} from './paths.mts' +import { copyDirectory } from './utils.mts' const logger = getDefaultLogger() diff --git a/packages/package-builder/scripts/generate-cli-sentry-package.mjs b/packages/package-builder/scripts/generate-cli-sentry-package.mts similarity index 92% rename from packages/package-builder/scripts/generate-cli-sentry-package.mjs rename to packages/package-builder/scripts/generate-cli-sentry-package.mts index f092ee38a..40d41c841 100644 --- a/packages/package-builder/scripts/generate-cli-sentry-package.mjs +++ b/packages/package-builder/scripts/generate-cli-sentry-package.mts @@ -4,7 +4,7 @@ * for publishing the CLI with Sentry telemetry integration. * * Usage: - * node scripts/generate-cli-sentry-package.mjs + * node scripts/generate-cli-sentry-package.mts */ import path from 'node:path' @@ -12,7 +12,7 @@ import { fileURLToPath } from 'node:url' import { getDefaultLogger } from '@socketsecurity/lib/logger' -import { copyDirectory } from './utils.mjs' +import { copyDirectory } from './utils.mts' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const generatePath = path.join(__dirname, '..') diff --git a/packages/package-builder/scripts/generate-socketaddon-packages.mjs b/packages/package-builder/scripts/generate-socketaddon-packages.mts similarity index 97% rename from packages/package-builder/scripts/generate-socketaddon-packages.mjs rename to packages/package-builder/scripts/generate-socketaddon-packages.mts index 03296fd3c..a002e9817 100644 --- a/packages/package-builder/scripts/generate-socketaddon-packages.mjs +++ b/packages/package-builder/scripts/generate-socketaddon-packages.mts @@ -4,7 +4,7 @@ * that will be used for native addon distribution via npm. * * Usage: - * node scripts/generate-socketaddon-packages.mjs + * node scripts/generate-socketaddon-packages.mts */ import { existsSync, promises as fs } from 'node:fs' @@ -18,8 +18,8 @@ import { getSocketaddonPackageDir, SOCKETADDON_MAIN_TEMPLATE_DIR, SOCKETADDON_TEMPLATE_DIR, -} from './paths.mjs' -import { processTemplate } from './utils.mjs' +} from './paths.mts' +import { processTemplate } from './utils.mts' const logger = getDefaultLogger() diff --git a/packages/package-builder/scripts/generate-socketbin-packages.mjs b/packages/package-builder/scripts/generate-socketbin-packages.mts similarity index 96% rename from packages/package-builder/scripts/generate-socketbin-packages.mjs rename to packages/package-builder/scripts/generate-socketbin-packages.mts index 3e3e002ee..ef5d2a0e1 100644 --- a/packages/package-builder/scripts/generate-socketbin-packages.mjs +++ b/packages/package-builder/scripts/generate-socketbin-packages.mts @@ -4,7 +4,7 @@ * that will be used for binary distribution via npm. * * Usage: - * node scripts/generate-socketbin-packages.mjs + * node scripts/generate-socketbin-packages.mts */ import { existsSync, promises as fs } from 'node:fs' @@ -13,8 +13,8 @@ import path from 'node:path' import { PLATFORM_CONFIGS } from 'build-infra/lib/platform-targets' import { getDefaultLogger } from '@socketsecurity/lib/logger' -import { getSocketbinPackageDir, SOCKETBIN_TEMPLATE_DIR } from './paths.mjs' -import { processTemplate } from './utils.mjs' +import { getSocketbinPackageDir, SOCKETBIN_TEMPLATE_DIR } from './paths.mts' +import { processTemplate } from './utils.mts' const logger = getDefaultLogger() diff --git a/packages/package-builder/scripts/paths.mjs b/packages/package-builder/scripts/paths.mts similarity index 88% rename from packages/package-builder/scripts/paths.mjs rename to packages/package-builder/scripts/paths.mts index 3f6458b7b..39996e8dc 100644 --- a/packages/package-builder/scripts/paths.mjs +++ b/packages/package-builder/scripts/paths.mts @@ -41,11 +41,11 @@ export function getBuildMode() { return 'prod' } // Check env var. - if (process.env.BUILD_MODE) { - return process.env.BUILD_MODE + if (process.env['BUILD_MODE']) { + return process.env['BUILD_MODE'] } // Default based on CI. - const isCI = process.env.CI === 'true' || process.env.CI === '1' + const isCI = process.env['CI'] === 'true' || process.env['CI'] === '1' return isCI ? 'prod' : 'dev' } @@ -66,7 +66,7 @@ export function getBuildOutDir(mode = getBuildMode()) { * @param {string} [mode] - Build mode (dev/prod), defaults to BUILD_MODE or CI detection. * @returns {string} Path to package output directory. */ -export function getPackageOutDir(packageName, mode = getBuildMode()) { +export function getPackageOutDir(packageName: string, mode = getBuildMode()) { return join(getBuildOutDir(mode), packageName) } @@ -80,7 +80,7 @@ export function getPackageOutDir(packageName, mode = getBuildMode()) { * @param {string} [mode] - Build mode (dev/prod), defaults to BUILD_MODE or CI detection. * @returns {string} Path to socketbin package directory. */ -export function getSocketbinPackageDir(platform, arch, libc, mode = getBuildMode()) { +export function getSocketbinPackageDir(platform: string, arch: string, libc?: string, mode = getBuildMode()) { // Normalize win32 → win for directory naming. const releasePlatform = platform === 'win32' ? 'win' : platform const muslSuffix = libc === 'musl' ? '-musl' : '' @@ -97,7 +97,7 @@ export function getSocketbinPackageDir(platform, arch, libc, mode = getBuildMode * @param {string} [mode] - Build mode (dev/prod), defaults to BUILD_MODE or CI detection. * @returns {string} Path to the socket binary. */ -export function getSocketbinBinaryPath(platform, arch, libc, mode = getBuildMode()) { +export function getSocketbinBinaryPath(platform: string, arch: string, libc?: string, mode = getBuildMode()) { // Accept both win and win32 for Windows detection. const binaryName = platform === 'win32' || platform === 'win' ? 'socket.exe' : 'socket' return join(getSocketbinPackageDir(platform, arch, libc, mode), binaryName) @@ -113,7 +113,7 @@ export function getSocketbinBinaryPath(platform, arch, libc, mode = getBuildMode * @param {string} [mode] - Build mode (dev/prod), defaults to BUILD_MODE or CI detection. * @returns {string} Path to socketaddon package directory. */ -export function getSocketaddonPackageDir(platform, arch, libc, mode = getBuildMode()) { +export function getSocketaddonPackageDir(platform: string, arch: string, libc?: string, mode = getBuildMode()) { // Normalize win32 → win for directory naming. const releasePlatform = platform === 'win32' ? 'win' : platform const muslSuffix = libc === 'musl' ? '-musl' : '' diff --git a/packages/package-builder/scripts/publish-socketaddon-placeholders.mjs b/packages/package-builder/scripts/publish-socketaddon-placeholders.mts similarity index 94% rename from packages/package-builder/scripts/publish-socketaddon-placeholders.mjs rename to packages/package-builder/scripts/publish-socketaddon-placeholders.mts index d268f6448..2375c3932 100644 --- a/packages/package-builder/scripts/publish-socketaddon-placeholders.mjs +++ b/packages/package-builder/scripts/publish-socketaddon-placeholders.mts @@ -6,20 +6,20 @@ * * Usage: * # Publish all packages - * node scripts/publish-socketaddon-placeholders.mjs - * node scripts/publish-socketaddon-placeholders.mjs --dry-run + * node scripts/publish-socketaddon-placeholders.mts + * node scripts/publish-socketaddon-placeholders.mts --dry-run * * # Publish specific packages - * node scripts/publish-socketaddon-placeholders.mjs --main - * node scripts/publish-socketaddon-placeholders.mjs --darwin-arm64 - * node scripts/publish-socketaddon-placeholders.mjs --linux-x64-musl - * node scripts/publish-socketaddon-placeholders.mjs --win-x64 + * node scripts/publish-socketaddon-placeholders.mts --main + * node scripts/publish-socketaddon-placeholders.mts --darwin-arm64 + * node scripts/publish-socketaddon-placeholders.mts --linux-x64-musl + * node scripts/publish-socketaddon-placeholders.mts --win-x64 * * # Publish multiple specific packages - * node scripts/publish-socketaddon-placeholders.mjs --main --darwin-arm64 --linux-x64 + * node scripts/publish-socketaddon-placeholders.mts --main --darwin-arm64 --linux-x64 * * # List available packages - * node scripts/publish-socketaddon-placeholders.mjs --list + * node scripts/publish-socketaddon-placeholders.mts --list */ import { spawnSync } from 'node:child_process' @@ -372,10 +372,10 @@ function listAvailablePackages() { logger.log('') logger.log('Examples:') - logger.log(' node scripts/publish-socketaddon-placeholders.mjs --main') - logger.log(' node scripts/publish-socketaddon-placeholders.mjs --darwin-arm64 --dry-run') - logger.log(' node scripts/publish-socketaddon-placeholders.mjs --main --linux-x64 --linux-x64-musl') - logger.log(' node scripts/publish-socketaddon-placeholders.mjs # publish all') + logger.log(' node scripts/publish-socketaddon-placeholders.mts --main') + logger.log(' node scripts/publish-socketaddon-placeholders.mts --darwin-arm64 --dry-run') + logger.log(' node scripts/publish-socketaddon-placeholders.mts --main --linux-x64 --linux-x64-musl') + logger.log(' node scripts/publish-socketaddon-placeholders.mts # publish all') logger.log('') } diff --git a/packages/package-builder/scripts/utils.mjs b/packages/package-builder/scripts/utils.mts similarity index 100% rename from packages/package-builder/scripts/utils.mjs rename to packages/package-builder/scripts/utils.mts diff --git a/packages/package-builder/scripts/utils/prepare-package.mjs b/packages/package-builder/scripts/utils/prepare-package.mts similarity index 100% rename from packages/package-builder/scripts/utils/prepare-package.mjs rename to packages/package-builder/scripts/utils/prepare-package.mts diff --git a/packages/package-builder/templates/cli-package/.config/esbuild.cli.mjs b/packages/package-builder/templates/cli-package/.config/esbuild.cli.mts similarity index 83% rename from packages/package-builder/templates/cli-package/.config/esbuild.cli.mjs rename to packages/package-builder/templates/cli-package/.config/esbuild.cli.mts index d21e6efa9..23ee3e1e4 100644 --- a/packages/package-builder/templates/cli-package/.config/esbuild.cli.mjs +++ b/packages/package-builder/templates/cli-package/.config/esbuild.cli.mts @@ -6,9 +6,9 @@ import path from 'node:path' import { fileURLToPath } from 'node:url' -import { runBuild } from '../../cli/scripts/esbuild-utils.mjs' +import { runBuild } from '../../cli/scripts/esbuild-utils.mts' -import baseConfig from '../../cli/.config/esbuild.cli.mjs' +import baseConfig from '../../cli/.config/esbuild.cli.mts' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const rootPath = path.join(__dirname, '..') diff --git a/packages/package-builder/templates/cli-package/.config/esbuild.index.mjs b/packages/package-builder/templates/cli-package/.config/esbuild.index.mts similarity index 93% rename from packages/package-builder/templates/cli-package/.config/esbuild.index.mjs rename to packages/package-builder/templates/cli-package/.config/esbuild.index.mts index 1c3973c24..ecf0ed95d 100644 --- a/packages/package-builder/templates/cli-package/.config/esbuild.index.mjs +++ b/packages/package-builder/templates/cli-package/.config/esbuild.index.mts @@ -9,7 +9,7 @@ import { fileURLToPath } from 'node:url' import { createIndexConfig, runBuild, -} from '../../cli/scripts/esbuild-utils.mjs' +} from '../../cli/scripts/esbuild-utils.mts' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const rootPath = path.resolve(__dirname, '..') diff --git a/packages/package-builder/templates/cli-package/package.json b/packages/package-builder/templates/cli-package/package.json index 7c1474373..0f6051e4a 100644 --- a/packages/package-builder/templates/cli-package/package.json +++ b/packages/package-builder/templates/cli-package/package.json @@ -22,10 +22,10 @@ "logo-light.png" ], "scripts": { - "build": "node scripts/build.mjs", + "build": "node scripts/build.mts", "clean:dist": "del-cli 'dist'", "test": "vitest run", - "verify": "node scripts/verify-package.mjs" + "verify": "node scripts/verify-package.mts" }, "devDependencies": { "build-infra": "workspace:*", diff --git a/packages/package-builder/templates/cli-package/scripts/build.mjs b/packages/package-builder/templates/cli-package/scripts/build.mts similarity index 94% rename from packages/package-builder/templates/cli-package/scripts/build.mjs rename to packages/package-builder/templates/cli-package/scripts/build.mts index b8934ed59..42a8aa779 100644 --- a/packages/package-builder/templates/cli-package/scripts/build.mjs +++ b/packages/package-builder/templates/cli-package/scripts/build.mts @@ -24,7 +24,7 @@ async function main() { // Build CLI bundle. logger.info('Building CLI bundle...') - let result = await spawn('node', ['.config/esbuild.cli.mjs'], { + let result = await spawn('node', ['.config/esbuild.cli.mts'], { shell: WIN32, stdio: 'inherit', cwd: rootPath, @@ -41,7 +41,7 @@ async function main() { // Build index loader. logger.info('Building index loader...') - result = await spawn('node', ['.config/esbuild.index.mjs'], { + result = await spawn('node', ['.config/esbuild.index.mts'], { shell: WIN32, stdio: 'inherit', cwd: rootPath, diff --git a/packages/package-builder/templates/cli-package/scripts/verify-package.mjs b/packages/package-builder/templates/cli-package/scripts/verify-package.mts similarity index 100% rename from packages/package-builder/templates/cli-package/scripts/verify-package.mjs rename to packages/package-builder/templates/cli-package/scripts/verify-package.mts diff --git a/packages/package-builder/templates/cli-package/test/package.test.mjs b/packages/package-builder/templates/cli-package/test/package.test.mts similarity index 95% rename from packages/package-builder/templates/cli-package/test/package.test.mjs rename to packages/package-builder/templates/cli-package/test/package.test.mts index 9b4f50523..ebf5d8075 100644 --- a/packages/package-builder/templates/cli-package/test/package.test.mjs +++ b/packages/package-builder/templates/cli-package/test/package.test.mts @@ -34,7 +34,7 @@ describe('@socketsecurity/cli-with-sentry package', () => { ) expect(pkgJson.scripts).toBeDefined() - expect(pkgJson.scripts.build).toBe('node scripts/build.mjs') + expect(pkgJson.scripts.build).toBe('node scripts/build.mts') expect(pkgJson.scripts['clean:dist']).toBeDefined() }) @@ -116,21 +116,21 @@ describe('@socketsecurity/cli-with-sentry package', () => { }) it('should have esbuild config', () => { - const esbuildPath = path.join(configDir, 'esbuild.cli-sentry.build.mjs') + const esbuildPath = path.join(configDir, 'esbuild.cli-sentry.build.mts') expect(existsSync(esbuildPath)).toBe(true) }) it('esbuild config should import base config', async () => { - const esbuildPath = path.join(configDir, 'esbuild.cli-sentry.build.mjs') + const esbuildPath = path.join(configDir, 'esbuild.cli-sentry.build.mts') const content = await fs.readFile(esbuildPath, 'utf-8') expect(content).toContain( - "import baseConfig from '../../cli/.config/esbuild.cli.mjs'", + "import baseConfig from '../../cli/.config/esbuild.cli.mts'", ) }) it('esbuild config should enable Sentry build flag', async () => { - const esbuildPath = path.join(configDir, 'esbuild.cli-sentry.build.mjs') + const esbuildPath = path.join(configDir, 'esbuild.cli-sentry.build.mts') const content = await fs.readFile(esbuildPath, 'utf-8') expect(content).toContain('INLINED_SENTRY_BUILD') @@ -138,14 +138,14 @@ describe('@socketsecurity/cli-with-sentry package', () => { }) it('esbuild config should use CLI dispatch with Sentry entry point', async () => { - const esbuildPath = path.join(configDir, 'esbuild.cli-sentry.build.mjs') + const esbuildPath = path.join(configDir, 'esbuild.cli-sentry.build.mts') const content = await fs.readFile(esbuildPath, 'utf-8') expect(content).toContain('cli-dispatch-with-sentry.mts') }) it('esbuild config should call build() when run', async () => { - const esbuildPath = path.join(configDir, 'esbuild.cli-sentry.build.mjs') + const esbuildPath = path.join(configDir, 'esbuild.cli-sentry.build.mts') const content = await fs.readFile(esbuildPath, 'utf-8') expect(content).toContain('build(config)') @@ -158,18 +158,18 @@ describe('@socketsecurity/cli-with-sentry package', () => { expect(existsSync(scriptsDir)).toBe(true) }) - it('should have build.mjs script', () => { - const buildPath = path.join(scriptsDir, 'build.mjs') + it('should have build.mts script', () => { + const buildPath = path.join(scriptsDir, 'build.mts') expect(existsSync(buildPath)).toBe(true) }) - it('build.mjs should be valid JavaScript', async () => { - const buildPath = path.join(scriptsDir, 'build.mjs') + it('build.mts should be valid JavaScript', async () => { + const buildPath = path.join(scriptsDir, 'build.mts') const content = await fs.readFile(buildPath, 'utf-8') expect(content).toBeTruthy() expect(content).toContain('import') - expect(content).toContain('esbuild.cli-sentry.build.mjs') + expect(content).toContain('esbuild.cli-sentry.build.mts') }) }) diff --git a/packages/package-builder/templates/cli-sentry-package/.config/esbuild.cli-sentry.build.mjs b/packages/package-builder/templates/cli-sentry-package/.config/esbuild.cli-sentry.build.mts similarity index 88% rename from packages/package-builder/templates/cli-sentry-package/.config/esbuild.cli-sentry.build.mjs rename to packages/package-builder/templates/cli-sentry-package/.config/esbuild.cli-sentry.build.mts index 45d37f3db..42304a210 100644 --- a/packages/package-builder/templates/cli-sentry-package/.config/esbuild.cli-sentry.build.mjs +++ b/packages/package-builder/templates/cli-sentry-package/.config/esbuild.cli-sentry.build.mts @@ -6,9 +6,9 @@ import path from 'node:path' import { fileURLToPath } from 'node:url' -import { runBuild } from '../../cli/scripts/esbuild-utils.mjs' +import { runBuild } from '../../cli/scripts/esbuild-utils.mts' -import baseConfig from '../../cli/.config/esbuild.cli.mjs' +import baseConfig from '../../cli/.config/esbuild.cli.mts' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const rootPath = path.join(__dirname, '..') diff --git a/packages/package-builder/templates/cli-sentry-package/.config/esbuild.index.mjs b/packages/package-builder/templates/cli-sentry-package/.config/esbuild.index.mts similarity index 94% rename from packages/package-builder/templates/cli-sentry-package/.config/esbuild.index.mjs rename to packages/package-builder/templates/cli-sentry-package/.config/esbuild.index.mts index 5932b1e45..62652f17c 100644 --- a/packages/package-builder/templates/cli-sentry-package/.config/esbuild.index.mjs +++ b/packages/package-builder/templates/cli-sentry-package/.config/esbuild.index.mts @@ -9,7 +9,7 @@ import { fileURLToPath } from 'node:url' import { createIndexConfig, runBuild, -} from '../../cli/scripts/esbuild-utils.mjs' +} from '../../cli/scripts/esbuild-utils.mts' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const rootPath = path.resolve(__dirname, '..') diff --git a/packages/package-builder/templates/cli-sentry-package/package.json b/packages/package-builder/templates/cli-sentry-package/package.json index fe5929c56..b3cb4837e 100644 --- a/packages/package-builder/templates/cli-sentry-package/package.json +++ b/packages/package-builder/templates/cli-sentry-package/package.json @@ -22,10 +22,10 @@ "logo-light.png" ], "scripts": { - "build": "node scripts/build.mjs", + "build": "node scripts/build.mts", "clean:dist": "del-cli 'dist'", "test": "vitest run", - "verify": "node scripts/verify-package.mjs" + "verify": "node scripts/verify-package.mts" }, "dependencies": { "@sentry/node": "catalog:" diff --git a/packages/package-builder/templates/cli-sentry-package/scripts/build.mjs b/packages/package-builder/templates/cli-sentry-package/scripts/build.mts similarity index 96% rename from packages/package-builder/templates/cli-sentry-package/scripts/build.mjs rename to packages/package-builder/templates/cli-sentry-package/scripts/build.mts index 53ede83a6..c6c30de6f 100644 --- a/packages/package-builder/templates/cli-sentry-package/scripts/build.mjs +++ b/packages/package-builder/templates/cli-sentry-package/scripts/build.mts @@ -24,7 +24,7 @@ async function main() { // Build CLI bundle. logger.info('Building CLI bundle...') - let result = await spawn('node', ['.config/esbuild.cli-sentry.build.mjs'], { + let result = await spawn('node', ['.config/esbuild.cli-sentry.build.mts'], { shell: WIN32, stdio: 'inherit', cwd: rootPath, @@ -39,7 +39,7 @@ async function main() { // Build index loader. logger.info('Building index loader...') - result = await spawn('node', ['.config/esbuild.index.mjs'], { + result = await spawn('node', ['.config/esbuild.index.mts'], { shell: WIN32, stdio: 'inherit', cwd: rootPath, diff --git a/packages/package-builder/templates/cli-sentry-package/scripts/verify-package.mjs b/packages/package-builder/templates/cli-sentry-package/scripts/verify-package.mts similarity index 100% rename from packages/package-builder/templates/cli-sentry-package/scripts/verify-package.mjs rename to packages/package-builder/templates/cli-sentry-package/scripts/verify-package.mts diff --git a/packages/package-builder/templates/cli-sentry-package/test/package.test.mjs b/packages/package-builder/templates/cli-sentry-package/test/package.test.mts similarity index 95% rename from packages/package-builder/templates/cli-sentry-package/test/package.test.mjs rename to packages/package-builder/templates/cli-sentry-package/test/package.test.mts index e23dd6dc0..65f347326 100644 --- a/packages/package-builder/templates/cli-sentry-package/test/package.test.mjs +++ b/packages/package-builder/templates/cli-sentry-package/test/package.test.mts @@ -34,7 +34,7 @@ describe('@socketsecurity/cli-with-sentry package', () => { ) expect(pkgJson.scripts).toBeDefined() - expect(pkgJson.scripts.build).toBe('node scripts/build.mjs') + expect(pkgJson.scripts.build).toBe('node scripts/build.mts') expect(pkgJson.scripts['clean:dist']).toBeDefined() }) @@ -116,21 +116,21 @@ describe('@socketsecurity/cli-with-sentry package', () => { }) it('should have esbuild config', () => { - const esbuildPath = path.join(configDir, 'esbuild.cli-sentry.build.mjs') + const esbuildPath = path.join(configDir, 'esbuild.cli-sentry.build.mts') expect(existsSync(esbuildPath)).toBe(true) }) it('esbuild config should import base config', async () => { - const esbuildPath = path.join(configDir, 'esbuild.cli-sentry.build.mjs') + const esbuildPath = path.join(configDir, 'esbuild.cli-sentry.build.mts') const content = await fs.readFile(esbuildPath, 'utf-8') expect(content).toContain( - "import baseConfig from '../../cli/.config/esbuild.cli.mjs'", + "import baseConfig from '../../cli/.config/esbuild.cli.mts'", ) }) it('esbuild config should enable Sentry build flag', async () => { - const esbuildPath = path.join(configDir, 'esbuild.cli-sentry.build.mjs') + const esbuildPath = path.join(configDir, 'esbuild.cli-sentry.build.mts') const content = await fs.readFile(esbuildPath, 'utf-8') expect(content).toContain('INLINED_SENTRY_BUILD') @@ -138,14 +138,14 @@ describe('@socketsecurity/cli-with-sentry package', () => { }) it('esbuild config should use CLI dispatch with Sentry entry point', async () => { - const esbuildPath = path.join(configDir, 'esbuild.cli-sentry.build.mjs') + const esbuildPath = path.join(configDir, 'esbuild.cli-sentry.build.mts') const content = await fs.readFile(esbuildPath, 'utf-8') expect(content).toContain('cli-dispatch-with-sentry.mts') }) it('esbuild config should call build() when run', async () => { - const esbuildPath = path.join(configDir, 'esbuild.cli-sentry.build.mjs') + const esbuildPath = path.join(configDir, 'esbuild.cli-sentry.build.mts') const content = await fs.readFile(esbuildPath, 'utf-8') expect(content).toContain('build(config)') @@ -158,18 +158,18 @@ describe('@socketsecurity/cli-with-sentry package', () => { expect(existsSync(scriptsDir)).toBe(true) }) - it('should have build.mjs script', () => { - const buildPath = path.join(scriptsDir, 'build.mjs') + it('should have build.mts script', () => { + const buildPath = path.join(scriptsDir, 'build.mts') expect(existsSync(buildPath)).toBe(true) }) - it('build.mjs should be valid JavaScript', async () => { - const buildPath = path.join(scriptsDir, 'build.mjs') + it('build.mts should be valid JavaScript', async () => { + const buildPath = path.join(scriptsDir, 'build.mts') const content = await fs.readFile(buildPath, 'utf-8') expect(content).toBeTruthy() expect(content).toContain('import') - expect(content).toContain('esbuild.cli-sentry.build.mjs') + expect(content).toContain('esbuild.cli-sentry.build.mts') }) }) diff --git a/packages/package-builder/test-iocraft-package.mjs b/packages/package-builder/test-iocraft-package.mts similarity index 100% rename from packages/package-builder/test-iocraft-package.mjs rename to packages/package-builder/test-iocraft-package.mts diff --git a/scripts/babel/babel-plugin-inline-const-enum.mjs b/scripts/babel/babel-plugin-inline-const-enum.mts similarity index 100% rename from scripts/babel/babel-plugin-inline-const-enum.mjs rename to scripts/babel/babel-plugin-inline-const-enum.mts diff --git a/scripts/babel/babel-plugin-inline-process-env.mjs b/scripts/babel/babel-plugin-inline-process-env.mts similarity index 100% rename from scripts/babel/babel-plugin-inline-process-env.mjs rename to scripts/babel/babel-plugin-inline-process-env.mts diff --git a/scripts/babel/babel-plugin-strict-mode.mjs b/scripts/babel/babel-plugin-strict-mode.mts similarity index 100% rename from scripts/babel/babel-plugin-strict-mode.mjs rename to scripts/babel/babel-plugin-strict-mode.mts diff --git a/scripts/babel/babel-plugin-strip-debug.mjs b/scripts/babel/babel-plugin-strip-debug.mts similarity index 100% rename from scripts/babel/babel-plugin-strip-debug.mjs rename to scripts/babel/babel-plugin-strip-debug.mts diff --git a/scripts/babel/babel-plugin-with-intl-none.mjs b/scripts/babel/babel-plugin-with-intl-none.mts similarity index 100% rename from scripts/babel/babel-plugin-with-intl-none.mjs rename to scripts/babel/babel-plugin-with-intl-none.mts diff --git a/scripts/babel/transform-set-proto-plugin.mjs b/scripts/babel/transform-set-proto-plugin.mts similarity index 100% rename from scripts/babel/transform-set-proto-plugin.mjs rename to scripts/babel/transform-set-proto-plugin.mts diff --git a/scripts/babel/transform-url-parse-plugin.mjs b/scripts/babel/transform-url-parse-plugin.mts similarity index 100% rename from scripts/babel/transform-url-parse-plugin.mjs rename to scripts/babel/transform-url-parse-plugin.mts diff --git a/scripts/build.mjs b/scripts/build.mts similarity index 90% rename from scripts/build.mjs rename to scripts/build.mts index aac22bebd..77b191db7 100755 --- a/scripts/build.mjs +++ b/scripts/build.mts @@ -33,15 +33,15 @@ import { PLATFORM_TARGETS, formatPlatformTarget, parsePlatformTarget, -} from '../packages/build-infra/lib/platform-targets.mjs' +} from '../packages/build-infra/lib/platform-targets.mts' const logger = getDefaultLogger() const __filename = fileURLToPath(import.meta.url) const __dirname = path.dirname(__filename) const rootDir = path.resolve(__dirname, '..') -const TARGET_PACKAGES = { - __proto__: null, +const TARGET_PACKAGES: Record = { + __proto__: null as unknown as string, all: './packages/**', cli: '@socketsecurity/cli', 'cli-sentry': '@socketsecurity/cli-with-sentry', @@ -50,10 +50,39 @@ const TARGET_PACKAGES = { socket: 'socket', } +interface BuildPackageConfig { + name: string + filter: string + outputCheck: string +} + +interface BuildResult { + success: boolean + skipped: boolean +} + +interface BuildTargetResult { + duration: string + success: boolean + target: string +} + +interface ParsedArgs { + arch: string | undefined + buildArgs: string[] + force: boolean + help: boolean + parallel: boolean + platform: string | undefined + platforms: boolean + target: string | undefined + targets: string[] +} + /** * Build configuration for each package in the default build order. */ -const BUILD_PACKAGES = [ +const BUILD_PACKAGES: BuildPackageConfig[] = [ { name: 'CLI Package', filter: '@socketsecurity/cli', @@ -64,24 +93,24 @@ const BUILD_PACKAGES = [ /** * Parse command line arguments. */ -function parseArgs() { +function parseArgs(): ParsedArgs { const args = process.argv.slice(2) - let target - let targets = [] + let target: string | undefined + let targets: string[] = [] let platforms = false let parallel = false let force = false let help = false - let platform - let arch - const buildArgs = [] + let platform: string | undefined + let arch: string | undefined + const buildArgs: string[] = [] for (let i = 0; i < args.length; i++) { - const arg = args[i] + const arg = args[i]! if (arg === '--target' && i + 1 < args.length) { target = args[++i] } else if (arg === '--targets' && i + 1 < args.length) { - targets = args[++i].split(',').map(t => t.trim()) + targets = args[++i]!.split(',').map(t => t.trim()) } else if (arg === '--platform' && i + 1 < args.length) { platform = args[++i] } else if (arg.startsWith('--platform=')) { @@ -124,7 +153,7 @@ function parseArgs() { /** * Display help message. */ -function showHelp() { +function showHelp(): void { logger.log('') logger.log(`${colors.blue('Socket CLI Build System')}`) logger.log('') @@ -182,7 +211,7 @@ function showHelp() { * Check if a package needs to be built. * Returns true if build is needed, false if can skip. */ -function needsBuild(pkg, force) { +function needsBuild(pkg: BuildPackageConfig, force: boolean): boolean { if (force) { return true } @@ -199,7 +228,10 @@ function needsBuild(pkg, force) { /** * Build a single package. */ -async function buildPackage(pkg, force) { +async function buildPackage( + pkg: BuildPackageConfig, + force: boolean, +): Promise { const skip = !needsBuild(pkg, force) if (skip) { @@ -237,7 +269,7 @@ async function buildPackage(pkg, force) { /** * Build SEA binary for current platform. */ -async function buildCurrentPlatformSea() { +async function buildCurrentPlatformSea(): Promise<{ success: boolean }> { const { arch, platform } = await import('node:os') const currentPlatform = platform() const currentArch = arch() @@ -277,7 +309,7 @@ async function buildCurrentPlatformSea() { /** * Run the default smart build with caching. */ -async function runSmartBuild(force) { +async function runSmartBuild(force: boolean): Promise { logger.log('') logger.log('='.repeat(60)) logger.log(`${colors.blue('Socket CLI Build System')}`) @@ -362,12 +394,12 @@ async function runSmartBuild(force) { /** * Build SEA binary for a specific platform. - * - * @param {string} platform - Platform (darwin, linux, win32). - * @param {string} arch - Architecture (arm64, x64). - * @param {string} [libc] - Optional libc (musl). */ -async function buildPlatformSea(platform, arch, libc) { +async function buildPlatformSea( + platform: string, + arch: string, + libc: string | undefined, +): Promise<{ success: boolean }> { const targetName = formatPlatformTarget(platform, arch, libc) logger.log('') @@ -409,7 +441,10 @@ async function buildPlatformSea(platform, arch, libc) { /** * Run a targeted build for a specific package or platform. */ -async function runTargetedBuild(target, buildArgs) { +async function runTargetedBuild( + target: string, + buildArgs: string[], +): Promise { // Check if this is a platform target (e.g., darwin-arm64). const platformInfo = parsePlatformTarget(target) if (platformInfo) { @@ -458,7 +493,10 @@ async function runTargetedBuild(target, buildArgs) { /** * Build a single target (for parallel/sequential builds). */ -async function buildTarget(target, buildArgs) { +async function buildTarget( + target: string, + buildArgs: string[], +): Promise { const startTime = Date.now() logger.log(`${colors.cyan('→')} [${target}] Starting build...`) @@ -533,7 +571,10 @@ async function buildTarget(target, buildArgs) { /** * Run multiple targeted builds in parallel. */ -async function runParallelBuilds(targetsToBuild, buildArgs) { +async function runParallelBuilds( + targetsToBuild: string[], + buildArgs: string[], +): Promise { logger.log('') logger.log('='.repeat(60)) logger.log( @@ -601,7 +642,10 @@ async function runParallelBuilds(targetsToBuild, buildArgs) { /** * Run multiple targeted builds sequentially. */ -async function runSequentialBuilds(targetsToBuild, buildArgs) { +async function runSequentialBuilds( + targetsToBuild: string[], + buildArgs: string[], +): Promise { logger.log('') logger.log('='.repeat(60)) logger.log( @@ -673,7 +717,7 @@ async function runSequentialBuilds(targetsToBuild, buildArgs) { /** * Main build function. */ -async function main() { +async function main(): Promise { const opts = parseArgs() if (opts.help) { @@ -705,9 +749,10 @@ async function main() { await runSmartBuild(opts.force) } -main().catch(e => { +main().catch((e: unknown) => { + const message = e instanceof Error ? e.message : String(e) logger.error('') - logger.error(`${colors.red('✗')} Unexpected error: ${e.message}`) + logger.error(`${colors.red('✗')} Unexpected error: ${message}`) logger.error('') process.exitCode = 1 }) diff --git a/scripts/check.mjs b/scripts/check.mts similarity index 90% rename from scripts/check.mjs rename to scripts/check.mts index 017d669ae..4f844beba 100644 --- a/scripts/check.mjs +++ b/scripts/check.mts @@ -20,17 +20,34 @@ import { getAffectedPackages, getPackagesWithScript, runAcrossPackages, -} from './utils/monorepo-helper.mjs' +} from './utils/monorepo-helper.mts' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const scriptsDir = __dirname const logger = getDefaultLogger() +import type { PackageInfo } from './utils/monorepo-helper.mts' + +interface CheckOptions { + all?: boolean + changed?: boolean + staged?: boolean + quiet?: boolean +} + +interface FilesToCheckResult { + mode: string + packages: PackageInfo[] + reason: string | null +} + /** * Get files to check and determine affected packages. */ -async function getFilesToCheck(options) { +async function getFilesToCheck( + options: CheckOptions, +): Promise { const { all, changed, staged } = options // If --all, return all packages. @@ -43,7 +60,7 @@ async function getFilesToCheck(options) { } // Get changed files. - let changedFiles = [] + let changedFiles: string[] = [] let mode = 'changed' if (staged) { @@ -80,7 +97,7 @@ async function getFilesToCheck(options) { /** * Run Oxlint check via lint script on affected packages. */ -async function runOxlintCheck(options = {}) { +async function runOxlintCheck(options: CheckOptions = {}): Promise { const { quiet = false } = options // Get files to check and affected packages. @@ -107,7 +124,7 @@ async function runOxlintCheck(options = {}) { /** * Run TypeScript type check across all packages with type script. */ -async function runTypeCheck(options = {}) { +async function runTypeCheck(options: { quiet?: boolean } = {}): Promise { const { quiet = false } = options const packages = getPackagesWithScript('type') @@ -130,7 +147,7 @@ async function runTypeCheck(options = {}) { ) } -async function main() { +async function main(): Promise { try { // Parse arguments. const { values } = parseArgs({ @@ -226,7 +243,7 @@ async function main() { } const validateResult = await spawn( 'node', - [path.join(scriptsDir, 'validate-no-link-deps.mjs')], + [path.join(scriptsDir, 'validate-no-link-deps.mts')], { shell: WIN32, stdio: 'pipe', @@ -262,7 +279,7 @@ async function main() { } const bundleResult = await spawn( 'node', - [path.join(scriptsDir, 'validate-bundle-deps.mjs')], + [path.join(scriptsDir, 'validate-bundle-deps.mts')], { shell: WIN32, stdio: 'pipe', @@ -298,7 +315,7 @@ async function main() { } const cdnResult = await spawn( 'node', - [path.join(scriptsDir, 'validate-no-cdn-refs.mjs')], + [path.join(scriptsDir, 'validate-no-cdn-refs.mts')], { shell: WIN32, stdio: 'pipe', @@ -334,7 +351,7 @@ async function main() { } const sizeResult = await spawn( 'node', - [path.join(scriptsDir, 'validate-file-size.mjs')], + [path.join(scriptsDir, 'validate-file-size.mts')], { shell: WIN32, stdio: 'pipe', @@ -367,13 +384,14 @@ async function main() { logger.success('All checks passed') printFooter() } - } catch (error) { - logger.error(`Check runner failed: ${error.message}`) + } catch (e) { + const message = e instanceof Error ? e.message : String(e) + logger.error(`Check runner failed: ${message}`) process.exitCode = 1 } } -main().catch(e => { +main().catch((e: unknown) => { logger.error(e) process.exitCode = 1 }) diff --git a/scripts/clean-cache.mjs b/scripts/clean-cache.mts similarity index 84% rename from scripts/clean-cache.mjs rename to scripts/clean-cache.mts index b9302b9e9..0aacf12a7 100755 --- a/scripts/clean-cache.mjs +++ b/scripts/clean-cache.mts @@ -15,7 +15,7 @@ import { parseArgs } from 'node:util' import { safeDelete } from '@socketsecurity/lib/fs' import { getDefaultLogger } from '@socketsecurity/lib/logger' -import { getGlobalCacheDirs } from '../packages/cli/scripts/constants/paths.mjs' +import { getGlobalCacheDirs } from '../packages/cli/scripts/constants/paths.mts' const logger = getDefaultLogger() @@ -33,11 +33,24 @@ const { values } = parseArgs({ const dryRun = values['dry-run'] const cleanAll = values.all +interface CacheDirInfo { + package: string + path: string +} + +interface CacheEntry { + name: string + path: string + size: number + mtime: Date + ageD: number +} + /** * Find all .cache directories in packages. */ -function findCacheDirs() { - const cacheDirs = [] +function findCacheDirs(): CacheDirInfo[] { + const cacheDirs: CacheDirInfo[] = [] const packagesDir = join(ROOT_DIR, 'packages') try { @@ -51,8 +64,9 @@ function findCacheDirs() { // No cache dir, skip. } } - } catch (error) { - logger.error(`Error scanning packages: ${error.message}`) + } catch (e) { + const message = e instanceof Error ? e.message : String(e) + logger.error(`Error scanning packages: ${message}`) } return cacheDirs @@ -61,8 +75,8 @@ function findCacheDirs() { /** * Analyze cache directory and determine what to clean. */ -function analyzeCacheDir(cacheDir) { - const entries = [] +function analyzeCacheDir(cacheDir: string): CacheEntry[] { + const entries: CacheEntry[] = [] try { const items = readdirSync(cacheDir) @@ -82,17 +96,18 @@ function analyzeCacheDir(cacheDir) { }) } } - } catch (error) { - logger.error(`Error analyzing ${cacheDir}: ${error.message}`) + } catch (e) { + const message = e instanceof Error ? e.message : String(e) + logger.error(`Error analyzing ${cacheDir}: ${message}`) } - return entries.sort((a, b) => b.mtime - a.mtime) + return entries.sort((a, b) => b.mtime.getTime() - a.mtime.getTime()) } /** * Get directory size recursively. */ -function getDirSize(dir) { +function getDirSize(dir: string): number { let size = 0 try { const items = readdirSync(dir) @@ -114,7 +129,7 @@ function getDirSize(dir) { /** * Format bytes to human readable. */ -function formatSize(bytes) { +function formatSize(bytes: number): string { if (bytes < 1024) { return `${bytes} B` } @@ -127,7 +142,7 @@ function formatSize(bytes) { return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB` } -async function main() { +async function main(): Promise { const cacheDirs = findCacheDirs() if (!cacheDirs.length) { @@ -226,7 +241,8 @@ async function main() { } } -main().catch(error => { - logger.error(`Error: ${error.message}`) +main().catch((e: unknown) => { + const message = e instanceof Error ? e.message : String(e) + logger.error(`Error: ${message}`) process.exitCode = 1 }) diff --git a/scripts/download-iocraft-binaries.mjs b/scripts/download-iocraft-binaries.mts similarity index 79% rename from scripts/download-iocraft-binaries.mjs rename to scripts/download-iocraft-binaries.mts index 49da9a073..9e5eb3773 100755 --- a/scripts/download-iocraft-binaries.mjs +++ b/scripts/download-iocraft-binaries.mts @@ -6,10 +6,10 @@ * before publishing @socketaddon/iocraft platform packages. * * Usage: - * node scripts/download-iocraft-binaries.mjs [--platform=] [--arch=] [--libc=] - * node scripts/download-iocraft-binaries.mjs # Download all platforms - * node scripts/download-iocraft-binaries.mjs --platform=darwin --arch=arm64 - * node scripts/download-iocraft-binaries.mjs --platform=linux --arch=x64 --libc=musl + * node scripts/download-iocraft-binaries.mts [--platform=] [--arch=] [--libc=] + * node scripts/download-iocraft-binaries.mts # Download all platforms + * node scripts/download-iocraft-binaries.mts --platform=darwin --arch=arm64 + * node scripts/download-iocraft-binaries.mts --platform=linux --arch=x64 --libc=musl */ import { existsSync, promises as fs } from 'node:fs' @@ -19,8 +19,8 @@ import { fileURLToPath } from 'node:url' import { PLATFORM_CONFIGS, parsePlatformArgs, -} from '../packages/build-infra/lib/platform-targets.mjs' -import { logTransientErrorHelp } from '../packages/build-infra/lib/github-error-utils.mjs' +} from '../packages/build-infra/lib/platform-targets.mts' +import { logTransientErrorHelp } from '../packages/build-infra/lib/github-error-utils.mts' import { getDefaultLogger } from '@socketsecurity/lib/logger' import { downloadSocketBtmRelease } from '@socketsecurity/lib/releases/socket-btm' @@ -29,10 +29,35 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url)) const rootPath = path.join(__dirname, '..') const logger = getDefaultLogger() +interface DownloadResult { + ok: boolean + target: string + error?: unknown +} + +interface PlatformConfig { + arch: string + description: string + libc?: string + platform: string + releasePlatform: string + runner: string +} + +interface PlatformFilter { + platform: string + arch: string + libc?: string +} + /** * Get output path for a platform-specific .node binary. */ -function getBinaryOutputPath(platform, arch, libc) { +function getBinaryOutputPath( + platform: string, + arch: string, + libc: string | undefined, +): string { const muslSuffix = libc === 'musl' ? '-musl' : '' const releasePlatform = platform === 'win32' ? 'win' : platform const target = `${releasePlatform}-${arch}${muslSuffix}` @@ -47,7 +72,9 @@ function getBinaryOutputPath(platform, arch, libc) { /** * Download iocraft binary for a specific platform. */ -async function downloadIocraftBinary(config) { +async function downloadIocraftBinary( + config: PlatformConfig, +): Promise { const { arch, description, libc, platform, releasePlatform } = config const target = `${releasePlatform}-${arch}${libc ? `-${libc}` : ''}` @@ -68,7 +95,7 @@ async function downloadIocraftBinary(config) { ) // Download the asset. - let assetPath + let assetPath: string try { const assetPattern = `iocraft-*-${target}.node` assetPath = await downloadSocketBtmRelease('iocraft', { @@ -79,7 +106,8 @@ async function downloadIocraftBinary(config) { }) logger.info(`Downloaded to ${assetPath}`) } catch (e) { - logger.error(`Failed to download ${target}: ${e.message}`) + const message = e instanceof Error ? e.message : String(e) + logger.error(`Failed to download ${target}: ${message}`) await logTransientErrorHelp(e) throw e } @@ -121,18 +149,21 @@ async function downloadIocraftBinary(config) { logger.groupEnd() logger.success(`${target} download complete`) return { ok: true, target } - } catch (error) { + } catch (e) { + const message = e instanceof Error ? e.message : String(e) logger.groupEnd() - logger.error(`Failed to download ${target}: ${error.message}`) - await logTransientErrorHelp(error) - return { error, ok: false, target } + logger.error(`Failed to download ${target}: ${message}`) + await logTransientErrorHelp(e) + return { error: e, ok: false, target } } } /** * Download binaries for all platforms or a specific platform. */ -async function downloadBinaries(platformFilter = null) { +async function downloadBinaries( + platformFilter: PlatformFilter | null = null, +): Promise { const configs = platformFilter ? PLATFORM_CONFIGS.filter( c => @@ -176,7 +207,7 @@ async function downloadBinaries(platformFilter = null) { /** * Main entry point. */ -async function main() { +async function main(): Promise { const args = process.argv.slice(2) const platformArgs = parsePlatformArgs(args) @@ -198,8 +229,8 @@ async function main() { // Run if invoked directly. if (fileURLToPath(import.meta.url) === process.argv[1]) { - main().catch(error => { - logger.error('Download failed:', error) + main().catch((e: unknown) => { + logger.error('Download failed:', e) process.exitCode = 1 }) } diff --git a/scripts/fix.mjs b/scripts/fix.mts similarity index 90% rename from scripts/fix.mjs rename to scripts/fix.mts index 776c67b97..226d75edd 100644 --- a/scripts/fix.mjs +++ b/scripts/fix.mts @@ -8,7 +8,7 @@ * 3. `agentshield scan --fix` — fix Claude config security findings (if .claude/ exists) * * Usage: - * node scripts/fix.mjs [options] + * node scripts/fix.mts [options] * * Options: * --all Fix all packages @@ -33,7 +33,7 @@ const logger = getDefaultLogger() * Resolve the path to a binary, checking global PATH first then node_modules/.bin. * Returns undefined if the binary is not found anywhere. */ -function resolveBin(name) { +function resolveBin(name: string): string | undefined { // spawn will find it on PATH or in node_modules/.bin via pnpm exec. // We just need to know if it exists at all. try { @@ -46,17 +46,23 @@ function resolveBin(name) { return undefined } +interface SecurityFixOptions { + args: string[] + bin: string + label: string + quiet: boolean +} + /** * Run a security tool with --fix. Non-blocking: logs warnings on failure * but does not fail the overall fix run. - * - * @param {object} opts - * @param {string[]} opts.args - Arguments to pass to spawn. - * @param {string} opts.bin - Binary name. - * @param {string} opts.label - Human-readable label for log output. - * @param {boolean} opts.quiet - Suppress progress output. */ -async function runSecurityFix({ args, bin, label, quiet }) { +async function runSecurityFix({ + args, + bin, + label, + quiet, +}: SecurityFixOptions): Promise { if (!quiet) { logger.stdout.progress(`Running ${label}...`) } @@ -83,7 +89,7 @@ async function runSecurityFix({ args, bin, label, quiet }) { } } -async function main() { +async function main(): Promise { const { values } = parseArgs({ options: { all: { type: 'boolean', default: false }, @@ -163,18 +169,19 @@ async function main() { logger.log('') logger.success('Auto-fix completed!') } - } catch (error) { + } catch (e) { + const message = e instanceof Error ? e.message : String(e) if (!quiet) { - logger.error(`Fix failed: ${error.message}`) + logger.error(`Fix failed: ${message}`) } if (verbose) { - logger.error(error) + logger.error(e) } process.exitCode = 1 } } -main().catch(e => { +main().catch((e: unknown) => { logger.error(e) process.exitCode = 1 }) diff --git a/scripts/get-platform-matrix.mjs b/scripts/get-platform-matrix.mjs deleted file mode 100644 index c0f737ba1..000000000 --- a/scripts/get-platform-matrix.mjs +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env node -/** - * Output platform matrix JSON for GitHub Actions. - * Used by publish workflow to generate dynamic matrix. - * - * Usage: - * node scripts/get-platform-matrix.mjs - * # Outputs: {"include":[...]} - */ - -import { PLATFORM_CONFIGS } from '../packages/build-infra/lib/platform-targets.mjs' - -const matrix = { - include: PLATFORM_CONFIGS.map(c => ({ - arch: c.arch, - libc: c.libc ?? null, - platform: c.platform, // Node.js platform (win32 for Windows) - releasePlatform: c.releasePlatform, // Release naming (win for Windows) - runner: c.runner, - })), -} - -console.log(JSON.stringify(matrix)) diff --git a/scripts/get-platform-matrix.mts b/scripts/get-platform-matrix.mts new file mode 100644 index 000000000..4693416e6 --- /dev/null +++ b/scripts/get-platform-matrix.mts @@ -0,0 +1,33 @@ +#!/usr/bin/env node +/** + * Output platform matrix JSON for GitHub Actions. + * Used by publish workflow to generate dynamic matrix. + * + * Usage: + * node scripts/get-platform-matrix.mts + * # Outputs: {"include":[...]} + */ + +import { PLATFORM_CONFIGS } from '../packages/build-infra/lib/platform-targets.mts' + +interface MatrixEntry { + arch: string + libc: string | null + platform: string + releasePlatform: string + runner: string +} + +const matrix: { include: MatrixEntry[] } = { + include: PLATFORM_CONFIGS.map( + (c): MatrixEntry => ({ + arch: c.arch, + libc: c.libc ?? null, + platform: c.platform, // Node.js platform (win32 for Windows) + releasePlatform: c.releasePlatform, // Release naming (win for Windows) + runner: c.runner, + }), + ), +} + +console.log(JSON.stringify(matrix)) diff --git a/scripts/get-platform-targets.mjs b/scripts/get-platform-targets.mts similarity index 82% rename from scripts/get-platform-targets.mjs rename to scripts/get-platform-targets.mts index 42d8c5882..fe2c389f2 100644 --- a/scripts/get-platform-targets.mjs +++ b/scripts/get-platform-targets.mts @@ -4,10 +4,10 @@ * Used by publish workflow to iterate over platforms. * * Usage: - * node scripts/get-platform-targets.mjs + * node scripts/get-platform-targets.mts * # Outputs space-separated: linux-x64 linux-arm64 ... */ -import { PLATFORM_TARGETS } from '../packages/build-infra/lib/platform-targets.mjs' +import { PLATFORM_TARGETS } from '../packages/build-infra/lib/platform-targets.mts' console.log(PLATFORM_TARGETS.join(' ')) diff --git a/scripts/lib/build-exec.mjs b/scripts/lib/build-exec.mts similarity index 67% rename from scripts/lib/build-exec.mjs rename to scripts/lib/build-exec.mts index 160741dfd..1abf15d1f 100644 --- a/scripts/lib/build-exec.mjs +++ b/scripts/lib/build-exec.mts @@ -4,16 +4,41 @@ * Centralized command execution for build script. */ +import type { SpawnStdioResult } from '@socketsecurity/lib/spawn' + import { getDefaultLogger } from '@socketsecurity/lib/logger' import { spawn } from '@socketsecurity/lib/spawn' -import { saveBuildLog } from './build-helpers.mjs' +import { saveBuildLog } from './build-helpers.mts' const logger = getDefaultLogger() + +interface ExecOptions { + buildDir?: string + cwd?: string + env?: NodeJS.ProcessEnv +} + +interface ExecSilentResult { + code: number + stdout: string + stderr: string +} + +interface DownloadOptions { + buildDir?: string + maxRetries?: number + verifyIntegrity?: boolean +} + /** * Execute a command and stream output. */ -export async function exec(command, args = [], options = {}) { +export async function exec( + command: string, + args: string[] = [], + options: ExecOptions = {}, +): Promise { const { buildDir, cwd = process.cwd(), env = process.env } = options const cmdStr = `$ ${command} ${args.join(' ')}` @@ -42,7 +67,11 @@ export async function exec(command, args = [], options = {}) { /** * Execute a command silently (no output). */ -export async function execSilent(command, args = [], options = {}) { +export async function execSilent( + command: string, + args: string[] = [], + options: ExecOptions = {}, +): Promise { const { cwd = process.cwd(), env = process.env } = options const result = await spawn(command, args, { @@ -54,19 +83,23 @@ export async function execSilent(command, args = [], options = {}) { return { code: result.code, - stdout: result.stdout ? result.stdout.trim() : '', - stderr: result.stderr ? result.stderr.trim() : '', + stdout: result.stdout ? String(result.stdout).trim() : '', + stderr: result.stderr ? String(result.stderr).trim() : '', } } /** * Download file with retry and verification. */ -export async function downloadWithRetry(url, outputPath, options = {}) { +export async function downloadWithRetry( + url: string, + outputPath: string, + options: DownloadOptions = {}, +): Promise { const { buildDir, maxRetries = 3, verifyIntegrity = true } = options // Import verifyFileIntegrity dynamically to avoid circular dependency. - const { verifyFileIntegrity } = await import('./build-helpers.mjs') + const { verifyFileIntegrity } = await import('./build-helpers.mts') for (let attempt = 1; attempt <= maxRetries; attempt++) { try { @@ -85,13 +118,14 @@ export async function downloadWithRetry(url, outputPath, options = {}) { return true } catch (e) { + const message = e instanceof Error ? e.message : String(e) if (attempt === maxRetries) { throw new Error( - `Download failed after ${maxRetries} attempts: ${e.message}`, + `Download failed after ${maxRetries} attempts: ${message}`, ) } - logger.warn(` ⚠️ Download attempt ${attempt} failed: ${e.message}`) + logger.warn(` ⚠️ Download attempt ${attempt} failed: ${message}`) // Delete corrupted file if it exists. try { @@ -104,7 +138,7 @@ export async function downloadWithRetry(url, outputPath, options = {}) { // Wait before retry (exponential backoff). const waitTime = Math.min(1000 * 2 ** (attempt - 1), 5000) logger.log(` ⏱️ Waiting ${waitTime}ms before retry...`) - await new Promise(resolve => setTimeout(resolve, waitTime)) + await new Promise(resolve => setTimeout(resolve, waitTime)) } } diff --git a/scripts/lib/build-helpers.mjs b/scripts/lib/build-helpers.mts similarity index 76% rename from scripts/lib/build-helpers.mjs rename to scripts/lib/build-helpers.mts index 0922c1451..8dd2efa1d 100644 --- a/scripts/lib/build-helpers.mjs +++ b/scripts/lib/build-helpers.mts @@ -8,14 +8,17 @@ import { join } from 'node:path' /** * Get build log path. */ -export function getBuildLogPath(buildDir) { +export function getBuildLogPath(buildDir: string): string { return join(buildDir, 'build.log') } /** * Save build output to log file. */ -export async function saveBuildLog(buildDir, content) { +export async function saveBuildLog( + buildDir: string, + content: string, +): Promise { const logPath = getBuildLogPath(buildDir) try { await fs.appendFile(logPath, `${content}\n`) @@ -27,7 +30,7 @@ export async function saveBuildLog(buildDir, content) { /** * Format file size in human-readable format. */ -export function formatBytes(bytes) { +export function formatBytes(bytes: number): string { if (bytes === 0) { return '0 B' } diff --git a/scripts/lib/build-output.mjs b/scripts/lib/build-output.mts similarity index 73% rename from scripts/lib/build-output.mjs rename to scripts/lib/build-output.mts index b55de31bb..79f20fb3f 100644 --- a/scripts/lib/build-output.mjs +++ b/scripts/lib/build-output.mts @@ -10,7 +10,7 @@ const logger = getDefaultLogger() /** * Print section header. */ -export function printHeader(title) { +export function printHeader(title: string): void { logger.log('') logger.log('━'.repeat(60)) logger.log(` ${title}`) @@ -21,7 +21,11 @@ export function printHeader(title) { /** * Print error with instructions. */ -export function printError(title, message, instructions = []) { +export function printError( + title: string, + message: string, + instructions: string[] = [], +): void { logger.error('') logger.error('❌', title) logger.error('') @@ -39,7 +43,11 @@ export function printError(title, message, instructions = []) { /** * Print warning with suggestions. */ -export function printWarning(title, message, suggestions = []) { +export function printWarning( + title: string, + message: string, + suggestions: string[] = [], +): void { logger.warn('') logger.warn('⚠️ ', title) logger.warn('') @@ -57,20 +65,24 @@ export function printWarning(title, message, suggestions = []) { /** * Print success message. */ -export function printSuccess(message) { +export function printSuccess(message: string): void { logger.log(`✅ ${message}`) } /** * Print info message. */ -export function printInfo(message) { +export function printInfo(message: string): void { logger.log(`ℹ️ ${message}`) } /** * Print step with description. */ -export function printStep(step, total, description) { +export function printStep( + step: number, + total: number, + description: string, +): void { logger.log(`[${step}/${total}] ${description}`) } diff --git a/scripts/lib/patch-validator.mjs b/scripts/lib/patch-validator.mts similarity index 77% rename from scripts/lib/patch-validator.mjs rename to scripts/lib/patch-validator.mts index 575565394..ae5ea5eed 100644 --- a/scripts/lib/patch-validator.mjs +++ b/scripts/lib/patch-validator.mts @@ -7,12 +7,55 @@ import { promises as fs } from 'node:fs' import { spawn } from '@socketsecurity/lib/spawn' +interface PatchMetadata { + description: string | null + nodeVersions: string[] + requires: string[] + conflicts: string[] +} + +interface CompatibilityResult { + compatible: boolean + reason: string | null +} + +interface ValidationResult { + valid: boolean + reason?: string | null + metadata: PatchMetadata | null +} + +interface PatchAnalysis { + modifiesV8Includes: boolean + modifiesSEA: boolean + modifiesFiles: string[] +} + +interface PatchInfo { + name: string + analysis: PatchAnalysis +} + +interface PatchConflict { + type: string + file?: string + patches: string[] + message: string + severity?: string +} + +interface PatchApplicationResult { + canApply: boolean + reason: string | null + stderr?: string | Buffer +} + /** * Parse patch metadata from header comments. */ -export function parsePatchMetadata(patchContent) { +export function parsePatchMetadata(patchContent: string): PatchMetadata { const lines = patchContent.split('\n') - const metadata = { + const metadata: PatchMetadata = { description: null, nodeVersions: [], requires: [], @@ -52,7 +95,10 @@ export function parsePatchMetadata(patchContent) { /** * Check if patch is compatible with Node version. */ -export function isPatchCompatible(metadata, nodeVersion) { +export function isPatchCompatible( + metadata: PatchMetadata, + nodeVersion: string, +): CompatibilityResult { if (metadata.nodeVersions.length === 0) { // No version restriction = compatible with all. return { compatible: true, reason: null } @@ -92,15 +138,15 @@ export function isPatchCompatible(metadata, nodeVersion) { /** * Compare Node.js versions. */ -function compareVersions(v1, v2) { +function compareVersions(v1: string, v2: string): number { const parts1 = v1.replace('v', '').split('.').map(Number) const parts2 = v2.replace('v', '').split('.').map(Number) for (let i = 0; i < 3; i++) { - if (parts1[i] > parts2[i]) { + if ((parts1[i] ?? 0) > (parts2[i] ?? 0)) { return 1 } - if (parts1[i] < parts2[i]) { + if ((parts1[i] ?? 0) < (parts2[i] ?? 0)) { return -1 } } @@ -110,7 +156,10 @@ function compareVersions(v1, v2) { /** * Validate patch file before applying. */ -export async function validatePatch(patchPath, nodeVersion) { +export async function validatePatch( + patchPath: string, + nodeVersion: string, +): Promise { try { const content = await fs.readFile(patchPath, 'utf8') @@ -160,9 +209,10 @@ export async function validatePatch(patchPath, nodeVersion) { metadata, } } catch (e) { + const message = e instanceof Error ? e.message : String(e) return { valid: false, - reason: `Cannot read patch: ${e.message}`, + reason: `Cannot read patch: ${message}`, metadata: null, } } @@ -171,15 +221,15 @@ export async function validatePatch(patchPath, nodeVersion) { /** * Analyze what a patch modifies. */ -export function analyzePatchContent(patchContent) { - const analysis = { +export function analyzePatchContent(patchContent: string): PatchAnalysis { + const analysis: PatchAnalysis = { modifiesV8Includes: false, modifiesSEA: false, modifiesFiles: [], } const lines = patchContent.split('\n') - let currentFile + let currentFile: string | undefined for (const line of lines) { // Track which files are modified. @@ -217,18 +267,21 @@ export function analyzePatchContent(patchContent) { /** * Check for patch conflicts. */ -export function checkPatchConflicts(patches, nodeVersion) { - const conflicts = [] +export function checkPatchConflicts( + patches: PatchInfo[], + nodeVersion: string, +): PatchConflict[] { + const conflicts: PatchConflict[] = [] // Check for multiple patches modifying same files. - const fileModifications = new Map() + const fileModifications = new Map() for (const patch of patches) { for (const file of patch.analysis.modifiesFiles) { if (!fileModifications.has(file)) { fileModifications.set(file, []) } - fileModifications.get(file).push(patch.name) + fileModifications.get(file)!.push(patch.name) } } @@ -263,10 +316,10 @@ export function checkPatchConflicts(patches, nodeVersion) { * Test if a patch will apply cleanly (dry-run). */ export async function testPatchApplication( - patchPath, - targetDir, - stripLevel = 1, -) { + patchPath: string, + targetDir: string, + stripLevel: number = 1, +): Promise { try { // Use /bin/sh wrapper to ensure patch command is found in PATH. // This matches the pattern used in the build script for applying patches. @@ -289,9 +342,10 @@ export async function testPatchApplication( stderr: result.stderr, } } catch (e) { + const message = e instanceof Error ? e.message : String(e) return { canApply: false, - reason: `Patch dry-run error: ${e.message}`, + reason: `Patch dry-run error: ${message}`, } } } diff --git a/scripts/lint.mjs b/scripts/lint.mts similarity index 88% rename from scripts/lint.mjs rename to scripts/lint.mts index 734723160..21cd9bd6f 100644 --- a/scripts/lint.mjs +++ b/scripts/lint.mts @@ -5,6 +5,8 @@ import process from 'node:process' * Runs linting across affected packages based on changed files. */ +import type { PackageInfo } from './utils/monorepo-helper.mts' + import { isQuiet } from '@socketsecurity/lib/argv/flags' import { parseArgs } from '@socketsecurity/lib/argv/parse' import { getChangedFiles, getStagedFiles } from '@socketsecurity/lib/git' @@ -15,14 +17,27 @@ import { getAffectedPackages, getPackagesWithScript, runAcrossPackages, -} from './utils/monorepo-helper.mjs' +} from './utils/monorepo-helper.mts' const logger = getDefaultLogger() +interface LintOptions { + all?: boolean + changed?: boolean + fix?: boolean + staged?: boolean +} + +interface FilesToLintResult { + mode: string + packages: PackageInfo[] + reason: string | null +} + /** * Get files to lint and determine affected packages. */ -async function getFilesToLint(options) { +async function getFilesToLint(options: LintOptions): Promise { const { all, changed, staged } = options // If --all, return all packages. @@ -35,7 +50,7 @@ async function getFilesToLint(options) { } // Get changed files. - let changedFiles = [] + let changedFiles: string[] = [] let mode = 'changed' if (staged) { @@ -69,7 +84,7 @@ async function getFilesToLint(options) { return { mode, packages: affectedPackages, reason: null } } -async function main() { +async function main(): Promise { try { // Parse arguments. const { values } = parseArgs({ @@ -151,13 +166,14 @@ async function main() { logger.success('All lint checks passed!') } } - } catch (error) { - logger.error(`Lint runner failed: ${error.message}`) + } catch (e) { + const message = e instanceof Error ? e.message : String(e) + logger.error(`Lint runner failed: ${message}`) process.exitCode = 1 } } -main().catch(e => { +main().catch((e: unknown) => { logger.error(e) process.exitCode = 1 }) diff --git a/scripts/prepare-package-for-publish.mjs b/scripts/prepare-package-for-publish.mts similarity index 65% rename from scripts/prepare-package-for-publish.mjs rename to scripts/prepare-package-for-publish.mts index a2c08a7a2..064b5a6d1 100644 --- a/scripts/prepare-package-for-publish.mjs +++ b/scripts/prepare-package-for-publish.mts @@ -7,24 +7,25 @@ import { resolve } from 'node:path' import { getDefaultLogger } from '@socketsecurity/lib/logger' -import { preparePackageForPublish } from 'package-builder/scripts/utils/prepare-package.mjs' +import { preparePackageForPublish } from 'package-builder/scripts/utils/prepare-package.mts' const logger = getDefaultLogger() const args = process.argv.slice(2) -const packagePath = args[0] -const version = args[1] +const packagePath: string | undefined = args[0] +const version: string | undefined = args[1] if (!packagePath) { logger.error( - 'Usage: prepare-package-for-publish.mjs [version]', + 'Usage: prepare-package-for-publish.mts [version]', ) process.exitCode = 1 } else { try { preparePackageForPublish(resolve(packagePath), { version }) } catch (e) { - logger.error(`Error preparing package: ${e.message}`) + const message = e instanceof Error ? e.message : String(e) + logger.error(`Error preparing package: ${message}`) process.exitCode = 1 } } diff --git a/scripts/prepublish-socketbin.mjs b/scripts/prepublish-socketbin.mts similarity index 93% rename from scripts/prepublish-socketbin.mjs rename to scripts/prepublish-socketbin.mts index 92bce25b7..c909a6a86 100644 --- a/scripts/prepublish-socketbin.mjs +++ b/scripts/prepublish-socketbin.mts @@ -12,8 +12,8 @@ import { getDefaultLogger } from '@socketsecurity/lib/logger' import { getSocketbinBinaryPath, getSocketbinPackageDir, -} from 'package-builder/scripts/paths.mjs' -import { preparePackageForPublish } from 'package-builder/scripts/utils/prepare-package.mjs' +} from 'package-builder/scripts/paths.mts' +import { preparePackageForPublish } from 'package-builder/scripts/utils/prepare-package.mts' const logger = getDefaultLogger() @@ -39,7 +39,7 @@ const { if (!platform || !arch) { logger.error( - 'Usage: prepublish-socketbin.mjs --platform=darwin --arch=arm64 --version=2.1.0 [--method=sea]', + 'Usage: prepublish-socketbin.mts --platform=darwin --arch=arm64 --version=2.1.0 [--method=sea]', ) process.exitCode = 1 } else if (!providedVersion) { diff --git a/scripts/setup.mjs b/scripts/setup.mts similarity index 92% rename from scripts/setup.mjs rename to scripts/setup.mts index 21f33ea69..6f7b27a45 100644 --- a/scripts/setup.mjs +++ b/scripts/setup.mts @@ -72,10 +72,23 @@ Examples: process.exitCode = 0 } +interface VersionInfo { + major: number + minor: number + patch: number +} + +interface PrerequisiteOptions { + command: string + minVersion?: VersionInfo + name: string + required?: boolean +} + /** * Check if a command is available. */ -async function hasCommand(command) { +async function hasCommand(command: string): Promise { try { const result = await spawn(command, ['--version'], { stdio: 'pipe', @@ -89,13 +102,16 @@ async function hasCommand(command) { /** * Get version of a command. */ -async function getVersion(command, args = ['--version']) { +async function getVersion( + command: string, + args: string[] = ['--version'], +): Promise { try { const result = await spawn(command, args, { stdio: 'pipe', }) if (result.code === 0) { - return result.stdout.trim() + return String(result.stdout).trim() } } catch { // Ignore. @@ -106,7 +122,7 @@ async function getVersion(command, args = ['--version']) { /** * Parse version string to compare. */ -function parseVersion(versionString) { +function parseVersion(versionString: string): VersionInfo | undefined { const match = versionString.match(/(\d+)\.(\d+)\.(\d+)/) if (!match) { return undefined @@ -122,7 +138,7 @@ function parseVersion(versionString) { * Compare two version objects. * Returns: -1 if a < b, 0 if a === b, 1 if a > b */ -function compareVersions(a, b) { +function compareVersions(a: VersionInfo, b: VersionInfo): number { if (a.major !== b.major) { return a.major < b.major ? -1 : 1 } @@ -138,7 +154,7 @@ function compareVersions(a, b) { /** * Install Homebrew (macOS/Linux). */ -async function installHomebrew() { +async function installHomebrew(): Promise { if (WIN32) { logger.warn('Homebrew is not available on Windows') return false @@ -166,7 +182,7 @@ async function installHomebrew() { /** * Install Chocolatey (Windows). */ -async function installChocolatey() { +async function installChocolatey(): Promise { if (!WIN32) { logger.warn('Chocolatey is only available on Windows') return false @@ -195,7 +211,7 @@ async function installChocolatey() { /** * Install a package using Homebrew (macOS/Linux). */ -async function installWithHomebrew(packageName) { +async function installWithHomebrew(packageName: string): Promise { if (!(await hasCommand('brew'))) { logger.error('Homebrew not available') return false @@ -219,7 +235,7 @@ async function installWithHomebrew(packageName) { /** * Install a package using Chocolatey (Windows). */ -async function installWithChocolatey(packageName) { +async function installWithChocolatey(packageName: string): Promise { if (!(await hasCommand('choco'))) { logger.error('Chocolatey not available') return false @@ -244,7 +260,7 @@ async function installWithChocolatey(packageName) { /** * Check and optionally install gh CLI. */ -async function ensureGhCli() { +async function ensureGhCli(): Promise { if (await hasCommand('gh')) { const version = await getVersion('gh') logger.log(`gh CLI ${version} (optional)`) @@ -335,7 +351,7 @@ async function checkPrerequisite({ minVersion, name, required = true, -}) { +}: PrerequisiteOptions): Promise { const version = await getVersion(command) if (!version) { @@ -364,13 +380,13 @@ async function checkPrerequisite({ /** * Generate cli-with-sentry package from template. */ -async function generateCliSentryPackage() { +async function generateCliSentryPackage(): Promise { if (!quiet) { logger.log('Generating cli-with-sentry package from template...') } const scriptPath = new URL( - '../packages/package-builder/scripts/generate-cli-sentry-package.mjs', + '../packages/package-builder/scripts/generate-cli-sentry-package.mts', import.meta.url, ) const result = await spawn('node', [scriptPath.pathname], { @@ -395,13 +411,13 @@ async function generateCliSentryPackage() { /** * Generate socketbin packages from template. */ -async function generateSocketbinPackages() { +async function generateSocketbinPackages(): Promise { if (!quiet) { logger.log('Generating socketbin packages from template...') } const scriptPath = new URL( - '../packages/package-builder/scripts/generate-socketbin-packages.mjs', + '../packages/package-builder/scripts/generate-socketbin-packages.mts', import.meta.url, ) const result = await spawn('node', [scriptPath.pathname], { @@ -422,7 +438,7 @@ async function generateSocketbinPackages() { /** * Restore build cache if possible. */ -async function restoreCache(hasGh) { +async function restoreCache(hasGh: boolean): Promise { // Skip entirely if gh CLI not available. if (!hasGh) { logger.info('Skipping cache restoration (gh CLI not available)') @@ -462,7 +478,7 @@ async function restoreCache(hasGh) { /** * Main entry point. */ -async function main() { +async function main(): Promise { // Handle --skip-prereqs: skip prerequisite checks, proceed to cache restoration. if (skipPrereqs) { if (!quiet) { @@ -592,11 +608,12 @@ async function main() { if (!showHelp) { main() - .then(code => { + .then((code: number) => { process.exitCode = code }) - .catch(error => { - logger.error(error.message) + .catch((e: unknown) => { + const message = e instanceof Error ? e.message : String(e) + logger.error(message) process.exitCode = 1 }) } diff --git a/scripts/test-monorepo.mjs b/scripts/test-monorepo.mts similarity index 88% rename from scripts/test-monorepo.mjs rename to scripts/test-monorepo.mts index 63606d4c4..79367b132 100644 --- a/scripts/test-monorepo.mjs +++ b/scripts/test-monorepo.mts @@ -3,6 +3,8 @@ * Runs tests across affected packages based on changed files. */ +import type { PackageInfo } from './utils/monorepo-helper.mts' + import colors from 'yoctocolors-cjs' import { isQuiet } from '@socketsecurity/lib/argv/flags' @@ -18,13 +20,28 @@ import { ProgressBar } from '@socketsecurity/lib/stdio/progress' import { getAffectedPackages, getPackagesWithScript, -} from './utils/monorepo-helper.mjs' +} from './utils/monorepo-helper.mts' const logger = getDefaultLogger() + +interface TestOptions { + all?: boolean + changed?: boolean + staged?: boolean +} + +interface PackagesToTestResult { + mode: string + packages: PackageInfo[] + reason: string | null +} + /** * Get packages to test and determine affected packages. */ -async function getPackagesToTest(options) { +async function getPackagesToTest( + options: TestOptions, +): Promise { const { all, changed, staged } = options // If --all, return all packages. @@ -37,7 +54,7 @@ async function getPackagesToTest(options) { } // Get changed files. - let changedFiles = [] + let changedFiles: string[] = [] let mode = 'changed' if (staged) { @@ -75,18 +92,18 @@ async function getPackagesToTest(options) { * Run tests on a specific package with pretty output. */ async function runPackageTest( - pkg, - testArgs = [], - quiet = false, - showProgress = true, -) { + pkg: PackageInfo, + testArgs: string[] = [], + quiet: boolean = false, + showProgress: boolean = true, +): Promise { const displayName = pkg.displayName || pkg.name if (!quiet && showProgress) { logger.progress(`${displayName}: running tests`) } - let result + let result: Awaited> try { result = await spawn( 'pnpm', @@ -112,7 +129,8 @@ async function runPackageTest( } return e.code } - logger.error(`Failed to spawn test command: ${e.message}`) + const message = e instanceof Error ? e.message : String(e) + logger.error(`Failed to spawn test command: ${message}`) return 1 } @@ -138,7 +156,7 @@ async function runPackageTest( return 0 } -async function main() { +async function main(): Promise { try { // Parse arguments. const { positionals, values } = parseArgs({ @@ -271,13 +289,14 @@ async function main() { logger.success('All tests passed!') } } - } catch (error) { - logger.error(`Test runner failed: ${error.message}`) + } catch (e) { + const message = e instanceof Error ? e.message : String(e) + logger.error(`Test runner failed: ${message}`) process.exitCode = 1 } } -main().catch(e => { +main().catch((e: unknown) => { logger.error(e) process.exitCode = 1 }) diff --git a/scripts/type.mjs b/scripts/type.mts similarity index 90% rename from scripts/type.mjs rename to scripts/type.mts index 0b9597678..9e5d103ce 100644 --- a/scripts/type.mjs +++ b/scripts/type.mts @@ -3,6 +3,8 @@ * Runs type checking across packages with pretty UI. */ +import type { PackageInfo } from './utils/monorepo-helper.mts' + import colors from 'yoctocolors-cjs' import { isQuiet } from '@socketsecurity/lib/argv/flags' @@ -12,13 +14,16 @@ import { getDefaultLogger } from '@socketsecurity/lib/logger' import { spawn } from '@socketsecurity/lib/spawn' import { printFooter, printHeader } from '@socketsecurity/lib/stdio/header' -import { getPackagesWithScript } from './utils/monorepo-helper.mjs' +import { getPackagesWithScript } from './utils/monorepo-helper.mts' const logger = getDefaultLogger() /** * Run type check on a specific package with pretty output. */ -async function runPackageTypeCheck(pkg, quiet = false) { +async function runPackageTypeCheck( + pkg: PackageInfo, + quiet: boolean = false, +): Promise { const displayName = pkg.displayName || pkg.name if (!quiet) { @@ -54,7 +59,7 @@ async function runPackageTypeCheck(pkg, quiet = false) { return 0 } -async function main() { +async function main(): Promise { try { // Parse arguments. const { values } = parseArgs({ @@ -132,13 +137,14 @@ async function main() { printFooter() } } - } catch (error) { - logger.error(`Type checker failed: ${error.message}`) + } catch (e) { + const message = e instanceof Error ? e.message : String(e) + logger.error(`Type checker failed: ${message}`) process.exitCode = 1 } } -main().catch(e => { +main().catch((e: unknown) => { logger.error(e) process.exitCode = 1 }) diff --git a/scripts/update.mjs b/scripts/update.mts similarity index 89% rename from scripts/update.mjs rename to scripts/update.mts index 2c11c6d02..af86c61d1 100644 --- a/scripts/update.mjs +++ b/scripts/update.mts @@ -5,7 +5,7 @@ import process from 'node:process' * Uses taze to update dependencies across all packages in the monorepo. * * Usage: - * node scripts/update.mjs [options] + * node scripts/update.mts [options] * * Options: * --quiet Suppress progress output @@ -17,7 +17,7 @@ import { WIN32 } from '@socketsecurity/lib/constants/platform' import { getDefaultLogger } from '@socketsecurity/lib/logger' import { spawn } from '@socketsecurity/lib/spawn' -async function main() { +async function main(): Promise { const quiet = isQuiet() const verbose = isVerbose() const logger = getDefaultLogger() @@ -90,18 +90,19 @@ async function main() { logger.log('') } } - } catch (error) { + } catch (e) { + const message = e instanceof Error ? e.message : String(e) if (!quiet) { - logger.fail(`Update failed: ${error.message}`) + logger.fail(`Update failed: ${message}`) } if (verbose) { - logger.error(error) + logger.error(e) } process.exitCode = 1 } } -main().catch(e => { +main().catch((e: unknown) => { const logger = getDefaultLogger() logger.error(e) process.exitCode = 1 diff --git a/scripts/utils/changed-test-mapper.mjs b/scripts/utils/changed-test-mapper.mts similarity index 88% rename from scripts/utils/changed-test-mapper.mjs rename to scripts/utils/changed-test-mapper.mts index 18973c21d..343fa5731 100644 --- a/scripts/utils/changed-test-mapper.mjs +++ b/scripts/utils/changed-test-mapper.mts @@ -17,7 +17,7 @@ const rootPath = path.resolve(process.cwd()) /** * Core files that require running all tests when changed. */ -const CORE_FILES = [ +const CORE_FILES: string[] = [ 'packages/cli/src/constants/', 'packages/cli/src/bootstrap/', 'packages/cli/src/polyfills/', @@ -27,12 +27,21 @@ const CORE_FILES = [ '.config/tsconfig', ] +interface GetTestsOptions { + staged?: boolean + all?: boolean +} + +interface GetTestsResult { + tests: string[] | 'all' | null + reason?: string + mode?: string +} + /** * Map source files to their corresponding test files. - * @param {string} filepath - Path to source file - * @returns {string[]} Array of test file paths */ -function mapSourceToTests(filepath) { +function mapSourceToTests(filepath: string): string[] { const normalized = normalizePath(filepath) // Skip non-code files @@ -113,21 +122,17 @@ function mapSourceToTests(filepath) { /** * Get affected test files to run based on changed files. - * @param {Object} options - * @param {boolean} options.staged - Use staged files instead of all changes - * @param {boolean} options.all - Run all tests - * @returns {{tests: string[] | 'all' | null, reason?: string, mode?: string}} Object with test patterns, reason, and mode */ -export function getTestsToRun(options = {}) { +export function getTestsToRun(options: GetTestsOptions = {}): GetTestsResult { const { all = false, staged = false } = options // All mode runs all tests - if (all || process.env.FORCE_TEST === '1') { + if (all || process.env['FORCE_TEST'] === '1') { return { tests: 'all', reason: 'explicit --all flag', mode: 'all' } } // CI always runs all tests - if (process.env.CI === 'true') { + if (process.env['CI'] === 'true') { return { tests: 'all', reason: 'CI environment', mode: 'all' } } @@ -140,7 +145,7 @@ export function getTestsToRun(options = {}) { return { tests: null, mode } } - const testFiles = new Set() + const testFiles = new Set() let runAllTests = false let runAllReason = '' diff --git a/scripts/utils/monorepo-helper.mjs b/scripts/utils/monorepo-helper.mts similarity index 76% rename from scripts/utils/monorepo-helper.mjs rename to scripts/utils/monorepo-helper.mts index 6287d2f0c..2bb20298b 100644 --- a/scripts/utils/monorepo-helper.mjs +++ b/scripts/utils/monorepo-helper.mts @@ -13,13 +13,18 @@ import { getDefaultLogger } from '@socketsecurity/lib/logger' import { spawn } from '@socketsecurity/lib/spawn' const logger = getDefaultLogger() + +export interface PackageInfo { + name: string + path: string + displayName: string +} + /** * Get all packages in the monorepo with specific scripts. - * @param {string} scriptName - Script name to check for - * @returns {{name: string, path: string, displayName: string}[]} */ -export function getPackagesWithScript(scriptName) { - const packages = [] +export function getPackagesWithScript(scriptName: string): PackageInfo[] { + const packages: PackageInfo[] = [] const packagesDir = path.join(process.cwd(), 'packages') // Main CLI package always has all scripts. @@ -63,11 +68,9 @@ export function getPackagesWithScript(scriptName) { /** * Determine which packages are affected by changed files. - * @param {string[]} changedFiles - Array of relative file paths - * @returns {{name: string, path: string, displayName: string}[]} Affected packages */ -export function getAffectedPackages(changedFiles) { - const affectedPkgs = new Set() +export function getAffectedPackages(changedFiles: string[]): PackageInfo[] { + const affectedPkgs = new Set() const packages = getPackagesWithScript('lint') for (const file of changedFiles) { @@ -105,20 +108,14 @@ export function getAffectedPackages(changedFiles) { /** * Run a script on a specific package with pretty output. - * @param {object} pkg - Package info - * @param {string} scriptName - Script to run - * @param {string[]} args - Additional arguments - * @param {boolean} quiet - Suppress output - * @param {string} [progressMessage] - Optional custom progress message - * @returns {Promise} Exit code */ export async function runPackageScript( - pkg, - scriptName, - args = [], - quiet = false, - progressMessage = '', -) { + pkg: PackageInfo, + scriptName: string, + args: string[] = [], + quiet: boolean = false, + progressMessage: string = '', +): Promise { const displayName = pkg.displayName || pkg.name if (!quiet) { @@ -161,20 +158,14 @@ export async function runPackageScript( /** * Run a script across multiple packages. - * @param {Array} packages - Packages to run on - * @param {string} scriptName - Script to run - * @param {string[]} args - Additional arguments - * @param {boolean} quiet - Suppress output - * @param {string} [sectionTitle] - Optional section title to use as progress message - * @returns {Promise} Exit code (0 if all succeed, first failure code otherwise) */ export async function runAcrossPackages( - packages, - scriptName, - args = [], - quiet = false, - sectionTitle = '', -) { + packages: PackageInfo[], + scriptName: string, + args: string[] = [], + quiet: boolean = false, + sectionTitle: string = '', +): Promise { if (!packages.length) { if (!quiet) { logger.substep('No packages to process') diff --git a/scripts/validate-bundle-deps.mjs b/scripts/validate-bundle-deps.mts similarity index 91% rename from scripts/validate-bundle-deps.mjs rename to scripts/validate-bundle-deps.mts index a6bd362db..1fca36d89 100644 --- a/scripts/validate-bundle-deps.mjs +++ b/scripts/validate-bundle-deps.mts @@ -32,10 +32,22 @@ const BUILTIN_MODULES = new Set([ // These are packages referenced in bundled code that's never actually called. const EXCUSED_EXTERNALS = new Set(['node-gyp']) +interface BundleViolation { + type: string + package: string + message: string + fix: string +} + +interface BundleValidationResult { + violations: BundleViolation[] + warnings: BundleViolation[] +} + /** * Find all JavaScript files in dist directory. */ -async function findDistFiles(distPath) { +async function findDistFiles(distPath: string): Promise { const files = [] try { @@ -65,7 +77,7 @@ async function findDistFiles(distPath) { /** * Extract bundled package names from node_modules paths in comments and code. */ -async function extractBundledPackages(filePath) { +async function extractBundledPackages(filePath: string): Promise> { const content = await fs.readFile(filePath, 'utf8') const bundled = new Set() @@ -127,7 +139,7 @@ async function extractBundledPackages(filePath) { /** * Get package name from a module specifier (strip subpaths). */ -function getPackageName(specifier) { +function getPackageName(specifier: string): string | undefined { // Relative imports are not packages if (specifier.startsWith('.') || specifier.startsWith('/')) { return undefined @@ -180,12 +192,12 @@ function getPackageName(specifier) { /** * Extract external packages from esbuild config files. */ -async function extractExternalsFromConfigs() { +async function extractExternalsFromConfigs(): Promise> { const externals = new Set() const configFiles = [ - path.join(cliPackagePath, '.config/esbuild.cli.build.mjs'), - path.join(cliPackagePath, '.config/esbuild.inject.config.mjs'), - path.join(cliPackagePath, '.config/esbuild.index.config.mjs'), + path.join(cliPackagePath, '.config/esbuild.cli.build.mts'), + path.join(cliPackagePath, '.config/esbuild.inject.config.mts'), + path.join(cliPackagePath, '.config/esbuild.index.config.mts'), ] for (const configFile of configFiles) { @@ -205,7 +217,7 @@ async function extractExternalsFromConfigs() { } } } - } catch (e) { + } catch { // Config file doesn't exist or can't be read. continue } @@ -217,7 +229,10 @@ async function extractExternalsFromConfigs() { /** * Check if a package is a direct dependency (not transitive). */ -async function isDirectDependency(packageName, devDependencies) { +async function isDirectDependency( + packageName: string, + devDependencies: Set, +): Promise { // If it's in devDependencies, it's direct. if (devDependencies.has(packageName)) { return true @@ -251,7 +266,7 @@ async function isDirectDependency(packageName, devDependencies) { /** * Find all source files in a directory. */ -async function findSourceFiles(srcPath) { +async function findSourceFiles(srcPath: string): Promise { const files = [] try { @@ -283,7 +298,7 @@ async function findSourceFiles(srcPath) { /** * Validate bundle dependencies. */ -async function validateBundleDeps() { +async function validateBundleDeps(): Promise { const distPath = path.join(cliPackagePath, 'build') const packageJsonPath = path.join(cliPackagePath, 'package.json') const pkg = JSON.parse(await fs.readFile(packageJsonPath, 'utf8')) @@ -362,7 +377,7 @@ async function validateBundleDeps() { return { violations, warnings } } -async function main() { +async function main(): Promise { try { const { violations, warnings } = await validateBundleDeps() @@ -393,8 +408,9 @@ async function main() { // Only fail on violations, not warnings process.exitCode = violations.length > 0 ? 1 : 0 - } catch (error) { - logger.error('Validation failed:', error.message) + } catch (e) { + const message = e instanceof Error ? e.message : String(e) + logger.error('Validation failed:', message) process.exitCode = 1 } } diff --git a/scripts/validate-checksums.mjs b/scripts/validate-checksums.mts similarity index 93% rename from scripts/validate-checksums.mjs rename to scripts/validate-checksums.mts index acf79a73b..1de341ffb 100644 --- a/scripts/validate-checksums.mjs +++ b/scripts/validate-checksums.mts @@ -19,7 +19,7 @@ import { fileURLToPath } from 'node:url' import { getDefaultLogger } from '@socketsecurity/lib/logger' -import { PLATFORM_MAP_TOOLS } from '../packages/cli/scripts/constants/external-tools-platforms.mjs' +import { PLATFORM_MAP_TOOLS } from '../packages/cli/scripts/constants/external-tools-platforms.mts' const logger = getDefaultLogger() const __dirname = path.dirname(fileURLToPath(import.meta.url)) @@ -31,16 +31,15 @@ const externalTools = JSON.parse(readFileSync(externalToolsPath, 'utf8')) /** * Validate that all required checksums exist for external tools. - * @returns {boolean} True if all checksums are valid, false otherwise. */ -function validateChecksums() { - const errors = [] - const warnings = [] +function validateChecksums(): boolean { + const errors: string[] = [] + const warnings: string[] = [] logger.info('Validating SHA-256 checksums for external tools...\n') // Track all unique assets that need checksums. - const requiredAssets = new Map() // Map> + const requiredAssets = new Map>() // Collect all assets needed across all platforms. for (const [platform, tools] of Object.entries(PLATFORM_MAP_TOOLS)) { @@ -75,7 +74,7 @@ function validateChecksums() { } const checksums = toolConfig.checksums || {} - const missingAssets = [] + const missingAssets: string[] = [] for (const assetName of assets) { if (!checksums[assetName]) { diff --git a/scripts/validate-file-size.mjs b/scripts/validate-file-size.mts similarity index 84% rename from scripts/validate-file-size.mjs rename to scripts/validate-file-size.mts index d6550d625..f8ba4d39d 100644 --- a/scripts/validate-file-size.mjs +++ b/scripts/validate-file-size.mts @@ -13,7 +13,7 @@ import { fileURLToPath } from 'node:url' import { getDefaultLogger } from '@socketsecurity/lib/logger' -import { formatBytes } from './lib/build-helpers.mjs' +import { formatBytes } from './lib/build-helpers.mts' const logger = getDefaultLogger() @@ -42,10 +42,20 @@ const SKIP_DIRS = new Set([ 'external', ]) +interface FileSizeViolation { + file: string + size: number + formattedSize: string + maxSize: string +} + /** * Recursively scan directory for files exceeding size limit. */ -async function scanDirectory(dir, violations = []) { +async function scanDirectory( + dir: string, + violations: FileSizeViolation[] = [], +): Promise { try { const entries = await fs.readdir(dir, { withFileTypes: true }) @@ -90,7 +100,7 @@ async function scanDirectory(dir, violations = []) { /** * Validate file sizes in repository. */ -async function validateFileSizes() { +async function validateFileSizes(): Promise { const violations = await scanDirectory(rootPath) // Sort by size descending (largest first) @@ -99,7 +109,7 @@ async function validateFileSizes() { return violations } -async function main() { +async function main(): Promise { try { const violations = await validateFileSizes() @@ -131,13 +141,14 @@ async function main() { logger.log('') process.exitCode = 1 - } catch (error) { - logger.fail(`Validation failed: ${error.message}`) + } catch (e) { + const message = e instanceof Error ? e.message : String(e) + logger.fail(`Validation failed: ${message}`) process.exitCode = 1 } } -main().catch(error => { - logger.fail(`Validation failed: ${error}`) +main().catch((e: unknown) => { + logger.fail(`Validation failed: ${e}`) process.exitCode = 1 }) diff --git a/scripts/validate-no-cdn-refs.mjs b/scripts/validate-no-cdn-refs.mts similarity index 82% rename from scripts/validate-no-cdn-refs.mjs rename to scripts/validate-no-cdn-refs.mts index 8f04f3cb5..4bf3bca7c 100644 --- a/scripts/validate-no-cdn-refs.mjs +++ b/scripts/validate-no-cdn-refs.mts @@ -72,10 +72,17 @@ const TEXT_EXTENSIONS = new Set([ '.bash', ]) +interface CdnViolation { + file: string + line: number + content: string + cdnDomain: string +} + /** * Check if file should be scanned. */ -function shouldScanFile(filename) { +function shouldScanFile(filename: string): boolean { const ext = path.extname(filename).toLowerCase() return TEXT_EXTENSIONS.has(ext) } @@ -83,7 +90,10 @@ function shouldScanFile(filename) { /** * Recursively find all text files to scan. */ -async function findTextFiles(dir, files = []) { +async function findTextFiles( + dir: string, + files: string[] = [], +): Promise { try { const entries = await fs.readdir(dir, { withFileTypes: true }) @@ -112,16 +122,16 @@ async function findTextFiles(dir, files = []) { /** * Check file contents for CDN references. */ -async function checkFileForCdnRefs(filePath) { +async function checkFileForCdnRefs(filePath: string): Promise { // Skip this validator script itself (it mentions CDN domains by necessity) - if (filePath.endsWith('validate-no-cdn-refs.mjs')) { + if (filePath.endsWith('validate-no-cdn-refs.mts')) { return [] } try { const content = await fs.readFile(filePath, 'utf8') const lines = content.split('\n') - const violations = [] + const violations: CdnViolation[] = [] for (let i = 0; i < lines.length; i++) { const line = lines[i] @@ -141,9 +151,10 @@ async function checkFileForCdnRefs(filePath) { } return violations - } catch (error) { + } catch (e) { // Skip files we can't read (likely binary despite extension) - if (error.code === 'EISDIR' || error.message.includes('ENOENT')) { + const error = e as NodeJS.ErrnoException + if (error.code === 'EISDIR' || error.message?.includes('ENOENT')) { return [] } // For other errors, try to continue @@ -154,7 +165,7 @@ async function checkFileForCdnRefs(filePath) { /** * Validate all files for CDN references. */ -async function validateNoCdnRefs() { +async function validateNoCdnRefs(): Promise { const files = await findTextFiles(rootPath) const allViolations = [] @@ -166,7 +177,7 @@ async function validateNoCdnRefs() { return allViolations } -async function main() { +async function main(): Promise { try { const violations = await validateNoCdnRefs() @@ -202,13 +213,15 @@ async function main() { logger.log('') process.exitCode = 1 - } catch (error) { - logger.fail(`Validation failed: ${error.message}`) + } catch (e) { + const message = e instanceof Error ? e.message : String(e) + logger.fail(`Validation failed: ${message}`) process.exitCode = 1 } } -main().catch(error => { - logger.fail(`Unexpected error: ${error.message}`) +main().catch((e: unknown) => { + const message = e instanceof Error ? e.message : String(e) + logger.fail(`Unexpected error: ${message}`) process.exitCode = 1 }) diff --git a/scripts/validate-no-link-deps.mjs b/scripts/validate-no-link-deps.mts similarity index 90% rename from scripts/validate-no-link-deps.mjs rename to scripts/validate-no-link-deps.mts index bb749efbd..cdfea78a1 100755 --- a/scripts/validate-no-link-deps.mjs +++ b/scripts/validate-no-link-deps.mts @@ -14,10 +14,17 @@ const logger = getDefaultLogger() const __dirname = path.dirname(fileURLToPath(import.meta.url)) const rootPath = path.join(__dirname, '..') +interface LinkViolation { + file: string + field: string + package: string + value: string +} + /** * Find all package.json files in the repository. */ -async function findPackageJsonFiles(dir) { +async function findPackageJsonFiles(dir: string): Promise { const files = [] const entries = await fs.readdir(dir, { withFileTypes: true }) @@ -47,11 +54,11 @@ async function findPackageJsonFiles(dir) { /** * Check if a package.json contains link: dependencies. */ -async function checkPackageJson(filePath) { +async function checkPackageJson(filePath: string): Promise { const content = await fs.readFile(filePath, 'utf8') const pkg = JSON.parse(content) - const violations = [] + const violations: LinkViolation[] = [] // Check dependencies. if (pkg.dependencies) { @@ -126,9 +133,9 @@ async function checkPackageJson(filePath) { return violations } -async function main() { +async function main(): Promise { const packageJsonFiles = await findPackageJsonFiles(rootPath) - const allViolations = [] + const allViolations: LinkViolation[] = [] for (const file of packageJsonFiles) { const violations = await checkPackageJson(file) @@ -163,7 +170,7 @@ async function main() { } } -main().catch(error => { - logger.error('Validation failed:', error) +main().catch((e: unknown) => { + logger.error('Validation failed:', e) process.exitCode = 1 })