Skip to content

Commit 34a2689

Browse files
committed
refactor: adopt safeMkdir utilities from @socketsecurity/lib
Replace fs.mkdir/fs.mkdirSync with safeMkdir/safeMkdirSync across codebase. These utilities gracefully handle EEXIST errors for concurrent directory creation, eliminating manual error handling code.
1 parent c72bfdd commit 34a2689

File tree

17 files changed

+57
-48
lines changed

17 files changed

+57
-48
lines changed

packages/cli/src/bootstrap/node.mts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import { spawn } from 'node:child_process'
1818
import { existsSync, promises as fs } from 'node:fs'
1919
import path from 'node:path'
2020

21+
import { safeMkdir } from '@socketsecurity/lib/fs'
22+
2123
import { getNodeDisableSigusr1Flags } from './shared/node-flags.mjs'
2224
import {
2325
getCliEntryPoint,
@@ -44,7 +46,7 @@ async function downloadCli(): Promise<void> {
4446
const dlxDir = getDlxDir()
4547
const cliDir = getCliPackageDir()
4648

47-
await fs.mkdir(dlxDir, { recursive: true })
49+
await safeMkdir(dlxDir)
4850

4951
console.error(`Downloading ${packageName}...`)
5052

@@ -75,7 +77,7 @@ async function downloadCli(): Promise<void> {
7577
try {
7678
const tarballPath = path.join(dlxDir, tarballName.trim())
7779

78-
await fs.mkdir(cliDir, { recursive: true })
80+
await safeMkdir(cliDir)
7981

8082
const tarExtractProcess = spawn(
8183
'tar',

packages/cli/src/commands/fix/ghsa-tracker.mts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import { promises as fs } from 'node:fs'
21
import path from 'node:path'
32

43
import { debug, debugDir } from '@socketsecurity/lib/debug'
5-
import { readJson, writeJson } from '@socketsecurity/lib/fs'
4+
import { readJson, safeMkdir, writeJson } from '@socketsecurity/lib/fs'
65

76
import { getSocketFixBranchName } from './git.mts'
87

@@ -47,7 +46,7 @@ export async function saveGhsaTracker(
4746
const trackerPath = path.join(cwd, TRACKER_FILE)
4847

4948
// Ensure .socket directory exists.
50-
await fs.mkdir(path.dirname(trackerPath), { recursive: true })
49+
await safeMkdir(path.dirname(trackerPath))
5150

5251
await writeJson(trackerPath, tracker, { spaces: 2 })
5352
debug(`ghsa-tracker: saved ${tracker.fixed.length} records to ${trackerPath}`)

packages/cli/src/commands/install/setup-tab-completion.mts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import fs from 'node:fs'
22
import path from 'node:path'
33

44
import { debug } from '@socketsecurity/lib/debug'
5+
import { safeMkdirSync } from '@socketsecurity/lib/fs'
56

67
import ENV from '../../constants/env.mts'
78
import { homePath, rootPath } from '../../constants/paths.mts'
@@ -35,7 +36,7 @@ export async function setupTabCompletion(targetName: string): Promise<
3536

3637
if (!fs.existsSync(targetDir)) {
3738
debug('create: target dir')
38-
fs.mkdirSync(targetDir, { recursive: true })
39+
safeMkdirSync(targetDir)
3940
}
4041

4142
updateInstalledTabCompletionScript(targetPath)

packages/cli/src/commands/patch/handle-patch-get.mts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
DOT_SOCKET_DIR,
77
MANIFEST_JSON,
88
} from '@socketsecurity/lib/constants/paths'
9+
import { safeMkdir } from '@socketsecurity/lib/fs'
910
import { logger } from '@socketsecurity/lib/logger'
1011
import { normalizePath } from '@socketsecurity/lib/path'
1112
import { pluralize } from '@socketsecurity/lib/words'
@@ -64,7 +65,7 @@ export async function handlePatchGet({
6465

6566
// Create output directory if it doesn't exist.
6667
if (!existsSync(targetDir)) {
67-
await fs.mkdir(targetDir, { recursive: true })
68+
await safeMkdir(targetDir)
6869
}
6970

7071
spinner?.text('Copying patch files')
@@ -87,7 +88,7 @@ export async function handlePatchGet({
8788
// Create subdirectories if needed.
8889
if (!existsSync(targetFileDir)) {
8990
// eslint-disable-next-line no-await-in-loop
90-
await fs.mkdir(targetFileDir, { recursive: true })
91+
await safeMkdir(targetFileDir)
9192
}
9293

9394
// eslint-disable-next-line no-await-in-loop

packages/cli/src/commands/scan/create-scan-from-github.mts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ import {
22
createWriteStream,
33
existsSync,
44
promises as fs,
5-
mkdirSync,
65
mkdtempSync,
76
} from 'node:fs'
87
import os from 'node:os'
98
import path from 'node:path'
109
import { pipeline } from 'node:stream/promises'
1110

1211
import { debug, debugDir } from '@socketsecurity/lib/debug'
12+
import { safeMkdirSync } from '@socketsecurity/lib/fs'
1313
import { logger } from '@socketsecurity/lib/logger'
1414
import { confirm, select } from '@socketsecurity/lib/prompts'
1515

@@ -467,7 +467,7 @@ async function streamDownloadWithFetch(
467467
// before starting the download.
468468
const dir = path.dirname(localPath)
469469
if (!existsSync(dir)) {
470-
mkdirSync(dir, { recursive: true })
470+
safeMkdirSync(dir)
471471
}
472472

473473
const fileStream = createWriteStream(localPath)

packages/cli/src/commands/self-update/handle-self-update.mts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import path from 'node:path'
1212
import colors from 'yoctocolors-cjs'
1313

1414
import { detectPackageManager } from '@socketsecurity/lib/env/package-manager'
15+
import { safeMkdir } from '@socketsecurity/lib/fs'
1516
import { getIpcStubPath } from '@socketsecurity/lib/ipc'
1617
import { logger } from '@socketsecurity/lib/logger'
1718

@@ -157,8 +158,8 @@ async function updateStubBinary(
157158
const downloadsDir = getSocketCliUpdaterDownloadsDir()
158159
const stagingDir = getSocketCliUpdaterStagingDir()
159160

160-
await fs.mkdir(downloadsDir, { recursive: true })
161-
await fs.mkdir(stagingDir, { recursive: true })
161+
await safeMkdir(downloadsDir)
162+
await safeMkdir(stagingDir)
162163

163164
const timestamp = Date.now()
164165
const tarballPath = path.join(downloadsDir, `stub-${timestamp}.tgz`)
@@ -376,7 +377,7 @@ Examples
376377

377378
// Create temporary directory for download.
378379
const tempDir = path.join(os.tmpdir(), `socket-update-${Date.now()}`)
379-
await fs.mkdir(tempDir, { recursive: true })
380+
await safeMkdir(tempDir)
380381

381382
try {
382383
const tarballPath = path.join(tempDir, 'package.tgz')

packages/cli/src/index.mts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010

1111
// CommonJS globals are available since we're outputting to CJS format.
1212
const {
13-
mkdirSync,
1413
readFileSync,
1514
unlinkSync,
1615
writeFileSync,
1716
} = require('node:fs')
17+
const { safeMkdirSync } = require('@socketsecurity/lib/fs')
1818
const Module = require('node:module')
1919
const path = require('node:path')
2020
const { brotliDecompressSync } = require('node:zlib')
@@ -27,7 +27,7 @@ const compressed = readFileSync(cliBzPath)
2727
const decompressed = brotliDecompressSync(compressed)
2828

2929
// Ensure build/ directory exists.
30-
mkdirSync(buildPath, { recursive: true })
30+
safeMkdirSync(buildPath)
3131

3232
// Write to build/ directory (gitignored, local to package).
3333
const tempCliPath = path.join(buildPath, `cli-runtime-${process.pid}.js`)

packages/cli/src/utils/config.test.mts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { mkdirSync, mkdtempSync, promises as fs, writeFileSync } from 'node:fs'
1+
import { mkdtempSync, promises as fs, writeFileSync } from 'node:fs'
22
import os from 'node:os'
33
import path from 'node:path'
44

5+
import { safeMkdirSync } from '@socketsecurity/lib/fs'
56
import { beforeEach, describe, expect, it } from 'vitest'
67

78
import {
@@ -59,7 +60,7 @@ describe('utils/config', () => {
5960

6061
try {
6162
// Create nested directories.
62-
mkdirSync(nestedDir, { recursive: true })
63+
safeMkdirSync(nestedDir)
6364

6465
// Create socket.yml in the tmpdir root.
6566
writeFileSync(

packages/cli/src/utils/dlx/binary.mts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import os from 'node:os'
2929
import path from 'node:path'
3030

3131
import { generateCacheKey } from '@socketsecurity/lib/dlx'
32-
import { readJson } from '@socketsecurity/lib/fs'
32+
import { readJson, safeMkdir } from '@socketsecurity/lib/fs'
3333
import { normalizePath } from '@socketsecurity/lib/path'
3434
import { getSocketDlxDir } from '@socketsecurity/lib/paths'
3535
import { spawn } from '@socketsecurity/lib/spawn'
@@ -202,7 +202,7 @@ async function downloadBinary(
202202

203203
try {
204204
// Ensure directory exists.
205-
await fs.mkdir(path.dirname(destPath), { recursive: true })
205+
await safeMkdir(path.dirname(destPath))
206206

207207
// Get the response as a buffer and compute hash.
208208
const arrayBuffer = await response.arrayBuffer()
@@ -391,7 +391,7 @@ export async function dlxBinary(
391391

392392
if (downloaded) {
393393
// Ensure cache directory exists.
394-
await fs.mkdir(cacheEntryDir, { recursive: true })
394+
await safeMkdir(cacheEntryDir)
395395

396396
// Download the binary.
397397
computedChecksum = await downloadBinary(url, binaryPath, checksum)

packages/cli/src/utils/git/github.mts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,12 @@ import {
3939
debugNs,
4040
isDebugNs,
4141
} from '@socketsecurity/lib/debug'
42-
import { readJson, safeStatsSync, writeJson } from '@socketsecurity/lib/fs'
42+
import {
43+
readJson,
44+
safeMkdir,
45+
safeStatsSync,
46+
writeJson,
47+
} from '@socketsecurity/lib/fs'
4348
import { spawn } from '@socketsecurity/lib/spawn'
4449
import { parseUrl } from '@socketsecurity/lib/url'
4550

@@ -77,7 +82,7 @@ export async function writeCache(
7782
const githubCachePath = getGithubCachePath()
7883
const cacheJsonPath = path.join(githubCachePath, `${key}.json`)
7984
if (!existsSync(githubCachePath)) {
80-
await fs.mkdir(githubCachePath, { recursive: true })
85+
await safeMkdir(githubCachePath)
8186
}
8287
await writeJson(cacheJsonPath, data as JsonContent)
8388
}

0 commit comments

Comments
 (0)