@effected/xdg 0.1.7 → 0.1.9
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/XdgConfig.js +63 -68
- package/index.d.ts +64 -5
- package/package.json +4 -4
- package/tsdoc-metadata.json +1 -1
package/XdgConfig.js
CHANGED
|
@@ -5,27 +5,6 @@ import { Effect, FileSystem, Option, Path } from "effect";
|
|
|
5
5
|
import { Walker } from "@effected/walker";
|
|
6
6
|
|
|
7
7
|
//#region src/XdgConfig.ts
|
|
8
|
-
/**
|
|
9
|
-
* Search the app's XDG config search path for `filename`.
|
|
10
|
-
*
|
|
11
|
-
* @remarks
|
|
12
|
-
* Probes the app's own config directory first, then each `$XDG_CONFIG_DIRS`
|
|
13
|
-
* entry namespaced — `~/.config/myapp/rc`, then `/etc/xdg/myapp/rc`. v3 probed
|
|
14
|
-
* only the first of those; the system search path is half the XDG spec and it
|
|
15
|
-
* was missing.
|
|
16
|
-
*
|
|
17
|
-
* The scan runs through `Walker.firstMatch`, so a failure on one candidate means
|
|
18
|
-
* "this candidate did not match" and the search continues to the next. That is a
|
|
19
|
-
* bug fixed, not a refactor: v3 wrapped the whole resolver in a single
|
|
20
|
-
* `catchAll`, so an unreadable `/etc/xdg` aborted the probe and hid a perfectly
|
|
21
|
-
* readable `~/.config`. Not-found and cannot-look stay indistinguishable to the
|
|
22
|
-
* caller, which is the resolver contract — `resolve`'s error channel is `never`.
|
|
23
|
-
*
|
|
24
|
-
* Place it **before** `nativeResolver` in a chain, so an existing
|
|
25
|
-
* `~/.config/<app>` still wins over the OS-native directory.
|
|
26
|
-
*
|
|
27
|
-
* @public
|
|
28
|
-
*/
|
|
29
8
|
const resolver = (options) => ({
|
|
30
9
|
name: "xdg",
|
|
31
10
|
resolve: Effect.gen(function* () {
|
|
@@ -36,24 +15,6 @@ const resolver = (options) => ({
|
|
|
36
15
|
return yield* Walker.firstMatch(candidates, (candidate) => fs.exists(candidate));
|
|
37
16
|
})
|
|
38
17
|
});
|
|
39
|
-
/**
|
|
40
|
-
* Probe the OS-native config directory for `filename`.
|
|
41
|
-
*
|
|
42
|
-
* @remarks
|
|
43
|
-
* Resolves the native config directory for `namespace`
|
|
44
|
-
* (`~/Library/Application Support/<ns>` on macOS, `%APPDATA%\<ns>` on Windows)
|
|
45
|
-
* and checks whether `filename` is there. On Linux and everywhere else
|
|
46
|
-
* {@link NativeDirs.resolve} yields `Option.none()`, so this resolver returns
|
|
47
|
-
* `Option.none()` without probing at all — the XDG resolver already owns
|
|
48
|
-
* `~/.config` there.
|
|
49
|
-
*
|
|
50
|
-
* Takes `namespace` rather than reading it off {@link AppDirs}: the native
|
|
51
|
-
* directory is a property of the OS convention, not of however the app happened
|
|
52
|
-
* to configure its XDG directories, and a caller may well probe a *different*
|
|
53
|
-
* namespace than the one their `AppDirs` was built for.
|
|
54
|
-
*
|
|
55
|
-
* @public
|
|
56
|
-
*/
|
|
57
18
|
const nativeResolver = (options) => ({
|
|
58
19
|
name: "native",
|
|
59
20
|
resolve: Effect.gen(function* () {
|
|
@@ -71,31 +32,6 @@ const nativeResolver = (options) => ({
|
|
|
71
32
|
return yield* Walker.firstMatch([path.join(native.value.config, options.filename)], (candidate) => fs.exists(candidate));
|
|
72
33
|
})
|
|
73
34
|
});
|
|
74
|
-
/**
|
|
75
|
-
* The default save target for a config file: `<app config dir>/<filename>`.
|
|
76
|
-
*
|
|
77
|
-
* @remarks
|
|
78
|
-
* Drops straight into `ConfigFileOptions.defaultPath`, whose slot is typed
|
|
79
|
-
* `Effect<string, never, RR>`. That infallible channel is the whole reason
|
|
80
|
-
* {@link AppDirs} resolves at layer-construction time: with v3's per-access
|
|
81
|
-
* resolution this could fail, and a consumer had to `orDie` it into the slot.
|
|
82
|
-
*
|
|
83
|
-
* It does **not** create the directory — `ConfigFile.save` already `mkdir -p`s
|
|
84
|
-
* the parent of whatever path it is given.
|
|
85
|
-
*
|
|
86
|
-
* @example
|
|
87
|
-
* ```ts
|
|
88
|
-
* const layer = ConfigFile.layer(AppConfig, {
|
|
89
|
-
* schema: AppShape,
|
|
90
|
-
* codec: JsonCodec,
|
|
91
|
-
* strategy: MergeStrategy.firstMatch<AppShape>(),
|
|
92
|
-
* resolvers: [XdgConfig.resolver({ filename: "config.json" })],
|
|
93
|
-
* defaultPath: XdgConfig.savePath("config.json"),
|
|
94
|
-
* });
|
|
95
|
-
* ```
|
|
96
|
-
*
|
|
97
|
-
* @public
|
|
98
|
-
*/
|
|
99
35
|
const savePath = (filename) => Effect.gen(function* () {
|
|
100
36
|
const appDirs = yield* AppDirs;
|
|
101
37
|
return (yield* Path.Path).join(appDirs.dirs.config, filename);
|
|
@@ -105,10 +41,69 @@ const savePath = (filename) => Effect.gen(function* () {
|
|
|
105
41
|
*
|
|
106
42
|
* @public
|
|
107
43
|
*/
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
44
|
+
var XdgConfig = class {
|
|
45
|
+
constructor() {}
|
|
46
|
+
/**
|
|
47
|
+
* Search the app's XDG config search path for `filename`.
|
|
48
|
+
*
|
|
49
|
+
* @remarks
|
|
50
|
+
* Probes the app's own config directory first, then each `$XDG_CONFIG_DIRS`
|
|
51
|
+
* entry namespaced — `~/.config/myapp/rc`, then `/etc/xdg/myapp/rc`. v3 probed
|
|
52
|
+
* only the first of those; the system search path is half the XDG spec and it
|
|
53
|
+
* was missing.
|
|
54
|
+
*
|
|
55
|
+
* The scan runs through `Walker.firstMatch`, so a failure on one candidate means
|
|
56
|
+
* "this candidate did not match" and the search continues to the next. That is a
|
|
57
|
+
* bug fixed, not a refactor: v3 wrapped the whole resolver in a single
|
|
58
|
+
* `catchAll`, so an unreadable `/etc/xdg` aborted the probe and hid a perfectly
|
|
59
|
+
* readable `~/.config`. Not-found and cannot-look stay indistinguishable to the
|
|
60
|
+
* caller, which is the resolver contract — `resolve`'s error channel is `never`.
|
|
61
|
+
*
|
|
62
|
+
* Place it **before** {@link XdgConfig.nativeResolver} in a chain, so an
|
|
63
|
+
* existing `~/.config/<app>` still wins over the OS-native directory.
|
|
64
|
+
*/
|
|
65
|
+
static resolver = resolver;
|
|
66
|
+
/**
|
|
67
|
+
* Probe the OS-native config directory for `filename`.
|
|
68
|
+
*
|
|
69
|
+
* @remarks
|
|
70
|
+
* Resolves the native config directory for `namespace`
|
|
71
|
+
* (`~/Library/Application Support/<ns>` on macOS, `%APPDATA%\<ns>` on Windows)
|
|
72
|
+
* and checks whether `filename` is there. On Linux and everywhere else
|
|
73
|
+
* {@link NativeDirs.resolve} yields `Option.none()`, so this resolver returns
|
|
74
|
+
* `Option.none()` without probing at all — the XDG resolver already owns
|
|
75
|
+
* `~/.config` there.
|
|
76
|
+
*
|
|
77
|
+
* Takes `namespace` rather than reading it off {@link AppDirs}: the native
|
|
78
|
+
* directory is a property of the OS convention, not of however the app happened
|
|
79
|
+
* to configure its XDG directories, and a caller may well probe a *different*
|
|
80
|
+
* namespace than the one their `AppDirs` was built for.
|
|
81
|
+
*/
|
|
82
|
+
static nativeResolver = nativeResolver;
|
|
83
|
+
/**
|
|
84
|
+
* The default save target for a config file: `<app config dir>/<filename>`.
|
|
85
|
+
*
|
|
86
|
+
* @remarks
|
|
87
|
+
* Drops straight into `ConfigFileOptions.defaultPath`, whose slot is typed
|
|
88
|
+
* `Effect<string, never, RR>`. That infallible channel is the whole reason
|
|
89
|
+
* {@link AppDirs} resolves at layer-construction time: with v3's per-access
|
|
90
|
+
* resolution this could fail, and a consumer had to `orDie` it into the slot.
|
|
91
|
+
*
|
|
92
|
+
* It does **not** create the directory — `ConfigFile.save` already `mkdir -p`s
|
|
93
|
+
* the parent of whatever path it is given.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* const layer = ConfigFile.layer(AppConfig, {
|
|
98
|
+
* schema: AppShape,
|
|
99
|
+
* codec: JsonCodec,
|
|
100
|
+
* strategy: MergeStrategy.firstMatch<AppShape>(),
|
|
101
|
+
* resolvers: [XdgConfig.resolver({ filename: "config.json" })],
|
|
102
|
+
* defaultPath: XdgConfig.savePath("config.json"),
|
|
103
|
+
* });
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
static savePath = savePath;
|
|
112
107
|
};
|
|
113
108
|
|
|
114
109
|
//#endregion
|
package/index.d.ts
CHANGED
|
@@ -377,16 +377,75 @@ declare class NativeDirs extends NativeDirs_base {
|
|
|
377
377
|
*
|
|
378
378
|
* @public
|
|
379
379
|
*/
|
|
380
|
-
declare
|
|
381
|
-
|
|
380
|
+
declare class XdgConfig {
|
|
381
|
+
private constructor();
|
|
382
|
+
/**
|
|
383
|
+
* Search the app's XDG config search path for `filename`.
|
|
384
|
+
*
|
|
385
|
+
* @remarks
|
|
386
|
+
* Probes the app's own config directory first, then each `$XDG_CONFIG_DIRS`
|
|
387
|
+
* entry namespaced — `~/.config/myapp/rc`, then `/etc/xdg/myapp/rc`. v3 probed
|
|
388
|
+
* only the first of those; the system search path is half the XDG spec and it
|
|
389
|
+
* was missing.
|
|
390
|
+
*
|
|
391
|
+
* The scan runs through `Walker.firstMatch`, so a failure on one candidate means
|
|
392
|
+
* "this candidate did not match" and the search continues to the next. That is a
|
|
393
|
+
* bug fixed, not a refactor: v3 wrapped the whole resolver in a single
|
|
394
|
+
* `catchAll`, so an unreadable `/etc/xdg` aborted the probe and hid a perfectly
|
|
395
|
+
* readable `~/.config`. Not-found and cannot-look stay indistinguishable to the
|
|
396
|
+
* caller, which is the resolver contract — `resolve`'s error channel is `never`.
|
|
397
|
+
*
|
|
398
|
+
* Place it **before** {@link XdgConfig.nativeResolver} in a chain, so an
|
|
399
|
+
* existing `~/.config/<app>` still wins over the OS-native directory.
|
|
400
|
+
*/
|
|
401
|
+
static readonly resolver: (options: {
|
|
382
402
|
readonly filename: string;
|
|
383
403
|
}) => ConfigResolver<AppDirs | FileSystem.FileSystem | Path.Path>;
|
|
384
|
-
|
|
404
|
+
/**
|
|
405
|
+
* Probe the OS-native config directory for `filename`.
|
|
406
|
+
*
|
|
407
|
+
* @remarks
|
|
408
|
+
* Resolves the native config directory for `namespace`
|
|
409
|
+
* (`~/Library/Application Support/<ns>` on macOS, `%APPDATA%\<ns>` on Windows)
|
|
410
|
+
* and checks whether `filename` is there. On Linux and everywhere else
|
|
411
|
+
* {@link NativeDirs.resolve} yields `Option.none()`, so this resolver returns
|
|
412
|
+
* `Option.none()` without probing at all — the XDG resolver already owns
|
|
413
|
+
* `~/.config` there.
|
|
414
|
+
*
|
|
415
|
+
* Takes `namespace` rather than reading it off {@link AppDirs}: the native
|
|
416
|
+
* directory is a property of the OS convention, not of however the app happened
|
|
417
|
+
* to configure its XDG directories, and a caller may well probe a *different*
|
|
418
|
+
* namespace than the one their `AppDirs` was built for.
|
|
419
|
+
*/
|
|
420
|
+
static readonly nativeResolver: (options: {
|
|
385
421
|
readonly namespace: string;
|
|
386
422
|
readonly filename: string;
|
|
387
423
|
}) => ConfigResolver<Xdg | FileSystem.FileSystem | Path.Path>;
|
|
388
|
-
|
|
389
|
-
|
|
424
|
+
/**
|
|
425
|
+
* The default save target for a config file: `<app config dir>/<filename>`.
|
|
426
|
+
*
|
|
427
|
+
* @remarks
|
|
428
|
+
* Drops straight into `ConfigFileOptions.defaultPath`, whose slot is typed
|
|
429
|
+
* `Effect<string, never, RR>`. That infallible channel is the whole reason
|
|
430
|
+
* {@link AppDirs} resolves at layer-construction time: with v3's per-access
|
|
431
|
+
* resolution this could fail, and a consumer had to `orDie` it into the slot.
|
|
432
|
+
*
|
|
433
|
+
* It does **not** create the directory — `ConfigFile.save` already `mkdir -p`s
|
|
434
|
+
* the parent of whatever path it is given.
|
|
435
|
+
*
|
|
436
|
+
* @example
|
|
437
|
+
* ```ts
|
|
438
|
+
* const layer = ConfigFile.layer(AppConfig, {
|
|
439
|
+
* schema: AppShape,
|
|
440
|
+
* codec: JsonCodec,
|
|
441
|
+
* strategy: MergeStrategy.firstMatch<AppShape>(),
|
|
442
|
+
* resolvers: [XdgConfig.resolver({ filename: "config.json" })],
|
|
443
|
+
* defaultPath: XdgConfig.savePath("config.json"),
|
|
444
|
+
* });
|
|
445
|
+
* ```
|
|
446
|
+
*/
|
|
447
|
+
static readonly savePath: (filename: string) => Effect.Effect<string, never, AppDirs | Path.Path>;
|
|
448
|
+
}
|
|
390
449
|
//#endregion
|
|
391
450
|
export { AppDirKind, type AppDirOverrides, AppDirs, AppDirsError, type AppDirsOptions, type AppDirsShape, CurrentPlatform, NativeDirs, ResolvedAppDirs, Xdg, XdgConfig, XdgEnvError, XdgPaths, XdgPlatform };
|
|
392
451
|
//# sourceMappingURL=index.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effected/xdg",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "XDG Base Directory resolution for Effect: environment paths, app-namespaced directories, native OS conventions and config-file resolvers.",
|
|
6
6
|
"keywords": [
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
"./package.json": "./package.json"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"@effected/config-file": "~0.
|
|
42
|
-
"@effected/walker": "~0.3.
|
|
43
|
-
"effect": "4.0.0-beta.
|
|
41
|
+
"@effected/config-file": "~0.2.0",
|
|
42
|
+
"@effected/walker": "~0.3.3",
|
|
43
|
+
"effect": "4.0.0-beta.101"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|
|
46
46
|
"node": ">=24.11.0"
|