@pluv/persistence-redis 3.2.1 → 4.0.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/.turbo/turbo-build.log +16 -16
- package/CHANGELOG.md +29 -0
- package/dist/index.d.mts +24 -22
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +98 -160
- package/dist/index.mjs.map +1 -0
- package/package.json +19 -15
- package/tsdown.config.ts +14 -0
- package/dist/index.d.ts +0 -29
- package/dist/index.js +0 -189
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
|
|
2
|
-
> @pluv/persistence-redis@
|
|
3
|
-
>
|
|
2
|
+
> @pluv/persistence-redis@4.0.0 build /home/runner/work/pluv/pluv/packages/persistence-redis
|
|
3
|
+
> tsdown
|
|
4
4
|
|
|
5
|
-
[
|
|
6
|
-
[
|
|
7
|
-
[
|
|
8
|
-
[
|
|
9
|
-
[
|
|
10
|
-
[
|
|
11
|
-
[
|
|
12
|
-
[
|
|
13
|
-
[
|
|
14
|
-
[
|
|
15
|
-
[
|
|
16
|
-
[
|
|
17
|
-
|
|
18
|
-
[
|
|
5
|
+
[34mℹ[39m tsdown [2mv0.20.0-beta.4[22m powered by rolldown [2mv1.0.0-beta.60[22m
|
|
6
|
+
[34mℹ[39m config file: [4m/home/runner/work/pluv/pluv/packages/persistence-redis/tsdown.config.ts[24m
|
|
7
|
+
[34mℹ[39m entry: [34msrc/index.ts[39m
|
|
8
|
+
[34mℹ[39m target: [34mesnext[39m
|
|
9
|
+
[34mℹ[39m tsconfig: [34mtsconfig.json[39m
|
|
10
|
+
[34mℹ[39m Build start
|
|
11
|
+
[34mℹ[39m [2mdist/[22m[1mindex.mjs[22m [2m3.65 kB[22m [2m│ gzip: 1.00 kB[22m
|
|
12
|
+
[34mℹ[39m [2mdist/[22mindex.mjs.map [2m8.19 kB[22m [2m│ gzip: 2.15 kB[22m
|
|
13
|
+
[34mℹ[39m [2mdist/[22mindex.d.mts.map [2m0.73 kB[22m [2m│ gzip: 0.34 kB[22m
|
|
14
|
+
[34mℹ[39m [2mdist/[22m[32m[1mindex.d.mts[22m[39m [2m1.25 kB[22m [2m│ gzip: 0.46 kB[22m
|
|
15
|
+
[34mℹ[39m 4 files, total: 13.82 kB
|
|
16
|
+
[33m[PLUGIN_TIMINGS] Warning:[0m Your build spent significant time in plugin `rolldown-plugin-dts:generate`. See https://rolldown.rs/options/checks#plugintimings for more details.
|
|
17
|
+
|
|
18
|
+
[32m✔[39m Build complete in [32m4009ms[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# @pluv/persistence-redis
|
|
2
2
|
|
|
3
|
+
## 4.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- df5c39c: Update all packages to be ESM only.
|
|
8
|
+
|
|
9
|
+
### Minor Changes
|
|
10
|
+
|
|
11
|
+
- 037074e: Migrated build process from tsup to tsdown.
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- 2eb5def: Bumped dependencies.
|
|
16
|
+
- Updated dependencies [2eb5def]
|
|
17
|
+
- Updated dependencies [df5c39c]
|
|
18
|
+
- Updated dependencies [c142910]
|
|
19
|
+
- Updated dependencies [037074e]
|
|
20
|
+
- Updated dependencies [07e2a1e]
|
|
21
|
+
- @pluv/types@4.0.0
|
|
22
|
+
- @pluv/io@4.0.0
|
|
23
|
+
|
|
24
|
+
## 3.2.2
|
|
25
|
+
|
|
26
|
+
### Patch Changes
|
|
27
|
+
|
|
28
|
+
- Updated dependencies [8665dbe]
|
|
29
|
+
- @pluv/types@3.2.2
|
|
30
|
+
- @pluv/io@3.2.2
|
|
31
|
+
|
|
3
32
|
## 3.2.1
|
|
4
33
|
|
|
5
34
|
### Patch Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -1,29 +1,31 @@
|
|
|
1
|
-
import { AbstractPersistence } from
|
|
2
|
-
import { JsonObject } from
|
|
3
|
-
import { Cluster, Redis } from
|
|
1
|
+
import { AbstractPersistence } from "@pluv/io";
|
|
2
|
+
import { JsonObject } from "@pluv/types";
|
|
3
|
+
import { Cluster, Redis } from "ioredis";
|
|
4
4
|
|
|
5
|
+
//#region src/PersistenceRedis.d.ts
|
|
5
6
|
type RedisClient = Cluster | Redis;
|
|
6
7
|
interface PersistenceRedisOptions {
|
|
7
|
-
|
|
8
|
+
client: RedisClient;
|
|
8
9
|
}
|
|
9
10
|
declare class PersistenceRedis extends AbstractPersistence {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
11
|
+
private _client;
|
|
12
|
+
private _initialized;
|
|
13
|
+
constructor(options: PersistenceRedisOptions);
|
|
14
|
+
addUser(room: string, connectionId: string, user: JsonObject | null): Promise<void>;
|
|
15
|
+
deleteStorageState(room: string): Promise<void>;
|
|
16
|
+
deleteUser(room: string, connectionId: string): Promise<void>;
|
|
17
|
+
deleteUsers(room: string): Promise<void>;
|
|
18
|
+
getStorageState(room: string): Promise<string | null>;
|
|
19
|
+
setStorageState(room: string, state: string): Promise<void>;
|
|
20
|
+
getUser(room: string, connectionId: string): Promise<JsonObject | null>;
|
|
21
|
+
getUsers(room: string): Promise<Map<[connectionId: string][0], JsonObject | null>>;
|
|
22
|
+
getUsersSize(room: string): Promise<number>;
|
|
23
|
+
initialize(roomContext: {}): typeof this;
|
|
24
|
+
private _getClusterKey;
|
|
25
|
+
private _getRoomStorageKey;
|
|
26
|
+
private _getRoomUsersKey;
|
|
27
|
+
private _getRoomUsersUserKey;
|
|
27
28
|
}
|
|
28
|
-
|
|
29
|
+
//#endregion
|
|
29
30
|
export { PersistenceRedis, type RedisClient };
|
|
31
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/PersistenceRedis.ts"],"mappings":";;;;;KAUY,WAAA,GAAc,OAAA,GAAU,KAAA;AAAA,UAEnB,uBAAA;EACb,MAAA,EAAQ,WAAA;AAAA;AAAA,cAGC,gBAAA,SAAyB,mBAAA;EAAA,QAC1B,OAAA;EAAA,QACA,YAAA;cAEI,OAAA,EAAS,uBAAA;EASR,OAAA,CACT,IAAA,UACA,YAAA,UACA,IAAA,EAAM,UAAA,UACP,OAAA;EAYU,kBAAA,CAAmB,IAAA,WAAe,OAAA;EAQlC,UAAA,CAAW,IAAA,UAAc,YAAA,WAAuB,OAAA;EAmBhD,WAAA,CAAY,IAAA,WAAe,OAAA;EAiB3B,eAAA,CAAgB,IAAA,WAAe,OAAA;EAQ/B,eAAA,CAAgB,IAAA,UAAc,KAAA,WAAgB,OAAA;EAQ9C,OAAA,CAAQ,IAAA,UAAc,YAAA,WAAuB,OAAA,CAAQ,UAAA;EAUrD,QAAA,CACT,IAAA,WACD,OAAA,CAAQ,GAAA,EAAK,YAAA,cAA0B,UAAA;EAqB7B,YAAA,CAAa,IAAA,WAAe,OAAA;EAQlC,UAAA,CAAW,WAAA;EAAA,QAOV,cAAA;EAAA,QAIA,kBAAA;EAAA,QAIA,gBAAA;EAAA,QAIA,oBAAA;AAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,165 +1,103 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
5
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
-
var __spreadValues = (a, b) => {
|
|
7
|
-
for (var prop in b || (b = {}))
|
|
8
|
-
if (__hasOwnProp.call(b, prop))
|
|
9
|
-
__defNormalProp(a, prop, b[prop]);
|
|
10
|
-
if (__getOwnPropSymbols)
|
|
11
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
12
|
-
if (__propIsEnum.call(b, prop))
|
|
13
|
-
__defNormalProp(a, prop, b[prop]);
|
|
14
|
-
}
|
|
15
|
-
return a;
|
|
16
|
-
};
|
|
17
|
-
var __async = (__this, __arguments, generator) => {
|
|
18
|
-
return new Promise((resolve, reject) => {
|
|
19
|
-
var fulfilled = (value) => {
|
|
20
|
-
try {
|
|
21
|
-
step(generator.next(value));
|
|
22
|
-
} catch (e) {
|
|
23
|
-
reject(e);
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
var rejected = (value) => {
|
|
27
|
-
try {
|
|
28
|
-
step(generator.throw(value));
|
|
29
|
-
} catch (e) {
|
|
30
|
-
reject(e);
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
34
|
-
step((generator = generator.apply(__this, __arguments)).next());
|
|
35
|
-
});
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
// src/PersistenceRedis.ts
|
|
39
1
|
import { AbstractPersistence } from "@pluv/io";
|
|
40
2
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const tail = arr.slice(length);
|
|
46
|
-
return [head, ...partitionByLength(tail, length)];
|
|
3
|
+
//#region src/utils/partitionByLength.ts
|
|
4
|
+
const partitionByLength = (arr, length) => {
|
|
5
|
+
if (!arr.length) return [];
|
|
6
|
+
return [arr.slice(0, length), ...partitionByLength(arr.slice(length), length)];
|
|
47
7
|
};
|
|
48
8
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
return __async(this, null, function* () {
|
|
140
|
-
if (!this._initialized) return 0;
|
|
141
|
-
yield this._initialized;
|
|
142
|
-
return yield this._client.scard(this._getRoomUsersKey(room));
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
initialize(roomContext) {
|
|
146
|
-
return new _PersistenceRedis(__spreadValues({
|
|
147
|
-
client: this._client
|
|
148
|
-
}, { _initialized: Promise.resolve(true) }));
|
|
149
|
-
}
|
|
150
|
-
_getClusterKey(key) {
|
|
151
|
-
return `${HASH_TAG}${key}`;
|
|
152
|
-
}
|
|
153
|
-
_getRoomStorageKey(room) {
|
|
154
|
-
return this._getClusterKey(`room_storage${DELIMITER}${room}`);
|
|
155
|
-
}
|
|
156
|
-
_getRoomUsersKey(room) {
|
|
157
|
-
return this._getClusterKey(`room_users${DELIMITER}${room}`);
|
|
158
|
-
}
|
|
159
|
-
_getRoomUsersUserKey(room, connectionId) {
|
|
160
|
-
return this._getClusterKey(`${this._getRoomUsersKey(room)}${DELIMITER}${connectionId}`);
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
export {
|
|
164
|
-
PersistenceRedis
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region src/PersistenceRedis.ts
|
|
11
|
+
const DELIMITER = ":::";
|
|
12
|
+
const HASH_TAG = "{PluvPersistenceRedis}";
|
|
13
|
+
const GET_USERS_CONCURRENCY = 4;
|
|
14
|
+
var PersistenceRedis = class PersistenceRedis extends AbstractPersistence {
|
|
15
|
+
_client;
|
|
16
|
+
_initialized = null;
|
|
17
|
+
constructor(options) {
|
|
18
|
+
super();
|
|
19
|
+
const { client } = options;
|
|
20
|
+
this._client = client;
|
|
21
|
+
this._initialized = options._initialized;
|
|
22
|
+
}
|
|
23
|
+
async addUser(room, connectionId, user) {
|
|
24
|
+
if (!this._initialized) return;
|
|
25
|
+
await this._initialized;
|
|
26
|
+
await this._client.multi().sadd(this._getRoomUsersKey(room), connectionId).set(this._getRoomUsersUserKey(room, connectionId), JSON.stringify(user)).exec();
|
|
27
|
+
}
|
|
28
|
+
async deleteStorageState(room) {
|
|
29
|
+
if (!this._initialized) return;
|
|
30
|
+
await this._initialized;
|
|
31
|
+
await this._client.del(this._getRoomStorageKey(room));
|
|
32
|
+
}
|
|
33
|
+
async deleteUser(room, connectionId) {
|
|
34
|
+
if (!this._initialized) return;
|
|
35
|
+
await this._initialized;
|
|
36
|
+
const size = await this.getUsersSize(room);
|
|
37
|
+
let multi = this._client.multi().srem(this._getRoomUsersKey(room), connectionId).del(this._getRoomUsersUserKey(room, connectionId));
|
|
38
|
+
if (size === 1) multi = multi.del(this._getRoomStorageKey(room)).del(this._getRoomUsersKey(room));
|
|
39
|
+
await multi.exec();
|
|
40
|
+
}
|
|
41
|
+
async deleteUsers(room) {
|
|
42
|
+
if (!this._initialized) return;
|
|
43
|
+
await this._initialized;
|
|
44
|
+
await (await this._client.smembers(this._getRoomUsersKey(room))).reduce((commands, connectionId) => {
|
|
45
|
+
return commands.del(this._getRoomUsersUserKey(room, connectionId));
|
|
46
|
+
}, this._client.multi().del(this._getRoomUsersKey(room))).exec();
|
|
47
|
+
}
|
|
48
|
+
async getStorageState(room) {
|
|
49
|
+
if (!this._initialized) return null;
|
|
50
|
+
await this._initialized;
|
|
51
|
+
return await this._client.get(this._getRoomStorageKey(room));
|
|
52
|
+
}
|
|
53
|
+
async setStorageState(room, state) {
|
|
54
|
+
if (!this._initialized) return;
|
|
55
|
+
await this._initialized;
|
|
56
|
+
await this._client.set(this._getRoomStorageKey(room), state);
|
|
57
|
+
}
|
|
58
|
+
async getUser(room, connectionId) {
|
|
59
|
+
if (!this._initialized) return null;
|
|
60
|
+
await this._initialized;
|
|
61
|
+
const data = await this._client.get(this._getRoomUsersUserKey(room, connectionId));
|
|
62
|
+
return !data ? null : JSON.parse(data);
|
|
63
|
+
}
|
|
64
|
+
async getUsers(room) {
|
|
65
|
+
if (!this._initialized) return /* @__PURE__ */ new Map();
|
|
66
|
+
await this._initialized;
|
|
67
|
+
return await partitionByLength(await this._client.smembers(this._getRoomUsersKey(room)), GET_USERS_CONCURRENCY).reduce(async (promise, partition) => {
|
|
68
|
+
const map = await promise;
|
|
69
|
+
const promises = partition.map(async (connectionId) => {
|
|
70
|
+
map.set(connectionId, await this.getUser(room, connectionId));
|
|
71
|
+
});
|
|
72
|
+
await Promise.all(promises);
|
|
73
|
+
return map;
|
|
74
|
+
}, Promise.resolve(/* @__PURE__ */ new Map()));
|
|
75
|
+
}
|
|
76
|
+
async getUsersSize(room) {
|
|
77
|
+
if (!this._initialized) return 0;
|
|
78
|
+
await this._initialized;
|
|
79
|
+
return await this._client.scard(this._getRoomUsersKey(room));
|
|
80
|
+
}
|
|
81
|
+
initialize(roomContext) {
|
|
82
|
+
return new PersistenceRedis({
|
|
83
|
+
client: this._client,
|
|
84
|
+
_initialized: Promise.resolve(true)
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
_getClusterKey(key) {
|
|
88
|
+
return `${HASH_TAG}${key}`;
|
|
89
|
+
}
|
|
90
|
+
_getRoomStorageKey(room) {
|
|
91
|
+
return this._getClusterKey(`room_storage${DELIMITER}${room}`);
|
|
92
|
+
}
|
|
93
|
+
_getRoomUsersKey(room) {
|
|
94
|
+
return this._getClusterKey(`room_users${DELIMITER}${room}`);
|
|
95
|
+
}
|
|
96
|
+
_getRoomUsersUserKey(room, connectionId) {
|
|
97
|
+
return this._getClusterKey(`${this._getRoomUsersKey(room)}${DELIMITER}${connectionId}`);
|
|
98
|
+
}
|
|
165
99
|
};
|
|
100
|
+
|
|
101
|
+
//#endregion
|
|
102
|
+
export { PersistenceRedis };
|
|
103
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/utils/partitionByLength.ts","../src/PersistenceRedis.ts"],"sourcesContent":["export const partitionByLength = <T>(\n arr: readonly T[] | T[],\n length: number,\n): readonly (readonly T[])[] => {\n if (!arr.length) return [];\n\n const head = arr.slice(0, length);\n const tail = arr.slice(length);\n\n return [head, ...partitionByLength(tail, length)];\n};\n","import { AbstractPersistence } from \"@pluv/io\";\nimport type { JsonObject } from \"@pluv/types\";\nimport type { Cluster, Redis } from \"ioredis\";\nimport { partitionByLength } from \"./utils\";\n\nconst DELIMITER = \":::\";\nconst HASH_TAG = \"{PluvPersistenceRedis}\";\n\nconst GET_USERS_CONCURRENCY = 4;\n\nexport type RedisClient = Cluster | Redis;\n\nexport interface PersistenceRedisOptions {\n client: RedisClient;\n}\n\nexport class PersistenceRedis extends AbstractPersistence {\n private _client: RedisClient;\n private _initialized: Promise<true> | null = null;\n\n constructor(options: PersistenceRedisOptions) {\n super();\n\n const { client } = options;\n\n this._client = client;\n this._initialized = (options as any)._initialized;\n }\n\n public async addUser(\n room: string,\n connectionId: string,\n user: JsonObject | null,\n ): Promise<void> {\n if (!this._initialized) return;\n\n await this._initialized;\n\n await this._client\n .multi()\n .sadd(this._getRoomUsersKey(room), connectionId)\n .set(this._getRoomUsersUserKey(room, connectionId), JSON.stringify(user))\n .exec();\n }\n\n public async deleteStorageState(room: string): Promise<void> {\n if (!this._initialized) return;\n\n await this._initialized;\n\n await this._client.del(this._getRoomStorageKey(room));\n }\n\n public async deleteUser(room: string, connectionId: string): Promise<void> {\n if (!this._initialized) return;\n\n await this._initialized;\n\n const size = await this.getUsersSize(room);\n\n let multi = this._client\n .multi()\n .srem(this._getRoomUsersKey(room), connectionId)\n .del(this._getRoomUsersUserKey(room, connectionId));\n\n if (size === 1) {\n multi = multi.del(this._getRoomStorageKey(room)).del(this._getRoomUsersKey(room));\n }\n\n await multi.exec();\n }\n\n public async deleteUsers(room: string): Promise<void> {\n if (!this._initialized) return;\n\n await this._initialized;\n\n const members = await this._client.smembers(this._getRoomUsersKey(room));\n\n await members\n .reduce(\n (commands, connectionId) => {\n return commands.del(this._getRoomUsersUserKey(room, connectionId));\n },\n this._client.multi().del(this._getRoomUsersKey(room)),\n )\n .exec();\n }\n\n public async getStorageState(room: string): Promise<string | null> {\n if (!this._initialized) return null;\n\n await this._initialized;\n\n return await this._client.get(this._getRoomStorageKey(room));\n }\n\n public async setStorageState(room: string, state: string): Promise<void> {\n if (!this._initialized) return;\n\n await this._initialized;\n\n await this._client.set(this._getRoomStorageKey(room), state);\n }\n\n public async getUser(room: string, connectionId: string): Promise<JsonObject | null> {\n if (!this._initialized) return null;\n\n await this._initialized;\n\n const data = await this._client.get(this._getRoomUsersUserKey(room, connectionId));\n\n return !data ? null : JSON.parse(data);\n }\n\n public async getUsers(\n room: string,\n ): Promise<Map<[connectionId: string][0], JsonObject | null>> {\n if (!this._initialized) return new Map();\n\n await this._initialized;\n\n const members = await this._client.smembers(this._getRoomUsersKey(room));\n const partitions = partitionByLength(members, GET_USERS_CONCURRENCY);\n\n return await partitions.reduce(async (promise, partition) => {\n const map = await promise;\n\n const promises = partition.map(async (connectionId) => {\n map.set(connectionId, await this.getUser(room, connectionId));\n });\n\n await Promise.all(promises);\n\n return map;\n }, Promise.resolve(new Map<string, JsonObject | null>()));\n }\n\n public async getUsersSize(room: string): Promise<number> {\n if (!this._initialized) return 0;\n\n await this._initialized;\n\n return await this._client.scard(this._getRoomUsersKey(room));\n }\n\n public initialize(roomContext: {}): typeof this {\n return new PersistenceRedis({\n client: this._client,\n ...{ _initialized: Promise.resolve(true as const) },\n }) as typeof this;\n }\n\n private _getClusterKey(key: string): string {\n return `${HASH_TAG}${key}`;\n }\n\n private _getRoomStorageKey(room: string): string {\n return this._getClusterKey(`room_storage${DELIMITER}${room}`);\n }\n\n private _getRoomUsersKey(room: string): string {\n return this._getClusterKey(`room_users${DELIMITER}${room}`);\n }\n\n private _getRoomUsersUserKey(room: string, connectionId: string): string {\n return this._getClusterKey(`${this._getRoomUsersKey(room)}${DELIMITER}${connectionId}`);\n }\n}\n"],"mappings":";;;AAAA,MAAa,qBACT,KACA,WAC4B;AAC5B,KAAI,CAAC,IAAI,OAAQ,QAAO,EAAE;AAK1B,QAAO,CAHM,IAAI,MAAM,GAAG,OAAO,EAGnB,GAAG,kBAFJ,IAAI,MAAM,OAAO,EAEW,OAAO,CAAC;;;;;ACJrD,MAAM,YAAY;AAClB,MAAM,WAAW;AAEjB,MAAM,wBAAwB;AAQ9B,IAAa,mBAAb,MAAa,yBAAyB,oBAAoB;CACtD,AAAQ;CACR,AAAQ,eAAqC;CAE7C,YAAY,SAAkC;AAC1C,SAAO;EAEP,MAAM,EAAE,WAAW;AAEnB,OAAK,UAAU;AACf,OAAK,eAAgB,QAAgB;;CAGzC,MAAa,QACT,MACA,cACA,MACa;AACb,MAAI,CAAC,KAAK,aAAc;AAExB,QAAM,KAAK;AAEX,QAAM,KAAK,QACN,OAAO,CACP,KAAK,KAAK,iBAAiB,KAAK,EAAE,aAAa,CAC/C,IAAI,KAAK,qBAAqB,MAAM,aAAa,EAAE,KAAK,UAAU,KAAK,CAAC,CACxE,MAAM;;CAGf,MAAa,mBAAmB,MAA6B;AACzD,MAAI,CAAC,KAAK,aAAc;AAExB,QAAM,KAAK;AAEX,QAAM,KAAK,QAAQ,IAAI,KAAK,mBAAmB,KAAK,CAAC;;CAGzD,MAAa,WAAW,MAAc,cAAqC;AACvE,MAAI,CAAC,KAAK,aAAc;AAExB,QAAM,KAAK;EAEX,MAAM,OAAO,MAAM,KAAK,aAAa,KAAK;EAE1C,IAAI,QAAQ,KAAK,QACZ,OAAO,CACP,KAAK,KAAK,iBAAiB,KAAK,EAAE,aAAa,CAC/C,IAAI,KAAK,qBAAqB,MAAM,aAAa,CAAC;AAEvD,MAAI,SAAS,EACT,SAAQ,MAAM,IAAI,KAAK,mBAAmB,KAAK,CAAC,CAAC,IAAI,KAAK,iBAAiB,KAAK,CAAC;AAGrF,QAAM,MAAM,MAAM;;CAGtB,MAAa,YAAY,MAA6B;AAClD,MAAI,CAAC,KAAK,aAAc;AAExB,QAAM,KAAK;AAIX,SAFgB,MAAM,KAAK,QAAQ,SAAS,KAAK,iBAAiB,KAAK,CAAC,EAGnE,QACI,UAAU,iBAAiB;AACxB,UAAO,SAAS,IAAI,KAAK,qBAAqB,MAAM,aAAa,CAAC;KAEtE,KAAK,QAAQ,OAAO,CAAC,IAAI,KAAK,iBAAiB,KAAK,CAAC,CACxD,CACA,MAAM;;CAGf,MAAa,gBAAgB,MAAsC;AAC/D,MAAI,CAAC,KAAK,aAAc,QAAO;AAE/B,QAAM,KAAK;AAEX,SAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,mBAAmB,KAAK,CAAC;;CAGhE,MAAa,gBAAgB,MAAc,OAA8B;AACrE,MAAI,CAAC,KAAK,aAAc;AAExB,QAAM,KAAK;AAEX,QAAM,KAAK,QAAQ,IAAI,KAAK,mBAAmB,KAAK,EAAE,MAAM;;CAGhE,MAAa,QAAQ,MAAc,cAAkD;AACjF,MAAI,CAAC,KAAK,aAAc,QAAO;AAE/B,QAAM,KAAK;EAEX,MAAM,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,qBAAqB,MAAM,aAAa,CAAC;AAElF,SAAO,CAAC,OAAO,OAAO,KAAK,MAAM,KAAK;;CAG1C,MAAa,SACT,MAC0D;AAC1D,MAAI,CAAC,KAAK,aAAc,wBAAO,IAAI,KAAK;AAExC,QAAM,KAAK;AAKX,SAAO,MAFY,kBADH,MAAM,KAAK,QAAQ,SAAS,KAAK,iBAAiB,KAAK,CAAC,EAC1B,sBAAsB,CAE5C,OAAO,OAAO,SAAS,cAAc;GACzD,MAAM,MAAM,MAAM;GAElB,MAAM,WAAW,UAAU,IAAI,OAAO,iBAAiB;AACnD,QAAI,IAAI,cAAc,MAAM,KAAK,QAAQ,MAAM,aAAa,CAAC;KAC/D;AAEF,SAAM,QAAQ,IAAI,SAAS;AAE3B,UAAO;KACR,QAAQ,wBAAQ,IAAI,KAAgC,CAAC,CAAC;;CAG7D,MAAa,aAAa,MAA+B;AACrD,MAAI,CAAC,KAAK,aAAc,QAAO;AAE/B,QAAM,KAAK;AAEX,SAAO,MAAM,KAAK,QAAQ,MAAM,KAAK,iBAAiB,KAAK,CAAC;;CAGhE,AAAO,WAAW,aAA8B;AAC5C,SAAO,IAAI,iBAAiB;GACxB,QAAQ,KAAK;GACR,cAAc,QAAQ,QAAQ,KAAc;GACpD,CAAC;;CAGN,AAAQ,eAAe,KAAqB;AACxC,SAAO,GAAG,WAAW;;CAGzB,AAAQ,mBAAmB,MAAsB;AAC7C,SAAO,KAAK,eAAe,eAAe,YAAY,OAAO;;CAGjE,AAAQ,iBAAiB,MAAsB;AAC3C,SAAO,KAAK,eAAe,aAAa,YAAY,OAAO;;CAG/D,AAAQ,qBAAqB,MAAc,cAA8B;AACrE,SAAO,KAAK,eAAe,GAAG,KAAK,iBAAiB,KAAK,GAAG,YAAY,eAAe"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pluv/persistence-redis",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "@pluv/io crdt storage persistence for node.js",
|
|
5
5
|
"author": {
|
|
6
6
|
"email": "david@pluv.io",
|
|
@@ -14,32 +14,36 @@
|
|
|
14
14
|
"url": "git+https://github.com/pluv-io/pluv.git",
|
|
15
15
|
"directory": "packages/persistence-redis"
|
|
16
16
|
},
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"types": "./dist/index.d.ts",
|
|
17
|
+
"type": "module",
|
|
18
|
+
"types": "./dist/index.d.mts",
|
|
20
19
|
"publishConfig": {
|
|
21
20
|
"access": "public"
|
|
22
21
|
},
|
|
23
22
|
"dependencies": {
|
|
24
|
-
"@types/node": "^
|
|
25
|
-
"@pluv/io": "^
|
|
26
|
-
"@pluv/types": "^
|
|
23
|
+
"@types/node": "^25.0.9",
|
|
24
|
+
"@pluv/io": "^4.0.0",
|
|
25
|
+
"@pluv/types": "^4.0.0"
|
|
27
26
|
},
|
|
28
27
|
"peerDependencies": {
|
|
29
28
|
"ioredis": "^5.0.0"
|
|
30
29
|
},
|
|
31
30
|
"devDependencies": {
|
|
32
|
-
"eslint": "^9.
|
|
33
|
-
"ioredis": "^5.
|
|
34
|
-
"
|
|
35
|
-
"typescript": "^5.
|
|
36
|
-
"@pluv/tsconfig": "^
|
|
37
|
-
"eslint-config-pluv": "^
|
|
31
|
+
"eslint": "^9.39.2",
|
|
32
|
+
"ioredis": "^5.9.2",
|
|
33
|
+
"tsdown": "0.20.0-beta.4",
|
|
34
|
+
"typescript": "^5.9.3",
|
|
35
|
+
"@pluv/tsconfig": "^4.0.0",
|
|
36
|
+
"eslint-config-pluv": "^4.0.0"
|
|
37
|
+
},
|
|
38
|
+
"exports": {
|
|
39
|
+
".": "./dist/index.mjs",
|
|
40
|
+
"./*": "./*"
|
|
38
41
|
},
|
|
39
42
|
"scripts": {
|
|
40
|
-
"build": "
|
|
41
|
-
"dev": "
|
|
43
|
+
"build": "tsdown",
|
|
44
|
+
"dev": "tsdown --watch",
|
|
42
45
|
"lint": "eslint \"src/**/*.ts*\" --fix --max-warnings 0",
|
|
46
|
+
"typecheck": "tsc --noEmit",
|
|
43
47
|
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
|
|
44
48
|
}
|
|
45
49
|
}
|
package/tsdown.config.ts
ADDED
package/dist/index.d.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { AbstractPersistence } from '@pluv/io';
|
|
2
|
-
import { JsonObject } from '@pluv/types';
|
|
3
|
-
import { Cluster, Redis } from 'ioredis';
|
|
4
|
-
|
|
5
|
-
type RedisClient = Cluster | Redis;
|
|
6
|
-
interface PersistenceRedisOptions {
|
|
7
|
-
client: RedisClient;
|
|
8
|
-
}
|
|
9
|
-
declare class PersistenceRedis extends AbstractPersistence {
|
|
10
|
-
private _client;
|
|
11
|
-
private _initialized;
|
|
12
|
-
constructor(options: PersistenceRedisOptions);
|
|
13
|
-
addUser(room: string, connectionId: string, user: JsonObject | null): Promise<void>;
|
|
14
|
-
deleteStorageState(room: string): Promise<void>;
|
|
15
|
-
deleteUser(room: string, connectionId: string): Promise<void>;
|
|
16
|
-
deleteUsers(room: string): Promise<void>;
|
|
17
|
-
getStorageState(room: string): Promise<string | null>;
|
|
18
|
-
setStorageState(room: string, state: string): Promise<void>;
|
|
19
|
-
getUser(room: string, connectionId: string): Promise<JsonObject | null>;
|
|
20
|
-
getUsers(room: string): Promise<Map<[connectionId: string][0], JsonObject | null>>;
|
|
21
|
-
getUsersSize(room: string): Promise<number>;
|
|
22
|
-
initialize(roomContext: {}): typeof this;
|
|
23
|
-
private _getClusterKey;
|
|
24
|
-
private _getRoomStorageKey;
|
|
25
|
-
private _getRoomUsersKey;
|
|
26
|
-
private _getRoomUsersUserKey;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export { PersistenceRedis, type RedisClient };
|
package/dist/index.js
DELETED
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
8
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
-
var __spreadValues = (a, b) => {
|
|
10
|
-
for (var prop in b || (b = {}))
|
|
11
|
-
if (__hasOwnProp.call(b, prop))
|
|
12
|
-
__defNormalProp(a, prop, b[prop]);
|
|
13
|
-
if (__getOwnPropSymbols)
|
|
14
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
15
|
-
if (__propIsEnum.call(b, prop))
|
|
16
|
-
__defNormalProp(a, prop, b[prop]);
|
|
17
|
-
}
|
|
18
|
-
return a;
|
|
19
|
-
};
|
|
20
|
-
var __export = (target, all) => {
|
|
21
|
-
for (var name in all)
|
|
22
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
23
|
-
};
|
|
24
|
-
var __copyProps = (to, from, except, desc) => {
|
|
25
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
26
|
-
for (let key of __getOwnPropNames(from))
|
|
27
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
28
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
29
|
-
}
|
|
30
|
-
return to;
|
|
31
|
-
};
|
|
32
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
33
|
-
var __async = (__this, __arguments, generator) => {
|
|
34
|
-
return new Promise((resolve, reject) => {
|
|
35
|
-
var fulfilled = (value) => {
|
|
36
|
-
try {
|
|
37
|
-
step(generator.next(value));
|
|
38
|
-
} catch (e) {
|
|
39
|
-
reject(e);
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
var rejected = (value) => {
|
|
43
|
-
try {
|
|
44
|
-
step(generator.throw(value));
|
|
45
|
-
} catch (e) {
|
|
46
|
-
reject(e);
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
50
|
-
step((generator = generator.apply(__this, __arguments)).next());
|
|
51
|
-
});
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
// src/index.ts
|
|
55
|
-
var index_exports = {};
|
|
56
|
-
__export(index_exports, {
|
|
57
|
-
PersistenceRedis: () => PersistenceRedis
|
|
58
|
-
});
|
|
59
|
-
module.exports = __toCommonJS(index_exports);
|
|
60
|
-
|
|
61
|
-
// src/PersistenceRedis.ts
|
|
62
|
-
var import_io = require("@pluv/io");
|
|
63
|
-
|
|
64
|
-
// src/utils/partitionByLength.ts
|
|
65
|
-
var partitionByLength = (arr, length) => {
|
|
66
|
-
if (!arr.length) return [];
|
|
67
|
-
const head = arr.slice(0, length);
|
|
68
|
-
const tail = arr.slice(length);
|
|
69
|
-
return [head, ...partitionByLength(tail, length)];
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
// src/PersistenceRedis.ts
|
|
73
|
-
var DELIMITER = ":::";
|
|
74
|
-
var HASH_TAG = "{PluvPersistenceRedis}";
|
|
75
|
-
var GET_USERS_CONCURRENCY = 4;
|
|
76
|
-
var PersistenceRedis = class _PersistenceRedis extends import_io.AbstractPersistence {
|
|
77
|
-
constructor(options) {
|
|
78
|
-
super();
|
|
79
|
-
this._initialized = null;
|
|
80
|
-
const { client } = options;
|
|
81
|
-
this._client = client;
|
|
82
|
-
this._initialized = options._initialized;
|
|
83
|
-
}
|
|
84
|
-
addUser(room, connectionId, user) {
|
|
85
|
-
return __async(this, null, function* () {
|
|
86
|
-
if (!this._initialized) return;
|
|
87
|
-
yield this._initialized;
|
|
88
|
-
yield this._client.multi().sadd(this._getRoomUsersKey(room), connectionId).set(this._getRoomUsersUserKey(room, connectionId), JSON.stringify(user)).exec();
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
deleteStorageState(room) {
|
|
92
|
-
return __async(this, null, function* () {
|
|
93
|
-
if (!this._initialized) return;
|
|
94
|
-
yield this._initialized;
|
|
95
|
-
yield this._client.del(this._getRoomStorageKey(room));
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
deleteUser(room, connectionId) {
|
|
99
|
-
return __async(this, null, function* () {
|
|
100
|
-
if (!this._initialized) return;
|
|
101
|
-
yield this._initialized;
|
|
102
|
-
const size = yield this.getUsersSize(room);
|
|
103
|
-
let multi = this._client.multi().srem(this._getRoomUsersKey(room), connectionId).del(this._getRoomUsersUserKey(room, connectionId));
|
|
104
|
-
if (size === 1) {
|
|
105
|
-
multi = multi.del(this._getRoomStorageKey(room)).del(this._getRoomUsersKey(room));
|
|
106
|
-
}
|
|
107
|
-
yield multi.exec();
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
deleteUsers(room) {
|
|
111
|
-
return __async(this, null, function* () {
|
|
112
|
-
if (!this._initialized) return;
|
|
113
|
-
yield this._initialized;
|
|
114
|
-
const members = yield this._client.smembers(this._getRoomUsersKey(room));
|
|
115
|
-
yield members.reduce(
|
|
116
|
-
(commands, connectionId) => {
|
|
117
|
-
return commands.del(this._getRoomUsersUserKey(room, connectionId));
|
|
118
|
-
},
|
|
119
|
-
this._client.multi().del(this._getRoomUsersKey(room))
|
|
120
|
-
).exec();
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
getStorageState(room) {
|
|
124
|
-
return __async(this, null, function* () {
|
|
125
|
-
if (!this._initialized) return null;
|
|
126
|
-
yield this._initialized;
|
|
127
|
-
return yield this._client.get(this._getRoomStorageKey(room));
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
setStorageState(room, state) {
|
|
131
|
-
return __async(this, null, function* () {
|
|
132
|
-
if (!this._initialized) return;
|
|
133
|
-
yield this._initialized;
|
|
134
|
-
yield this._client.set(this._getRoomStorageKey(room), state);
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
getUser(room, connectionId) {
|
|
138
|
-
return __async(this, null, function* () {
|
|
139
|
-
if (!this._initialized) return null;
|
|
140
|
-
yield this._initialized;
|
|
141
|
-
const data = yield this._client.get(this._getRoomUsersUserKey(room, connectionId));
|
|
142
|
-
return !data ? null : JSON.parse(data);
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
getUsers(room) {
|
|
146
|
-
return __async(this, null, function* () {
|
|
147
|
-
if (!this._initialized) return /* @__PURE__ */ new Map();
|
|
148
|
-
yield this._initialized;
|
|
149
|
-
const members = yield this._client.smembers(this._getRoomUsersKey(room));
|
|
150
|
-
const partitions = partitionByLength(members, GET_USERS_CONCURRENCY);
|
|
151
|
-
return yield partitions.reduce((promise, partition) => __async(this, null, function* () {
|
|
152
|
-
const map = yield promise;
|
|
153
|
-
const promises = partition.map((connectionId) => __async(this, null, function* () {
|
|
154
|
-
map.set(connectionId, yield this.getUser(room, connectionId));
|
|
155
|
-
}));
|
|
156
|
-
yield Promise.all(promises);
|
|
157
|
-
return map;
|
|
158
|
-
}), Promise.resolve(/* @__PURE__ */ new Map()));
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
getUsersSize(room) {
|
|
162
|
-
return __async(this, null, function* () {
|
|
163
|
-
if (!this._initialized) return 0;
|
|
164
|
-
yield this._initialized;
|
|
165
|
-
return yield this._client.scard(this._getRoomUsersKey(room));
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
initialize(roomContext) {
|
|
169
|
-
return new _PersistenceRedis(__spreadValues({
|
|
170
|
-
client: this._client
|
|
171
|
-
}, { _initialized: Promise.resolve(true) }));
|
|
172
|
-
}
|
|
173
|
-
_getClusterKey(key) {
|
|
174
|
-
return `${HASH_TAG}${key}`;
|
|
175
|
-
}
|
|
176
|
-
_getRoomStorageKey(room) {
|
|
177
|
-
return this._getClusterKey(`room_storage${DELIMITER}${room}`);
|
|
178
|
-
}
|
|
179
|
-
_getRoomUsersKey(room) {
|
|
180
|
-
return this._getClusterKey(`room_users${DELIMITER}${room}`);
|
|
181
|
-
}
|
|
182
|
-
_getRoomUsersUserKey(room, connectionId) {
|
|
183
|
-
return this._getClusterKey(`${this._getRoomUsersKey(room)}${DELIMITER}${connectionId}`);
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
187
|
-
0 && (module.exports = {
|
|
188
|
-
PersistenceRedis
|
|
189
|
-
});
|