-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpackages.ts
More file actions
129 lines (120 loc) · 3.41 KB
/
packages.ts
File metadata and controls
129 lines (120 loc) · 3.41 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
/** @fileoverview Package management utilities for DLX installations. */
import { readDirNamesSync } from '../fs/read-dir'
import { safeDelete, safeDeleteSync } from '../fs/safe'
import { getSocketDlxDir } from '../paths/socket'
import { getDlxInstalledPackageDir, getDlxPackageDir } from './paths'
import { ArrayPrototypeFilter } from '../primordials/array'
import { ErrorCtor } from '../primordials/error'
import { getNodeFs } from '../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 = getNodeFs()
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 = getNodeFs()
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 },
)
}
}