Appearance
@bendyline/molen-pack/cache
Molen content packs: build, open and read zip packs of models and documents from any source.
ts
import { /* … */ } from '@bendyline/molen-pack/cache';Interfaces
ArchiveKey
What an archive is and where its bytes come from.
Properties
key?
ts
optional key?: string;Identity of the bytes: a content hash or a URL whose content never changes.
keyBy?
ts
optional keyBy?: "etag";Key by the server's strong ETag instead, for a stable URL whose bytes are replaced.
priority?
ts
optional priority?: ArchivePriority;Default 'normal'.
size?
ts
optional size?: number;Total size in bytes, when known. A read never asks for bytes past it.
url
ts
url: string;Where the bytes come from; recorded with the archive (and the basis of keyBy: 'etag').
BlockCache
A shared cache of archive blocks; open each archive through it.
Properties
blockBytes
ts
readonly blockBytes: number;store
ts
readonly store: ByteStore;Methods
clear()
ts
clear(): Promise<void>;Delete everything, in memory and in the store.
Returns
Promise<void>
dispose()
ts
dispose(): void;Returns
void
drop()
ts
drop(key): Promise<void>;Forget an archive by key.
Parameters
key
string
Returns
Promise<void>
flush()
ts
flush(): Promise<void>;Write buffered blocks, evict down to the budget and refresh the store totals.
Returns
Promise<void>
open()
ts
open(archive, source): CachedArchive;Parameters
archive
source
Returns
setBudget()
ts
setBudget(bytes): void;Parameters
bytes
number
Returns
void
stats()
ts
stats(): BlockCacheStats;A snapshot; the store totals are as of the last flush().
Returns
BlockCacheOptions
Properties
blockBytes?
ts
optional blockBytes?: number;Block size in bytes (default 64 KiB).
evictHighWater?
ts
optional evictHighWater?: number;Evict when the store holds more than this times the budget (default 1.05)…
evictLowWater?
ts
optional evictLowWater?: number;…down to this times the budget (default 0.9).
flushDelayMs?
ts
optional flushDelayMs?: number;Delay before buffered writes go to the store (default 50 ms).
maxSpanBytes?
ts
optional maxSpanBytes?: number;Largest single network request when merging missing blocks (default 4 MiB).
memoryBytes?
ts
optional memoryBytes?: number;In-memory tier (default 32 MiB).
now?
ts
optional now?: () => number;Clock, for tests (default Date.now).
Returns
number
touchIntervalMs?
ts
optional touchIntervalMs?: number;A block's last-used time is written at most this often (default 60 s).
BlockCacheStats
Counters and totals for a BlockCache. Block counts, not reads.
Properties
backend
ts
backend: "memory" | "indexeddb";blockBytes
ts
blockBytes: number;budgetBytes
ts
budgetBytes: number;degraded
ts
degraded: boolean;evictedBytes
ts
evictedBytes: number;memoryBlocks
ts
memoryBlocks: number;memoryBytes
ts
memoryBytes: number;memoryHits
ts
memoryHits: number;misses
ts
misses: number;networkBytes
ts
networkBytes: number;networkRequests
ts
networkRequests: number;pendingBlocks
ts
pendingBlocks: number;storeArchives
ts
storeArchives: number;storeBlocks
ts
storeBlocks: number;storeBytes
ts
storeBytes: number;storeHits
ts
storeHits: number;uncachedRequests
ts
uncachedRequests: number;Reads passed straight through (no validator to key them, or a version mismatch).
ByteStore
Persistent block storage behind a BlockCache. Every method resolves, never rejects: a failure is a miss or a no-op, so a broken store only costs network.
Properties
budgetBytes
ts
readonly budgetBytes: number;The budget in force (possibly clamped below the requested one by the origin's quota).
kind
ts
readonly kind: "memory" | "indexeddb";Methods
archivesForUrl()
ts
archivesForUrl(url): Promise<StoredArchive[]>;Every archive recorded with this URL.
Parameters
url
string
Returns
Promise<StoredArchive[]>
clear()
ts
clear(): Promise<void>;Returns
Promise<void>
close()?
ts
optional close(): void;Returns
void
deleteArchive()
ts
deleteArchive(key): Promise<void>;Parameters
key
string
Returns
Promise<void>
evict()
ts
evict(targetBytes): Promise<number>;Evict blocks in priority-biased LRU order until at most targetBytes remain; returns bytes freed.
Parameters
targetBytes
number
Returns
Promise<number>
getArchive()
ts
getArchive(key): Promise<StoredArchive | undefined>;Parameters
key
string
Returns
Promise<StoredArchive | undefined>
getBlocks()
ts
getBlocks(key, indices): Promise<(Uint8Array<ArrayBufferLike> | undefined)[]>;Parameters
key
string
indices
readonly number[]
Returns
Promise<(Uint8Array<ArrayBufferLike> | undefined)[]>
putBlocks()
ts
putBlocks(
info,
blocks,
now
): Promise<void>;Write blocks (replacing any with the same index) and the archive's record.
Parameters
info
blocks
readonly object[]
now
number
Returns
Promise<void>
setBudget()
ts
setBudget(bytes): void;Parameters
bytes
number
Returns
void
stats()
ts
stats(): Promise<ByteStoreStats>;Returns
Promise<ByteStoreStats>
touch()
ts
touch(
key,
indices,
now
): Promise<void>;Mark blocks as used now (they move to the back of the eviction order).
Parameters
key
string
indices
readonly number[]
now
number
Returns
Promise<void>
updateArchive()
ts
updateArchive(info): Promise<void>;Replace an archive's record without touching its blocks; creates an empty record if absent.
Parameters
info
Returns
Promise<void>
ByteStoreStats
Totals reported by a store.
Properties
archives
ts
archives: number;backend
ts
backend: "memory" | "indexeddb";blocks
ts
blocks: number;budgetBytes
ts
budgetBytes: number;bytes
ts
bytes: number;degraded
ts
degraded: boolean;The store could not be opened or ran out of quota; nothing more is written.
CachedArchive
One archive opened through a BlockCache.
Methods
drop()
ts
drop(): Promise<void>;Forget every cached block of this archive.
Returns
Promise<void>
etag()
ts
etag(): string | undefined;The strong ETag of the cached bytes, when known.
Returns
string | undefined
read()
ts
read(
offset,
length,
signal?,
etag?
): Promise<CachedRead>;Read length bytes at offset; shorter only at the end of the archive. With etag, the caller expects that version: bytes cached for another version are never returned.
Parameters
offset
number
length
number
signal?
AbortSignal
etag?
string
Returns
Promise<CachedRead>
size()
ts
size(): number | undefined;Total size, declared or learned from a short read at the end.
Returns
number | undefined
CachedRead
The result of a cached read.
Properties
bytes
ts
bytes: Uint8Array;etag?
ts
optional etag?: string;The validator these bytes belong to, when known.
CachingRangeReaderOptions
Properties
wholeBelow?
ts
optional wholeBelow?: number;Archives at most this size are fetched whole on the first read, in one request (default 4 MiB), so a small pack costs one request on its first visit and none after.
DocumentCacheOptions
Properties
maxAgeMs?
ts
optional maxAgeMs?: number | ((url) => number);Serve a stored copy without asking the server while it is younger than this, in ms (default 0: always revalidate). A function picks a policy per URL.
maxBytes?
ts
optional maxBytes?: number;Largest document kept, in bytes (default 2 MiB).
now?
ts
optional now?: () => number;Clock, for tests (default Date.now).
Returns
number
timeoutMs?
ts
optional timeoutMs?: number;Serve the stored copy when the server has not answered within this many ms (default 4000).
IndexedDbByteStoreOptions
Properties
budgetBytes?
ts
optional budgetBytes?: number;Bytes kept before eviction (default 512 MiB); clamped to half the origin's free quota.
indexedDB?
ts
optional indexedDB?: IDBFactory;The IndexedDB factory (default globalThis.indexedDB).
name?
ts
optional name?: string;Database name (default 'molen-bytes').
persist?
ts
optional persist?: boolean;Ask the browser to make this origin's storage persistent (default false). Firefox shows a permission prompt for it, so only hosts that expect one (an installed app) should set it.
RangeSourceLike
The shape of a PMTiles Source (FetchSource, a retrying wrapper, a native reader).
Methods
getBytes()
ts
getBytes(
offset,
length,
signal?,
etag?
): Promise<RangeSourceResponse>;Parameters
offset
number
length
number
signal?
AbortSignal
etag?
string
Returns
Promise<RangeSourceResponse>
getKey()
ts
getKey(): string;Returns
string
RangeSourceResponse
A PMTiles range response, typed structurally so this package never imports pmtiles.
Properties
cacheControl?
ts
optional cacheControl?: string;data
ts
data: ArrayBuffer;etag?
ts
optional etag?: string;expires?
ts
optional expires?: string;StoredArchive
A stored archive and the bytes it holds.
Extends
Properties
blocks
ts
blocks: number;bytes
ts
bytes: number;etag?
ts
optional etag?: string;The strong ETag the bytes were read with.
Inherited from
key
ts
key: string;Inherited from
priority
ts
priority: ArchivePriority;Inherited from
size?
ts
optional size?: number;Inherited from
type?
ts
optional type?: string;Media type, for documents.
Inherited from
url
ts
url: string;Inherited from
validated?
ts
optional validated?: number;When a document was last confirmed current, in ms since the epoch.
Inherited from
StoredArchiveInfo
What a store records about one archive besides its blocks.
Extended by
Properties
etag?
ts
optional etag?: string;The strong ETag the bytes were read with.
key
ts
key: string;priority
ts
priority: ArchivePriority;size?
ts
optional size?: number;type?
ts
optional type?: string;Media type, for documents.
url
ts
url: string;validated?
ts
optional validated?: number;When a document was last confirmed current, in ms since the epoch.
UrlRangeReaderOptions
Properties
fetch?
ts
optional fetch?: (input, init?) => Promise<Response>;Parameters
input
RequestInfo | URL
init?
RequestInit
Returns
Promise<Response>
retry?
ts
optional retry?: PackRetryOptions;signal?
ts
optional signal?: AbortSignal;Aborts every read.
size
ts
size: number;Total size in bytes (a pack index lists it).
Type Aliases
ArchivePriority
ts
type ArchivePriority = "high" | "normal" | "low";How long an archive's blocks are kept relative to others when the store is full.
SpanReader
ts
type SpanReader = (offset, length, signal, etag?) => Promise<{
bytes: Uint8Array;
etag?: string;
}>;One read from the network (or wherever the archive lives) for the cache.
Parameters
offset
number
length
number
signal
AbortSignal
etag?
string
Returns
Promise<{ bytes: Uint8Array; etag?: string; }>
Variables
DOCUMENT_CACHE_HEADER
ts
const DOCUMENT_CACHE_HEADER: "x-molen-cache" = "x-molen-cache";Response header naming where a cached document came from: hit, revalidated or stale.
PRIORITY_BIAS_MS
ts
const PRIORITY_BIAS_MS: Readonly<Record<ArchivePriority, number>>;Recency bias per priority: added to a block's last-used time to order eviction.
Functions
cachingDocumentFetch()
ts
function cachingDocumentFetch(
store,
fetchImpl?,
options?
): (input, init?) => Promise<Response>;Wrap fetchImpl so GETs of small documents are kept in store.
Parameters
store
fetchImpl?
(input, init?) => Promise<Response>
options?
Returns
ts
(input, init?): Promise<Response>;Parameters
input
RequestInfo | URL
init?
RequestInit
Returns
Promise<Response>
cachingRangeReader()
ts
function cachingRangeReader(
reader,
cache,
archive,
options?
): RangeReader;A pack RangeReader whose bytes come from cache when it has them. Key it by the pack's content hash (contentHash in a pack index) so a cached copy can never be another version.
Parameters
reader
cache
archive
options?
Returns
cachingRangeSource()
ts
function cachingRangeSource(
source,
cache,
archive
): RangeSourceLike;A PMTiles source whose bytes come from cache when it has them. The inner source must honour Range requests. Its validator handling is kept: a request carrying the archive's ETag still reaches the inner source on a miss, so a replaced file fails with the inner source's own mismatch error (which also drops the cached bytes). Use keyBy: 'etag' for a stable URL whose contents are replaced in place; then the first read of a session (the header) always goes to the network and names the version the rest are cached under.
Parameters
source
cache
archive
Returns
createBlockCache()
ts
function createBlockCache(store?, options?): BlockCache;Create a cache over store (default: an in-memory store with a 64 MiB budget).
Parameters
store?
options?
Returns
createIndexedDbByteStore()
ts
function createIndexedDbByteStore(options?): ByteStore | undefined;Open (lazily) a block store in IndexedDB. Undefined where IndexedDB does not exist (Node, restricted embedded browsers); a database that fails to open behaves as an empty store.
Parameters
options?
Returns
ByteStore | undefined
createMemoryByteStore()
ts
function createMemoryByteStore(options?): ByteStore;A ByteStore in memory: for tests, private browsing, and hosts without IndexedDB.
Parameters
options?
budgetBytes?
number
Returns
evictionRank()
ts
function evictionRank(priority, touched): number;A block's place in the eviction order: lower ranks go first.
Parameters
priority
touched
number
Returns
number
isChangedError()
ts
function isChangedError(error): boolean;Whether an error says the server's bytes changed while they were being read.
Parameters
error
unknown
Returns
boolean
urlRangeReader()
ts
function urlRangeReader(url, options): RangeReader;A RangeReader over a URL whose size is already known, with no opening request: the first response's strong ETag becomes the If-Range validator for every later read, so a file replaced mid-read fails with PackChangedError instead of mixing versions. Pair it with cachingRangeReader to open a pack from cached bytes.
Parameters
url
string
options
Returns
References
RangeReader
Re-exports RangeReader