-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.ts
More file actions
116 lines (92 loc) · 3.34 KB
/
Copy pathindex.ts
File metadata and controls
116 lines (92 loc) · 3.34 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
import * as fsSync from 'node:fs';
import * as fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import { Readable } from 'node:stream';
import { finished } from 'node:stream/promises';
import { SpawnStatus, codifySpawn } from './codify-spawn.js';
import { SpotlightKind, SpotlightUtils } from './spotlight-search.js';
export const Utils = {
async findApplication(name: string): Promise<string[]> {
const [
spotlightResult,
applicationDir
] = await Promise.all([
SpotlightUtils.mdfind(name, SpotlightKind.APPLICATION),
Utils.findInFolder('/Applications', name)
])
return [...new Set([...spotlightResult, ...applicationDir])]
},
async findInFolder(dir: string, search: string): Promise<string[]> {
const data = await fs.readdir(dir);
return data
.filter((l) => l.includes(search))
.map((l) => path.join(dir, l));
},
async createBinDirectoryIfNotExists(): Promise<void> {
let lstat = null;
try {
lstat = await fs.lstat('/usr/local/bin')
} catch {}
if (lstat && lstat.isDirectory()) {
return;
}
if (lstat && !lstat.isDirectory()) {
throw new Error('Found file at /usr/local/bin. Cannot create a directory there')
}
await codifySpawn('sudo mkdir -p -m 775 /usr/local/bin')
},
async createDirectoryIfNotExists(path: string): Promise<void> {
let lstat = null;
try {
lstat = await fs.lstat(path)
} catch {}
if (lstat && lstat.isDirectory()) {
return;
}
if (lstat && !lstat.isDirectory()) {
throw new Error(`Found file at ${path}. Cannot create a directory there`)
}
await fs.mkdir(path, { recursive: true })
},
async findInstallLocation(name: string): Promise<null | string> {
const query = await codifySpawn(`which ${name}`, { throws: false });
if (query.status === SpawnStatus.ERROR) {
return null;
}
return query.data.trim();
},
async isArmArch(): Promise<boolean> {
const query = await codifySpawn('sysctl -n machdep.cpu.brand_string');
return /M(\d)/.test(query.data);
},
async isDirectoryOnPath(directory: string): Promise<boolean> {
const pathQuery = await codifySpawn('echo $PATH');
return pathQuery.data.includes(directory);
},
async isHomebrewInstalled(): Promise<boolean> {
const query = await codifySpawn('which brew', { throws: false });
return query.status === SpawnStatus.SUCCESS;
},
async isRosetta2Installed(): Promise<boolean> {
const query = await codifySpawn('arch -x86_64 /usr/bin/true 2> /dev/null', { throws: false });
return query.status === SpawnStatus.SUCCESS;
},
shellEscape(arg: string): string {
if (/[^\w/:=-]/.test(arg)) return arg.replaceAll(/([ !"#$%&'()*;<>?@[\\\]`{}~])/g, '\\$1')
return arg;
},
async downloadUrlIntoFile(filePath: string, url: string): Promise<void> {
const { body } = await fetch(url)
const dirname = path.dirname(filePath);
if (!await fs.stat(dirname).then((s) => s.isDirectory()).catch(() => false)) {
await fs.mkdir(dirname, { recursive: true });
}
const ws = fsSync.createWriteStream(filePath)
// Different type definitions here for readable stream (NodeJS vs DOM). Small hack to fix that
await finished(Readable.fromWeb(body as never).pipe(ws));
},
getUser(): string {
return os.userInfo().username;
}
};