@bejibun/redis 0.1.25 → 0.1.27

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 CHANGED
@@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file.
3
3
 
4
4
  ---
5
5
 
6
+ ## [v0.1.26](https://github.com/crenata/bejibun-redis/compare/v0.1.24...v0.1.26) - 2025-10-18
7
+
8
+ ### 🩹 Fixes
9
+
10
+ ### 📖 Changes
11
+ What's New :
12
+ - A minor adjustment on error logs
13
+
14
+ ### ❤️Contributors
15
+ - Havea Crenata ([@crenata](https://github.com/crenata))
16
+ - Ghulje ([@ghulje](https://github.com/ghulje))
17
+
18
+ **Full Changelog**: https://github.com/crenata/bejibun-redis/blob/master/CHANGELOG.md
19
+
20
+ ---
21
+
6
22
  ## [v0.1.24](https://github.com/crenata/bejibun-redis/compare/v0.1.23...v0.1.24) - 2025-10-16
7
23
 
8
24
  ### 🩹 Fixes
package/README.md CHANGED
@@ -55,15 +55,20 @@ You can pass the value with environment variables.
55
55
  How to use tha package.
56
56
 
57
57
  ```ts
58
- import Redis from "@bejibun/Redis";
58
+ import type {RedisPipeline} from "@bejibun/redis/types";
59
+ import BaseController from "@bejibun/core/bases/BaseController";
60
+ import Logger from "@bejibun/logger";
61
+ import Redis from "@bejibun/redis";
59
62
  import {BunRequest} from "bun";
60
- import BaseController from "@/app/controllers/BaseController";
61
63
 
62
64
  export default class TestController extends BaseController {
63
65
  public async redis(request: BunRequest): Promise<Response> {
64
66
  await Redis.set("redis", {hello: "world"});
65
67
  const redis = await Redis.get("redis");
66
68
 
69
+ await Redis.connection("local").set("connection", "This is using custom connection.");
70
+ const connection = await Redis.connection("local").get("connection");
71
+
67
72
  const pipeline = await Redis.pipeline((pipe: RedisPipeline) => {
68
73
  pipe.set("redis-pipeline-1", "This is redis pipeline 1");
69
74
  pipe.set("redis-pipeline-2", "This is redis pipeline 2");
@@ -73,14 +78,14 @@ export default class TestController extends BaseController {
73
78
  });
74
79
 
75
80
  const subscriber = await Redis.subscribe("redis-subscribe", (message: string, channel: string) => {
76
- console.log(`[${channel}]: ${message}`);
81
+ Logger.setContext(channel).debug(message);
77
82
  });
78
83
  await Redis.publish("redis-subscribe", "Hai redis subscriber!");
79
84
  setTimeout(async () => {
80
85
  await subscriber.unsubscribe();
81
86
  }, 500);
82
87
 
83
- return super.response.setData({redis, pipeline}).send();
88
+ return super.response.setData({redis, connection, pipeline}).send();
84
89
  }
85
90
  }
86
91
  ```
@@ -1,16 +1,15 @@
1
1
  import type { RedisPipeline, RedisSubscribe } from "../types/redis";
2
- import { RedisClient } from "bun";
3
2
  export default class RedisBuilder {
4
3
  private static clients;
5
4
  private static emitter;
6
5
  static connection(name: string): Record<string, Function>;
7
- static connect(name?: string): Promise<RedisClient>;
6
+ static connect(name?: string): Promise<Bun.RedisClient>;
8
7
  static disconnect(name?: string): Promise<void>;
9
- static get(key: RedisClient.KeyLike, connection?: string): Promise<any>;
10
- static set(key: RedisClient.KeyLike, value: any, ttl?: number, connection?: string): Promise<number | "OK">;
11
- static del(key: RedisClient.KeyLike, connection?: string): Promise<number>;
8
+ static get(key: Bun.RedisClient.KeyLike, connection?: string): Promise<any>;
9
+ static set(key: Bun.RedisClient.KeyLike, value: any, ttl?: number, connection?: string): Promise<number | "OK">;
10
+ static del(key: Bun.RedisClient.KeyLike, connection?: string): Promise<number>;
12
11
  static publish(channel: string, message: any, connection?: string): Promise<number>;
13
- static subscribe(channel: string, listener: RedisClient.StringPubSubListener, connection?: string): Promise<RedisSubscribe>;
12
+ static subscribe(channel: string, listener: Bun.RedisClient.StringPubSubListener, connection?: string): Promise<RedisSubscribe>;
14
13
  static pipeline(fn: (pipe: RedisPipeline) => void, connection?: string): Promise<any[]>;
15
14
  static on(event: "connect" | "disconnect" | "error", listener: (...args: Array<any>) => void): void;
16
15
  static off(event: "connect" | "disconnect" | "error", listener: (...args: Array<any>) => void): void;
@@ -1,6 +1,5 @@
1
1
  import Logger from "@bejibun/logger";
2
2
  import { defineValue, isEmpty, isNotEmpty } from "@bejibun/utils";
3
- import { RedisClient } from "bun";
4
3
  import { EventEmitter } from "events";
5
4
  import config from "../config/redis";
6
5
  import RedisException from "../exceptions/RedisException";
@@ -48,7 +47,7 @@ export default class RedisBuilder {
48
47
  static async set(key, value, ttl, connection) {
49
48
  const client = this.getClient(connection);
50
49
  const serialized = this.serialize(value);
51
- if (ttl)
50
+ if (isNotEmpty(ttl))
52
51
  return await client.expire(key, ttl);
53
52
  return await client.set(key, serialized);
54
53
  }
@@ -67,8 +66,8 @@ export default class RedisBuilder {
67
66
  Logger.setContext("Redis").info(`Subscribed to "${channel}" channel.`);
68
67
  const unsubscribe = async () => {
69
68
  await client.unsubscribe(channel);
70
- Logger.setContext("Redis").warn(`Unsubscribed from "${channel}" channel.`);
71
69
  await client.close();
70
+ Logger.setContext("Redis").warn(`Unsubscribed from "${channel}" channel.`);
72
71
  return true;
73
72
  };
74
73
  return {
@@ -113,13 +112,13 @@ export default class RedisBuilder {
113
112
  }
114
113
  static createClient(name, cfg) {
115
114
  const url = this.buildUrl(cfg);
116
- const client = new RedisClient(url, this.getOptions(cfg));
115
+ const client = new Bun.RedisClient(url, this.getOptions(cfg));
117
116
  client.onconnect = () => {
118
117
  Logger.setContext("Redis").info(`Connected to "${name}" connection.`);
119
118
  this.emitter.emit("connect", name);
120
119
  };
121
120
  client.onclose = (error) => {
122
- console.warn(`[Redis]: Disconnected from "${name}" connection.`, error.message);
121
+ Logger.setContext("Redis").warn(`Disconnected from "${name}" connection.`).trace(error);
123
122
  this.emitter.emit("disconnect", name, error);
124
123
  };
125
124
  return client;
@@ -180,7 +179,7 @@ export default class RedisBuilder {
180
179
  Logger.setContext("Redis").warn(`Disconnected on "${defineValue(signal, "exit")}".`);
181
180
  }
182
181
  catch (error) {
183
- console.error("[Redis]: Error during disconnect.", error.message);
182
+ Logger.setContext("Redis").error("Error during disconnect.").trace(error);
184
183
  }
185
184
  finally {
186
185
  process.exit(0);
@@ -1,3 +1,4 @@
1
+ import Logger from "@bejibun/logger";
1
2
  import { defineValue } from "@bejibun/utils";
2
3
  export default class RedisException extends Error {
3
4
  code;
@@ -5,6 +6,7 @@ export default class RedisException extends Error {
5
6
  super(message);
6
7
  this.name = "RedisException";
7
8
  this.code = defineValue(code, 503);
9
+ Logger.setContext(this.name).error(this.message).trace(this.stack);
8
10
  if (Error.captureStackTrace) {
9
11
  Error.captureStackTrace(this, RedisException);
10
12
  }
@@ -1,14 +1,13 @@
1
1
  import type { RedisPipeline, RedisSubscribe } from "../types/redis";
2
- import { RedisClient } from "bun";
3
2
  export default class Redis {
4
3
  static connection(name: string): Record<string, Function>;
5
- static connect(name?: string): Promise<RedisClient>;
4
+ static connect(name?: string): Promise<Bun.RedisClient>;
6
5
  static disconnect(name?: string): Promise<void>;
7
- static get(key: RedisClient.KeyLike, connection?: string): Promise<any>;
8
- static set(key: RedisClient.KeyLike, value: any, ttl?: number, connection?: string): Promise<number | "OK">;
9
- static del(key: RedisClient.KeyLike, connection?: string): Promise<number>;
6
+ static get(key: Bun.RedisClient.KeyLike, connection?: string): Promise<any>;
7
+ static set(key: Bun.RedisClient.KeyLike, value: any, ttl?: number, connection?: string): Promise<number | "OK">;
8
+ static del(key: Bun.RedisClient.KeyLike, connection?: string): Promise<number>;
10
9
  static publish(channel: string, message: any, connection?: string): Promise<number>;
11
- static subscribe(channel: string, listener: RedisClient.StringPubSubListener, connection?: string): Promise<RedisSubscribe>;
10
+ static subscribe(channel: string, listener: Bun.RedisClient.StringPubSubListener, connection?: string): Promise<RedisSubscribe>;
12
11
  static pipeline(fn: (pipe: RedisPipeline) => void, connection?: string): Promise<any[]>;
13
12
  static on(event: "connect" | "disconnect" | "error", listener: (...args: Array<any>) => void): void;
14
13
  static off(event: "connect" | "disconnect" | "error", listener: (...args: Array<any>) => void): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bejibun/redis",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
4
4
  "author": "Havea Crenata <havea.crenata@gmail.com>",
5
5
  "repository": {
6
6
  "type": "git",
@@ -31,12 +31,12 @@
31
31
  "rsync": "rsync -a dist/ ./",
32
32
  "clean": "rm -rf dist",
33
33
  "build": "bunx tsc -p tsconfig.json && bun run copy && bun run alias && bun run rsync && bun run clean",
34
- "deploy": "bun run build && npm publish --access public"
34
+ "deploy": "bun run build && bun publish --access public"
35
35
  },
36
36
  "type": "module",
37
37
  "types": "index.d.ts",
38
38
  "dependencies": {
39
- "@bejibun/logger": "^0.1.13",
40
- "@bejibun/utils": "^0.1.0"
39
+ "@bejibun/logger": "^0.1.18",
40
+ "@bejibun/utils": "^0.1.14"
41
41
  }
42
42
  }
package/bun.lock DELETED
@@ -1,113 +0,0 @@
1
- {
2
- "lockfileVersion": 1,
3
- "workspaces": {
4
- "": {
5
- "name": "@bejibun/redis",
6
- "dependencies": {
7
- "@bejibun/logger": "^0.1.13",
8
- "@bejibun/utils": "^0.1.0",
9
- },
10
- "devDependencies": {
11
- "@types/bun": "latest",
12
- "tsc-alias": "^1.8.16",
13
- },
14
- },
15
- },
16
- "packages": {
17
- "@bejibun/logger": ["@bejibun/logger@0.1.13", "", { "dependencies": { "@bejibun/utils": "^0.1.0", "chalk": "^5.6.2", "luxon": "^3.7.2" } }, "sha512-Vq17rFd10P/jtUdUHVNOP+cdHnMjobgw5t4rQ4iF/vPtS/qtyvBJN6rkmpL+4mtAquVYOdJCycZtk7cSdXhpGw=="],
18
-
19
- "@bejibun/utils": ["@bejibun/utils@0.1.0", "", {}, "sha512-zH9Sxo1C+y8rzLTf5/t78HfDYp8C34d+gsEzbo98OKKwI9so37ljdz2LDlXxDinp3lDBi9r/l/EmkNLECfP10g=="],
20
-
21
- "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
22
-
23
- "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
24
-
25
- "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
26
-
27
- "@types/bun": ["@types/bun@1.3.0", "", { "dependencies": { "bun-types": "1.3.0" } }, "sha512-+lAGCYjXjip2qY375xX/scJeVRmZ5cY0wyHYyCYxNcdEXrQ4AOe3gACgd4iQ8ksOslJtW4VNxBJ8llUwc3a6AA=="],
28
-
29
- "@types/node": ["@types/node@24.7.2", "", { "dependencies": { "undici-types": "~7.14.0" } }, "sha512-/NbVmcGTP+lj5oa4yiYxxeBjRivKQ5Ns1eSZeB99ExsEQ6rX5XYU1Zy/gGxY/ilqtD4Etx9mKyrPxZRetiahhA=="],
30
-
31
- "@types/react": ["@types/react@19.2.2", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA=="],
32
-
33
- "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="],
34
-
35
- "array-union": ["array-union@2.1.0", "", {}, "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="],
36
-
37
- "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="],
38
-
39
- "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
40
-
41
- "bun-types": ["bun-types@1.3.0", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-u8X0thhx+yJ0KmkxuEo9HAtdfgCBaM/aI9K90VQcQioAmkVp3SG3FkwWGibUFz3WdXAdcsqOcbU40lK7tbHdkQ=="],
42
-
43
- "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
44
-
45
- "chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],
46
-
47
- "commander": ["commander@9.5.0", "", {}, "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ=="],
48
-
49
- "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
50
-
51
- "dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="],
52
-
53
- "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
54
-
55
- "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="],
56
-
57
- "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
58
-
59
- "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
60
-
61
- "get-tsconfig": ["get-tsconfig@4.12.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-LScr2aNr2FbjAjZh2C6X6BxRx1/x+aTDExct/xyq2XKbYOiG5c0aK7pMsSuyc0brz3ibr/lbQiHD9jzt4lccJw=="],
62
-
63
- "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
64
-
65
- "globby": ["globby@11.1.0", "", { "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" } }, "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g=="],
66
-
67
- "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
68
-
69
- "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="],
70
-
71
- "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
72
-
73
- "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
74
-
75
- "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
76
-
77
- "luxon": ["luxon@3.7.2", "", {}, "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew=="],
78
-
79
- "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
80
-
81
- "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
82
-
83
- "mylas": ["mylas@2.1.13", "", {}, "sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg=="],
84
-
85
- "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
86
-
87
- "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="],
88
-
89
- "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
90
-
91
- "plimit-lit": ["plimit-lit@1.6.1", "", { "dependencies": { "queue-lit": "^1.5.1" } }, "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA=="],
92
-
93
- "queue-lit": ["queue-lit@1.5.2", "", {}, "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw=="],
94
-
95
- "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
96
-
97
- "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
98
-
99
- "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="],
100
-
101
- "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
102
-
103
- "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
104
-
105
- "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
106
-
107
- "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
108
-
109
- "tsc-alias": ["tsc-alias@1.8.16", "", { "dependencies": { "chokidar": "^3.5.3", "commander": "^9.0.0", "get-tsconfig": "^4.10.0", "globby": "^11.0.4", "mylas": "^2.1.9", "normalize-path": "^3.0.0", "plimit-lit": "^1.2.6" }, "bin": { "tsc-alias": "dist/bin/index.js" } }, "sha512-QjCyu55NFyRSBAl6+MTFwplpFcnm2Pq01rR/uxfqJoLMm6X3O14KEGtaSDZpJYaE1bJBGDjD0eSuiIWPe2T58g=="],
110
-
111
- "undici-types": ["undici-types@7.14.0", "", {}, "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA=="],
112
- }
113
- }
@@ -1,241 +0,0 @@
1
- import type {RedisConfig, RedisPipeline, RedisSubscribe} from "@/types/redis";
2
- import Logger from "@bejibun/logger";
3
- import {defineValue, isEmpty, isNotEmpty} from "@bejibun/utils";
4
- import {RedisClient, RedisOptions} from "bun";
5
- import {EventEmitter} from "events";
6
- import config from "@/config/redis";
7
- import RedisException from "@/exceptions/RedisException";
8
-
9
- export default class RedisBuilder {
10
- private static clients: Record<string, RedisClient> = {};
11
- private static emitter = new EventEmitter();
12
-
13
- public static connection(name: string): Record<string, Function> {
14
- return {
15
- del: (key: RedisClient.KeyLike) => this.del(key, name),
16
- get: (key: RedisClient.KeyLike) => this.get(key, name),
17
- pipeline: (fn: (pipe: RedisPipeline) => void) => this.pipeline(fn, name),
18
- publish: (channel: string, message: any) => this.publish(channel, message, name),
19
- set: (key: RedisClient.KeyLike, value: any, ttl?: number) => this.set(key, value, ttl, name),
20
- subscribe: (channel: string, listener: RedisClient.StringPubSubListener) => this.subscribe(channel, listener, name),
21
- };
22
- }
23
-
24
- public static async connect(name?: string): Promise<RedisClient> {
25
- const client = this.getClient(name);
26
- await client.connect();
27
- Logger.setContext("Redis").info(`Connected manually to "${defineValue(name, "default")}" connection.`);
28
- this.emitter.emit("connect", defineValue(name, "default"));
29
-
30
- return client;
31
- }
32
-
33
- public static async disconnect(name?: string): Promise<void> {
34
- if (isNotEmpty(name)) {
35
- const client = this.clients[name as string];
36
-
37
- if (isNotEmpty(client)) {
38
- await client.close();
39
- delete this.clients[name as string];
40
- Logger.setContext("Redis").warn(`Disconnected manually from "${name}" connection.`);
41
- }
42
- } else {
43
- for (const [connectionName, client] of Object.entries(this.clients)) {
44
- await client.close();
45
- Logger.setContext("Redis").warn(`Disconnected manually from "${connectionName}" connection.`);
46
- }
47
-
48
- this.clients = {};
49
- }
50
- }
51
-
52
- public static async get(key: RedisClient.KeyLike, connection?: string): Promise<any> {
53
- const response = await this.getClient(connection).get(key);
54
-
55
- return this.deserialize(response);
56
- }
57
-
58
- public static async set(key: RedisClient.KeyLike, value: any, ttl?: number, connection?: string): Promise<number | "OK"> {
59
- const client = this.getClient(connection);
60
- const serialized = this.serialize(value);
61
-
62
- if (ttl) return await client.expire(key, ttl);
63
-
64
- return await client.set(key, serialized);
65
- }
66
-
67
- public static async del(key: RedisClient.KeyLike, connection?: string): Promise<number> {
68
- return await this.getClient(connection).del(key);
69
- }
70
-
71
- public static async publish(channel: string, message: any, connection?: string): Promise<number> {
72
- const serialized = this.serialize(message);
73
-
74
- return await this.getClient(connection).publish(channel, serialized);
75
- }
76
-
77
- public static async subscribe(channel: string, listener: RedisClient.StringPubSubListener, connection?: string): Promise<RedisSubscribe> {
78
- const cfg = this.getConfig(connection);
79
- const client = this.createClient(config.default, cfg);
80
- this.clients[channel] = client;
81
-
82
- await client.subscribe(channel, (message: string, channel: string) => listener(this.deserialize(message), channel));
83
- Logger.setContext("Redis").info(`Subscribed to "${channel}" channel.`);
84
-
85
- const unsubscribe = async () => {
86
- await client.unsubscribe(channel);
87
- Logger.setContext("Redis").warn(`Unsubscribed from "${channel}" channel.`);
88
- await client.close();
89
-
90
- return true;
91
- };
92
-
93
- return {
94
- client,
95
- unsubscribe: unsubscribe
96
- };
97
- }
98
-
99
- public static async pipeline(fn: (pipe: RedisPipeline) => void, connection?: string) {
100
- const client = this.getClient(connection);
101
- const ops: Array<Promise<any>> = [];
102
-
103
- const pipe: RedisPipeline = {
104
- del: (key: RedisClient.KeyLike): void => {
105
- ops.push(client.del(key));
106
- },
107
- get: (key: RedisClient.KeyLike): void => {
108
- ops.push(client.get(key));
109
- },
110
- set: (key: RedisClient.KeyLike, value: any, ttl?: number): void => {
111
- const serialized = this.serialize(value);
112
-
113
- if (isNotEmpty(ttl)) ops.push(client.expire(key, ttl as number));
114
-
115
- ops.push(client.set(key, serialized));
116
- }
117
- };
118
-
119
- fn(pipe);
120
-
121
- const results = await Promise.all(ops);
122
-
123
- return results.map((result: any) => this.deserialize(result));
124
- }
125
-
126
- public static on(event: "connect" | "disconnect" | "error", listener: (...args: Array<any>) => void): void {
127
- this.emitter.on(event, listener);
128
- }
129
-
130
- public static off(event: "connect" | "disconnect" | "error", listener: (...args: Array<any>) => void): void {
131
- this.emitter.off(event, listener);
132
- }
133
-
134
- private static buildUrl(cfg: RedisConfig): string {
135
- const url = new URL(`redis://${cfg.host}:${cfg.port}`);
136
-
137
- if (isNotEmpty(cfg.password)) url.password = cfg.password as string;
138
- if (isNotEmpty(cfg.database)) url.pathname = `/${cfg.database}`;
139
-
140
- return url.toString();
141
- }
142
-
143
- private static createClient(name: string, cfg: RedisConfig): RedisClient {
144
- const url = this.buildUrl(cfg);
145
- const client = new RedisClient(url, this.getOptions(cfg));
146
-
147
- client.onconnect = () => {
148
- Logger.setContext("Redis").info(`Connected to "${name}" connection.`);
149
- this.emitter.emit("connect", name);
150
- };
151
-
152
- client.onclose = (error: Error) => {
153
- console.warn(`[Redis]: Disconnected from "${name}" connection.`, error.message);
154
- this.emitter.emit("disconnect", name, error);
155
- };
156
-
157
- return client;
158
- }
159
-
160
- private static getOptions(cfg: RedisConfig): RedisOptions {
161
- return {
162
- autoReconnect: true,
163
- maxRetries: cfg.maxRetries
164
- };
165
- }
166
-
167
- private static getConfig(name?: string): RedisConfig {
168
- const connectionName = defineValue(name, config.default);
169
- const connection = config.connections[connectionName];
170
-
171
- if (isEmpty(connection)) throw new RedisException(`[Redis]: Connection "${connectionName}" not found.`);
172
-
173
- return connection;
174
- }
175
-
176
- private static getClient(name?: string): RedisClient {
177
- const connectionName = defineValue(name, config.default);
178
-
179
- this.ensureExitHooks();
180
-
181
- if (isEmpty(this.clients[connectionName])) {
182
- const cfg = this.getConfig(connectionName);
183
- this.clients[connectionName] = this.createClient(connectionName, cfg);
184
- }
185
-
186
- return this.clients[connectionName];
187
- }
188
-
189
- private static serialize(value: any): string {
190
- if (isEmpty(value)) return "";
191
- if (typeof value === "object") return JSON.stringify(value);
192
- if (typeof value === "number" || typeof value === "boolean") return String(value);
193
-
194
- return value;
195
- }
196
-
197
- private static deserialize(value?: string | null): any {
198
- if (isEmpty(value)) return null;
199
-
200
- try {
201
- return JSON.parse(value as string);
202
- } catch (error) {
203
- return value;
204
- }
205
- }
206
-
207
- private static ensureExitHooks(): void {
208
- this.setupExitHooks();
209
- }
210
-
211
- private static setupExitHooks = ((): Function => {
212
- let initialized = false;
213
-
214
- return (): void => {
215
- if (initialized) return;
216
-
217
- initialized = true;
218
-
219
- const handleExit = async (signal?: string): Promise<void> => {
220
- try {
221
- await RedisBuilder.disconnect();
222
- Logger.setContext("Redis").warn(`Disconnected on "${defineValue(signal, "exit")}".`);
223
- } catch (error: any) {
224
- console.error("[Redis]: Error during disconnect.", error.message);
225
- } finally {
226
- process.exit(0);
227
- }
228
- };
229
-
230
- process.on("exit", async (): Promise<void> => {
231
- await handleExit();
232
- });
233
- process.on("SIGINT", async (): Promise<void> => {
234
- await handleExit("SIGINT");
235
- });
236
- process.on("SIGTERM", async (): Promise<void> => {
237
- await handleExit("SIGTERM");
238
- });
239
- };
240
- })();
241
- }
@@ -1,15 +0,0 @@
1
- const config: Record<string, any> = {
2
- default: "local",
3
-
4
- connections: {
5
- local: {
6
- host: "127.0.0.1",
7
- port: 6379,
8
- password: "",
9
- database: 0,
10
- maxRetries: 10
11
- }
12
- }
13
- };
14
-
15
- export default config;
@@ -1,15 +0,0 @@
1
- import {defineValue} from "@bejibun/utils";
2
-
3
- export default class RedisException extends Error {
4
- public code: number;
5
-
6
- public constructor(message?: string, code?: number) {
7
- super(message);
8
- this.name = "RedisException";
9
- this.code = defineValue(code, 503);
10
-
11
- if (Error.captureStackTrace) {
12
- Error.captureStackTrace(this, RedisException);
13
- }
14
- }
15
- }
@@ -1 +0,0 @@
1
- export * from "@/exceptions/RedisException";
@@ -1,49 +0,0 @@
1
- import type {RedisPipeline, RedisSubscribe} from "@/types/redis";
2
- import {RedisClient} from "bun";
3
- import RedisBuilder from "@/builders/RedisBuilder";
4
-
5
- export default class Redis {
6
- public static connection(name: string): Record<string, Function> {
7
- return RedisBuilder.connection(name);
8
- }
9
-
10
- public static async connect(name?: string): Promise<RedisClient> {
11
- return RedisBuilder.connect(name);
12
- }
13
-
14
- public static async disconnect(name?: string): Promise<void> {
15
- return RedisBuilder.disconnect(name);
16
- }
17
-
18
- public static async get(key: RedisClient.KeyLike, connection?: string): Promise<any> {
19
- return RedisBuilder.get(key, connection);
20
- }
21
-
22
- public static async set(key: RedisClient.KeyLike, value: any, ttl?: number, connection?: string): Promise<number | "OK"> {
23
- return RedisBuilder.set(key, value, ttl, connection);
24
- }
25
-
26
- public static async del(key: RedisClient.KeyLike, connection?: string): Promise<number> {
27
- return RedisBuilder.del(key, connection);
28
- }
29
-
30
- public static async publish(channel: string, message: any, connection?: string): Promise<number> {
31
- return RedisBuilder.publish(channel, message, connection);
32
- }
33
-
34
- public static async subscribe(channel: string, listener: RedisClient.StringPubSubListener, connection?: string): Promise<RedisSubscribe> {
35
- return RedisBuilder.subscribe(channel, listener, connection);
36
- }
37
-
38
- public static async pipeline(fn: (pipe: RedisPipeline) => void, connection?: string) {
39
- return RedisBuilder.pipeline(fn, connection);
40
- }
41
-
42
- public static on(event: "connect" | "disconnect" | "error", listener: (...args: Array<any>) => void): void {
43
- return RedisBuilder.on(event, listener);
44
- }
45
-
46
- public static off(event: "connect" | "disconnect" | "error", listener: (...args: Array<any>) => void): void {
47
- return RedisBuilder.off(event, listener);
48
- }
49
- }
@@ -1 +0,0 @@
1
- export * from "@/facades/Redis";
package/src/index.ts DELETED
@@ -1,5 +0,0 @@
1
- export {default} from "@/facades/Redis";
2
-
3
- export * from "@/exceptions/index";
4
-
5
- export * from "@/facades/index";
@@ -1 +0,0 @@
1
- export * from "@/types/redis";
@@ -1,16 +0,0 @@
1
- export type RedisConfig = {
2
- host: string;
3
- port: number;
4
- password?: string | null;
5
- database?: number;
6
- maxRetries?: number;
7
- };
8
- export type RedisPipeline = {
9
- del: (key: string) => void;
10
- get: (key: string) => void;
11
- set: (key: string, value: any, ttl?: number) => void;
12
- };
13
- export type RedisSubscribe = {
14
- client: RedisClient;
15
- unsubscribe: () => Promise<boolean>;
16
- };