70 lines
1.8 KiB
JavaScript
70 lines
1.8 KiB
JavaScript
export async function computeMissing(current, manifest) {
|
|
const missing = [];
|
|
for (const path in manifest) {
|
|
if (!current || !current[path] || current[path].hash !== manifest[path]) {
|
|
missing.push(path);
|
|
}
|
|
}
|
|
return missing;
|
|
}
|
|
|
|
const octets = [];
|
|
for (let i = 0; i < 256; ++i) {
|
|
octets.push(i.toString(16).padStart(2, '0'));
|
|
}
|
|
|
|
export async function parseResources(resources, buffer) {
|
|
const view = new DataView(buffer);
|
|
let caret = 0;
|
|
const count = view.getUint32(caret);
|
|
caret += 4;
|
|
const manifest = {};
|
|
for (let i = 0; i < count; ++i) {
|
|
let hash = '';
|
|
for (let j = 0; j < 20; ++j) {
|
|
hash += octets[view.getUint8(caret)]
|
|
caret += 1;
|
|
}
|
|
const byteLength = view.getUint32(caret);
|
|
caret += 4;
|
|
const asset = new ArrayBuffer(byteLength);
|
|
const assetView = new DataView(asset);
|
|
for (let j = 0; j < asset.byteLength; ++j) {
|
|
assetView.setUint8(j, view.getUint8(caret));
|
|
caret += 1;
|
|
}
|
|
manifest[resources[i]] = {asset, hash};
|
|
}
|
|
return manifest;
|
|
}
|
|
|
|
export async function fetchResources(paths, {signal} = {}) {
|
|
const response = await fetch('/resources/stream', {
|
|
body: JSON.stringify(paths),
|
|
method: 'post',
|
|
signal,
|
|
});
|
|
if (signal.aborted) {
|
|
return undefined;
|
|
}
|
|
return parseResources(paths, await response.arrayBuffer());
|
|
}
|
|
|
|
export async function get() {
|
|
const {get} = await import('idb-keyval');
|
|
const resources = await get('$$silphius_resources');
|
|
return resources || {};
|
|
}
|
|
|
|
export async function set(resources) {
|
|
const {set} = await import('idb-keyval');
|
|
await set('$$silphius_resources', resources);
|
|
}
|
|
|
|
export async function readAsset(path) {
|
|
const {pathname} = new URL(path, 'http://example.org');
|
|
const resourcePath = pathname.slice('/resources/'.length);
|
|
const resources = await get();
|
|
return resources[resourcePath]?.asset;
|
|
}
|