-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpackages.ts
More file actions
142 lines (133 loc) · 3.73 KB
/
packages.ts
File metadata and controls
142 lines (133 loc) · 3.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/** @fileoverview Package management utilities for DLX installations. */
import { readDirNamesSync, safeDelete, safeDeleteSync } from '../fs'
import { getSocketDlxDir } from '../paths/socket'
import { getDlxInstalledPackageDir, getDlxPackageDir } from './paths'
import { ArrayPrototypeFilter, ErrorCtor } from '../primordials'
let _fs: typeof import('node:fs') | undefined
/**
* Lazily load the fs module to avoid Webpack errors.
* Uses non-'node:' prefixed require to prevent Webpack bundling issues.
*
* @returns The Node.js fs module
* @private
*/
/*@__NO_SIDE_EFFECTS__*/
function getFs() {
if (_fs === undefined) {
// Use non-'node:' prefixed require to avoid Webpack errors.
_fs = /*@__PURE__*/ require('node:fs')
}
return _fs as typeof import('node:fs')
}
/**
* Check if a package is installed in DLX.
*
* @example
* ```typescript
* if (isDlxPackageInstalled('prettier')) {
* console.log('prettier is installed')
* }
* ```
*/
export function isDlxPackageInstalled(packageName: string): boolean {
const fs = getFs()
return fs.existsSync(getDlxInstalledPackageDir(packageName))
}
/**
* List all packages installed in DLX.
*
* @example
* ```typescript
* const packages = listDlxPackages()
* console.log('Installed:', packages.join(', '))
* ```
*/
export function listDlxPackages(): string[] {
try {
return readDirNamesSync(getSocketDlxDir(), { sort: true })
} catch {
return []
}
}
/**
* List all packages installed in DLX asynchronously.
*
* @example
* ```typescript
* const packages = await listDlxPackagesAsync()
* console.log('Installed:', packages.join(', '))
* ```
*/
export async function listDlxPackagesAsync(): Promise<string[]> {
const fs = getFs()
try {
const entries = await fs.promises.readdir(getSocketDlxDir(), {
withFileTypes: true,
})
return ArrayPrototypeFilter(entries, e => e.isDirectory())
.map(e => e.name)
.sort()
} catch {
return []
}
}
/**
* Remove a DLX package installation.
*
* @example
* ```typescript
* await removeDlxPackage('prettier')
* ```
*/
export async function removeDlxPackage(packageName: string): Promise<void> {
const packageDir = getDlxPackageDir(packageName)
try {
await safeDelete(packageDir, { recursive: true, force: true })
} catch (e) {
throw new ErrorCtor(`Failed to remove DLX package "${packageName}"`, {
cause: e,
})
}
}
/**
* Remove a DLX package installation synchronously.
*
* @example
* ```typescript
* removeDlxPackageSync('prettier')
* ```
*/
export function removeDlxPackageSync(packageName: string): void {
const packageDir = getDlxPackageDir(packageName)
try {
safeDeleteSync(packageDir, { recursive: true, force: true })
} catch (e) {
const code = (e as NodeJS.ErrnoException).code
if (code === 'EACCES' || code === 'EPERM') {
throw new ErrorCtor(
`Permission denied removing DLX package "${packageName}"\n` +
`Directory: ${packageDir}\n` +
'To resolve:\n' +
' 1. Check file/directory permissions\n' +
' 2. Close any programs using files in this directory\n' +
' 3. Try running with elevated privileges if necessary\n' +
` 4. Manually remove: rm -rf "${packageDir}"`,
{ cause: e },
)
}
if (code === 'EROFS') {
throw new ErrorCtor(
`Cannot remove DLX package "${packageName}" from read-only filesystem\n` +
`Directory: ${packageDir}\n` +
'The filesystem is mounted read-only.',
{ cause: e },
)
}
throw new ErrorCtor(
`Failed to remove DLX package "${packageName}"\n` +
`Directory: ${packageDir}\n` +
'Check permissions and ensure no programs are using this directory.',
{ cause: e },
)
}
}