"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.sleep = exports.mockGlobalScope = exports.mockRequestScope = exports.mockCaches = exports.mockManifest = exports.mockKV = exports.getEvent = void 0; const makeServiceWorkerEnv = require('service-worker-mock'); const HASH = '123HASHBROWN'; const getEvent = (request) => { const waitUntil = async (callback) => { await callback; }; return { request, waitUntil, }; }; exports.getEvent = getEvent; const store = { 'key1.123HASHBROWN.txt': 'val1', 'key1.123HASHBROWN.png': 'val1', 'index.123HASHBROWN.html': 'index.html', 'cache.123HASHBROWN.html': 'cache me if you can', '测试.123HASHBROWN.html': 'My filename is non-ascii', '%not-really-percent-encoded.123HASHBROWN.html': 'browser percent encoded', '%2F.123HASHBROWN.html': 'user percent encoded', '你好.123HASHBROWN.html': 'I shouldnt be served', '%E4%BD%A0%E5%A5%BD.123HASHBROWN.html': 'Im important', 'nohash.txt': 'no hash but still got some result', 'sub/blah.123HASHBROWN.png': 'picturedis', 'sub/index.123HASHBROWN.html': 'picturedis', 'client.123HASHBROWN': 'important file', 'client.123HASHBROWN/index.html': 'Im here but serve my big bro above', 'image.123HASHBROWN.png': 'imagepng', 'image.123HASHBROWN.webp': 'imagewebp', '你好/index.123HASHBROWN.html': 'My path is non-ascii', }; const mockKV = (store) => { return { get: (path) => store[path] || null, }; }; exports.mockKV = mockKV; const mockManifest = () => { return JSON.stringify({ 'key1.txt': `key1.${HASH}.txt`, 'key1.png': `key1.${HASH}.png`, 'cache.html': `cache.${HASH}.html`, '测试.html': `测试.${HASH}.html`, '你好.html': `你好.${HASH}.html`, '%not-really-percent-encoded.html': `%not-really-percent-encoded.${HASH}.html`, '%2F.html': `%2F.${HASH}.html`, '%E4%BD%A0%E5%A5%BD.html': `%E4%BD%A0%E5%A5%BD.${HASH}.html`, 'index.html': `index.${HASH}.html`, 'sub/blah.png': `sub/blah.${HASH}.png`, 'sub/index.html': `sub/index.${HASH}.html`, client: `client.${HASH}`, 'client/index.html': `client.${HASH}`, 'image.png': `image.${HASH}.png`, 'image.webp': `image.${HASH}.webp`, '你好/index.html': `你好/index.${HASH}.html`, }); }; exports.mockManifest = mockManifest; let cacheStore = new Map(); const mockCaches = () => { return { default: { async match(key) { let cacheKey = { url: key.url, headers: {}, }; let response; if (key.headers.has('if-none-match')) { let makeStrongEtag = key.headers.get('if-none-match').replace('W/', ''); Reflect.set(cacheKey.headers, 'etag', makeStrongEtag); response = cacheStore.get(JSON.stringify(cacheKey)); } else { // if client doesn't send if-none-match, we need to iterate through these keys // and just test the URL const activeCacheKeys = Array.from(cacheStore.keys()); for (const cacheStoreKey of activeCacheKeys) { if (JSON.parse(cacheStoreKey).url === key.url) { response = cacheStore.get(cacheStoreKey); } } } // TODO: write test to accomodate for rare scenarios with where range requests accomodate etags if (response && !key.headers.has('if-none-match')) { // this appears overly verbose, but is necessary to document edge cache behavior // The Range request header triggers the response header Content-Range ... const range = key.headers.get('range'); if (range) { response.headers.set('content-range', `bytes ${range.split('=').pop()}/${response.headers.get('content-length')}`); } // ... which we are using in this repository to set status 206 if (response.headers.has('content-range')) { response.status = 206; } else { response.status = 200; } let etag = response.headers.get('etag'); if (etag && !etag.includes('W/')) { response.headers.set('etag', `W/${etag}`); } } return response; }, async put(key, val) { let headers = new Headers(val.headers); let url = new URL(key.url); let resWithBody = new Response(val.body, { headers, status: 200 }); let resNoBody = new Response(null, { headers, status: 304 }); let cacheKey = { url: key.url, headers: { etag: `"${url.pathname.replace('/', '')}"`, }, }; cacheStore.set(JSON.stringify(cacheKey), resNoBody); cacheKey.headers = {}; cacheStore.set(JSON.stringify(cacheKey), resWithBody); return; }, }, }; }; exports.mockCaches = mockCaches; // mocks functionality used inside worker request function mockRequestScope() { Object.assign(global, makeServiceWorkerEnv()); Object.assign(global, { __STATIC_CONTENT_MANIFEST: (0, exports.mockManifest)() }); Object.assign(global, { __STATIC_CONTENT: (0, exports.mockKV)(store) }); Object.assign(global, { caches: (0, exports.mockCaches)() }); } exports.mockRequestScope = mockRequestScope; // mocks functionality used on global isolate scope. such as the KV namespace bind function mockGlobalScope() { Object.assign(global, { __STATIC_CONTENT_MANIFEST: (0, exports.mockManifest)() }); Object.assign(global, { __STATIC_CONTENT: (0, exports.mockKV)(store) }); } exports.mockGlobalScope = mockGlobalScope; const sleep = (milliseconds) => { return new Promise((resolve) => setTimeout(resolve, milliseconds)); }; exports.sleep = sleep;