| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- import { request } from '@/common';
- import storage from '@/common/storage';
- /** @type { function(url, options, check): Promise<void> } or throws on error */
- storage.cache.fetch = cacheOrFetch({
- init(options) {
- return { ...options, responseType: 'blob' };
- },
- async transform(response, url, options, check) {
- const [type, body] = await storage.cache.makeRaw(response, true);
- await check?.(url, response.data, type);
- return `${type},${body}`;
- },
- });
- /** @type { function(url, options): Promise<void> } or throws on error */
- storage.require.fetch = cacheOrFetch({
- transform: ({ data }, url) => (
- /^\s*</.test(data)
- ? Promise.reject(`NOT_JS: ${url} "${data.slice(0, 100).trim().replace(/\s{2,}/g, ' ')}"`)
- : data
- ),
- });
- function cacheOrFetch(handlers = {}) {
- const requests = {};
- const { init, transform } = handlers;
- /** @this VMStorageBase */
- return function cacheOrFetchHandler(...args) {
- const [url] = args;
- const promise = requests[url] || (requests[url] = this::doFetch(...args));
- return promise;
- };
- /** @this VMStorageBase */
- async function doFetch(...args) {
- const [url, options] = args;
- try {
- const res = !url.startsWith('data:')
- && await requestNewer(url, init ? init(options) : options);
- if (res) {
- const result = transform ? await transform(res, ...args) : res.data;
- await this.set(url, result);
- }
- } finally {
- delete requests[url];
- }
- }
- }
- export async function requestNewer(url, opts) {
- const modOld = await storage.mod.getOne(url);
- for (const get of [0, 1]) {
- if (modOld || get) {
- const req = await request(url, !get ? { ...opts, method: 'HEAD' } : opts);
- const { headers } = req;
- const mod = headers.get('etag')
- || +new Date(headers.get('last-modified'))
- || +new Date(headers.get('date'));
- if (mod && mod === modOld) {
- return;
- }
- if (get) {
- if (mod) storage.mod.set(url, mod);
- else if (modOld) storage.mod.remove(url);
- return req;
- }
- }
- }
- }
|