Skip to content

Commit 81bce76

Browse files
committed
Update scripts and test configurations
- Add new clean-test-cache and rebuild-registry-exports scripts - Update all scripts to use Node.js directly without dotenvx wrapper - Remove obsolete eslint.config.js in favor of eslint.config.mjs - Improve TypeScript typing in utility scripts - Update test configurations and imports - Add suppress-warnings utility script
1 parent 5df866a commit 81bce76

40 files changed

+978
-371
lines changed

scripts/check-registry-package-types.mjs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import constants from './constants.mjs'
88

99
const require = createRequire(import.meta.url)
1010

11-
void (async () => {
11+
async function main() {
1212
const { registryPkgPath, rootPath } = constants
1313

1414
const libPath = path.join(registryPkgPath, 'src', 'lib')
@@ -26,4 +26,6 @@ void (async () => {
2626
throw new Error(`Type '${key}' not declared in ${relLibConstDtsPath}`)
2727
}
2828
}
29-
})()
29+
}
30+
31+
main().catch(console.error)

scripts/clean-test-cache.mjs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { promises as fs } from 'node:fs'
2+
import os from 'node:os'
3+
import path from 'node:path'
4+
5+
async function cleanTestCache() {
6+
const dirs = [
7+
path.join(os.homedir(), '.socket-npm-test-cache'),
8+
path.join(os.tmpdir(), 'npm-package-tests'),
9+
]
10+
11+
for (const dir of dirs) {
12+
try {
13+
// eslint-disable-next-line no-await-in-loop
14+
await fs.rm(dir, { recursive: true, force: true })
15+
console.log('Removed:', dir)
16+
} catch {
17+
// Silently ignore errors (directory might not exist).
18+
}
19+
}
20+
}
21+
22+
cleanTestCache().catch(console.error)

scripts/constants.mjs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import path from 'node:path'
99
import { fileURLToPath } from 'node:url'
1010
import { includeIgnoreFile } from '@eslint/compat'
1111
import which from 'which'
12-
import registryConstants from '@socketsecurity/registry/lib/constants'
13-
import { whichBinSync } from '@socketsecurity/registry/lib/agent'
14-
import { envAsBoolean } from '@socketsecurity/registry/lib/env'
15-
import { createConstantsObject } from '@socketsecurity/registry/lib/objects'
12+
import registryConstants from '../registry/dist/lib/constants/index.js'
13+
import { whichBinSync } from '../registry/dist/lib/bin.js'
14+
import { envAsBoolean } from '../registry/dist/lib/env.js'
15+
import { createConstantsObject } from '../registry/dist/lib/objects.js'
1616

1717
const require = createRequire(import.meta.url)
1818

@@ -63,15 +63,15 @@ const LAZY_LICENSE_CONTENT = () =>
6363
fs.readFileSync(constants.rootLicensePath, UTF8)
6464

6565
const lazyEcosystems = () => {
66-
const registryLibFs = /*@__PURE__*/ require('@socketsecurity/registry/lib/fs')
66+
const registryLibFs = /*@__PURE__*/ require('../registry/dist/lib/fs')
6767
const readDirNamesSync = registryLibFs.readDirNamesSync
6868
return Object.freeze(readDirNamesSync(constants.rootPackagesPath))
6969
}
7070

7171
const lazyGitExecPath = () => which.sync('git', { ...getDefaultWhichOptions() })
7272

7373
const lazyGitIgnoreFile = () =>
74-
includeIgnoreFile(path.join(constants.rootPath, GITIGNORE))
74+
includeIgnoreFile(path.join(lazyRootPath(), GITIGNORE))
7575

7676
const lazyIgnoreGlobs = () =>
7777
Object.freeze([
@@ -91,7 +91,7 @@ const lazyIgnoreGlobs = () =>
9191
])
9292

9393
const lazyNpmPackageNames = () => {
94-
const registryLibFs = /*@__PURE__*/ require('@socketsecurity/registry/lib/fs')
94+
const registryLibFs = /*@__PURE__*/ require('../registry/dist/lib/fs')
9595
const readDirNamesSync = registryLibFs.readDirNamesSync
9696
return Object.freeze(readDirNamesSync(constants.npmPackagesPath))
9797
}
@@ -141,6 +141,8 @@ const lazyRootPath = () => {
141141
}
142142

143143
// Fallback if not found (shouldn't happen in normal operation).
144+
const __filename = fileURLToPath(import.meta.url)
145+
const __dirname = path.dirname(__filename)
144146
return path.resolve(__dirname, '..')
145147
}
146148

scripts/download-npm-packages.mjs

Lines changed: 156 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -6,53 +6,46 @@
66
import { existsSync, promises as fs } from 'node:fs'
77
import os from 'node:os'
88
import path from 'node:path'
9-
import util from 'node:util'
9+
import { parseArgs } from '../registry/dist/lib/parse-args.js'
1010

1111
import constants from './constants.mjs'
12-
import ENV from '@socketsecurity/registry/lib/constants/env'
13-
import WIN32 from '@socketsecurity/registry/lib/constants/win32'
12+
import ENV from '../registry/dist/lib/constants/ENV.js'
13+
import WIN32 from '../registry/dist/lib/constants/WIN32.js'
1414
import {
1515
readPackageJson,
1616
resolveOriginalPackageName,
17-
} from '@socketsecurity/registry/lib/packages'
18-
import { pEach } from '@socketsecurity/registry/lib/promises'
19-
import { LOG_SYMBOLS, logger } from '@socketsecurity/registry/lib/logger'
17+
} from '../registry/dist/lib/packages.js'
18+
import { pEach } from '../registry/dist/lib/promises.js'
19+
import { LOG_SYMBOLS, logger } from '../registry/dist/lib/logger.js'
20+
import { pluralize } from '../registry/dist/lib/words.js'
2021

21-
const { values: cliArgs } = util.parseArgs({
22+
const { values: cliArgs } = parseArgs({
2223
options: {
23-
package: {
24-
type: 'string',
25-
multiple: true,
26-
},
2724
concurrency: {
2825
type: 'string',
29-
// Reduce concurrency in CI to avoid memory issues, especially on Windows.
30-
default: ENV.CI ? (WIN32 ? '5' : '10') : '50',
26+
default: ENV.CI ? (WIN32 ? '10' : '20') : '50',
3127
},
3228
'temp-dir': {
3329
type: 'string',
3430
default: path.join(os.tmpdir(), 'npm-package-tests'),
3531
},
32+
package: {
33+
type: 'string',
34+
multiple: true,
35+
},
36+
'clear-cache': {
37+
type: 'boolean',
38+
default: false,
39+
},
3640
},
41+
strict: false,
3742
})
3843

3944
const concurrency = Math.max(1, parseInt(cliArgs.concurrency, 10))
40-
const tempBaseDir = cliArgs['temp-dir']
41-
const MAX_PROGRESS_WIDTH = 80
42-
43-
// Progress tracking for line wrapping.
44-
let currentLinePosition = 0
45-
let completedPackages = 0
46-
let totalPackagesCount = 0
47-
48-
function writeProgress(symbol) {
49-
completedPackages += 1
50-
if (currentLinePosition >= MAX_PROGRESS_WIDTH) {
51-
process.stdout.write(`\n(${completedPackages}/${totalPackagesCount}) `)
52-
currentLinePosition = `(${completedPackages}/${totalPackagesCount}) `.length
53-
}
54-
process.stdout.write(symbol)
55-
currentLinePosition += 1
45+
const tempBaseDir = cliArgs.tempDir
46+
47+
function writeProgress() {
48+
// Don't output progress dots, too noisy.
5649
}
5750

5851
async function downloadPackage(socketPkgName) {
@@ -62,7 +55,7 @@ async function downloadPackage(socketPkgName) {
6255
const skipTestsMap = constants.skipTestsByEcosystem
6356
const skipSet = skipTestsMap.get('npm')
6457
if (skipSet && (skipSet.has(socketPkgName) || skipSet.has(origPkgName))) {
65-
writeProgress(LOG_SYMBOLS.warn)
58+
writeProgress()
6659
return {
6760
package: origPkgName,
6861
socketPackage: socketPkgName,
@@ -120,49 +113,158 @@ async function downloadPackage(socketPkgName) {
120113
}
121114
}
122115

123-
void (async () => {
116+
async function main() {
124117
const packages = cliArgs.package?.length
125118
? cliArgs.package
126119
: constants.npmPackageNames
127120

128-
logger.log(
129-
`Processing package info for ${packages.length} packages with concurrency ${concurrency}...`,
130-
)
131-
logger.log(`Temp directory: ${tempBaseDir}`)
132-
logger.log(
133-
`Progress: ${LOG_SYMBOLS.success} = success, ${LOG_SYMBOLS.fail} = failed, ${LOG_SYMBOLS.warn} = skipped\n`,
134-
)
135-
136-
// Initialize progress tracking.
137-
totalPackagesCount = packages.length
138-
completedPackages = 0
139-
currentLinePosition = 0
140-
process.stdout.write('(0/' + totalPackagesCount + ') ')
141-
currentLinePosition = ('(0/' + totalPackagesCount + ') ').length
142-
143121
// Ensure base temp directory exists.
144122
await fs.mkdir(tempBaseDir, { recursive: true })
145123

146-
const results = []
124+
// Check if download results already exist and are fresh.
125+
const resultsFile = path.join(tempBaseDir, 'download-results.json')
126+
const clearCache = cliArgs.clearCache
127+
128+
// Clear cache if requested.
129+
if (clearCache && existsSync(resultsFile)) {
130+
await fs.unlink(resultsFile)
131+
logger.log('🗑️ Cleared download cache')
132+
}
133+
134+
// Load existing cache if available.
135+
let cachedResults = []
136+
if (!clearCache && existsSync(resultsFile)) {
137+
try {
138+
cachedResults = JSON.parse(await fs.readFile(resultsFile, 'utf8'))
139+
} catch {
140+
logger.warn('Could not read cache, starting fresh...')
141+
}
142+
}
143+
144+
// Determine which packages need processing.
145+
let packagesToProcess = packages
146+
let usedCache = false
147+
148+
if (cachedResults.length > 0) {
149+
if (cliArgs.package?.length) {
150+
// For specific packages, check which ones are already cached.
151+
const cachedPackageNames = new Set(
152+
cachedResults.map(r => r.socketPackage || r.package),
153+
)
154+
const missingPackages = packages.filter(
155+
pkg => !cachedPackageNames.has(pkg),
156+
)
157+
158+
if (missingPackages.length === 0) {
159+
// All requested packages are cached.
160+
const relevantResults = cachedResults.filter(
161+
r =>
162+
packages.includes(r.socketPackage) || packages.includes(r.package),
163+
)
164+
logger.log(
165+
`💾 Using cached download results (${relevantResults.length} ${pluralize('package', relevantResults.length)})`,
166+
)
167+
await fs.writeFile(
168+
resultsFile,
169+
JSON.stringify(relevantResults, null, 2),
170+
)
171+
process.exitCode = 0
172+
return
173+
} else if (missingPackages.length < packages.length) {
174+
// Some packages are cached, only process missing ones.
175+
packagesToProcess = missingPackages
176+
usedCache = true
177+
logger.log(
178+
`💾 Found ${packages.length - missingPackages.length} cached, processing ${missingPackages.length} new ${pluralize('package', missingPackages.length)}...`,
179+
)
180+
}
181+
} else {
182+
// For full run, check if cache has all packages.
183+
const cachedPackageNames = cachedResults
184+
.map(r => r.socketPackage || r.package)
185+
.sort()
186+
const requestedPackages = packages.slice().sort()
187+
if (
188+
JSON.stringify(cachedPackageNames) === JSON.stringify(requestedPackages)
189+
) {
190+
logger.log(
191+
`💾 Using cached download results (${cachedResults.length} ${pluralize('package', cachedResults.length)})`,
192+
)
193+
process.exitCode = 0
194+
return
195+
}
196+
}
197+
}
198+
199+
logger.log(
200+
`Processing ${packagesToProcess.length} ${pluralize('package', packagesToProcess.length)}...`,
201+
)
202+
203+
// Start with cached results if doing incremental update.
204+
const results =
205+
usedCache && cliArgs.package?.length
206+
? cachedResults.filter(
207+
r =>
208+
!packagesToProcess.includes(r.socketPackage) &&
209+
!packagesToProcess.includes(r.package),
210+
)
211+
: []
147212

148213
await pEach(
149-
packages,
214+
packagesToProcess,
150215
async pkgName => {
151216
const result = await downloadPackage(pkgName)
152217
results.push(result)
153218
},
154219
{ concurrency },
155220
)
156221

157-
// Add newline after progress indicators.
158-
process.stdout.write('\n')
159-
160222
const failed = results.filter(r => !r.downloaded && r.reason !== 'Skipped')
223+
const skipped = results.filter(r => r.reason === 'Skipped')
224+
const succeeded = results.filter(r => r.downloaded)
225+
226+
// Summary.
227+
logger.log(
228+
`✅ ${clearCache ? 'Redownloaded' : 'Processed'}: ${succeeded.length}`,
229+
)
230+
if (skipped.length > 0) {
231+
logger.log(`⏭️ Skipped: ${skipped.length}`)
232+
}
233+
if (failed.length > 0) {
234+
logger.fail(`Failed: ${failed.length}`)
235+
}
236+
237+
// Merge new results with existing cache for full dataset.
238+
const finalResults =
239+
cliArgs.package?.length && usedCache
240+
? [
241+
...cachedResults.filter(
242+
r =>
243+
!packages.includes(r.socketPackage) &&
244+
!packages.includes(r.package),
245+
),
246+
...results,
247+
]
248+
: results
161249

162250
// Write results to file for the install phase.
163-
const resultsFile = path.join(tempBaseDir, 'download-results.json')
164-
await fs.writeFile(resultsFile, JSON.stringify(results, null, 2))
251+
await fs.writeFile(
252+
resultsFile,
253+
JSON.stringify(
254+
cliArgs.package?.length
255+
? finalResults.filter(
256+
r =>
257+
packages.includes(r.socketPackage) ||
258+
packages.includes(r.package),
259+
)
260+
: finalResults,
261+
null,
262+
2,
263+
),
264+
)
165265

166266
// Set exit code for process termination.
167267
process.exitCode = failed.length ? 1 : 0
168-
})()
268+
}
269+
270+
main().catch(console.error)

scripts/generate-actions-allow-list.mjs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import fs from 'node:fs/promises'
22
import path from 'node:path'
33

44
import clipboardy from 'clipboardy'
5-
import { logger } from '@socketsecurity/registry/lib/logger'
5+
import { logger } from '../registry/dist/lib/logger.js'
66

77
const GITHUB_PATH = '.github'
88
const WORKFLOWS_PATH = path.join(GITHUB_PATH, 'workflows')
@@ -62,7 +62,7 @@ async function getAllYamlFiles(dir) {
6262
return files
6363
}
6464

65-
void (async () => {
65+
async function main() {
6666
const allDependencies = new Set()
6767

6868
// Process workflow files.
@@ -107,7 +107,8 @@ void (async () => {
107107
externalActions.sort()
108108

109109
// Generate the allow list.
110-
const indent = ' ' // Base indentation.
110+
// Base indentation.
111+
const indent = ' '
111112

112113
logger.log('# GitHub Actions Allow List')
113114
logger.log('# Generated by scripts/generate-actions-allow-list.js')
@@ -151,4 +152,6 @@ void (async () => {
151152
} else {
152153
console.log('💡 Tip: Use --copy flag to copy the allow list to clipboard')
153154
}
154-
})()
155+
}
156+
157+
main().catch(console.error)

0 commit comments

Comments
 (0)