@stacksjs/cache 0.64.6 → 0.65.0

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/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@stacksjs/cache",
3
3
  "type": "module",
4
- "version": "0.64.6",
4
+ "version": "0.65.0",
5
5
  "description": "Caching the Stacks way.",
6
6
  "author": "Chris Breuer",
7
+ "contributors": ["Chris Breuer <chris@stacksjs.org>"],
7
8
  "license": "MIT",
8
9
  "funding": "https://github.com/sponsors/chrisbbreuer",
9
10
  "homepage": "https://github.com/stacksjs/stacks/tree/main/storage/framework/core/cache#readme",
@@ -35,25 +36,20 @@
35
36
  },
36
37
  "module": "dist/index.js",
37
38
  "types": "dist/index.d.ts",
38
- "contributors": [
39
- "Chris Breuer <chris@stacksjs.org>"
40
- ],
41
- "files": [
42
- "README.md",
43
- "dist",
44
- "src"
45
- ],
39
+ "files": ["README.md", "dist", "src"],
46
40
  "scripts": {
47
- "build": "bun --bun build.ts",
48
- "typecheck": "bun --bun tsc --noEmit",
41
+ "build": "bun build.ts",
42
+ "typecheck": "bun tsc --noEmit",
49
43
  "prepublishOnly": "bun run build"
50
44
  },
51
45
  "dependencies": {
52
- "@aws-sdk/client-dynamodb": "^3.637.0",
53
- "@stacksjs/config": "latest",
54
- "bentocache": "^1.0.0-beta.9"
46
+ "@aws-sdk/client-dynamodb": "^3.668.0",
47
+ "@stacksjs/config": "0.64.6",
48
+ "bentocache": "^1.0.0-beta.9",
49
+ "ioredis": "^5.4.1"
55
50
  },
56
51
  "devDependencies": {
57
- "@stacksjs/development": "latest"
52
+ "@stacksjs/development": "0.64.6",
53
+ "dynamodb-tooling": "^0.3.2"
58
54
  }
59
55
  }
@@ -1,104 +1,80 @@
1
- import type { PutItemCommandInput } from '@aws-sdk/client-dynamodb'
2
- import { DynamoDB, ListTablesCommand } from '@aws-sdk/client-dynamodb'
3
- import { cache } from '@stacksjs/config'
4
1
  import type { CacheDriver } from './type'
5
-
6
- const valueAttribute = 'value'
7
- const keyAttribute = 'key'
8
- const tableName = cache.drivers?.dynamodb?.table
9
-
10
- const client = new DynamoDB({ region: cache.drivers?.dynamodb?.region })
11
-
12
- function getValueType(value: string | number) {
13
- if (typeof value === 'string') return 'S'
14
- if (typeof value === 'number') return 'N'
15
- return 'S'
16
- }
17
-
18
- function serialize(value: string | number) {
19
- return String(value)
20
- }
21
-
22
- export const dynamodb: CacheDriver = {
23
- async createTable() {
24
- const tables = await client.send(new ListTablesCommand({}))
25
-
26
- const tableExists = tables.TableNames?.includes('cache')
27
-
28
- if (tableExists) return
29
-
30
- const params = {
31
- AttributeDefinitions: [
32
- {
33
- AttributeName: 'key',
34
- AttributeType: 'S',
2
+ import process from 'node:process'
3
+ import { BentoCache, bentostore } from 'bentocache'
4
+ import { dynamoDbDriver } from 'bentocache/drivers/dynamodb'
5
+
6
+ const awsAccessKeyId = process.env.AWS_ACCESS_KEY_ID || 'dummy'
7
+ const awsSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY || 'dummy'
8
+ const dynamoEndpoint = process.env.AWS_DYNAMODB_ENDPOINT || 'http://localhost:8000'
9
+ const tableName = process.env.AWS_DYNAMODB_TABLE || 'stacks'
10
+ const region = process.env.AWS_REGION || 'us-east-1'
11
+
12
+ const client = new BentoCache({
13
+ default: 'dynamo',
14
+ stores: {
15
+ dynamo: bentostore().useL2Layer(
16
+ dynamoDbDriver({
17
+ endpoint: dynamoEndpoint,
18
+ region,
19
+ table: {
20
+ name: tableName,
35
21
  },
36
- ],
37
- KeySchema: [
38
- {
39
- AttributeName: 'key',
40
- KeyType: 'HASH',
22
+ credentials: {
23
+ accessKeyId: awsAccessKeyId,
24
+ secretAccessKey: awsSecretAccessKey,
41
25
  },
42
- ],
43
- ProvisionedThroughput: {
44
- ReadCapacityUnits: 5,
45
- WriteCapacityUnits: 5,
46
- },
47
- TableName: tableName,
48
- }
49
-
50
- client.createTable(params)
26
+ }),
27
+ ),
51
28
  },
29
+ })
52
30
 
53
- async set(key: string, value: string | number): Promise<void> {
54
- const params: PutItemCommandInput = {
55
- TableName: tableName,
56
- Item: {
57
- [keyAttribute]: {
58
- S: key,
59
- },
60
- [valueAttribute]: {
61
- [getValueType(value)]: serialize(value),
62
- },
63
- },
64
- }
65
-
66
- await client.putItem(params)
31
+ export const dynamodb: CacheDriver = {
32
+ async set(key: string, value: string, ttl?: number): Promise<void> {
33
+ await client.set({
34
+ key,
35
+ value,
36
+ gracePeriod: { enabled: true, duration: '5m' },
37
+ })
38
+ },
39
+ async setForever(key: string, value: string, ttl?: number): Promise<void> {
40
+ await client.setForever({
41
+ key,
42
+ value,
43
+ })
67
44
  },
68
-
69
45
  async get(key: string): Promise<string | undefined | null> {
70
- const params = {
71
- TableName: tableName,
72
- Key: {
73
- [keyAttribute]: {
74
- S: key,
75
- },
76
- },
77
- }
78
-
79
- const response = await client.getItem(params)
46
+ const items = await client.get<string>(key)
80
47
 
81
- if (!response.Item) return null
82
-
83
- return response.Item[valueAttribute].S ?? response.Item[valueAttribute].N
48
+ return items
84
49
  },
50
+ async getOrSet(key: string, value: string): Promise<string | undefined | null> {
51
+ const items = await client.getOrSet(key, () => value)
85
52
 
53
+ return items
54
+ },
55
+ async del(key: string): Promise<void> {
56
+ await client.delete({ key })
57
+ },
58
+ async deleteMany(keys: string[]): Promise<void> {
59
+ await client.deleteMany({ keys })
60
+ },
86
61
  async remove(key: string): Promise<void> {
87
- const params = {
88
- TableName: tableName,
89
- Key: {
90
- [keyAttribute]: {
91
- S: key,
92
- },
93
- },
94
- }
95
-
96
- await client.deleteItem(params)
62
+ await client.delete({ key })
97
63
  },
98
-
99
- del(key: string): Promise<void> {
100
- return this.remove(key)
64
+ async has(key: string): Promise<boolean> {
65
+ return await client.has({ key })
66
+ },
67
+ async missing(key: string): Promise<boolean> {
68
+ return await client.missing({ key })
69
+ },
70
+ async deleteAll(): Promise<void> {
71
+ await client.clear()
72
+ },
73
+ async clear(): Promise<void> {
74
+ await client.clear()
75
+ },
76
+ async disconnect(): Promise<void> {
77
+ await client.disconnect()
101
78
  },
102
-
103
79
  client,
104
80
  }
@@ -0,0 +1,66 @@
1
+ import type { CacheDriver } from './type'
2
+ import { BentoCache, bentostore } from 'bentocache'
3
+ import { fileDriver } from 'bentocache/drivers/file'
4
+
5
+ const client = new BentoCache({
6
+ default: 'redis',
7
+ stores: {
8
+ redis: bentostore().useL2Layer(
9
+ fileDriver({
10
+ directory: './cache',
11
+ pruneInterval: '1h',
12
+ }),
13
+ ),
14
+ },
15
+ })
16
+
17
+ export const fileSystem: CacheDriver = {
18
+ async set(key: string, value: string, ttl?: number): Promise<void> {
19
+ await client.set({
20
+ key,
21
+ value,
22
+ gracePeriod: { enabled: true, duration: '5m' },
23
+ })
24
+ },
25
+ async setForever(key: string, value: string, ttl?: number): Promise<void> {
26
+ await client.setForever({
27
+ key,
28
+ value,
29
+ })
30
+ },
31
+ async get(key: string): Promise<string | undefined | null> {
32
+ const items = await client.get<string>(key)
33
+
34
+ return items
35
+ },
36
+ async getOrSet(key: string, value: string): Promise<string | undefined | null> {
37
+ const items = await client.getOrSet(key, () => value)
38
+
39
+ return items
40
+ },
41
+ async del(key: string): Promise<void> {
42
+ await client.delete({ key })
43
+ },
44
+ async deleteMany(keys: string[]): Promise<void> {
45
+ await client.deleteMany({ keys })
46
+ },
47
+ async remove(key: string): Promise<void> {
48
+ await client.delete({ key })
49
+ },
50
+ async has(key: string): Promise<boolean> {
51
+ return await client.has({ key })
52
+ },
53
+ async missing(key: string): Promise<boolean> {
54
+ return await client.missing({ key })
55
+ },
56
+ async deleteAll(): Promise<void> {
57
+ await client.clear()
58
+ },
59
+ async clear(): Promise<void> {
60
+ await client.clear()
61
+ },
62
+ async disconnect(): Promise<void> {
63
+ await client.disconnect()
64
+ },
65
+ client,
66
+ }
@@ -1 +1,29 @@
1
- export { dynamodb } from './dynamodb'
1
+ import type { CacheDriver } from './type'
2
+ import { config } from '@stacksjs/config'
3
+ import { dynamodb } from './dynamodb'
4
+ import { fileSystem } from './filesystem'
5
+ import { memory } from './memory'
6
+
7
+ import { redis } from './redis'
8
+
9
+ const driver = config.cache.driver || 'memory'
10
+
11
+ let driverInstance = fileSystem
12
+
13
+ if (driver === 'redis') {
14
+ driverInstance = redis
15
+ }
16
+
17
+ if (driver === 'fileSystem') {
18
+ driverInstance = fileSystem
19
+ }
20
+
21
+ if (driver === 'memory') {
22
+ driverInstance = memory
23
+ }
24
+
25
+ if (driver === 'dynamodb') {
26
+ driverInstance = dynamodb
27
+ }
28
+
29
+ export const cache: CacheDriver = driverInstance
@@ -0,0 +1,66 @@
1
+ import type { CacheDriver } from './type'
2
+ import { BentoCache, bentostore } from 'bentocache'
3
+ import { memoryDriver } from 'bentocache/drivers/memory'
4
+
5
+ const client = new BentoCache({
6
+ default: 'memory',
7
+ stores: {
8
+ memory: bentostore().useL1Layer(
9
+ memoryDriver({
10
+ maxSize: 10 * 1024 * 1024,
11
+ maxItems: 1000,
12
+ }),
13
+ ),
14
+ },
15
+ })
16
+
17
+ export const memory: CacheDriver = {
18
+ async set(key: string, value: string, ttl?: number): Promise<void> {
19
+ await client.set({
20
+ key,
21
+ value,
22
+ gracePeriod: { enabled: true, duration: '5m' },
23
+ })
24
+ },
25
+ async setForever(key: string, value: string, ttl?: number): Promise<void> {
26
+ await client.setForever({
27
+ key,
28
+ value,
29
+ })
30
+ },
31
+ async get(key: string): Promise<string | undefined | null> {
32
+ const items = await client.get<string>(key)
33
+
34
+ return items
35
+ },
36
+ async getOrSet(key: string, value: string): Promise<string | undefined | null> {
37
+ const items = await client.getOrSet(key, () => value)
38
+
39
+ return items
40
+ },
41
+ async del(key: string): Promise<void> {
42
+ await client.delete({ key })
43
+ },
44
+ async deleteMany(keys: string[]): Promise<void> {
45
+ await client.deleteMany({ keys })
46
+ },
47
+ async remove(key: string): Promise<void> {
48
+ await client.delete({ key })
49
+ },
50
+ async has(key: string): Promise<boolean> {
51
+ return await client.has({ key })
52
+ },
53
+ async missing(key: string): Promise<boolean> {
54
+ return await client.missing({ key })
55
+ },
56
+ async deleteAll(): Promise<void> {
57
+ await client.clear()
58
+ },
59
+ async clear(): Promise<void> {
60
+ await client.clear()
61
+ },
62
+ async disconnect(): Promise<void> {
63
+ await client.disconnect()
64
+ },
65
+ client,
66
+ }
@@ -0,0 +1,65 @@
1
+ import type { CacheDriver } from './type'
2
+ import { BentoCache, bentostore } from 'bentocache'
3
+ import { redisDriver } from 'bentocache/drivers/redis'
4
+
5
+ const client = new BentoCache({
6
+ default: 'redis',
7
+ stores: {
8
+ redis: bentostore().useL2Layer(
9
+ redisDriver({
10
+ connection: { host: '127.0.0.1', port: 6379 },
11
+ }),
12
+ ),
13
+ },
14
+ })
15
+
16
+ export const redis: CacheDriver = {
17
+ async set(key: string, value: string, ttl?: number): Promise<void> {
18
+ await client.set({
19
+ key,
20
+ value,
21
+ gracePeriod: { enabled: true, duration: '5m' },
22
+ })
23
+ },
24
+ async setForever(key: string, value: string, ttl?: number): Promise<void> {
25
+ await client.setForever({
26
+ key,
27
+ value,
28
+ })
29
+ },
30
+ async get(key: string): Promise<string | undefined | null> {
31
+ const items = await client.get<string>(key)
32
+
33
+ return items
34
+ },
35
+ async getOrSet(key: string, value: string): Promise<string | undefined | null> {
36
+ const items = await client.getOrSet(key, () => value)
37
+
38
+ return items
39
+ },
40
+ async del(key: string): Promise<void> {
41
+ await client.delete({ key })
42
+ },
43
+ async deleteMany(keys: string[]): Promise<void> {
44
+ await client.deleteMany({ keys })
45
+ },
46
+ async remove(key: string): Promise<void> {
47
+ await client.delete({ key })
48
+ },
49
+ async has(key: string): Promise<boolean> {
50
+ return await client.has({ key })
51
+ },
52
+ async missing(key: string): Promise<boolean> {
53
+ return await client.missing({ key })
54
+ },
55
+ async deleteAll(): Promise<void> {
56
+ await client.clear()
57
+ },
58
+ async clear(): Promise<void> {
59
+ await client.clear()
60
+ },
61
+ async disconnect(): Promise<void> {
62
+ await client.disconnect()
63
+ },
64
+ client,
65
+ }
@@ -1,10 +1,17 @@
1
- import type { DynamoDB } from '@aws-sdk/client-dynamodb'
1
+ import type { BentoCache } from 'bentocache'
2
2
 
3
- export type CacheDriver = {
4
- createTable: () => Promise<void>
5
- set: (key: string, value: string | number) => Promise<void>
3
+ export interface CacheDriver {
4
+ set: (key: string, value: string, ttl?: number) => Promise<void>
5
+ setForever: (key: string, value: string, ttl?: number) => Promise<void>
6
6
  get: (key: string) => Promise<string | undefined | null>
7
+ getOrSet: (key: string, value: string) => Promise<string | undefined | null>
7
8
  remove: (key: string) => Promise<void>
9
+ has: (key: string) => Promise<boolean>
10
+ missing: (key: string) => Promise<boolean>
8
11
  del: (key: string) => Promise<void>
9
- client: DynamoDB
12
+ deleteMany: (keys: string[]) => Promise<void>
13
+ clear: () => Promise<void>
14
+ deleteAll: () => Promise<void>
15
+ disconnect: () => Promise<void>
16
+ client: BentoCache<Record<string, any>>
10
17
  }
package/src/index.ts CHANGED
@@ -1 +1,2 @@
1
1
  export * from './drivers'
2
+ export * as dynamoDbTool from 'dynamodb-tooling'