@serve.zone/dcrouter 11.23.5 → 12.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/dist_serve/bundle.js +1 -1
- package/dist_ts/00_commitinfo_data.js +2 -2
- package/dist_ts/classes.cert-provision-scheduler.d.ts +6 -8
- package/dist_ts/classes.cert-provision-scheduler.js +37 -17
- package/dist_ts/classes.dcrouter.d.ts +15 -29
- package/dist_ts/classes.dcrouter.js +96 -91
- package/dist_ts/classes.storage-cert-manager.d.ts +3 -6
- package/dist_ts/classes.storage-cert-manager.js +35 -25
- package/dist_ts/config/classes.api-token-manager.d.ts +1 -3
- package/dist_ts/config/classes.api-token-manager.js +45 -15
- package/dist_ts/config/classes.route-config-manager.d.ts +1 -3
- package/dist_ts/config/classes.route-config-manager.js +62 -24
- package/dist_ts/{cache → db}/classes.cache.cleaner.d.ts +3 -3
- package/dist_ts/db/classes.cache.cleaner.js +130 -0
- package/dist_ts/{cache → db}/classes.cached.document.js +1 -1
- package/dist_ts/db/classes.dcrouter-db.d.ts +70 -0
- package/dist_ts/db/classes.dcrouter-db.js +146 -0
- package/dist_ts/db/documents/classes.accounting-session.doc.d.ts +32 -0
- package/dist_ts/db/documents/classes.accounting-session.doc.js +214 -0
- package/dist_ts/db/documents/classes.acme-cert.doc.d.ts +13 -0
- package/dist_ts/db/documents/classes.acme-cert.doc.js +109 -0
- package/dist_ts/db/documents/classes.api-token.doc.d.ts +18 -0
- package/dist_ts/db/documents/classes.api-token.doc.js +127 -0
- package/dist_ts/{cache → db}/documents/classes.cached.email.js +3 -3
- package/dist_ts/{cache → db}/documents/classes.cached.ip.reputation.js +3 -3
- package/dist_ts/db/documents/classes.cert-backoff.doc.d.ts +11 -0
- package/dist_ts/db/documents/classes.cert-backoff.doc.js +97 -0
- package/dist_ts/db/documents/classes.proxy-cert.doc.d.ts +12 -0
- package/dist_ts/db/documents/classes.proxy-cert.doc.js +103 -0
- package/dist_ts/db/documents/classes.remote-ingress-edge.doc.d.ts +17 -0
- package/dist_ts/db/documents/classes.remote-ingress-edge.doc.js +130 -0
- package/dist_ts/db/documents/classes.route-override.doc.d.ts +10 -0
- package/dist_ts/db/documents/classes.route-override.doc.js +91 -0
- package/dist_ts/db/documents/classes.stored-route.doc.d.ts +12 -0
- package/dist_ts/db/documents/classes.stored-route.doc.js +103 -0
- package/dist_ts/db/documents/classes.vlan-mappings.doc.d.ts +15 -0
- package/dist_ts/db/documents/classes.vlan-mappings.doc.js +77 -0
- package/dist_ts/db/documents/classes.vpn-client.doc.d.ts +18 -0
- package/dist_ts/db/documents/classes.vpn-client.doc.js +136 -0
- package/dist_ts/db/documents/classes.vpn-server-keys.doc.d.ts +10 -0
- package/dist_ts/db/documents/classes.vpn-server-keys.doc.js +94 -0
- package/dist_ts/db/documents/index.d.ts +13 -0
- package/dist_ts/db/documents/index.js +20 -0
- package/dist_ts/{cache → db}/index.d.ts +1 -1
- package/dist_ts/db/index.js +9 -0
- package/dist_ts/opsserver/handlers/certificate.handler.js +66 -66
- package/dist_ts/opsserver/handlers/config.handler.js +14 -15
- package/dist_ts/paths.d.ts +0 -1
- package/dist_ts/paths.js +1 -2
- package/dist_ts/radius/classes.accounting.manager.d.ts +4 -12
- package/dist_ts/radius/classes.accounting.manager.js +80 -93
- package/dist_ts/radius/classes.radius.server.d.ts +1 -3
- package/dist_ts/radius/classes.radius.server.js +4 -6
- package/dist_ts/radius/classes.vlan.manager.d.ts +3 -7
- package/dist_ts/radius/classes.vlan.manager.js +21 -28
- package/dist_ts/radius/index.d.ts +1 -1
- package/dist_ts/radius/index.js +1 -1
- package/dist_ts/remoteingress/classes.remoteingress-manager.d.ts +3 -5
- package/dist_ts/remoteingress/classes.remoteingress-manager.js +41 -21
- package/dist_ts/security/classes.ipreputationchecker.d.ts +6 -21
- package/dist_ts/security/classes.ipreputationchecker.js +59 -138
- package/dist_ts/vpn/classes.vpn-manager.d.ts +4 -22
- package/dist_ts/vpn/classes.vpn-manager.js +40 -45
- package/dist_ts_oci_container/index.js +4 -4
- package/dist_ts_web/00_commitinfo_data.js +2 -2
- package/package.json +1 -1
- package/readme.storage.md +55 -91
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.cert-provision-scheduler.ts +35 -17
- package/ts/classes.dcrouter.ts +113 -125
- package/ts/classes.storage-cert-manager.ts +34 -22
- package/ts/config/classes.api-token-manager.ts +42 -11
- package/ts/config/classes.route-config-manager.ts +56 -21
- package/ts/{cache → db}/classes.cache.cleaner.ts +6 -6
- package/ts/db/classes.dcrouter-db.ts +179 -0
- package/ts/db/documents/classes.accounting-session.doc.ts +106 -0
- package/ts/db/documents/classes.acme-cert.doc.ts +41 -0
- package/ts/db/documents/classes.api-token.doc.ts +56 -0
- package/ts/{cache → db}/documents/classes.cached.email.ts +2 -2
- package/ts/{cache → db}/documents/classes.cached.ip.reputation.ts +2 -2
- package/ts/db/documents/classes.cert-backoff.doc.ts +35 -0
- package/ts/db/documents/classes.proxy-cert.doc.ts +38 -0
- package/ts/db/documents/classes.remote-ingress-edge.doc.ts +54 -0
- package/ts/db/documents/classes.route-override.doc.ts +32 -0
- package/ts/db/documents/classes.stored-route.doc.ts +38 -0
- package/ts/db/documents/classes.vlan-mappings.doc.ts +32 -0
- package/ts/db/documents/classes.vpn-client.doc.ts +57 -0
- package/ts/db/documents/classes.vpn-server-keys.doc.ts +31 -0
- package/ts/db/documents/index.ts +24 -0
- package/ts/{cache → db}/index.ts +6 -2
- package/ts/opsserver/handlers/certificate.handler.ts +67 -65
- package/ts/opsserver/handlers/config.handler.ts +13 -14
- package/ts/paths.ts +0 -1
- package/ts/radius/classes.accounting.manager.ts +81 -103
- package/ts/radius/classes.radius.server.ts +3 -6
- package/ts/radius/classes.vlan.manager.ts +20 -32
- package/ts/radius/index.ts +1 -1
- package/ts/remoteingress/classes.remoteingress-manager.ts +40 -22
- package/ts/security/classes.ipreputationchecker.ts +103 -196
- package/ts/vpn/classes.vpn-manager.ts +44 -75
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/dist_ts/cache/classes.cache.cleaner.js +0 -130
- package/dist_ts/cache/classes.cachedb.d.ts +0 -60
- package/dist_ts/cache/classes.cachedb.js +0 -126
- package/dist_ts/cache/documents/index.d.ts +0 -2
- package/dist_ts/cache/documents/index.js +0 -3
- package/dist_ts/cache/index.js +0 -7
- package/dist_ts/storage/classes.storagemanager.d.ts +0 -83
- package/dist_ts/storage/classes.storagemanager.js +0 -348
- package/dist_ts/storage/index.d.ts +0 -1
- package/dist_ts/storage/index.js +0 -3
- package/ts/cache/classes.cachedb.ts +0 -155
- package/ts/cache/documents/index.ts +0 -2
- package/ts/storage/classes.storagemanager.ts +0 -404
- package/ts/storage/index.ts +0 -2
- /package/dist_ts/{cache → db}/classes.cached.document.d.ts +0 -0
- /package/dist_ts/{cache → db}/documents/classes.cached.email.d.ts +0 -0
- /package/dist_ts/{cache → db}/documents/classes.cached.ip.reputation.d.ts +0 -0
- /package/ts/{cache → db}/classes.cached.document.ts +0 -0
|
@@ -1,404 +0,0 @@
|
|
|
1
|
-
import * as plugins from '../plugins.js';
|
|
2
|
-
import { logger } from '../logger.js';
|
|
3
|
-
|
|
4
|
-
// Promisify filesystem operations
|
|
5
|
-
const readFile = plugins.util.promisify(plugins.fs.readFile);
|
|
6
|
-
const writeFile = plugins.util.promisify(plugins.fs.writeFile);
|
|
7
|
-
const unlink = plugins.util.promisify(plugins.fs.unlink);
|
|
8
|
-
const rename = plugins.util.promisify(plugins.fs.rename);
|
|
9
|
-
const readdir = plugins.util.promisify(plugins.fs.readdir);
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Storage configuration interface
|
|
13
|
-
*/
|
|
14
|
-
export interface IStorageConfig {
|
|
15
|
-
/** Filesystem path for storage */
|
|
16
|
-
fsPath?: string;
|
|
17
|
-
/** Custom read function */
|
|
18
|
-
readFunction?: (key: string) => Promise<string | null>;
|
|
19
|
-
/** Custom write function */
|
|
20
|
-
writeFunction?: (key: string, value: string) => Promise<void>;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Storage backend type
|
|
25
|
-
*/
|
|
26
|
-
export type StorageBackend = 'filesystem' | 'custom' | 'memory';
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Central storage manager for DcRouter
|
|
30
|
-
* Provides unified key-value storage with multiple backend support
|
|
31
|
-
*/
|
|
32
|
-
export class StorageManager {
|
|
33
|
-
private static readonly MAX_MEMORY_ENTRIES = 10_000;
|
|
34
|
-
private backend: StorageBackend;
|
|
35
|
-
private memoryStore: Map<string, string> = new Map();
|
|
36
|
-
private config: IStorageConfig;
|
|
37
|
-
private fsBasePath?: string;
|
|
38
|
-
|
|
39
|
-
constructor(config?: IStorageConfig) {
|
|
40
|
-
this.config = config || {};
|
|
41
|
-
|
|
42
|
-
// Check if both fsPath and custom functions are provided
|
|
43
|
-
if (config?.fsPath && (config?.readFunction || config?.writeFunction)) {
|
|
44
|
-
console.warn(
|
|
45
|
-
'⚠️ WARNING: Both fsPath and custom read/write functions are configured.\n' +
|
|
46
|
-
' Using custom read/write functions. fsPath will be ignored.'
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Determine backend based on configuration
|
|
51
|
-
if (config?.readFunction && config?.writeFunction) {
|
|
52
|
-
this.backend = 'custom';
|
|
53
|
-
} else if (config?.fsPath) {
|
|
54
|
-
// Set up internal read/write functions for filesystem
|
|
55
|
-
this.backend = 'custom'; // Use custom backend with internal functions
|
|
56
|
-
this.fsBasePath = plugins.path.resolve(config.fsPath);
|
|
57
|
-
this.ensureDirectory(this.fsBasePath);
|
|
58
|
-
|
|
59
|
-
// Set up internal filesystem read/write functions
|
|
60
|
-
this.config.readFunction = (key: string): Promise<string | null> => this.fsRead(key);
|
|
61
|
-
this.config.writeFunction = async (key: string, value: string) => {
|
|
62
|
-
await this.fsWrite(key, value);
|
|
63
|
-
};
|
|
64
|
-
} else {
|
|
65
|
-
this.backend = 'memory';
|
|
66
|
-
this.showMemoryWarning();
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
logger.log('info', `StorageManager initialized with ${this.backend} backend`);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Show warning when using memory backend
|
|
74
|
-
*/
|
|
75
|
-
private showMemoryWarning(): void {
|
|
76
|
-
console.warn(
|
|
77
|
-
'⚠️ WARNING: StorageManager is using in-memory storage.\n' +
|
|
78
|
-
' Data will be lost when the process restarts.\n' +
|
|
79
|
-
' Configure storage.fsPath or storage functions for persistence.'
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Ensure directory exists for filesystem backend
|
|
85
|
-
*/
|
|
86
|
-
private async ensureDirectory(dirPath: string): Promise<void> {
|
|
87
|
-
try {
|
|
88
|
-
await plugins.fsUtils.ensureDir(dirPath);
|
|
89
|
-
} catch (error: unknown) {
|
|
90
|
-
logger.log('error', `Failed to create storage directory: ${(error as Error).message}`);
|
|
91
|
-
throw error;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Validate and sanitize storage key
|
|
97
|
-
*/
|
|
98
|
-
private validateKey(key: string): string {
|
|
99
|
-
if (!key || typeof key !== 'string') {
|
|
100
|
-
throw new Error('Storage key must be a non-empty string');
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Ensure key starts with /
|
|
104
|
-
if (!key.startsWith('/')) {
|
|
105
|
-
key = '/' + key;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Remove any dangerous path elements
|
|
109
|
-
key = key.replace(/\.\./g, '').replace(/\/+/g, '/');
|
|
110
|
-
|
|
111
|
-
return key;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Convert key to filesystem path
|
|
116
|
-
*/
|
|
117
|
-
private keyToPath(key: string): string {
|
|
118
|
-
if (!this.fsBasePath) {
|
|
119
|
-
throw new Error('Filesystem base path not configured');
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Remove leading slash and convert to path
|
|
123
|
-
const relativePath = key.substring(1);
|
|
124
|
-
return plugins.path.join(this.fsBasePath, relativePath);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Internal filesystem read function
|
|
129
|
-
*/
|
|
130
|
-
private async fsRead(key: string): Promise<string | null> {
|
|
131
|
-
const filePath = this.keyToPath(key);
|
|
132
|
-
try {
|
|
133
|
-
const content = await readFile(filePath, 'utf8');
|
|
134
|
-
return content;
|
|
135
|
-
} catch (error: unknown) {
|
|
136
|
-
if ((error as any).code === 'ENOENT') {
|
|
137
|
-
return null;
|
|
138
|
-
}
|
|
139
|
-
throw error;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Internal filesystem write function
|
|
145
|
-
*/
|
|
146
|
-
private async fsWrite(key: string, value: string): Promise<void> {
|
|
147
|
-
const filePath = this.keyToPath(key);
|
|
148
|
-
const dir = plugins.path.dirname(filePath);
|
|
149
|
-
|
|
150
|
-
// Ensure directory exists
|
|
151
|
-
await plugins.fsUtils.ensureDir(dir);
|
|
152
|
-
|
|
153
|
-
// Write atomically with temp file
|
|
154
|
-
const tempPath = `${filePath}.tmp`;
|
|
155
|
-
await writeFile(tempPath, value, 'utf8');
|
|
156
|
-
await rename(tempPath, filePath);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Get value by key
|
|
161
|
-
*/
|
|
162
|
-
async get(key: string): Promise<string | null> {
|
|
163
|
-
key = this.validateKey(key);
|
|
164
|
-
|
|
165
|
-
try {
|
|
166
|
-
switch (this.backend) {
|
|
167
|
-
|
|
168
|
-
case 'custom': {
|
|
169
|
-
if (!this.config.readFunction) {
|
|
170
|
-
throw new Error('Read function not configured');
|
|
171
|
-
}
|
|
172
|
-
try {
|
|
173
|
-
return await this.config.readFunction(key);
|
|
174
|
-
} catch (error) {
|
|
175
|
-
// Assume null if read fails (key doesn't exist)
|
|
176
|
-
return null;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
case 'memory': {
|
|
181
|
-
return this.memoryStore.get(key) || null;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
default:
|
|
185
|
-
throw new Error(`Unknown backend: ${this.backend}`);
|
|
186
|
-
}
|
|
187
|
-
} catch (error: unknown) {
|
|
188
|
-
logger.log('error', `Storage get error for key ${key}: ${(error as Error).message}`);
|
|
189
|
-
throw error;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Set value by key
|
|
195
|
-
*/
|
|
196
|
-
async set(key: string, value: string): Promise<void> {
|
|
197
|
-
key = this.validateKey(key);
|
|
198
|
-
|
|
199
|
-
if (typeof value !== 'string') {
|
|
200
|
-
throw new Error('Storage value must be a string');
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
try {
|
|
204
|
-
switch (this.backend) {
|
|
205
|
-
case 'filesystem': {
|
|
206
|
-
const filePath = this.keyToPath(key);
|
|
207
|
-
const dirPath = plugins.path.dirname(filePath);
|
|
208
|
-
|
|
209
|
-
// Ensure directory exists
|
|
210
|
-
await plugins.fsUtils.ensureDir(dirPath);
|
|
211
|
-
|
|
212
|
-
// Write atomically
|
|
213
|
-
const tempPath = filePath + '.tmp';
|
|
214
|
-
await writeFile(tempPath, value, 'utf8');
|
|
215
|
-
await rename(tempPath, filePath);
|
|
216
|
-
break;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
case 'custom': {
|
|
220
|
-
if (!this.config.writeFunction) {
|
|
221
|
-
throw new Error('Write function not configured');
|
|
222
|
-
}
|
|
223
|
-
await this.config.writeFunction(key, value);
|
|
224
|
-
break;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
case 'memory': {
|
|
228
|
-
this.memoryStore.set(key, value);
|
|
229
|
-
// Evict oldest entries if memory store exceeds limit
|
|
230
|
-
while (this.memoryStore.size > StorageManager.MAX_MEMORY_ENTRIES) {
|
|
231
|
-
const firstKey = this.memoryStore.keys().next().value!;
|
|
232
|
-
this.memoryStore.delete(firstKey);
|
|
233
|
-
}
|
|
234
|
-
break;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
default:
|
|
238
|
-
throw new Error(`Unknown backend: ${this.backend}`);
|
|
239
|
-
}
|
|
240
|
-
} catch (error: unknown) {
|
|
241
|
-
logger.log('error', `Storage set error for key ${key}: ${(error as Error).message}`);
|
|
242
|
-
throw error;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Delete value by key
|
|
248
|
-
*/
|
|
249
|
-
async delete(key: string): Promise<void> {
|
|
250
|
-
key = this.validateKey(key);
|
|
251
|
-
|
|
252
|
-
try {
|
|
253
|
-
switch (this.backend) {
|
|
254
|
-
case 'filesystem': {
|
|
255
|
-
const filePath = this.keyToPath(key);
|
|
256
|
-
try {
|
|
257
|
-
await unlink(filePath);
|
|
258
|
-
} catch (error: unknown) {
|
|
259
|
-
if ((error as any).code !== 'ENOENT') {
|
|
260
|
-
throw error;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
break;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
case 'custom': {
|
|
267
|
-
// Try to delete by setting empty value
|
|
268
|
-
if (this.config.writeFunction) {
|
|
269
|
-
await this.config.writeFunction(key, '');
|
|
270
|
-
}
|
|
271
|
-
break;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
case 'memory': {
|
|
275
|
-
this.memoryStore.delete(key);
|
|
276
|
-
break;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
default:
|
|
280
|
-
throw new Error(`Unknown backend: ${this.backend}`);
|
|
281
|
-
}
|
|
282
|
-
} catch (error: unknown) {
|
|
283
|
-
logger.log('error', `Storage delete error for key ${key}: ${(error as Error).message}`);
|
|
284
|
-
throw error;
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* List keys by prefix
|
|
290
|
-
*/
|
|
291
|
-
async list(prefix?: string): Promise<string[]> {
|
|
292
|
-
prefix = prefix ? this.validateKey(prefix) : '/';
|
|
293
|
-
|
|
294
|
-
try {
|
|
295
|
-
switch (this.backend) {
|
|
296
|
-
case 'custom': {
|
|
297
|
-
// If we have fsBasePath, this is actually filesystem backend
|
|
298
|
-
if (this.fsBasePath) {
|
|
299
|
-
const basePath = this.keyToPath(prefix);
|
|
300
|
-
const keys: string[] = [];
|
|
301
|
-
|
|
302
|
-
const walkDir = async (dir: string, baseDir: string): Promise<void> => {
|
|
303
|
-
try {
|
|
304
|
-
const entries = await readdir(dir, { withFileTypes: true });
|
|
305
|
-
|
|
306
|
-
for (const entry of entries) {
|
|
307
|
-
const fullPath = plugins.path.join(dir, entry.name);
|
|
308
|
-
|
|
309
|
-
if (entry.isDirectory()) {
|
|
310
|
-
await walkDir(fullPath, baseDir);
|
|
311
|
-
} else if (entry.isFile()) {
|
|
312
|
-
// Convert path back to key
|
|
313
|
-
const relativePath = plugins.path.relative(this.fsBasePath!, fullPath);
|
|
314
|
-
const key = '/' + relativePath.replace(/\\/g, '/');
|
|
315
|
-
if (key.startsWith(prefix)) {
|
|
316
|
-
keys.push(key);
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
} catch (error: unknown) {
|
|
321
|
-
if ((error as any).code !== 'ENOENT') {
|
|
322
|
-
throw error;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
};
|
|
326
|
-
|
|
327
|
-
await walkDir(basePath, basePath);
|
|
328
|
-
return keys.sort();
|
|
329
|
-
} else {
|
|
330
|
-
// True custom backends need to implement their own listing
|
|
331
|
-
logger.log('warn', 'List operation not supported for custom backend');
|
|
332
|
-
return [];
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
case 'memory': {
|
|
337
|
-
const keys: string[] = [];
|
|
338
|
-
for (const key of this.memoryStore.keys()) {
|
|
339
|
-
if (key.startsWith(prefix)) {
|
|
340
|
-
keys.push(key);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
return keys.sort();
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
default:
|
|
347
|
-
throw new Error(`Unknown backend: ${this.backend}`);
|
|
348
|
-
}
|
|
349
|
-
} catch (error: unknown) {
|
|
350
|
-
logger.log('error', `Storage list error for prefix ${prefix}: ${(error as Error).message}`);
|
|
351
|
-
throw error;
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
/**
|
|
356
|
-
* Check if key exists
|
|
357
|
-
*/
|
|
358
|
-
async exists(key: string): Promise<boolean> {
|
|
359
|
-
key = this.validateKey(key);
|
|
360
|
-
|
|
361
|
-
try {
|
|
362
|
-
const value = await this.get(key);
|
|
363
|
-
return value !== null;
|
|
364
|
-
} catch (error) {
|
|
365
|
-
return false;
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
/**
|
|
370
|
-
* Get storage backend type
|
|
371
|
-
*/
|
|
372
|
-
getBackend(): StorageBackend {
|
|
373
|
-
// If we're using custom backend with fsBasePath, report it as filesystem
|
|
374
|
-
if (this.backend === 'custom' && this.fsBasePath) {
|
|
375
|
-
return 'filesystem' as StorageBackend;
|
|
376
|
-
}
|
|
377
|
-
return this.backend;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* JSON helper: Get and parse JSON value
|
|
382
|
-
*/
|
|
383
|
-
async getJSON<T = any>(key: string): Promise<T | null> {
|
|
384
|
-
const value = await this.get(key);
|
|
385
|
-
if (value === null || value.trim() === '') {
|
|
386
|
-
return null;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
try {
|
|
390
|
-
return JSON.parse(value) as T;
|
|
391
|
-
} catch (error: unknown) {
|
|
392
|
-
logger.log('error', `Failed to parse JSON for key ${key}: ${(error as Error).message}`);
|
|
393
|
-
throw error;
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
/**
|
|
398
|
-
* JSON helper: Set value as JSON
|
|
399
|
-
*/
|
|
400
|
-
async setJSON(key: string, value: any): Promise<void> {
|
|
401
|
-
const jsonString = JSON.stringify(value, null, 2);
|
|
402
|
-
await this.set(key, jsonString);
|
|
403
|
-
}
|
|
404
|
-
}
|
package/ts/storage/index.ts
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|