@mrxsys/mrx-core 2.11.0-1-and-269-20251003 → 2.11.1-1-and-275-20251023

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.
Files changed (46) hide show
  1. package/dist/{chunk-dzfefxjq.js → chunk-pjv1ekwr.js} +32 -0
  2. package/dist/chunk-rz5p4j3p.js +13 -0
  3. package/dist/modules/elysia/cache/cache.d.ts +7 -13
  4. package/dist/modules/elysia/cache/index.js +66 -46
  5. package/dist/modules/elysia/cache/types/cache-item.d.ts +0 -1
  6. package/dist/modules/elysia/cache/types/cache-options.d.ts +2 -11
  7. package/dist/modules/elysia/crud/index.js +10 -10
  8. package/dist/modules/elysia/crud/operations/index.js +1 -1
  9. package/dist/modules/elysia/rate-limit/index.js +51 -26
  10. package/dist/modules/elysia/rate-limit/rate-limit.d.ts +361 -32
  11. package/dist/modules/elysia/rate-limit/types/rate-limit-options.d.ts +0 -9
  12. package/dist/modules/kv-store/bun-redis/bun-redis-store.d.ts +25 -0
  13. package/dist/modules/kv-store/bun-redis/index.d.ts +1 -0
  14. package/dist/modules/kv-store/bun-redis/index.js +76 -0
  15. package/dist/modules/kv-store/ioredis/index.js +4 -10
  16. package/dist/modules/kv-store/ioredis/ioredis-store.d.ts +0 -82
  17. package/dist/modules/kv-store/memory/index.js +98 -4
  18. package/dist/modules/kv-store/memory/memory-store.d.ts +0 -84
  19. package/dist/modules/kv-store/types/kv-store.d.ts +2 -2
  20. package/dist/modules/logger/enums/index.js +1 -1
  21. package/dist/modules/logger/enums/logger-error-keys.d.ts +6 -3
  22. package/dist/modules/logger/events/logger-events.d.ts +12 -3
  23. package/dist/modules/logger/index.js +173 -81
  24. package/dist/modules/logger/logger.d.ts +115 -133
  25. package/dist/modules/logger/sinks/console-logger.d.ts +2 -16
  26. package/dist/modules/logger/sinks/devnull-logger.d.ts +8 -0
  27. package/dist/modules/logger/sinks/file-logger/enums/file-logger-error-keys.d.ts +3 -0
  28. package/dist/modules/logger/sinks/file-logger/file-logger.d.ts +25 -0
  29. package/dist/modules/logger/sinks/index.d.ts +4 -2
  30. package/dist/modules/logger/sinks/index.js +54 -31
  31. package/dist/modules/logger/types/index.d.ts +6 -6
  32. package/dist/modules/logger/types/log-levels.d.ts +1 -4
  33. package/dist/modules/logger/types/logger-options.d.ts +41 -0
  34. package/dist/modules/logger/types/logger-sink.d.ts +12 -3
  35. package/dist/modules/logger/types/sink-bodies-intersection.d.ts +2 -0
  36. package/dist/modules/logger/types/sink-body.d.ts +1 -1
  37. package/dist/modules/logger/types/sink-map.d.ts +1 -1
  38. package/package.json +26 -21
  39. package/dist/chunk-b23dvm2d.js +0 -29
  40. package/dist/chunk-b96fm9ph.js +0 -10
  41. package/dist/chunk-e30paw8a.js +0 -101
  42. package/dist/modules/elysia/cache/utils/index.d.ts +0 -1
  43. package/dist/modules/elysia/cache/utils/index.js +0 -7
  44. package/dist/modules/logger/sinks/file-logger.d.ts +0 -25
  45. package/dist/modules/logger/types/bodies-intersection.d.ts +0 -2
  46. package/dist/modules/logger/types/log-stream-chunk.d.ts +0 -15
@@ -35,6 +35,10 @@ var count = (database, tableName, {
35
35
  content: data
36
36
  };
37
37
  }, {
38
+ detail: {
39
+ summary: "Count",
40
+ description: `Count ${tableName} records based on query options.`
41
+ },
38
42
  ...getDbInjection(database),
39
43
  body: `${tableName}Count`,
40
44
  response: `${tableName}CountResponse200`,
@@ -63,6 +67,10 @@ var batchDelete = (database, tableName, {
63
67
  content: data
64
68
  };
65
69
  }, {
70
+ detail: {
71
+ summary: "Delete",
72
+ description: `Delete ${tableName} records based on query options.`
73
+ },
66
74
  ...getDbInjection(database),
67
75
  body: `${tableName}Delete`,
68
76
  response: `${tableName}Response200`,
@@ -96,6 +104,10 @@ var deleteOne = (database, tableName, {
96
104
  content: data
97
105
  };
98
106
  }, {
107
+ detail: {
108
+ summary: "Delete One",
109
+ description: `Delete a single ${tableName} record by its primary key.`
110
+ },
99
111
  ...getDbInjection(database),
100
112
  params: `${tableName}IdParam`,
101
113
  response: `${tableName}Response200`,
@@ -122,6 +134,10 @@ var find = (database, tableName, {
122
134
  content: data
123
135
  };
124
136
  }, {
137
+ detail: {
138
+ summary: "Find",
139
+ description: `Find ${tableName} records based on query options.`
140
+ },
125
141
  ...getDbInjection(database),
126
142
  body: `${tableName}Find`,
127
143
  response: `${tableName}Response200`,
@@ -154,6 +170,10 @@ var findOne = (database, tableName, {
154
170
  content: data
155
171
  };
156
172
  }, {
173
+ detail: {
174
+ summary: "Find One",
175
+ description: `Find a single ${tableName} record by its primary key.`
176
+ },
157
177
  ...getDbInjection(database),
158
178
  params: `${tableName}IdParam`,
159
179
  response: `${tableName}Response200`,
@@ -181,6 +201,10 @@ var insert = (database, tableName, {
181
201
  content: data
182
202
  };
183
203
  }, {
204
+ detail: {
205
+ summary: "Insert",
206
+ description: `Insert one or more records into the ${tableName} table.`
207
+ },
184
208
  ...getDbInjection(database),
185
209
  body: `${tableName}Insert`,
186
210
  response: `${tableName}Response200`,
@@ -208,6 +232,10 @@ var update = (database, tableName, {
208
232
  content: data
209
233
  };
210
234
  }, {
235
+ detail: {
236
+ summary: "Update",
237
+ description: `Update one or more ${tableName} records based on query options.`
238
+ },
211
239
  ...getDbInjection(database),
212
240
  body: `${tableName}Update`,
213
241
  response: `${tableName}Response200`,
@@ -242,6 +270,10 @@ var updateOne = (database, tableName, {
242
270
  content: data
243
271
  };
244
272
  }, {
273
+ detail: {
274
+ summary: "Update Single Record",
275
+ description: `Update a single record in the ${tableName} table by its primary key.`
276
+ },
245
277
  ...getDbInjection(database),
246
278
  params: `${tableName}IdParam`,
247
279
  body: `${tableName}UpdateOne`,
@@ -0,0 +1,13 @@
1
+ // @bun
2
+ // source/modules/logger/enums/logger-error-keys.ts
3
+ var LOGGER_ERROR_KEYS = {
4
+ BEFORE_EXIT_CLOSE_ERROR: "mrx-core.logger.error.before_exit_close_error",
5
+ BEFORE_EXIT_FLUSH_ERROR: "mrx-core.logger.error.before_exit_flush_error",
6
+ NO_SINKS_PROVIDED: "mrx-core.logger.error.no_sinks_provided",
7
+ REGISTER_SINK_ERROR: "mrx-core.logger.error.register_sink_error",
8
+ SINK_ALREADY_ADDED: "mrx-core.logger.error.sink_already_added",
9
+ SINK_CLOSE_ERROR: "mrx-core.logger.error.sink_close_error",
10
+ SINK_LOG_ERROR: "mrx-core.logger.error.sink_log_error"
11
+ };
12
+
13
+ export { LOGGER_ERROR_KEYS };
@@ -1,12 +1,9 @@
1
1
  import { Elysia } from 'elysia';
2
- import { MemoryStore } from '../../../modules/kv-store/memory/memory-store';
2
+ import type { KvStore } from '../../../modules/kv-store/types';
3
3
  import type { CacheOptions } from './types/cache-options';
4
- export declare const cache: ({ defaultTtl, prefix, store }?: CacheOptions) => Elysia<"", {
4
+ export declare const cache: (store?: KvStore) => Elysia<"", {
5
5
  decorator: {};
6
- store: {
7
- kvStore: import("../../kv-store/types").KvStore | MemoryStore;
8
- _cachedRoutes: Set<string>;
9
- };
6
+ store: {};
10
7
  derive: {};
11
8
  resolve: {};
12
9
  }, {
@@ -16,11 +13,11 @@ export declare const cache: ({ defaultTtl, prefix, store }?: CacheOptions) => El
16
13
  schema: {};
17
14
  standaloneSchema: {};
18
15
  macro: Partial<{
19
- readonly isCached: number | boolean;
16
+ readonly isCached: CacheOptions;
20
17
  }>;
21
18
  macroFn: {
22
- readonly isCached: (enable: boolean | number) => {
23
- readonly afterHandle: ({ set, responseValue, store, request }: {
19
+ readonly isCached: ({ ttl, prefix }: CacheOptions) => {
20
+ readonly afterHandle: ({ set, responseValue, request }: {
24
21
  body: unknown;
25
22
  query: Record<string, string>;
26
23
  params: {};
@@ -37,10 +34,7 @@ export declare const cache: ({ defaultTtl, prefix, store }?: CacheOptions) => El
37
34
  path: string;
38
35
  route: string;
39
36
  request: Request;
40
- store: {
41
- kvStore: import("../../kv-store/types").KvStore | MemoryStore;
42
- _cachedRoutes: Set<string>;
43
- };
37
+ store: {};
44
38
  status: <const Code extends number | keyof import("elysia").StatusMap, const T = Code extends 100 | 101 | 102 | 103 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 | 300 | 301 | 302 | 303 | 304 | 307 | 308 | 420 ? {
45
39
  readonly 100: "Continue";
46
40
  readonly 101: "Switching Protocols";
@@ -1,70 +1,90 @@
1
1
  // @bun
2
2
  import {
3
3
  MemoryStore
4
- } from "../../../chunk-e30paw8a.js";
4
+ } from "../../kv-store/memory/index.js";
5
5
  import"../../../chunk-xhhj1gvj.js";
6
- import {
7
- generateCacheKey
8
- } from "../../../chunk-b23dvm2d.js";
9
6
  import"../../../chunk-9cgzhc50.js";
10
7
 
11
8
  // source/modules/elysia/cache/cache.ts
12
9
  import { Elysia } from "elysia";
13
- var cache = ({
14
- defaultTtl = 60,
15
- prefix = "",
16
- store = ":memory:"
17
- } = {}) => new Elysia().state({
18
- kvStore: store === ":memory:" ? new MemoryStore : store
19
- }).state({
20
- _cachedRoutes: new Set
21
- }).onRequest(async ({ request, store: store2, set }) => {
22
- const sanitizeUrl = new URL(request.url).pathname;
23
- if (store2._cachedRoutes.has(`${request.method}:${sanitizeUrl}`)) {
24
- const cacheKey = await generateCacheKey(request.clone());
25
- const cachedData = await store2.kvStore.get(`${prefix}${cacheKey}`);
26
- if (cachedData && typeof cachedData === "object" && "response" in cachedData && "metadata" in cachedData) {
27
- const { response, metadata } = cachedData;
28
- set.headers["cache-control"] = `max-age=${metadata.ttl}, public`;
29
- set.headers["x-cache"] = "HIT";
30
- set.headers["etag"] = `"${prefix}${cacheKey}"`;
31
- set.headers["expires"] = new Date(Date.now() + metadata.ttl * 1000).toUTCString();
32
- set.headers["last-modified"] = metadata.createdAt;
33
- if (response instanceof Response)
34
- return response.clone();
35
- return response;
10
+
11
+ // source/modules/elysia/cache/utils/generate-cache-key.ts
12
+ var _calculateBodyHash = async (body, hasher) => {
13
+ if (!body)
14
+ return;
15
+ const reader = body.getReader();
16
+ try {
17
+ while (true) {
18
+ const { done, value } = await reader.read();
19
+ if (done)
20
+ break;
21
+ if (value)
22
+ hasher.update(new Uint8Array(value));
36
23
  }
37
- set.headers["x-cache"] = "MISS";
24
+ } finally {
25
+ reader.releaseLock();
38
26
  }
39
- return;
40
- }).macro({
41
- isCached: (enable) => {
42
- const ttl = typeof enable === "number" ? enable : enable ? defaultTtl : 0;
43
- return {
44
- async afterHandle({ set, responseValue, store: store2, request }) {
45
- const sanitizeUrl = new URL(request.url).pathname;
46
- if (!store2._cachedRoutes.has(`${request.method}:${sanitizeUrl}`))
47
- store2._cachedRoutes.add(`${request.method}:${sanitizeUrl}`);
27
+ };
28
+ var generateCacheKey = async (request) => {
29
+ const { method, url, headers } = request;
30
+ const hasher = new Bun.CryptoHasher("sha256");
31
+ hasher.update(method);
32
+ hasher.update(url);
33
+ hasher.update(JSON.stringify(headers));
34
+ await _calculateBodyHash(request.body, hasher);
35
+ return hasher.digest("hex");
36
+ };
37
+
38
+ // source/modules/elysia/cache/cache.ts
39
+ var cache = (store = new MemoryStore) => {
40
+ const cachedRoutes = new Map;
41
+ return new Elysia().onRequest(async ({ request, set }) => {
42
+ const route = `${request.method}:${new URL(request.url).pathname}`;
43
+ if (cachedRoutes.has(route)) {
44
+ const { ttl, prefix } = cachedRoutes.get(route);
45
+ const cacheKey = await generateCacheKey(request.clone());
46
+ const cacheItem = await store.get(`${prefix}${cacheKey}`);
47
+ if (cacheItem && typeof cacheItem === "object" && "response" in cacheItem && "metadata" in cacheItem) {
48
+ const createdAt = new Date(cacheItem.metadata.createdAt);
49
+ const expiresAt = new Date(createdAt.getTime() + ttl * 1000);
50
+ const now = Date.now();
51
+ const remaining = Math.max(0, Math.ceil((expiresAt.getTime() - now) / 1000));
52
+ set.headers["cache-control"] = `max-age=${remaining}, public`;
53
+ set.headers["etag"] = `"${prefix}${cacheKey}"`;
54
+ set.headers["last-modified"] = cacheItem.metadata.createdAt;
55
+ set.headers["expires"] = expiresAt.toUTCString();
56
+ set.headers["x-cache"] = "HIT";
57
+ if (cacheItem.response instanceof Response)
58
+ return cacheItem.response.clone();
59
+ return cacheItem.response;
60
+ }
61
+ set.headers["x-cache"] = "MISS";
62
+ }
63
+ return;
64
+ }).macro({
65
+ isCached: ({ ttl, prefix = "" }) => ({
66
+ async afterHandle({ set, responseValue, request }) {
67
+ const route = `${request.method}:${new URL(request.url).pathname}`;
68
+ if (!cachedRoutes.has(route))
69
+ cachedRoutes.set(route, { ttl, prefix });
48
70
  const cacheKey = await generateCacheKey(request.clone());
49
71
  const now = new Date;
50
72
  set.headers["cache-control"] = `max-age=${ttl}, public`;
51
73
  set.headers["etag"] = `"${prefix}${cacheKey}"`;
52
74
  set.headers["last-modified"] = now.toUTCString();
53
75
  set.headers["expires"] = new Date(now.getTime() + ttl * 1000).toUTCString();
54
- if (!set.headers["x-cache"])
55
- set.headers["x-cache"] = "MISS";
56
- const cacheData = {
76
+ set.headers["x-cache"] = "MISS";
77
+ const cacheItem = {
57
78
  response: responseValue instanceof Response ? responseValue.clone() : responseValue,
58
79
  metadata: {
59
- createdAt: now.toUTCString(),
60
- ttl
80
+ createdAt: now.toUTCString()
61
81
  }
62
82
  };
63
- await store2.kvStore.set(`${prefix}${cacheKey}`, cacheData, ttl);
83
+ await store.set(`${prefix}${cacheKey}`, cacheItem, ttl);
64
84
  }
65
- };
66
- }
67
- });
85
+ })
86
+ });
87
+ };
68
88
  export {
69
89
  cache
70
90
  };
@@ -2,6 +2,5 @@ export interface CacheItem {
2
2
  response: unknown;
3
3
  metadata: {
4
4
  createdAt: string;
5
- ttl: number;
6
5
  };
7
6
  }
@@ -1,21 +1,12 @@
1
- import type { KvStore } from '../../../../modules/kv-store/types/kv-store';
2
1
  export interface CacheOptions {
3
2
  /**
4
- * Default TTL in seconds
5
- *
6
- * @defaultValue 60
3
+ * TTL in seconds
7
4
  */
8
- defaultTtl?: number;
5
+ ttl: number;
9
6
  /**
10
7
  * Cache key prefix
11
8
  *
12
9
  * @defaultValue ''
13
10
  */
14
11
  prefix?: string;
15
- /**
16
- * Storage backend
17
- *
18
- * @defaultValue ':memory:'
19
- */
20
- store?: ':memory:' | KvStore;
21
12
  }
@@ -1,14 +1,4 @@
1
1
  // @bun
2
- import {
3
- batchDelete,
4
- count,
5
- deleteOne,
6
- find,
7
- findOne,
8
- insert,
9
- update,
10
- updateOne
11
- } from "../../../chunk-dzfefxjq.js";
12
2
  import {
13
3
  createCountResponse200Schema,
14
4
  createCountSchema,
@@ -21,6 +11,16 @@ import {
21
11
  createUpdateSchema
22
12
  } from "../../../chunk-p14h6jfs.js";
23
13
  import"../../../chunk-9dzsj7f2.js";
14
+ import {
15
+ batchDelete,
16
+ count,
17
+ deleteOne,
18
+ find,
19
+ findOne,
20
+ insert,
21
+ update,
22
+ updateOne
23
+ } from "../../../chunk-pjv1ekwr.js";
24
24
  import"../../../chunk-441xs5k1.js";
25
25
  import"../../../chunk-fs3wm3p4.js";
26
26
  import"../../../chunk-z0ct35ft.js";
@@ -8,7 +8,7 @@ import {
8
8
  insert,
9
9
  update,
10
10
  updateOne
11
- } from "../../../../chunk-dzfefxjq.js";
11
+ } from "../../../../chunk-pjv1ekwr.js";
12
12
  import"../../../../chunk-441xs5k1.js";
13
13
  import"../../../../chunk-fs3wm3p4.js";
14
14
  import"../../../../chunk-z0ct35ft.js";
@@ -4,7 +4,7 @@ import {
4
4
  } from "../../../chunk-dre2fgj0.js";
5
5
  import {
6
6
  MemoryStore
7
- } from "../../../chunk-e30paw8a.js";
7
+ } from "../../kv-store/memory/index.js";
8
8
  import"../../../chunk-xhhj1gvj.js";
9
9
  import {
10
10
  HttpError
@@ -14,40 +14,65 @@ import"../../../chunk-9cgzhc50.js";
14
14
 
15
15
  // source/modules/elysia/rate-limit/rate-limit.ts
16
16
  import { Elysia } from "elysia";
17
- var rateLimit = ({ store, limit, window }) => {
18
- const storeInstance = store === ":memory:" || !store ? new MemoryStore : store;
19
- return new Elysia({
20
- name: "rateLimit",
21
- seed: {
22
- store,
23
- limit,
24
- window
25
- }
26
- }).onRequest(async ({ set, request, server }) => {
27
- const ip = request.headers.get("x-forwarded-for") || request.headers.get("x-real-ip") || server?.requestIP(request)?.address || "127.0.0.1";
28
- const key = `ratelimit:${ip}`;
29
- const count = await storeInstance.get(key);
30
- let newCount;
31
- if (count === null) {
32
- await storeInstance.set(key, 1, window);
33
- newCount = 1;
17
+ var rateLimit = (store = new MemoryStore) => {
18
+ const restrictedRoutes = new Map;
19
+ const rateLimitCheck = async (key, limit, window, set) => {
20
+ if (set.headers["X-RateLimit-Limit"])
21
+ return;
22
+ let count = await store.get(key) ?? 0;
23
+ if (count === 0) {
24
+ await store.set(key, 1, window);
25
+ count = 1;
34
26
  } else {
35
- newCount = await storeInstance.increment(key);
27
+ count = await store.increment(key);
36
28
  }
37
- if (newCount > limit) {
29
+ const remaining = Math.max(0, limit - count);
30
+ const resetTime = await store.ttl(key);
31
+ set.headers = {
32
+ "X-RateLimit-Limit": limit.toString(),
33
+ "X-RateLimit-Remaining": remaining.toString(),
34
+ "X-RateLimit-Reset": resetTime.toString()
35
+ };
36
+ if (count > limit) {
38
37
  set.status = 429;
39
38
  throw new HttpError(RATE_LIMIT_ERROR_KEYS.RATE_LIMIT_EXCEEDED, "TOO_MANY_REQUESTS", {
40
39
  limit,
41
40
  window,
42
41
  remaining: 0,
43
- reset: await storeInstance.ttl(key)
42
+ reset: resetTime
44
43
  });
45
44
  }
46
- set.headers = {
47
- "X-RateLimit-Limit": limit.toString(),
48
- "X-RateLimit-Remaining": Math.max(0, limit - newCount).toString(),
49
- "X-RateLimit-Reset": (await storeInstance.ttl(key)).toString()
50
- };
45
+ };
46
+ return new Elysia({
47
+ name: "rateLimit",
48
+ seed: {
49
+ store
50
+ }
51
+ }).macro({
52
+ rateLimit: ({ limit, window }) => ({
53
+ transform: ({ request }) => {
54
+ const route = `${request.method}:${new URL(request.url).pathname}`;
55
+ if (!restrictedRoutes.has(route)) {
56
+ restrictedRoutes.set(route, { limit, window });
57
+ } else if (restrictedRoutes.has(route)) {
58
+ const existing = restrictedRoutes.get(route);
59
+ if (limit != existing.limit || window != existing.window)
60
+ restrictedRoutes.set(route, {
61
+ limit,
62
+ window
63
+ });
64
+ }
65
+ },
66
+ beforeHandle: async ({ set, request, server }) => {
67
+ const route = `${request.method}:${new URL(request.url).pathname}`;
68
+ if (restrictedRoutes.has(route)) {
69
+ const { limit: limit2, window: window2 } = restrictedRoutes.get(route);
70
+ const ip = request.headers.get("x-forwarded-for") || request.headers.get("x-real-ip") || server?.requestIP(request)?.address || "127.0.0.1";
71
+ const key = `ratelimit:${route}:${ip}`;
72
+ await rateLimitCheck(key, limit2, window2, set);
73
+ }
74
+ }
75
+ })
51
76
  }).as("global");
52
77
  };
53
78
  export {