wip library to store cold objects in s3, warm objects on disk, and hot objects in memory
nodejs
typescript
1/**
2 * Simple glob pattern matching for key placement rules.
3 *
4 * Supports:
5 * - `*` matches any characters except `/`
6 * - `**` matches any characters including `/` (including empty string)
7 * - `{a,b,c}` matches any of the alternatives
8 * - Exact strings match exactly
9 */
10export function matchGlob(pattern: string, key: string): boolean {
11 // Handle exact match
12 if (!pattern.includes('*') && !pattern.includes('{')) {
13 return pattern === key;
14 }
15
16 // Escape regex special chars (except * and {})
17 let regex = pattern.replace(/[.+^$|\\()[\]]/g, '\\$&');
18
19 // Handle {a,b,c} alternation
20 regex = regex.replace(/\{([^}]+)\}/g, (_, alts) => `(${alts.split(',').join('|')})`);
21
22 // Use placeholder to avoid double-processing
23 const DOUBLE = '\x00DOUBLE\x00';
24 const SINGLE = '\x00SINGLE\x00';
25
26 // Mark ** and * with placeholders
27 regex = regex.replace(/\*\*/g, DOUBLE);
28 regex = regex.replace(/\*/g, SINGLE);
29
30 // Replace placeholders with regex patterns
31 // ** matches anything (including /)
32 // When followed by /, it's optional (matches zero or more path segments)
33 regex = regex
34 .replace(new RegExp(`${DOUBLE}/`, 'g'), '(?:.*/)?') // **/ -> optional path prefix
35 .replace(new RegExp(`/${DOUBLE}`, 'g'), '(?:/.*)?') // /** -> optional path suffix
36 .replace(new RegExp(DOUBLE, 'g'), '.*') // ** alone -> match anything
37 .replace(new RegExp(SINGLE, 'g'), '[^/]*'); // * -> match non-slash
38
39 return new RegExp(`^${regex}$`).test(key);
40}