@stacksjs/cache 0.70.22 → 0.70.25

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.
@@ -0,0 +1,127 @@
1
+ import { CacheManager, MemoryDriver, RedisDriver } from '@stacksjs/ts-cache';
2
+ import type { CacheDriver, CacheStats } from '@stacksjs/types';
3
+ /**
4
+ * Create a memory cache driver
5
+ */
6
+ export declare function createMemoryCache(options?: MemoryOptions): CacheDriver;
7
+ /**
8
+ * Create a Redis cache driver
9
+ */
10
+ export declare function createRedisCache(options?: RedisOptions): CacheDriver;
11
+ /**
12
+ * Create a cache driver based on the specified type
13
+ */
14
+ export declare function createCache(driver: 'memory', options?: MemoryOptions): CacheDriver;
15
+ export declare function createCache(driver: 'redis', options?: RedisOptions): CacheDriver;
16
+ /**
17
+ * Default memory cache instance
18
+ */
19
+ export declare const memory: CacheDriver;
20
+ /**
21
+ * Default cache instance (memory)
22
+ */
23
+ export declare const cache: CacheDriver;
24
+ /**
25
+ * Memory cache options
26
+ */
27
+ export declare interface MemoryOptions {
28
+ stdTTL?: number
29
+ checkPeriod?: number
30
+ maxKeys?: number
31
+ useClones?: boolean
32
+ prefix?: string
33
+ }
34
+ /**
35
+ * Redis cache options
36
+ */
37
+ export declare interface RedisOptions {
38
+ url?: string
39
+ host?: string
40
+ port?: number
41
+ username?: string
42
+ password?: string
43
+ database?: number
44
+ tls?: boolean
45
+ stdTTL?: number
46
+ prefix?: string
47
+ }
48
+ /**
49
+ * Stacks Cache Wrapper
50
+ *
51
+ * Wraps ts-cache's CacheManager to provide a consistent API
52
+ * that matches the Stacks CacheDriver interface.
53
+ */
54
+ export declare class StacksCache implements CacheDriver {
55
+ constructor(manager: CacheManager);
56
+ get<T>(key: string): Promise<T | undefined>;
57
+ mget<T>(keys: string[]): Promise<Record<string, T>>;
58
+ set<T>(key: string, value: T, ttl?: number): Promise<boolean>;
59
+ mset<T>(entries: Array<{ key: string, value: T, ttl?: number }>): Promise<boolean>;
60
+ setForever<T>(key: string, value: T): Promise<boolean>;
61
+ getOrSet<T>(key: string, fetcher: () => T | Promise<T>, ttl?: number): Promise<T>;
62
+ remember<T>(key: string, ttl: number, callback: () => T | Promise<T>): Promise<T>;
63
+ rememberForever<T>(key: string, callback: () => T | Promise<T>): Promise<T>;
64
+ del(keys: string | string[]): Promise<number>;
65
+ has(key: string): Promise<boolean>;
66
+ missing(key: string): Promise<boolean>;
67
+ remove(key: string): Promise<void>;
68
+ deleteMany(keys: string[]): Promise<number>;
69
+ clear(): Promise<void>;
70
+ flush(): Promise<void>;
71
+ keys(pattern?: string): Promise<string[]>;
72
+ getTtl(key: string): Promise<number | undefined>;
73
+ ttl(key: string, ttl: number): Promise<boolean>;
74
+ take<T>(key: string): Promise<T | undefined>;
75
+ getStats(): Promise<CacheStats>;
76
+ close(): Promise<void>;
77
+ disconnect(): Promise<void>;
78
+ get cacheManager(): CacheManager;
79
+ tags(tags: readonly string[]): TaggedCache;
80
+ }
81
+ /**
82
+ * Tag-scoped wrapper around `StacksCache`. Records every write under
83
+ * the named tag(s) so `flush()` can invalidate cascade-style without the
84
+ * caller having to track keys themselves.
85
+ *
86
+ * The tag index is stored as `string[]` on disk (so it survives the
87
+ * Redis driver's serializer), but operated on in memory as a `Set` so
88
+ * each write is `O(1)` instead of `O(N)` over the existing index.
89
+ *
90
+ * `flush()` uses a per-tag in-process mutex so concurrent flushes don't
91
+ * race-and-lose keys: without it, two parallel flushes could both read
92
+ * the index, both delete, and the second flush would succeed against
93
+ * the now-empty index — leaving any keys added between the two reads
94
+ * orphaned.
95
+ */
96
+ export declare class TaggedCache {
97
+ constructor(cache: StacksCache, tags: readonly string[]);
98
+ put<T>(key: string, value: T, ttl?: number): Promise<boolean>;
99
+ set<T>(key: string, value: T, ttl?: number): Promise<boolean>;
100
+ setForever<T>(key: string, value: T): Promise<boolean>;
101
+ remember<T>(key: string, ttl: number, callback: () => T | Promise<T>): Promise<T>;
102
+ rememberForever<T>(key: string, callback: () => T | Promise<T>): Promise<T>;
103
+ get<T>(key: string): Promise<T | undefined>;
104
+ has(key: string): Promise<boolean>;
105
+ flush(): Promise<number>;
106
+ }
107
+ // Re-export ts-cache utilities for advanced usage
108
+ export {
109
+ CacheManager,
110
+ MemoryDriver,
111
+ RedisDriver,
112
+ } from '@stacksjs/ts-cache';
113
+ // Re-export patterns and utilities
114
+ export {
115
+ // Patterns
116
+ CacheAsidePattern,
117
+ MultiLevelPattern,
118
+ RefreshAheadPattern,
119
+ WriteThroughPattern,
120
+ // Utilities
121
+ BatchOperations,
122
+ CacheInvalidation,
123
+ CacheLock,
124
+ CircuitBreaker,
125
+ memoize,
126
+ RateLimiter,
127
+ } from '@stacksjs/ts-cache';
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @stacksjs/cache
3
+ *
4
+ * A high-performance, type-safe caching library powered by ts-cache.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import { cache, createCache, createMemoryCache, createRedisCache } from '@stacksjs/cache'
9
+ *
10
+ * // Use the default memory cache
11
+ * await cache.set('key', 'value', 60) // 60 second TTL
12
+ * const value = await cache.get('key')
13
+ *
14
+ * // Create a custom Redis cache
15
+ * const redisCache = createRedisCache({
16
+ * host: 'localhost',
17
+ * port: 6379,
18
+ * prefix: 'myapp',
19
+ * })
20
+ *
21
+ * // Use the factory function
22
+ * const customCache = createCache('memory', { maxKeys: 1000 })
23
+ * ```
24
+ */
25
+ export * from './drivers';
package/package.json CHANGED
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "name": "@stacksjs/cache",
3
3
  "type": "module",
4
- "version": "0.70.22",
4
+ "version": "0.70.25",
5
5
  "description": "Caching the Stacks way.",
6
6
  "author": "Chris Breuer",
7
- "contributors": ["Chris Breuer <chris@stacksjs.org>"],
7
+ "contributors": [
8
+ "Chris Breuer <chris@stacksjs.com>"
9
+ ],
8
10
  "license": "MIT",
9
11
  "funding": "https://github.com/sponsors/chrisbbreuer",
10
12
  "homepage": "https://github.com/stacksjs/stacks/tree/main/storage/framework/core/cache#readme",
@@ -26,26 +28,29 @@
26
28
  ],
27
29
  "exports": {
28
30
  ".": {
31
+ "bun": "./src/index.ts",
32
+ "types": "./dist/index.d.ts",
29
33
  "import": "./dist/index.js"
30
34
  },
31
35
  "./*": {
36
+ "bun": "./src/*",
32
37
  "import": "./dist/*"
33
38
  }
34
39
  },
35
40
  "module": "dist/index.js",
36
41
  "types": "dist/index.d.ts",
37
- "files": ["README.md", "dist"],
42
+ "sideEffects": false,
43
+ "files": [
44
+ "README.md",
45
+ "dist"
46
+ ],
38
47
  "scripts": {
39
48
  "build": "bun build.ts",
40
49
  "typecheck": "bun tsc --noEmit",
41
50
  "prepublishOnly": "bun run build"
42
51
  },
43
52
  "devDependencies": {
44
- "@aws-sdk/client-dynamodb": "^3.777.0",
45
- "@stacksjs/config": "0.70.18",
46
- "@stacksjs/development": "0.70.18",
47
- "bentocache": "^1.2.1",
48
- "dynamodb-tooling": "^0.3.2",
49
- "ioredis": "^5.6.0"
53
+ "@stacksjs/config": "0.70.23",
54
+ "@stacksjs/ts-cache": "^0.1.4"
50
55
  }
51
56
  }
package/dist/base.d.ts DELETED
@@ -1,77 +0,0 @@
1
- import type { BentoCache } from 'bentocache';
2
- import type { CacheDriver } from '@stacksjs/types';
3
- import type { GetOptions } from 'bentocache/types';
4
-
5
- export declare abstract class BaseCacheDriver implements CacheDriver {
6
- constructor(protected client: BentoCache<Record<string, any>>) {}
7
-
8
- async set(key: string, value: string, ttl?: number): Promise<void> {
9
- const data: { key: string, value: string, gracePeriod?: { enabled: boolean, duration: string } } = {
10
- key,
11
- value,
12
- }
13
-
14
- if (ttl) {
15
- data.gracePeriod = {
16
- enabled: true,
17
- duration: `${ttl}m`,
18
- }
19
- }
20
-
21
- await this.client.set(data)
22
- }
23
-
24
- async setForever(key: string, value: string): Promise<void> {
25
- await this.client.setForever({
26
- key,
27
- value,
28
- })
29
- }
30
-
31
- async get<T>(key: GetOptions<T>): Promise<T> {
32
- return await this.client.get<T>(key)
33
- }
34
-
35
- async getOrSet<T>(key: string, value: T): Promise<T> {
36
- return await this.client.getOrSet<T>({
37
- key,
38
- factory: async () => value,
39
- })
40
- }
41
-
42
- async del(key: string): Promise<void> {
43
- await this.client.delete({ key })
44
- }
45
-
46
- async deleteMany(keys: string[]): Promise<void> {
47
- await this.client.deleteMany({ keys })
48
- }
49
-
50
- async remove(key: string): Promise<void> {
51
- await this.client.delete({ key })
52
- }
53
-
54
- async has(key: string): Promise<boolean> {
55
- return await this.client.has({ key })
56
- }
57
-
58
- async missing(key: string): Promise<boolean> {
59
- return await this.client.missing({ key })
60
- }
61
-
62
- async deleteAll(): Promise<void> {
63
- await this.client.clear()
64
- }
65
-
66
- async clear(): Promise<void> {
67
- await this.client.clear()
68
- }
69
-
70
- async disconnect(): Promise<void> {
71
- await this.client.disconnect()
72
- }
73
-
74
- get bentoCacheClient(): BentoCache<Record<string, any>> {
75
- return this.client
76
- }
77
- }
@@ -1,38 +0,0 @@
1
- export declare interface DynamoDBOptions {
2
- endpoint?: string
3
- region?: string
4
- tableName?: string
5
- accessKeyId?: string
6
- secretAccessKey?: string
7
- }
8
- export declare class DynamoDBCacheDriver extends BaseCacheDriver {
9
- constructor(options: DynamoDBOptions = {}) {
10
- const awsAccessKeyId = options.accessKeyId ?? config.cache.drivers?.dynamodb?.key ?? 'dummy'
11
- const awsSecretAccessKey = options.secretAccessKey ?? config.cache.drivers?.dynamodb?.secret ?? 'dummy'
12
- const dynamoEndpoint = options.endpoint ?? config.cache.drivers?.dynamodb?.endpoint ?? 'http:
13
- const tableName = options.tableName ?? config.cache.drivers?.dynamodb?.table ?? 'stacks'
14
- const region = options.region ?? config.cache.drivers?.dynamodb?.region ?? 'us-east-1'
15
-
16
- const client = new BentoCache({
17
- default: 'dynamo',
18
- stores: {
19
- dynamo: bentostore().useL2Layer(
20
- dynamoDbDriver({
21
- endpoint: dynamoEndpoint,
22
- region,
23
- table: {
24
- name: tableName,
25
- },
26
- credentials: {
27
- accessKeyId: awsAccessKeyId,
28
- secretAccessKey: awsSecretAccessKey,
29
- },
30
- }),
31
- ),
32
- },
33
- })
34
-
35
- super(client)
36
- }
37
- }
38
- export declare const dynamodb: DynamoDBCacheDriver;
@@ -1,22 +0,0 @@
1
- export declare interface FileSystemOptions {
2
- directory?: string
3
- pruneInterval?: string
4
- }
5
- export declare class FileSystemCacheDriver extends BaseCacheDriver {
6
- constructor(options: FileSystemOptions = {}) {
7
- const client = new BentoCache({
8
- default: 'file',
9
- stores: {
10
- file: bentostore().useL2Layer(
11
- fileDriver({
12
- directory: options.directory ?? './cache',
13
- pruneInterval: options.pruneInterval ?? '1h',
14
- }),
15
- ),
16
- },
17
- })
18
-
19
- super(client)
20
- }
21
- }
22
- export declare const fileSystem: unknown;
package/dist/index.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from './drivers'
2
- export * as dynamoDbTool from 'dynamodb-tooling'
package/dist/memory.d.ts DELETED
@@ -1,18 +0,0 @@
1
- export declare class MemoryCacheDriver extends BaseCacheDriver {
2
- constructor(options: { maxSize?: number, maxItems?: number } = {}) {
3
- const client = new BentoCache({
4
- default: 'memory',
5
- stores: {
6
- memory: bentostore().useL1Layer(
7
- memoryDriver({
8
- maxSize: options.maxSize ?? 10 * 1024 * 1024,
9
- maxItems: options.maxItems ?? 1000,
10
- }),
11
- ),
12
- },
13
- })
14
-
15
- super(client)
16
- }
17
- }
18
- export declare const memory: MemoryCacheDriver;
package/dist/redis.d.ts DELETED
@@ -1,32 +0,0 @@
1
- export declare interface RedisOptions {
2
- host?: string
3
- port?: number
4
- username?: string
5
- password?: string
6
- db?: number
7
- tls?: boolean
8
- }
9
- export declare class RedisCacheDriver extends BaseCacheDriver {
10
- constructor(options: RedisOptions = {}) {
11
- const client = new BentoCache({
12
- default: 'redis',
13
- stores: {
14
- redis: bentostore().useL2Layer(
15
- redisDriver({
16
- connection: {
17
- host: options.host ?? '127.0.0.1',
18
- port: options.port ?? 6379,
19
- ...(options.username && { username: options.username }),
20
- ...(options.password && { password: options.password }),
21
- ...(options.db !== undefined && { db: options.db }),
22
- ...(options.tls && { tls: {} }),
23
- },
24
- }),
25
- ),
26
- },
27
- })
28
-
29
- super(client)
30
- }
31
- }
32
- export declare const redis: RedisCacheDriver;