@dexto/storage 1.6.0 → 1.6.2

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/index.d.cts CHANGED
@@ -1,24 +1,503 @@
1
- export { StorageConfig, StorageSchema, ValidatedStorageConfig } from './schemas.cjs';
2
- export { CacheFactory } from './cache/factory.cjs';
3
- export { inMemoryCacheFactory } from './cache/factories/memory.cjs';
4
- export { redisCacheFactory } from './cache/factories/redis.cjs';
5
- export { CACHE_TYPES, CacheConfig, CacheConfigSchema, CacheType, InMemoryCacheConfig, RedisCacheConfig } from './cache/schemas.cjs';
6
- export { MemoryCacheStore } from './cache/memory-cache-store.cjs';
7
- export { RedisStore } from './cache/redis-store.cjs';
8
- export { DatabaseFactory } from './database/factory.cjs';
9
- export { inMemoryDatabaseFactory } from './database/factories/memory.cjs';
10
- export { sqliteDatabaseFactory } from './database/factories/sqlite.cjs';
11
- export { postgresDatabaseFactory } from './database/factories/postgres.cjs';
12
- export { DATABASE_TYPES, DatabaseConfig, DatabaseConfigSchema, DatabaseType, InMemoryDatabaseConfig, PostgresDatabaseConfig, SqliteDatabaseConfig } from './database/schemas.cjs';
13
- export { MemoryDatabaseStore } from './database/memory-database-store.cjs';
14
- export { SQLiteStore } from './database/sqlite-store.cjs';
15
- export { PostgresStore } from './database/postgres-store.cjs';
16
- export { BlobStoreFactory } from './blob/factory.cjs';
17
- export { localBlobStoreFactory } from './blob/factories/local.cjs';
18
- export { inMemoryBlobStoreFactory } from './blob/factories/memory.cjs';
19
- export { BLOB_STORE_TYPES, BlobStoreConfig, BlobStoreConfigSchema, BlobStoreType, InMemoryBlobStoreConfig, InMemoryBlobStoreConfigInput, InMemoryBlobStoreSchema, LocalBlobStoreConfig, LocalBlobStoreConfigInput, LocalBlobStoreSchema } from './blob/schemas.cjs';
20
- export { LocalBlobStore } from './blob/local-blob-store.cjs';
21
- export { MemoryBlobStore } from './blob/memory-blob-store.cjs';
22
- import 'zod';
23
- import '@dexto/core';
24
- import 'pg';
1
+ import { InMemoryCacheConfig, RedisCacheConfig, InMemoryDatabaseConfig, SqliteDatabaseConfig, PostgresDatabaseConfig, LocalBlobStoreConfig, InMemoryBlobStoreConfig, InMemoryBlobStoreConfigInput } from './schemas.cjs';
2
+ export { BLOB_STORE_TYPES, BlobStoreConfig, BlobStoreConfigSchema, BlobStoreType, CACHE_TYPES, CacheConfig, CacheConfigSchema, CacheType, DATABASE_TYPES, DatabaseConfig, DatabaseConfigSchema, DatabaseType, InMemoryBlobStoreSchema, LocalBlobStoreConfigInput, LocalBlobStoreSchema, StorageConfig, StorageSchema, ValidatedStorageConfig } from './schemas.cjs';
3
+ import { Logger, Cache, Database, BlobStore, BlobInput, BlobMetadata, BlobReference, BlobData, BlobStats } from '@dexto/core';
4
+ import { z } from 'zod';
5
+ import { PoolClient } from 'pg';
6
+
7
+ /**
8
+ * Factory interface for creating cache instances.
9
+ *
10
+ * Factories are plain exports (no global registries). Images decide which factories are
11
+ * available by including them in `image.storage.cache`.
12
+ */
13
+ interface CacheFactory<TConfig = unknown> {
14
+ /**
15
+ * Zod schema for validating factory-specific configuration.
16
+ * The schema must output the `TConfig` type.
17
+ */
18
+ configSchema: z.ZodType<TConfig, z.ZodTypeDef, unknown>;
19
+ /**
20
+ * Factory function to create a Cache instance.
21
+ *
22
+ * Cache factories may return a Promise to support lazy loading of optional
23
+ * dependencies (e.g., `ioredis`).
24
+ *
25
+ * @param config - Validated configuration specific to this backend
26
+ * @param logger - Logger instance for the cache
27
+ * @returns A Cache implementation (or Promise for async backends)
28
+ */
29
+ create(config: TConfig, logger: Logger): Cache | Promise<Cache>;
30
+ /**
31
+ * Optional metadata for documentation, UIs, and discovery.
32
+ */
33
+ metadata?: {
34
+ /** Human-readable name (e.g., "Redis", "Memcached") */
35
+ displayName: string;
36
+ /** Brief description of this cache backend */
37
+ description: string;
38
+ /** Whether this backend requires network connectivity */
39
+ requiresNetwork?: boolean;
40
+ /** Whether this backend supports TTL (time-to-live) */
41
+ supportsTTL?: boolean;
42
+ };
43
+ }
44
+
45
+ /**
46
+ * Factory for in-memory cache storage.
47
+ *
48
+ * This factory stores data in RAM and is ideal for development,
49
+ * testing, and ephemeral use cases where persistence is not required.
50
+ *
51
+ * Features:
52
+ * - Zero external dependencies
53
+ * - Fast in-memory operations
54
+ * - TTL support for automatic expiration
55
+ * - No network required
56
+ * - Data is lost on restart
57
+ */
58
+ declare const inMemoryCacheFactory: CacheFactory<InMemoryCacheConfig>;
59
+
60
+ /**
61
+ * Factory for Redis cache storage.
62
+ *
63
+ * This factory stores data in a Redis server using the ioredis package.
64
+ * It's ideal for production deployments requiring scalability, persistence,
65
+ * and multi-machine access.
66
+ *
67
+ * Features:
68
+ * - Native TTL support
69
+ * - Connection pooling
70
+ * - Pub/sub capabilities (via additional methods)
71
+ * - Suitable for distributed deployments
72
+ *
73
+ * Note: ioredis is an optional dependency. Install it with:
74
+ * npm install ioredis
75
+ */
76
+ declare const redisCacheFactory: CacheFactory<RedisCacheConfig>;
77
+
78
+ /**
79
+ * In-memory cache store for development and testing.
80
+ * Supports TTL for automatic cleanup of temporary data.
81
+ * Data is lost when the process restarts.
82
+ */
83
+ declare class MemoryCacheStore implements Cache {
84
+ private data;
85
+ private ttls;
86
+ private connected;
87
+ connect(): Promise<void>;
88
+ disconnect(): Promise<void>;
89
+ isConnected(): boolean;
90
+ getStoreType(): string;
91
+ get<T>(key: string): Promise<T | undefined>;
92
+ set<T>(key: string, value: T, ttlSeconds?: number): Promise<void>;
93
+ delete(key: string): Promise<void>;
94
+ private checkConnection;
95
+ private checkTTL;
96
+ clear(): Promise<void>;
97
+ dump(): Promise<{
98
+ data: Record<string, unknown>;
99
+ }>;
100
+ }
101
+
102
+ /**
103
+ * Redis cache store for production cache operations.
104
+ * Implements the Cache interface with connection pooling and optimizations.
105
+ * EXPERIMENTAL - NOT FULLY TESTED YET
106
+ */
107
+ declare class RedisStore implements Cache {
108
+ private config;
109
+ private redis;
110
+ private connected;
111
+ private logger;
112
+ constructor(config: RedisCacheConfig, logger: Logger);
113
+ connect(): Promise<void>;
114
+ disconnect(): Promise<void>;
115
+ isConnected(): boolean;
116
+ getStoreType(): string;
117
+ get<T>(key: string): Promise<T | undefined>;
118
+ set<T>(key: string, value: T, ttlSeconds?: number): Promise<void>;
119
+ delete(key: string): Promise<void>;
120
+ mget<T>(keys: string[]): Promise<(T | undefined)[]>;
121
+ mset<T>(entries: [string, T][]): Promise<void>;
122
+ exists(key: string): Promise<boolean>;
123
+ expire(key: string, ttlSeconds: number): Promise<void>;
124
+ increment(key: string, by?: number): Promise<number>;
125
+ decrement(key: string, by?: number): Promise<number>;
126
+ private checkConnection;
127
+ flushdb(): Promise<void>;
128
+ info(): Promise<string>;
129
+ }
130
+
131
+ /**
132
+ * Factory interface for creating database instances.
133
+ *
134
+ * Factories are plain exports (no global registries). Images decide which factories are
135
+ * available by including them in `image.storage.database`.
136
+ */
137
+ interface DatabaseFactory<TConfig = unknown> {
138
+ /**
139
+ * Zod schema for validating factory-specific configuration.
140
+ * The schema must output the `TConfig` type.
141
+ */
142
+ configSchema: z.ZodType<TConfig, z.ZodTypeDef, unknown>;
143
+ /**
144
+ * Factory function to create a Database instance.
145
+ *
146
+ * Database factories may return a Promise to support lazy loading of optional
147
+ * dependencies (e.g., `better-sqlite3`, `pg`).
148
+ *
149
+ * @param config - Validated configuration specific to this backend
150
+ * @param logger - Logger instance for the database
151
+ * @returns A Database implementation (or Promise for async backends)
152
+ */
153
+ create(config: TConfig, logger: Logger): Database | Promise<Database>;
154
+ /**
155
+ * Optional metadata for documentation, UIs, and discovery.
156
+ */
157
+ metadata?: {
158
+ /** Human-readable name (e.g., "SQLite", "PostgreSQL") */
159
+ displayName: string;
160
+ /** Brief description of this storage backend */
161
+ description: string;
162
+ /** Whether this backend requires network connectivity */
163
+ requiresNetwork?: boolean;
164
+ /** Whether this backend supports list operations (append/getRange) */
165
+ supportsListOperations?: boolean;
166
+ };
167
+ }
168
+
169
+ /**
170
+ * Factory for in-memory database storage.
171
+ *
172
+ * This factory stores data in RAM and is ideal for development,
173
+ * testing, and ephemeral use cases where persistence is not required.
174
+ *
175
+ * Features:
176
+ * - Zero external dependencies
177
+ * - Fast in-memory operations
178
+ * - No network required
179
+ * - Data is lost on restart
180
+ */
181
+ declare const inMemoryDatabaseFactory: DatabaseFactory<InMemoryDatabaseConfig>;
182
+
183
+ /**
184
+ * Factory for SQLite database storage.
185
+ *
186
+ * This factory stores data in a local SQLite database file using better-sqlite3.
187
+ * It's ideal for single-machine deployments and development scenarios where
188
+ * persistence is required without the overhead of a database server.
189
+ *
190
+ * Features:
191
+ * - Uses better-sqlite3 for synchronous, fast operations
192
+ * - WAL mode enabled for better concurrency
193
+ * - No external server required
194
+ * - Persistent storage survives restarts
195
+ *
196
+ * Note: better-sqlite3 is an optional dependency. Install it with:
197
+ * npm install better-sqlite3
198
+ */
199
+ declare const sqliteDatabaseFactory: DatabaseFactory<SqliteDatabaseConfig>;
200
+
201
+ /**
202
+ * Factory for PostgreSQL database storage.
203
+ *
204
+ * This factory stores data in a PostgreSQL database server using the pg package.
205
+ * It's ideal for production deployments requiring scalability and multi-machine access.
206
+ *
207
+ * Features:
208
+ * - Connection pooling for efficient resource usage
209
+ * - JSONB storage for flexible data types
210
+ * - Transaction support
211
+ * - Suitable for distributed deployments
212
+ *
213
+ * Note: pg is an optional dependency. Install it with:
214
+ * npm install pg
215
+ */
216
+ declare const postgresDatabaseFactory: DatabaseFactory<PostgresDatabaseConfig>;
217
+
218
+ /**
219
+ * In-memory database store for development and testing.
220
+ * Supports list operations for message history and enumeration for settings.
221
+ * Data is lost when the process restarts.
222
+ */
223
+ declare class MemoryDatabaseStore implements Database {
224
+ private data;
225
+ private lists;
226
+ private connected;
227
+ connect(): Promise<void>;
228
+ disconnect(): Promise<void>;
229
+ isConnected(): boolean;
230
+ getStoreType(): string;
231
+ get<T>(key: string): Promise<T | undefined>;
232
+ set<T>(key: string, value: T): Promise<void>;
233
+ delete(key: string): Promise<void>;
234
+ list(prefix: string): Promise<string[]>;
235
+ append<T>(key: string, item: T): Promise<void>;
236
+ getRange<T>(key: string, start: number, count: number): Promise<T[]>;
237
+ private checkConnection;
238
+ clear(): Promise<void>;
239
+ dump(): Promise<{
240
+ data: Record<string, unknown>;
241
+ lists: Record<string, unknown[]>;
242
+ }>;
243
+ }
244
+
245
+ /**
246
+ * SQLite database store for local development and production.
247
+ * Implements the Database interface with proper schema and connection handling.
248
+ */
249
+ declare class SQLiteStore implements Database {
250
+ private db;
251
+ private dbPath;
252
+ private config;
253
+ private logger;
254
+ constructor(config: SqliteDatabaseConfig, logger: Logger);
255
+ private initializeTables;
256
+ connect(): Promise<void>;
257
+ disconnect(): Promise<void>;
258
+ isConnected(): boolean;
259
+ getStoreType(): string;
260
+ get<T>(key: string): Promise<T | undefined>;
261
+ set<T>(key: string, value: T): Promise<void>;
262
+ delete(key: string): Promise<void>;
263
+ list(prefix: string): Promise<string[]>;
264
+ append<T>(key: string, item: T): Promise<void>;
265
+ getRange<T>(key: string, start: number, count: number): Promise<T[]>;
266
+ private checkConnection;
267
+ vacuum(): Promise<void>;
268
+ getStats(): Promise<{
269
+ kvCount: number;
270
+ listCount: number;
271
+ dbSize: number;
272
+ }>;
273
+ }
274
+
275
+ /**
276
+ * PostgreSQL database store for production database operations.
277
+ * Implements the Database interface with connection pooling and JSONB support.
278
+ * EXPERIMENTAL - NOT FULLY TESTED YET
279
+ */
280
+ declare class PostgresStore implements Database {
281
+ private config;
282
+ private pool;
283
+ private connected;
284
+ private logger;
285
+ constructor(config: PostgresDatabaseConfig, logger: Logger);
286
+ connect(): Promise<void>;
287
+ /**
288
+ * Creates a PostgreSQL schema if it doesn't exist.
289
+ */
290
+ private createSchema;
291
+ disconnect(): Promise<void>;
292
+ isConnected(): boolean;
293
+ getStoreType(): string;
294
+ get<T>(key: string): Promise<T | undefined>;
295
+ set<T>(key: string, value: T): Promise<void>;
296
+ delete(key: string): Promise<void>;
297
+ list(prefix: string): Promise<string[]>;
298
+ append<T>(key: string, item: T): Promise<void>;
299
+ getRange<T>(key: string, start: number, count: number): Promise<T[]>;
300
+ private createTables;
301
+ private checkConnection;
302
+ /**
303
+ * Check if an error is a connection error that should trigger a retry.
304
+ * Common with serverless databases (Neon) where connections go stale.
305
+ */
306
+ private isConnectionError;
307
+ /**
308
+ * Execute a database operation with automatic retry on connection errors.
309
+ * Handles serverless DB connection issues (Neon cold starts, stale connections).
310
+ */
311
+ private withRetry;
312
+ /**
313
+ * Execute a callback within a database transaction.
314
+ * Note: On connection failure, the entire callback will be retried on a new connection.
315
+ * Ensure callback operations are idempotent or use this only for read operations.
316
+ */
317
+ transaction<T>(callback: (client: PoolClient) => Promise<T>): Promise<T>;
318
+ getStats(): Promise<{
319
+ kvCount: number;
320
+ listCount: number;
321
+ totalSize: string;
322
+ }>;
323
+ vacuum(): Promise<void>;
324
+ }
325
+
326
+ /**
327
+ * Factory interface for creating blob store instances.
328
+ *
329
+ * Factories are plain exports (no global registries). Images decide which factories are
330
+ * available by including them in `image.storage.blob`.
331
+ */
332
+ interface BlobStoreFactory<TConfig = unknown> {
333
+ /**
334
+ * Zod schema for validating factory-specific configuration.
335
+ * The schema must output the `TConfig` type.
336
+ */
337
+ configSchema: z.ZodType<TConfig, z.ZodTypeDef, unknown>;
338
+ /**
339
+ * Factory function to create a BlobStore instance.
340
+ * @param config - Validated configuration specific to this backend
341
+ * @param logger - Logger instance for the blob store
342
+ * @returns A BlobStore implementation
343
+ */
344
+ create(config: TConfig, logger: Logger): BlobStore | Promise<BlobStore>;
345
+ /**
346
+ * Optional metadata for documentation, UIs, and discovery.
347
+ */
348
+ metadata?: {
349
+ /** Human-readable name (e.g., "Local Filesystem", "Amazon S3") */
350
+ displayName: string;
351
+ /** Brief description of this storage backend */
352
+ description: string;
353
+ /** Whether this backend requires network connectivity */
354
+ requiresNetwork?: boolean;
355
+ };
356
+ }
357
+
358
+ /**
359
+ * Factory for local filesystem blob storage.
360
+ *
361
+ * This factory stores blobs on the local filesystem with content-based
362
+ * deduplication and metadata tracking. It's ideal for development and
363
+ * single-machine deployments.
364
+ *
365
+ * Features:
366
+ * - Zero external dependencies (uses Node.js fs module)
367
+ * - Content-based deduplication (same hash = same blob)
368
+ * - Automatic cleanup of old blobs
369
+ * - No network required
370
+ */
371
+ declare const localBlobStoreFactory: BlobStoreFactory<LocalBlobStoreConfig>;
372
+
373
+ /**
374
+ * Factory for in-memory blob storage.
375
+ *
376
+ * This factory stores blobs in RAM, making it ideal for testing and
377
+ * development. All data is lost when the process exits.
378
+ *
379
+ * Features:
380
+ * - Zero dependencies
381
+ * - Extremely fast (no I/O)
382
+ * - Configurable size limits
383
+ * - No network required
384
+ * - Perfect for unit tests
385
+ */
386
+ declare const inMemoryBlobStoreFactory: BlobStoreFactory<InMemoryBlobStoreConfig>;
387
+
388
+ /**
389
+ * Local filesystem blob store implementation.
390
+ *
391
+ * Stores blobs on the local filesystem with content-based deduplication
392
+ * and metadata tracking. This is the default store for development
393
+ * and single-machine deployments.
394
+ */
395
+ declare class LocalBlobStore implements BlobStore {
396
+ private config;
397
+ private storePath;
398
+ private connected;
399
+ private statsCache;
400
+ private statsCachePromise;
401
+ private lastStatsRefresh;
402
+ private logger;
403
+ private static readonly STATS_REFRESH_INTERVAL_MS;
404
+ constructor(config: LocalBlobStoreConfig, logger: Logger);
405
+ connect(): Promise<void>;
406
+ disconnect(): Promise<void>;
407
+ isConnected(): boolean;
408
+ getStoreType(): string;
409
+ store(input: BlobInput, metadata?: BlobMetadata): Promise<BlobReference>;
410
+ retrieve(reference: string, format?: 'base64' | 'buffer' | 'path' | 'stream' | 'url'): Promise<BlobData>;
411
+ exists(reference: string): Promise<boolean>;
412
+ delete(reference: string): Promise<void>;
413
+ cleanup(olderThan?: Date): Promise<number>;
414
+ getStats(): Promise<BlobStats>;
415
+ getStoragePath(): string | undefined;
416
+ listBlobs(): Promise<BlobReference[]>;
417
+ private ensureStatsCache;
418
+ private refreshStatsCache;
419
+ private updateStatsCacheAfterStore;
420
+ private updateStatsCacheAfterDelete;
421
+ /**
422
+ * Convert various input types to Buffer
423
+ */
424
+ private inputToBuffer;
425
+ /**
426
+ * Parse blob reference to extract ID
427
+ */
428
+ private parseReference;
429
+ /**
430
+ * Detect MIME type from buffer content and/or filename
431
+ */
432
+ private detectMimeType;
433
+ /**
434
+ * Check if buffer contains text content
435
+ */
436
+ private isTextBuffer;
437
+ }
438
+
439
+ /**
440
+ * In-memory blob store implementation.
441
+ *
442
+ * Stores blobs in memory with content-based deduplication and size limits.
443
+ * Suitable for development, testing, and scenarios where blob persistence
444
+ * across restarts is not required.
445
+ *
446
+ * Features:
447
+ * - Content-based deduplication (same as LocalBlobStore)
448
+ * - Configurable size limits (per-blob and total)
449
+ * - Automatic cleanup of old blobs
450
+ * - MIME type detection
451
+ * - Multi-format retrieval (base64, buffer, stream, data URI)
452
+ *
453
+ * Limitations:
454
+ * - Data lost on restart (no persistence)
455
+ * - Path format not supported (no filesystem)
456
+ * - Memory usage proportional to blob size
457
+ */
458
+ type MemoryBlobStoreOptions = Omit<InMemoryBlobStoreConfigInput, 'type'>;
459
+ declare class MemoryBlobStore implements BlobStore {
460
+ private config;
461
+ private blobs;
462
+ private connected;
463
+ private logger;
464
+ constructor(options: MemoryBlobStoreOptions, logger: Logger);
465
+ connect(): Promise<void>;
466
+ disconnect(): Promise<void>;
467
+ isConnected(): boolean;
468
+ getStoreType(): string;
469
+ store(input: BlobInput, metadata?: BlobMetadata): Promise<BlobReference>;
470
+ retrieve(reference: string, format?: 'base64' | 'buffer' | 'path' | 'stream' | 'url'): Promise<BlobData>;
471
+ exists(reference: string): Promise<boolean>;
472
+ delete(reference: string): Promise<void>;
473
+ cleanup(olderThan?: Date): Promise<number>;
474
+ getStats(): Promise<BlobStats>;
475
+ listBlobs(): Promise<BlobReference[]>;
476
+ getStoragePath(): string | undefined;
477
+ /**
478
+ * Calculate total size of all blobs in memory
479
+ */
480
+ private getTotalSize;
481
+ /**
482
+ * Convert various input types to Buffer.
483
+ * Copied from LocalBlobStore with minor adaptations.
484
+ */
485
+ private inputToBuffer;
486
+ /**
487
+ * Parse blob reference to extract ID.
488
+ * Copied from LocalBlobStore.
489
+ */
490
+ private parseReference;
491
+ /**
492
+ * Detect MIME type from buffer content and/or filename.
493
+ * Copied from LocalBlobStore.
494
+ */
495
+ private detectMimeType;
496
+ /**
497
+ * Check if buffer contains text content.
498
+ * Copied from LocalBlobStore.
499
+ */
500
+ private isTextBuffer;
501
+ }
502
+
503
+ export { type BlobStoreFactory, type CacheFactory, type DatabaseFactory, InMemoryBlobStoreConfig, InMemoryBlobStoreConfigInput, InMemoryCacheConfig, InMemoryDatabaseConfig, LocalBlobStore, LocalBlobStoreConfig, MemoryBlobStore, MemoryCacheStore, MemoryDatabaseStore, PostgresDatabaseConfig, PostgresStore, RedisCacheConfig, RedisStore, SQLiteStore, SqliteDatabaseConfig, inMemoryBlobStoreFactory, inMemoryCacheFactory, inMemoryDatabaseFactory, localBlobStoreFactory, postgresDatabaseFactory, redisCacheFactory, sqliteDatabaseFactory };