@frontmcp/utils 0.0.1 → 0.7.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +110 -0
  3. package/content/content.d.ts +43 -0
  4. package/content/index.d.ts +1 -0
  5. package/crypto/browser.d.ts +11 -0
  6. package/crypto/encrypted-blob.d.ts +157 -0
  7. package/crypto/index.d.ts +98 -0
  8. package/crypto/jwt-alg.d.ts +8 -0
  9. package/crypto/node.d.ts +59 -0
  10. package/crypto/pkce/index.d.ts +9 -0
  11. package/crypto/pkce/pkce.d.ts +140 -0
  12. package/crypto/runtime.d.ts +18 -0
  13. package/crypto/secret-persistence/index.d.ts +25 -0
  14. package/crypto/secret-persistence/persistence.d.ts +97 -0
  15. package/crypto/secret-persistence/schema.d.ts +34 -0
  16. package/crypto/secret-persistence/types.d.ts +65 -0
  17. package/crypto/types.d.ts +61 -0
  18. package/escape/escape.d.ts +101 -0
  19. package/escape/index.d.ts +1 -0
  20. package/esm/index.mjs +3264 -0
  21. package/esm/package.json +53 -0
  22. package/fs/fs.d.ts +254 -0
  23. package/fs/index.d.ts +1 -0
  24. package/http/http.d.ts +20 -0
  25. package/http/index.d.ts +1 -0
  26. package/index.d.ts +18 -0
  27. package/index.js +3425 -0
  28. package/naming/index.d.ts +1 -0
  29. package/naming/naming.d.ts +79 -0
  30. package/package.json +3 -2
  31. package/path/index.d.ts +1 -0
  32. package/path/path.d.ts +34 -0
  33. package/regex/index.d.ts +24 -0
  34. package/regex/patterns.d.ts +155 -0
  35. package/regex/safe-regex.d.ts +179 -0
  36. package/serialization/index.d.ts +1 -0
  37. package/serialization/serialization.d.ts +33 -0
  38. package/storage/adapters/base.d.ts +90 -0
  39. package/storage/adapters/index.d.ts +10 -0
  40. package/storage/adapters/memory.d.ts +99 -0
  41. package/storage/adapters/redis.d.ts +88 -0
  42. package/storage/adapters/upstash.d.ts +81 -0
  43. package/storage/adapters/vercel-kv.d.ts +69 -0
  44. package/storage/errors.d.ts +117 -0
  45. package/storage/factory.d.ts +70 -0
  46. package/storage/index.d.ts +13 -0
  47. package/storage/namespace.d.ts +88 -0
  48. package/storage/types.d.ts +428 -0
  49. package/storage/utils/index.d.ts +5 -0
  50. package/storage/utils/pattern.d.ts +71 -0
  51. package/storage/utils/ttl.d.ts +54 -0
  52. package/uri/index.d.ts +2 -0
  53. package/uri/uri-template.d.ts +92 -0
  54. package/uri/uri-validation.d.ts +46 -0
@@ -0,0 +1 @@
1
+ export { NameCase, splitWords, toCase, sepFor, shortHash, ensureMaxLen, idFromString } from './naming';
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Shared naming and case conversion utilities.
3
+ *
4
+ * Provides functions for transforming strings between different naming conventions
5
+ * (camelCase, snake_case, kebab-case, etc.) and generating unique identifiers.
6
+ */
7
+ /**
8
+ * Supported naming conventions for identifiers.
9
+ */
10
+ export type NameCase = 'snake' | 'kebab' | 'dot' | 'camel';
11
+ /**
12
+ * Split a string into words, handling camelCase, PascalCase, and delimiters.
13
+ *
14
+ * @param input - The string to split
15
+ * @returns Array of words
16
+ *
17
+ * @example
18
+ * splitWords("myFunctionName") // ["my", "Function", "Name"]
19
+ * splitWords("my_function_name") // ["my", "function", "name"]
20
+ * splitWords("MyClassName") // ["My", "Class", "Name"]
21
+ */
22
+ export declare function splitWords(input: string): string[];
23
+ /**
24
+ * Convert words to a specific naming case.
25
+ *
26
+ * @param words - Array of words to convert
27
+ * @param kind - Target naming case
28
+ * @returns Converted string
29
+ *
30
+ * @example
31
+ * toCase(["my", "function"], "snake") // "my_function"
32
+ * toCase(["my", "function"], "kebab") // "my-function"
33
+ * toCase(["my", "function"], "camel") // "myFunction"
34
+ * toCase(["My", "Class"], "dot") // "my.class"
35
+ */
36
+ export declare function toCase(words: string[], kind: NameCase): string;
37
+ /**
38
+ * Get the separator character for a naming case.
39
+ *
40
+ * @param kind - The naming case
41
+ * @returns Separator character ('_', '-', '.', or '' for camelCase)
42
+ */
43
+ export declare function sepFor(kind: NameCase): string;
44
+ /**
45
+ * Generate a short hash (6 hex chars) from a string.
46
+ * Uses djb2 algorithm for fast, reasonable distribution.
47
+ *
48
+ * @param s - String to hash
49
+ * @returns 6-character hex string
50
+ *
51
+ * @example
52
+ * shortHash("some-string") // "a1b2c3"
53
+ */
54
+ export declare function shortHash(s: string): string;
55
+ /**
56
+ * Ensure a name fits within a maximum length, using hash truncation if needed.
57
+ * Preserves meaningful suffix while adding a hash for uniqueness.
58
+ *
59
+ * @param name - The name to potentially truncate
60
+ * @param max - Maximum allowed length
61
+ * @returns Name within max length, with hash if truncated
62
+ *
63
+ * @example
64
+ * ensureMaxLen("short", 20) // "short"
65
+ * ensureMaxLen("very-long-name-that-exceeds-limit", 20) // "very-a1b2c3-limit"
66
+ */
67
+ export declare function ensureMaxLen(name: string, max: number): string;
68
+ /**
69
+ * Convert a string to a valid identifier by removing invalid characters.
70
+ * Replaces any run of invalid characters with a hyphen.
71
+ *
72
+ * @param name - The string to convert
73
+ * @returns Valid identifier (alphanumeric, hyphens, underscores, max 64 chars)
74
+ *
75
+ * @example
76
+ * idFromString("My Function Name!") // "My-Function-Name"
77
+ * idFromString("foo@bar#baz") // "foo-bar-baz"
78
+ */
79
+ export declare function idFromString(name: string): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/utils",
3
- "version": "0.0.1",
3
+ "version": "0.7.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",
@@ -25,7 +25,8 @@
25
25
  "homepage": "https://github.com/agentfront/frontmcp/blob/main/libs/utils/README.md",
26
26
  "dependencies": {
27
27
  "@noble/hashes": "^2.0.1",
28
- "@noble/ciphers": "^2.1.1"
28
+ "@noble/ciphers": "^2.1.1",
29
+ "ast-guard": "^2.4.0"
29
30
  },
30
31
  "type": "commonjs",
31
32
  "main": "./index.js",
@@ -0,0 +1 @@
1
+ export { trimSlashes, joinPath } from './path';
package/path/path.d.ts ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Path utilities for URL and file path manipulation.
3
+ *
4
+ * Provides common operations for normalizing and joining path segments.
5
+ */
6
+ /**
7
+ * Trim leading and trailing slashes from a string.
8
+ *
9
+ * Uses a safe non-regex approach to avoid ReDoS vulnerabilities
10
+ * (the pattern /^\/+|\/+$/g can cause polynomial backtracking).
11
+ *
12
+ * @param s - The string to trim (null/undefined treated as empty string)
13
+ * @returns String with leading/trailing slashes removed
14
+ *
15
+ * @example
16
+ * trimSlashes('/path/to/resource/') // 'path/to/resource'
17
+ * trimSlashes('no-slashes') // 'no-slashes'
18
+ * trimSlashes('///multiple///') // 'multiple'
19
+ */
20
+ export declare function trimSlashes(s: string | null | undefined): string;
21
+ /**
22
+ * Join URL path segments with a single slash and no trailing slash.
23
+ * Empty segments are filtered out.
24
+ *
25
+ * @param parts - Path segments to join
26
+ * @returns Joined path starting with / or empty string
27
+ *
28
+ * @example
29
+ * joinPath('api', 'v1', 'users') // '/api/v1/users'
30
+ * joinPath('/api/', '/v1/', '/users/') // '/api/v1/users'
31
+ * joinPath('', 'path', '') // '/path'
32
+ * joinPath() // ''
33
+ */
34
+ export declare function joinPath(...parts: string[]): string;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Safe regex utilities for preventing ReDoS (Regular Expression Denial of Service) attacks.
3
+ *
4
+ * Uses ast-guard's analyzeForReDoS function to validate patterns and provides
5
+ * input length guards to prevent polynomial-time attacks on untrusted data.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { isPatternSafe, safeTest, safeReplace, trimBoth } from '@frontmcp/utils';
10
+ *
11
+ * // Check if a pattern is safe
12
+ * if (isPatternSafe(myPattern)) {
13
+ * // Use pattern
14
+ * }
15
+ *
16
+ * // Safe regex operations with input length guards
17
+ * const result = safeTest(/foo/, userInput, { maxInputLength: 10000 });
18
+ *
19
+ * // Pre-built safe patterns for common operations
20
+ * const trimmed = trimBoth(input, '/');
21
+ * ```
22
+ */
23
+ export * from './safe-regex';
24
+ export * from './patterns';
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Pre-built safe pattern utilities for common string operations.
3
+ *
4
+ * These utilities avoid vulnerable regex patterns like alternation with
5
+ * greedy quantifiers (e.g., /^\/+|\/+$/g) that can cause ReDoS attacks.
6
+ */
7
+ /**
8
+ * Remove leading occurrences of a character from a string.
9
+ *
10
+ * This is a safe alternative to patterns like /^X+/ that avoids
11
+ * potential ReDoS issues with alternation patterns.
12
+ *
13
+ * @param input - String to trim
14
+ * @param char - Single character to remove from the start
15
+ * @returns String with leading characters removed
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * trimLeading('///path', '/'); // 'path'
20
+ * trimLeading('---name', '-'); // 'name'
21
+ * trimLeading('hello', 'x'); // 'hello'
22
+ * ```
23
+ */
24
+ export declare function trimLeading(input: string, char: string): string;
25
+ /**
26
+ * Remove trailing occurrences of a character from a string.
27
+ *
28
+ * This is a safe alternative to patterns like /X+$/ that avoids
29
+ * potential ReDoS issues with alternation patterns.
30
+ *
31
+ * @param input - String to trim
32
+ * @param char - Single character to remove from the end
33
+ * @returns String with trailing characters removed
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * trimTrailing('path///', '/'); // 'path'
38
+ * trimTrailing('name---', '-'); // 'name'
39
+ * trimTrailing('hello', 'x'); // 'hello'
40
+ * ```
41
+ */
42
+ export declare function trimTrailing(input: string, char: string): string;
43
+ /**
44
+ * Remove both leading and trailing occurrences of a character from a string.
45
+ *
46
+ * This is a safe alternative to the vulnerable pattern /^X+|X+$/g
47
+ * which uses alternation with greedy quantifiers and can cause ReDoS.
48
+ *
49
+ * @param input - String to trim
50
+ * @param char - Single character to remove from both ends
51
+ * @returns String with leading and trailing characters removed
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * trimBoth('///path///', '/'); // 'path'
56
+ * trimBoth('---name---', '-'); // 'name'
57
+ * trimBoth('/single/', '/'); // 'single'
58
+ * ```
59
+ */
60
+ export declare function trimBoth(input: string, char: string): string;
61
+ /**
62
+ * Remove multiple leading/trailing characters from a string.
63
+ *
64
+ * @param input - String to trim
65
+ * @param chars - Set of characters to remove from both ends
66
+ * @returns String with specified characters removed from both ends
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * trimChars(' -name- ', new Set([' ', '-'])); // 'name'
71
+ * ```
72
+ */
73
+ export declare function trimChars(input: string, chars: Set<string>): string;
74
+ /**
75
+ * Extract parameters from a braced template string safely.
76
+ *
77
+ * Uses a non-backtracking approach to parse {param} patterns,
78
+ * avoiding the vulnerable /\{([^}]+)\}/g pattern.
79
+ *
80
+ * @param template - Template string containing {param} placeholders
81
+ * @param maxLength - Maximum template length to process (default: 50000)
82
+ * @returns Array of parameter names found in the template
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * extractBracedParams('/users/{userId}/posts/{postId}');
87
+ * // ['userId', 'postId']
88
+ *
89
+ * extractBracedParams('Hello {name}!');
90
+ * // ['name']
91
+ * ```
92
+ */
93
+ export declare function extractBracedParams(template: string, maxLength?: number): string[];
94
+ /**
95
+ * Expand a template string by replacing {param} placeholders with values.
96
+ *
97
+ * Uses a safe character-by-character approach instead of regex.
98
+ *
99
+ * @param template - Template string containing {param} placeholders
100
+ * @param values - Object mapping parameter names to values
101
+ * @param maxLength - Maximum template length to process (default: 50000)
102
+ * @returns Expanded string with placeholders replaced
103
+ *
104
+ * @example
105
+ * ```typescript
106
+ * expandTemplate('/users/{userId}', { userId: '123' });
107
+ * // '/users/123'
108
+ *
109
+ * expandTemplate('Hello {name}!', { name: 'World' });
110
+ * // 'Hello World!'
111
+ * ```
112
+ */
113
+ export declare function expandTemplate(template: string, values: Record<string, string>, maxLength?: number): string;
114
+ /**
115
+ * Check if a string contains template placeholders.
116
+ *
117
+ * Uses a simple indexOf check instead of regex.
118
+ *
119
+ * @param str - String to check
120
+ * @param maxLength - Maximum string length to check (default: 50000)
121
+ * @returns true if string contains {param} style placeholders
122
+ */
123
+ export declare function hasTemplatePlaceholders(str: string, maxLength?: number): boolean;
124
+ /**
125
+ * Collapse multiple consecutive characters into a single occurrence.
126
+ *
127
+ * Safe alternative to patterns like /X+/g which can be combined
128
+ * with other patterns to create ReDoS vulnerabilities.
129
+ *
130
+ * @param input - String to process
131
+ * @param char - Character to collapse
132
+ * @returns String with consecutive characters collapsed
133
+ *
134
+ * @example
135
+ * ```typescript
136
+ * collapseChar('foo///bar', '/'); // 'foo/bar'
137
+ * collapseChar('hello world', ' '); // 'hello world'
138
+ * ```
139
+ */
140
+ export declare function collapseChar(input: string, char: string): string;
141
+ /**
142
+ * Collapse all whitespace to single spaces.
143
+ *
144
+ * Safe alternative to /\s+/g which can be part of vulnerable patterns.
145
+ *
146
+ * @param input - String to process
147
+ * @param maxLength - Maximum input length to process (default: 50000)
148
+ * @returns String with whitespace collapsed to single spaces
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * collapseWhitespace('hello world\n\nfoo'); // 'hello world foo'
153
+ * ```
154
+ */
155
+ export declare function collapseWhitespace(input: string, maxLength?: number): string;
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Safe regex utilities using ast-guard's ReDoS analysis.
3
+ *
4
+ * These utilities protect against ReDoS (Regular Expression Denial of Service)
5
+ * attacks by validating patterns and enforcing input length limits.
6
+ */
7
+ import { REDOS_THRESHOLDS } from 'ast-guard';
8
+ /**
9
+ * Default maximum input length for safe regex operations.
10
+ * Inputs longer than this will be rejected to prevent ReDoS attacks.
11
+ */
12
+ export declare const DEFAULT_MAX_INPUT_LENGTH = 50000;
13
+ /**
14
+ * Configuration options for safe regex operations.
15
+ */
16
+ export interface SafeRegexOptions {
17
+ /**
18
+ * Maximum input length to process.
19
+ * If input exceeds this, operations return null/fallback.
20
+ * @default 50000
21
+ */
22
+ maxInputLength?: number;
23
+ /**
24
+ * Analysis level for pattern vulnerability detection.
25
+ * - 'catastrophic': Only detect exponential-time vulnerabilities (faster)
26
+ * - 'polynomial': Also detect polynomial-time vulnerabilities (more thorough)
27
+ * @default 'polynomial'
28
+ */
29
+ level?: 'catastrophic' | 'polynomial';
30
+ /**
31
+ * If true, throw an error when pattern is vulnerable instead of returning null.
32
+ * @default false
33
+ */
34
+ throwOnVulnerable?: boolean;
35
+ }
36
+ /**
37
+ * Result from pattern analysis.
38
+ */
39
+ export interface PatternAnalysisResult {
40
+ /** Whether the pattern is safe to use */
41
+ safe: boolean;
42
+ /** Vulnerability score (0-100, higher = more vulnerable) */
43
+ score: number;
44
+ /** Type of vulnerability detected, if any */
45
+ vulnerabilityType?: string;
46
+ /** Human-readable explanation of the vulnerability */
47
+ explanation?: string;
48
+ }
49
+ /**
50
+ * Analyze a regex pattern for ReDoS vulnerability.
51
+ *
52
+ * Uses ast-guard's analyzeForReDoS to detect patterns that could cause
53
+ * exponential or polynomial backtracking on malicious input.
54
+ *
55
+ * @param pattern - Regex pattern to analyze (string or RegExp)
56
+ * @param level - Analysis level: 'catastrophic' or 'polynomial'
57
+ * @returns Analysis result with safety assessment
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * const result = analyzePattern('(a+)+');
62
+ * // result.safe === false (nested quantifiers)
63
+ *
64
+ * const result2 = analyzePattern('[a-z]+');
65
+ * // result2.safe === true
66
+ * ```
67
+ */
68
+ export declare function analyzePattern(pattern: string | RegExp, level?: 'catastrophic' | 'polynomial'): PatternAnalysisResult;
69
+ /**
70
+ * Check if a regex pattern is safe from ReDoS vulnerabilities.
71
+ *
72
+ * @param pattern - Regex pattern to check (string or RegExp)
73
+ * @param level - Analysis level: 'catastrophic' or 'polynomial'
74
+ * @returns true if pattern is safe, false if vulnerable
75
+ *
76
+ * @example
77
+ * ```typescript
78
+ * isPatternSafe('(a+)+'); // false - nested quantifiers
79
+ * isPatternSafe('[a-z]+'); // true
80
+ * isPatternSafe(/^foo$/); // true
81
+ * ```
82
+ */
83
+ export declare function isPatternSafe(pattern: string | RegExp, level?: 'catastrophic' | 'polynomial'): boolean;
84
+ /**
85
+ * Create a validated RegExp that has been checked for ReDoS vulnerabilities.
86
+ *
87
+ * @param pattern - Pattern string
88
+ * @param flags - Optional regex flags
89
+ * @param options - Safety options
90
+ * @returns RegExp if pattern is safe, null if vulnerable or invalid
91
+ *
92
+ * @example
93
+ * ```typescript
94
+ * const regex = createSafeRegExp('[a-z]+', 'g');
95
+ * if (regex) {
96
+ * // Pattern is safe to use
97
+ * }
98
+ * ```
99
+ */
100
+ export declare function createSafeRegExp(pattern: string, flags?: string, options?: SafeRegexOptions): RegExp | null;
101
+ /**
102
+ * Execute regex test() with input length protection.
103
+ *
104
+ * Returns null if input exceeds maxInputLength to prevent ReDoS attacks.
105
+ *
106
+ * @param pattern - RegExp to test with
107
+ * @param input - String to test
108
+ * @param options - Safety options including maxInputLength
109
+ * @returns Match result, or null if input is too long
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * const result = safeTest(/foo/, userInput, { maxInputLength: 10000 });
114
+ * if (result === null) {
115
+ * // Input was too long, rejected for safety
116
+ * } else if (result) {
117
+ * // Pattern matched
118
+ * }
119
+ * ```
120
+ */
121
+ export declare function safeTest(pattern: RegExp, input: string, options?: SafeRegexOptions): boolean | null;
122
+ /**
123
+ * Execute regex match() with input length protection.
124
+ *
125
+ * Returns null if input exceeds maxInputLength to prevent ReDoS attacks.
126
+ *
127
+ * @param pattern - RegExp to match with
128
+ * @param input - String to match against
129
+ * @param options - Safety options including maxInputLength
130
+ * @returns Match result array, or null if input is too long or no match
131
+ *
132
+ * @example
133
+ * ```typescript
134
+ * const matches = safeMatch(/(\d+)/, userInput, { maxInputLength: 5000 });
135
+ * ```
136
+ */
137
+ export declare function safeMatch(pattern: RegExp, input: string, options?: SafeRegexOptions): RegExpMatchArray | null;
138
+ /**
139
+ * Execute regex replace() with input length protection.
140
+ *
141
+ * Returns original input unchanged if it exceeds maxInputLength to prevent ReDoS attacks.
142
+ *
143
+ * @param input - String to perform replacement on
144
+ * @param pattern - RegExp pattern to match
145
+ * @param replacement - Replacement string or function
146
+ * @param options - Safety options including maxInputLength
147
+ * @returns Replaced string, or original input if too long
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * const result = safeReplace(userInput, /foo/g, 'bar', { maxInputLength: 10000 });
152
+ * ```
153
+ */
154
+ export declare function safeReplace(input: string, pattern: RegExp, replacement: string | ((match: string, ...args: unknown[]) => string), options?: SafeRegexOptions): string;
155
+ /**
156
+ * Execute regex exec() with input length protection.
157
+ *
158
+ * Returns null if input exceeds maxInputLength to prevent ReDoS attacks.
159
+ *
160
+ * @param pattern - RegExp to execute
161
+ * @param input - String to execute against
162
+ * @param options - Safety options including maxInputLength
163
+ * @returns Exec result array, or null if input is too long or no match
164
+ *
165
+ * @example
166
+ * ```typescript
167
+ * const result = safeExec(/(\w+)/, userInput, { maxInputLength: 10000 });
168
+ * ```
169
+ */
170
+ export declare function safeExec(pattern: RegExp, input: string, options?: SafeRegexOptions): RegExpExecArray | null;
171
+ /**
172
+ * Check if input length is within safe limits for regex operations.
173
+ *
174
+ * @param input - String to check
175
+ * @param maxLength - Maximum allowed length
176
+ * @returns true if input is within limits
177
+ */
178
+ export declare function isInputLengthSafe(input: string, maxLength?: number): boolean;
179
+ export { REDOS_THRESHOLDS };
@@ -0,0 +1 @@
1
+ export { safeStringify } from './serialization';
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Safe JSON Serialization Utilities
3
+ *
4
+ * Utilities for safely serializing values to JSON, handling circular references
5
+ * and other edge cases that would cause JSON.stringify to fail.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ /**
10
+ * Safely stringify a value, handling circular references and other edge cases.
11
+ *
12
+ * Uses a WeakSet to track visited objects and replaces circular references
13
+ * with the string '[Circular]' instead of throwing an error.
14
+ *
15
+ * @param value - The value to stringify
16
+ * @param space - Optional indentation for pretty-printing (passed to JSON.stringify)
17
+ * @returns JSON string representation of the value
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * // Normal object
22
+ * safeStringify({ name: 'test' }); // '{"name":"test"}'
23
+ *
24
+ * // Circular reference
25
+ * const obj = { name: 'test' };
26
+ * obj.self = obj;
27
+ * safeStringify(obj); // '{"name":"test","self":"[Circular]"}'
28
+ *
29
+ * // Pretty print
30
+ * safeStringify({ name: 'test' }, 2); // '{\n "name": "test"\n}'
31
+ * ```
32
+ */
33
+ export declare function safeStringify(value: unknown, space?: number): string;
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Base Storage Adapter
3
+ *
4
+ * Abstract base class for storage adapters.
5
+ * Provides common validation and default implementations.
6
+ */
7
+ import type { StorageAdapter, SetOptions, SetEntry, MessageHandler, Unsubscribe } from '../types';
8
+ /**
9
+ * Abstract base class for storage adapters.
10
+ * Subclasses must implement the abstract methods.
11
+ */
12
+ export declare abstract class BaseStorageAdapter implements StorageAdapter {
13
+ /**
14
+ * Backend name for error messages (e.g., 'memory', 'redis').
15
+ */
16
+ protected abstract readonly backendName: string;
17
+ /**
18
+ * Whether the adapter is currently connected.
19
+ */
20
+ protected connected: boolean;
21
+ abstract connect(): Promise<void>;
22
+ abstract disconnect(): Promise<void>;
23
+ abstract ping(): Promise<boolean>;
24
+ /**
25
+ * Ensure adapter is connected before operations.
26
+ * @throws StorageNotConnectedError if not connected
27
+ */
28
+ protected ensureConnected(): void;
29
+ abstract get(key: string): Promise<string | null>;
30
+ /**
31
+ * Set with validation.
32
+ */
33
+ set(key: string, value: string, options?: SetOptions): Promise<void>;
34
+ /**
35
+ * Internal set implementation. Override in subclass.
36
+ */
37
+ protected abstract doSet(key: string, value: string, options?: SetOptions): Promise<void>;
38
+ abstract delete(key: string): Promise<boolean>;
39
+ abstract exists(key: string): Promise<boolean>;
40
+ /**
41
+ * Default mget: sequential gets.
42
+ * Override for more efficient implementations.
43
+ */
44
+ mget(keys: string[]): Promise<(string | null)[]>;
45
+ /**
46
+ * Default mset: sequential sets.
47
+ * Override for atomic/pipelined implementations.
48
+ */
49
+ mset(entries: SetEntry[]): Promise<void>;
50
+ /**
51
+ * Default mdelete: sequential deletes.
52
+ * Override for more efficient implementations.
53
+ */
54
+ mdelete(keys: string[]): Promise<number>;
55
+ abstract expire(key: string, ttlSeconds: number): Promise<boolean>;
56
+ abstract ttl(key: string): Promise<number | null>;
57
+ abstract keys(pattern?: string): Promise<string[]>;
58
+ /**
59
+ * Default count: keys().length.
60
+ * Override for more efficient implementations.
61
+ */
62
+ count(pattern?: string): Promise<number>;
63
+ abstract incr(key: string): Promise<number>;
64
+ abstract decr(key: string): Promise<number>;
65
+ abstract incrBy(key: string, amount: number): Promise<number>;
66
+ /**
67
+ * Default: pub/sub not supported.
68
+ * Override in adapters that support it.
69
+ */
70
+ supportsPubSub(): boolean;
71
+ /**
72
+ * Default: throw not supported error.
73
+ * Override in adapters that support pub/sub.
74
+ */
75
+ publish(_channel: string, _message: string): Promise<number>;
76
+ /**
77
+ * Default: throw not supported error.
78
+ * Override in adapters that support pub/sub.
79
+ */
80
+ subscribe(_channel: string, _handler: MessageHandler): Promise<Unsubscribe>;
81
+ /**
82
+ * Get suggestion message for pub/sub not supported error.
83
+ * Override in specific adapters.
84
+ */
85
+ protected getPubSubSuggestion(): string;
86
+ /**
87
+ * Validate set options.
88
+ */
89
+ protected validateSetOptions(options?: SetOptions): void;
90
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Storage Adapters
3
+ *
4
+ * Export all storage adapter implementations.
5
+ */
6
+ export { BaseStorageAdapter } from './base';
7
+ export { MemoryStorageAdapter } from './memory';
8
+ export { RedisStorageAdapter } from './redis';
9
+ export { VercelKvStorageAdapter } from './vercel-kv';
10
+ export { UpstashStorageAdapter } from './upstash';