@mrxsys/mrx-core 2.6.0 → 2.8.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/CHANGELOG.md +84 -19
- package/dist/chunk-4mt568fz.js +26 -0
- package/dist/chunk-7g8k2epn.js +104 -0
- package/dist/chunk-kv9hms2z.js +28 -0
- package/dist/{chunk-7m70tmz2.js → chunk-m18th1g5.js} +1 -1
- package/dist/chunk-ncc0m208.js +8 -0
- package/dist/chunk-r1kcf1q6.js +62 -0
- package/dist/chunk-sepwfqdh.js +6 -0
- package/dist/chunk-snqdnkk7.js +10 -0
- package/dist/{chunk-9wk2pajt.js → chunk-syhskygx.js} +9 -8
- package/dist/{chunk-64d6w5kt.js → chunk-y78xrx17.js} +2 -2
- package/dist/chunk-yd82hdxv.js +6 -0
- package/dist/chunk-z1skzn1j.js +8 -0
- package/dist/modules/data/data.d.ts +1 -1
- package/dist/modules/database/index.js +2 -2
- package/dist/modules/elysia/cache/cache.d.ts +306 -0
- package/dist/modules/elysia/cache/index.d.ts +1 -0
- package/dist/modules/elysia/cache/index.js +68 -0
- package/dist/modules/elysia/cache/types/cacheItem.d.ts +7 -0
- package/dist/modules/elysia/cache/types/cacheOptions.d.ts +21 -0
- package/dist/modules/elysia/cache/types/index.d.ts +1 -0
- package/dist/modules/elysia/cache/utils/generateCacheKey.d.ts +5 -0
- package/dist/modules/elysia/cache/utils/index.d.ts +1 -0
- package/dist/modules/elysia/cache/utils/index.js +7 -0
- package/dist/modules/elysia/crud/crud.d.ts +1 -1
- package/dist/modules/elysia/crud/index.js +13 -10
- package/dist/modules/elysia/crud/types/crudOptions.d.ts +2 -0
- package/dist/modules/elysia/dbResolver/dbResolver.d.ts +1 -1
- package/dist/modules/elysia/dbResolver/index.js +3 -3
- package/dist/modules/elysia/error/index.js +11 -2
- package/dist/modules/elysia/rateLimit/enums/index.d.ts +1 -0
- package/dist/modules/elysia/rateLimit/enums/index.js +7 -0
- package/dist/modules/elysia/rateLimit/enums/rateLimitErrorKeys.d.ts +3 -0
- package/dist/modules/elysia/rateLimit/index.d.ts +1 -0
- package/dist/modules/elysia/rateLimit/index.js +59 -0
- package/dist/modules/elysia/{ratelimit/ratelimit.d.ts → rateLimit/rateLimit.d.ts} +32 -15
- package/dist/modules/elysia/{ratelimit → rateLimit}/types/rateLimitOptions.d.ts +7 -16
- package/dist/modules/jwt/enums/index.d.ts +2 -0
- package/dist/modules/jwt/enums/index.js +11 -0
- package/dist/modules/jwt/enums/jwtErrorKeys.d.ts +5 -0
- package/dist/modules/jwt/enums/parseHumanTimeToSecondsErrorKeys.d.ts +3 -0
- package/dist/modules/jwt/index.d.ts +1 -0
- package/dist/modules/jwt/index.js +58 -0
- package/dist/modules/jwt/jwt.d.ts +3 -0
- package/dist/modules/jwt/utils/index.d.ts +1 -0
- package/dist/modules/jwt/utils/index.js +9 -0
- package/dist/modules/jwt/utils/parseHumanTimeToSeconds.d.ts +17 -0
- package/dist/modules/kvStore/enums/index.d.ts +1 -0
- package/dist/modules/kvStore/enums/index.js +7 -0
- package/dist/modules/kvStore/enums/kvStoreErrorKeys.d.ts +5 -0
- package/dist/modules/kvStore/ioredis/index.d.ts +1 -0
- package/dist/modules/kvStore/ioredis/index.js +102 -0
- package/dist/modules/kvStore/ioredis/ioredisStore.d.ts +107 -0
- package/dist/modules/kvStore/memory/index.d.ts +1 -0
- package/dist/modules/kvStore/memory/index.js +9 -0
- package/dist/modules/kvStore/memory/memoryStore.d.ts +119 -0
- package/dist/modules/kvStore/memory/types/memoryStoreEntry.d.ts +11 -0
- package/dist/modules/kvStore/types/index.d.ts +1 -0
- package/dist/modules/kvStore/types/index.js +1 -0
- package/dist/modules/kvStore/types/kvStore.d.ts +81 -0
- package/dist/modules/repository/index.js +1 -1
- package/dist/modules/repository/types/queryOptions.d.ts +5 -1
- package/dist/modules/totp/enums/index.d.ts +1 -0
- package/dist/modules/totp/enums/index.js +7 -0
- package/dist/modules/totp/enums/totpErrorKeys.d.ts +7 -0
- package/dist/modules/totp/hotp.d.ts +11 -0
- package/dist/modules/totp/index.d.ts +3 -0
- package/dist/modules/totp/index.js +110 -0
- package/dist/modules/totp/otpAuthUri.d.ts +21 -0
- package/dist/modules/totp/totp.d.ts +23 -0
- package/dist/modules/totp/types/index.d.ts +3 -0
- package/dist/modules/totp/types/index.js +1 -0
- package/dist/modules/totp/types/otpAuthUri.d.ts +35 -0
- package/dist/modules/totp/types/totpOptions.d.ts +23 -0
- package/dist/modules/totp/types/verifyOptions.d.ts +18 -0
- package/dist/modules/totp/utils/base32.d.ts +19 -0
- package/dist/modules/totp/utils/createCounterBuffer.d.ts +8 -0
- package/dist/modules/totp/utils/dynamicTruncation.d.ts +9 -0
- package/dist/modules/totp/utils/generateHmac.d.ts +9 -0
- package/dist/modules/totp/utils/generateSecretBytes.d.ts +10 -0
- package/dist/modules/totp/utils/index.d.ts +6 -0
- package/dist/modules/totp/utils/index.js +81 -0
- package/dist/modules/totp/utils/timeRemaining.d.ts +9 -0
- package/dist/utils/types/index.d.ts +1 -0
- package/dist/utils/types/renameKey.d.ts +10 -0
- package/package.json +86 -75
- package/dist/chunk-cqw9xq4y.js +0 -7
- package/dist/chunk-twaga0fp.js +0 -6
- package/dist/modules/elysia/jwt/enums/index.d.ts +0 -1
- package/dist/modules/elysia/jwt/enums/index.js +0 -7
- package/dist/modules/elysia/jwt/enums/jwtErrorKeys.d.ts +0 -4
- package/dist/modules/elysia/jwt/index.d.ts +0 -1
- package/dist/modules/elysia/jwt/index.js +0 -77
- package/dist/modules/elysia/jwt/jwt.d.ts +0 -119
- package/dist/modules/elysia/jwt/types/index.d.ts +0 -1
- package/dist/modules/elysia/jwt/types/jwtOptions.d.ts +0 -98
- package/dist/modules/elysia/ratelimit/enums/index.d.ts +0 -1
- package/dist/modules/elysia/ratelimit/enums/index.js +0 -7
- package/dist/modules/elysia/ratelimit/enums/ratelimitErrorKeys.d.ts +0 -3
- package/dist/modules/elysia/ratelimit/index.d.ts +0 -1
- package/dist/modules/elysia/ratelimit/index.js +0 -52
- /package/dist/modules/elysia/{jwt → cache}/types/index.js +0 -0
- /package/dist/modules/elysia/{ratelimit → rateLimit}/types/index.d.ts +0 -0
- /package/dist/modules/elysia/{ratelimit → rateLimit}/types/index.js +0 -0
|
@@ -16,30 +16,47 @@ import type { RateLimitOptions } from './types/rateLimitOptions';
|
|
|
16
16
|
* @returns An {@link Elysia} plugin that adds rate limiting functionality
|
|
17
17
|
*
|
|
18
18
|
* @example
|
|
19
|
+
* Basic usage with default in-memory store
|
|
19
20
|
* ```ts
|
|
20
|
-
*
|
|
21
|
-
*
|
|
21
|
+
* import { rateLimit } from '@nowarajs/elysia-ratelimit';
|
|
22
|
+
* import { Elysia } from 'elysia';
|
|
23
|
+
*
|
|
24
|
+
* const app = new Elysia()
|
|
25
|
+
* .use(rateLimit({
|
|
26
|
+
* store: ':memory:', // Use in-memory store
|
|
27
|
+
* limit: 100, // 100 requests
|
|
28
|
+
* window: 60, // per minute
|
|
29
|
+
* }))
|
|
30
|
+
* .get('/api/endpoint', () => ({ message: 'Hello World' }));
|
|
31
|
+
*
|
|
32
|
+
* app.listen(3000);
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* Using Redis store for distributed rate limiting
|
|
37
|
+
* ```ts
|
|
38
|
+
* import { IoRedisStore } from '@nowarajs/kv-store';
|
|
39
|
+
* import { rateLimit } from '@nowarajs/elysia-ratelimit';
|
|
40
|
+
* import { Elysia } from 'elysia';
|
|
41
|
+
*
|
|
42
|
+
* const redisStore = new IoRedisStore({
|
|
22
43
|
* host: 'localhost',
|
|
23
44
|
* port: 6379
|
|
24
45
|
* });
|
|
25
|
-
* await
|
|
46
|
+
* await redisStore.connect();
|
|
26
47
|
*
|
|
27
|
-
* // Create and configure the application with rate limiting
|
|
28
48
|
* const app = new Elysia()
|
|
29
49
|
* .use(rateLimit({
|
|
30
|
-
*
|
|
31
|
-
* limit:
|
|
32
|
-
* window:
|
|
50
|
+
* store: redisStore,
|
|
51
|
+
* limit: 1000, // 1000 requests
|
|
52
|
+
* window: 3600, // per hour
|
|
33
53
|
* }))
|
|
34
|
-
* .get('/
|
|
35
|
-
* return { success: true, message: 'This endpoint is rate limited' };
|
|
36
|
-
* });
|
|
54
|
+
* .get('/api/endpoint', () => ({ message: 'Hello World' }));
|
|
37
55
|
*
|
|
38
|
-
* // Start the server
|
|
39
56
|
* app.listen(3000);
|
|
40
57
|
* ```
|
|
41
58
|
*/
|
|
42
|
-
export declare const rateLimit: ({
|
|
59
|
+
export declare const rateLimit: ({ store, limit, window }: RateLimitOptions) => Elysia<"", {
|
|
43
60
|
decorator: {};
|
|
44
61
|
store: {};
|
|
45
62
|
derive: {};
|
|
@@ -48,7 +65,7 @@ export declare const rateLimit: ({ redis, limit, window }: RateLimitOptions) =>
|
|
|
48
65
|
typebox: {};
|
|
49
66
|
error: {};
|
|
50
67
|
}, {
|
|
51
|
-
schema: {}
|
|
68
|
+
schema: import("elysia").MergeSchema<import("elysia").MergeSchema<{}, {}, "">, {}, "">;
|
|
52
69
|
standaloneSchema: {};
|
|
53
70
|
macro: {};
|
|
54
71
|
macroFn: {};
|
|
@@ -56,8 +73,8 @@ export declare const rateLimit: ({ redis, limit, window }: RateLimitOptions) =>
|
|
|
56
73
|
}, {}, {
|
|
57
74
|
derive: {};
|
|
58
75
|
resolve: {};
|
|
59
|
-
schema:
|
|
60
|
-
standaloneSchema:
|
|
76
|
+
schema: {};
|
|
77
|
+
standaloneSchema: {};
|
|
61
78
|
}, {
|
|
62
79
|
derive: {};
|
|
63
80
|
resolve: {};
|
|
@@ -1,22 +1,13 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
/**
|
|
3
|
-
* Options to configure the rate limit plugin.
|
|
4
|
-
*
|
|
5
|
-
* @example
|
|
6
|
-
* ```ts
|
|
7
|
-
* const options: RateLimitOptions = {
|
|
8
|
-
* redis: redisInstance, // Your Redis instance
|
|
9
|
-
* limit: 100, // Allow 100 requests
|
|
10
|
-
* window: 60, // Per 60 seconds
|
|
11
|
-
* message: 'You have exceeded the rate limit. Please try again later.'
|
|
12
|
-
* };
|
|
13
|
-
* ```
|
|
14
|
-
*/
|
|
1
|
+
import type { KvStore } from '../../../../modules/kvStore/types/kvStore';
|
|
15
2
|
export interface RateLimitOptions {
|
|
16
3
|
/**
|
|
17
|
-
*
|
|
4
|
+
* Storage backend for rate limit data.
|
|
5
|
+
*
|
|
6
|
+
* - If not specified, defaults to in-memory storage
|
|
7
|
+
* - Use ':memory:' to explicitly specify in-memory storage
|
|
8
|
+
* - Provide a KvStore instance for persistent distributed storage
|
|
18
9
|
*/
|
|
19
|
-
readonly
|
|
10
|
+
readonly store?: ':memory:' | KvStore;
|
|
20
11
|
/**
|
|
21
12
|
* Maximum number of requests allowed in the time window.
|
|
22
13
|
*
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { signJWT, verifyJWT } from './jwt';
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
JWT_ERROR_KEYS
|
|
4
|
+
} from "../../chunk-ncc0m208.js";
|
|
5
|
+
import {
|
|
6
|
+
parseHumanTimeToSeconds
|
|
7
|
+
} from "../../chunk-r1kcf1q6.js";
|
|
8
|
+
import"../../chunk-sepwfqdh.js";
|
|
9
|
+
import {
|
|
10
|
+
HttpError
|
|
11
|
+
} from "../../chunk-683sda6e.js";
|
|
12
|
+
import"../../chunk-9nw6qekv.js";
|
|
13
|
+
import"../../chunk-vknq69e0.js";
|
|
14
|
+
|
|
15
|
+
// source/modules/jwt/jwt.ts
|
|
16
|
+
import {
|
|
17
|
+
SignJWT,
|
|
18
|
+
jwtVerify
|
|
19
|
+
} from "jose";
|
|
20
|
+
var signJWT = (secret, payload, expiration = Math.floor(Date.now() / 1000) + 60 * 15) => {
|
|
21
|
+
const exp = expiration instanceof Date ? Math.floor(expiration.getTime() / 1000) : typeof expiration === "number" ? expiration : parseHumanTimeToSeconds(expiration);
|
|
22
|
+
if (exp <= Math.floor(Date.now() / 1000))
|
|
23
|
+
throw new HttpError({
|
|
24
|
+
message: JWT_ERROR_KEYS.JWT_EXPIRATION_PASSED,
|
|
25
|
+
httpStatusCode: "BAD_REQUEST"
|
|
26
|
+
});
|
|
27
|
+
const finalPayload = {
|
|
28
|
+
iss: "Core-Issuer",
|
|
29
|
+
sub: "",
|
|
30
|
+
aud: ["Core-Audience"],
|
|
31
|
+
jti: Bun.randomUUIDv7(),
|
|
32
|
+
nbf: Math.floor(Date.now() / 1000),
|
|
33
|
+
iat: Math.floor(Date.now() / 1000),
|
|
34
|
+
exp,
|
|
35
|
+
...payload
|
|
36
|
+
};
|
|
37
|
+
try {
|
|
38
|
+
const jwt = new SignJWT(finalPayload).setProtectedHeader({ alg: "HS256", typ: "JWT" }).setIssuer(finalPayload.iss).setSubject(finalPayload.sub).setAudience(finalPayload.aud).setJti(finalPayload.jti).setNotBefore(finalPayload.nbf).setIssuedAt(finalPayload.iat).setExpirationTime(expiration).sign(new TextEncoder().encode(secret));
|
|
39
|
+
return jwt;
|
|
40
|
+
} catch (error) {
|
|
41
|
+
throw new HttpError({
|
|
42
|
+
message: JWT_ERROR_KEYS.JWT_SIGN_ERROR,
|
|
43
|
+
httpStatusCode: "INTERNAL_SERVER_ERROR",
|
|
44
|
+
cause: error
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var verifyJWT = async (token, secret) => {
|
|
49
|
+
try {
|
|
50
|
+
return await jwtVerify(token, new TextEncoder().encode(secret));
|
|
51
|
+
} catch {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
export {
|
|
56
|
+
verifyJWT,
|
|
57
|
+
signJWT
|
|
58
|
+
};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type JWTPayload, type JWTVerifyResult } from 'jose';
|
|
2
|
+
export declare const signJWT: (secret: string, payload: JWTPayload, expiration?: number | string | Date) => Promise<string>;
|
|
3
|
+
export declare const verifyJWT: (token: string, secret: string) => Promise<JWTVerifyResult | false>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { parseHumanTimeToSeconds } from './parseHumanTimeToSeconds';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a human-readable time expression to seconds
|
|
3
|
+
*
|
|
4
|
+
* @param timeExpression - A string representing a time period (e.g., "2 hours", "30 minutes ago", "+1 day")
|
|
5
|
+
*
|
|
6
|
+
* @throws ({@link BaseError}) - If the time expression is invalid or contains an unknown unit
|
|
7
|
+
*
|
|
8
|
+
* @returns The time period in seconds (negative for past times)
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* parseHumanTimeToSeconds("2 hours") // Returns 7200
|
|
13
|
+
* parseHumanTimeToSeconds("30 mins ago") // Returns -1800
|
|
14
|
+
* parseHumanTimeToSeconds("+1 day") // Returns 86400
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare const parseHumanTimeToSeconds: (timeExpression: string) => number;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { KV_STORE_ERROR_KEYS } from './kvStoreErrorKeys';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { IoRedisStore } from './ioredisStore';
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
KV_STORE_ERROR_KEYS
|
|
4
|
+
} from "../../../chunk-z1skzn1j.js";
|
|
5
|
+
import {
|
|
6
|
+
BaseError
|
|
7
|
+
} from "../../../chunk-vknq69e0.js";
|
|
8
|
+
|
|
9
|
+
// source/modules/kvStore/ioredis/ioredisStore.ts
|
|
10
|
+
import { Redis } from "ioredis";
|
|
11
|
+
class IoRedisStore {
|
|
12
|
+
_client;
|
|
13
|
+
constructor(options) {
|
|
14
|
+
this._client = new Redis({
|
|
15
|
+
...options,
|
|
16
|
+
lazyConnect: true
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
async connect() {
|
|
20
|
+
try {
|
|
21
|
+
await this._client.connect();
|
|
22
|
+
} catch (e) {
|
|
23
|
+
throw new BaseError({
|
|
24
|
+
message: KV_STORE_ERROR_KEYS.CONNECTION_FAILED,
|
|
25
|
+
cause: e
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async close() {
|
|
30
|
+
try {
|
|
31
|
+
await this._client.quit();
|
|
32
|
+
} catch (e) {
|
|
33
|
+
throw new BaseError({
|
|
34
|
+
message: KV_STORE_ERROR_KEYS.CLOSING_CONNECTION_FAILED,
|
|
35
|
+
cause: e
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async get(key) {
|
|
40
|
+
const value = await this._client.get(key);
|
|
41
|
+
if (value === null)
|
|
42
|
+
return null;
|
|
43
|
+
try {
|
|
44
|
+
return JSON.parse(value);
|
|
45
|
+
} catch {
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async set(key, value, ttlSec) {
|
|
50
|
+
const serialized = typeof value === "string" ? value : JSON.stringify(value);
|
|
51
|
+
if (ttlSec)
|
|
52
|
+
await this._client.setex(key, ttlSec, serialized);
|
|
53
|
+
else
|
|
54
|
+
await this._client.set(key, serialized);
|
|
55
|
+
}
|
|
56
|
+
async increment(key, amount = 1) {
|
|
57
|
+
const current = await this._client.get(key);
|
|
58
|
+
if (current !== null) {
|
|
59
|
+
const parsed = Number(current);
|
|
60
|
+
if (Number.isNaN(parsed))
|
|
61
|
+
throw new BaseError({
|
|
62
|
+
message: KV_STORE_ERROR_KEYS.NOT_INTEGER
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
if (amount === 1)
|
|
66
|
+
return this._client.incr(key);
|
|
67
|
+
return this._client.incrby(key, amount);
|
|
68
|
+
}
|
|
69
|
+
async decrement(key, amount = 1) {
|
|
70
|
+
const current = await this._client.get(key);
|
|
71
|
+
if (current !== null) {
|
|
72
|
+
const parsed = Number(current);
|
|
73
|
+
if (Number.isNaN(parsed))
|
|
74
|
+
throw new BaseError({
|
|
75
|
+
message: KV_STORE_ERROR_KEYS.NOT_INTEGER
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
if (amount === 1)
|
|
79
|
+
return this._client.decr(key);
|
|
80
|
+
return this._client.decrby(key, amount);
|
|
81
|
+
}
|
|
82
|
+
async del(key) {
|
|
83
|
+
const result = await this._client.del(key);
|
|
84
|
+
return result === 1;
|
|
85
|
+
}
|
|
86
|
+
async expire(key, ttlSec) {
|
|
87
|
+
const result = await this._client.expire(key, ttlSec);
|
|
88
|
+
return result === 1;
|
|
89
|
+
}
|
|
90
|
+
ttl(key) {
|
|
91
|
+
return this._client.ttl(key);
|
|
92
|
+
}
|
|
93
|
+
async clean() {
|
|
94
|
+
const keys = await this._client.keys("*");
|
|
95
|
+
if (keys.length === 0)
|
|
96
|
+
return 0;
|
|
97
|
+
return this._client.del(...keys);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
export {
|
|
101
|
+
IoRedisStore
|
|
102
|
+
};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { type RedisOptions } from 'ioredis';
|
|
2
|
+
import type { KvStore } from '../../../modules/kvStore/types/kvStore';
|
|
3
|
+
/**
|
|
4
|
+
* Redis-based key-value store implementation using ioredis client.
|
|
5
|
+
*
|
|
6
|
+
* Provides a Redis-backed implementation of the KvStore interface with
|
|
7
|
+
* automatic JSON serialization/deserialization and proper error handling.
|
|
8
|
+
*/
|
|
9
|
+
export declare class IoRedisStore implements KvStore {
|
|
10
|
+
/**
|
|
11
|
+
* Redis client instance.
|
|
12
|
+
*/
|
|
13
|
+
private readonly _client;
|
|
14
|
+
/**
|
|
15
|
+
* Creates an IoRedis store instance.
|
|
16
|
+
*
|
|
17
|
+
* @param options - Redis connection options
|
|
18
|
+
*/
|
|
19
|
+
constructor(options: RedisOptions);
|
|
20
|
+
/**
|
|
21
|
+
* Establishes connection to Redis server.
|
|
22
|
+
*
|
|
23
|
+
* @throws ({@link BaseError}) - When connection fails
|
|
24
|
+
*/
|
|
25
|
+
connect(): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Closes the Redis connection gracefully.
|
|
28
|
+
*
|
|
29
|
+
* @throws ({@link BaseError}) - When closing connection fails
|
|
30
|
+
*/
|
|
31
|
+
close(): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Retrieves a value from Redis by key.
|
|
34
|
+
*
|
|
35
|
+
* @template T - The expected type of the stored value
|
|
36
|
+
*
|
|
37
|
+
* @param key - The key to retrieve
|
|
38
|
+
*
|
|
39
|
+
* @returns The value associated with the key, or null if not found or expired
|
|
40
|
+
*/
|
|
41
|
+
get<T = unknown>(key: string): Promise<T | null>;
|
|
42
|
+
/**
|
|
43
|
+
* Stores a value in Redis with optional TTL.
|
|
44
|
+
*
|
|
45
|
+
* @template T - The type of the value being stored
|
|
46
|
+
*
|
|
47
|
+
* @param key - The key to store the value under
|
|
48
|
+
* @param value - The value to store
|
|
49
|
+
* @param ttlSec - Time to live in seconds (optional)
|
|
50
|
+
*/
|
|
51
|
+
set<T = unknown>(key: string, value: T, ttlSec?: number): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Increments a numeric value stored at key by the specified amount.
|
|
54
|
+
* If the key does not exist, it is set to 0 before performing the operation.
|
|
55
|
+
*
|
|
56
|
+
* @param key - The key containing the numeric value
|
|
57
|
+
* @param amount - The amount to increment by (default: 1)
|
|
58
|
+
*
|
|
59
|
+
* @throws ({@link BaseError}) - When the value is not a valid integer
|
|
60
|
+
*
|
|
61
|
+
* @returns The value after incrementing
|
|
62
|
+
*/
|
|
63
|
+
increment(key: string, amount?: number): Promise<number>;
|
|
64
|
+
/**
|
|
65
|
+
* Decrements a numeric value stored at key by the specified amount.
|
|
66
|
+
* If the key does not exist, it is set to 0 before performing the operation.
|
|
67
|
+
*
|
|
68
|
+
* @param key - The key containing the numeric value
|
|
69
|
+
* @param amount - The amount to decrement by (default: 1)
|
|
70
|
+
*
|
|
71
|
+
* @throws ({@link BaseError}) - When the value is not a valid integer
|
|
72
|
+
*
|
|
73
|
+
* @returns The value after decrementing
|
|
74
|
+
*/
|
|
75
|
+
decrement(key: string, amount?: number): Promise<number>;
|
|
76
|
+
/**
|
|
77
|
+
* Deletes a key from Redis.
|
|
78
|
+
*
|
|
79
|
+
* @param key - The key to delete
|
|
80
|
+
*
|
|
81
|
+
* @returns True if the key was deleted, false if it did not exist
|
|
82
|
+
*/
|
|
83
|
+
del(key: string): Promise<boolean>;
|
|
84
|
+
/**
|
|
85
|
+
* Sets an expiration time for a key.
|
|
86
|
+
*
|
|
87
|
+
* @param key - The key to set expiration for
|
|
88
|
+
* @param ttlSec - Time to live in seconds
|
|
89
|
+
*
|
|
90
|
+
* @returns True if the expiration was set, false if the key does not exist
|
|
91
|
+
*/
|
|
92
|
+
expire(key: string, ttlSec: number): Promise<boolean>;
|
|
93
|
+
/**
|
|
94
|
+
* Gets the remaining time to live for a key.
|
|
95
|
+
*
|
|
96
|
+
* @param key - The key to check
|
|
97
|
+
*
|
|
98
|
+
* @returns Time to live in seconds, -1 if key has no expiration, -2 if key does not exist
|
|
99
|
+
*/
|
|
100
|
+
ttl(key: string): Promise<number>;
|
|
101
|
+
/**
|
|
102
|
+
* Removes all keys from the Redis database.
|
|
103
|
+
*
|
|
104
|
+
* @returns The number of keys that were deleted
|
|
105
|
+
*/
|
|
106
|
+
clean(): Promise<number>;
|
|
107
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { MemoryStore } from './memoryStore';
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { KvStore } from '../../../modules/kvStore/types/kvStore';
|
|
2
|
+
/**
|
|
3
|
+
* In-memory key-value store implementation with automatic cleanup of expired entries.
|
|
4
|
+
*
|
|
5
|
+
* Provides a memory-based implementation of the KvStore interface with TTL support
|
|
6
|
+
* and automatic background cleanup of expired entries.
|
|
7
|
+
*/
|
|
8
|
+
export declare class MemoryStore implements KvStore {
|
|
9
|
+
/**
|
|
10
|
+
* In-memory key-value store.
|
|
11
|
+
*/
|
|
12
|
+
private readonly _store;
|
|
13
|
+
/**
|
|
14
|
+
* Cleanup interval (5 minutes by default).
|
|
15
|
+
*
|
|
16
|
+
* @defaultValue 300000
|
|
17
|
+
*/
|
|
18
|
+
private readonly _cleanupInterval;
|
|
19
|
+
/**
|
|
20
|
+
* Timer for cleanup operations.
|
|
21
|
+
*/
|
|
22
|
+
private _cleanupTimer;
|
|
23
|
+
/**
|
|
24
|
+
* Creates instance and starts cleanup process.
|
|
25
|
+
*
|
|
26
|
+
* @param cleanupIntervalMs - Cleanup interval in milliseconds (default: 300000 ms / 5 minutes)
|
|
27
|
+
*/
|
|
28
|
+
constructor(cleanupIntervalMs?: number);
|
|
29
|
+
/**
|
|
30
|
+
* Retrieves a value from the store by key.
|
|
31
|
+
* Automatically removes expired entries during retrieval.
|
|
32
|
+
*
|
|
33
|
+
* @template T - The expected type of the stored value
|
|
34
|
+
*
|
|
35
|
+
* @param key - The key to retrieve
|
|
36
|
+
*
|
|
37
|
+
* @returns The value associated with the key, or null if not found or expired
|
|
38
|
+
*/
|
|
39
|
+
get<T = unknown>(key: string): T | null;
|
|
40
|
+
/**
|
|
41
|
+
* Stores a value in memory with optional TTL.
|
|
42
|
+
*
|
|
43
|
+
* @template T - The type of the value being stored
|
|
44
|
+
*
|
|
45
|
+
* @param key - The key to store the value under
|
|
46
|
+
* @param value - The value to store
|
|
47
|
+
* @param ttlSec - Time to live in seconds (optional)
|
|
48
|
+
*/
|
|
49
|
+
set<T = unknown>(key: string, value: T, ttlSec?: number): void;
|
|
50
|
+
/**
|
|
51
|
+
* Increments a numeric value stored at key by the specified amount.
|
|
52
|
+
* If the key does not exist, it is set to 0 before performing the operation.
|
|
53
|
+
* Preserves existing TTL when incrementing.
|
|
54
|
+
*
|
|
55
|
+
* @param key - The key containing the numeric value
|
|
56
|
+
* @param amount - The amount to increment by (default: 1)
|
|
57
|
+
*
|
|
58
|
+
* @throws ({@link BaseError}) - When the value is not a valid integer
|
|
59
|
+
*
|
|
60
|
+
* @returns The value after incrementing
|
|
61
|
+
*/
|
|
62
|
+
increment(key: string, amount?: number): number;
|
|
63
|
+
/**
|
|
64
|
+
* Decrements a numeric value stored at key by the specified amount.
|
|
65
|
+
* If the key does not exist, it is set to 0 before performing the operation.
|
|
66
|
+
* Preserves existing TTL when decrementing.
|
|
67
|
+
*
|
|
68
|
+
* @param key - The key containing the numeric value
|
|
69
|
+
* @param amount - The amount to decrement by (default: 1)
|
|
70
|
+
*
|
|
71
|
+
* @throws ({@link BaseError}) - When the value is not a valid integer
|
|
72
|
+
*
|
|
73
|
+
* @returns The value after decrementing
|
|
74
|
+
*/
|
|
75
|
+
decrement(key: string, amount?: number): number;
|
|
76
|
+
/**
|
|
77
|
+
* Deletes a key from the store.
|
|
78
|
+
*
|
|
79
|
+
* @param key - The key to delete
|
|
80
|
+
*
|
|
81
|
+
* @returns True if the key was deleted, false if it did not exist
|
|
82
|
+
*/
|
|
83
|
+
del(key: string): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Sets an expiration time for a key.
|
|
86
|
+
*
|
|
87
|
+
* @param key - The key to set expiration for
|
|
88
|
+
* @param ttlSec - Time to live in seconds
|
|
89
|
+
*
|
|
90
|
+
* @returns True if the expiration was set, false if the key does not exist
|
|
91
|
+
*/
|
|
92
|
+
expire(key: string, ttlSec: number): boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Gets the remaining time to live for a key.
|
|
95
|
+
*
|
|
96
|
+
* @param key - The key to check
|
|
97
|
+
*
|
|
98
|
+
* @returns Time to live in seconds, -1 if key has no expiration or does not exist
|
|
99
|
+
*/
|
|
100
|
+
ttl(key: string): number;
|
|
101
|
+
/**
|
|
102
|
+
* Removes all keys from the store.
|
|
103
|
+
*
|
|
104
|
+
* @returns The number of keys that were deleted
|
|
105
|
+
*/
|
|
106
|
+
clean(): number;
|
|
107
|
+
/**
|
|
108
|
+
* Starts the cleanup process for expired entries.
|
|
109
|
+
*/
|
|
110
|
+
private _startCleanup;
|
|
111
|
+
/**
|
|
112
|
+
* Removes expired entries from the store.
|
|
113
|
+
*/
|
|
114
|
+
private _removeExpiredEntries;
|
|
115
|
+
/**
|
|
116
|
+
* Stops the cleanup process and clears resources.
|
|
117
|
+
*/
|
|
118
|
+
destroy(): void;
|
|
119
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type { KvStore } from './kvStore';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// @bun
|