@bejibun/cache 0.1.11 → 0.1.13
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/CHANGELOG.md +42 -0
- package/README.md +7 -1
- package/builders/CacheBuilder.d.ts +5 -0
- package/builders/CacheBuilder.js +108 -2
- package/config/cache.js +5 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,48 @@ All notable changes to this project will be documented in this file.
|
|
|
3
3
|
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
## [v0.1.13](https://github.com/crenata/bejibun-cache/compare/v0.1.12...v0.1.13) - 2025-12-12
|
|
7
|
+
|
|
8
|
+
### 🩹 Fixes
|
|
9
|
+
|
|
10
|
+
### 📖 Changes
|
|
11
|
+
What's New :
|
|
12
|
+
- Adding `ttl` supports for file scheme.
|
|
13
|
+
|
|
14
|
+
#### How does it work?
|
|
15
|
+
When you use a cache and include a `ttl`, the system generates a `unix timestamp` and adds it with specified `ttl`.
|
|
16
|
+
Then system will write it to a file in the format `ttl|file`, separated by the `|` symbol.
|
|
17
|
+
|
|
18
|
+
When you call data from the cache, the system creates metadata consisting of the `ttl` and `data` by splitting them with `|`.
|
|
19
|
+
The system then checks if the `ttl` is empty and returns the data.
|
|
20
|
+
|
|
21
|
+
Or if the `ttl` is present, the system checks whether the `current timestamp` <= `ttl`?
|
|
22
|
+
If so, the data is returned. Otherwise, the cache file will be deleted and returned null.
|
|
23
|
+
|
|
24
|
+
### ❤️Contributors
|
|
25
|
+
- Havea Crenata ([@crenata](https://github.com/crenata))
|
|
26
|
+
|
|
27
|
+
**Full Changelog**: https://github.com/crenata/bejibun-cache/blob/master/CHANGELOG.md
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## [v0.1.12](https://github.com/crenata/bejibun-cache/compare/v0.1.11...v0.1.12) - 2025-12-04
|
|
32
|
+
|
|
33
|
+
### 🩹 Fixes
|
|
34
|
+
|
|
35
|
+
### 📖 Changes
|
|
36
|
+
What's New :
|
|
37
|
+
- Adding `local` connection for file schema
|
|
38
|
+
|
|
39
|
+
Now, [@bejibun/cache](https://github.com/crenata/bejibun-cache) has local and redis for cache system.
|
|
40
|
+
|
|
41
|
+
### ❤️Contributors
|
|
42
|
+
- Havea Crenata ([@crenata](https://github.com/crenata))
|
|
43
|
+
|
|
44
|
+
**Full Changelog**: https://github.com/crenata/bejibun-cache/blob/master/CHANGELOG.md
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
6
48
|
## [v0.1.11](https://github.com/crenata/bejibun-cache/compare/v0.1.0...v0.1.11) - 2025-11-23
|
|
7
49
|
|
|
8
50
|
### 🩹 Fixes
|
package/README.md
CHANGED
|
@@ -38,10 +38,16 @@ config/cache.ts
|
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
```ts
|
|
41
|
+
import App from "@bejibun/app";
|
|
42
|
+
|
|
41
43
|
const config: Record<string, any> = {
|
|
42
|
-
connection: "
|
|
44
|
+
connection: "local",
|
|
43
45
|
|
|
44
46
|
connections: {
|
|
47
|
+
local: {
|
|
48
|
+
path: App.Path.storagePath("cache") // absolute path
|
|
49
|
+
},
|
|
50
|
+
|
|
45
51
|
redis: {
|
|
46
52
|
host: "127.0.0.100",
|
|
47
53
|
port: 6379,
|
|
@@ -4,6 +4,11 @@ export default class CacheBuilder {
|
|
|
4
4
|
constructor();
|
|
5
5
|
private get config();
|
|
6
6
|
private key;
|
|
7
|
+
private connection;
|
|
8
|
+
private filePath;
|
|
9
|
+
private file;
|
|
10
|
+
private setFile;
|
|
11
|
+
private getFile;
|
|
7
12
|
remember(key: string, callback: Function, ttl?: number): Promise<any>;
|
|
8
13
|
has(key: string): Promise<boolean>;
|
|
9
14
|
get(key: string): Promise<any>;
|
package/builders/CacheBuilder.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import App from "@bejibun/app";
|
|
2
2
|
import Logger from "@bejibun/logger";
|
|
3
3
|
import Redis from "@bejibun/redis";
|
|
4
|
-
import
|
|
4
|
+
import Luxon from "@bejibun/utils/facades/Luxon";
|
|
5
|
+
import { defineValue, isEmpty, isNotEmpty } from "@bejibun/utils";
|
|
5
6
|
import fs from "fs";
|
|
7
|
+
import path from "path";
|
|
6
8
|
import CacheConfig from "../config/cache";
|
|
7
9
|
import CacheException from "../exceptions/CacheException";
|
|
8
10
|
export default class CacheBuilder {
|
|
@@ -24,11 +26,65 @@ export default class CacheBuilder {
|
|
|
24
26
|
return this.conf;
|
|
25
27
|
}
|
|
26
28
|
key(key) {
|
|
27
|
-
|
|
29
|
+
const defaultKey = `${this.prefix}-${key.replaceAll("/", "-").replaceAll(" ", "-")}`;
|
|
30
|
+
return defaultKey;
|
|
31
|
+
/*if (forceDefault) return defaultKey;
|
|
32
|
+
|
|
33
|
+
switch (this.config.connection) {
|
|
34
|
+
case "local":
|
|
35
|
+
return `${Luxon.DateTime.now().toUnixInteger()}-${defaultKey}`;
|
|
36
|
+
default:
|
|
37
|
+
return defaultKey;
|
|
38
|
+
}*/
|
|
39
|
+
}
|
|
40
|
+
connection() {
|
|
41
|
+
return this.config.connections[this.config.connection];
|
|
42
|
+
}
|
|
43
|
+
filePath(key) {
|
|
44
|
+
return path.resolve(this.connection().path, `${this.key(key)}.cache`);
|
|
45
|
+
}
|
|
46
|
+
file(key) {
|
|
47
|
+
return Bun.file(this.filePath(key));
|
|
48
|
+
}
|
|
49
|
+
async setFile(key, data, ttl) {
|
|
50
|
+
ttl = defineValue(ttl, "");
|
|
51
|
+
if (isNotEmpty(ttl))
|
|
52
|
+
ttl = Luxon.DateTime.now().toUnixInteger() + ttl;
|
|
53
|
+
await fs.promises.mkdir(this.connection().path, { recursive: true });
|
|
54
|
+
return await Bun.write(this.filePath(key), `${ttl}|${data}`);
|
|
55
|
+
}
|
|
56
|
+
async getFile(key) {
|
|
57
|
+
let metadata = {
|
|
58
|
+
ttl: null,
|
|
59
|
+
data: null
|
|
60
|
+
};
|
|
61
|
+
const file = this.file(key);
|
|
62
|
+
if (await file.exists()) {
|
|
63
|
+
const raw = await file.text();
|
|
64
|
+
const [unix, ...rest] = raw.split("|");
|
|
65
|
+
const ttl = Number(unix);
|
|
66
|
+
const data = rest.join("|");
|
|
67
|
+
if (isEmpty(ttl) || Luxon.DateTime.now().toUnixInteger() <= ttl)
|
|
68
|
+
metadata = {
|
|
69
|
+
ttl: defineValue(Number(ttl)),
|
|
70
|
+
data
|
|
71
|
+
};
|
|
72
|
+
else
|
|
73
|
+
await this.file(key).delete();
|
|
74
|
+
}
|
|
75
|
+
return metadata;
|
|
28
76
|
}
|
|
29
77
|
async remember(key, callback, ttl) {
|
|
30
78
|
let data;
|
|
31
79
|
switch (this.config.connection) {
|
|
80
|
+
case "local":
|
|
81
|
+
const raw = await this.getFile(key);
|
|
82
|
+
data = raw.data;
|
|
83
|
+
if (isEmpty(data)) {
|
|
84
|
+
data = callback();
|
|
85
|
+
await this.setFile(key, data, ttl);
|
|
86
|
+
}
|
|
87
|
+
break;
|
|
32
88
|
case "redis":
|
|
33
89
|
data = await Redis.get(this.key(key));
|
|
34
90
|
if (isEmpty(data)) {
|
|
@@ -45,6 +101,10 @@ export default class CacheBuilder {
|
|
|
45
101
|
async has(key) {
|
|
46
102
|
let data;
|
|
47
103
|
switch (this.config.connection) {
|
|
104
|
+
case "local":
|
|
105
|
+
const raw = await this.getFile(key);
|
|
106
|
+
data = raw.data;
|
|
107
|
+
break;
|
|
48
108
|
case "redis":
|
|
49
109
|
data = await Redis.get(this.key(key));
|
|
50
110
|
break;
|
|
@@ -57,6 +117,10 @@ export default class CacheBuilder {
|
|
|
57
117
|
async get(key) {
|
|
58
118
|
let data;
|
|
59
119
|
switch (this.config.connection) {
|
|
120
|
+
case "local":
|
|
121
|
+
const raw = await this.getFile(key);
|
|
122
|
+
data = raw.data;
|
|
123
|
+
break;
|
|
60
124
|
case "redis":
|
|
61
125
|
data = await Redis.get(this.key(key));
|
|
62
126
|
break;
|
|
@@ -71,6 +135,10 @@ export default class CacheBuilder {
|
|
|
71
135
|
let data;
|
|
72
136
|
try {
|
|
73
137
|
switch (this.config.connection) {
|
|
138
|
+
case "local":
|
|
139
|
+
const raw = await this.getFile(key);
|
|
140
|
+
data = raw.data;
|
|
141
|
+
break;
|
|
74
142
|
case "redis":
|
|
75
143
|
data = await Redis.get(this.key(key));
|
|
76
144
|
break;
|
|
@@ -80,6 +148,9 @@ export default class CacheBuilder {
|
|
|
80
148
|
}
|
|
81
149
|
if (isEmpty(data)) {
|
|
82
150
|
switch (this.config.connection) {
|
|
151
|
+
case "local":
|
|
152
|
+
await this.setFile(key, value, ttl);
|
|
153
|
+
break;
|
|
83
154
|
case "redis":
|
|
84
155
|
await Redis.set(this.key(key), value, ttl);
|
|
85
156
|
break;
|
|
@@ -102,6 +173,9 @@ export default class CacheBuilder {
|
|
|
102
173
|
let status = true;
|
|
103
174
|
try {
|
|
104
175
|
switch (this.config.connection) {
|
|
176
|
+
case "local":
|
|
177
|
+
await this.setFile(key, value, ttl);
|
|
178
|
+
break;
|
|
105
179
|
case "redis":
|
|
106
180
|
await Redis.set(this.key(key), value, ttl);
|
|
107
181
|
break;
|
|
@@ -117,6 +191,14 @@ export default class CacheBuilder {
|
|
|
117
191
|
}
|
|
118
192
|
async forget(key) {
|
|
119
193
|
switch (this.config.connection) {
|
|
194
|
+
case "local":
|
|
195
|
+
try {
|
|
196
|
+
await this.file(key).delete();
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
break;
|
|
120
202
|
case "redis":
|
|
121
203
|
await Redis.del(this.key(key));
|
|
122
204
|
break;
|
|
@@ -127,6 +209,18 @@ export default class CacheBuilder {
|
|
|
127
209
|
async increment(key, ttl) {
|
|
128
210
|
let data;
|
|
129
211
|
switch (this.config.connection) {
|
|
212
|
+
case "local":
|
|
213
|
+
const raw = await this.getFile(key);
|
|
214
|
+
data = Number(raw.data);
|
|
215
|
+
if (isEmpty(data)) {
|
|
216
|
+
data = 1;
|
|
217
|
+
await this.setFile(key, String(data), ttl);
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
data++;
|
|
221
|
+
await this.setFile(key, String(data), ttl);
|
|
222
|
+
}
|
|
223
|
+
break;
|
|
130
224
|
case "redis":
|
|
131
225
|
data = Number(await Redis.get(this.key(key)));
|
|
132
226
|
if (isEmpty(data)) {
|
|
@@ -147,6 +241,18 @@ export default class CacheBuilder {
|
|
|
147
241
|
async decrement(key, ttl) {
|
|
148
242
|
let data;
|
|
149
243
|
switch (this.config.connection) {
|
|
244
|
+
case "local":
|
|
245
|
+
const raw = await this.getFile(key);
|
|
246
|
+
data = Number(raw.data);
|
|
247
|
+
if (isEmpty(data)) {
|
|
248
|
+
data = -1;
|
|
249
|
+
await this.setFile(key, String(data), ttl);
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
data--;
|
|
253
|
+
await this.setFile(key, String(data), ttl);
|
|
254
|
+
}
|
|
255
|
+
break;
|
|
150
256
|
case "redis":
|
|
151
257
|
data = Number(await Redis.get(this.key(key)));
|
|
152
258
|
if (isEmpty(data)) {
|
package/config/cache.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bejibun/cache",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"author": "Havea Crenata <havea.crenata@gmail.com>",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@bejibun/app": "^0.1.22",
|
|
39
39
|
"@bejibun/logger": "^0.1.22",
|
|
40
|
-
"@bejibun/redis": "^0.1.
|
|
41
|
-
"@bejibun/utils": "^0.1.
|
|
40
|
+
"@bejibun/redis": "^0.1.36",
|
|
41
|
+
"@bejibun/utils": "^0.1.27"
|
|
42
42
|
}
|
|
43
43
|
}
|