@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.
- package/CHANGELOG.md +12 -0
- package/README.md +110 -0
- package/content/content.d.ts +43 -0
- package/content/index.d.ts +1 -0
- package/crypto/browser.d.ts +11 -0
- package/crypto/encrypted-blob.d.ts +157 -0
- package/crypto/index.d.ts +98 -0
- package/crypto/jwt-alg.d.ts +8 -0
- package/crypto/node.d.ts +59 -0
- package/crypto/pkce/index.d.ts +9 -0
- package/crypto/pkce/pkce.d.ts +140 -0
- package/crypto/runtime.d.ts +18 -0
- package/crypto/secret-persistence/index.d.ts +25 -0
- package/crypto/secret-persistence/persistence.d.ts +97 -0
- package/crypto/secret-persistence/schema.d.ts +34 -0
- package/crypto/secret-persistence/types.d.ts +65 -0
- package/crypto/types.d.ts +61 -0
- package/escape/escape.d.ts +101 -0
- package/escape/index.d.ts +1 -0
- package/esm/index.mjs +3264 -0
- package/esm/package.json +53 -0
- package/fs/fs.d.ts +254 -0
- package/fs/index.d.ts +1 -0
- package/http/http.d.ts +20 -0
- package/http/index.d.ts +1 -0
- package/index.d.ts +18 -0
- package/index.js +3425 -0
- package/naming/index.d.ts +1 -0
- package/naming/naming.d.ts +79 -0
- package/package.json +3 -2
- package/path/index.d.ts +1 -0
- package/path/path.d.ts +34 -0
- package/regex/index.d.ts +24 -0
- package/regex/patterns.d.ts +155 -0
- package/regex/safe-regex.d.ts +179 -0
- package/serialization/index.d.ts +1 -0
- package/serialization/serialization.d.ts +33 -0
- package/storage/adapters/base.d.ts +90 -0
- package/storage/adapters/index.d.ts +10 -0
- package/storage/adapters/memory.d.ts +99 -0
- package/storage/adapters/redis.d.ts +88 -0
- package/storage/adapters/upstash.d.ts +81 -0
- package/storage/adapters/vercel-kv.d.ts +69 -0
- package/storage/errors.d.ts +117 -0
- package/storage/factory.d.ts +70 -0
- package/storage/index.d.ts +13 -0
- package/storage/namespace.d.ts +88 -0
- package/storage/types.d.ts +428 -0
- package/storage/utils/index.d.ts +5 -0
- package/storage/utils/pattern.d.ts +71 -0
- package/storage/utils/ttl.d.ts +54 -0
- package/uri/index.d.ts +2 -0
- package/uri/uri-template.d.ts +92 -0
- 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.
|
|
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",
|
package/path/index.d.ts
ADDED
|
@@ -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;
|
package/regex/index.d.ts
ADDED
|
@@ -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';
|