@boostkit/cache 0.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 BoostKit
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # @boostkit/cache
2
+
3
+ Cache facade, cache registry, and provider factory with an in-memory built-in driver.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @boostkit/cache
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```ts
14
+ // bootstrap/providers.ts
15
+ import { cache } from '@boostkit/cache'
16
+ import configs from '../config/index.js'
17
+
18
+ export default [
19
+ cache(configs.cache),
20
+ ]
21
+
22
+ // anywhere after boot
23
+ import { Cache } from '@boostkit/cache'
24
+ await Cache.set('users:count', 10, 60)
25
+ const count = await Cache.get<number>('users:count')
26
+ ```
27
+
28
+ ## API Reference
29
+
30
+ - `CacheAdapter`, `CacheAdapterProvider`
31
+ - `CacheRegistry`
32
+ - `Cache`
33
+ - `CacheStoreConfig`, `CacheConfig`
34
+ - `cache(config)`
35
+
36
+ ## Configuration
37
+
38
+ - `CacheConfig`
39
+ - `default`
40
+ - `stores`
41
+ - `CacheStoreConfig`
42
+ - `driver`
43
+ - additional driver-specific keys
44
+
45
+ ## Notes
46
+
47
+ - Built-in driver: `memory`.
48
+ - Plugin driver supported by factory: `redis` (via `@boostkit/cache-redis`).
@@ -0,0 +1,57 @@
1
+ import { ServiceProvider, type Application } from '@boostkit/core';
2
+ export interface CacheAdapter {
3
+ get<T = unknown>(key: string): Promise<T | null>;
4
+ set(key: string, value: unknown, ttlSeconds?: number): Promise<void>;
5
+ forget(key: string): Promise<void>;
6
+ has(key: string): Promise<boolean>;
7
+ flush(): Promise<void>;
8
+ }
9
+ export interface CacheAdapterProvider {
10
+ create(): CacheAdapter | Promise<CacheAdapter>;
11
+ }
12
+ export declare class CacheRegistry {
13
+ private static adapter;
14
+ static set(adapter: CacheAdapter): void;
15
+ static get(): CacheAdapter | null;
16
+ }
17
+ export declare class Cache {
18
+ private static store;
19
+ /** Retrieve a value. Returns null on miss or expiry. */
20
+ static get<T = unknown>(key: string): Promise<T | null>;
21
+ /** Store a value, optionally with a TTL in seconds. */
22
+ static set(key: string, value: unknown, ttl?: number): Promise<void>;
23
+ /**
24
+ * Retrieve a value, or compute + store it if missing.
25
+ * @param ttl Time-to-live in seconds
26
+ */
27
+ static remember<T = unknown>(key: string, ttl: number, callback: () => T | Promise<T>): Promise<T>;
28
+ /** Remove a single key. */
29
+ static forget(key: string): Promise<void>;
30
+ /** Check if a key exists (and hasn't expired). */
31
+ static has(key: string): Promise<boolean>;
32
+ /** Remove all cached entries. */
33
+ static flush(): Promise<void>;
34
+ }
35
+ export interface CacheStoreConfig {
36
+ driver: string;
37
+ [key: string]: unknown;
38
+ }
39
+ export interface CacheConfig {
40
+ /** The default cache store name */
41
+ default: string;
42
+ /** Named cache stores */
43
+ stores: Record<string, CacheStoreConfig>;
44
+ }
45
+ /**
46
+ * Returns a CacheServiceProvider class configured for the given cache config.
47
+ *
48
+ * Built-in drivers: memory (in-process — resets on restart, great for dev)
49
+ * Plugin drivers: redis (@boostkit/cache-redis)
50
+ *
51
+ * Usage in bootstrap/providers.ts:
52
+ * import { cache } from '@boostkit/cache'
53
+ * import configs from '../config/index.js'
54
+ * export default [..., cache(configs.cache), ...]
55
+ */
56
+ export declare function cache(config: CacheConfig): new (app: Application) => ServiceProvider;
57
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAKlE,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;IAChD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAClC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAClC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,IAAI,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;CAC/C;AAID,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,OAAO,CAA4B;IAElD,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IACvC,MAAM,CAAC,GAAG,IAAI,YAAY,GAAG,IAAI;CAClC;AAID,qBAAa,KAAK;IAChB,OAAO,CAAC,MAAM,CAAC,KAAK;IAMpB,wDAAwD;IACxD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAIvD,uDAAuD;IACvD,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE;;;OAGG;WACU,QAAQ,CAAC,CAAC,GAAG,OAAO,EAC/B,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAC7B,OAAO,CAAC,CAAC,CAAC;IAQb,2BAA2B;IAC3B,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAEzC,kDAAkD;IAClD,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAEzC,iCAAiC;IACjC,MAAM,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAC9B;AA0CD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,yBAAyB;IACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;CACzC;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,GAAG,EAAE,WAAW,KAAK,eAAe,CA4BpF"}
package/dist/index.js ADDED
@@ -0,0 +1,113 @@
1
+ import { ServiceProvider } from '@boostkit/core';
2
+ import { resolveOptionalPeer } from '@boostkit/core';
3
+ // ─── Cache Registry ────────────────────────────────────────
4
+ export class CacheRegistry {
5
+ static adapter = null;
6
+ static set(adapter) { this.adapter = adapter; }
7
+ static get() { return this.adapter; }
8
+ }
9
+ // ─── Cache Facade ──────────────────────────────────────────
10
+ export class Cache {
11
+ static store() {
12
+ const a = CacheRegistry.get();
13
+ if (!a)
14
+ throw new Error('[BoostKit Cache] No cache adapter registered. Add cache() to providers.');
15
+ return a;
16
+ }
17
+ /** Retrieve a value. Returns null on miss or expiry. */
18
+ static get(key) {
19
+ return this.store().get(key);
20
+ }
21
+ /** Store a value, optionally with a TTL in seconds. */
22
+ static set(key, value, ttl) {
23
+ return this.store().set(key, value, ttl);
24
+ }
25
+ /**
26
+ * Retrieve a value, or compute + store it if missing.
27
+ * @param ttl Time-to-live in seconds
28
+ */
29
+ static async remember(key, ttl, callback) {
30
+ const cached = await this.get(key);
31
+ if (cached !== null)
32
+ return cached;
33
+ const value = await callback();
34
+ await this.set(key, value, ttl);
35
+ return value;
36
+ }
37
+ /** Remove a single key. */
38
+ static forget(key) { return this.store().forget(key); }
39
+ /** Check if a key exists (and hasn't expired). */
40
+ static has(key) { return this.store().has(key); }
41
+ /** Remove all cached entries. */
42
+ static flush() { return this.store().flush(); }
43
+ }
44
+ class MemoryAdapter {
45
+ store = new Map();
46
+ expired(entry) {
47
+ return entry.expiresAt !== null && Date.now() > entry.expiresAt;
48
+ }
49
+ async get(key) {
50
+ const entry = this.store.get(key);
51
+ if (!entry)
52
+ return null;
53
+ if (this.expired(entry)) {
54
+ this.store.delete(key);
55
+ return null;
56
+ }
57
+ return entry.value;
58
+ }
59
+ async set(key, value, ttlSeconds) {
60
+ const expiresAt = ttlSeconds ? Date.now() + ttlSeconds * 1_000 : null;
61
+ this.store.set(key, { value, expiresAt });
62
+ }
63
+ async forget(key) { this.store.delete(key); }
64
+ async has(key) {
65
+ const entry = this.store.get(key);
66
+ if (!entry)
67
+ return false;
68
+ if (this.expired(entry)) {
69
+ this.store.delete(key);
70
+ return false;
71
+ }
72
+ return true;
73
+ }
74
+ async flush() { this.store.clear(); }
75
+ }
76
+ // ─── Service Provider Factory ──────────────────────────────
77
+ /**
78
+ * Returns a CacheServiceProvider class configured for the given cache config.
79
+ *
80
+ * Built-in drivers: memory (in-process — resets on restart, great for dev)
81
+ * Plugin drivers: redis (@boostkit/cache-redis)
82
+ *
83
+ * Usage in bootstrap/providers.ts:
84
+ * import { cache } from '@boostkit/cache'
85
+ * import configs from '../config/index.js'
86
+ * export default [..., cache(configs.cache), ...]
87
+ */
88
+ export function cache(config) {
89
+ class CacheServiceProvider extends ServiceProvider {
90
+ register() { }
91
+ async boot() {
92
+ const storeName = config.default;
93
+ const storeConfig = config.stores[storeName] ?? { driver: 'memory' };
94
+ const driver = storeConfig['driver'];
95
+ let adapter;
96
+ if (driver === 'memory') {
97
+ adapter = new MemoryAdapter();
98
+ }
99
+ else if (driver === 'redis') {
100
+ const { redis } = await resolveOptionalPeer('@boostkit/cache-redis');
101
+ adapter = await redis(storeConfig).create();
102
+ }
103
+ else {
104
+ throw new Error(`[BoostKit Cache] Unknown driver "${driver}". Available: memory, redis`);
105
+ }
106
+ CacheRegistry.set(adapter);
107
+ this.app.instance('cache', adapter);
108
+ console.log(`[CacheServiceProvider] booted — driver: ${driver}`);
109
+ }
110
+ }
111
+ return CacheServiceProvider;
112
+ }
113
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAoB,MAAM,gBAAgB,CAAA;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AAgBpD,8DAA8D;AAE9D,MAAM,OAAO,aAAa;IAChB,MAAM,CAAC,OAAO,GAAwB,IAAI,CAAA;IAElD,MAAM,CAAC,GAAG,CAAC,OAAqB,IAAU,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA,CAAC,CAAC;IAClE,MAAM,CAAC,GAAG,KAAiC,OAAO,IAAI,CAAC,OAAO,CAAA,CAAC,CAAC;;AAGlE,8DAA8D;AAE9D,MAAM,OAAO,KAAK;IACR,MAAM,CAAC,KAAK;QAClB,MAAM,CAAC,GAAG,aAAa,CAAC,GAAG,EAAE,CAAA;QAC7B,IAAI,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAA;QAClG,OAAO,CAAC,CAAA;IACV,CAAC;IAED,wDAAwD;IACxD,MAAM,CAAC,GAAG,CAAc,GAAW;QACjC,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,CAAI,GAAG,CAAC,CAAA;IACjC,CAAC;IAED,uDAAuD;IACvD,MAAM,CAAC,GAAG,CAAC,GAAW,EAAE,KAAc,EAAE,GAAY;QAClD,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,CAAA;IAC1C,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,KAAK,CAAC,QAAQ,CACnB,GAAW,EACX,GAAW,EACX,QAA8B;QAE9B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAI,GAAG,CAAC,CAAA;QACrC,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,MAAM,CAAA;QAClC,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAA;QAC9B,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,CAAA;QAC/B,OAAO,KAAK,CAAA;IACd,CAAC;IAED,2BAA2B;IAC3B,MAAM,CAAC,MAAM,CAAC,GAAW,IAAoB,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA,CAAC,CAAC;IAE9E,kDAAkD;IAClD,MAAM,CAAC,GAAG,CAAC,GAAW,IAAuB,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA,CAAC,CAAC;IAE3E,iCAAiC;IACjC,MAAM,CAAC,KAAK,KAAiC,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,CAAA,CAAC,CAAC;CAC3E;AASD,MAAM,aAAa;IACA,KAAK,GAAG,IAAI,GAAG,EAAuB,CAAA;IAE/C,OAAO,CAAC,KAAkB;QAChC,OAAO,KAAK,CAAC,SAAS,KAAK,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,CAAA;IACjE,CAAC;IAED,KAAK,CAAC,GAAG,CAAc,GAAW;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACjC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAA;QACvB,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAAC,OAAO,IAAI,CAAA;QAAC,CAAC;QAChE,OAAO,KAAK,CAAC,KAAU,CAAA;IACzB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAc,EAAE,UAAmB;QACxD,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA;QACrE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;IAC3C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW,IAAoB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA,CAAC,CAAC;IAEpE,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACjC,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAA;QACxB,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAAC,OAAO,KAAK,CAAA;QAAC,CAAC;QACjE,OAAO,IAAI,CAAA;IACb,CAAC;IAED,KAAK,CAAC,KAAK,KAAoB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA,CAAC,CAAC;CACpD;AAgBD,8DAA8D;AAE9D;;;;;;;;;;GAUG;AACH,MAAM,UAAU,KAAK,CAAC,MAAmB;IACvC,MAAM,oBAAqB,SAAQ,eAAe;QAChD,QAAQ,KAAU,CAAC;QAEnB,KAAK,CAAC,IAAI;YACR,MAAM,SAAS,GAAK,MAAM,CAAC,OAAO,CAAA;YAClC,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAA;YACpE,MAAM,MAAM,GAAQ,WAAW,CAAC,QAAQ,CAAW,CAAA;YAEnD,IAAI,OAAqB,CAAA;YAEzB,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;gBACxB,OAAO,GAAG,IAAI,aAAa,EAAE,CAAA;YAC/B,CAAC;iBAAM,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;gBAC9B,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,mBAAmB,CAAM,uBAAuB,CAAC,CAAA;gBACzE,OAAO,GAAG,MAAO,KAA8C,CAAC,WAAW,CAAC,CAAC,MAAM,EAAE,CAAA;YACvF,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,KAAK,CAAC,oCAAoC,MAAM,6BAA6B,CAAC,CAAA;YAC1F,CAAC;YAED,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YAC1B,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;YAEnC,OAAO,CAAC,GAAG,CAAC,2CAA2C,MAAM,EAAE,CAAC,CAAA;QAClE,CAAC;KACF;IAED,OAAO,oBAAoB,CAAA;AAC7B,CAAC"}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@boostkit/cache",
3
+ "version": "0.0.1",
4
+ "license": "MIT",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/boostkitjs/boostkit",
8
+ "directory": "packages/cache"
9
+ },
10
+ "type": "module",
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "main": "./dist/index.js",
15
+ "types": "./dist/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "import": "./dist/index.js",
19
+ "types": "./dist/index.d.ts"
20
+ }
21
+ },
22
+ "dependencies": {
23
+ "@boostkit/core": "0.0.1"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "^20.0.0",
27
+ "typescript": "^5.4.0",
28
+ "tsx": "^4.0.0"
29
+ },
30
+ "scripts": {
31
+ "build": "tsc",
32
+ "dev": "tsc --watch",
33
+ "typecheck": "tsc --noEmit",
34
+ "clean": "rm -rf dist",
35
+ "test": "tsc -p tsconfig.test.json && node --test dist-test/index.test.js; rm -rf dist-test"
36
+ }
37
+ }