"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { CacheBranchAsync: () => CacheBranchAsync, CacheBranchSync: () => CacheBranchSync }); module.exports = __toCommonJS(src_exports); // src/base/CacheBranch.ts var CacheBranch = class { data; branches; constructor(data) { this.data = data; this.branches = /* @__PURE__ */ new Map(); } /** * The method splits the provided key value into tokens and returns them as an array. * For instance, if you pass `'user/name/middle'` as the parameter, it will return `['user', 'name', 'middle']` as the split values. * @param key The key value to split. */ tokens(key) { return key.split("/"); } to(key, getNextBranch) { const tokens = this.tokens(key); let current = this; for (let i = 0, len = tokens.length; i < len; i++) { const last = i === len - 1; const key2 = tokens[i]; const next = getNextBranch(current, key2, i, last); if (next === null) { return void 0; } current = next; } return current; } }; // node_modules/@ungap/structured-clone/esm/types.js var VOID = -1; var PRIMITIVE = 0; var ARRAY = 1; var OBJECT = 2; var DATE = 3; var REGEXP = 4; var MAP = 5; var SET = 6; var ERROR = 7; var BIGINT = 8; // node_modules/@ungap/structured-clone/esm/deserialize.js var env = typeof self === "object" ? self : globalThis; var deserializer = ($, _) => { const as = (out, index) => { $.set(index, out); return out; }; const unpair = (index) => { if ($.has(index)) return $.get(index); const [type, value] = _[index]; switch (type) { case PRIMITIVE: case VOID: return as(value, index); case ARRAY: { const arr = as([], index); for (const index2 of value) arr.push(unpair(index2)); return arr; } case OBJECT: { const object = as({}, index); for (const [key, index2] of value) object[unpair(key)] = unpair(index2); return object; } case DATE: return as(new Date(value), index); case REGEXP: { const { source, flags } = value; return as(new RegExp(source, flags), index); } case MAP: { const map = as(/* @__PURE__ */ new Map(), index); for (const [key, index2] of value) map.set(unpair(key), unpair(index2)); return map; } case SET: { const set = as(/* @__PURE__ */ new Set(), index); for (const index2 of value) set.add(unpair(index2)); return set; } case ERROR: { const { name, message } = value; return as(new env[name](message), index); } case BIGINT: return as(BigInt(value), index); case "BigInt": return as(Object(BigInt(value)), index); } return as(new env[type](value), index); }; return unpair; }; var deserialize = (serialized) => deserializer(/* @__PURE__ */ new Map(), serialized)(0); // node_modules/@ungap/structured-clone/esm/serialize.js var EMPTY = ""; var { toString } = {}; var { keys } = Object; var typeOf = (value) => { const type = typeof value; if (type !== "object" || !value) return [PRIMITIVE, type]; const asString = toString.call(value).slice(8, -1); switch (asString) { case "Array": return [ARRAY, EMPTY]; case "Object": return [OBJECT, EMPTY]; case "Date": return [DATE, EMPTY]; case "RegExp": return [REGEXP, EMPTY]; case "Map": return [MAP, EMPTY]; case "Set": return [SET, EMPTY]; } if (asString.includes("Array")) return [ARRAY, asString]; if (asString.includes("Error")) return [ERROR, asString]; return [OBJECT, asString]; }; var shouldSkip = ([TYPE, type]) => TYPE === PRIMITIVE && (type === "function" || type === "symbol"); var serializer = (strict, json, $, _) => { const as = (out, value) => { const index = _.push(out) - 1; $.set(value, index); return index; }; const pair = (value) => { if ($.has(value)) return $.get(value); let [TYPE, type] = typeOf(value); switch (TYPE) { case PRIMITIVE: { let entry = value; switch (type) { case "bigint": TYPE = BIGINT; entry = value.toString(); break; case "function": case "symbol": if (strict) throw new TypeError("unable to serialize " + type); entry = null; break; case "undefined": return as([VOID], value); } return as([TYPE, entry], value); } case ARRAY: { if (type) return as([type, [...value]], value); const arr = []; const index = as([TYPE, arr], value); for (const entry of value) arr.push(pair(entry)); return index; } case OBJECT: { if (type) { switch (type) { case "BigInt": return as([type, value.toString()], value); case "Boolean": case "Number": case "String": return as([type, value.valueOf()], value); } } if (json && "toJSON" in value) return pair(value.toJSON()); const entries = []; const index = as([TYPE, entries], value); for (const key of keys(value)) { if (strict || !shouldSkip(typeOf(value[key]))) entries.push([pair(key), pair(value[key])]); } return index; } case DATE: return as([TYPE, value.toISOString()], value); case REGEXP: { const { source, flags } = value; return as([TYPE, { source, flags }], value); } case MAP: { const entries = []; const index = as([TYPE, entries], value); for (const [key, entry] of value) { if (strict || !(shouldSkip(typeOf(key)) || shouldSkip(typeOf(entry)))) entries.push([pair(key), pair(entry)]); } return index; } case SET: { const entries = []; const index = as([TYPE, entries], value); for (const entry of value) { if (strict || !shouldSkip(typeOf(entry))) entries.push(pair(entry)); } return index; } } const { message } = value; return as([TYPE, { name: type, message }], value); }; return pair; }; var serialize = (value, { json, lossy } = {}) => { const _ = []; return serializer(!(json || lossy), !!json, /* @__PURE__ */ new Map(), _)(value), _; }; // node_modules/@ungap/structured-clone/esm/index.js var esm_default = typeof structuredClone === "function" ? ( /* c8 ignore start */ (any, options) => options && ("json" in options || "lossy" in options) ? deserialize(serialize(any, options)) : structuredClone(any) ) : (any, options) => deserialize(serialize(any, options)); // src/base/CacheData.ts var CacheData = class _CacheData { static IsDirty(data) { return data.dirty; } static SetDirty(data, value) { data.dirty = value; return data; } static StructuredClone = globalThis.structuredClone ?? esm_default; _raw; generator; dirty; constructor(generator) { this._raw = void 0; this.dirty = false; this.generator = generator; } /** * This is cached data. * It was generated at the time of caching, so there is a risk of modification if it's an object due to shallow copying. * Therefore, if it's not a primitive type, please avoid using this value directly and use the `clone` method to use a copied version of the data. */ get raw() { if (!this.dirty) { throw new Error(`The data is not initialized and cannot be accessed. Please use the 'ensure' or 'set' method to create the data first.`); } return this._raw; } /** * The method returns a copied value of the cached data. * You can pass a function as a parameter to copy the value. This parameter function should return the copied value. * * If no parameter is passed, it defaults to using Javascript's or \@ungap/structured-clone's `structuredClone` function to copy the value. * If you prefer shallow copying instead of deep copying, * you can use the default options `array-shallow-copy`, `object-shallow-copy` and `deep-copy`, * which are replaced with functions to shallow copy arrays and objects, respectively. This is a syntactic sugar. * @param strategy The function that returns the copied value. * If you want to perform a shallow copy, simply pass the strings `array-shallow-copy` or `object-shallow-copy` for easy use. * The default is `structuredClone`. */ clone(strategy = "deep-copy") { if (strategy && typeof strategy !== "string") { return strategy(this.raw); } switch (strategy) { case "array-shallow-copy": return [].concat(this.raw); case "object-shallow-copy": return Object.assign({}, this.raw); case "deep-copy": default: return _CacheData.StructuredClone(this.raw); } } }; // src/CacheDataAsync.ts var CacheDataAsync = class extends CacheData { static EmptyDataGenerator = async () => void 0; static async Update(branch, data, generator) { data._raw = await generator(branch); data.generator = generator; data.dirty = true; return data; } static async Cache(branch, data) { data._raw = await data.generator(branch); return data; } }; // src/CacheBranchAsync.ts var CacheBranchAsync = class _CacheBranchAsync extends CacheBranch { root; constructor(generator = CacheDataAsync.EmptyDataGenerator, root) { super(new CacheDataAsync(generator)); this.root = root ?? this; } ensureBranch(key, generator) { return this.to(key, (b, k) => { const branch = b; if (!branch.branches.has(k)) { branch.branches.set(k, new _CacheBranchAsync(generator, this.root)); } return branch.branches.get(k); }); } getBranch(key) { return this.to(key, (b, k) => { const branch = b; if (!branch.branches.has(k)) { return null; } return branch.branches.get(k); }); } async cache(key, recursive) { const branch = this.ensureBranch(key, CacheDataAsync.EmptyDataGenerator); if (!branch) { return this; } if (recursive === "bottom-up") { for (const key2 of branch.branches.keys()) { await branch.cache(key2, recursive); } } await CacheDataAsync.Cache(this.root, branch.data); if (recursive === "top-down") { for (const key2 of branch.branches.keys()) { await branch.cache(key2, recursive); } } return this; } async ensure(key, generator) { const branch = this.ensureBranch(key, CacheDataAsync.EmptyDataGenerator); if (!CacheDataAsync.IsDirty(branch.data)) { await CacheDataAsync.Update(this.root, branch.data, generator); } return branch.data; } get(key) { const branch = this.ensureBranch(key, CacheDataAsync.EmptyDataGenerator); if (!CacheDataAsync.IsDirty(branch.data)) { return void 0; } return branch.data; } async set(key, generator) { const branch = this.ensureBranch(key, CacheDataAsync.EmptyDataGenerator); await CacheDataAsync.Update(this.root, branch.data, generator); return this; } async delete(key) { const branch = this.ensureBranch(key, CacheDataAsync.EmptyDataGenerator); if (branch) { branch.branches.clear(); await CacheDataAsync.Update(this.root, branch.data, CacheDataAsync.EmptyDataGenerator); CacheDataAsync.SetDirty(branch.data, false); } return this; } }; // src/CacheDataSync.ts var CacheDataSync = class extends CacheData { static EmptyDataGenerator = () => void 0; static Update(branch, data, generator) { data._raw = generator(branch); data.generator = generator; data.dirty = true; return data; } static Cache(branch, data) { data._raw = data.generator(branch); return data; } }; // src/CacheBranchSync.ts var CacheBranchSync = class _CacheBranchSync extends CacheBranch { root; constructor(generator = CacheDataSync.EmptyDataGenerator, root) { super(new CacheDataSync(generator)); this.root = root ?? this; } ensureBranch(key, generator) { return this.to(key, (b, k) => { const branch = b; if (!branch.branches.has(k)) { branch.branches.set(k, new _CacheBranchSync(generator, this.root)); } return branch.branches.get(k); }); } getBranch(key) { return this.to(key, (b, k) => { const branch = b; if (!branch.branches.has(k)) { return null; } return branch.branches.get(k); }); } cache(key, recursive) { const branch = this.ensureBranch(key, CacheDataSync.EmptyDataGenerator); if (!branch) { return this; } if (recursive === "bottom-up") { for (const key2 of branch.branches.keys()) { branch.cache(key2, recursive); } } CacheDataSync.Cache(this.root, branch.data); if (recursive === "top-down") { for (const key2 of branch.branches.keys()) { branch.cache(key2, recursive); } } return this; } ensure(key, generator) { const branch = this.ensureBranch(key, CacheDataSync.EmptyDataGenerator); if (!CacheDataSync.IsDirty(branch.data)) { CacheDataSync.Update(this.root, branch.data, generator); } return branch.data; } get(key) { const branch = this.ensureBranch(key, CacheDataSync.EmptyDataGenerator); if (!CacheDataSync.IsDirty(branch.data)) { return void 0; } return branch.data; } set(key, generator) { const branch = this.ensureBranch(key, CacheDataSync.EmptyDataGenerator); CacheDataSync.Update(this.root, branch.data, generator); return this; } delete(key) { const branch = this.ensureBranch(key, CacheDataSync.EmptyDataGenerator); if (branch) { branch.branches.clear(); CacheDataSync.Update(this.root, branch.data, CacheDataSync.EmptyDataGenerator); CacheDataSync.SetDirty(branch.data, false); } return this; } };