run npm install to generate a package lock
This commit is contained in:
98
node_modules/@weborigami/async-tree/src/operations/cache.js
generated
vendored
Normal file
98
node_modules/@weborigami/async-tree/src/operations/cache.js
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
import { ObjectTree, Tree } from "../internal.js";
|
||||
|
||||
/**
|
||||
* Caches values from a source tree in a second cache tree. Cache source tree
|
||||
* keys in memory.
|
||||
*
|
||||
* If no second tree is supplied, an in-memory value cache is used.
|
||||
*
|
||||
* An optional third filter tree can be supplied. If a filter tree is supplied,
|
||||
* only values for keys that match the filter will be cached.
|
||||
*
|
||||
* @typedef {import("@weborigami/types").AsyncTree} AsyncTree
|
||||
* @typedef {import("@weborigami/types").AsyncMutableTree} AsyncMutableTree
|
||||
* @typedef {import("../../index.ts").Treelike} Treelike
|
||||
*
|
||||
* @param {Treelike} sourceTreelike
|
||||
* @param {AsyncMutableTree} [cacheTreelike]
|
||||
* @param {Treelike} [filterTreelike]
|
||||
* @returns {AsyncTree & { description: string }}
|
||||
*/
|
||||
export default function treeCache(
|
||||
sourceTreelike,
|
||||
cacheTreelike,
|
||||
filterTreelike
|
||||
) {
|
||||
if (!sourceTreelike) {
|
||||
const error = new TypeError(`cache: The source tree isn't defined.`);
|
||||
/** @type {any} */ (error).position = 0;
|
||||
throw error;
|
||||
}
|
||||
|
||||
const source = Tree.from(sourceTreelike);
|
||||
const filter = filterTreelike ? Tree.from(filterTreelike) : undefined;
|
||||
|
||||
/** @type {AsyncMutableTree} */
|
||||
let cache;
|
||||
if (cacheTreelike) {
|
||||
// @ts-ignore
|
||||
cache = Tree.from(cacheTreelike);
|
||||
if (!Tree.isAsyncMutableTree(cache)) {
|
||||
throw new Error("Cache tree must define a set() method.");
|
||||
}
|
||||
} else {
|
||||
cache = new ObjectTree({});
|
||||
}
|
||||
|
||||
let keys;
|
||||
return {
|
||||
description: "cache",
|
||||
|
||||
async get(key) {
|
||||
// Check cache tree first.
|
||||
let cacheValue = await cache.get(key);
|
||||
if (cacheValue !== undefined && !Tree.isAsyncTree(cacheValue)) {
|
||||
// Leaf node cache hit
|
||||
return cacheValue;
|
||||
}
|
||||
|
||||
// Cache miss or interior node cache hit.
|
||||
let value = await source.get(key);
|
||||
if (value !== undefined) {
|
||||
// If a filter is defined, does the key match the filter?
|
||||
const filterValue = filter ? await filter.get(key) : undefined;
|
||||
const filterMatch = !filter || filterValue !== undefined;
|
||||
if (filterMatch) {
|
||||
if (Tree.isAsyncTree(value)) {
|
||||
// Construct merged tree for a tree result.
|
||||
if (cacheValue === undefined) {
|
||||
// Construct new empty container in cache
|
||||
await cache.set(key, {});
|
||||
cacheValue = await cache.get(key);
|
||||
if (!Tree.isAsyncTree(cacheValue)) {
|
||||
// Coerce to tree and then save it back to the cache. This is
|
||||
// necessary, e.g., if cache is an ObjectTree; we want the
|
||||
// subtree to also be an ObjectTree, not a plain object.
|
||||
cacheValue = Tree.from(cacheValue);
|
||||
await cache.set(key, cacheValue);
|
||||
}
|
||||
}
|
||||
value = treeCache(value, cacheValue, filterValue);
|
||||
} else {
|
||||
// Save in cache before returning.
|
||||
await cache.set(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
},
|
||||
|
||||
async keys() {
|
||||
keys ??= await source.keys();
|
||||
return keys;
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user