From 32ea38177efc80ed7cb97b2e4fa9f04ee735d1ca Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Fri, 31 Oct 2025 22:55:47 -0400 Subject: [PATCH] fetch bad :( --- app.js | 45 ++++++++++++++++++++++++++++++++++----- graph/graph.js | 11 ++++++---- graph/types.ts | 10 ++++----- service-worker.js | 45 ++++++++++++++++++++++++++++++++++----- store-directory-handle.js | 10 ++++----- 5 files changed, 97 insertions(+), 24 deletions(-) diff --git a/app.js b/app.js index 661d575..bf74e4d 100644 --- a/app.js +++ b/app.js @@ -29,7 +29,7 @@ async function LoadHandleFiles() { try { - const module = await import("./data/room.js"+"?rand="+Math.random()); + const module = await import("./fsx/data/room.js"+""); /** @type {Record} */ const read = module.default(); rooms.val = read; @@ -39,11 +39,41 @@ async function LoadHandleFiles() rooms.val = {}; } } + + /** @type {Van.State>} */ const rooms = van.state({}); let handle = await FSHandle.getDirectoryHandle(); await LoadHandleFiles(); +/** @type {(path:string[], part:string, time:number, data:string)=>void} */ +async function WRITE(path, part, time, data) +{ + const fileHandle = await FSHandle.drilldown(handle, path, true); + if(fileHandle) + { + const file = await fileHandle.getFile(); + const text = await file.text(); + let json = {}; + if(text) + { + json = JSON.parse(text); + } + let partProp = json[part]; + if(!partProp) + { + partProp = []; + json[part] = partProp; + } + partProp.push([time, data]); + + const writeable = await fileHandle.createWritable(); + await writeable.write(JSON.stringify(json, null, 2)); + await writeable.close(); + } + +} + /** @type {Van.State} */ const loggedIn = van.state(false); @@ -65,7 +95,7 @@ function Room(room_id, graphParts) DOM.div.Plain(user.name), ()=>{ return DOM.button.Plain( - {onclick(){ + {async onclick(){ rerender.val++ loggedIn.val = user; }}, @@ -122,10 +152,15 @@ function Room(room_id, graphParts) DOM.strong(data), )), Div.Plain( - loggedIn.val && DOM.button({onclick(){ - data.make(loggedIn.val, "NEW"); - rerender.val++ + loggedIn.val ? DOM.button({onclick(){ + if(loggedIn.val) + { + data.make(loggedIn.val, "NEW"); + rerender.val++ + WRITE(["room", room_id, pass.id, loggedIn.val.id+".json"], part_id, new Date().getTime(), "NEW"); + } }}, "Add work!") + : null ) )) } diff --git a/graph/graph.js b/graph/graph.js index 16d97b8..1534534 100644 --- a/graph/graph.js +++ b/graph/graph.js @@ -11,7 +11,8 @@ export function Room({user, role, part, desk, pass}) for(let userId in user) { const name = user[userId]; - UserList[userId] = {name, desk:new Set()}; + + UserList[userId] = {name, id:userId, desk:new Set()}; } // mutate roles @@ -21,7 +22,7 @@ export function Room({user, role, part, desk, pass}) for(let roleId in role) { const [name, ...userIds] = role[roleId]; - RoleList[roleId] = {name, user:userIds.map(uId=>UserList[/**@type{string}*/(uId)])}; + RoleList[roleId] = {name, id:roleId, user:userIds.map(uId=>UserList[/**@type{string}*/(uId)])}; } // mutate parts @@ -31,7 +32,7 @@ export function Room({user, role, part, desk, pass}) for(let partId in part) { const name = part[partId]; - PartList[partId] = /** @type {TYPES.Part} */({name, need:[], make:[], pass:new Map()}); + PartList[partId] = /** @type {TYPES.Part} */({name, id:partId, need:[], make:[], pass:new Map()}); } // mutate desks @@ -47,6 +48,7 @@ export function Room({user, role, part, desk, pass}) /** @type {TYPES.Desk} */ const deskObj = { name, + id:deskId, mode, need, time, @@ -89,6 +91,7 @@ export function Room({user, role, part, desk, pass}) /** @type {TYPES.Pass} */ const passObj = { name: pass[passID][0], + id:passID, path:passID, async load(){ @@ -116,7 +119,7 @@ export function Room({user, role, part, desk, pass}) const [userID, userObject] = userData[i]; try { - const resp = await fetch(`./room/${context.Path}/${passID}/${userID}.json`); + const resp = await fetch(`./fsx/room/${context.Path}/${passID}/${userID}`); /** @type {TYPES.UserPassFile} */ const json = await resp.json(); diff --git a/graph/types.ts b/graph/types.ts index d0cb5bc..857b448 100644 --- a/graph/types.ts +++ b/graph/types.ts @@ -1,8 +1,8 @@ -export type User = {name:string, desk:Set}; -export type Role = {name:string, user:User[]}; -export type Desk = {name:string, need:Part[], time:number[], make:Part[], pass:Map, mode:string, role:Role[]}; -export type Pass = {name:string, path:string, live:boolean, load:()=>Promise, dump:()=>void}; -export type Part = {name:string, pass:Mapvoid}>, need:Desk[], make:Desk[]}; +export type User = {name:string, id:string, desk:Set}; +export type Role = {name:string, id:string, user:User[]}; +export type Desk = {name:string, id:string, need:Part[], time:number[], make:Part[], pass:Map, mode:string, role:Role[]}; +export type Pass = {name:string, id:string, path:string, live:boolean, load:()=>Promise, dump:()=>void}; +export type Part = {name:string, id:string, pass:Mapvoid}>, need:Desk[], make:Desk[]}; export type Work = [time:number, data:string, user:User]; export type Flag = {need:number[], make:number[]} diff --git a/service-worker.js b/service-worker.js index 5650b18..62f9b9b 100644 --- a/service-worker.js +++ b/service-worker.js @@ -4,22 +4,57 @@ self.addEventListener('install', ()=> self.skipWaiting()); // Activate worker im self.addEventListener('activate', ()=> self.clients.claim()); // Become available to all pages); self.addEventListener('fetch', (event) =>event.respondWith(Interceptor(event))); +/** @type {(event:{request:Request})=>Promise} */ async function Interceptor(event) { const url = new URL(event.request.url); const pathname = url.pathname.substring(1); - const parts = pathname.split("/"); + let parts = pathname.split("/"); - if(parts[0] == "data" || parts[0] == "room") + if(parts[0] == "fsx") { - console.log("intercept:", pathname) + parts = parts.slice(1); + console.log("intercept:", pathname); + + if(parts[0] == "room") + { + parts[parts.length-1] = parts[parts.length-1]+".json"; + } + const handle = await FSAccess.getDirectoryHandle(); if(handle) { - const file = await FSAccess.drilldown(handle, parts); - if(file) + if(event.request.method == "PUT") { + const body = await event.request.text(); + console.log("PUT intercept", parts, body); + const fileHandle = await FSAccess.drilldown(handle, parts, true); + + if(fileHandle) + { + + const writeable = await fileHandle.createWritable(); + await writeable.write(body); + await writeable.close(); + return new Response("OK", { + headers: { + 'Content-Type': 'application/javascript', + 'Cache-Control': 'no-cache' + } + }); + } + else + { + return new Response("404", {status:404}); + } + } + + const fileHandle = await FSAccess.drilldown(handle, parts); + if(fileHandle) + { + const file = await fileHandle.getFile(); const content = await file.text(); + return new Response(content, { headers: { 'Content-Type': 'application/javascript', diff --git a/store-directory-handle.js b/store-directory-handle.js index 2e6e7d2..ae03e03 100644 --- a/store-directory-handle.js +++ b/store-directory-handle.js @@ -35,18 +35,18 @@ export async function getDirectoryHandle() { }); } -/** @type {(handle:FileSystemDirectoryHandle, parts:string[])=>Promise} */ -export async function drilldown(handle, parts) +/** @type {(handle:FileSystemDirectoryHandle, parts:string[], create?:boolean)=>Promise} */ +export async function drilldown(handle, parts, create=false) { try { let filePointer = handle; for(let i=0; i