@effected/app 0.3.1 → 0.4.1

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/App.js CHANGED
@@ -15,48 +15,12 @@ const testPaths = () => XdgPaths.make({
15
15
  configDirs: ["/etc/xdg"],
16
16
  dataDirs: ["/usr/local/share", "/usr/share"]
17
17
  });
18
- /**
19
- * Build the application control plane: namespaced directories, the state
20
- * database and the cache database, all pointed at the same place.
21
- *
22
- * @remarks
23
- * Composition is `AppDirs.layer(options)` `provideMerge` `Xdg.layer`, with the
24
- * {@link AppStore} and {@link AppCache} glue `provideMerge`d over the result,
25
- * so all four services come out and only `FileSystem` and `Path` stay in `R` —
26
- * the two the consumer's platform layer supplies once, at the edge.
27
- *
28
- * `App.layer` always provides **both** databases: an application that wants
29
- * only one composes `AppStore.layer` or `AppCache.layer` directly and never
30
- * opens the other file. Passing no `cache` options still opens `cache.db`,
31
- * because `CacheOptions` are all-optional and absence means defaults.
32
- *
33
- * This is a layer-returning function: bind the result to a `const` once and
34
- * reuse that binding. Calling it inline at two provide sites opens two
35
- * databases — two connections onto one file, two migration ledgers, and two
36
- * independent `CacheEvent` PubSubs whose subscribers each see half the events.
37
- */
38
18
  const layer = (options) => {
39
19
  const { store, cache, ...dirOptions } = options;
40
20
  const dirs = Layer.provideMerge(AppDirs.layer(dirOptions), Xdg.layer);
41
21
  const databases = Layer.mergeAll(AppStore.layer(store), AppCache.layer(cache));
42
22
  return Layer.provideMerge(databases, dirs);
43
23
  };
44
- /**
45
- * The hermetic control plane: fixed XDG paths, `:memory:` databases, and the
46
- * platform layers provided internally.
47
- *
48
- * @remarks
49
- * `Xdg.layerFrom` over a synthetic default {@link XdgPaths}, `Store.layerTest`
50
- * and `Cache.layerTest`, with `Path.layer` and `FileSystem.layerNoop` provided
51
- * **internally** via `Layer.provide` — not merged into the output, not
52
- * exposed. A consumer's first test needs no platform package at all.
53
- *
54
- * The documented limit: code paths that actually exercise `ensure*` **die**
55
- * against `FileSystem.layerNoop` — it is a stub, not a working filesystem.
56
- * `layerTest` is for testing logic that *uses* the control plane; a test of
57
- * real directory behaviour uses {@link (App:variable).layer} with a
58
- * temp-directory `HOME`.
59
- */
60
24
  const layerTest = (options) => {
61
25
  const dirs = Layer.provideMerge(AppDirs.layer({ namespace: options.namespace }), Xdg.layerFrom(options.paths ?? testPaths()));
62
26
  const databases = Layer.mergeAll(Store.layerTest(options.store ?? { migrations: [] }), Cache.layerTest(options.cache));
@@ -68,9 +32,46 @@ const layerTest = (options) => {
68
32
  *
69
33
  * @public
70
34
  */
71
- const App = {
72
- layer,
73
- layerTest
35
+ var App = class {
36
+ constructor() {}
37
+ /**
38
+ * Build the application control plane: namespaced directories, the state
39
+ * database and the cache database, all pointed at the same place.
40
+ *
41
+ * @remarks
42
+ * Composition is `AppDirs.layer(options)` `provideMerge` `Xdg.layer`, with the
43
+ * {@link AppStore} and {@link AppCache} glue `provideMerge`d over the result,
44
+ * so all four services come out and only `FileSystem` and `Path` stay in `R` —
45
+ * the two the consumer's platform layer supplies once, at the edge.
46
+ *
47
+ * `App.layer` always provides **both** databases: an application that wants
48
+ * only one composes `AppStore.layer` or `AppCache.layer` directly and never
49
+ * opens the other file. Passing no `cache` options still opens `cache.db`,
50
+ * because `CacheOptions` are all-optional and absence means defaults.
51
+ *
52
+ * This is a layer-returning function: bind the result to a `const` once and
53
+ * reuse that binding. Calling it inline at two provide sites opens two
54
+ * databases — two connections onto one file, two migration ledgers, and two
55
+ * independent `CacheEvent` PubSubs whose subscribers each see half the events.
56
+ */
57
+ static layer = layer;
58
+ /**
59
+ * The hermetic control plane: fixed XDG paths, `:memory:` databases, and the
60
+ * platform layers provided internally.
61
+ *
62
+ * @remarks
63
+ * `Xdg.layerFrom` over a synthetic default `XdgPaths`, `Store.layerTest`
64
+ * and `Cache.layerTest`, with `Path.layer` and `FileSystem.layerNoop` provided
65
+ * **internally** via `Layer.provide` — not merged into the output, not
66
+ * exposed. A consumer's first test needs no platform package at all.
67
+ *
68
+ * The documented limit: code paths that actually exercise `ensure*` **die**
69
+ * against `FileSystem.layerNoop` — it is a stub, not a working filesystem.
70
+ * `layerTest` is for testing logic that *uses* the control plane; a test of
71
+ * real directory behaviour uses {@link App.layer} with a temp-directory
72
+ * `HOME`.
73
+ */
74
+ static layerTest = layerTest;
74
75
  };
75
76
 
76
77
  //#endregion
package/AppCache.js CHANGED
@@ -4,20 +4,6 @@ import { AppDirs } from "@effected/xdg";
4
4
  import { Effect, Layer, Path } from "effect";
5
5
 
6
6
  //#region src/AppCache.ts
7
- /**
8
- * Build the cache-directory database layer: `AppDirs.ensureCache`, then
9
- * `Cache.layerSqlite` at `<cache dir>/<filename>`.
10
- *
11
- * @remarks
12
- * The same ensure-before-open ordering as `AppStore.layer`, and it matters
13
- * *more* here: the cache directory is the one an operator is most likely to
14
- * have deleted between runs. `options` is optional because every
15
- * `CacheOptions` field is.
16
- *
17
- * This is a layer-returning function: bind the result to a `const` and reuse
18
- * that binding, or memoization by reference is lost and the database is
19
- * opened twice.
20
- */
21
7
  const layer = (options) => Layer.unwrap(Effect.gen(function* () {
22
8
  const opts = options ?? {};
23
9
  const filename = opts.filename ?? "cache.db";
@@ -37,7 +23,24 @@ const layer = (options) => Layer.unwrap(Effect.gen(function* () {
37
23
  *
38
24
  * @public
39
25
  */
40
- const AppCache = { layer };
26
+ var AppCache = class {
27
+ constructor() {}
28
+ /**
29
+ * Build the cache-directory database layer: `AppDirs.ensureCache`, then
30
+ * `Cache.layerSqlite` at `<cache dir>/<filename>`.
31
+ *
32
+ * @remarks
33
+ * The same ensure-before-open ordering as `AppStore.layer`, and it matters
34
+ * *more* here: the cache directory is the one an operator is most likely to
35
+ * have deleted between runs. `options` is optional because every
36
+ * `CacheOptions` field is.
37
+ *
38
+ * This is a layer-returning function: bind the result to a `const` and reuse
39
+ * that binding, or memoization by reference is lost and the database is
40
+ * opened twice.
41
+ */
42
+ static layer = layer;
43
+ };
41
44
 
42
45
  //#endregion
43
46
  export { AppCache };
package/AppConfig.js CHANGED
@@ -4,25 +4,6 @@ import { Effect, Layer } from "effect";
4
4
  import { ConfigFile, MergeStrategy } from "@effected/config-file";
5
5
 
6
6
  //#region src/AppConfig.ts
7
- /**
8
- * Build the xdg-flavored config layer for a `ConfigFile.Service` class.
9
- *
10
- * @remarks
11
- * Wraps `ConfigFile.layer(tag, …)` with the resolver chain xdg documents, in
12
- * xdg's documented order — `XdgConfig.resolver`, then
13
- * `XdgConfig.nativeResolver` — and with `defaultPath:
14
- * XdgConfig.savePath(filename)`, which fits config-file's infallible
15
- * `defaultPath` slot without an `orDie` because xdg resolves at
16
- * layer-construction time.
17
- *
18
- * **The namespace is never a parameter.** It is read from the ambient
19
- * {@link AppDirs} service at layer build time, so it is typed exactly once, in
20
- * `App.layer` — the two-strings drift where an app passes `"myapp"` to
21
- * `App.layer` and `"my-app"` to its config preset cannot happen.
22
- *
23
- * This is a layer-returning function: bind the result to a `const` and reuse
24
- * that binding, or two provide sites mint two independent service instances.
25
- */
26
7
  const layer = (tag, options) => Layer.unwrap(Effect.gen(function* () {
27
8
  const invalid = badFilename("AppConfig.layer", options.filename);
28
9
  if (invalid !== void 0) return yield* Effect.die(invalid);
@@ -54,7 +35,28 @@ const layer = (tag, options) => Layer.unwrap(Effect.gen(function* () {
54
35
  *
55
36
  * @public
56
37
  */
57
- const AppConfig = { layer };
38
+ var AppConfig = class {
39
+ constructor() {}
40
+ /**
41
+ * Build the xdg-flavored config layer for a `ConfigFile.Service` class.
42
+ *
43
+ * @remarks
44
+ * Wraps `ConfigFile.layer(tag, …)` with the resolver chain xdg documents, in
45
+ * xdg's documented order — `XdgConfig.resolver`, then `XdgConfig.nativeResolver`
46
+ * — and with `defaultPath: XdgConfig.savePath(filename)`, which fits
47
+ * config-file's infallible `defaultPath` slot without an `orDie` because xdg
48
+ * resolves at layer-construction time.
49
+ *
50
+ * **The namespace is never a parameter.** It is read from the ambient
51
+ * `AppDirs` service at layer build time, so it is typed exactly once, in
52
+ * `App.layer` — the two-strings drift where an app passes `"myapp"` to
53
+ * `App.layer` and `"my-app"` to its config preset cannot happen.
54
+ *
55
+ * This is a layer-returning function: bind the result to a `const` and reuse
56
+ * that binding, or two provide sites mint two independent service instances.
57
+ */
58
+ static layer = layer;
59
+ };
58
60
 
59
61
  //#endregion
60
62
  export { AppConfig };
package/AppStore.js CHANGED
@@ -4,23 +4,6 @@ import { AppDirs } from "@effected/xdg";
4
4
  import { Effect, Layer, Path } from "effect";
5
5
 
6
6
  //#region src/AppStore.ts
7
- /**
8
- * Build the state-directory database layer: `AppDirs.ensureState`, then
9
- * `Store.layerSqlite` at `<state dir>/<filename>`.
10
- *
11
- * @remarks
12
- * The ensure-before-open ordering is the load-bearing glue.
13
- * `SqliteClient.layer` has no error channel and **defects** on a missing
14
- * parent directory; `AppDirs.ensureState` is a `mkdir -p` on a **typed**
15
- * `AppDirsError` channel. Running the ensure inside `Layer.unwrap`, before the
16
- * store layer is built, converts a defect surface into a typed one — "the
17
- * state directory could not be created" is an expected, recoverable boundary
18
- * failure and it stays on `E`. Nothing is `orDie`d.
19
- *
20
- * This is a layer-returning function: bind the result to a `const` and reuse
21
- * that binding, or memoization by reference is lost and the database is
22
- * opened twice.
23
- */
24
7
  const layer = (options) => Layer.unwrap(Effect.gen(function* () {
25
8
  const filename = options.filename ?? "store.db";
26
9
  const invalid = badFilename("AppStore.layer", filename);
@@ -39,7 +22,27 @@ const layer = (options) => Layer.unwrap(Effect.gen(function* () {
39
22
  *
40
23
  * @public
41
24
  */
42
- const AppStore = { layer };
25
+ var AppStore = class {
26
+ constructor() {}
27
+ /**
28
+ * Build the state-directory database layer: `AppDirs.ensureState`, then
29
+ * `Store.layerSqlite` at `<state dir>/<filename>`.
30
+ *
31
+ * @remarks
32
+ * The ensure-before-open ordering is the load-bearing glue.
33
+ * `SqliteClient.layer` has no error channel and **defects** on a missing
34
+ * parent directory; `AppDirs.ensureState` is a `mkdir -p` on a **typed**
35
+ * `AppDirsError` channel. Running the ensure inside `Layer.unwrap`, before the
36
+ * store layer is built, converts a defect surface into a typed one — "the
37
+ * state directory could not be created" is an expected, recoverable boundary
38
+ * failure and it stays on `E`. Nothing is `orDie`d.
39
+ *
40
+ * This is a layer-returning function: bind the result to a `const` and reuse
41
+ * that binding, or memoization by reference is lost and the database is
42
+ * opened twice.
43
+ */
44
+ static layer = layer;
45
+ };
43
46
 
44
47
  //#endregion
45
48
  export { AppStore };
package/index.d.ts CHANGED
@@ -4,7 +4,7 @@ import { Context, Effect, FileSystem, Layer, Path, Schema } from "effect";
4
4
  import { ConfigCodec, ConfigEvents, ConfigEventsShape, ConfigFileShape, ConfigValidationError, MergeStrategy } from "@effected/config-file";
5
5
  //#region src/AppCache.d.ts
6
6
  /**
7
- * Options for {@link (AppCache:variable).layer}.
7
+ * Options for {@link AppCache.layer}.
8
8
  *
9
9
  * @public
10
10
  */
@@ -25,13 +25,28 @@ interface AppCacheOptions extends CacheOptions {
25
25
  *
26
26
  * @public
27
27
  */
28
- declare const AppCache: {
29
- readonly layer: (options?: AppCacheOptions) => Layer.Layer<Cache, AppDirsError | CacheError, AppDirs | Path.Path>;
30
- };
28
+ declare class AppCache {
29
+ private constructor();
30
+ /**
31
+ * Build the cache-directory database layer: `AppDirs.ensureCache`, then
32
+ * `Cache.layerSqlite` at `<cache dir>/<filename>`.
33
+ *
34
+ * @remarks
35
+ * The same ensure-before-open ordering as `AppStore.layer`, and it matters
36
+ * *more* here: the cache directory is the one an operator is most likely to
37
+ * have deleted between runs. `options` is optional because every
38
+ * `CacheOptions` field is.
39
+ *
40
+ * This is a layer-returning function: bind the result to a `const` and reuse
41
+ * that binding, or memoization by reference is lost and the database is
42
+ * opened twice.
43
+ */
44
+ static readonly layer: (options?: AppCacheOptions) => Layer.Layer<Cache, AppDirsError | CacheError, AppDirs | Path.Path>;
45
+ }
31
46
  //#endregion
32
47
  //#region src/AppStore.d.ts
33
48
  /**
34
- * Options for {@link (AppStore:variable).layer}.
49
+ * Options for {@link AppStore.layer}.
35
50
  *
36
51
  * @public
37
52
  */
@@ -52,9 +67,27 @@ interface AppStoreOptions extends StoreOptions {
52
67
  *
53
68
  * @public
54
69
  */
55
- declare const AppStore: {
56
- readonly layer: (options: AppStoreOptions) => Layer.Layer<Store, AppDirsError | StoreError | StoreMigrationError, AppDirs | Path.Path>;
57
- };
70
+ declare class AppStore {
71
+ private constructor();
72
+ /**
73
+ * Build the state-directory database layer: `AppDirs.ensureState`, then
74
+ * `Store.layerSqlite` at `<state dir>/<filename>`.
75
+ *
76
+ * @remarks
77
+ * The ensure-before-open ordering is the load-bearing glue.
78
+ * `SqliteClient.layer` has no error channel and **defects** on a missing
79
+ * parent directory; `AppDirs.ensureState` is a `mkdir -p` on a **typed**
80
+ * `AppDirsError` channel. Running the ensure inside `Layer.unwrap`, before the
81
+ * store layer is built, converts a defect surface into a typed one — "the
82
+ * state directory could not be created" is an expected, recoverable boundary
83
+ * failure and it stays on `E`. Nothing is `orDie`d.
84
+ *
85
+ * This is a layer-returning function: bind the result to a `const` and reuse
86
+ * that binding, or memoization by reference is lost and the database is
87
+ * opened twice.
88
+ */
89
+ static readonly layer: (options: AppStoreOptions) => Layer.Layer<Store, AppDirsError | StoreError | StoreMigrationError, AppDirs | Path.Path>;
90
+ }
58
91
  //#endregion
59
92
  //#region src/App.d.ts
60
93
  /**
@@ -72,7 +105,7 @@ declare const AppStore: {
72
105
  */
73
106
  type AppError = XdgEnvError | AppDirsError | StoreError | StoreMigrationError | CacheError;
74
107
  /**
75
- * Options for {@link (App:variable).layer}.
108
+ * Options for {@link App.layer}.
76
109
  *
77
110
  * @remarks
78
111
  * The `AppDirsOptions` fields — `namespace`, `native`, `fallbackDir`, `dirs` —
@@ -88,7 +121,7 @@ interface AppOptions extends AppDirsOptions {
88
121
  readonly cache?: AppCacheOptions;
89
122
  }
90
123
  /**
91
- * Options for {@link (App:variable).layerTest}.
124
+ * Options for {@link App.layerTest}.
92
125
  *
93
126
  * @public
94
127
  */
@@ -108,14 +141,51 @@ interface AppTestOptions {
108
141
  *
109
142
  * @public
110
143
  */
111
- declare const App: {
112
- readonly layer: (options: AppOptions) => Layer.Layer<Xdg | AppDirs | Store | Cache, AppError, FileSystem.FileSystem | Path.Path>;
113
- readonly layerTest: (options: AppTestOptions) => Layer.Layer<Xdg | AppDirs | Store | Cache, AppError>;
114
- };
144
+ declare class App {
145
+ private constructor();
146
+ /**
147
+ * Build the application control plane: namespaced directories, the state
148
+ * database and the cache database, all pointed at the same place.
149
+ *
150
+ * @remarks
151
+ * Composition is `AppDirs.layer(options)` `provideMerge` `Xdg.layer`, with the
152
+ * {@link AppStore} and {@link AppCache} glue `provideMerge`d over the result,
153
+ * so all four services come out and only `FileSystem` and `Path` stay in `R` —
154
+ * the two the consumer's platform layer supplies once, at the edge.
155
+ *
156
+ * `App.layer` always provides **both** databases: an application that wants
157
+ * only one composes `AppStore.layer` or `AppCache.layer` directly and never
158
+ * opens the other file. Passing no `cache` options still opens `cache.db`,
159
+ * because `CacheOptions` are all-optional and absence means defaults.
160
+ *
161
+ * This is a layer-returning function: bind the result to a `const` once and
162
+ * reuse that binding. Calling it inline at two provide sites opens two
163
+ * databases — two connections onto one file, two migration ledgers, and two
164
+ * independent `CacheEvent` PubSubs whose subscribers each see half the events.
165
+ */
166
+ static readonly layer: (options: AppOptions) => Layer.Layer<Xdg | AppDirs | Store | Cache, AppError, FileSystem.FileSystem | Path.Path>;
167
+ /**
168
+ * The hermetic control plane: fixed XDG paths, `:memory:` databases, and the
169
+ * platform layers provided internally.
170
+ *
171
+ * @remarks
172
+ * `Xdg.layerFrom` over a synthetic default `XdgPaths`, `Store.layerTest`
173
+ * and `Cache.layerTest`, with `Path.layer` and `FileSystem.layerNoop` provided
174
+ * **internally** via `Layer.provide` — not merged into the output, not
175
+ * exposed. A consumer's first test needs no platform package at all.
176
+ *
177
+ * The documented limit: code paths that actually exercise `ensure*` **die**
178
+ * against `FileSystem.layerNoop` — it is a stub, not a working filesystem.
179
+ * `layerTest` is for testing logic that *uses* the control plane; a test of
180
+ * real directory behaviour uses {@link App.layer} with a temp-directory
181
+ * `HOME`.
182
+ */
183
+ static readonly layerTest: (options: AppTestOptions) => Layer.Layer<Xdg | AppDirs | Store | Cache, AppError>;
184
+ }
115
185
  //#endregion
116
186
  //#region src/AppConfig.d.ts
117
187
  /**
118
- * Options for {@link (AppConfig:variable).layer}.
188
+ * Options for {@link AppConfig.layer}.
119
189
  *
120
190
  * @public
121
191
  */
@@ -171,9 +241,28 @@ interface AppConfigOptions<A, I> {
171
241
  *
172
242
  * @public
173
243
  */
174
- declare const AppConfig: {
175
- readonly layer: <Self, A, I>(tag: Context.Key<Self, ConfigFileShape<A>>, options: AppConfigOptions<A, I>) => Layer.Layer<Self, never, FileSystem.FileSystem | Path.Path | AppDirs | Xdg>;
176
- };
244
+ declare class AppConfig {
245
+ private constructor();
246
+ /**
247
+ * Build the xdg-flavored config layer for a `ConfigFile.Service` class.
248
+ *
249
+ * @remarks
250
+ * Wraps `ConfigFile.layer(tag, …)` with the resolver chain xdg documents, in
251
+ * xdg's documented order — `XdgConfig.resolver`, then `XdgConfig.nativeResolver`
252
+ * — and with `defaultPath: XdgConfig.savePath(filename)`, which fits
253
+ * config-file's infallible `defaultPath` slot without an `orDie` because xdg
254
+ * resolves at layer-construction time.
255
+ *
256
+ * **The namespace is never a parameter.** It is read from the ambient
257
+ * `AppDirs` service at layer build time, so it is typed exactly once, in
258
+ * `App.layer` — the two-strings drift where an app passes `"myapp"` to
259
+ * `App.layer` and `"my-app"` to its config preset cannot happen.
260
+ *
261
+ * This is a layer-returning function: bind the result to a `const` and reuse
262
+ * that binding, or two provide sites mint two independent service instances.
263
+ */
264
+ static readonly layer: <Self, A, I>(tag: Context.Key<Self, ConfigFileShape<A>>, options: AppConfigOptions<A, I>) => Layer.Layer<Self, never, FileSystem.FileSystem | Path.Path | AppDirs | Xdg>;
265
+ }
177
266
  //#endregion
178
267
  export { App, AppCache, type AppCacheOptions, AppConfig, type AppConfigOptions, type AppError, type AppOptions, AppStore, type AppStoreOptions, type AppTestOptions };
179
268
  //# sourceMappingURL=index.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effected/app",
3
- "version": "0.3.1",
3
+ "version": "0.4.1",
4
4
  "private": false,
5
5
  "description": "The application control plane for Effect: one layer wiring XDG-namespaced directories, a migrated SQLite store, a TTL cache and a config file to the same place.",
6
6
  "keywords": [
@@ -39,9 +39,9 @@
39
39
  "./package.json": "./package.json"
40
40
  },
41
41
  "peerDependencies": {
42
- "@effected/config-file": "~0.1.9",
42
+ "@effected/config-file": "~0.2.0",
43
43
  "@effected/store": "~0.1.2",
44
- "@effected/xdg": "~0.1.8",
44
+ "@effected/xdg": "~0.1.9",
45
45
  "effect": "4.0.0-beta.101"
46
46
  },
47
47
  "engines": {