@dexto/storage 1.6.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.
Files changed (158) hide show
  1. package/LICENSE +44 -0
  2. package/README.md +80 -0
  3. package/dist/blob/factories/index.cjs +31 -0
  4. package/dist/blob/factories/index.d.cts +6 -0
  5. package/dist/blob/factories/index.d.ts +6 -0
  6. package/dist/blob/factories/index.d.ts.map +1 -0
  7. package/dist/blob/factories/index.js +6 -0
  8. package/dist/blob/factories/local.cjs +38 -0
  9. package/dist/blob/factories/local.d.cts +21 -0
  10. package/dist/blob/factories/local.d.ts +17 -0
  11. package/dist/blob/factories/local.d.ts.map +1 -0
  12. package/dist/blob/factories/local.js +14 -0
  13. package/dist/blob/factories/memory.cjs +44 -0
  14. package/dist/blob/factories/memory.d.cts +21 -0
  15. package/dist/blob/factories/memory.d.ts +17 -0
  16. package/dist/blob/factories/memory.d.ts.map +1 -0
  17. package/dist/blob/factories/memory.js +20 -0
  18. package/dist/blob/factory.cjs +16 -0
  19. package/dist/blob/factory.d.cts +36 -0
  20. package/dist/blob/factory.d.ts +35 -0
  21. package/dist/blob/factory.d.ts.map +1 -0
  22. package/dist/blob/factory.js +0 -0
  23. package/dist/blob/index.cjs +45 -0
  24. package/dist/blob/index.d.cts +8 -0
  25. package/dist/blob/index.d.ts +26 -0
  26. package/dist/blob/index.d.ts.map +1 -0
  27. package/dist/blob/index.js +19 -0
  28. package/dist/blob/local-blob-store.cjs +532 -0
  29. package/dist/blob/local-blob-store.d.cts +56 -0
  30. package/dist/blob/local-blob-store.d.ts +54 -0
  31. package/dist/blob/local-blob-store.d.ts.map +1 -0
  32. package/dist/blob/local-blob-store.js +498 -0
  33. package/dist/blob/memory-blob-store.cjs +327 -0
  34. package/dist/blob/memory-blob-store.d.cts +69 -0
  35. package/dist/blob/memory-blob-store.d.ts +67 -0
  36. package/dist/blob/memory-blob-store.d.ts.map +1 -0
  37. package/dist/blob/memory-blob-store.js +303 -0
  38. package/dist/blob/schemas.cjs +52 -0
  39. package/dist/blob/schemas.d.cts +87 -0
  40. package/dist/blob/schemas.d.ts +86 -0
  41. package/dist/blob/schemas.d.ts.map +1 -0
  42. package/dist/blob/schemas.js +25 -0
  43. package/dist/blob/types.cjs +16 -0
  44. package/dist/blob/types.d.cts +1 -0
  45. package/dist/blob/types.d.ts +2 -0
  46. package/dist/blob/types.d.ts.map +1 -0
  47. package/dist/blob/types.js +0 -0
  48. package/dist/cache/factories/index.cjs +31 -0
  49. package/dist/cache/factories/index.d.cts +6 -0
  50. package/dist/cache/factories/index.d.ts +6 -0
  51. package/dist/cache/factories/index.d.ts.map +1 -0
  52. package/dist/cache/factories/index.js +6 -0
  53. package/dist/cache/factories/memory.cjs +39 -0
  54. package/dist/cache/factories/memory.d.cts +21 -0
  55. package/dist/cache/factories/memory.d.ts +17 -0
  56. package/dist/cache/factories/memory.d.ts.map +1 -0
  57. package/dist/cache/factories/memory.js +15 -0
  58. package/dist/cache/factories/redis.cjs +65 -0
  59. package/dist/cache/factories/redis.d.cts +24 -0
  60. package/dist/cache/factories/redis.d.ts +20 -0
  61. package/dist/cache/factories/redis.d.ts.map +1 -0
  62. package/dist/cache/factories/redis.js +31 -0
  63. package/dist/cache/factory.cjs +16 -0
  64. package/dist/cache/factory.d.cts +42 -0
  65. package/dist/cache/factory.d.ts +41 -0
  66. package/dist/cache/factory.d.ts.map +1 -0
  67. package/dist/cache/factory.js +0 -0
  68. package/dist/cache/index.cjs +42 -0
  69. package/dist/cache/index.d.cts +7 -0
  70. package/dist/cache/index.d.ts +25 -0
  71. package/dist/cache/index.d.ts.map +1 -0
  72. package/dist/cache/index.js +17 -0
  73. package/dist/cache/memory-cache-store.cjs +106 -0
  74. package/dist/cache/memory-cache-store.d.cts +27 -0
  75. package/dist/cache/memory-cache-store.d.ts +25 -0
  76. package/dist/cache/memory-cache-store.d.ts.map +1 -0
  77. package/dist/cache/memory-cache-store.js +82 -0
  78. package/dist/cache/redis-store.cjs +176 -0
  79. package/dist/cache/redis-store.d.cts +34 -0
  80. package/dist/cache/redis-store.d.ts +32 -0
  81. package/dist/cache/redis-store.d.ts.map +1 -0
  82. package/dist/cache/redis-store.js +152 -0
  83. package/dist/cache/schemas.cjs +70 -0
  84. package/dist/cache/schemas.d.cts +93 -0
  85. package/dist/cache/schemas.d.ts +91 -0
  86. package/dist/cache/schemas.d.ts.map +1 -0
  87. package/dist/cache/schemas.js +43 -0
  88. package/dist/cache/types.cjs +16 -0
  89. package/dist/cache/types.d.cts +1 -0
  90. package/dist/cache/types.d.ts +2 -0
  91. package/dist/cache/types.d.ts.map +1 -0
  92. package/dist/cache/types.js +0 -0
  93. package/dist/database/factories/index.cjs +34 -0
  94. package/dist/database/factories/index.d.cts +7 -0
  95. package/dist/database/factories/index.d.ts +7 -0
  96. package/dist/database/factories/index.d.ts.map +1 -0
  97. package/dist/database/factories/index.js +8 -0
  98. package/dist/database/factories/memory.cjs +39 -0
  99. package/dist/database/factories/memory.d.cts +20 -0
  100. package/dist/database/factories/memory.d.ts +16 -0
  101. package/dist/database/factories/memory.d.ts.map +1 -0
  102. package/dist/database/factories/memory.js +15 -0
  103. package/dist/database/factories/postgres.cjs +61 -0
  104. package/dist/database/factories/postgres.d.cts +23 -0
  105. package/dist/database/factories/postgres.d.ts +19 -0
  106. package/dist/database/factories/postgres.d.ts.map +1 -0
  107. package/dist/database/factories/postgres.js +27 -0
  108. package/dist/database/factories/sqlite.cjs +65 -0
  109. package/dist/database/factories/sqlite.d.cts +24 -0
  110. package/dist/database/factories/sqlite.d.ts +20 -0
  111. package/dist/database/factories/sqlite.d.ts.map +1 -0
  112. package/dist/database/factories/sqlite.js +31 -0
  113. package/dist/database/factory.cjs +16 -0
  114. package/dist/database/factory.d.cts +42 -0
  115. package/dist/database/factory.d.ts +41 -0
  116. package/dist/database/factory.d.ts.map +1 -0
  117. package/dist/database/factory.js +0 -0
  118. package/dist/database/index.cjs +46 -0
  119. package/dist/database/index.d.cts +8 -0
  120. package/dist/database/index.d.ts +26 -0
  121. package/dist/database/index.d.ts.map +1 -0
  122. package/dist/database/index.js +24 -0
  123. package/dist/database/memory-database-store.cjs +121 -0
  124. package/dist/database/memory-database-store.d.cts +30 -0
  125. package/dist/database/memory-database-store.d.ts +28 -0
  126. package/dist/database/memory-database-store.d.ts.map +1 -0
  127. package/dist/database/memory-database-store.js +97 -0
  128. package/dist/database/postgres-store.cjs +342 -0
  129. package/dist/database/postgres-store.d.cts +57 -0
  130. package/dist/database/postgres-store.d.ts +55 -0
  131. package/dist/database/postgres-store.d.ts.map +1 -0
  132. package/dist/database/postgres-store.js +318 -0
  133. package/dist/database/schemas.cjs +82 -0
  134. package/dist/database/schemas.d.cts +127 -0
  135. package/dist/database/schemas.d.ts +125 -0
  136. package/dist/database/schemas.d.ts.map +1 -0
  137. package/dist/database/schemas.js +54 -0
  138. package/dist/database/sqlite-store.cjs +270 -0
  139. package/dist/database/sqlite-store.d.cts +35 -0
  140. package/dist/database/sqlite-store.d.ts +33 -0
  141. package/dist/database/sqlite-store.d.ts.map +1 -0
  142. package/dist/database/sqlite-store.js +236 -0
  143. package/dist/database/types.cjs +16 -0
  144. package/dist/database/types.d.cts +1 -0
  145. package/dist/database/types.d.ts +2 -0
  146. package/dist/database/types.d.ts.map +1 -0
  147. package/dist/database/types.js +0 -0
  148. package/dist/index.cjs +82 -0
  149. package/dist/index.d.cts +24 -0
  150. package/dist/index.d.ts +25 -0
  151. package/dist/index.d.ts.map +1 -0
  152. package/dist/index.js +50 -0
  153. package/dist/schemas.cjs +67 -0
  154. package/dist/schemas.d.cts +72 -0
  155. package/dist/schemas.d.ts +70 -0
  156. package/dist/schemas.d.ts.map +1 -0
  157. package/dist/schemas.js +46 -0
  158. package/package.json +55 -0
@@ -0,0 +1,82 @@
1
+ import { StorageError } from "@dexto/core";
2
+ class MemoryCacheStore {
3
+ data = /* @__PURE__ */ new Map();
4
+ ttls = /* @__PURE__ */ new Map();
5
+ connected = false;
6
+ async connect() {
7
+ if (this.connected) return;
8
+ this.connected = true;
9
+ }
10
+ async disconnect() {
11
+ this.connected = false;
12
+ this.data.clear();
13
+ this.ttls.clear();
14
+ }
15
+ isConnected() {
16
+ return this.connected;
17
+ }
18
+ getStoreType() {
19
+ return "in-memory";
20
+ }
21
+ async get(key) {
22
+ this.checkConnection();
23
+ try {
24
+ this.checkTTL(key);
25
+ return this.data.get(key);
26
+ } catch (error) {
27
+ throw StorageError.readFailed(
28
+ "get",
29
+ error instanceof Error ? error.message : String(error),
30
+ { key }
31
+ );
32
+ }
33
+ }
34
+ async set(key, value, ttlSeconds) {
35
+ this.checkConnection();
36
+ try {
37
+ this.data.set(key, value);
38
+ if (ttlSeconds) {
39
+ this.ttls.set(key, Date.now() + ttlSeconds * 1e3);
40
+ } else {
41
+ this.ttls.delete(key);
42
+ }
43
+ } catch (error) {
44
+ throw StorageError.writeFailed(
45
+ "set",
46
+ error instanceof Error ? error.message : String(error),
47
+ { key }
48
+ );
49
+ }
50
+ }
51
+ async delete(key) {
52
+ this.checkConnection();
53
+ this.data.delete(key);
54
+ this.ttls.delete(key);
55
+ }
56
+ // Helper methods
57
+ checkConnection() {
58
+ if (!this.connected) {
59
+ throw StorageError.notConnected("MemoryCacheStore");
60
+ }
61
+ }
62
+ checkTTL(key) {
63
+ const expiry = this.ttls.get(key);
64
+ if (expiry && Date.now() > expiry) {
65
+ this.data.delete(key);
66
+ this.ttls.delete(key);
67
+ }
68
+ }
69
+ // Development helpers
70
+ async clear() {
71
+ this.data.clear();
72
+ this.ttls.clear();
73
+ }
74
+ async dump() {
75
+ return {
76
+ data: Object.fromEntries(this.data.entries())
77
+ };
78
+ }
79
+ }
80
+ export {
81
+ MemoryCacheStore
82
+ };
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var redis_store_exports = {};
20
+ __export(redis_store_exports, {
21
+ RedisStore: () => RedisStore
22
+ });
23
+ module.exports = __toCommonJS(redis_store_exports);
24
+ var import_ioredis = require("ioredis");
25
+ var import_core = require("@dexto/core");
26
+ class RedisStore {
27
+ constructor(config, logger) {
28
+ this.config = config;
29
+ this.logger = logger.createChild(import_core.DextoLogComponent.STORAGE);
30
+ }
31
+ redis = null;
32
+ connected = false;
33
+ logger;
34
+ async connect() {
35
+ if (this.connected) return;
36
+ this.redis = new import_ioredis.Redis({
37
+ ...this.config.host && { host: this.config.host },
38
+ ...this.config.port && { port: this.config.port },
39
+ ...this.config.password && { password: this.config.password },
40
+ db: this.config.database || 0,
41
+ family: 4,
42
+ // IPv4 by default
43
+ ...this.config.connectionTimeoutMillis && {
44
+ connectTimeout: this.config.connectionTimeoutMillis
45
+ },
46
+ ...this.config.connectionTimeoutMillis && {
47
+ commandTimeout: this.config.connectionTimeoutMillis
48
+ },
49
+ maxRetriesPerRequest: 3,
50
+ lazyConnect: true,
51
+ ...this.config.options
52
+ });
53
+ this.redis.on("error", (error) => {
54
+ if (error instanceof Error) {
55
+ this.logger.trackException(error, { operation: "redis.connection_error" });
56
+ return;
57
+ }
58
+ this.logger.error("Redis connection error", { error: String(error) });
59
+ });
60
+ this.redis.on("connect", () => {
61
+ this.connected = true;
62
+ });
63
+ this.redis.on("close", () => {
64
+ this.connected = false;
65
+ });
66
+ await this.redis.connect();
67
+ }
68
+ async disconnect() {
69
+ if (this.redis) {
70
+ await this.redis.quit();
71
+ this.redis = null;
72
+ }
73
+ this.connected = false;
74
+ }
75
+ isConnected() {
76
+ return this.connected && this.redis?.status === "ready";
77
+ }
78
+ getStoreType() {
79
+ return "redis";
80
+ }
81
+ // Core operations
82
+ async get(key) {
83
+ this.checkConnection();
84
+ try {
85
+ const value = await this.redis.get(key);
86
+ return value ? JSON.parse(value) : void 0;
87
+ } catch (error) {
88
+ throw import_core.StorageError.readFailed(
89
+ "get",
90
+ error instanceof Error ? error.message : String(error),
91
+ { key }
92
+ );
93
+ }
94
+ }
95
+ async set(key, value, ttlSeconds) {
96
+ this.checkConnection();
97
+ try {
98
+ const serialized = JSON.stringify(value);
99
+ if (ttlSeconds) {
100
+ await this.redis.setex(key, ttlSeconds, serialized);
101
+ } else {
102
+ await this.redis.set(key, serialized);
103
+ }
104
+ } catch (error) {
105
+ throw import_core.StorageError.writeFailed(
106
+ "set",
107
+ error instanceof Error ? error.message : String(error),
108
+ { key }
109
+ );
110
+ }
111
+ }
112
+ async delete(key) {
113
+ this.checkConnection();
114
+ try {
115
+ await this.redis.del(key);
116
+ } catch (error) {
117
+ throw import_core.StorageError.deleteFailed(
118
+ "delete",
119
+ error instanceof Error ? error.message : String(error),
120
+ { key }
121
+ );
122
+ }
123
+ }
124
+ // Redis-specific optimizations
125
+ async mget(keys) {
126
+ this.checkConnection();
127
+ if (keys.length === 0) return [];
128
+ const values = await this.redis.mget(...keys);
129
+ return values.map((value) => value ? JSON.parse(value) : void 0);
130
+ }
131
+ async mset(entries) {
132
+ this.checkConnection();
133
+ if (entries.length === 0) return;
134
+ const pipeline = this.redis.pipeline();
135
+ for (const [key, value] of entries) {
136
+ pipeline.set(key, JSON.stringify(value));
137
+ }
138
+ await pipeline.exec();
139
+ }
140
+ async exists(key) {
141
+ this.checkConnection();
142
+ const result = await this.redis.exists(key);
143
+ return result === 1;
144
+ }
145
+ async expire(key, ttlSeconds) {
146
+ this.checkConnection();
147
+ await this.redis.expire(key, ttlSeconds);
148
+ }
149
+ // Cache-specific operations
150
+ async increment(key, by = 1) {
151
+ this.checkConnection();
152
+ return await this.redis.incrby(key, by);
153
+ }
154
+ async decrement(key, by = 1) {
155
+ this.checkConnection();
156
+ return await this.redis.decrby(key, by);
157
+ }
158
+ checkConnection() {
159
+ if (!this.connected || !this.redis || this.redis.status !== "ready") {
160
+ throw import_core.StorageError.notConnected("RedisStore");
161
+ }
162
+ }
163
+ // Maintenance operations
164
+ async flushdb() {
165
+ this.checkConnection();
166
+ await this.redis.flushdb();
167
+ }
168
+ async info() {
169
+ this.checkConnection();
170
+ return await this.redis.info();
171
+ }
172
+ }
173
+ // Annotate the CommonJS export names for ESM import in node:
174
+ 0 && (module.exports = {
175
+ RedisStore
176
+ });
@@ -0,0 +1,34 @@
1
+ import { Cache, Logger } from '@dexto/core';
2
+ import { RedisCacheConfig } from './schemas.cjs';
3
+ import 'zod';
4
+
5
+ /**
6
+ * Redis cache store for production cache operations.
7
+ * Implements the Cache interface with connection pooling and optimizations.
8
+ * EXPERIMENTAL - NOT FULLY TESTED YET
9
+ */
10
+ declare class RedisStore implements Cache {
11
+ private config;
12
+ private redis;
13
+ private connected;
14
+ private logger;
15
+ constructor(config: RedisCacheConfig, logger: Logger);
16
+ connect(): Promise<void>;
17
+ disconnect(): Promise<void>;
18
+ isConnected(): boolean;
19
+ getStoreType(): string;
20
+ get<T>(key: string): Promise<T | undefined>;
21
+ set<T>(key: string, value: T, ttlSeconds?: number): Promise<void>;
22
+ delete(key: string): Promise<void>;
23
+ mget<T>(keys: string[]): Promise<(T | undefined)[]>;
24
+ mset<T>(entries: [string, T][]): Promise<void>;
25
+ exists(key: string): Promise<boolean>;
26
+ expire(key: string, ttlSeconds: number): Promise<void>;
27
+ increment(key: string, by?: number): Promise<number>;
28
+ decrement(key: string, by?: number): Promise<number>;
29
+ private checkConnection;
30
+ flushdb(): Promise<void>;
31
+ info(): Promise<string>;
32
+ }
33
+
34
+ export { RedisStore };
@@ -0,0 +1,32 @@
1
+ import type { Cache } from './types.js';
2
+ import type { RedisCacheConfig } from './schemas.js';
3
+ import type { Logger } from '@dexto/core';
4
+ /**
5
+ * Redis cache store for production cache operations.
6
+ * Implements the Cache interface with connection pooling and optimizations.
7
+ * EXPERIMENTAL - NOT FULLY TESTED YET
8
+ */
9
+ export declare class RedisStore implements Cache {
10
+ private config;
11
+ private redis;
12
+ private connected;
13
+ private logger;
14
+ constructor(config: RedisCacheConfig, logger: Logger);
15
+ connect(): Promise<void>;
16
+ disconnect(): Promise<void>;
17
+ isConnected(): boolean;
18
+ getStoreType(): string;
19
+ get<T>(key: string): Promise<T | undefined>;
20
+ set<T>(key: string, value: T, ttlSeconds?: number): Promise<void>;
21
+ delete(key: string): Promise<void>;
22
+ mget<T>(keys: string[]): Promise<(T | undefined)[]>;
23
+ mset<T>(entries: [string, T][]): Promise<void>;
24
+ exists(key: string): Promise<boolean>;
25
+ expire(key: string, ttlSeconds: number): Promise<void>;
26
+ increment(key: string, by?: number): Promise<number>;
27
+ decrement(key: string, by?: number): Promise<number>;
28
+ private checkConnection;
29
+ flushdb(): Promise<void>;
30
+ info(): Promise<string>;
31
+ }
32
+ //# sourceMappingURL=redis-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis-store.d.ts","sourceRoot":"","sources":["../../src/cache/redis-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG1C;;;;GAIG;AACH,qBAAa,UAAW,YAAW,KAAK;IAMhC,OAAO,CAAC,MAAM;IALlB,OAAO,CAAC,KAAK,CAAsB;IACnC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAS;gBAGX,MAAM,EAAE,gBAAgB,EAChC,MAAM,EAAE,MAAM;IAKZ,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAwCxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQjC,WAAW,IAAI,OAAO;IAItB,YAAY,IAAI,MAAM;IAKhB,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAc3C,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBjE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAclC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC;IAQnD,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAW9C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMrC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtD,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,GAAE,MAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAKvD,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,GAAE,MAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAK7D,OAAO,CAAC,eAAe;IAOjB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAKxB,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;CAIhC"}
@@ -0,0 +1,152 @@
1
+ import { Redis } from "ioredis";
2
+ import { DextoLogComponent, StorageError } from "@dexto/core";
3
+ class RedisStore {
4
+ constructor(config, logger) {
5
+ this.config = config;
6
+ this.logger = logger.createChild(DextoLogComponent.STORAGE);
7
+ }
8
+ redis = null;
9
+ connected = false;
10
+ logger;
11
+ async connect() {
12
+ if (this.connected) return;
13
+ this.redis = new Redis({
14
+ ...this.config.host && { host: this.config.host },
15
+ ...this.config.port && { port: this.config.port },
16
+ ...this.config.password && { password: this.config.password },
17
+ db: this.config.database || 0,
18
+ family: 4,
19
+ // IPv4 by default
20
+ ...this.config.connectionTimeoutMillis && {
21
+ connectTimeout: this.config.connectionTimeoutMillis
22
+ },
23
+ ...this.config.connectionTimeoutMillis && {
24
+ commandTimeout: this.config.connectionTimeoutMillis
25
+ },
26
+ maxRetriesPerRequest: 3,
27
+ lazyConnect: true,
28
+ ...this.config.options
29
+ });
30
+ this.redis.on("error", (error) => {
31
+ if (error instanceof Error) {
32
+ this.logger.trackException(error, { operation: "redis.connection_error" });
33
+ return;
34
+ }
35
+ this.logger.error("Redis connection error", { error: String(error) });
36
+ });
37
+ this.redis.on("connect", () => {
38
+ this.connected = true;
39
+ });
40
+ this.redis.on("close", () => {
41
+ this.connected = false;
42
+ });
43
+ await this.redis.connect();
44
+ }
45
+ async disconnect() {
46
+ if (this.redis) {
47
+ await this.redis.quit();
48
+ this.redis = null;
49
+ }
50
+ this.connected = false;
51
+ }
52
+ isConnected() {
53
+ return this.connected && this.redis?.status === "ready";
54
+ }
55
+ getStoreType() {
56
+ return "redis";
57
+ }
58
+ // Core operations
59
+ async get(key) {
60
+ this.checkConnection();
61
+ try {
62
+ const value = await this.redis.get(key);
63
+ return value ? JSON.parse(value) : void 0;
64
+ } catch (error) {
65
+ throw StorageError.readFailed(
66
+ "get",
67
+ error instanceof Error ? error.message : String(error),
68
+ { key }
69
+ );
70
+ }
71
+ }
72
+ async set(key, value, ttlSeconds) {
73
+ this.checkConnection();
74
+ try {
75
+ const serialized = JSON.stringify(value);
76
+ if (ttlSeconds) {
77
+ await this.redis.setex(key, ttlSeconds, serialized);
78
+ } else {
79
+ await this.redis.set(key, serialized);
80
+ }
81
+ } catch (error) {
82
+ throw StorageError.writeFailed(
83
+ "set",
84
+ error instanceof Error ? error.message : String(error),
85
+ { key }
86
+ );
87
+ }
88
+ }
89
+ async delete(key) {
90
+ this.checkConnection();
91
+ try {
92
+ await this.redis.del(key);
93
+ } catch (error) {
94
+ throw StorageError.deleteFailed(
95
+ "delete",
96
+ error instanceof Error ? error.message : String(error),
97
+ { key }
98
+ );
99
+ }
100
+ }
101
+ // Redis-specific optimizations
102
+ async mget(keys) {
103
+ this.checkConnection();
104
+ if (keys.length === 0) return [];
105
+ const values = await this.redis.mget(...keys);
106
+ return values.map((value) => value ? JSON.parse(value) : void 0);
107
+ }
108
+ async mset(entries) {
109
+ this.checkConnection();
110
+ if (entries.length === 0) return;
111
+ const pipeline = this.redis.pipeline();
112
+ for (const [key, value] of entries) {
113
+ pipeline.set(key, JSON.stringify(value));
114
+ }
115
+ await pipeline.exec();
116
+ }
117
+ async exists(key) {
118
+ this.checkConnection();
119
+ const result = await this.redis.exists(key);
120
+ return result === 1;
121
+ }
122
+ async expire(key, ttlSeconds) {
123
+ this.checkConnection();
124
+ await this.redis.expire(key, ttlSeconds);
125
+ }
126
+ // Cache-specific operations
127
+ async increment(key, by = 1) {
128
+ this.checkConnection();
129
+ return await this.redis.incrby(key, by);
130
+ }
131
+ async decrement(key, by = 1) {
132
+ this.checkConnection();
133
+ return await this.redis.decrby(key, by);
134
+ }
135
+ checkConnection() {
136
+ if (!this.connected || !this.redis || this.redis.status !== "ready") {
137
+ throw StorageError.notConnected("RedisStore");
138
+ }
139
+ }
140
+ // Maintenance operations
141
+ async flushdb() {
142
+ this.checkConnection();
143
+ await this.redis.flushdb();
144
+ }
145
+ async info() {
146
+ this.checkConnection();
147
+ return await this.redis.info();
148
+ }
149
+ }
150
+ export {
151
+ RedisStore
152
+ };
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var schemas_exports = {};
20
+ __export(schemas_exports, {
21
+ CACHE_TYPES: () => CACHE_TYPES,
22
+ CacheConfigSchema: () => CacheConfigSchema,
23
+ InMemoryCacheSchema: () => InMemoryCacheSchema,
24
+ RedisCacheSchema: () => RedisCacheSchema
25
+ });
26
+ module.exports = __toCommonJS(schemas_exports);
27
+ var import_zod = require("zod");
28
+ var import_core = require("@dexto/core");
29
+ const CACHE_TYPES = ["in-memory", "redis"];
30
+ const BaseCacheSchema = import_zod.z.object({
31
+ maxConnections: import_zod.z.number().int().positive().optional().describe("Maximum connections"),
32
+ idleTimeoutMillis: import_zod.z.number().int().positive().optional().describe("Idle timeout in milliseconds"),
33
+ connectionTimeoutMillis: import_zod.z.number().int().positive().optional().describe("Connection timeout in milliseconds"),
34
+ options: import_zod.z.record(import_zod.z.unknown()).optional().describe("Backend-specific options")
35
+ });
36
+ const InMemoryCacheSchema = BaseCacheSchema.extend({
37
+ type: import_zod.z.literal("in-memory")
38
+ // In-memory cache doesn't need connection options, but inherits pool options for consistency
39
+ }).strict();
40
+ const RedisCacheSchema = BaseCacheSchema.extend({
41
+ type: import_zod.z.literal("redis"),
42
+ url: (0, import_core.EnvExpandedString)().optional().describe("Redis connection URL (redis://...)"),
43
+ host: import_zod.z.string().optional().describe("Redis host"),
44
+ port: import_zod.z.number().int().positive().optional().describe("Redis port"),
45
+ password: import_zod.z.string().optional().describe("Redis password"),
46
+ database: import_zod.z.number().int().nonnegative().optional().describe("Redis database number")
47
+ }).strict().superRefine((data, ctx) => {
48
+ if (!data.url && !data.host) {
49
+ ctx.addIssue({
50
+ code: import_zod.z.ZodIssueCode.custom,
51
+ message: "Redis cache requires either 'url' or 'host' to be specified",
52
+ path: ["url"],
53
+ params: {
54
+ code: import_core.StorageErrorCode.CONNECTION_CONFIG_MISSING,
55
+ scope: import_core.ErrorScope.STORAGE,
56
+ type: import_core.ErrorType.USER
57
+ }
58
+ });
59
+ }
60
+ });
61
+ const CacheConfigSchema = import_zod.z.object({
62
+ type: import_zod.z.string().describe("Cache backend type identifier")
63
+ }).passthrough().describe("Cache configuration (validated by image factory)");
64
+ // Annotate the CommonJS export names for ESM import in node:
65
+ 0 && (module.exports = {
66
+ CACHE_TYPES,
67
+ CacheConfigSchema,
68
+ InMemoryCacheSchema,
69
+ RedisCacheSchema
70
+ });
@@ -0,0 +1,93 @@
1
+ import { z } from 'zod';
2
+
3
+ declare const CACHE_TYPES: readonly ["in-memory", "redis"];
4
+ type CacheType = (typeof CACHE_TYPES)[number];
5
+ declare const InMemoryCacheSchema: z.ZodObject<{
6
+ maxConnections: z.ZodOptional<z.ZodNumber>;
7
+ idleTimeoutMillis: z.ZodOptional<z.ZodNumber>;
8
+ connectionTimeoutMillis: z.ZodOptional<z.ZodNumber>;
9
+ options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
10
+ } & {
11
+ type: z.ZodLiteral<"in-memory">;
12
+ }, "strict", z.ZodTypeAny, {
13
+ type: "in-memory";
14
+ maxConnections?: number | undefined;
15
+ idleTimeoutMillis?: number | undefined;
16
+ connectionTimeoutMillis?: number | undefined;
17
+ options?: Record<string, unknown> | undefined;
18
+ }, {
19
+ type: "in-memory";
20
+ maxConnections?: number | undefined;
21
+ idleTimeoutMillis?: number | undefined;
22
+ connectionTimeoutMillis?: number | undefined;
23
+ options?: Record<string, unknown> | undefined;
24
+ }>;
25
+ type InMemoryCacheConfig = z.output<typeof InMemoryCacheSchema>;
26
+ declare const RedisCacheSchema: z.ZodEffects<z.ZodObject<{
27
+ maxConnections: z.ZodOptional<z.ZodNumber>;
28
+ idleTimeoutMillis: z.ZodOptional<z.ZodNumber>;
29
+ connectionTimeoutMillis: z.ZodOptional<z.ZodNumber>;
30
+ options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
31
+ } & {
32
+ type: z.ZodLiteral<"redis">;
33
+ url: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
34
+ host: z.ZodOptional<z.ZodString>;
35
+ port: z.ZodOptional<z.ZodNumber>;
36
+ password: z.ZodOptional<z.ZodString>;
37
+ database: z.ZodOptional<z.ZodNumber>;
38
+ }, "strict", z.ZodTypeAny, {
39
+ type: "redis";
40
+ maxConnections?: number | undefined;
41
+ idleTimeoutMillis?: number | undefined;
42
+ connectionTimeoutMillis?: number | undefined;
43
+ options?: Record<string, unknown> | undefined;
44
+ url?: string | undefined;
45
+ host?: string | undefined;
46
+ port?: number | undefined;
47
+ password?: string | undefined;
48
+ database?: number | undefined;
49
+ }, {
50
+ type: "redis";
51
+ maxConnections?: number | undefined;
52
+ idleTimeoutMillis?: number | undefined;
53
+ connectionTimeoutMillis?: number | undefined;
54
+ options?: Record<string, unknown> | undefined;
55
+ url?: string | undefined;
56
+ host?: string | undefined;
57
+ port?: number | undefined;
58
+ password?: string | undefined;
59
+ database?: number | undefined;
60
+ }>, {
61
+ type: "redis";
62
+ maxConnections?: number | undefined;
63
+ idleTimeoutMillis?: number | undefined;
64
+ connectionTimeoutMillis?: number | undefined;
65
+ options?: Record<string, unknown> | undefined;
66
+ url?: string | undefined;
67
+ host?: string | undefined;
68
+ port?: number | undefined;
69
+ password?: string | undefined;
70
+ database?: number | undefined;
71
+ }, {
72
+ type: "redis";
73
+ maxConnections?: number | undefined;
74
+ idleTimeoutMillis?: number | undefined;
75
+ connectionTimeoutMillis?: number | undefined;
76
+ options?: Record<string, unknown> | undefined;
77
+ url?: string | undefined;
78
+ host?: string | undefined;
79
+ port?: number | undefined;
80
+ password?: string | undefined;
81
+ database?: number | undefined;
82
+ }>;
83
+ type RedisCacheConfig = z.output<typeof RedisCacheSchema>;
84
+ declare const CacheConfigSchema: z.ZodObject<{
85
+ type: z.ZodString;
86
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
87
+ type: z.ZodString;
88
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
89
+ type: z.ZodString;
90
+ }, z.ZodTypeAny, "passthrough">>;
91
+ type CacheConfig = z.output<typeof CacheConfigSchema>;
92
+
93
+ export { CACHE_TYPES, type CacheConfig, CacheConfigSchema, type CacheType, type InMemoryCacheConfig, InMemoryCacheSchema, type RedisCacheConfig, RedisCacheSchema };