@frontmcp/utils 0.7.2 → 0.8.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/utils",
3
- "version": "0.7.2",
3
+ "version": "0.8.1",
4
4
  "description": "Shared utility functions for FrontMCP - string manipulation, URI handling, path utilities, and more",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "license": "Apache-2.0",
@@ -23,12 +23,27 @@
23
23
  "url": "https://github.com/agentfront/frontmcp/issues"
24
24
  },
25
25
  "homepage": "https://github.com/agentfront/frontmcp/blob/main/libs/utils/README.md",
26
+ "engines": {
27
+ "node": ">=22.0.0"
28
+ },
26
29
  "dependencies": {
27
30
  "@noble/hashes": "^2.0.1",
28
31
  "@noble/ciphers": "^2.1.1",
29
- "ast-guard": "^2.4.0",
32
+ "@enclave-vm/ast": "^2.10.1",
30
33
  "zod": "^4.0.0"
31
34
  },
35
+ "peerDependencies": {
36
+ "@vercel/kv": "^2.0.0 || ^3.0.0",
37
+ "ioredis": "^5.0.0"
38
+ },
39
+ "peerDependenciesMeta": {
40
+ "@vercel/kv": {
41
+ "optional": true
42
+ },
43
+ "ioredis": {
44
+ "optional": true
45
+ }
46
+ },
32
47
  "type": "commonjs",
33
48
  "main": "./index.js",
34
49
  "module": "./esm/index.mjs",
@@ -4,7 +4,7 @@
4
4
  * These utilities protect against ReDoS (Regular Expression Denial of Service)
5
5
  * attacks by validating patterns and enforcing input length limits.
6
6
  */
7
- import { REDOS_THRESHOLDS } from 'ast-guard';
7
+ import { REDOS_THRESHOLDS } from '@enclave-vm/ast';
8
8
  /**
9
9
  * Default maximum input length for safe regex operations.
10
10
  * Inputs longer than this will be rejected to prevent ReDoS attacks.
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Filesystem Storage Adapter
3
+ *
4
+ * File-based storage implementation for Node.js environments.
5
+ * Each key is stored as a separate JSON file in a directory.
6
+ *
7
+ * **Node.js only** - throws an error if used in browser environments.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const adapter = new FileSystemStorageAdapter({
12
+ * baseDir: '.frontmcp/storage',
13
+ * });
14
+ *
15
+ * await adapter.connect();
16
+ * await adapter.set('user:123', JSON.stringify({ name: 'John' }));
17
+ * const value = await adapter.get('user:123');
18
+ * await adapter.disconnect();
19
+ * ```
20
+ */
21
+ import { BaseStorageAdapter } from './base';
22
+ import type { SetOptions } from '../types';
23
+ /**
24
+ * Options for FileSystemStorageAdapter.
25
+ */
26
+ export interface FileSystemAdapterOptions {
27
+ /**
28
+ * Base directory for storage (absolute or relative to cwd).
29
+ * Each key is stored as a file in this directory.
30
+ */
31
+ baseDir: string;
32
+ /**
33
+ * File extension for stored files.
34
+ * @default '.json'
35
+ */
36
+ extension?: string;
37
+ /**
38
+ * Directory permissions (Unix mode).
39
+ * @default 0o700
40
+ */
41
+ dirMode?: number;
42
+ /**
43
+ * File permissions (Unix mode).
44
+ * @default 0o600
45
+ */
46
+ fileMode?: number;
47
+ }
48
+ /**
49
+ * Filesystem-based storage adapter.
50
+ *
51
+ * Features:
52
+ * - Persists data to individual JSON files
53
+ * - Atomic writes using temp file + rename
54
+ * - Restricted file permissions (0o600)
55
+ * - TTL support with lazy expiration
56
+ *
57
+ * Limitations:
58
+ * - No pub/sub support
59
+ * - TTL not enforced with background sweeper
60
+ * - Not suitable for high-throughput scenarios
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * import { FileSystemStorageAdapter } from '@frontmcp/utils';
65
+ *
66
+ * const adapter = new FileSystemStorageAdapter({
67
+ * baseDir: '.frontmcp/keys',
68
+ * extension: '.json',
69
+ * });
70
+ *
71
+ * await adapter.connect();
72
+ *
73
+ * // Store data
74
+ * await adapter.set('my-key', 'my-value');
75
+ *
76
+ * // Retrieve data
77
+ * const value = await adapter.get('my-key');
78
+ *
79
+ * // List all keys
80
+ * const keys = await adapter.keys();
81
+ *
82
+ * await adapter.disconnect();
83
+ * ```
84
+ */
85
+ export declare class FileSystemStorageAdapter extends BaseStorageAdapter {
86
+ protected readonly backendName = "filesystem";
87
+ private readonly baseDir;
88
+ private readonly extension;
89
+ private readonly dirMode;
90
+ private readonly fileMode;
91
+ constructor(options: FileSystemAdapterOptions);
92
+ connect(): Promise<void>;
93
+ disconnect(): Promise<void>;
94
+ ping(): Promise<boolean>;
95
+ get(key: string): Promise<string | null>;
96
+ protected doSet(key: string, value: string, options?: SetOptions): Promise<void>;
97
+ delete(key: string): Promise<boolean>;
98
+ exists(key: string): Promise<boolean>;
99
+ expire(key: string, ttlSeconds: number): Promise<boolean>;
100
+ ttl(key: string): Promise<number | null>;
101
+ keys(pattern?: string): Promise<string[]>;
102
+ incr(key: string): Promise<number>;
103
+ decr(key: string): Promise<number>;
104
+ incrBy(key: string, amount: number): Promise<number>;
105
+ /**
106
+ * Convert a storage key to a file path.
107
+ * Sanitizes the key to be filesystem-safe.
108
+ */
109
+ private keyToPath;
110
+ /**
111
+ * Convert a filename back to a storage key.
112
+ */
113
+ private pathToKey;
114
+ /**
115
+ * Encode a key to be filesystem-safe.
116
+ * Uses URL encoding to handle special characters.
117
+ */
118
+ private encodeKey;
119
+ /**
120
+ * Decode a filesystem-safe key back to original.
121
+ */
122
+ private decodeKey;
123
+ /**
124
+ * Read an entry from a file.
125
+ */
126
+ private readEntry;
127
+ /**
128
+ * Check if an entry is expired.
129
+ */
130
+ private isExpired;
131
+ /**
132
+ * Delete a file, returning true if it existed.
133
+ */
134
+ private deleteFile;
135
+ /**
136
+ * Atomic write: write to temp file then rename.
137
+ * This ensures we don't corrupt the file if write is interrupted.
138
+ */
139
+ private atomicWrite;
140
+ /**
141
+ * Get suggestion message for pub/sub not supported error.
142
+ */
143
+ protected getPubSubSuggestion(): string;
144
+ }
@@ -8,3 +8,5 @@ export { MemoryStorageAdapter } from './memory';
8
8
  export { RedisStorageAdapter } from './redis';
9
9
  export { VercelKvStorageAdapter } from './vercel-kv';
10
10
  export { UpstashStorageAdapter } from './upstash';
11
+ export { FileSystemStorageAdapter } from './filesystem';
12
+ export type { FileSystemAdapterOptions } from './filesystem';
@@ -0,0 +1,196 @@
1
+ /**
2
+ * EncryptedTypedStorage
3
+ *
4
+ * A storage wrapper that provides transparent encryption/decryption
5
+ * with key rotation support on top of StorageAdapter.
6
+ *
7
+ * Uses AES-256-GCM for encryption with automatic JSON serialization.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { createStorage, EncryptedTypedStorage, randomBytes } from '@frontmcp/utils';
12
+ *
13
+ * interface Secret {
14
+ * apiKey: string;
15
+ * refreshToken: string;
16
+ * }
17
+ *
18
+ * const storage = await createStorage({ type: 'memory' });
19
+ * const keys = [
20
+ * { kid: 'key-2024', key: randomBytes(32) },
21
+ * { kid: 'key-2023', key: oldKey }, // For decrypting old data
22
+ * ];
23
+ *
24
+ * const secrets = new EncryptedTypedStorage<Secret>(storage, { keys });
25
+ *
26
+ * // Data is encrypted before storage
27
+ * await secrets.set('user:123', { apiKey: 'sk-...', refreshToken: 'rt-...' });
28
+ *
29
+ * // Data is decrypted on retrieval
30
+ * const secret = await secrets.get('user:123');
31
+ * ```
32
+ */
33
+ import type { StorageAdapter, NamespacedStorage, SetOptions } from './types';
34
+ import type { EncryptedTypedStorageOptions, EncryptedSetEntry, EncryptionKey } from './encrypted-typed-storage.types';
35
+ /**
36
+ * EncryptedTypedStorage provides transparent encryption/decryption
37
+ * on top of StorageAdapter.
38
+ *
39
+ * Features:
40
+ * - AES-256-GCM encryption for all stored values
41
+ * - Automatic JSON serialization/deserialization
42
+ * - Key rotation support (multiple keys, first is active)
43
+ * - Optional Zod schema validation after decryption
44
+ * - Batch operations (mget/mset)
45
+ */
46
+ export declare class EncryptedTypedStorage<T> {
47
+ private readonly storage;
48
+ private activeKey;
49
+ private readonly keyMap;
50
+ private readonly schema?;
51
+ private readonly throwOnError;
52
+ private readonly onKeyRotationNeeded?;
53
+ private readonly clientBinding?;
54
+ constructor(storage: StorageAdapter | NamespacedStorage, options: EncryptedTypedStorageOptions<T>);
55
+ /**
56
+ * Get a decrypted value by key.
57
+ *
58
+ * @param key - Storage key
59
+ * @returns The decrypted value, or null if not found or decryption fails
60
+ */
61
+ get(key: string): Promise<T | null>;
62
+ /**
63
+ * Encrypt and store a value.
64
+ *
65
+ * @param key - Storage key
66
+ * @param value - Value to encrypt and store
67
+ * @param options - Optional TTL and conditional flags
68
+ */
69
+ set(key: string, value: T, options?: SetOptions): Promise<void>;
70
+ /**
71
+ * Delete a key.
72
+ *
73
+ * @param key - Storage key
74
+ * @returns true if key existed and was deleted
75
+ */
76
+ delete(key: string): Promise<boolean>;
77
+ /**
78
+ * Check if a key exists.
79
+ *
80
+ * @param key - Storage key
81
+ * @returns true if key exists
82
+ */
83
+ exists(key: string): Promise<boolean>;
84
+ /**
85
+ * Get multiple decrypted values.
86
+ *
87
+ * @param keys - Array of storage keys
88
+ * @returns Array of decrypted values (null for missing/invalid keys)
89
+ */
90
+ mget(keys: string[]): Promise<(T | null)[]>;
91
+ /**
92
+ * Encrypt and store multiple values.
93
+ *
94
+ * @param entries - Array of key-value-options entries
95
+ */
96
+ mset(entries: EncryptedSetEntry<T>[]): Promise<void>;
97
+ /**
98
+ * Delete multiple keys.
99
+ *
100
+ * @param keys - Array of storage keys
101
+ * @returns Number of keys actually deleted
102
+ */
103
+ mdelete(keys: string[]): Promise<number>;
104
+ /**
105
+ * Update TTL on an existing key.
106
+ *
107
+ * @param key - Storage key
108
+ * @param ttlSeconds - New TTL in seconds
109
+ * @returns true if key exists and TTL was set
110
+ */
111
+ expire(key: string, ttlSeconds: number): Promise<boolean>;
112
+ /**
113
+ * Get remaining TTL for a key.
114
+ *
115
+ * @param key - Storage key
116
+ * @returns TTL in seconds, -1 if no TTL, or null if key doesn't exist
117
+ */
118
+ ttl(key: string): Promise<number | null>;
119
+ /**
120
+ * List keys matching a pattern.
121
+ *
122
+ * @param pattern - Glob pattern (default: '*' for all keys)
123
+ * @returns Array of matching keys
124
+ */
125
+ keys(pattern?: string): Promise<string[]>;
126
+ /**
127
+ * Count keys matching a pattern.
128
+ *
129
+ * @param pattern - Glob pattern (default: '*' for all keys)
130
+ * @returns Number of matching keys
131
+ */
132
+ count(pattern?: string): Promise<number>;
133
+ /**
134
+ * Re-encrypt a value with the active key.
135
+ * Useful for key rotation - reads with old key, writes with new key.
136
+ *
137
+ * @param key - Storage key to re-encrypt
138
+ * @param options - Optional TTL for the re-encrypted value
139
+ * @returns true if value was re-encrypted, false if not found
140
+ */
141
+ reencrypt(key: string, options?: SetOptions): Promise<boolean>;
142
+ /**
143
+ * Rotate the active encryption key.
144
+ * New encryptions will use the new key; old keys remain for decryption.
145
+ *
146
+ * @param newKey - New encryption key to use for writes
147
+ */
148
+ rotateKey(newKey: EncryptionKey): void;
149
+ /**
150
+ * Get the active key ID.
151
+ */
152
+ get activeKeyId(): string;
153
+ /**
154
+ * Get all known key IDs.
155
+ */
156
+ get keyIds(): string[];
157
+ /**
158
+ * Get the underlying storage adapter.
159
+ * Use with caution - operations bypass encryption.
160
+ */
161
+ get raw(): StorageAdapter | NamespacedStorage;
162
+ /**
163
+ * Check if client-side key binding is enabled.
164
+ * When true, encryption keys are derived from both server key and client secret.
165
+ */
166
+ get hasClientBinding(): boolean;
167
+ /**
168
+ * Derive the actual encryption key.
169
+ *
170
+ * If clientBinding is configured, combines server key with client secret
171
+ * using HKDF-SHA256 (RFC 5869) to produce the actual encryption key.
172
+ * Otherwise, returns the server key as-is.
173
+ *
174
+ * This provides zero-knowledge encryption where:
175
+ * - Server cannot decrypt without client secret (sessionId)
176
+ * - Client cannot decrypt without server key
177
+ * - Key derivation is deterministic (same inputs -> same derived key)
178
+ *
179
+ * @param serverKey - The server-side encryption key
180
+ * @returns The key to use for actual encryption/decryption
181
+ */
182
+ private deriveKey;
183
+ /**
184
+ * Encrypt a value using the active key.
185
+ * If client binding is configured, uses derived key from server key + client secret.
186
+ */
187
+ private encryptValue;
188
+ /**
189
+ * Decrypt and parse a stored value.
190
+ */
191
+ private decryptAndParse;
192
+ /**
193
+ * Validate blob structure.
194
+ */
195
+ private isValidBlob;
196
+ }
@@ -0,0 +1,139 @@
1
+ /**
2
+ * EncryptedTypedStorage Types
3
+ *
4
+ * Type definitions for the EncryptedTypedStorage wrapper that provides
5
+ * transparent encryption/decryption with key rotation support.
6
+ */
7
+ import type { SetOptions } from './types';
8
+ import type { z } from 'zod';
9
+ /**
10
+ * Encryption key with identifier for key rotation support.
11
+ */
12
+ export interface EncryptionKey {
13
+ /**
14
+ * Unique key identifier.
15
+ * Used to identify which key was used to encrypt a value.
16
+ */
17
+ kid: string;
18
+ /**
19
+ * 32-byte (256-bit) AES key.
20
+ */
21
+ key: Uint8Array;
22
+ }
23
+ /**
24
+ * Client-side key binding configuration for SOC2/ISO compliance.
25
+ *
26
+ * When provided, the actual encryption key is derived from BOTH
27
+ * the server key AND a client-provided secret using HKDF-SHA256.
28
+ *
29
+ * Security properties:
30
+ * - Server cannot decrypt without client secret (e.g., sessionId)
31
+ * - Client cannot decrypt without server key
32
+ * - Prevents RCE attacks from stealing user data
33
+ * - Deterministic derivation (same inputs -> same key)
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * const storage = new EncryptedTypedStorage(adapter, {
38
+ * keys: [{ kid: 'server-2024', key: serverKey }],
39
+ * clientBinding: {
40
+ * secret: sessionId, // From MCP client
41
+ * info: 'user-secrets-v1'
42
+ * }
43
+ * });
44
+ * ```
45
+ */
46
+ export interface ClientKeyBinding {
47
+ /**
48
+ * Client-provided secret (e.g., sessionId, token hash).
49
+ * This MUST be provided by the MCP client for every operation.
50
+ *
51
+ * Can be provided as a string (will be UTF-8 encoded) or raw bytes.
52
+ */
53
+ secret: Uint8Array | string;
54
+ /**
55
+ * Optional salt for HKDF derivation.
56
+ * If not provided, uses empty salt (per RFC 5869).
57
+ */
58
+ salt?: Uint8Array;
59
+ /**
60
+ * Domain separation info for HKDF.
61
+ * Different values produce different keys even with same inputs.
62
+ * Use to separate keys for different purposes (e.g., 'vault', 'tokens').
63
+ * @default 'frontmcp-client-bound-v1'
64
+ */
65
+ info?: string;
66
+ }
67
+ /**
68
+ * Options for EncryptedTypedStorage wrapper.
69
+ */
70
+ export interface EncryptedTypedStorageOptions<T> {
71
+ /**
72
+ * Encryption keys for the storage.
73
+ * First key is the "active" key used for new encryptions.
74
+ * All keys are tried for decryption (supports key rotation).
75
+ *
76
+ * Must have at least one key.
77
+ */
78
+ keys: EncryptionKey[];
79
+ /**
80
+ * Optional Zod schema for validation after decryption.
81
+ * If provided, values will be validated after decryption.
82
+ */
83
+ schema?: z.ZodType<T>;
84
+ /**
85
+ * Whether to throw an error when data fails validation or decryption.
86
+ * If false (default), returns null for invalid/undecryptable data.
87
+ * @default false
88
+ */
89
+ throwOnError?: boolean;
90
+ /**
91
+ * Optional callback when a value is decrypted with a non-active key.
92
+ * Useful for implementing transparent re-encryption during reads.
93
+ */
94
+ onKeyRotationNeeded?: (key: string, oldKid: string, newKid: string) => void;
95
+ /**
96
+ * Optional client-side key binding for SOC2/ISO compliance.
97
+ *
98
+ * When provided, the actual encryption key is derived from BOTH
99
+ * the server key AND this client secret using HKDF-SHA256 (RFC 5869).
100
+ *
101
+ * Security implications:
102
+ * - Without the client secret, data CANNOT be decrypted even
103
+ * if the server key is compromised
104
+ * - Prevents RCE attacks from stealing user data
105
+ * - Each session can only access its own encrypted data
106
+ *
107
+ * Omit for debugging/development to use server key directly.
108
+ */
109
+ clientBinding?: ClientKeyBinding;
110
+ }
111
+ /**
112
+ * Options for encrypted set operations.
113
+ * Re-export for convenience.
114
+ */
115
+ export type EncryptedSetOptions = SetOptions;
116
+ /**
117
+ * Entry for batch set operations with encrypted values.
118
+ */
119
+ export interface EncryptedSetEntry<T> {
120
+ key: string;
121
+ value: T;
122
+ options?: EncryptedSetOptions;
123
+ }
124
+ /**
125
+ * Encrypted blob stored in the underlying storage.
126
+ * Includes key ID for identifying which key was used.
127
+ */
128
+ export interface StoredEncryptedBlob {
129
+ /** Algorithm used (always A256GCM) */
130
+ alg: 'A256GCM';
131
+ /** Key ID used for encryption */
132
+ kid: string;
133
+ /** Base64url-encoded initialization vector */
134
+ iv: string;
135
+ /** Base64url-encoded authentication tag */
136
+ tag: string;
137
+ /** Base64url-encoded ciphertext */
138
+ data: string;
139
+ }
@@ -115,3 +115,14 @@ export declare class StorageNotConnectedError extends StorageError {
115
115
  readonly backend: string;
116
116
  constructor(backend: string);
117
117
  }
118
+ /**
119
+ * Error thrown when encryption/decryption operations fail.
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * throw new EncryptedStorageError('Failed to decrypt: invalid key');
124
+ * ```
125
+ */
126
+ export declare class EncryptedStorageError extends StorageError {
127
+ constructor(message: string);
128
+ }
@@ -7,7 +7,12 @@
7
7
  export type { StorageAdapter, NamespacedStorage, RootStorage, SetOptions, SetEntry, MessageHandler, Unsubscribe, MemoryAdapterOptions, RedisAdapterOptions, VercelKvAdapterOptions, UpstashAdapterOptions, StorageType, StorageConfig, } from './types';
8
8
  export { createStorage, createMemoryStorage, getDetectedStorageType } from './factory';
9
9
  export { NamespacedStorageImpl, createRootStorage, createNamespacedStorage, buildPrefix, NAMESPACE_SEPARATOR, } from './namespace';
10
- export { StorageError, StorageConnectionError, StorageOperationError, StorageNotSupportedError, StorageConfigError, StorageTTLError, StoragePatternError, StorageNotConnectedError, } from './errors';
11
- export { BaseStorageAdapter, MemoryStorageAdapter, RedisStorageAdapter, VercelKvStorageAdapter, UpstashStorageAdapter, } from './adapters';
10
+ export { StorageError, StorageConnectionError, StorageOperationError, StorageNotSupportedError, StorageConfigError, StorageTTLError, StoragePatternError, StorageNotConnectedError, EncryptedStorageError, } from './errors';
11
+ export { TypedStorage } from './typed-storage';
12
+ export type { TypedStorageOptions, TypedSetOptions, TypedSetEntry } from './typed-storage.types';
13
+ export { EncryptedTypedStorage } from './encrypted-typed-storage';
14
+ export type { EncryptedTypedStorageOptions, EncryptedSetOptions, EncryptedSetEntry, EncryptionKey, StoredEncryptedBlob, ClientKeyBinding, } from './encrypted-typed-storage.types';
15
+ export { BaseStorageAdapter, MemoryStorageAdapter, RedisStorageAdapter, VercelKvStorageAdapter, UpstashStorageAdapter, FileSystemStorageAdapter, } from './adapters';
16
+ export type { FileSystemAdapterOptions } from './adapters';
12
17
  export { globToRegex, matchesPattern, validatePattern, escapeGlob } from './utils/pattern';
13
18
  export { MAX_TTL_SECONDS, validateTTL, validateOptionalTTL, ttlToExpiresAt, expiresAtToTTL, isExpired, normalizeTTL, } from './utils/ttl';
@@ -0,0 +1,129 @@
1
+ /**
2
+ * TypedStorage
3
+ *
4
+ * A generic wrapper that provides type-safe JSON serialization
5
+ * on top of StorageAdapter or NamespacedStorage.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { createStorage, TypedStorage } from '@frontmcp/utils';
10
+ *
11
+ * interface User {
12
+ * id: string;
13
+ * name: string;
14
+ * }
15
+ *
16
+ * const storage = await createStorage({ type: 'memory' });
17
+ * const users = new TypedStorage<User>(storage);
18
+ *
19
+ * await users.set('user:1', { id: '1', name: 'Alice' });
20
+ * const user = await users.get('user:1');
21
+ * ```
22
+ */
23
+ import type { StorageAdapter, NamespacedStorage, SetOptions } from './types';
24
+ import type { TypedStorageOptions, TypedSetEntry } from './typed-storage.types';
25
+ /**
26
+ * TypedStorage provides type-safe JSON serialization on top of StorageAdapter.
27
+ *
28
+ * Features:
29
+ * - Automatic JSON serialization/deserialization
30
+ * - Optional Zod schema validation on read
31
+ * - Custom serializer support
32
+ * - Batch operations (mget/mset)
33
+ * - Full StorageAdapter method access
34
+ */
35
+ export declare class TypedStorage<T> {
36
+ private readonly storage;
37
+ private readonly serialize;
38
+ private readonly deserialize;
39
+ private readonly schema?;
40
+ private readonly throwOnInvalid;
41
+ constructor(storage: StorageAdapter | NamespacedStorage, options?: TypedStorageOptions<T>);
42
+ /**
43
+ * Get a typed value by key.
44
+ *
45
+ * @param key - Storage key
46
+ * @returns The typed value, or null if not found or invalid
47
+ */
48
+ get(key: string): Promise<T | null>;
49
+ /**
50
+ * Set a typed value with optional TTL.
51
+ *
52
+ * @param key - Storage key
53
+ * @param value - Typed value to store
54
+ * @param options - Optional TTL and conditional flags
55
+ */
56
+ set(key: string, value: T, options?: SetOptions): Promise<void>;
57
+ /**
58
+ * Delete a key.
59
+ *
60
+ * @param key - Storage key
61
+ * @returns true if key existed and was deleted
62
+ */
63
+ delete(key: string): Promise<boolean>;
64
+ /**
65
+ * Check if a key exists.
66
+ *
67
+ * @param key - Storage key
68
+ * @returns true if key exists
69
+ */
70
+ exists(key: string): Promise<boolean>;
71
+ /**
72
+ * Get multiple typed values.
73
+ *
74
+ * @param keys - Array of storage keys
75
+ * @returns Array of typed values (null for missing/invalid keys)
76
+ */
77
+ mget(keys: string[]): Promise<(T | null)[]>;
78
+ /**
79
+ * Set multiple typed values.
80
+ *
81
+ * @param entries - Array of key-value-options entries
82
+ */
83
+ mset(entries: TypedSetEntry<T>[]): Promise<void>;
84
+ /**
85
+ * Delete multiple keys.
86
+ *
87
+ * @param keys - Array of storage keys
88
+ * @returns Number of keys actually deleted
89
+ */
90
+ mdelete(keys: string[]): Promise<number>;
91
+ /**
92
+ * Update TTL on an existing key.
93
+ *
94
+ * @param key - Storage key
95
+ * @param ttlSeconds - New TTL in seconds
96
+ * @returns true if key exists and TTL was set
97
+ */
98
+ expire(key: string, ttlSeconds: number): Promise<boolean>;
99
+ /**
100
+ * Get remaining TTL for a key.
101
+ *
102
+ * @param key - Storage key
103
+ * @returns TTL in seconds, -1 if no TTL, or null if key doesn't exist
104
+ */
105
+ ttl(key: string): Promise<number | null>;
106
+ /**
107
+ * List keys matching a pattern.
108
+ *
109
+ * @param pattern - Glob pattern (default: '*' for all keys)
110
+ * @returns Array of matching keys
111
+ */
112
+ keys(pattern?: string): Promise<string[]>;
113
+ /**
114
+ * Count keys matching a pattern.
115
+ *
116
+ * @param pattern - Glob pattern (default: '*' for all keys)
117
+ * @returns Number of matching keys
118
+ */
119
+ count(pattern?: string): Promise<number>;
120
+ /**
121
+ * Get the underlying storage adapter.
122
+ * Use with caution - operations bypass type safety.
123
+ */
124
+ get raw(): StorageAdapter | NamespacedStorage;
125
+ /**
126
+ * Parse and validate a raw value.
127
+ */
128
+ private parseValue;
129
+ }