-
-
Notifications
You must be signed in to change notification settings - Fork 184
/
index.ts
133 lines (105 loc) · 3.61 KB
/
index.ts
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
import { platform } from 'os';
import debug from 'debug';
import { isNullOrUndefined, tryReleaseFile } from '../utils';
const log = debug('MongoMS:getos');
/** Collection of Regexes for "lsb_release -a" parsing */
const LSBRegex = {
// regex format is "lsb_release" (command output) and then "lsb-release" (file output)
name: /^(?:distributor id:|DISTRIB_ID=)\s*(.*)$/im,
codename: /^(?:codename:|DISTRIB_CODENAME=)\s*(.*)$/im,
release: /^(?:release:|DISTRIB_RELEASE=)\s*(.*)$/im,
};
/** Collection of Regexes for "/etc/os-release" parsing */
const OSRegex = {
name: /^id\s*=\s*"?(\w*)"?$/im,
codename: /^version_codename\s*=\s*(.*)$/im,
release: /^version_id\s*=\s*"?(\d*(?:\.\d*)?)"?$/im,
id_like: /^id_like\s*=\s*"?([\w\s]*)"?$/im,
};
export interface OtherOS {
os: 'aix' | 'android' | 'darwin' | 'freebsd' | 'openbsd' | 'sunos' | 'win32' | 'cygwin' | string;
}
export interface LinuxOS extends OtherOS {
os: 'linux';
dist: string;
release: string;
codename?: string;
id_like?: string[];
}
export type AnyOS = OtherOS | LinuxOS;
/**
* Check if the OS is a LinuxOS Typeguard
* @param os The OS object to check for
*/
export function isLinuxOS(os: AnyOS): os is LinuxOS {
return os.os === 'linux';
}
/** Get an OS object */
export async function getOS(): Promise<AnyOS> {
/** Node builtin function for first determinations */
const osName = platform();
// Linux is a special case.
if (osName === 'linux') {
return await getLinuxInformation();
}
return { os: osName };
}
export default getOS;
/** Function to outsource Linux Information Parsing */
async function getLinuxInformation(): Promise<LinuxOS> {
// Structure of this function:
// 1. get upstream release, if possible
// 2. get os release (etc) because it has an "id_like"
// 3. get os release (usr) because it has an "id_like"
// 4. get lsb-release (etc) as fallback
const upstreamLSB = await tryReleaseFile('/etc/upstream-release/lsb-release', parseLSB);
if (!isNullOrUndefined(upstreamLSB)) {
log('getLinuxInformation: Using UpstreamLSB');
return upstreamLSB;
}
const etcOsRelease = await tryReleaseFile('/etc/os-release', parseOS);
if (!isNullOrUndefined(etcOsRelease)) {
log('getLinuxInformation: Using etcOsRelease');
return etcOsRelease;
}
const usrOsRelease = await tryReleaseFile('/usr/lib/os-release', parseOS);
if (!isNullOrUndefined(usrOsRelease)) {
log('getLinuxInformation: Using usrOsRelease');
return usrOsRelease;
}
const etcLSBRelease = await tryReleaseFile('/etc/lsb-release', parseLSB);
if (!isNullOrUndefined(etcLSBRelease)) {
log('getLinuxInformation: Using etcLSBRelease');
return etcLSBRelease;
}
console.warn('Could not find any Release File, using fallback binary');
// if none has worked, return unknown
return {
os: 'linux',
dist: 'unknown',
release: '',
};
}
/**
* Parse LSB-like output (either command or file)
*/
export function parseLSB(input: string): LinuxOS {
return {
os: 'linux',
dist: input.match(LSBRegex.name)?.[1].toLocaleLowerCase() ?? 'unknown',
codename: input.match(LSBRegex.codename)?.[1].toLocaleLowerCase(),
release: input.match(LSBRegex.release)?.[1].toLocaleLowerCase() ?? '',
};
}
/**
* Parse OSRelease-like output
*/
export function parseOS(input: string): LinuxOS {
return {
os: 'linux',
dist: input.match(OSRegex.name)?.[1].toLocaleLowerCase() ?? 'unknown',
codename: input.match(OSRegex.codename)?.[1].toLocaleLowerCase(),
release: input.match(OSRegex.release)?.[1].toLocaleLowerCase() ?? '',
id_like: input.match(OSRegex.id_like)?.[1].toLocaleLowerCase().split(' '),
};
}