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(
21 /\{([^}]+)\}/g,
22 (_match: string, alts: string) => `(${alts.split(',').join('|')})`,
23 );
24
25 // Use placeholder to avoid double-processing
26 const DOUBLE = '\x00DOUBLE\x00';
27 const SINGLE = '\x00SINGLE\x00';
28
29 // Mark ** and * with placeholders
30 regex = regex.replace(/\*\*/g, DOUBLE);
31 regex = regex.replace(/\*/g, SINGLE);
32
33 // Replace placeholders with regex patterns
34 // ** matches anything (including /)
35 // When followed by /, it's optional (matches zero or more path segments)
36 regex = regex
37 .replace(new RegExp(`${DOUBLE}/`, 'g'), '(?:.*/)?') // **/ -> optional path prefix
38 .replace(new RegExp(`/${DOUBLE}`, 'g'), '(?:/.*)?') // /** -> optional path suffix
39 .replace(new RegExp(DOUBLE, 'g'), '.*') // ** alone -> match anything
40 .replace(new RegExp(SINGLE, 'g'), '[^/]*'); // * -> match non-slash
41
42 return new RegExp(`^${regex}$`).test(key);
43}