UNPKG

@satoshibits/cache-keys

Version:
162 lines 5.28 kB
"use strict"; import { sanitizeKeyComponent } from './sanitizer.mjs'; /** * Create an invalidation pattern from a key factory and partial arguments * * @param factory The key factory to use * @param prefixArgs Partial arguments to create a prefix pattern * @returns A pattern string for matching keys * * @example * // Invalidate all campaign keys for an account * const pattern = createInvalidationPattern(campaignKeys.list, accountId); * // Returns: "campaign:list:507f1f77bcf86cd799439011:*" */ export function createInvalidationPattern(factory) { var prefixArgs = []; for (var _i = 1; _i < arguments.length; _i++) { prefixArgs[_i - 1] = arguments[_i]; } if (prefixArgs.length === 0) { return factory.pattern(); } // Get the factory pattern and extract the prefix var fullPattern = factory.pattern(); var prefix = fullPattern.substring(0, fullPattern.lastIndexOf(':') + 1); // Sanitize all arguments to prevent injection var prefixParts = prefixArgs.map(function (arg) { return sanitizeKeyComponent(String(arg)); }); return prefix + prefixParts.join(':') + ':*'; } /** * Match keys against a pattern * * @param keys Array of cache keys * @param pattern Pattern to match against (supports * wildcard) * @returns Array of matching keys */ export function matchKeys(keys, pattern) { // Convert pattern to regex var regexPattern = pattern .split('*') .map(function (part) { return escapeRegex(part); }) .join('.*'); var regex = new RegExp("^".concat(regexPattern, "$")); return keys.filter(function (key) { return regex.test(key); }); } /** * Escape special regex characters in a string */ function escapeRegex(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } /** * Create a pattern that matches any of the given prefixes * * @param prefixes Array of key prefixes * @returns A regex pattern for matching */ export function createMultiPattern(prefixes) { var escapedPrefixes = prefixes.map(escapeRegex); return new RegExp("^(".concat(escapedPrefixes.join('|'), ")")); } /** * Extract the namespace from a cache key * * @param key The cache key * @param separator The separator used in the key * @returns The namespace or null if invalid */ export function extractNamespace(key, separator) { if (separator === void 0) { separator = ':'; } var firstSeparatorIndex = key.indexOf(separator); if (firstSeparatorIndex === -1) { return null; } return key.substring(0, firstSeparatorIndex); } /** * Extract namespace and type from a cache key * * @param key The cache key * @param separator The separator used in the key * @returns Object with namespace and type or null if invalid */ export function extractKeyType(key, separator) { var _a, _b; if (separator === void 0) { separator = ':'; } var parts = key.split(separator); if (parts.length < 2) { return null; } return { namespace: (_a = parts[0]) !== null && _a !== void 0 ? _a : '', type: (_b = parts[1]) !== null && _b !== void 0 ? _b : '', }; } /** * Group keys by their namespace * * @param keys Array of cache keys * @param separator The separator used in keys * @returns Map of namespace to keys */ export function groupKeysByNamespace(keys, separator) { var _a; if (separator === void 0) { separator = ':'; } var groups = new Map(); for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { var key = keys_1[_i]; var namespace = extractNamespace(key, separator); if (namespace) { var group = (_a = groups.get(namespace)) !== null && _a !== void 0 ? _a : []; group.push(key); groups.set(namespace, group); } } return groups; } /** * Create a hierarchical pattern for invalidation * Useful for invalidating parent and child keys together * * @param parts Hierarchical parts of the key * @param separator The separator to use * @returns Array of patterns from most specific to least specific * * @example * createHierarchicalPatterns(['user', '123', 'posts']) * // Returns: ['user:123:posts:*', 'user:123:*', 'user:*'] */ export function createHierarchicalPatterns(parts, separator) { if (separator === void 0) { separator = ':'; } var patterns = []; for (var i = parts.length; i > 0; i--) { var prefix = parts.slice(0, i).join(separator); patterns.push("".concat(prefix).concat(separator, "*")); } return patterns; } /** * Check if a key matches any of the provided patterns * * @param key The key to check * @param patterns Array of patterns to match against * @returns true if the key matches any pattern */ export function matchesAnyPattern(key, patterns) { if (patterns.length === 0) { return false; } // Compile all patterns into a single regex for efficiency var megaPattern = patterns .map(function (pattern) { return pattern .split('*') .map(function (part) { return escapeRegex(part); }) .join('.*'); }) .join('|'); var regex = new RegExp("^(".concat(megaPattern, ")$")); return regex.test(key); } //# sourceMappingURL=patterns.mjs.map