@c9up/echo 0.1.11 → 0.1.12

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 CHANGED
@@ -11,9 +11,12 @@ pnpm add @c9up/echo
11
11
  ream configure @c9up/echo
12
12
  ```
13
13
 
14
+ `ream add @c9up/echo` installs it, registers the provider and writes
15
+ `config/cache.ts`. The rest of this page assumes that has run.
16
+
14
17
  ## Usage
15
18
 
16
- Register the provider in your app, then configure it under `config/echo.ts`:
19
+ Register the provider, then name the cache stores in `config/cache.ts`:
17
20
 
18
21
  ```ts
19
22
  // reamrc.ts
@@ -22,6 +25,42 @@ providers: [
22
25
  ]
23
26
  ```
24
27
 
28
+ ```ts
29
+ // config/cache.ts
30
+ import { defineConfig, drivers, store } from '@c9up/echo'
31
+ import env from '#start/env'
32
+
33
+ export default defineConfig({
34
+ default: env.get('CACHE_STORE'),
35
+ stores: {
36
+ memory: store().useL1Layer(drivers.memory()),
37
+
38
+ tiered: store({ ttl: 60 })
39
+ .useL1Layer(drivers.memory())
40
+ .useL2Layer(drivers.redis({ connection: 'main' })),
41
+ },
42
+ })
43
+ ```
44
+
45
+ ```ts
46
+ import cache from '@c9up/echo/services/main'
47
+
48
+ await cache.set({ key: 'user:1', value: user })
49
+ await cache.use('tiered').get({ key: 'user:1' })
50
+ ```
51
+
52
+ A store is described a layer at a time: **L1** is the fast one (memory), **L2**
53
+ the shared one (Redis) — what makes the cache survive a restart. With both, a
54
+ read hits L1, a miss falls to L2, and a write reaches both. `useBus()` keeps
55
+ each instance's L1 in step after a write, and needs two layers to mean
56
+ anything.
57
+
58
+ Stores are built on first use, so naming a Redis store in an environment that
59
+ runs on memory opens no connection.
60
+
61
+ The plain `{ driver: drivers.memory(), ttl: 60 }` form is still accepted for
62
+ configs written against it.
63
+
25
64
  ## Entry points
26
65
 
27
66
  - `@c9up/echo` — main API
@@ -52,6 +52,13 @@ export default class EchoProvider {
52
52
  constructor(app: EchoAppContext);
53
53
  register(): void;
54
54
  boot(): Promise<void>;
55
+ /**
56
+ * Release the cache the app booted.
57
+ *
58
+ * The memory driver runs a sweep on a timer and the redis driver holds a
59
+ * connection. Neither is released on its own, so across a dev reload or a
60
+ * test run each cycle leaves another one behind.
61
+ */
55
62
  shutdown(): Promise<void>;
56
63
  }
57
64
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"EchoProvider.d.ts","sourceRoot":"","sources":["../src/EchoProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAgB,MAAM,mBAAmB,CAAC;AAMnE;;;;GAIG;AACH,UAAU,aAAa;IACtB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,GAAG,IAAI,CAAC;IACxD,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACjD;AACD,UAAU,eAAe;IACxB,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;CAC7C;AACD,MAAM,WAAW,cAAc;IAC9B,SAAS,EAAE,aAAa,CAAC;IACzB,MAAM,EAAE,eAAe,CAAC;CACxB;AAED,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACtD;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,QAAQ,CAAC;CAClB;AAmBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,OAAO,OAAO,YAAY;;IACpB,SAAS,CAAC,GAAG,EAAE,cAAc;gBAAnB,GAAG,EAAE,cAAc;IAYzC,QAAQ,IAAI,IAAI;IA0BV,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAC/B"}
1
+ {"version":3,"file":"EchoProvider.d.ts","sourceRoot":"","sources":["../src/EchoProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAgB,MAAM,mBAAmB,CAAC;AAMnE;;;;GAIG;AACH,UAAU,aAAa;IACtB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,GAAG,IAAI,CAAC;IACxD,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACjD;AACD,UAAU,eAAe;IACxB,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;CAC7C;AACD,MAAM,WAAW,cAAc;IAC9B,SAAS,EAAE,aAAa,CAAC;IACzB,MAAM,EAAE,eAAe,CAAC;CACxB;AAED,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACtD;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,QAAQ,CAAC;CAClB;AAmBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,OAAO,OAAO,YAAY;;IACpB,SAAS,CAAC,GAAG,EAAE,cAAc;gBAAnB,GAAG,EAAE,cAAc;IAYzC,QAAQ,IAAI,IAAI;IA6BV,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B;;;;;;OAMG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAS/B"}
@@ -1,7 +1,7 @@
1
1
  import { CacheManager } from "./CacheManager.js";
2
2
  import { MemoryDriver } from "./drivers/MemoryDriver.js";
3
3
  import { CacheStoreManager } from "./StoreManager.js";
4
- import { setCache } from "./services/main.js";
4
+ import { clearCache, getCache, setCache } from "./services/main.js";
5
5
  function isEmitter(value) {
6
6
  return (typeof value === "object" &&
7
7
  value !== null &&
@@ -67,9 +67,29 @@ export default class EchoProvider {
67
67
  });
68
68
  this.app.container.singleton("cache", () => this.app.container.resolve(CacheManager));
69
69
  }
70
+ /** The cache THIS provider booted — not whatever the module singleton holds. */
71
+ #cache;
70
72
  async boot() {
71
- setCache(await this.app.container.resolve(CacheManager));
73
+ this.#cache = await this.app.container.resolve(CacheManager);
74
+ setCache(this.#cache);
75
+ }
76
+ /**
77
+ * Release the cache the app booted.
78
+ *
79
+ * The memory driver runs a sweep on a timer and the redis driver holds a
80
+ * connection. Neither is released on its own, so across a dev reload or a
81
+ * test run each cycle leaves another one behind.
82
+ */
83
+ async shutdown() {
84
+ if (!this.#cache)
85
+ return;
86
+ await this.#cache.disconnect();
87
+ // Two applications can share a process — parallel tests, a hot reload.
88
+ // The module singleton holds whichever booted last, so it is only ours
89
+ // to clear while it still points at the cache this provider booted.
90
+ if (getCache() === this.#cache)
91
+ clearCache();
92
+ this.#cache = undefined;
72
93
  }
73
- async shutdown() { }
74
94
  }
75
95
  //# sourceMappingURL=EchoProvider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"EchoProvider.js","sourceRoot":"","sources":["../src/EchoProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAyB,MAAM,mBAAmB,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAiC9C,SAAS,SAAS,CAAC,KAAc;IAChC,OAAO,CACN,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,UAAU,CAChD,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAc;IACzC,OAAO,CACN,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,QAAQ,IAAI,KAAK;QACjB,SAAS,IAAI,KAAK,CAClB,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,OAAO,OAAO,YAAY;IACV;IAAtB,YAAsB,GAAmB;QAAnB,QAAG,GAAH,GAAG,CAAgB;IAAG,CAAC;IAE7C,KAAK,CAAC,eAAe;QACpB,IAAI,CAAC;YACJ,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAU,SAAS,CAAC,CAAC;YACvE,IAAI,SAAS,CAAC,SAAS,CAAC;gBAAE,OAAO,SAAS,CAAC;QAC5C,CAAC;QAAC,MAAM,CAAC;YACR,oDAAoD;QACrD,CAAC;QACD,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,QAAQ;QACP,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,YAAY,EAAE,KAAK,IAAI,EAAE;YACrD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;YAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAU,OAAO,CAAC,CAAC;YAElD,IAAI,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC7B,MAAM,OAAO,GAAG,IAAI,iBAAiB,CAAC,EAAE,GAAG,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC3D,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC;YACtB,CAAC;YAED,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,EAAE,CAAuB,CAAC;YACjD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,QAAQ,CAAC;YACzC,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CACd,8BAA8B,MAAM,2BAA2B;oBAC9D,gEAAgE;oBAChE,2CAA2C,CAC5C,CAAC;YACH,CAAC;YACD,OAAO,IAAI,YAAY,CAAC,IAAI,YAAY,EAAE,EAAE,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;QACrE,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,EAAE,CAC1C,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAe,YAAY,CAAC,CACtD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI;QACT,QAAQ,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAe,YAAY,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,KAAK,CAAC,QAAQ,KAAmB,CAAC;CAClC"}
1
+ {"version":3,"file":"EchoProvider.js","sourceRoot":"","sources":["../src/EchoProvider.ts"],"names":[],"mappings":"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"}
@@ -33,10 +33,42 @@ export interface StoreConfig {
33
33
  }
34
34
  export interface MultiStoreConfig {
35
35
  default: string;
36
- stores: Record<string, StoreConfig>;
36
+ /**
37
+ * The stores this application can use, by name. Each is a {@link store}
38
+ * builder — the shape a cache config takes — or the plain
39
+ * `{ driver, …options }` form kept for configs written against it.
40
+ */
41
+ stores: Record<string, StoreConfig | Store>;
37
42
  /** Shared emitter for all stores' events. */
38
43
  emitter?: CacheEmitter;
39
44
  }
45
+ /**
46
+ * A store, described the way a cache config describes one: a layer at a time.
47
+ *
48
+ * stores: {
49
+ * memoryOnly: store().useL1Layer(drivers.memory()),
50
+ * default: store({ ttl: 60 })
51
+ * .useL1Layer(drivers.memory())
52
+ * .useL2Layer(drivers.redis({ connection: "main" })),
53
+ * }
54
+ *
55
+ * One layer is that driver; two are a tiered driver over both, which is what
56
+ * the layering means — reads hit L1, misses fall to L2, and writes go to both.
57
+ */
58
+ export declare class Store {
59
+ #private;
60
+ constructor(options?: Omit<StoreConfig, "driver">);
61
+ /** The fast layer, usually memory. */
62
+ useL1Layer(driver: DriverFactory): this;
63
+ /** The shared layer, usually Redis — what makes the cache survive a restart. */
64
+ useL2Layer(driver: DriverFactory): this;
65
+ /** The bus that keeps every instance's L1 in step after a write. */
66
+ useBus(bus: CacheBus): this;
67
+ /** The `{ driver, …options }` the manager consumes. */
68
+ entry(): StoreConfig;
69
+ }
70
+ /** Start describing a store — AdonisJS's `store()`. */
71
+ export declare function store(options?: Omit<StoreConfig, "driver">): Store;
40
72
  /** Driver factory helpers (bento `drivers.memory` / `drivers.redis`). */
41
73
  export declare const drivers: {
42
74
  memory(options?: {
@@ -1 +1 @@
1
- {"version":3,"file":"StoreManager.d.ts","sourceRoot":"","sources":["../src/StoreManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,KAAK,WAAW,EAAe,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,KAAK,QAAQ,EAAgB,MAAM,2BAA2B,CAAC;AACxE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3E,2EAA2E;AAC3E,MAAM,MAAM,aAAa,GAAG,MAAM,WAAW,CAAC;AAE9C,MAAM,WAAW,WAAW;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,WAAW,CAAC,EAAE,QAAQ,CAAC;IACvB,WAAW,CAAC,EAAE,QAAQ,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACpC,6CAA6C;IAC7C,OAAO,CAAC,EAAE,YAAY,CAAC;CACvB;AAED,yEAAyE;AACzE,eAAO,MAAM,OAAO;qBACF;QAAE,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,aAAa;IAG7D;;;;;OAKG;mBAGC;QAAE,MAAM,EAAE,WAAW,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GACxC;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GACzC,aAAa;oBAOA;QACf,EAAE,EAAE,aAAa,CAAC;QAClB,EAAE,EAAE,aAAa,CAAC;QAClB,GAAG,CAAC,EAAE,QAAQ,CAAC;KACf,GAAG,aAAa;CAQjB,CAAC;AAEF,qBAAa,iBAAiB;;gBAejB,MAAM,EAAE,gBAAgB;IASpC,qFAAqF;IACrF,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,YAAY;IAoChC;;;;OAIG;IACH,EAAE,CAAC,CAAC,SAAS,MAAM,aAAa,EAC/B,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,IAAI,GAC3C,IAAI;IAMP,2EAA2E;IAC3E,IAAI,CAAC,CAAC,SAAS,MAAM,aAAa,EACjC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,IAAI,GAC3C,IAAI;IAQP,6EAA6E;IAC7E,GAAG,CAAC,CAAC,SAAS,MAAM,aAAa,EAChC,KAAK,EAAE,CAAC,EACR,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,IAAI,GAC5C,IAAI;IAOP,qEAAqE;IAC/D,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAI/B,uEAAuE;IACjE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B;;;;;OAKG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CAGpC"}
1
+ {"version":3,"file":"StoreManager.d.ts","sourceRoot":"","sources":["../src/StoreManager.ts"],"names":[],"mappings":"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"}
@@ -19,6 +19,70 @@ import { MemoryDriver } from "./drivers/MemoryDriver.js";
19
19
  import { RedisDriver } from "./drivers/RedisDriver.js";
20
20
  import { TieredDriver } from "./drivers/TieredDriver.js";
21
21
  import { quasarConnection } from "./quasar.js";
22
+ /**
23
+ * A store, described the way a cache config describes one: a layer at a time.
24
+ *
25
+ * stores: {
26
+ * memoryOnly: store().useL1Layer(drivers.memory()),
27
+ * default: store({ ttl: 60 })
28
+ * .useL1Layer(drivers.memory())
29
+ * .useL2Layer(drivers.redis({ connection: "main" })),
30
+ * }
31
+ *
32
+ * One layer is that driver; two are a tiered driver over both, which is what
33
+ * the layering means — reads hit L1, misses fall to L2, and writes go to both.
34
+ */
35
+ export class Store {
36
+ #options;
37
+ #l1;
38
+ #l2;
39
+ #bus;
40
+ constructor(options = {}) {
41
+ this.#options = options;
42
+ }
43
+ /** The fast layer, usually memory. */
44
+ useL1Layer(driver) {
45
+ this.#l1 = driver;
46
+ return this;
47
+ }
48
+ /** The shared layer, usually Redis — what makes the cache survive a restart. */
49
+ useL2Layer(driver) {
50
+ this.#l2 = driver;
51
+ return this;
52
+ }
53
+ /** The bus that keeps every instance's L1 in step after a write. */
54
+ useBus(bus) {
55
+ this.#bus = bus;
56
+ return this;
57
+ }
58
+ /** The `{ driver, …options }` the manager consumes. */
59
+ entry() {
60
+ const l1 = this.#l1;
61
+ const l2 = this.#l2;
62
+ if (!l1 && !l2) {
63
+ throw new Error("Echo: a store needs a layer — call useL1Layer() or useL2Layer() on it.");
64
+ }
65
+ if (l1 && l2) {
66
+ return {
67
+ ...this.#options,
68
+ driver: drivers.tiered({ l1, l2, bus: this.#bus }),
69
+ };
70
+ }
71
+ const only = (l1 ?? l2);
72
+ if (this.#bus) {
73
+ throw new Error("Echo: a bus only means something with two layers — it keeps each instance's L1 in step. Add useL2Layer(), or drop useBus().");
74
+ }
75
+ return { ...this.#options, driver: only };
76
+ }
77
+ }
78
+ /** Start describing a store — AdonisJS's `store()`. */
79
+ export function store(options) {
80
+ return new Store(options);
81
+ }
82
+ /** Normalise either accepted form to the one the manager reads. */
83
+ function entryOf(config) {
84
+ return config instanceof Store ? config.entry() : config;
85
+ }
22
86
  /** Driver factory helpers (bento `drivers.memory` / `drivers.redis`). */
23
87
  export const drivers = {
24
88
  memory(options) {
@@ -68,10 +132,11 @@ export class CacheStoreManager {
68
132
  const existing = this.#built.get(store);
69
133
  if (existing)
70
134
  return existing;
71
- const cfg = this.#config.stores[store];
72
- if (!cfg) {
135
+ const declared = this.#config.stores[store];
136
+ if (!declared) {
73
137
  throw new Error(`Echo: unknown cache store "${store}"`);
74
138
  }
139
+ const cfg = entryOf(declared);
75
140
  const manager = new CacheManager(cfg.driver(), {
76
141
  prefix: cfg.prefix,
77
142
  ttl: cfg.ttl,
@@ -1 +1 @@
1
- {"version":3,"file":"StoreManager.js","sourceRoot":"","sources":["../src/StoreManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"StoreManager.js","sourceRoot":"","sources":["../src/StoreManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * `ream configure @c9up/echo` — wire the cache in one command.
3
+ *
4
+ * The provider alone is not enough: it reads `config/cache.ts`, and a package
5
+ * registered without one falls back to a default that is rarely the one an
6
+ * application wants. Writing both together is what makes `ream add` mean
7
+ * installed AND working.
8
+ */
9
+ interface Codemods {
10
+ addProvider(importPath: string): Promise<void>;
11
+ addEnvVars(vars: Record<string, string>): Promise<void>;
12
+ writeFile(filePath: string, content: string, options?: {
13
+ force?: boolean;
14
+ }): Promise<void>;
15
+ }
16
+ export declare function configure(codemods: Codemods): Promise<void>;
17
+ export {};
18
+ //# sourceMappingURL=configure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,UAAU,QAAQ;IACjB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,SAAS,CACR,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CAAC;CACjB;AAED,wBAAsB,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BjE"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * `ream configure @c9up/echo` — wire the cache in one command.
3
+ *
4
+ * The provider alone is not enough: it reads `config/cache.ts`, and a package
5
+ * registered without one falls back to a default that is rarely the one an
6
+ * application wants. Writing both together is what makes `ream add` mean
7
+ * installed AND working.
8
+ */
9
+ export async function configure(codemods) {
10
+ // The config below reads these, so they are declared here. Writing the file
11
+ // without them leaves an application whose config asks the environment for
12
+ // something nothing ever put there.
13
+ await codemods.addEnvVars({
14
+ CACHE_STORE: "memory",
15
+ });
16
+ await codemods.addProvider("@c9up/echo/provider");
17
+ await codemods.writeFile("config/cache.ts", `import { defineConfig, drivers, store } from '@c9up/echo'
18
+ import env from '#start/env'
19
+
20
+ export default defineConfig({
21
+ default: env.get('CACHE_STORE', 'memory'),
22
+
23
+ stores: {
24
+ // One layer, in this process.
25
+ memory: store().useL1Layer(drivers.memory({ maxItems: 1000 })),
26
+
27
+ // Two layers: memory in front of Redis, with a bus so every instance
28
+ // drops its own L1 entry when another writes.
29
+ tiered: store()
30
+ .useL1Layer(drivers.memory({ maxItems: 1000 }))
31
+ .useL2Layer(drivers.redis({ connection: 'main' }))
32
+ .useBus(drivers.redisBus({ connection: 'main' })),
33
+ },
34
+ })`);
35
+ }
36
+ //# sourceMappingURL=configure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configure.js","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAYH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAkB;IACjD,4EAA4E;IAC5E,2EAA2E;IAC3E,oCAAoC;IACpC,MAAM,QAAQ,CAAC,UAAU,CAAC;QACzB,WAAW,EAAE,QAAQ;KACrB,CAAC,CAAC;IAEH,MAAM,QAAQ,CAAC,WAAW,CAAC,qBAAqB,CAAC,CAAC;IAClD,MAAM,QAAQ,CAAC,SAAS,CACvB,iBAAiB,EACjB;;;;;;;;;;;;;;;;;GAiBC,CACD,CAAC;AACH,CAAC"}
package/dist/index.d.ts CHANGED
@@ -19,7 +19,7 @@ export type { Duration } from "./duration.js";
19
19
  export { parseDuration, resolveTtlSeconds } from "./duration.js";
20
20
  export type { EchoProviderConfig } from "./EchoProvider.js";
21
21
  export { FactoryError, TimeoutError } from "./errors.js";
22
- export { CacheStoreManager, type DriverFactory, drivers, type MultiStoreConfig, type StoreConfig, } from "./StoreManager.js";
22
+ export { CacheStoreManager, type DriverFactory, drivers, type MultiStoreConfig, Store, type StoreConfig, store, } from "./StoreManager.js";
23
23
  export type { CacheEmitter, CacheEntry, CacheEventMap, DefaultValue, DeleteByTagOptions, DeleteManyOptions, DeleteOptions, ExpireOptions, Factory, GetOptions, GetOrSetForeverOptions, GetOrSetOptions, HasOptions, SetOptions, TaggableDriver, } from "./types.js";
24
24
  import type { EchoProviderConfig } from "./EchoProvider.js";
25
25
  import type { MultiStoreConfig } from "./StoreManager.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,YAAY,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,YAAY,EACX,UAAU,EACV,QAAQ,EACR,mBAAmB,GACnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACjE,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACN,iBAAiB,EACjB,KAAK,aAAa,EAClB,OAAO,EACP,KAAK,gBAAgB,EACrB,KAAK,WAAW,GAChB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACX,YAAY,EACZ,UAAU,EACV,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,OAAO,EACP,UAAU,EACV,sBAAsB,EACtB,eAAe,EACf,UAAU,EACV,UAAU,EACV,cAAc,GACd,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,kBAAkB,GAAG,gBAAgB,EAC3E,MAAM,EAAE,CAAC,GACP,CAAC,CAEH"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,YAAY,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,YAAY,EACX,UAAU,EACV,QAAQ,EACR,mBAAmB,GACnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACjE,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACN,iBAAiB,EACjB,KAAK,aAAa,EAClB,OAAO,EACP,KAAK,gBAAgB,EACrB,KAAK,EACL,KAAK,WAAW,EAChB,KAAK,GACL,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACX,YAAY,EACZ,UAAU,EACV,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,OAAO,EACP,UAAU,EACV,sBAAsB,EACtB,eAAe,EACf,UAAU,EACV,UAAU,EACV,cAAc,GACd,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,kBAAkB,GAAG,gBAAgB,EAC3E,MAAM,EAAE,CAAC,GACP,CAAC,CAEH"}
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ export { RedisDriver } from "./drivers/RedisDriver.js";
14
14
  export { TieredDriver } from "./drivers/TieredDriver.js";
15
15
  export { parseDuration, resolveTtlSeconds } from "./duration.js";
16
16
  export { FactoryError, TimeoutError } from "./errors.js";
17
- export { CacheStoreManager, drivers, } from "./StoreManager.js";
17
+ export { CacheStoreManager, drivers, Store, store, } from "./StoreManager.js";
18
18
  /**
19
19
  * Author-time config helper for `config/cache.ts` — AdonisJS cache `defineConfig`
20
20
  * parity. Identity at runtime; the generic preserves literal types for inference.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAMvD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEjE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACN,iBAAiB,EAEjB,OAAO,GAGP,MAAM,mBAAmB,CAAC;AAsB3B;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAC3B,MAAS;IAET,OAAO,MAAM,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAMvD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEjE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACN,iBAAiB,EAEjB,OAAO,EAEP,KAAK,EAEL,KAAK,GACL,MAAM,mBAAmB,CAAC;AAsB3B;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAC3B,MAAS;IAET,OAAO,MAAM,CAAC;AACf,CAAC"}
@@ -15,6 +15,11 @@ import type { CacheManager } from "../CacheManager.js";
15
15
  export declare function setCache(value: CacheManager): void;
16
16
  /** @internal Read the singleton (or `undefined` pre-boot). */
17
17
  export declare function getCache(): CacheManager | undefined;
18
+ /**
19
+ * @internal Release the singleton, so a shut-down application does not leave a
20
+ * disconnected cache reachable through `services/main`.
21
+ */
22
+ export declare function clearCache(): void;
18
23
  declare const cache: CacheManager;
19
24
  export default cache;
20
25
  //# sourceMappingURL=main.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/services/main.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAIvD,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAElD;AAED,8DAA8D;AAC9D,wBAAgB,QAAQ,IAAI,YAAY,GAAG,SAAS,CAEnD;AAED,QAAA,MAAM,KAAK,EAAE,YAoBX,CAAC;AAEH,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/services/main.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAIvD,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAElD;AAED,8DAA8D;AAC9D,wBAAgB,QAAQ,IAAI,YAAY,GAAG,SAAS,CAEnD;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAEjC;AAED,QAAA,MAAM,KAAK,EAAE,YAoBX,CAAC;AAEH,eAAe,KAAK,CAAC"}
@@ -19,6 +19,13 @@ export function setCache(value) {
19
19
  export function getCache() {
20
20
  return instance;
21
21
  }
22
+ /**
23
+ * @internal Release the singleton, so a shut-down application does not leave a
24
+ * disconnected cache reachable through `services/main`.
25
+ */
26
+ export function clearCache() {
27
+ instance = undefined;
28
+ }
22
29
  const cache = new Proxy({}, {
23
30
  get(_target, prop) {
24
31
  // A module loader inspects what it imports before anyone uses it: it reads
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/services/main.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,IAAI,QAAkC,CAAC;AAEvC,2EAA2E;AAC3E,MAAM,UAAU,QAAQ,CAAC,KAAmB;IAC3C,QAAQ,GAAG,KAAK,CAAC;AAClB,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,QAAQ;IACvB,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED,MAAM,KAAK,GAAiB,IAAI,KAAK,CAAC,EAAkB,EAAE;IACzD,GAAG,CAAC,OAAO,EAAE,IAAI;QAChB,2EAA2E;QAC3E,0EAA0E;QAC1E,8DAA8D;QAC9D,0EAA0E;QAC1E,0EAA0E;QAC1E,wEAAwE;QACxE,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACjD,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACd,wEAAwE;gBACvE,4DAA4D,CAC7D,CAAC;QACH,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACpD,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACnE,CAAC;CACD,CAAC,CAAC;AAEH,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/services/main.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,IAAI,QAAkC,CAAC;AAEvC,2EAA2E;AAC3E,MAAM,UAAU,QAAQ,CAAC,KAAmB;IAC3C,QAAQ,GAAG,KAAK,CAAC;AAClB,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,QAAQ;IACvB,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU;IACzB,QAAQ,GAAG,SAAS,CAAC;AACtB,CAAC;AAED,MAAM,KAAK,GAAiB,IAAI,KAAK,CAAC,EAAkB,EAAE;IACzD,GAAG,CAAC,OAAO,EAAE,IAAI;QAChB,2EAA2E;QAC3E,0EAA0E;QAC1E,8DAA8D;QAC9D,0EAA0E;QAC1E,0EAA0E;QAC1E,wEAAwE;QACxE,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACjD,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACd,wEAAwE;gBACvE,4DAA4D,CAC7D,CAAC;QACH,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACpD,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACnE,CAAC;CACD,CAAC,CAAC;AAEH,eAAe,KAAK,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c9up/echo",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "Cache — pluggable cache contract with memory + Redis drivers for the Ream framework",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -15,6 +15,10 @@
15
15
  "types": "./dist/EchoProvider.d.ts",
16
16
  "import": "./dist/EchoProvider.js"
17
17
  },
18
+ "./configure": {
19
+ "types": "./dist/configure.d.ts",
20
+ "import": "./dist/configure.js"
21
+ },
18
22
  "./services/main": {
19
23
  "types": "./dist/services/main.d.ts",
20
24
  "import": "./dist/services/main.js"
@@ -1,7 +1,7 @@
1
1
  import { type CacheConfig, CacheManager } from "./CacheManager.js";
2
2
  import { MemoryDriver } from "./drivers/MemoryDriver.js";
3
3
  import { CacheStoreManager, type MultiStoreConfig } from "./StoreManager.js";
4
- import { setCache } from "./services/main.js";
4
+ import { clearCache, getCache, setCache } from "./services/main.js";
5
5
  import type { CacheEmitter } from "./types.js";
6
6
 
7
7
  /**
@@ -109,9 +109,28 @@ export default class EchoProvider {
109
109
  );
110
110
  }
111
111
 
112
+ /** The cache THIS provider booted — not whatever the module singleton holds. */
113
+ #cache: CacheManager | undefined;
114
+
112
115
  async boot(): Promise<void> {
113
- setCache(await this.app.container.resolve<CacheManager>(CacheManager));
116
+ this.#cache = await this.app.container.resolve<CacheManager>(CacheManager);
117
+ setCache(this.#cache);
114
118
  }
115
119
 
116
- async shutdown(): Promise<void> {}
120
+ /**
121
+ * Release the cache the app booted.
122
+ *
123
+ * The memory driver runs a sweep on a timer and the redis driver holds a
124
+ * connection. Neither is released on its own, so across a dev reload or a
125
+ * test run each cycle leaves another one behind.
126
+ */
127
+ async shutdown(): Promise<void> {
128
+ if (!this.#cache) return;
129
+ await this.#cache.disconnect();
130
+ // Two applications can share a process — parallel tests, a hot reload.
131
+ // The module singleton holds whichever booted last, so it is only ours
132
+ // to clear while it still points at the cache this provider booted.
133
+ if (getCache() === this.#cache) clearCache();
134
+ this.#cache = undefined;
135
+ }
117
136
  }
@@ -39,11 +39,92 @@ export interface StoreConfig {
39
39
 
40
40
  export interface MultiStoreConfig {
41
41
  default: string;
42
- stores: Record<string, StoreConfig>;
42
+ /**
43
+ * The stores this application can use, by name. Each is a {@link store}
44
+ * builder — the shape a cache config takes — or the plain
45
+ * `{ driver, …options }` form kept for configs written against it.
46
+ */
47
+ stores: Record<string, StoreConfig | Store>;
43
48
  /** Shared emitter for all stores' events. */
44
49
  emitter?: CacheEmitter;
45
50
  }
46
51
 
52
+ /**
53
+ * A store, described the way a cache config describes one: a layer at a time.
54
+ *
55
+ * stores: {
56
+ * memoryOnly: store().useL1Layer(drivers.memory()),
57
+ * default: store({ ttl: 60 })
58
+ * .useL1Layer(drivers.memory())
59
+ * .useL2Layer(drivers.redis({ connection: "main" })),
60
+ * }
61
+ *
62
+ * One layer is that driver; two are a tiered driver over both, which is what
63
+ * the layering means — reads hit L1, misses fall to L2, and writes go to both.
64
+ */
65
+ export class Store {
66
+ readonly #options: Omit<StoreConfig, "driver">;
67
+ #l1: DriverFactory | undefined;
68
+ #l2: DriverFactory | undefined;
69
+ #bus: CacheBus | undefined;
70
+
71
+ constructor(options: Omit<StoreConfig, "driver"> = {}) {
72
+ this.#options = options;
73
+ }
74
+
75
+ /** The fast layer, usually memory. */
76
+ useL1Layer(driver: DriverFactory): this {
77
+ this.#l1 = driver;
78
+ return this;
79
+ }
80
+
81
+ /** The shared layer, usually Redis — what makes the cache survive a restart. */
82
+ useL2Layer(driver: DriverFactory): this {
83
+ this.#l2 = driver;
84
+ return this;
85
+ }
86
+
87
+ /** The bus that keeps every instance's L1 in step after a write. */
88
+ useBus(bus: CacheBus): this {
89
+ this.#bus = bus;
90
+ return this;
91
+ }
92
+
93
+ /** The `{ driver, …options }` the manager consumes. */
94
+ entry(): StoreConfig {
95
+ const l1 = this.#l1;
96
+ const l2 = this.#l2;
97
+ if (!l1 && !l2) {
98
+ throw new Error(
99
+ "Echo: a store needs a layer — call useL1Layer() or useL2Layer() on it.",
100
+ );
101
+ }
102
+ if (l1 && l2) {
103
+ return {
104
+ ...this.#options,
105
+ driver: drivers.tiered({ l1, l2, bus: this.#bus }),
106
+ };
107
+ }
108
+ const only = (l1 ?? l2) as DriverFactory;
109
+ if (this.#bus) {
110
+ throw new Error(
111
+ "Echo: a bus only means something with two layers — it keeps each instance's L1 in step. Add useL2Layer(), or drop useBus().",
112
+ );
113
+ }
114
+ return { ...this.#options, driver: only };
115
+ }
116
+ }
117
+
118
+ /** Start describing a store — AdonisJS's `store()`. */
119
+ export function store(options?: Omit<StoreConfig, "driver">): Store {
120
+ return new Store(options);
121
+ }
122
+
123
+ /** Normalise either accepted form to the one the manager reads. */
124
+ function entryOf(config: StoreConfig | Store): StoreConfig {
125
+ return config instanceof Store ? config.entry() : config;
126
+ }
127
+
47
128
  /** Driver factory helpers (bento `drivers.memory` / `drivers.redis`). */
48
129
  export const drivers = {
49
130
  memory(options?: { sweepIntervalMs?: number }): DriverFactory {
@@ -110,10 +191,11 @@ export class CacheStoreManager {
110
191
  const existing = this.#built.get(store);
111
192
  if (existing) return existing;
112
193
 
113
- const cfg = this.#config.stores[store];
114
- if (!cfg) {
194
+ const declared = this.#config.stores[store];
195
+ if (!declared) {
115
196
  throw new Error(`Echo: unknown cache store "${store}"`);
116
197
  }
198
+ const cfg = entryOf(declared);
117
199
  const manager = new CacheManager(cfg.driver(), {
118
200
  prefix: cfg.prefix,
119
201
  ttl: cfg.ttl,
@@ -0,0 +1,50 @@
1
+ /**
2
+ * `ream configure @c9up/echo` — wire the cache in one command.
3
+ *
4
+ * The provider alone is not enough: it reads `config/cache.ts`, and a package
5
+ * registered without one falls back to a default that is rarely the one an
6
+ * application wants. Writing both together is what makes `ream add` mean
7
+ * installed AND working.
8
+ */
9
+
10
+ interface Codemods {
11
+ addProvider(importPath: string): Promise<void>;
12
+ addEnvVars(vars: Record<string, string>): Promise<void>;
13
+ writeFile(
14
+ filePath: string,
15
+ content: string,
16
+ options?: { force?: boolean },
17
+ ): Promise<void>;
18
+ }
19
+
20
+ export async function configure(codemods: Codemods): Promise<void> {
21
+ // The config below reads these, so they are declared here. Writing the file
22
+ // without them leaves an application whose config asks the environment for
23
+ // something nothing ever put there.
24
+ await codemods.addEnvVars({
25
+ CACHE_STORE: "memory",
26
+ });
27
+
28
+ await codemods.addProvider("@c9up/echo/provider");
29
+ await codemods.writeFile(
30
+ "config/cache.ts",
31
+ `import { defineConfig, drivers, store } from '@c9up/echo'
32
+ import env from '#start/env'
33
+
34
+ export default defineConfig({
35
+ default: env.get('CACHE_STORE', 'memory'),
36
+
37
+ stores: {
38
+ // One layer, in this process.
39
+ memory: store().useL1Layer(drivers.memory({ maxItems: 1000 })),
40
+
41
+ // Two layers: memory in front of Redis, with a bus so every instance
42
+ // drops its own L1 entry when another writes.
43
+ tiered: store()
44
+ .useL1Layer(drivers.memory({ maxItems: 1000 }))
45
+ .useL2Layer(drivers.redis({ connection: 'main' }))
46
+ .useBus(drivers.redisBus({ connection: 'main' })),
47
+ },
48
+ })`,
49
+ );
50
+ }
package/src/index.ts CHANGED
@@ -29,7 +29,9 @@ export {
29
29
  type DriverFactory,
30
30
  drivers,
31
31
  type MultiStoreConfig,
32
+ Store,
32
33
  type StoreConfig,
34
+ store,
33
35
  } from "./StoreManager.js";
34
36
  export type {
35
37
  CacheEmitter,
@@ -25,6 +25,14 @@ export function getCache(): CacheManager | undefined {
25
25
  return instance;
26
26
  }
27
27
 
28
+ /**
29
+ * @internal Release the singleton, so a shut-down application does not leave a
30
+ * disconnected cache reachable through `services/main`.
31
+ */
32
+ export function clearCache(): void {
33
+ instance = undefined;
34
+ }
35
+
28
36
  const cache: CacheManager = new Proxy({} as CacheManager, {
29
37
  get(_target, prop) {
30
38
  // A module loader inspects what it imports before anyone uses it: it reads