2025-01-04 19:07:31 -05:00
|
|
|
// Cache names for different types of resources
|
|
|
|
const CACHE_NAMES = {
|
2025-01-06 14:56:16 -05:00
|
|
|
wasm: "wasm-cache-v1",
|
|
|
|
static: "static-cache-v1",
|
|
|
|
dynamic: "dynamic-cache-v1",
|
2025-01-04 19:07:31 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
// Import required scripts
|
|
|
|
importScripts(
|
|
|
|
"https://cdn.jsdelivr.net/gh/golang/go@go1.22.5/misc/wasm/wasm_exec.js",
|
|
|
|
"https://cdn.jsdelivr.net/gh/nlepage/go-wasm-http-server@v1.1.0/sw.js",
|
|
|
|
);
|
|
|
|
|
|
|
|
// Initialize WASM HTTP listener
|
2025-01-06 14:56:16 -05:00
|
|
|
const wasmInstance = registerWasmHTTPListener(
|
|
|
|
"https://cdn.sonr.id/wasm/app.wasm",
|
|
|
|
);
|
2025-01-04 19:07:31 -05:00
|
|
|
|
|
|
|
// MessageChannel port for WASM communication
|
|
|
|
let wasmPort;
|
|
|
|
|
|
|
|
// Request queue for offline operations
|
|
|
|
let requestQueue = new Map();
|
|
|
|
|
|
|
|
// Setup message channel handler
|
2025-01-06 14:56:16 -05:00
|
|
|
self.addEventListener("message", async (event) => {
|
|
|
|
if (event.data.type === "PORT_INITIALIZATION") {
|
2025-01-04 19:07:31 -05:00
|
|
|
wasmPort = event.data.port;
|
|
|
|
setupWasmCommunication();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
function setupWasmCommunication() {
|
|
|
|
wasmPort.onmessage = async (event) => {
|
|
|
|
const { type, data } = event.data;
|
|
|
|
|
|
|
|
switch (type) {
|
2025-01-06 14:56:16 -05:00
|
|
|
case "WASM_REQUEST":
|
2025-01-04 19:07:31 -05:00
|
|
|
handleWasmRequest(data);
|
|
|
|
break;
|
2025-01-06 14:56:16 -05:00
|
|
|
case "SYNC_REQUEST":
|
2025-01-04 19:07:31 -05:00
|
|
|
processSyncQueue();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Notify that WASM is ready
|
2025-01-06 14:56:16 -05:00
|
|
|
wasmPort.postMessage({ type: "WASM_READY" });
|
2025-01-04 19:07:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Enhanced install event
|
|
|
|
self.addEventListener("install", (event) => {
|
|
|
|
event.waitUntil(
|
|
|
|
Promise.all([
|
|
|
|
skipWaiting(),
|
|
|
|
// Cache WASM binary and essential resources
|
2025-01-06 14:56:16 -05:00
|
|
|
caches
|
|
|
|
.open(CACHE_NAMES.wasm)
|
|
|
|
.then((cache) =>
|
|
|
|
cache.addAll([
|
|
|
|
"https://cdn.sonr.id/wasm/app.wasm",
|
|
|
|
"https://cdn.jsdelivr.net/gh/golang/go@go1.22.5/misc/wasm/wasm_exec.js",
|
|
|
|
]),
|
|
|
|
),
|
|
|
|
]),
|
2025-01-04 19:07:31 -05:00
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Enhanced activate event
|
|
|
|
self.addEventListener("activate", (event) => {
|
|
|
|
event.waitUntil(
|
|
|
|
Promise.all([
|
|
|
|
clients.claim(),
|
|
|
|
// Clean up old caches
|
2025-01-06 14:56:16 -05:00
|
|
|
caches.keys().then((keys) =>
|
2025-01-04 19:07:31 -05:00
|
|
|
Promise.all(
|
2025-01-06 14:56:16 -05:00
|
|
|
keys.map((key) => {
|
2025-01-04 19:07:31 -05:00
|
|
|
if (!Object.values(CACHE_NAMES).includes(key)) {
|
|
|
|
return caches.delete(key);
|
|
|
|
}
|
2025-01-06 14:56:16 -05:00
|
|
|
}),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
]),
|
2025-01-04 19:07:31 -05:00
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Intercept fetch events
|
2025-01-06 14:56:16 -05:00
|
|
|
self.addEventListener("fetch", (event) => {
|
2025-01-04 19:07:31 -05:00
|
|
|
const request = event.request;
|
|
|
|
|
|
|
|
// Handle API requests differently from static resources
|
2025-01-06 14:56:16 -05:00
|
|
|
if (request.url.includes("/api/")) {
|
2025-01-04 19:07:31 -05:00
|
|
|
event.respondWith(handleApiRequest(request));
|
|
|
|
} else {
|
|
|
|
event.respondWith(handleStaticRequest(request));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
async function handleApiRequest(request) {
|
|
|
|
try {
|
|
|
|
// Try to make the request
|
|
|
|
const response = await fetch(request.clone());
|
|
|
|
|
|
|
|
// If successful, pass through WASM handler
|
|
|
|
if (response.ok) {
|
|
|
|
return await processWasmResponse(request, response);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If offline or failed, queue the request
|
|
|
|
await queueRequest(request);
|
|
|
|
|
|
|
|
// Return cached response if available
|
|
|
|
const cachedResponse = await caches.match(request);
|
|
|
|
if (cachedResponse) {
|
|
|
|
return cachedResponse;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return offline response
|
2025-01-06 14:56:16 -05:00
|
|
|
return new Response(JSON.stringify({ error: "Currently offline" }), {
|
|
|
|
status: 503,
|
|
|
|
headers: { "Content-Type": "application/json" },
|
|
|
|
});
|
2025-01-04 19:07:31 -05:00
|
|
|
} catch (error) {
|
|
|
|
await queueRequest(request);
|
2025-01-06 14:56:16 -05:00
|
|
|
return new Response(JSON.stringify({ error: "Request failed" }), {
|
|
|
|
status: 500,
|
|
|
|
headers: { "Content-Type": "application/json" },
|
|
|
|
});
|
2025-01-04 19:07:31 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function handleStaticRequest(request) {
|
|
|
|
// Check cache first
|
|
|
|
const cachedResponse = await caches.match(request);
|
|
|
|
if (cachedResponse) {
|
|
|
|
return cachedResponse;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
const response = await fetch(request);
|
|
|
|
|
|
|
|
// Cache successful responses
|
|
|
|
if (response.ok) {
|
|
|
|
const cache = await caches.open(CACHE_NAMES.static);
|
|
|
|
cache.put(request, response.clone());
|
|
|
|
}
|
|
|
|
|
|
|
|
return response;
|
|
|
|
} catch (error) {
|
|
|
|
// Return offline page for navigation requests
|
2025-01-06 14:56:16 -05:00
|
|
|
if (request.mode === "navigate") {
|
|
|
|
return caches.match("/offline.html");
|
2025-01-04 19:07:31 -05:00
|
|
|
}
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function processWasmResponse(request, response) {
|
|
|
|
// Clone the response before processing
|
|
|
|
const responseClone = response.clone();
|
|
|
|
|
|
|
|
try {
|
|
|
|
// Process through WASM
|
|
|
|
const processedResponse = await wasmInstance.processResponse(responseClone);
|
|
|
|
|
|
|
|
// Notify client through message channel
|
|
|
|
if (wasmPort) {
|
|
|
|
wasmPort.postMessage({
|
2025-01-06 14:56:16 -05:00
|
|
|
type: "RESPONSE",
|
|
|
|
requestId: request.headers.get("X-Wasm-Request-ID"),
|
|
|
|
response: processedResponse,
|
2025-01-04 19:07:31 -05:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return processedResponse;
|
|
|
|
} catch (error) {
|
2025-01-06 14:56:16 -05:00
|
|
|
console.error("WASM processing error:", error);
|
2025-01-04 19:07:31 -05:00
|
|
|
return response;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function queueRequest(request) {
|
|
|
|
const serializedRequest = await serializeRequest(request);
|
|
|
|
requestQueue.set(request.url, serializedRequest);
|
|
|
|
|
|
|
|
// Register for background sync
|
|
|
|
try {
|
2025-01-06 14:56:16 -05:00
|
|
|
await self.registration.sync.register("wasm-sync");
|
2025-01-04 19:07:31 -05:00
|
|
|
} catch (error) {
|
2025-01-06 14:56:16 -05:00
|
|
|
console.error("Sync registration failed:", error);
|
2025-01-04 19:07:31 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function serializeRequest(request) {
|
|
|
|
const headers = {};
|
|
|
|
for (const [key, value] of request.headers.entries()) {
|
|
|
|
headers[key] = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
url: request.url,
|
|
|
|
method: request.method,
|
|
|
|
headers,
|
|
|
|
body: await request.text(),
|
2025-01-06 14:56:16 -05:00
|
|
|
timestamp: Date.now(),
|
2025-01-04 19:07:31 -05:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle background sync
|
2025-01-06 14:56:16 -05:00
|
|
|
self.addEventListener("sync", (event) => {
|
|
|
|
if (event.tag === "wasm-sync") {
|
2025-01-04 19:07:31 -05:00
|
|
|
event.waitUntil(processSyncQueue());
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
async function processSyncQueue() {
|
|
|
|
const requests = Array.from(requestQueue.values());
|
|
|
|
|
|
|
|
for (const serializedRequest of requests) {
|
|
|
|
try {
|
2025-01-06 14:56:16 -05:00
|
|
|
const response = await fetch(
|
|
|
|
new Request(serializedRequest.url, {
|
|
|
|
method: serializedRequest.method,
|
|
|
|
headers: serializedRequest.headers,
|
|
|
|
body: serializedRequest.body,
|
|
|
|
}),
|
|
|
|
);
|
2025-01-04 19:07:31 -05:00
|
|
|
|
|
|
|
if (response.ok) {
|
|
|
|
requestQueue.delete(serializedRequest.url);
|
|
|
|
|
|
|
|
// Notify client of successful sync
|
|
|
|
if (wasmPort) {
|
|
|
|
wasmPort.postMessage({
|
2025-01-06 14:56:16 -05:00
|
|
|
type: "SYNC_COMPLETE",
|
|
|
|
url: serializedRequest.url,
|
2025-01-04 19:07:31 -05:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (error) {
|
2025-01-06 14:56:16 -05:00
|
|
|
console.error("Sync failed for request:", error);
|
2025-01-04 19:07:31 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle payment requests
|
|
|
|
self.addEventListener("canmakepayment", function (e) {
|
|
|
|
e.respondWith(Promise.resolve(true));
|
|
|
|
});
|
|
|
|
|
|
|
|
// Handle periodic sync if available
|
2025-01-06 14:56:16 -05:00
|
|
|
self.addEventListener("periodicsync", (event) => {
|
|
|
|
if (event.tag === "wasm-sync") {
|
2025-01-04 19:07:31 -05:00
|
|
|
event.waitUntil(processSyncQueue());
|
|
|
|
}
|
|
|
|
});
|