platformdirs 4.3.6 → 4.3.8-rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -6
- package/package.json +15 -17
- package/src/android.js +203 -0
- package/src/api.js +444 -0
- package/src/configparser.js +73 -0
- package/src/index.js +656 -0
- package/src/macos.js +199 -0
- package/src/main.js +50 -0
- package/src/unix.js +350 -0
- package/src/version.js +16 -0
- package/src/windows.js +279 -0
package/src/macos.js
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* macOS.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as os from "node:os";
|
|
7
|
+
import * as path from "node:path";
|
|
8
|
+
import process from "node:process";
|
|
9
|
+
import { PlatformDirsABC } from "./api.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Platform directories for the macOS operating system.
|
|
13
|
+
*
|
|
14
|
+
* Follows the guidance from [Apple documentation](https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/MacOSXDirectories/MacOSXDirectories.html). Makes use of the {@link PlatformDirsABC.appname}, {@link PlatformDirsABC.version}, {@link PlatformDirsABC.ensureExists}.
|
|
15
|
+
*/
|
|
16
|
+
export class MacOS extends PlatformDirsABC {
|
|
17
|
+
/**
|
|
18
|
+
* @return {string} data directory tied to the user, e.g. `~/Library/Application Support/$appname/$version`
|
|
19
|
+
* @override
|
|
20
|
+
*/
|
|
21
|
+
get userDataDir() {
|
|
22
|
+
return this._appendAppNameAndVersion(
|
|
23
|
+
path.join(os.homedir(), "Library/Application Support"),
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @return {string} data directory shared by users, e.g. `/Library/Application
|
|
29
|
+
* Support/$appname/$version`. If we're using a Node.js, Deno, or Bun binary
|
|
30
|
+
* managed by [Homebrew](https://brew.sh), the directory will be under the
|
|
31
|
+
* Homebrew prefix, e.g. `/opt/homebrew/share/$appname/$version`. If
|
|
32
|
+
* {@link PlatformDirsABC.multipath} is enabled, and we're in Homebrew, the
|
|
33
|
+
* response is a multi-path string separated by ":", e.g.
|
|
34
|
+
* `/opt/homebrew/share/$appname/$version:/Library/Application
|
|
35
|
+
* Support/$appname/$version`.
|
|
36
|
+
* @override
|
|
37
|
+
*/
|
|
38
|
+
get siteDataDir() {
|
|
39
|
+
const isHomebrew = process.execPath.startsWith("/opt/homebrew");
|
|
40
|
+
const pathList = isHomebrew
|
|
41
|
+
? [this._appendAppNameAndVersion("/opt/homebrew/share")]
|
|
42
|
+
: [];
|
|
43
|
+
pathList.push(
|
|
44
|
+
this._appendAppNameAndVersion("/Library/Application Support"),
|
|
45
|
+
);
|
|
46
|
+
if (this.multipath) {
|
|
47
|
+
return pathList.join(path.delimiter);
|
|
48
|
+
}
|
|
49
|
+
return pathList[0];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @return {string} data path shared by users. Only return the first item, even if
|
|
54
|
+
* `multipath` is enabled is set to `true`.
|
|
55
|
+
* @override
|
|
56
|
+
*/
|
|
57
|
+
get siteDataPath() {
|
|
58
|
+
return this._firstItemAsPathIfMultipath(this.siteDataDir);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @return {string} config directory tied to the user, same as `userDataDir`
|
|
63
|
+
* @override
|
|
64
|
+
*/
|
|
65
|
+
get userConfigDir() {
|
|
66
|
+
return this.userDataDir;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @return {string} config directory shared by users, same as `siteDataDir`
|
|
71
|
+
* @override
|
|
72
|
+
*/
|
|
73
|
+
get siteConfigDir() {
|
|
74
|
+
return this.siteDataDir;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @return {string} cache directory tied to the user, e.g. `~/Library/Caches/$appname/$version`
|
|
79
|
+
* @override
|
|
80
|
+
*/
|
|
81
|
+
get userCacheDir() {
|
|
82
|
+
return this._appendAppNameAndVersion(
|
|
83
|
+
path.join(os.homedir(), "Library/Caches"),
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @return {string} cache directory shared by users, e.g. `/Library/Caches/$appname/$version`.
|
|
89
|
+
* If we're using a Node.js, Deno, or Bun binary managed by [Homebrew](https://brew.sh),
|
|
90
|
+
* the directory will be under the Homebrew prefix, e.g. `/opt/homebrew/var/cache/$appname/$version`.
|
|
91
|
+
* If {@link PlatformDirsABC.multipath} is enabled, and we're in Homebrew, the response is a multi-path string separated by ":", e.g.
|
|
92
|
+
* `/opt/homebrew/var/cache/$appname/$version:/Library/Caches/$appname/$version`.
|
|
93
|
+
* @override
|
|
94
|
+
*/
|
|
95
|
+
get siteCacheDir() {
|
|
96
|
+
const isHomebrew = process.execPath.startsWith("/opt/homebrew");
|
|
97
|
+
const pathList = isHomebrew
|
|
98
|
+
? [this._appendAppNameAndVersion("/opt/homebrew/var/cache")]
|
|
99
|
+
: [];
|
|
100
|
+
pathList.push(this._appendAppNameAndVersion("/Library/Caches"));
|
|
101
|
+
if (this.multipath) {
|
|
102
|
+
return pathList.join(path.delimiter);
|
|
103
|
+
}
|
|
104
|
+
return pathList[0];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @return {string} cache path shared by users. Only return the first item, even if
|
|
109
|
+
* `multipath` is enabled is set to `true`.
|
|
110
|
+
* @override
|
|
111
|
+
*/
|
|
112
|
+
get siteCachePath() {
|
|
113
|
+
return this._firstItemAsPathIfMultipath(this.siteCacheDir);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @return {string} state directory tied to the user, e.g. `~/Library/Application Support/$appname/$version`
|
|
118
|
+
* @override
|
|
119
|
+
*/
|
|
120
|
+
get userStateDir() {
|
|
121
|
+
return this.userDataDir;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @return {string} log directory tied to the user, e.g. `~/Library/Logs/$appname/$version`
|
|
126
|
+
* @override
|
|
127
|
+
*/
|
|
128
|
+
get userLogDir() {
|
|
129
|
+
return this._appendAppNameAndVersion(
|
|
130
|
+
path.join(os.homedir(), "Library/Logs"),
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* @return {string} documents directory tied to the user, e.g. `~/Documents`
|
|
136
|
+
* @override
|
|
137
|
+
*/
|
|
138
|
+
get userDocumentsDir() {
|
|
139
|
+
return path.join(os.homedir(), "Documents");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* @return {string} downloads directory tied to the user, e.g. `~/Downloads`
|
|
144
|
+
* @override
|
|
145
|
+
*/
|
|
146
|
+
get userDownloadsDir() {
|
|
147
|
+
return path.join(os.homedir(), "Downloads");
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* @return {string} pictures directory tied to the user, e.g. `~/Pictures`
|
|
152
|
+
* @override
|
|
153
|
+
*/
|
|
154
|
+
get userPicturesDir() {
|
|
155
|
+
return path.join(os.homedir(), "Pictures");
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* @return {string} videos directory tied to the user, e.g. `~/Movies`
|
|
160
|
+
* @override
|
|
161
|
+
*/
|
|
162
|
+
get userVideosDir() {
|
|
163
|
+
return path.join(os.homedir(), "Movies");
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* @return {string} music directory tied to the user, e.g. `~/Music`
|
|
168
|
+
* @override
|
|
169
|
+
*/
|
|
170
|
+
get userMusicDir() {
|
|
171
|
+
return path.join(os.homedir(), "Music");
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* @return {string} desktop directory tied to the user, e.g. `~/Desktop`
|
|
176
|
+
* @override
|
|
177
|
+
*/
|
|
178
|
+
get userDesktopDir() {
|
|
179
|
+
return path.join(os.homedir(), "Desktop");
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* @return {string} runtime directory tied to the user, e.g. `~/Library/Caches/TemporaryItems`
|
|
184
|
+
* @override
|
|
185
|
+
*/
|
|
186
|
+
get userRuntimeDir() {
|
|
187
|
+
return this._appendAppNameAndVersion(
|
|
188
|
+
path.join(os.homedir(), "Library/Caches/TemporaryItems"),
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* @return {string} runtime directory shared by users, same as `userRuntimeDir`
|
|
194
|
+
* @override
|
|
195
|
+
*/
|
|
196
|
+
get siteRuntimeDir() {
|
|
197
|
+
return this.userRuntimeDir;
|
|
198
|
+
}
|
|
199
|
+
}
|
package/src/main.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { PlatformDirs, version } from "./index.js";
|
|
3
|
+
|
|
4
|
+
/** @type {Record<string, keyof PlatformDirs>} */
|
|
5
|
+
const props = {
|
|
6
|
+
user_data_dir: "userDataDir",
|
|
7
|
+
user_config_dir: "userConfigDir",
|
|
8
|
+
user_cache_dir: "userCacheDir",
|
|
9
|
+
user_state_dir: "userStateDir",
|
|
10
|
+
user_log_dir: "userLogDir",
|
|
11
|
+
user_documents_dir: "userDocumentsDir",
|
|
12
|
+
user_downloads_dir: "userDownloadsDir",
|
|
13
|
+
user_pictures_dir: "userPicturesDir",
|
|
14
|
+
user_videos_dir: "userVideosDir",
|
|
15
|
+
user_music_dir: "userMusicDir",
|
|
16
|
+
user_runtime_dir: "userRuntimeDir",
|
|
17
|
+
site_data_dir: "siteDataDir",
|
|
18
|
+
site_config_dir: "siteConfigDir",
|
|
19
|
+
site_cache_dir: "siteCacheDir",
|
|
20
|
+
site_runtime_dir: "siteRuntimeDir",
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const appName = "MyApp";
|
|
24
|
+
const appAuthor = "MyCompany";
|
|
25
|
+
|
|
26
|
+
console.log(`-- platformdirs ${version} --`);
|
|
27
|
+
|
|
28
|
+
console.log("-- app dirs (with optional 'version')");
|
|
29
|
+
let dirs = new PlatformDirs(appName, appAuthor, "1.0");
|
|
30
|
+
for (const [label, key] of Object.entries(props)) {
|
|
31
|
+
console.log(`${label}: ${dirs[key]}`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
console.log("\n-- app dirs (without optional 'version')");
|
|
35
|
+
dirs = new PlatformDirs(appName, appAuthor);
|
|
36
|
+
for (const [label, key] of Object.entries(props)) {
|
|
37
|
+
console.log(`${label}: ${dirs[key]}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
console.log("\n-- app dirs (without optional 'appauthor')");
|
|
41
|
+
dirs = new PlatformDirs(appName);
|
|
42
|
+
for (const [label, key] of Object.entries(props)) {
|
|
43
|
+
console.log(`${label}: ${dirs[key]}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
console.log("\n-- app dirs (with disabled 'appauthor')");
|
|
47
|
+
dirs = new PlatformDirs(appName, false);
|
|
48
|
+
for (const [label, key] of Object.entries(props)) {
|
|
49
|
+
console.log(`${label}: ${dirs[key]}`);
|
|
50
|
+
}
|
package/src/unix.js
ADDED
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* Unix.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as fs from "node:fs";
|
|
7
|
+
import * as os from "node:os";
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
import process from "node:process";
|
|
10
|
+
import { PlatformDirsABC } from "./api.js";
|
|
11
|
+
import { ConfigParser } from "./configparser.js";
|
|
12
|
+
|
|
13
|
+
/** @return {number} */
|
|
14
|
+
function getuid() {
|
|
15
|
+
if (!process.getuid) {
|
|
16
|
+
throw new Error("should only be used on Unix");
|
|
17
|
+
}
|
|
18
|
+
return process.getuid();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* On Unix/Linux, we follow the [XDG Basedir
|
|
23
|
+
* Spec](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html).
|
|
24
|
+
*
|
|
25
|
+
* The spec allows overriding directories via environment variables. The
|
|
26
|
+
* examples shown are the default values, alongside the name of the environment
|
|
27
|
+
* variable that overrides them. Makes use of the
|
|
28
|
+
* {@link PlatformDirsABC.appname}, {@link PlatformDirsABC.version},
|
|
29
|
+
* {@link PlatformDirsABC.multipath}, {@link PlatformDirsABC.opinion},
|
|
30
|
+
* {@link PlatformDirsABC.ensureExists}.
|
|
31
|
+
*/
|
|
32
|
+
export class Unix extends PlatformDirsABC {
|
|
33
|
+
/**
|
|
34
|
+
* @return {string} data directory tied to the user, e.g. `~/.local/share/$appname/$version` or `$XDG_DATA_HOME/$appname/$version`
|
|
35
|
+
* @override
|
|
36
|
+
*/
|
|
37
|
+
get userDataDir() {
|
|
38
|
+
let path2 = process.env.XDG_DATA_HOME ?? "";
|
|
39
|
+
if (!path2.trim()) {
|
|
40
|
+
path2 = path.join(os.homedir(), ".local/share");
|
|
41
|
+
}
|
|
42
|
+
return this._appendAppNameAndVersion(path2);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @return {string[]}
|
|
47
|
+
* @protected @ignore @internal
|
|
48
|
+
*/
|
|
49
|
+
get _siteDataDirs() {
|
|
50
|
+
let path2 = process.env.XDG_DATA_DIRS ?? "";
|
|
51
|
+
if (!path2.trim()) {
|
|
52
|
+
path2 = `/usr/local/share${path.delimiter}/usr/share`;
|
|
53
|
+
}
|
|
54
|
+
return path2
|
|
55
|
+
.split(path.delimiter)
|
|
56
|
+
.map((p) => this._appendAppNameAndVersion(p));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @return {string} data directories shared by users (if
|
|
61
|
+
* {@link PlatformDirsABC.multipath} is enabled and `XDG_DATA_DIRS` is and a
|
|
62
|
+
* multi path the response is also a multi path separated by the OS path
|
|
63
|
+
* separator), e.g.
|
|
64
|
+
* `/usr/local/share/$appname/$version:/usr/share/$appname/$version`
|
|
65
|
+
* @override
|
|
66
|
+
*/
|
|
67
|
+
get siteDataDir() {
|
|
68
|
+
const dirs = this._siteDataDirs;
|
|
69
|
+
if (!this.multipath) {
|
|
70
|
+
return dirs[0];
|
|
71
|
+
}
|
|
72
|
+
return dirs.join(path.delimiter);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @return {string} config directory tied to the user, e.g. `~/.config/$appname/$version` or `$XDG_CONFIG_HOME/$appname/$version`
|
|
77
|
+
* @override
|
|
78
|
+
*/
|
|
79
|
+
get userConfigDir() {
|
|
80
|
+
let path2 = process.env.XDG_CONFIG_HOME ?? "";
|
|
81
|
+
if (!path2.trim()) {
|
|
82
|
+
path2 = path.join(os.homedir(), ".config");
|
|
83
|
+
}
|
|
84
|
+
return this._appendAppNameAndVersion(path2);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @return {string[]}
|
|
89
|
+
* @ignore @internal
|
|
90
|
+
*/
|
|
91
|
+
get _siteConfigDirs() {
|
|
92
|
+
let path2 = process.env.XDG_CONFIG_DIRS ?? "";
|
|
93
|
+
if (!path2.trim()) {
|
|
94
|
+
path2 = "/etc/xdg";
|
|
95
|
+
}
|
|
96
|
+
return path2
|
|
97
|
+
.split(path.delimiter)
|
|
98
|
+
.map((p) => this._appendAppNameAndVersion(p));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @return {string} config directories shared by users (if
|
|
103
|
+
* {@link PlatformDirsABC.multipath} is enabled and `XDG_CONFIG_DIRS` is and
|
|
104
|
+
* a multi path the response is also a multi path separated by the OS path
|
|
105
|
+
* separator), e.g. `/etc/xdg/$appname/$version`
|
|
106
|
+
* @override
|
|
107
|
+
*/
|
|
108
|
+
get siteConfigDir() {
|
|
109
|
+
const dirs = this._siteConfigDirs;
|
|
110
|
+
if (!this.multipath) {
|
|
111
|
+
return dirs[0];
|
|
112
|
+
}
|
|
113
|
+
return dirs.join(path.delimiter);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @return {string} cache directory tied to the user, e.g. `~/.cache/$appname/$version` or `$XDG_CACHE_HOME/$appname/$version`
|
|
118
|
+
* @override
|
|
119
|
+
*/
|
|
120
|
+
get userCacheDir() {
|
|
121
|
+
let path2 = process.env.XDG_CACHE_HOME ?? "";
|
|
122
|
+
if (!path2.trim()) {
|
|
123
|
+
path2 = path.join(os.homedir(), ".cache");
|
|
124
|
+
}
|
|
125
|
+
return this._appendAppNameAndVersion(path2);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @return {string} cache directory shared by users, e.g. `/var/cache/$appname/$version`
|
|
130
|
+
* @override
|
|
131
|
+
*/
|
|
132
|
+
get siteCacheDir() {
|
|
133
|
+
return this._appendAppNameAndVersion("/var/cache");
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* @return {string} state directory tied to the user, e.g. `~/.local/state/$appname/$version` or `$XDG_STATE_HOME/$appname/$version`
|
|
138
|
+
* @override
|
|
139
|
+
*/
|
|
140
|
+
get userStateDir() {
|
|
141
|
+
let path2 = process.env.XDG_STATE_HOME ?? "";
|
|
142
|
+
if (!path2.trim()) {
|
|
143
|
+
path2 = path.join(os.homedir(), ".local/state");
|
|
144
|
+
}
|
|
145
|
+
return this._appendAppNameAndVersion(path2);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* @return {string} log directory tied to the user, same as `userCacheDir` if not opinionated else `log` in it.
|
|
150
|
+
* @override
|
|
151
|
+
*/
|
|
152
|
+
get userLogDir() {
|
|
153
|
+
let path2 = this.userStateDir;
|
|
154
|
+
if (this.opinion) {
|
|
155
|
+
path2 = path.join(path2, "log");
|
|
156
|
+
this._optionallyCreateDirectory(path2);
|
|
157
|
+
}
|
|
158
|
+
return path2;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* @return {string} documents directory tied to the user, e.g. `~/Documents`
|
|
163
|
+
* @override
|
|
164
|
+
*/
|
|
165
|
+
get userDocumentsDir() {
|
|
166
|
+
return getUserMediaDir("XDG_DOCUMENTS_DIR", "~/Documents");
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* @return {string} downloads directory tied to the user, e.g. `~/Downloads`
|
|
171
|
+
* @override
|
|
172
|
+
*/
|
|
173
|
+
get userDownloadsDir() {
|
|
174
|
+
return getUserMediaDir("XDG_DOWNLOAD_DIR", "~/Downloads");
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* @return {string} pictures directory tied to the user, e.g. `~/Pictures`
|
|
179
|
+
* @override
|
|
180
|
+
*/
|
|
181
|
+
get userPicturesDir() {
|
|
182
|
+
return getUserMediaDir("XDG_PICTURES_DIR", "~/Pictures");
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* @return {string} videos directory tied to the user, e.g. `~/Videos`
|
|
187
|
+
* @override
|
|
188
|
+
*/
|
|
189
|
+
get userVideosDir() {
|
|
190
|
+
return getUserMediaDir("XDG_VIDEOS_DIR", "~/Videos");
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* @return {string} music directory tied to the user, e.g. `~/Music`
|
|
195
|
+
* @override
|
|
196
|
+
*/
|
|
197
|
+
get userMusicDir() {
|
|
198
|
+
return getUserMediaDir("XDG_MUSIC_DIR", "~/Music");
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* @return {string} desktop directory tied to the user, e.g. `~/Desktop`
|
|
203
|
+
* @override
|
|
204
|
+
*/
|
|
205
|
+
get userDesktopDir() {
|
|
206
|
+
return getUserMediaDir("XDG_DESKTOP_DIR", "~/Desktop");
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* @return {string} runtime directory tied to the user, e.g. `/run/user/$(id -u)/$appname/$version` or `$XDG_RUNTIME_DIR/$appname/$version`.
|
|
211
|
+
*
|
|
212
|
+
* For FreeBSD/OpenBSD/NetBSD, it would return `/var/run/user/$(id -u)/$appname/$version` if it exists, otherwise `/tmp/runtime-$(id -u)/$appname/$version`, if `XDG_RUNTIME_DIR` is not set.
|
|
213
|
+
* @override
|
|
214
|
+
*/
|
|
215
|
+
get userRuntimeDir() {
|
|
216
|
+
let path2 = process.env.XDG_RUNTIME_DIR ?? "";
|
|
217
|
+
if (!path2.trim()) {
|
|
218
|
+
if (
|
|
219
|
+
process.platform === "freebsd" ||
|
|
220
|
+
process.platform === "netbsd" ||
|
|
221
|
+
process.platform === "openbsd"
|
|
222
|
+
) {
|
|
223
|
+
path2 = `/var/run/user/${getuid()}`;
|
|
224
|
+
if (!fs.existsSync(path2)) {
|
|
225
|
+
path2 = `/tmp/runtime-${getuid()}`;
|
|
226
|
+
}
|
|
227
|
+
} else {
|
|
228
|
+
path2 = `/run/user/${getuid()}`;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return this._appendAppNameAndVersion(path2);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* @return {string} runtime directory shared by users, e.g. `/run/$appname/$version` or `$XDG_RUNTIME_DIR/$appname/$version`.
|
|
236
|
+
*
|
|
237
|
+
* Note that this behaves almost exactly like `userRuntimeDir` if `XDG_RUNTIME_DIR` is set, but will fall back to paths associated to the root user isntead of a regular logged-in user if it's not set.
|
|
238
|
+
*
|
|
239
|
+
* If you wish to ensure that a logged-in user path is returned e.g. `/run/user/0`, use `userRuntimeDir` instead.
|
|
240
|
+
*
|
|
241
|
+
* For FreeBSD/OpenBSD/NetBSD, it would return `/var/run/$appname/$version` if `XDG_RUNTIME_DIR` is not set.
|
|
242
|
+
* @override
|
|
243
|
+
*/
|
|
244
|
+
get siteRuntimeDir() {
|
|
245
|
+
let path2 = process.env.XDG_RUNTIME_DIR ?? "";
|
|
246
|
+
if (!path2.trim()) {
|
|
247
|
+
if (
|
|
248
|
+
process.platform === "freebsd" ||
|
|
249
|
+
process.platform === "netbsd" ||
|
|
250
|
+
process.platform === "openbsd"
|
|
251
|
+
) {
|
|
252
|
+
path2 = "/var/run";
|
|
253
|
+
} else {
|
|
254
|
+
path2 = "/run";
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return this._appendAppNameAndVersion(path2);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* @return {string} data path shared by users. Only return the first item, even if `multipath` is set to `true`.
|
|
262
|
+
* @override
|
|
263
|
+
*/
|
|
264
|
+
get siteDataPath() {
|
|
265
|
+
return this._firstItemAsPathIfMultipath(this.siteDataDir);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* @return {string} config path shared by users. Only return the first item, even if `multipath` is set to `true`.
|
|
270
|
+
* @override
|
|
271
|
+
*/
|
|
272
|
+
get siteConfigPath() {
|
|
273
|
+
return this._firstItemAsPathIfMultipath(this.siteConfigDir);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* @return {string} cache path shared by users. Only return the first item, even if `multipath` is set to `true`.
|
|
278
|
+
* @override
|
|
279
|
+
*/
|
|
280
|
+
get siteCachePath() {
|
|
281
|
+
return this._firstItemAsPathIfMultipath(this.siteCacheDir);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* @yields all user and site configuation directories
|
|
286
|
+
* @return {Generator<string>}
|
|
287
|
+
* @override
|
|
288
|
+
*/
|
|
289
|
+
*iterConfigDirs() {
|
|
290
|
+
yield this.userConfigDir;
|
|
291
|
+
yield* this._siteConfigDirs;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* @yields all user and site data directories
|
|
296
|
+
* @return {Generator<string>}
|
|
297
|
+
* @override
|
|
298
|
+
*/
|
|
299
|
+
*iterDataDirs() {
|
|
300
|
+
yield this.userDataDir;
|
|
301
|
+
yield* this._siteDataDirs;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* @param {string} envVar
|
|
307
|
+
* @param {string} fallbackTildePath
|
|
308
|
+
* @returns {string}
|
|
309
|
+
*/
|
|
310
|
+
function getUserMediaDir(envVar, fallbackTildePath) {
|
|
311
|
+
let mediaDir = getUserDirsFolder(envVar);
|
|
312
|
+
if (mediaDir === undefined) {
|
|
313
|
+
mediaDir = (process.env[envVar] ?? "").trim();
|
|
314
|
+
if (!mediaDir) {
|
|
315
|
+
mediaDir = fallbackTildePath.replace(/^~/, os.homedir());
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return mediaDir;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Return directory from user-dirs.dirs config file.
|
|
323
|
+
*
|
|
324
|
+
* See https://freedesktop.org/wiki/Software/xdg-user-dirs/.
|
|
325
|
+
*
|
|
326
|
+
* ⚠️ This function uses **synchronous FS operations**.
|
|
327
|
+
*
|
|
328
|
+
* @param {string} key
|
|
329
|
+
* @returns {string | undefined}
|
|
330
|
+
*/
|
|
331
|
+
function getUserDirsFolder(key) {
|
|
332
|
+
const userDirsConfigPath = path.join(new Unix().userConfigDir, "user-dirs.dirs");
|
|
333
|
+
if (fs.existsSync(userDirsConfigPath)) {
|
|
334
|
+
// This works for now.
|
|
335
|
+
const parser = new ConfigParser()
|
|
336
|
+
|
|
337
|
+
const read = fs.readFileSync(userDirsConfigPath, "utf-8")
|
|
338
|
+
parser.readString(`[top]\n${read}`)
|
|
339
|
+
|
|
340
|
+
const top = parser.get("top");
|
|
341
|
+
if (!top || !(Object.hasOwn(top, key))) {
|
|
342
|
+
return undefined
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const path2 = top[key].replace(/(^"|"$)/g, "")
|
|
346
|
+
return path2.replace("$HOME", os.homedir())
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return undefined;
|
|
350
|
+
}
|
package/src/version.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// https://github.com/nodejs/node/issues/51347
|
|
2
|
+
import packageJSON from "../package.json" with { type: "json" };
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @param {unknown} error
|
|
6
|
+
* @return {never}
|
|
7
|
+
*/
|
|
8
|
+
function throwExpression(error) {
|
|
9
|
+
throw error;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const version = packageJSON.version;
|
|
13
|
+
const match =
|
|
14
|
+
packageJSON.version.match(/^(\d+)\.(\d+)\.(\d+)/) ??
|
|
15
|
+
throwExpression(new Error("unreachable"));
|
|
16
|
+
export const versionTuple = [+match[1], +match[2], +match[3]];
|