@satoshibits/cache-keys
Version:
Type-safe cache key generation with zero dependencies
210 lines • 6.53 kB
JavaScript
"use strict";
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
import { sanitizeKeyComponent, joinKeyComponents } from './sanitizer.mjs';
/**
* Fluent builder for creating complex cache keys
*/
var CacheKeyBuilder = /** @class */ (function () {
function CacheKeyBuilder(options) {
if (options === void 0) { options = {}; }
var _a;
this.parts = [];
this.options = {
separator: (_a = options.separator) !== null && _a !== void 0 ? _a : ':',
sanitize: options.sanitize !== false,
};
}
/**
* Create a new CacheKeyBuilder instance
*/
CacheKeyBuilder.create = function (options) {
return new CacheKeyBuilder(options);
};
/**
* Add a namespace component
*/
CacheKeyBuilder.prototype.namespace = function (namespace) {
if (this.options.sanitize) {
this.parts.push(sanitizeKeyComponent(namespace));
}
else {
this.parts.push(namespace);
}
return this;
};
/**
* Add a type component
*/
CacheKeyBuilder.prototype.type = function (type) {
if (this.options.sanitize) {
this.parts.push(sanitizeKeyComponent(type));
}
else {
this.parts.push(type);
}
return this;
};
/**
* Add an ID component
*/
CacheKeyBuilder.prototype.id = function (id) {
var idStr;
try {
idStr = typeof id === 'object' ? id.toString() : String(id);
}
catch (e) {
var message = e instanceof Error ? e.message : String(e);
throw new Error("Failed to convert ID to string: ".concat(message));
}
if (this.options.sanitize) {
this.parts.push(sanitizeKeyComponent(idStr));
}
else {
this.parts.push(idStr);
}
return this;
};
/**
* Add a parameter with key-value format
*/
CacheKeyBuilder.prototype.param = function (key, value) {
var paramStr = "".concat(key, "_").concat(value);
if (this.options.sanitize) {
this.parts.push(sanitizeKeyComponent(paramStr));
}
else {
this.parts.push(paramStr);
}
return this;
};
/**
* Add a version component
*/
CacheKeyBuilder.prototype.version = function (version) {
var versionStr = "v".concat(version);
if (this.options.sanitize) {
this.parts.push(sanitizeKeyComponent(versionStr));
}
else {
this.parts.push(versionStr);
}
return this;
};
/**
* Add a custom component
*/
CacheKeyBuilder.prototype.add = function (component) {
if (this.options.sanitize) {
this.parts.push(sanitizeKeyComponent(component));
}
else {
this.parts.push(component);
}
return this;
};
/**
* Add multiple components at once
*/
CacheKeyBuilder.prototype.addAll = function () {
var _this = this;
var components = [];
for (var _i = 0; _i < arguments.length; _i++) {
components[_i] = arguments[_i];
}
components.forEach(function (c) { return _this.add(c); });
return this;
};
/**
* Build the final cache key
*/
CacheKeyBuilder.prototype.build = function () {
if (this.parts.length === 0) {
throw new Error('Cannot build empty cache key');
}
return joinKeyComponents(this.parts, this.options.separator, false // Already sanitized if needed
);
};
/**
* Build a pattern for matching (adds wildcard at the end)
*/
CacheKeyBuilder.prototype.pattern = function () {
return this.build() + this.options.separator + '*';
};
/**
* Reset the builder
*/
CacheKeyBuilder.prototype.reset = function () {
this.parts = [];
return this;
};
/**
* Clone the current builder state
*/
CacheKeyBuilder.prototype.clone = function () {
var newBuilder = new CacheKeyBuilder(this.options);
newBuilder.parts = __spreadArray([], this.parts, true);
return newBuilder;
};
Object.defineProperty(CacheKeyBuilder.prototype, "length", {
/**
* Get the current number of parts
*/
get: function () {
return this.parts.length;
},
enumerable: false,
configurable: true
});
return CacheKeyBuilder;
}());
export { CacheKeyBuilder };
/**
* Create a cache key from a template string with replacements
*
* @param template Template string with placeholders like {id}
* @param values Values to replace in the template
* @param sanitize Whether to sanitize the values
* @returns The formatted cache key
*
* @example
* fromTemplate('user:{id}:profile', { id: '123' }) // 'user:123:profile'
*/
export function fromTemplate(template, values, sanitize) {
if (sanitize === void 0) { sanitize = true; }
return template.replace(/{(\w+)}/g, function (_match, key) {
if (!(key in values)) {
throw new Error("Missing value for placeholder: ".concat(key));
}
var value = values[key];
var strValue;
try {
strValue = typeof value === 'object' ? value.toString() : String(value);
}
catch (e) {
var message = e instanceof Error ? e.message : String(e);
throw new Error("Failed to convert value for placeholder '".concat(key, "' to string: ").concat(message));
}
return sanitize ? sanitizeKeyComponent(strValue) : strValue;
});
}
/**
* Create a scoped key builder that always starts with specific components
*
* @param baseComponents Initial components for all keys
* @param options Builder options
* @returns A new key builder with the base components
*/
export function scopedBuilder(baseComponents, options) {
var builder = new CacheKeyBuilder(options);
baseComponents.forEach(function (component) { return builder.add(component); });
return builder;
}
//# sourceMappingURL=builder.mjs.map