@nasriya/cachify
Version:
A lightweight, extensible in-memory caching library for storing anything, with built-in TTL and customizable cache types.
91 lines (90 loc) • 4.59 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const cachify_1 = __importDefault(require("../../cachify"));
const atomix_1 = __importDefault(require("@nasriya/atomix"));
const consts_1 = __importDefault(require("../consts/consts"));
class PersistenceProxy {
#_manager;
constructor(manager) { this.#_manager = manager; }
#_helpers = {
validate: {
backupData: (data) => {
if (!atomix_1.default.valueIs.record(data)) {
throw new TypeError(`The "data" argument must be a record, but instead got ${typeof data}`);
}
if (atomix_1.default.dataTypes.record.hasOwnProperty(data, 'source')) {
const source = data.source;
if (!atomix_1.default.valueIs.string(source)) {
throw new TypeError(`The "initiator" property of the "data" object must be a string, but instead got ${typeof source}`);
}
if (!consts_1.default.CACHE_FLAVORS.includes(source)) {
throw new RangeError(`The "initiator" property of the "data" object must be one of the following values: ${consts_1.default.CACHE_FLAVORS.join(', ')}`);
}
if (!(source in cachify_1.default)) {
throw new Error(`The cache flavor "${source}" is not implemented yet by cachify.`);
}
}
else {
throw new SyntaxError(`The "initiator" property of the "data" object is required and missing.`);
}
if (atomix_1.default.dataTypes.record.hasOwnProperty(data, 'content')) {
const content = data.content;
if (!(content instanceof Map)) {
throw new TypeError(`The "content" property of the "data" object must be a Map, but instead got ${typeof content}`);
}
}
else {
throw new SyntaxError(`The "content" property of the "data" object is required and missing.`);
}
},
service: (service) => {
if (!atomix_1.default.valueIs.string(service)) {
throw new TypeError(`The "service" argument must be a string, but instead got ${typeof service}`);
}
if (!consts_1.default.BACKUP_STORAGE_SERVICES.includes(service)) {
throw new RangeError(`The "service" argument must be one of the following values: ${consts_1.default.BACKUP_STORAGE_SERVICES.join(', ')}`);
}
}
}
};
async backup(...args) {
const [data, to, ...rest] = args;
this.#_helpers.validate.backupData(data);
this.#_helpers.validate.service(to);
const driver = this.#_manager.getDriver(to);
if (!driver) {
throw new Error(`The provided storage service (${to}) is not implemented.`);
}
const backupStream = this.#_manager.createBackupStream();
// Pass the stream to the backup() BEFORE writing data
const backupPromise = driver.backup(
// @ts-ignore - backup method signature is safe for the given storage type `S`
data.source, backupStream, ...rest);
const writePromise = async () => {
for (const [scope, scopeMap] of data.content) {
const scopeRecords = Array.from(scopeMap.values());
const promises = scopeRecords.map(record => record.export());
const records = await Promise.all(promises);
for (const record of records.filter(i => atomix_1.default.valueIs.record(i))) {
await backupStream.writeRecord(record);
}
}
await backupStream.close();
};
await Promise.all([backupPromise, writePromise()]);
}
async restore(...args) {
const [flavor, from, ...rest] = args;
this.#_helpers.validate.service(from);
const driver = this.#_manager.getDriver(from);
if (!driver) {
throw new Error(`The provided storage service (${from}) is not implemented.`);
}
// @ts-ignore - backup method signature is safe for the given storage type `S`
await driver.restore(flavor, ...rest);
}
}
exports.default = PersistenceProxy;