@tensorix/metahub 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +165 -15
- package/dist/cli.js.map +5 -5
- package/dist/core/properties.d.ts +8 -0
- package/dist/core/properties.d.ts.map +1 -1
- package/dist/db-worker.js +56 -56
- package/dist/edge-worker.js +84 -6
- package/dist/index.js +159 -13
- package/dist/index.js.map +4 -4
- package/dist/metahub-sdk.js +6 -6
- package/dist/sw.js +4 -4
- package/dist/webui/server/routes.d.ts.map +1 -1
- package/dist/webui.js +122 -116
- package/package.json +2 -2
package/dist/metahub-sdk.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
class U extends Error{code;constructor(
|
|
2
|
-
`));let z=Math.max(0,Z.blankAfter??0);if(W<Q.length-1)
|
|
3
|
-
`)}var RQ="intent_receipts";var YX=["hlc","node_id","dataset","row_id","col","value","txn"];var O1=YX.join(", "),WQ=null,HX=null;function qX(X,Q){if(WQ!==null)return Q();WQ=(X?X+":":"")+g(8);try{return Q()}finally{WQ=null}}function S(X,Q=null){return(...$)=>qX(Q,()=>X(...$))}var LX={databases:{table:"databases",cols:new Set(["name","icon","meta","created_hlc","__deleted"])},properties:{table:"properties",cols:new Set(["database_id","name","type","config","position","__deleted"])},documents:{table:"documents",cols:new Set(["title","body","database_id","parent_id","created_hlc","order_key","__deleted"])},doc_blocks:{table:"doc_blocks",cols:new Set(["doc_id","text","order_key","blank_after","__deleted"])},sites:{table:"sites",cols:new Set(["name","title","created_hlc","visibility","spa","public_grants","__deleted"])},site_channels:{table:"site_channels",cols:new Set(["site_id","audience","hosting","controller_node_id","target_ref","canonical_url","policy_json","desired_state","created_hlc","__deleted"])},site_files:{table:"site_files",cols:new Set(["site_id","path","content_type","encoding","content","created_hlc","__deleted"])},blob_policy:{table:"blob_policy",cols:new Set(["full_nodes","redundancy","__deleted"])}},AX=new Set(["database_id","created_hlc","order_key","__deleted"]),NX=new Set([RQ]),KX=new Set(["records:__deleted","databases:__deleted","properties:__deleted","documents:__deleted","doc_blocks:__deleted","doc_blocks:blank_after","sites:__deleted","sites:spa","site_channels:__deleted","site_files:__deleted","blob_policy:__deleted"]);function MQ(X,Q,$){if($!==null)return JSON.parse($);return KX.has(`${X}:${Q}`)?0:null}function kQ(X){if(X===null||X===void 0)return null;if(typeof X==="boolean")return X?1:0;if(typeof X==="number")return X;if(typeof X==="string")return X;return JSON.stringify(X)}function zQ(X,Q,$){X.query(`INSERT OR IGNORE INTO ${Q} (id) VALUES (?)`).run($)}function DX(X,Q){return X.query("SELECT 1 AS x FROM doc_blocks WHERE doc_id = ? LIMIT 1").get(Q)!=null}function BX(X,Q){let $=X.query("SELECT text, blank_after FROM doc_blocks WHERE doc_id = ? AND __deleted = 0 ORDER BY order_key, id").all(Q);zQ(X,"documents",Q),X.query("UPDATE documents SET body = ? WHERE id = ?").run(TQ($.map((Z)=>({text:Z.text,blankAfter:Z.blank_after??0}))),Q)}function OX(X,Q,$,Z,W){if(NX.has(Q))return;if(Q==="records"){if(AX.has(Z)){zQ(X,"records",$);let J=MQ("records",Z,W);X.query(`UPDATE records SET "${Z}" = ? WHERE id = ?`).run(kQ(J),$)}else if(zQ(X,"records",$),W===null)X.query(`UPDATE records SET data = json_remove(data, '$."' || ? || '"') WHERE id = ?`).run(Z,$);else X.query(`UPDATE records SET data = json_set(coalesce(data, '{}'), '$."' || ? || '"', json(?)) WHERE id = ?`).run(Z,W,$);return}let z=LX[Q];if(!z||!z.cols.has(Z))return;if(Q==="documents"&&Z==="body"&&DX(X,$))return;zQ(X,z.table,$);let j=MQ(Q,Z,W);if(X.query(`UPDATE ${z.table} SET "${Z}" = ? WHERE id = ?`).run(kQ(j),$),Q==="doc_blocks"){let J=X.query("SELECT doc_id FROM doc_blocks WHERE id = ?").get($);if(J?.doc_id)BX(X,J.doc_id)}}function _X(X,Q){let $=X.query("INSERT OR IGNORE INTO crdt_changes (hlc, node_id, dataset, row_id, col, value, txn) VALUES (?, ?, ?, ?, ?, ?, ?)").run(Q.hlc,Q.node_id,Q.dataset,Q.row_id,Q.col,Q.value,Q.txn??null).changes>0;if(X.query("SELECT MAX(hlc) AS h FROM crdt_changes WHERE dataset = ? AND row_id = ? AND col = ?").get(Q.dataset,Q.row_id,Q.col).h!==Q.hlc)return{inserted:$,winner:!1};try{OX(X,Q.dataset,Q.row_id,Q.col,Q.value)}catch(W){if($)X.query("DELETE FROM crdt_changes WHERE dataset = ? AND row_id = ? AND col = ? AND hlc = ?").run(Q.dataset,Q.row_id,Q.col,Q.hlc);throw W}return{inserted:$,winner:!0}}function L(X,Q,$,Z,W){let z=HX??SQ(X),j={hlc:PQ(X,z),node_id:z,dataset:Q,row_id:$,col:Z,value:W===void 0?null:JSON.stringify(W),txn:WQ};return _X(X,j),j}function yQ(X){return X.replace(/[^a-zA-Z0-9_]/g,"_")}function IQ(X){return X.replace(/'/g,"''")}function gQ(X,Q){return`idx_rec_${yQ(X)}_${yQ(Q)}`}function CX(X,Q,$){return X.query("SELECT 1 AS ok FROM sqlite_master WHERE type = 'index' AND name = ?").get(gQ(Q,$))!=null}function UQ(X,Q,$){let Z=gQ(Q,$);X.exec(`CREATE INDEX IF NOT EXISTS "${Z}" ON records (data ->> '${IQ($)}', created_hlc) WHERE database_id = '${IQ(Q)}' AND __deleted = 0`)}function GQ(X,Q,$){if(CX(X,Q,$.id))return;if($.type!=="relation"){if(X.query("SELECT COUNT(*) AS c FROM records WHERE database_id = ? AND __deleted = 0").get(Q).c<2000)return}UQ(X,Q,$.id)}var EQ=new Set(["text","number","checkbox","select","multi_select","date","relation","url"]),xX=["id","database_id","name","type","config","position"];var vQ=xX.join(", ");function YQ(X,Q){if(X==="select"||X==="multi_select"){let $=Q?.options;if(!Array.isArray($)||$.length===0||!$.every((Z)=>typeof Z==="string"))throw new U("invalid_input",`${X} requires config.options: string[]`)}if(X==="relation"){if(typeof Q?.database!=="string")throw new U("invalid_input","relation requires config.database (target database id)")}}function PX(X,Q){return(X.query("SELECT MAX(position) AS m FROM properties WHERE database_id = ? AND __deleted = 0").get(Q).m??0)+1}var wQ=S(function(Q,$,Z){if(!E(Q,$))throw new U("not_found",`no such database: ${$}`);if(!EQ.has(Z.type))throw new U("invalid_input",`unknown property type: ${Z.type}`);YQ(Z.type,Z.config);let W=Z.indexed?{...Z.config??{},indexed:!0}:Z.config??null,z=i("prop",Z.name);if(L(Q,"properties",z,"database_id",$),L(Q,"properties",z,"name",Z.name),L(Q,"properties",z,"type",Z.type),L(Q,"properties",z,"config",W),L(Q,"properties",z,"position",Z.position??PX(Q,$)),Z.type==="relation"||Z.indexed===!0)UQ(Q,$,z);return JQ(Q,z)});function JQ(X,Q){let $=X.query(`SELECT ${vQ} FROM properties WHERE id = ? AND __deleted = 0`).get(Q);if(!$)return null;return{...$,config:$.config?JSON.parse($.config):null}}function n(X,Q){return X.query(`SELECT ${vQ} FROM properties WHERE database_id = ? AND __deleted = 0 ORDER BY position`).all(Q).map((Z)=>({...Z,config:Z.config?JSON.parse(Z.config):null}))}var M1=S(function(Q,$,Z){let W=JQ(Q,$);if(!W)throw new U("not_found",`no such property: ${$}`);let z=Z.type!==void 0&&Z.type!==W.type;if(Z.type!==void 0&&!EQ.has(Z.type))throw new U("invalid_input",`unknown property type: ${Z.type}`);let j=Z.type??W.type;if(Z.config!==void 0)YQ(j,Z.config);else if(z)YQ(Z.type,void 0);if(Z.name!==void 0)L(Q,"properties",$,"name",Z.name);if(Z.type!==void 0)L(Q,"properties",$,"type",Z.type);if(Z.config!==void 0)L(Q,"properties",$,"config",Z.config);if(Z.position!==void 0)L(Q,"properties",$,"position",Z.position);if(z){let J=Q.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(W.database_id,$);for(let V of J)L(Q,"records",V.id,$,null)}return JQ(Q,$)});var k1=S(function(Q,$){let Z=JQ(Q,$);if(!Z)return!1;L(Q,"properties",$,"__deleted",1);let W=Q.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(Z.database_id,$);for(let z of W)L(Q,"records",z.id,$,void 0);return!0});var SX={db:{table:"databases",nameCol:"name",scoped:!1,noun:"database"},prop:{table:"properties",nameCol:"name",scoped:!0,noun:"property"},rec:{table:"records",nameCol:null,scoped:!0,noun:"record"},doc:{table:"documents",nameCol:"title",scoped:!0,noun:"document"}},TX=["db","prop","rec","doc"];function RX(X){return X!==null&&X!=="blk"}var hQ="{";function MX(X,Q){return X.query("SELECT id FROM properties WHERE database_id = ? AND type = 'text' AND __deleted = 0 ORDER BY position LIMIT 1").get(Q)?.id??null}function kX(X,Q,$,Z){let W=SX[Q],z=W.nameCol;if(Q==="rec"&&Z){let O=MX(X,Z);if(O)z=`data ->> '${O.replace(/'/g,"''")}'`}let j=z??"''",J=[],V=[];J.push("(id >= ? AND id < ?)"),V.push($,$+hQ);let B=`${Q}_${$}`;if(J.push("(id >= ? AND id < ?)"),V.push(B,B+hQ),z)J.push(`lower(${z}) = lower(?)`),V.push($);let _=`SELECT id, ${j} AS label FROM ${W.table} WHERE __deleted = 0 AND (${J.join(" OR ")})`;if(W.scoped&&Z)_+=" AND database_id = ?",V.push(Z);return X.query(_).all(...V).map((O)=>({kind:Q,id:O.id,label:O.label??""}))}function mQ(X,Q,$={}){let Z=$.kind?[$.kind]:RX(t(Q))?[t(Q)]:TX,W=[],z=new Set;for(let j of Z)for(let J of kX(X,j,Q,$.databaseId)){if(z.has(J.id))continue;z.add(J.id),W.push(J)}return W}function HQ(X,Q){if(Q!==null&&X>=Q)throw Error(`fracdex: ${X} >= ${Q}`);if(X.endsWith("0")||Q!==null&&Q.endsWith("0"))throw Error(`fracdex: trailing zero in ${X}/${Q}`);if(Q!==null){let z=0;while((X[z]??"0")===Q[z])z++;if(z>0)return Q.slice(0,z)+HQ(X.slice(z),Q.slice(z))}let Z=X===""?0:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".indexOf(X[0]),W=Q===null?62:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".indexOf(Q[0]);if(W-Z>1)return"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[Math.round(0.5*(Z+W))];if(Q!==null&&Q.length>1)return Q.slice(0,1);return"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[Z]+HQ(X.slice(1),null)}function m(X,Q){return HQ(X??"",Q)}function r(X,Q,$){if($<=0)return[];if($===1)return[m(X,Q)];if(Q===null){let z=m(X,null),j=[z];for(let J=1;J<$;J++)z=m(z,null),j.push(z);return j}if(X===null){let z=m(null,Q),j=[z];for(let J=1;J<$;J++)z=m(null,z),j.unshift(z);return j}let Z=Math.floor($/2),W=m(X,Q);return[...r(X,W,Z),W,...r(W,Q,$-Z-1)]}function fQ(X){return typeof X==="string"||typeof X==="number"||typeof X==="boolean"}function yX(X){return typeof X==="boolean"?X?1:0:X}function IX(X,Q,$){let Z=Q.config?.database;if(!Z)return $;let W=mQ(X,$,{kind:"rec",databaseId:Z}),z=W.find((j)=>j.id===$);if(z)return z.id;if(W.length===1)return W[0].id;if(W.length===0){if(t($)==="rec")return $;throw new U("not_found",`${Q.name}: no such record in target database: ${$}`)}throw new U("ambiguous",`${Q.name}: ambiguous relation "${$}" (${W.length} matches); use a full id`)}function LQ(X,Q,$){switch(Q.type){case"text":case"url":case"date":{if($===null)return null;if(typeof $!=="string")throw new U("invalid_input",`${Q.name} expects a string`);return $}case"number":{if($===null)return null;let Z=typeof $==="number"?$:Number($);if(!Number.isFinite(Z))throw new U("invalid_input",`${Q.name} expects a number`);return Z}case"checkbox":{if(typeof $==="boolean")return $;if($==="true"||$===1)return!0;if($==="false"||$===0||$===null)return!1;throw new U("invalid_input",`${Q.name} expects a boolean`)}case"select":{if($===null)return null;let Z=String($);if(!Q.config?.options?.includes(Z))throw new U("invalid_input",`${Q.name}: '${Z}' is not an allowed option`);return Z}case"multi_select":{let Z=$===null?[]:Array.isArray($)?$:[$],W=Q.config?.options??[];for(let z of Z)if(!W.includes(String(z)))throw new U("invalid_input",`${Q.name}: '${z}' is not an allowed option`);return Z.map(String)}case"relation":return($===null?[]:Array.isArray($)?$:[$]).map((W)=>IX(X,Q,String(W)))}}function gX(X){let Q=new Map;for(let $ of X){let Z=$.name.toLowerCase(),W=Q.get(Z);if(W)W.push($);else Q.set(Z,[$])}return Q}function AQ(X,Q){let $=new Map(X.map((z)=>[z.id,z])),Z=gX(X),W=[];for(let[z,j]of Object.entries(Q)){let J=$.get(z);if(!J){let V=Z.get(z.toLowerCase())??[];if(V.length>1)throw new U("ambiguous",`property name "${z}" matches ${V.length} properties; use a property id`);J=V[0]}if(!J)throw new U("not_found",`unknown property: ${z}`);W.push({prop:J,value:j})}return W}function nQ(X,Q,$){return AQ(n(X,Q),$).map(({prop:Z,value:W})=>({prop:Z,value:LQ(X,Z,W)}))}function bQ(X,Q){let $=JSON.parse(X.data||"{}"),Z=new Map(Q.map((j)=>[j.id,j])),W={},z={};for(let[j,J]of Object.entries($)){let V=Z.get(j);if(!V)continue;W[V.name]=J,z[V.id]=J}return{id:X.id,database_id:X.database_id,values:W,cells:z}}function EX(X,Q){let $=X.find((Z)=>Z.prop.type==="text"&&typeof Z.value==="string"&&Z.value);return i("rec",$?String($.value):"",Q)}function uQ(X,Q){return X.query("SELECT 1 AS ok FROM sqlite_master WHERE type = 'table' AND name = ?").get(Q)!=null}function vX(X){return uQ(X,"meta")&&uQ(X,"crdt_changes")}function wX(X,Q,$,Z){if(Z)L(X,"records",Q,"order_key",$);else X.query("UPDATE records SET order_key = ? WHERE id = ?").run($,Q)}function lQ(X,Q){return X.query(`SELECT order_key FROM records
|
|
1
|
+
class U extends Error{code;constructor($,Q){super(Q);this.code=$;this.name="MhError"}}function E($=6){let Q=crypto.getRandomValues(new Uint8Array($)),X="";for(let Z of Q)X+="0123456789abcdefghijklmnopqrstuvwxyz".charAt(Z%36);return X}function VQ($,Q="item"){return $.normalize("NFKD").replace(/[^\x20-\x7E]/g,"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,32).replace(/-+$/g,"")||Q}var VX=new Set(["db","prop","rec","doc","blk","site","sf","chan"]);function o($,Q,X=$){return`${$}_${VQ(Q,X)}-${E()}`}function r($){let Q=$.indexOf("_");if(Q<=0)return null;let X=$.slice(0,Q);return VX.has(X)?X:null}var UX=600000;function BQ($){let Q=new Uint8Array($.byteLength);return Q.set($),Q.buffer}function ZQ($){let Q="";for(let X=0;X<$.length;X++)Q+=String.fromCharCode($[X]);return btoa(Q)}function WQ($){let Q=atob($),X=new Uint8Array(Q.length);for(let Z=0;Z<Q.length;Z++)X[Z]=Q.charCodeAt(Z);return X}async function OQ($,Q){let X=await crypto.subtle.importKey("raw",BQ(new TextEncoder().encode($)),"PBKDF2",!1,["deriveBits"]),Z=await crypto.subtle.deriveBits({name:"PBKDF2",salt:BQ(Q),iterations:UX,hash:"SHA-256"},X,256);return new Uint8Array(Z)}function _Q($,Q){if(Q<=65535)return{millis:$,counter:Q};return{millis:$+Math.floor(Q/65536),counter:Q%65536}}function CQ($){let{millis:Q,counter:X}=_Q($.millis,$.counter);return`${String(Q).padStart(15,"0")}-${X.toString(16).padStart(4,"0")}-${$.node}`}function xQ($){let Q=$.indexOf("-"),X=$.indexOf("-",Q+1);return{millis:Number($.slice(0,Q)),counter:parseInt($.slice(Q+1,X),16),node:$.slice(X+1)}}function GX($,Q){let X=$.query("SELECT value FROM meta WHERE key = 'hlc'").get();return X?xQ(X.value):{millis:0,counter:0,node:Q}}function YX($,Q){$.query("INSERT INTO meta (key, value) VALUES ('hlc', ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value").run(CQ(Q))}function PQ($,Q,X=Date.now()){let Z=GX($,Q),W=Math.max(Z.millis,X),z=W===Z.millis?Z.counter+1:0,j={..._Q(W,z),node:Q};return YX($,j),CQ(j)}function SQ($){let Q=$.query("SELECT value FROM meta WHERE key = 'node_id'").get();if(Q)return Q.value;let X=E(8);return $.query("INSERT INTO meta (key, value) VALUES ('node_id', ?)").run(X),X}function TQ($){let Q=$.filter((Z)=>!!Z.text&&Z.text.length>0),X=[];return Q.forEach((Z,W)=>{X.push(...Z.text.split(`
|
|
2
|
+
`));let z=Math.max(0,Z.blankAfter??0);if(W<Q.length-1)X.push("");for(let j=0;j<z;j++)X.push("")}),X.join(`
|
|
3
|
+
`)}var RQ="intent_receipts";var HX=["hlc","node_id","dataset","row_id","col","value","txn"];var _1=HX.join(", "),zQ=null,qX=null;function LX($,Q){if(zQ!==null)return Q();zQ=($?$+":":"")+E(8);try{return Q()}finally{zQ=null}}function P($,Q=null){return(...X)=>LX(Q,()=>$(...X))}var AX={databases:{table:"databases",cols:new Set(["name","icon","meta","created_hlc","__deleted"])},properties:{table:"properties",cols:new Set(["database_id","name","type","config","position","__deleted"])},documents:{table:"documents",cols:new Set(["title","body","database_id","parent_id","created_hlc","order_key","__deleted"])},doc_blocks:{table:"doc_blocks",cols:new Set(["doc_id","text","order_key","blank_after","__deleted"])},sites:{table:"sites",cols:new Set(["name","title","created_hlc","visibility","spa","public_grants","__deleted"])},site_channels:{table:"site_channels",cols:new Set(["site_id","audience","hosting","controller_node_id","target_ref","canonical_url","policy_json","desired_state","created_hlc","__deleted"])},site_files:{table:"site_files",cols:new Set(["site_id","path","content_type","encoding","content","created_hlc","__deleted"])},blob_policy:{table:"blob_policy",cols:new Set(["full_nodes","redundancy","__deleted"])}},NX=new Set(["database_id","created_hlc","order_key","__deleted"]),KX=new Set([RQ]),DX=new Set(["records:__deleted","databases:__deleted","properties:__deleted","documents:__deleted","doc_blocks:__deleted","doc_blocks:blank_after","sites:__deleted","sites:spa","site_channels:__deleted","site_files:__deleted","blob_policy:__deleted"]);function MQ($,Q,X){if(X!==null)return JSON.parse(X);return DX.has(`${$}:${Q}`)?0:null}function kQ($){if($===null||$===void 0)return null;if(typeof $==="boolean")return $?1:0;if(typeof $==="number")return $;if(typeof $==="string")return $;return JSON.stringify($)}function JQ($,Q,X){$.query(`INSERT OR IGNORE INTO ${Q} (id) VALUES (?)`).run(X)}function BX($,Q){return $.query("SELECT 1 AS x FROM doc_blocks WHERE doc_id = ? LIMIT 1").get(Q)!=null}function OX($,Q){let X=$.query("SELECT text, blank_after FROM doc_blocks WHERE doc_id = ? AND __deleted = 0 ORDER BY order_key, id").all(Q);JQ($,"documents",Q),$.query("UPDATE documents SET body = ? WHERE id = ?").run(TQ(X.map((Z)=>({text:Z.text,blankAfter:Z.blank_after??0}))),Q)}function _X($,Q,X,Z,W){if(KX.has(Q))return;if(Q==="records"){if(NX.has(Z)){JQ($,"records",X);let J=MQ("records",Z,W);$.query(`UPDATE records SET "${Z}" = ? WHERE id = ?`).run(kQ(J),X)}else if(JQ($,"records",X),W===null)$.query(`UPDATE records SET data = json_remove(data, '$."' || ? || '"') WHERE id = ?`).run(Z,X);else $.query(`UPDATE records SET data = json_set(coalesce(data, '{}'), '$."' || ? || '"', json(?)) WHERE id = ?`).run(Z,W,X);return}let z=AX[Q];if(!z||!z.cols.has(Z))return;if(Q==="documents"&&Z==="body"&&BX($,X))return;JQ($,z.table,X);let j=MQ(Q,Z,W);if($.query(`UPDATE ${z.table} SET "${Z}" = ? WHERE id = ?`).run(kQ(j),X),Q==="doc_blocks"){let J=$.query("SELECT doc_id FROM doc_blocks WHERE id = ?").get(X);if(J?.doc_id)OX($,J.doc_id)}}function CX($,Q){let X=$.query("INSERT OR IGNORE INTO crdt_changes (hlc, node_id, dataset, row_id, col, value, txn) VALUES (?, ?, ?, ?, ?, ?, ?)").run(Q.hlc,Q.node_id,Q.dataset,Q.row_id,Q.col,Q.value,Q.txn??null).changes>0;if($.query("SELECT MAX(hlc) AS h FROM crdt_changes WHERE dataset = ? AND row_id = ? AND col = ?").get(Q.dataset,Q.row_id,Q.col).h!==Q.hlc)return{inserted:X,winner:!1};try{_X($,Q.dataset,Q.row_id,Q.col,Q.value)}catch(W){if(X)$.query("DELETE FROM crdt_changes WHERE dataset = ? AND row_id = ? AND col = ? AND hlc = ?").run(Q.dataset,Q.row_id,Q.col,Q.hlc);throw W}return{inserted:X,winner:!0}}function q($,Q,X,Z,W){let z=qX??SQ($),j={hlc:PQ($,z),node_id:z,dataset:Q,row_id:X,col:Z,value:W===void 0?null:JSON.stringify(W),txn:zQ};return CX($,j),j}function IQ($){return $.replace(/[^a-zA-Z0-9_]/g,"_")}function yQ($){return $.replace(/'/g,"''")}function EQ($,Q){return`idx_rec_${IQ($)}_${IQ(Q)}`}function xX($,Q,X){return $.query("SELECT 1 AS ok FROM sqlite_master WHERE type = 'index' AND name = ?").get(EQ(Q,X))!=null}function UQ($,Q,X){let Z=EQ(Q,X);$.exec(`CREATE INDEX IF NOT EXISTS "${Z}" ON records (data ->> '${yQ(X)}', created_hlc) WHERE database_id = '${yQ(Q)}' AND __deleted = 0`)}function GQ($,Q,X){if(xX($,Q,X.id))return;if(X.type!=="relation"){if($.query("SELECT COUNT(*) AS c FROM records WHERE database_id = ? AND __deleted = 0").get(Q).c<2000)return}UQ($,Q,X.id)}var gQ=new Set(["text","number","checkbox","select","multi_select","date","relation","url"]),PX=["id","database_id","name","type","config","position"];var wQ=PX.join(", ");function YQ($,Q){if($==="select"||$==="multi_select"){let X=Q?.options;if(!Array.isArray(X)||X.length===0||!X.every((Z)=>typeof Z==="string"))throw new U("invalid_input",`${$} requires config.options: string[]`)}if($==="relation"){if(typeof Q?.database!=="string")throw new U("invalid_input","relation requires config.database (target database id)")}}function SX($,Q){return($.query("SELECT MAX(position) AS m FROM properties WHERE database_id = ? AND __deleted = 0").get(Q).m??0)+1}var vQ=P(function(Q,X,Z){if(!g(Q,X))throw new U("not_found",`no such database: ${X}`);if(!gQ.has(Z.type))throw new U("invalid_input",`unknown property type: ${Z.type}`);YQ(Z.type,Z.config);let W=Z.indexed?{...Z.config??{},indexed:!0}:Z.config??null,z=o("prop",Z.name);if(q(Q,"properties",z,"database_id",X),q(Q,"properties",z,"name",Z.name),q(Q,"properties",z,"type",Z.type),q(Q,"properties",z,"config",W),q(Q,"properties",z,"position",Z.position??SX(Q,X)),Z.type==="relation"||Z.indexed===!0)UQ(Q,X,z);return n(Q,z)});function n($,Q){let X=$.query(`SELECT ${wQ} FROM properties WHERE id = ? AND __deleted = 0`).get(Q);if(!X)return null;return{...X,config:X.config?JSON.parse(X.config):null}}function l($,Q){return $.query(`SELECT ${wQ} FROM properties WHERE database_id = ? AND __deleted = 0 ORDER BY position`).all(Q).map((Z)=>({...Z,config:Z.config?JSON.parse(Z.config):null}))}var k1=P(function(Q,X,Z){let W=n(Q,X);if(!W)throw new U("not_found",`no such property: ${X}`);let z=Z.type!==void 0&&Z.type!==W.type;if(Z.type!==void 0&&!gQ.has(Z.type))throw new U("invalid_input",`unknown property type: ${Z.type}`);let j=Z.type??W.type,J;if(Z.config!==void 0){let F={...W.config??{}};for(let[Y,D]of Object.entries(Z.config))if(D===null)delete F[Y];else F[Y]=D;J=F,YQ(j,J)}else if(z)YQ(Z.type,W.config??void 0);if(Z.name!==void 0)q(Q,"properties",X,"name",Z.name);if(Z.type!==void 0)q(Q,"properties",X,"type",Z.type);if(J!==void 0)q(Q,"properties",X,"config",J);if(Z.position!==void 0)q(Q,"properties",X,"position",Z.position);if(z){let F=Q.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(W.database_id,X);for(let Y of F)q(Q,"records",Y.id,X,null)}return n(Q,X)});function hQ($,Q){let X=n($,Q);if(!X)throw new U("not_found",`no such property: ${Q}`);if(X.type!=="select"&&X.type!=="multi_select")throw new U("invalid_input",`${X.type} property has no options`);return{prop:X,options:X.config?.options??[]}}var I1=P(function(Q,X,Z,W){let{prop:z,options:j}=hQ(Q,X);if(W=W.trim(),!W)throw new U("invalid_input","option name must not be empty");if(!j.includes(Z))throw new U("not_found",`no such option: ${Z}`);if(W===Z)return{property:z,renamed:0};if(j.includes(W))throw new U("conflict",`option already exists: ${W}`);q(Q,"properties",X,"config",{...z.config??{},options:j.map((F)=>F===Z?W:F)});let J=0;if(z.type==="select"){let F=Q.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? = ?").all(z.database_id,X,Z);for(let Y of F)q(Q,"records",Y.id,X,W);J=F.length}else{let F=Q.query("SELECT id, data ->> ? AS v FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(X,z.database_id,X);for(let Y of F){let D=JSON.parse(Y.v);if(!Array.isArray(D)||!D.includes(Z))continue;q(Q,"records",Y.id,X,[...new Set(D.map((_)=>_===Z?W:_))]),J++}}return{property:n(Q,X),renamed:J}}),y1=P(function(Q,X,Z){let{prop:W,options:z}=hQ(Q,X);if(!z.includes(Z))throw new U("not_found",`no such option: ${Z}`);if(z.length===1)throw new U("invalid_input","cannot remove the last option; delete the property instead");q(Q,"properties",X,"config",{...W.config??{},options:z.filter((J)=>J!==Z)});let j=0;if(W.type==="select"){let J=Q.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? = ?").all(W.database_id,X,Z);for(let F of J)q(Q,"records",F.id,X,null);j=J.length}else{let J=Q.query("SELECT id, data ->> ? AS v FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(X,W.database_id,X);for(let F of J){let Y=JSON.parse(F.v);if(!Array.isArray(Y)||!Y.includes(Z))continue;q(Q,"records",F.id,X,Y.filter((D)=>D!==Z)),j++}}return{property:n(Q,X),cleared:j}}),E1=P(function(Q,X){let Z=n(Q,X);if(!Z)return!1;q(Q,"properties",X,"__deleted",1);let W=Q.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(Z.database_id,X);for(let z of W)q(Q,"records",z.id,X,void 0);return!0});var TX={db:{table:"databases",nameCol:"name",scoped:!1,noun:"database"},prop:{table:"properties",nameCol:"name",scoped:!0,noun:"property"},rec:{table:"records",nameCol:null,scoped:!0,noun:"record"},doc:{table:"documents",nameCol:"title",scoped:!0,noun:"document"}},RX=["db","prop","rec","doc"];function MX($){return $!==null&&$!=="blk"}var mQ="{";function kX($,Q){return $.query("SELECT id FROM properties WHERE database_id = ? AND type = 'text' AND __deleted = 0 ORDER BY position LIMIT 1").get(Q)?.id??null}function IX($,Q,X,Z){let W=TX[Q],z=W.nameCol;if(Q==="rec"&&Z){let C=kX($,Z);if(C)z=`data ->> '${C.replace(/'/g,"''")}'`}let j=z??"''",J=[],F=[];J.push("(id >= ? AND id < ?)"),F.push(X,X+mQ);let Y=`${Q}_${X}`;if(J.push("(id >= ? AND id < ?)"),F.push(Y,Y+mQ),z)J.push(`lower(${z}) = lower(?)`),F.push(X);let D=`SELECT id, ${j} AS label FROM ${W.table} WHERE __deleted = 0 AND (${J.join(" OR ")})`;if(W.scoped&&Z)D+=" AND database_id = ?",F.push(Z);return $.query(D).all(...F).map((C)=>({kind:Q,id:C.id,label:C.label??""}))}function fQ($,Q,X={}){let Z=X.kind?[X.kind]:MX(r(Q))?[r(Q)]:RX,W=[],z=new Set;for(let j of Z)for(let J of IX($,j,Q,X.databaseId)){if(z.has(J.id))continue;z.add(J.id),W.push(J)}return W}function HQ($,Q){if(Q!==null&&$>=Q)throw Error(`fracdex: ${$} >= ${Q}`);if($.endsWith("0")||Q!==null&&Q.endsWith("0"))throw Error(`fracdex: trailing zero in ${$}/${Q}`);if(Q!==null){let z=0;while(($[z]??"0")===Q[z])z++;if(z>0)return Q.slice(0,z)+HQ($.slice(z),Q.slice(z))}let Z=$===""?0:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".indexOf($[0]),W=Q===null?62:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".indexOf(Q[0]);if(W-Z>1)return"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[Math.round(0.5*(Z+W))];if(Q!==null&&Q.length>1)return Q.slice(0,1);return"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[Z]+HQ($.slice(1),null)}function m($,Q){return HQ($??"",Q)}function d($,Q,X){if(X<=0)return[];if(X===1)return[m($,Q)];if(Q===null){let z=m($,null),j=[z];for(let J=1;J<X;J++)z=m(z,null),j.push(z);return j}if($===null){let z=m(null,Q),j=[z];for(let J=1;J<X;J++)z=m(null,z),j.unshift(z);return j}let Z=Math.floor(X/2),W=m($,Q);return[...d($,W,Z),W,...d(W,Q,X-Z-1)]}function uQ($){return typeof $==="string"||typeof $==="number"||typeof $==="boolean"}function yX($){return typeof $==="boolean"?$?1:0:$}function EX($,Q,X){let Z=Q.config?.database;if(!Z)return X;let W=fQ($,X,{kind:"rec",databaseId:Z}),z=W.find((j)=>j.id===X);if(z)return z.id;if(W.length===1)return W[0].id;if(W.length===0){if(r(X)==="rec")return X;throw new U("not_found",`${Q.name}: no such record in target database: ${X}`)}throw new U("ambiguous",`${Q.name}: ambiguous relation "${X}" (${W.length} matches); use a full id`)}function LQ($,Q,X){switch(Q.type){case"text":case"url":case"date":{if(X===null)return null;if(typeof X!=="string")throw new U("invalid_input",`${Q.name} expects a string`);return X}case"number":{if(X===null)return null;let Z=typeof X==="number"?X:Number(X);if(!Number.isFinite(Z))throw new U("invalid_input",`${Q.name} expects a number`);return Z}case"checkbox":{if(typeof X==="boolean")return X;if(X==="true"||X===1)return!0;if(X==="false"||X===0||X===null)return!1;throw new U("invalid_input",`${Q.name} expects a boolean`)}case"select":{if(X===null)return null;let Z=String(X);if(!Q.config?.options?.includes(Z))throw new U("invalid_input",`${Q.name}: '${Z}' is not an allowed option`);return Z}case"multi_select":{let Z=X===null?[]:Array.isArray(X)?X:[X],W=Q.config?.options??[];for(let z of Z)if(!W.includes(String(z)))throw new U("invalid_input",`${Q.name}: '${z}' is not an allowed option`);return Z.map(String)}case"relation":return(X===null?[]:Array.isArray(X)?X:[X]).map((W)=>EX($,Q,String(W)))}}function gX($){let Q=new Map;for(let X of $){let Z=X.name.toLowerCase(),W=Q.get(Z);if(W)W.push(X);else Q.set(Z,[X])}return Q}function AQ($,Q){let X=new Map($.map((z)=>[z.id,z])),Z=gX($),W=[];for(let[z,j]of Object.entries(Q)){let J=X.get(z);if(!J){let F=Z.get(z.toLowerCase())??[];if(F.length>1)throw new U("ambiguous",`property name "${z}" matches ${F.length} properties; use a property id`);J=F[0]}if(!J)throw new U("not_found",`unknown property: ${z}`);W.push({prop:J,value:j})}return W}function lQ($,Q,X){return AQ(l($,Q),X).map(({prop:Z,value:W})=>({prop:Z,value:LQ($,Z,W)}))}function bQ($,Q){let X=JSON.parse($.data||"{}"),Z=new Map(Q.map((j)=>[j.id,j])),W={},z={};for(let[j,J]of Object.entries(X)){let F=Z.get(j);if(!F)continue;W[F.name]=J,z[F.id]=J}return{id:$.id,database_id:$.database_id,values:W,cells:z}}function wX($,Q){let X=$.find((Z)=>Z.prop.type==="text"&&typeof Z.value==="string"&&Z.value);return o("rec",X?String(X.value):"",Q)}function cQ($,Q){return $.query("SELECT 1 AS ok FROM sqlite_master WHERE type = 'table' AND name = ?").get(Q)!=null}function vX($){return cQ($,"meta")&&cQ($,"crdt_changes")}function hX($,Q,X,Z){if(Z)q($,"records",Q,"order_key",X);else $.query("UPDATE records SET order_key = ? WHERE id = ?").run(X,Q)}function pQ($,Q){return $.query(`SELECT order_key FROM records
|
|
4
4
|
WHERE database_id = ? AND __deleted = 0 AND order_key IS NOT NULL
|
|
5
|
-
ORDER BY order_key DESC, id DESC LIMIT 1`).get(Q)?.order_key??null}function qQ(
|
|
5
|
+
ORDER BY order_key DESC, id DESC LIMIT 1`).get(Q)?.order_key??null}function qQ($,Q){return $.query(`SELECT id, database_id, created_hlc, order_key FROM records
|
|
6
6
|
WHERE database_id = ? AND __deleted = 0
|
|
7
|
-
ORDER BY order_key IS NULL, order_key, created_hlc, id`).all(Q)}function
|
|
7
|
+
ORDER BY order_key IS NULL, order_key, created_hlc, id`).all(Q)}function mX($,Q){let X=qQ($,Q),Z=d(null,null,X.length);X.forEach((W,z)=>{if(W.order_key!==Z[z])q($,"records",W.id,"order_key",Z[z])})}var fX=P(function(Q,X){let Z=vX(Q),W=X?[{database_id:X}]:Q.query(`SELECT DISTINCT database_id FROM records
|
|
8
8
|
WHERE database_id IS NOT NULL AND __deleted = 0 AND order_key IS NULL`).all();for(let z of W){let j=Q.query(`SELECT id FROM records
|
|
9
9
|
WHERE database_id = ? AND __deleted = 0 AND order_key IS NULL
|
|
10
|
-
ORDER BY created_hlc, id`).all(z.database_id);if(!j.length)continue;let J=lQ(Q,z.database_id),V=r(J,null,j.length);j.forEach((B,_)=>wX(Q,B.id,V[_],Z))}}),pQ=S(function(Q,$,Z){let W=EX(Z,VQ($.name,"rec")),z=m(lQ(Q,$.id),null),j=L(Q,"records",W,"database_id",$.id);L(Q,"records",W,"created_hlc",j.hlc),L(Q,"records",W,"order_key",z);for(let{prop:J,value:V}of Z)L(Q,"records",W,J.id,V);return d(Q,W)}),iQ=S(function(Q,$,Z){let W=E(Q,$);if(!W)throw new U("not_found",`no such database: ${$}`);return pQ(Q,W,nQ(Q,W.id,Z))});function d(X,Q){let $=X.query("SELECT id, database_id, data FROM records WHERE id = ? AND __deleted = 0").get(Q);if(!$)return null;return bQ($,n(X,$.database_id))}function cQ(X){return X.replace(/'/g,"''")}function oQ(X,Q,$={}){let Z=n(X,Q),W=$.filter&&Object.keys($.filter).length?AQ(Z,$.filter).map(({prop:K,value:R})=>({prop:K,value:LQ(X,K,R)})):[],z=W.filter((K)=>fQ(K.value)),j=W.filter((K)=>!fQ(K.value)),J,V=!1;if($.sort){let K=$.sort;if(K.startsWith("-"))V=!0,K=K.slice(1);if(K!=="created"&&K!=="created_hlc"){let R=Z.find((v)=>v.id===K);if(!R){let v=Z.filter((u)=>u.name.toLowerCase()===K.toLowerCase());if(v.length>1)throw new U("ambiguous",`sort field "${K}" matches ${v.length} properties; use a property id`);R=v[0]}if(!R)throw new U("not_found",`unknown sort field: ${K}`);J=R}}for(let K of z)GQ(X,Q,K.prop);if(J)GQ(X,Q,J);let B=["database_id = ?","__deleted = 0"],_=[Q];for(let K of z)B.push(`data ->> '${cQ(K.prop.id)}' = ?`),_.push(yX(K.value));let C=$.sort==null,O=J?`data ->> '${cQ(J.id)}'`:"created_hlc",T=`SELECT id, database_id, data FROM records WHERE ${B.join(" AND ")} `+(C?"ORDER BY order_key IS NULL, order_key, id":`ORDER BY ${O} ${V?"DESC":"ASC"}, id`);if($.limit!=null&&j.length===0)T+=" LIMIT ?",_.push($.limit);let y=X.query(T).all(..._).map((K)=>bQ(K,Z));if(j.length){if(y=y.filter((K)=>j.every((R)=>JSON.stringify(K.cells[R.prop.id]??null)===JSON.stringify(R.value))),$.limit!=null)y=y.slice(0,$.limit)}return y}var l1=S(function(Q,$,Z,W){if(W!=="before"&&W!=="after")throw new U("invalid_input",`unknown move position: ${W}`);let z=Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get($);if(!z)throw new U("not_found",`no such record: ${$}`);let j=Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get(Z);if(!j)throw new U("not_found",`no such record: ${Z}`);if(z.database_id!==j.database_id)throw new U("invalid_input","cannot move a record across databases");if($===Z)return d(Q,$);mX(Q,z.database_id);let J=qQ(Q,z.database_id).filter((C)=>C.id!==$),V=J.findIndex((C)=>C.id===Z);if(V<0)throw new U("not_found",`no such target record: ${Z}`);let B=W==="before"?J[V-1]?.order_key??null:J[V].order_key,_=W==="before"?J[V].order_key:J[V+1]?.order_key??null;if(B!==null&&_!==null&&B>=_)hX(Q,z.database_id),J=qQ(Q,z.database_id).filter((C)=>C.id!==$),V=J.findIndex((C)=>C.id===Z),B=W==="before"?J[V-1]?.order_key??null:J[V].order_key,_=W==="before"?J[V].order_key:J[V+1]?.order_key??null;return L(Q,"records",$,"order_key",m(B,_)),d(Q,$)}),sQ=S(function(Q,$,Z){if(!Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get($))throw new U("not_found",`no such record: ${$}`);for(let{prop:z,value:j}of Z)L(Q,"records",$,z.id,j);return d(Q,$)}),p1=S(function(Q,$,Z){let W=Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get($);if(!W)throw new U("not_found",`no such record: ${$}`);return sQ(Q,$,nQ(Q,W.database_id,Z))}),i1=S(function(Q,$){if(!Q.query("SELECT id FROM records WHERE id = ? AND __deleted = 0").get($))return!1;return L(Q,"records",$,"__deleted",1),!0});var fX=["id","name","icon","meta","created_hlc"];var uX=fX.join(", ");function cX(X){if(!X)return null;return{...X,meta:X.meta===null?null:JSON.parse(X.meta)}}var nX=S(function(Q,$){let Z=i("db",$.name),W=L(Q,"databases",Z,"name",$.name);if(L(Q,"databases",Z,"created_hlc",W.hlc),$.icon!==void 0)L(Q,"databases",Z,"icon",$.icon);return E(Q,Z)}),e1=S(function(Q,$,Z){if(!E(Q,$))throw new U("not_found",`no such database: ${$}`);if(Z.name!==void 0)L(Q,"databases",$,"name",Z.name);if(Z.icon!==void 0)L(Q,"databases",$,"icon",Z.icon);if(Z.meta!==void 0){if(Z.meta!==null&&(typeof Z.meta!=="object"||Array.isArray(Z.meta)))throw new U("invalid_input","meta must be a JSON object or null");L(Q,"databases",$,"meta",Z.meta)}return E(Q,$)}),Q4=S(function(Q,$,Z={}){let W=E(Q,$);if(!W)throw new U("not_found",`no such database: ${$}`);let z=nX(Q,{name:Z.name??W.name,icon:Z.icon??W.icon??void 0});if(W.meta!==null){let{collapsed:J,...V}=W.meta;if(Object.keys(V).length)L(Q,"databases",z.id,"meta",V)}let j=new Map;for(let J of n(Q,$)){let V=J.config?.database===$?{...J.config,database:z.id}:J.config??void 0,B=wQ(Q,z.id,{name:J.name,type:J.type,config:V,position:J.position});j.set(J.id,B.id)}for(let J of oQ(Q,$)){let V={};for(let[B,_]of Object.entries(J.cells)){let C=j.get(B);if(C)V[C]=_}iQ(Q,z.id,V)}return E(Q,z.id)});function E(X,Q){return cX(X.query(`SELECT ${uX} FROM databases WHERE id = ? AND __deleted = 0`).get(Q))}var X4=S(function(Q,$){if(!E(Q,$))return!1;L(Q,"databases",$,"__deleted",1);let Z=(W)=>{for(let z of aQ(Q,W,"database_id",$))L(Q,W,z,"__deleted",1)};Z("properties"),Z("records");for(let W of aQ(Q,"documents","database_id",$))L(Q,"documents",W,"database_id",null);return Q.query("DELETE FROM meta WHERE key = 'current_db' AND value = ?").run($),!0});function aQ(X,Q,$,Z){return X.query(`SELECT id FROM ${Q} WHERE ${$} = ? AND __deleted = 0`).all(Z).map((W)=>W.id)}var rQ="sealed-p256";var bX=12,lX="mh-drop-seal-v1",tQ={name:"ECDH",namedCurve:"P-256"};function e(X){let Q=new Uint8Array(X.byteLength);return Q.set(X),Q.buffer}function dQ(...X){let Q=X.reduce((W,z)=>W+z.byteLength,0),$=new Uint8Array(Q),Z=0;for(let W of X)$.set(W,Z),Z+=W.byteLength;return $}async function pX(X,Q,$){let Z=new Uint8Array(await crypto.subtle.digest("SHA-256",e($))),W=dQ(new TextEncoder().encode(lX),Q,Z),z=await crypto.subtle.importKey("raw",X,"HKDF",!1,["deriveKey"]);return crypto.subtle.deriveKey({name:"HKDF",hash:"SHA-256",salt:new Uint8Array(16).buffer,info:e(W)},z,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}async function eQ(X,Q){let $=await crypto.subtle.importKey("raw",e(X),tQ,!1,[]),Z=await crypto.subtle.generateKey(tQ,!0,["deriveBits"]),W=new Uint8Array(await crypto.subtle.exportKey("raw",Z.publicKey)),z=await crypto.subtle.deriveBits({name:"ECDH",public:$},Z.privateKey,256),j=await pX(z,W,X),J=crypto.getRandomValues(new Uint8Array(bX)),V=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:e(J)},j,e(Q)));return dQ(W,J,V)}var QX=/^g[0-9a-z]{8}$/;function iX(){return"e"+g(16)}function XX(){return"g"+g(8)}function oX(X){return new TextEncoder().encode(JSON.stringify(X))}async function $X(X){let Q=await eQ(X.pk,oX(X.payload));return{v:1,envelope_id:iX(),drop_id:X.dropId,enc:rQ,key_id:X.keyId,sealed:$Q(Q),created_at:X.now??Date.now()}}async function NQ(X,Q){return $Q(await OQ(X,ZQ(Q)))}function ZX(){try{if(typeof localStorage<"u"&&localStorage)return localStorage.getItem("mh_drop_probe"),{get:(Q)=>localStorage.getItem(Q),set:(Q,$)=>localStorage.setItem(Q,$)}}catch{}let X=new Map;return{get:(Q)=>X.get(Q)??null,set:(Q,$)=>X.set(Q,$)}}function sX(X){if(X===401)return"auth";if(X===404)return"not_found";if(X===429)return"rate_limited";if(X===400||X===413)return"invalid_input";return"network"}async function KQ(X="mh-drop.json",Q={}){let Z=await(Q.fetcher??fetch)(X);if(!Z.ok)throw new U("not_found",`no drop config at ${X}`);let W=await Z.json().catch(()=>null);if(!W||W.v!==1||!W.endpoint||!W.drop_id||!W.key_id||!W.pk)throw new U("invalid_input","malformed mh-drop.json");return aX(W,Z.headers.get("date"),Q),FQ(W,Q)}function aX(X,Q,$){if(!Q)return;let Z=Date.parse(Q);if(!Number.isFinite(Z))return;let W=$.storage??ZX(),z="mh_drop_clock:"+X.endpoint.replace(/\/+$/,"");if(W.get(z))return;let j=$.now??(()=>Date.now());W.set(z,String(Z-j()))}function FQ(X,Q={}){let $=Q.storage??ZX(),Z=Q.fetcher??fetch,W=Q.now??(()=>Date.now()),z=X.endpoint.replace(/\/+$/,""),j="mh_drop_guest",J=$.get("mh_drop_guest");if(!J||!QX.test(J))J=XX(),$.set("mh_drop_guest",J);let V="mh_drop_clock:"+z,B=Number($.get(V)??"0")||0,_="mh_drop_hlc:"+J,C=/^(\d+):(\d+)$/.exec($.get(_)??""),O=C?{millis:Number(C[1]),counter:Number(C[2])}:{millis:0,counter:0};function T(){let G=W()+B,H=Math.max(O.millis,G),A=H===O.millis?O.counter+1:0;return O={millis:H,counter:A},$.set(_,`${H}:${A}`),`${String(H).padStart(15,"0")}-${A.toString(16).padStart(4,"0")}-${J}`}let o="mh_drop_pending:"+X.drop_id;function y(){try{let G=$.get(o),H=G?JSON.parse(G):[];return Array.isArray(H)?H:[]}catch{return[]}}function K(G){$.set(o,JSON.stringify(G))}function R(G){let H=X.databases??[],A=H.find((N)=>N.id===G)??H.find((N)=>N.name.toLowerCase()===G.toLowerCase());if(!A)throw new U("not_found",`"${G}" is not a submittable table on this page`);return A}function v(G,H){let A=G.properties.find((N)=>N.id===H)??G.properties.find((N)=>N.name.toLowerCase()===H.toLowerCase());if(!A)throw new U("not_found",`unknown column: ${H}`);return A}let u=null;function F(){return u??=(async()=>{if(!Q.password||!X.password_salt)return null;return NQ(Q.password,X.password_salt)})(),u}async function Y(G,H,A={}){let N=R(G),P="rec_"+g(10),x={},M={},I={};for(let[f,c]of Object.entries(H)){let p=v(N,f);x[p.id]=c,M[p.name]=c,I[p.id]=c??null}let QQ=(X.payload_versions??[1]).includes(2),b;if(QQ){let f={intentId:"int_"+g(16),action:"createRecord",table:N.id,recordId:P,payload:I,submittedAt:W()+B};b={v:2,guest_node:J,intents:[f]}}else{let f=[],c=(jQ,a,FX)=>{f.push({hlc:FX,node_id:J,dataset:"records",row_id:P,col:jQ,value:a===void 0||a===null?null:JSON.stringify(a)})},p=T();c("database_id",N.id,p),c("created_hlc",p,T());for(let[jQ,a]of Object.entries(I))c(jQ,a,T());b={v:1,guest_node:J,changes:f}}let l=await $X({dropId:X.drop_id,keyId:X.key_id,pk:ZQ(X.pk),payload:b,now:W()}),w={"content-type":"application/json"},XQ=await F();if(XQ)w["x-drop-pass"]=XQ;if(A.turnstileToken)w["x-turnstile-token"]=A.turnstileToken;let h;try{h=await Z(`${z}/v1/inbox/${encodeURIComponent(X.drop_id)}/envelopes`,{method:"POST",headers:w,body:JSON.stringify(l)})}catch(f){throw new U("network",`drop submission failed: ${f.message}`)}let s=await h.json().catch(()=>null);if(!h.ok)throw new U(sX(h.status),s?.error??`drop submission failed (HTTP ${h.status})`);if(typeof s?.server_time==="number")B=s.server_time-W(),$.set(V,String(B));let DQ={id:P,database_id:N.id,values:M,cells:x,_pending:!0,envelope_id:l.envelope_id,created_at:W()};return K([...y(),DQ]),DQ}function q(G){let H=y();if(!G)return H;let A=R(G).id;return H.filter((N)=>N.database_id===A)}function D(G,H){let A=new Set(G.map((I)=>I.id)),N=y(),P=N.filter((I)=>!A.has(I.id));if(P.length!==N.length)K(P);let x=H?R(H).id:null,M=P.filter((I)=>x===null||I.database_id===x);return[...G,...M]}return{config:X,guest:J,createRecord:Y,pending:q,merge:D}}class k extends Error{code;status;constructor(X,Q,$){super(X);this.code=Q;this.status=$;this.name="MetahubError"}}var WX="mh_token",zX="/auth/token",tX=5000;function rX(X){let Q=X??(typeof location<"u"&&location?location.pathname:""),$=/^\/(sites|share|r)\/[^/]+/.exec(Q);return $?$[0]:""}function JX(X){let Q=X;if(/^https?:\/\//i.test(X))try{Q=new URL(X).pathname.replace(/\/+$/,"")}catch{return!1}return/^\/(sites|share|r)\/[^/]+$/.test(Q)}function dX(X){if(!X||typeof X!=="object"||Array.isArray(X))return!1;let Q=X;return typeof Q.id==="string"&&Q.id.length>0&&typeof Q.name==="string"&&Q.name.length>0&&Array.isArray(Q.properties)&&Q.properties.every(($)=>{if(!$||typeof $!=="object"||Array.isArray($))return!1;let Z=$;return typeof Z.id==="string"&&Z.id.length>0&&typeof Z.name==="string"&&Z.name.length>0&&typeof Z.type==="string"&&Z.type.length>0})}function eX(X){if(!X||typeof X!=="object"||Array.isArray(X))throw new k("malformed mh-manifest.json","invalid_input",500);let Q=X;if(Q.v!==1||Q.mode!=="live"&&Q.mode!=="static-async"||!Number.isInteger(Q.policyRevision)||Q.policyRevision<0||Q.runtimeEndpoint!==void 0&&typeof Q.runtimeEndpoint!=="string"||Q.websocketEndpoint!==void 0&&typeof Q.websocketEndpoint!=="string"||Q.inboxEndpoint!==void 0&&typeof Q.inboxEndpoint!=="string"||Q.fallback!==void 0&&Q.fallback!=="inbox")throw new k("malformed mh-manifest.json","invalid_input",500);if(Q.drop!==void 0){let $=Q.drop;if(!$||typeof $!=="object"||typeof $.drop_id!=="string"||!$.drop_id||typeof $.key_id!=="string"||!$.key_id||typeof $.pk!=="string"||!$.pk||$.payload_versions!==void 0&&(!Array.isArray($.payload_versions)||!$.payload_versions.every((Z)=>Number.isInteger(Z)&&Z>0))||$.databases!==void 0&&(!Array.isArray($.databases)||!$.databases.every(dX))||$.password_salt!==void 0&&(typeof $.password_salt!=="string"||!$.password_salt)||$.turnstile_sitekey!==void 0&&(typeof $.turnstile_sitekey!=="string"||!$.turnstile_sitekey))throw new k("malformed mh-manifest.json drop config","invalid_input",500)}if((Q.mode==="static-async"||Q.fallback==="inbox")&&(!Q.inboxEndpoint||!Q.drop))throw new k("inbox deployment is missing endpoint or drop config","invalid_input",500);return Q}function Q1(X,Q){if(!X)return Q;if(/^https?:\/\//i.test(X))return X.replace(/\/+$/,"");if(/^https?:\/\//i.test(Q))return new URL(X,Q.endsWith("/")?Q:Q+"/").toString().replace(/\/+$/,"");if(X.startsWith("/"))return X.replace(/\/+$/,"");return`${Q}/${X}`.replace(/\/+/g,"/").replace(/\/+$/,"")}function X1(X={}){let Q=(X.baseUrl??rX()).replace(/\/$/,""),$=JX(Q),Z=X.manifestUrl!==void 0||X.baseUrl===void 0||$,W=X.manifestUrl??`${Q}/mh-manifest.json`,z=/^https?:\/\//i.test(Q)?new URL(zX,Q).toString():zX,j=()=>{if(X.token)return X.token;try{return typeof localStorage<"u"?localStorage.getItem(WX):null}catch{return null}},J=(F)=>{try{localStorage.setItem(WX,F)}catch{}};async function V(F,Y,q,D,G={}){let H=(x)=>{let M={...G};if(D!==void 0)M["content-type"]="application/json";if(x)M.authorization=`Bearer ${x}`;return fetch(F+q,{method:Y,headers:M,body:D!==void 0?JSON.stringify(D):void 0})},A=j(),N=await H(A);if(N.status===401&&A&&!X.token){let x=await fetch(z,{headers:{authorization:`Bearer ${A}`}}).catch(()=>null),M=x?.ok?await x.json():null;if(M?.token)J(M.token),A=M.token,N=await H(A)}let P=await N.json().catch(()=>null);if(!N.ok||P&&P.error)throw new k(P?.error??`${N.status} ${N.statusText}`,P?.code,N.status);return P}let B=null,_=()=>{if(!Z)return Promise.resolve(null);if(B)return B;let F=(async()=>{let Y;try{Y=await fetch(W,{signal:typeof AbortSignal<"u"&&typeof AbortSignal.timeout==="function"?AbortSignal.timeout(tX):void 0})}catch(q){throw new k(`deployment manifest unavailable: ${q.message}`,"network",0)}if(Y.status===404)return null;if(!Y.ok)throw new k(`deployment manifest failed (HTTP ${Y.status})`,"network",Y.status);return eX(await Y.json().catch(()=>null))})();return B=F,F.catch(()=>{if(B===F)B=null}),F},C=(F)=>{if(F?.mode==="static-async")throw new k("static-async deployment has no live runtime","invalid_input",400);return Q1(F?.runtimeEndpoint,Q)},O=async(F,Y,q,D)=>{let G=await _();return V(C(G),F,Y,q,D)},T=(F)=>encodeURIComponent(F),o=()=>"int_"+Math.random().toString(36).slice(2,10)+Date.now().toString(36),y=null,K=(F)=>{return y??=(F?.drop&&F.inboxEndpoint?Promise.resolve(FQ({...F.drop,v:1,endpoint:F.inboxEndpoint},{password:X.dropPassword})):KQ(`${Q}/mh-drop.json`,{password:X.dropPassword})).catch(()=>null),y},R=null,v=async(F,Y)=>{let q={};if(Y.turnstileToken)q["x-turnstile-token"]=Y.turnstileToken;let D=F?.drop?.password_salt;if(X.dropPassword&&D)R??=NQ(X.dropPassword,D),q["x-drop-pass"]=await R;return q},u=async(F,Y,q,D,G)=>{let H=C(F),A=JX(H),N=A?{$intent:{id:o(),submittedAt:Date.now()},values:D}:D,P=await v(F,G);try{return await V(H,Y,q,N,P)}catch(x){if(F===null&&A&&x instanceof k&&(x.status===400||x.status===404))return V(H,Y,q,D,P);throw x}};return{listDatabases:()=>O("GET","/api/databases"),createDatabase:(F)=>O("POST","/api/databases",F),listProperties:(F)=>O("GET",`/api/properties?db=${T(F)}`),listRecords:(F,Y={})=>{let q=new URLSearchParams({db:F});if(Y.sort)q.set("sort",Y.sort);if(Y.limit!=null)q.set("limit",String(Y.limit));return O("GET",`/api/records?${q}`)},getRecord:(F)=>O("GET",`/api/record?id=${T(F)}`),createRecord:async(F,Y,q={})=>{let D=await _();if(D?.mode==="static-async"){let G=await K(D);if(!G)throw new k("static-async inbox is unavailable","network",0);return G.createRecord(F,Y,q)}try{return await u(D,"POST",`/api/records?db=${T(F)}`,Y,q)}catch(G){if(!(G instanceof k?G.status===401:!0))throw G;if(D&&D.fallback!=="inbox")throw G;let A=await K(D);if(!A)throw G;return A.createRecord(F,Y,q)}},updateRecord:async(F,Y,q={})=>{let D=await _();if(D?.mode==="static-async")throw new k("static-async deployment does not support updateRecord","invalid_input",400);return u(D,"PATCH",`/api/record?id=${T(F)}`,Y,q)},deleteRecord:async(F)=>{let Y=await _();if(Y?.mode==="static-async")throw new k("static-async deployment does not support deleteRecord","invalid_input",400);return V(C(Y),"DELETE",`/api/record?id=${T(F)}`)},listDocuments:(F)=>O("GET",F?`/api/documents?db=${T(F)}`:"/api/documents"),getDocument:(F)=>O("GET",`/api/document?id=${T(F)}`),createDocument:(F)=>O("POST","/api/documents",F),updateDocument:(F,Y)=>O("PATCH",`/api/document?id=${T(F)}`,Y),deleteDocument:(F)=>O("DELETE",`/api/document?id=${T(F)}`),search:(F,Y)=>{let q=new URLSearchParams({q:F});if(Y!=null)q.set("limit",String(Y));return O("GET",`/api/search?${q}`)},onUpdate(F,Y={}){let q=!1,D=null,G=null,H=null,A=/(^|\/)r\/[^/]+$/.test(Q)?Q:null;if(A&&typeof WebSocket<"u"){let N=/^https?:\/\//i.test(A)?new URL(A+"/ws"):new URL(A+"/ws",typeof location<"u"?location.href:"http://localhost"),P=N.toString();N.protocol=N.protocol==="https:"?"wss:":"ws:";let x=0,M=new Set([4401,4403]),I=()=>{q=!0,F({gone:!0})},QQ=()=>{if(q)return;let b=!1;D=new WebSocket(N.toString()),D.onopen=()=>{b=!0,H=setTimeout(()=>{x=0},5000)},D.onmessage=(l)=>{try{let w=JSON.parse(String(l.data));if(w?.type==="poke")F({seq:w.seq})}catch{}},D.onerror=()=>{},D.onclose=(l)=>{if(H!=null)clearTimeout(H),H=null;if(q)return;if(M.has(l.code)){I();return}let w=Math.min(30000,1000*2**x++),XQ=w*0.25*Math.random(),h=()=>{G=setTimeout(QQ,w+XQ)};if(!b&&x>=3)fetch(P).then((s)=>{if(q)return;if(s.status===404)I();else h()}).catch(()=>{if(!q)h()});else h()}};QQ()}else if(Y.pollMs&&Y.pollMs>0)G=setInterval(()=>F({}),Y.pollMs);return()=>{if(q=!0,G!=null)clearTimeout(G),clearInterval(G);if(H!=null)clearTimeout(H);try{D?.close()}catch{}}}}}var T4=X1();export{KQ as initDrop,rX as detectBase,FQ as createDrop,X1 as createClient,T4 as api,k as MetahubError};
|
|
10
|
+
ORDER BY created_hlc, id`).all(z.database_id);if(!j.length)continue;let J=pQ(Q,z.database_id),F=d(J,null,j.length);j.forEach((Y,D)=>hX(Q,Y.id,F[D],Z))}}),iQ=P(function(Q,X,Z){let W=wX(Z,VQ(X.name,"rec")),z=m(pQ(Q,X.id),null),j=q(Q,"records",W,"database_id",X.id);q(Q,"records",W,"created_hlc",j.hlc),q(Q,"records",W,"order_key",z);for(let{prop:J,value:F}of Z)q(Q,"records",W,J.id,F);return e(Q,W)}),oQ=P(function(Q,X,Z){let W=g(Q,X);if(!W)throw new U("not_found",`no such database: ${X}`);return iQ(Q,W,lQ(Q,W.id,Z))});function e($,Q){let X=$.query("SELECT id, database_id, data FROM records WHERE id = ? AND __deleted = 0").get(Q);if(!X)return null;return bQ(X,l($,X.database_id))}function nQ($){return $.replace(/'/g,"''")}function sQ($,Q,X={}){let Z=l($,Q),W=X.filter&&Object.keys(X.filter).length?AQ(Z,X.filter).map(({prop:B,value:R})=>({prop:B,value:LQ($,B,R)})):[],z=W.filter((B)=>uQ(B.value)),j=W.filter((B)=>!uQ(B.value)),J,F=!1;if(X.sort){let B=X.sort;if(B.startsWith("-"))F=!0,B=B.slice(1);if(B!=="created"&&B!=="created_hlc"){let R=Z.find((w)=>w.id===B);if(!R){let w=Z.filter((u)=>u.name.toLowerCase()===B.toLowerCase());if(w.length>1)throw new U("ambiguous",`sort field "${B}" matches ${w.length} properties; use a property id`);R=w[0]}if(!R)throw new U("not_found",`unknown sort field: ${B}`);J=R}}for(let B of z)GQ($,Q,B.prop);if(J)GQ($,Q,J);let Y=["database_id = ?","__deleted = 0"],D=[Q];for(let B of z)Y.push(`data ->> '${nQ(B.prop.id)}' = ?`),D.push(yX(B.value));let _=X.sort==null,C=J?`data ->> '${nQ(J.id)}'`:"created_hlc",T=`SELECT id, database_id, data FROM records WHERE ${Y.join(" AND ")} `+(_?"ORDER BY order_key IS NULL, order_key, id":`ORDER BY ${C} ${F?"DESC":"ASC"}, id`);if(X.limit!=null&&j.length===0)T+=" LIMIT ?",D.push(X.limit);let I=$.query(T).all(...D).map((B)=>bQ(B,Z));if(j.length){if(I=I.filter((B)=>j.every((R)=>JSON.stringify(B.cells[R.prop.id]??null)===JSON.stringify(R.value))),X.limit!=null)I=I.slice(0,X.limit)}return I}var o1=P(function(Q,X,Z,W){if(W!=="before"&&W!=="after")throw new U("invalid_input",`unknown move position: ${W}`);let z=Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get(X);if(!z)throw new U("not_found",`no such record: ${X}`);let j=Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get(Z);if(!j)throw new U("not_found",`no such record: ${Z}`);if(z.database_id!==j.database_id)throw new U("invalid_input","cannot move a record across databases");if(X===Z)return e(Q,X);fX(Q,z.database_id);let J=qQ(Q,z.database_id).filter((_)=>_.id!==X),F=J.findIndex((_)=>_.id===Z);if(F<0)throw new U("not_found",`no such target record: ${Z}`);let Y=W==="before"?J[F-1]?.order_key??null:J[F].order_key,D=W==="before"?J[F].order_key:J[F+1]?.order_key??null;if(Y!==null&&D!==null&&Y>=D)mX(Q,z.database_id),J=qQ(Q,z.database_id).filter((_)=>_.id!==X),F=J.findIndex((_)=>_.id===Z),Y=W==="before"?J[F-1]?.order_key??null:J[F].order_key,D=W==="before"?J[F].order_key:J[F+1]?.order_key??null;return q(Q,"records",X,"order_key",m(Y,D)),e(Q,X)}),aQ=P(function(Q,X,Z){if(!Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get(X))throw new U("not_found",`no such record: ${X}`);for(let{prop:z,value:j}of Z)q(Q,"records",X,z.id,j);return e(Q,X)}),s1=P(function(Q,X,Z){let W=Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get(X);if(!W)throw new U("not_found",`no such record: ${X}`);return aQ(Q,X,lQ(Q,W.database_id,Z))}),a1=P(function(Q,X){if(!Q.query("SELECT id FROM records WHERE id = ? AND __deleted = 0").get(X))return!1;return q(Q,"records",X,"__deleted",1),!0});var uX=["id","name","icon","meta","created_hlc"];var cX=uX.join(", ");function nX($){if(!$)return null;return{...$,meta:$.meta===null?null:JSON.parse($.meta)}}var lX=P(function(Q,X){let Z=o("db",X.name),W=q(Q,"databases",Z,"name",X.name);if(q(Q,"databases",Z,"created_hlc",W.hlc),X.icon!==void 0)q(Q,"databases",Z,"icon",X.icon);return g(Q,Z)}),$4=P(function(Q,X,Z){if(!g(Q,X))throw new U("not_found",`no such database: ${X}`);if(Z.name!==void 0)q(Q,"databases",X,"name",Z.name);if(Z.icon!==void 0)q(Q,"databases",X,"icon",Z.icon);if(Z.meta!==void 0){if(Z.meta!==null&&(typeof Z.meta!=="object"||Array.isArray(Z.meta)))throw new U("invalid_input","meta must be a JSON object or null");q(Q,"databases",X,"meta",Z.meta)}return g(Q,X)}),Z4=P(function(Q,X,Z={}){let W=g(Q,X);if(!W)throw new U("not_found",`no such database: ${X}`);let z=lX(Q,{name:Z.name??W.name,icon:Z.icon??W.icon??void 0});if(W.meta!==null){let{collapsed:J,...F}=W.meta;if(Object.keys(F).length)q(Q,"databases",z.id,"meta",F)}let j=new Map;for(let J of l(Q,X)){let F=J.config?.database===X?{...J.config,database:z.id}:J.config??void 0,Y=vQ(Q,z.id,{name:J.name,type:J.type,config:F,position:J.position});j.set(J.id,Y.id)}for(let J of sQ(Q,X)){let F={};for(let[Y,D]of Object.entries(J.cells)){let _=j.get(Y);if(_)F[_]=D}oQ(Q,z.id,F)}return g(Q,z.id)});function g($,Q){return nX($.query(`SELECT ${cX} FROM databases WHERE id = ? AND __deleted = 0`).get(Q))}var W4=P(function(Q,X){if(!g(Q,X))return!1;q(Q,"databases",X,"__deleted",1);let Z=(W)=>{for(let z of tQ(Q,W,"database_id",X))q(Q,W,z,"__deleted",1)};Z("properties"),Z("records");for(let W of tQ(Q,"documents","database_id",X))q(Q,"documents",W,"database_id",null);return Q.query("DELETE FROM meta WHERE key = 'current_db' AND value = ?").run(X),!0});function tQ($,Q,X,Z){return $.query(`SELECT id FROM ${Q} WHERE ${X} = ? AND __deleted = 0`).all(Z).map((W)=>W.id)}var dQ="sealed-p256";var bX=12,pX="mh-drop-seal-v1",rQ={name:"ECDH",namedCurve:"P-256"};function QQ($){let Q=new Uint8Array($.byteLength);return Q.set($),Q.buffer}function eQ(...$){let Q=$.reduce((W,z)=>W+z.byteLength,0),X=new Uint8Array(Q),Z=0;for(let W of $)X.set(W,Z),Z+=W.byteLength;return X}async function iX($,Q,X){let Z=new Uint8Array(await crypto.subtle.digest("SHA-256",QQ(X))),W=eQ(new TextEncoder().encode(pX),Q,Z),z=await crypto.subtle.importKey("raw",$,"HKDF",!1,["deriveKey"]);return crypto.subtle.deriveKey({name:"HKDF",hash:"SHA-256",salt:new Uint8Array(16).buffer,info:QQ(W)},z,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}async function QX($,Q){let X=await crypto.subtle.importKey("raw",QQ($),rQ,!1,[]),Z=await crypto.subtle.generateKey(rQ,!0,["deriveBits"]),W=new Uint8Array(await crypto.subtle.exportKey("raw",Z.publicKey)),z=await crypto.subtle.deriveBits({name:"ECDH",public:X},Z.privateKey,256),j=await iX(z,W,$),J=crypto.getRandomValues(new Uint8Array(bX)),F=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:QQ(J)},j,QQ(Q)));return eQ(W,J,F)}var XX=/^g[0-9a-z]{8}$/;function oX(){return"e"+E(16)}function $X(){return"g"+E(8)}function sX($){return new TextEncoder().encode(JSON.stringify($))}async function ZX($){let Q=await QX($.pk,sX($.payload));return{v:1,envelope_id:oX(),drop_id:$.dropId,enc:dQ,key_id:$.keyId,sealed:ZQ(Q),created_at:$.now??Date.now()}}async function NQ($,Q){return ZQ(await OQ($,WQ(Q)))}function WX(){try{if(typeof localStorage<"u"&&localStorage)return localStorage.getItem("mh_drop_probe"),{get:(Q)=>localStorage.getItem(Q),set:(Q,X)=>localStorage.setItem(Q,X)}}catch{}let $=new Map;return{get:(Q)=>$.get(Q)??null,set:(Q,X)=>$.set(Q,X)}}function aX($){if($===401)return"auth";if($===404)return"not_found";if($===429)return"rate_limited";if($===400||$===413)return"invalid_input";return"network"}async function KQ($="mh-drop.json",Q={}){let Z=await(Q.fetcher??fetch)($);if(!Z.ok)throw new U("not_found",`no drop config at ${$}`);let W=await Z.json().catch(()=>null);if(!W||W.v!==1||!W.endpoint||!W.drop_id||!W.key_id||!W.pk)throw new U("invalid_input","malformed mh-drop.json");return tX(W,Z.headers.get("date"),Q),FQ(W,Q)}function tX($,Q,X){if(!Q)return;let Z=Date.parse(Q);if(!Number.isFinite(Z))return;let W=X.storage??WX(),z="mh_drop_clock:"+$.endpoint.replace(/\/+$/,"");if(W.get(z))return;let j=X.now??(()=>Date.now());W.set(z,String(Z-j()))}function FQ($,Q={}){let X=Q.storage??WX(),Z=Q.fetcher??fetch,W=Q.now??(()=>Date.now()),z=$.endpoint.replace(/\/+$/,""),j="mh_drop_guest",J=X.get("mh_drop_guest");if(!J||!XX.test(J))J=$X(),X.set("mh_drop_guest",J);let F="mh_drop_clock:"+z,Y=Number(X.get(F)??"0")||0,D="mh_drop_hlc:"+J,_=/^(\d+):(\d+)$/.exec(X.get(D)??""),C=_?{millis:Number(_[1]),counter:Number(_[2])}:{millis:0,counter:0};function T(){let G=W()+Y,L=Math.max(C.millis,G),N=L===C.millis?C.counter+1:0;return C={millis:L,counter:N},X.set(D,`${L}:${N}`),`${String(L).padStart(15,"0")}-${N.toString(16).padStart(4,"0")}-${J}`}let s="mh_drop_pending:"+$.drop_id;function I(){try{let G=X.get(s),L=G?JSON.parse(G):[];return Array.isArray(L)?L:[]}catch{return[]}}function B(G){X.set(s,JSON.stringify(G))}function R(G){let L=$.databases??[],N=L.find((K)=>K.id===G)??L.find((K)=>K.name.toLowerCase()===G.toLowerCase());if(!N)throw new U("not_found",`"${G}" is not a submittable table on this page`);return N}function w(G,L){let N=G.properties.find((K)=>K.id===L)??G.properties.find((K)=>K.name.toLowerCase()===L.toLowerCase());if(!N)throw new U("not_found",`unknown column: ${L}`);return N}let u=null;function V(){return u??=(async()=>{if(!Q.password||!$.password_salt)return null;return NQ(Q.password,$.password_salt)})(),u}async function H(G,L,N={}){let K=R(G),S="rec_"+E(10),x={},M={},y={};for(let[f,c]of Object.entries(L)){let i=w(K,f);x[i.id]=c,M[i.name]=c,y[i.id]=c??null}let XQ=($.payload_versions??[1]).includes(2),b;if(XQ){let f={intentId:"int_"+E(16),action:"createRecord",table:K.id,recordId:S,payload:y,submittedAt:W()+Y};b={v:2,guest_node:J,intents:[f]}}else{let f=[],c=(jQ,t,jX)=>{f.push({hlc:jX,node_id:J,dataset:"records",row_id:S,col:jQ,value:t===void 0||t===null?null:JSON.stringify(t)})},i=T();c("database_id",K.id,i),c("created_hlc",i,T());for(let[jQ,t]of Object.entries(y))c(jQ,t,T());b={v:1,guest_node:J,changes:f}}let p=await ZX({dropId:$.drop_id,keyId:$.key_id,pk:WQ($.pk),payload:b,now:W()}),v={"content-type":"application/json"},$Q=await V();if($Q)v["x-drop-pass"]=$Q;if(N.turnstileToken)v["x-turnstile-token"]=N.turnstileToken;let h;try{h=await Z(`${z}/v1/inbox/${encodeURIComponent($.drop_id)}/envelopes`,{method:"POST",headers:v,body:JSON.stringify(p)})}catch(f){throw new U("network",`drop submission failed: ${f.message}`)}let a=await h.json().catch(()=>null);if(!h.ok)throw new U(aX(h.status),a?.error??`drop submission failed (HTTP ${h.status})`);if(typeof a?.server_time==="number")Y=a.server_time-W(),X.set(F,String(Y));let DQ={id:S,database_id:K.id,values:M,cells:x,_pending:!0,envelope_id:p.envelope_id,created_at:W()};return B([...I(),DQ]),DQ}function A(G){let L=I();if(!G)return L;let N=R(G).id;return L.filter((K)=>K.database_id===N)}function O(G,L){let N=new Set(G.map((y)=>y.id)),K=I(),S=K.filter((y)=>!N.has(y.id));if(S.length!==K.length)B(S);let x=L?R(L).id:null,M=S.filter((y)=>x===null||y.database_id===x);return[...G,...M]}return{config:$,guest:J,createRecord:H,pending:A,merge:O}}class k extends Error{code;status;constructor($,Q,X){super($);this.code=Q;this.status=X;this.name="MetahubError"}}var zX="mh_token",JX="/auth/token",rX=5000;function dX($){let Q=$??(typeof location<"u"&&location?location.pathname:""),X=/^\/(sites|share|r)\/[^/]+/.exec(Q);return X?X[0]:""}function FX($){let Q=$;if(/^https?:\/\//i.test($))try{Q=new URL($).pathname.replace(/\/+$/,"")}catch{return!1}return/^\/(sites|share|r)\/[^/]+$/.test(Q)}function eX($){if(!$||typeof $!=="object"||Array.isArray($))return!1;let Q=$;return typeof Q.id==="string"&&Q.id.length>0&&typeof Q.name==="string"&&Q.name.length>0&&Array.isArray(Q.properties)&&Q.properties.every((X)=>{if(!X||typeof X!=="object"||Array.isArray(X))return!1;let Z=X;return typeof Z.id==="string"&&Z.id.length>0&&typeof Z.name==="string"&&Z.name.length>0&&typeof Z.type==="string"&&Z.type.length>0})}function Q1($){if(!$||typeof $!=="object"||Array.isArray($))throw new k("malformed mh-manifest.json","invalid_input",500);let Q=$;if(Q.v!==1||Q.mode!=="live"&&Q.mode!=="static-async"||!Number.isInteger(Q.policyRevision)||Q.policyRevision<0||Q.runtimeEndpoint!==void 0&&typeof Q.runtimeEndpoint!=="string"||Q.websocketEndpoint!==void 0&&typeof Q.websocketEndpoint!=="string"||Q.inboxEndpoint!==void 0&&typeof Q.inboxEndpoint!=="string"||Q.fallback!==void 0&&Q.fallback!=="inbox")throw new k("malformed mh-manifest.json","invalid_input",500);if(Q.drop!==void 0){let X=Q.drop;if(!X||typeof X!=="object"||typeof X.drop_id!=="string"||!X.drop_id||typeof X.key_id!=="string"||!X.key_id||typeof X.pk!=="string"||!X.pk||X.payload_versions!==void 0&&(!Array.isArray(X.payload_versions)||!X.payload_versions.every((Z)=>Number.isInteger(Z)&&Z>0))||X.databases!==void 0&&(!Array.isArray(X.databases)||!X.databases.every(eX))||X.password_salt!==void 0&&(typeof X.password_salt!=="string"||!X.password_salt)||X.turnstile_sitekey!==void 0&&(typeof X.turnstile_sitekey!=="string"||!X.turnstile_sitekey))throw new k("malformed mh-manifest.json drop config","invalid_input",500)}if((Q.mode==="static-async"||Q.fallback==="inbox")&&(!Q.inboxEndpoint||!Q.drop))throw new k("inbox deployment is missing endpoint or drop config","invalid_input",500);return Q}function X1($,Q){if(!$)return Q;if(/^https?:\/\//i.test($))return $.replace(/\/+$/,"");if(/^https?:\/\//i.test(Q))return new URL($,Q.endsWith("/")?Q:Q+"/").toString().replace(/\/+$/,"");if($.startsWith("/"))return $.replace(/\/+$/,"");return`${Q}/${$}`.replace(/\/+/g,"/").replace(/\/+$/,"")}function $1($={}){let Q=($.baseUrl??dX()).replace(/\/$/,""),X=FX(Q),Z=$.manifestUrl!==void 0||$.baseUrl===void 0||X,W=$.manifestUrl??`${Q}/mh-manifest.json`,z=/^https?:\/\//i.test(Q)?new URL(JX,Q).toString():JX,j=()=>{if($.token)return $.token;try{return typeof localStorage<"u"?localStorage.getItem(zX):null}catch{return null}},J=(V)=>{try{localStorage.setItem(zX,V)}catch{}};async function F(V,H,A,O,G={}){let L=(x)=>{let M={...G};if(O!==void 0)M["content-type"]="application/json";if(x)M.authorization=`Bearer ${x}`;return fetch(V+A,{method:H,headers:M,body:O!==void 0?JSON.stringify(O):void 0})},N=j(),K=await L(N);if(K.status===401&&N&&!$.token){let x=await fetch(z,{headers:{authorization:`Bearer ${N}`}}).catch(()=>null),M=x?.ok?await x.json():null;if(M?.token)J(M.token),N=M.token,K=await L(N)}let S=await K.json().catch(()=>null);if(!K.ok||S&&S.error)throw new k(S?.error??`${K.status} ${K.statusText}`,S?.code,K.status);return S}let Y=null,D=()=>{if(!Z)return Promise.resolve(null);if(Y)return Y;let V=(async()=>{let H;try{H=await fetch(W,{signal:typeof AbortSignal<"u"&&typeof AbortSignal.timeout==="function"?AbortSignal.timeout(rX):void 0})}catch(A){throw new k(`deployment manifest unavailable: ${A.message}`,"network",0)}if(H.status===404)return null;if(!H.ok)throw new k(`deployment manifest failed (HTTP ${H.status})`,"network",H.status);return Q1(await H.json().catch(()=>null))})();return Y=V,V.catch(()=>{if(Y===V)Y=null}),V},_=(V)=>{if(V?.mode==="static-async")throw new k("static-async deployment has no live runtime","invalid_input",400);return X1(V?.runtimeEndpoint,Q)},C=async(V,H,A,O)=>{let G=await D();return F(_(G),V,H,A,O)},T=(V)=>encodeURIComponent(V),s=()=>"int_"+Math.random().toString(36).slice(2,10)+Date.now().toString(36),I=null,B=(V)=>{return I??=(V?.drop&&V.inboxEndpoint?Promise.resolve(FQ({...V.drop,v:1,endpoint:V.inboxEndpoint},{password:$.dropPassword})):KQ(`${Q}/mh-drop.json`,{password:$.dropPassword})).catch(()=>null),I},R=null,w=async(V,H)=>{let A={};if(H.turnstileToken)A["x-turnstile-token"]=H.turnstileToken;let O=V?.drop?.password_salt;if($.dropPassword&&O)R??=NQ($.dropPassword,O),A["x-drop-pass"]=await R;return A},u=async(V,H,A,O,G)=>{let L=_(V),N=FX(L),K=N?{$intent:{id:s(),submittedAt:Date.now()},values:O}:O,S=await w(V,G);try{return await F(L,H,A,K,S)}catch(x){if(V===null&&N&&x instanceof k&&(x.status===400||x.status===404))return F(L,H,A,O,S);throw x}};return{listDatabases:()=>C("GET","/api/databases"),createDatabase:(V)=>C("POST","/api/databases",V),listProperties:(V)=>C("GET",`/api/properties?db=${T(V)}`),listRecords:(V,H={})=>{let A=new URLSearchParams({db:V});if(H.sort)A.set("sort",H.sort);if(H.limit!=null)A.set("limit",String(H.limit));return C("GET",`/api/records?${A}`)},getRecord:(V)=>C("GET",`/api/record?id=${T(V)}`),createRecord:async(V,H,A={})=>{let O=await D();if(O?.mode==="static-async"){let G=await B(O);if(!G)throw new k("static-async inbox is unavailable","network",0);return G.createRecord(V,H,A)}try{return await u(O,"POST",`/api/records?db=${T(V)}`,H,A)}catch(G){if(!(G instanceof k?G.status===401:!0))throw G;if(O&&O.fallback!=="inbox")throw G;let N=await B(O);if(!N)throw G;return N.createRecord(V,H,A)}},updateRecord:async(V,H,A={})=>{let O=await D();if(O?.mode==="static-async")throw new k("static-async deployment does not support updateRecord","invalid_input",400);return u(O,"PATCH",`/api/record?id=${T(V)}`,H,A)},deleteRecord:async(V)=>{let H=await D();if(H?.mode==="static-async")throw new k("static-async deployment does not support deleteRecord","invalid_input",400);return F(_(H),"DELETE",`/api/record?id=${T(V)}`)},listDocuments:(V)=>C("GET",V?`/api/documents?db=${T(V)}`:"/api/documents"),getDocument:(V)=>C("GET",`/api/document?id=${T(V)}`),createDocument:(V)=>C("POST","/api/documents",V),updateDocument:(V,H)=>C("PATCH",`/api/document?id=${T(V)}`,H),deleteDocument:(V)=>C("DELETE",`/api/document?id=${T(V)}`),search:(V,H)=>{let A=new URLSearchParams({q:V});if(H!=null)A.set("limit",String(H));return C("GET",`/api/search?${A}`)},onUpdate(V,H={}){let A=!1,O=null,G=null,L=null,N=/(^|\/)r\/[^/]+$/.test(Q)?Q:null;if(N&&typeof WebSocket<"u"){let K=/^https?:\/\//i.test(N)?new URL(N+"/ws"):new URL(N+"/ws",typeof location<"u"?location.href:"http://localhost"),S=K.toString();K.protocol=K.protocol==="https:"?"wss:":"ws:";let x=0,M=new Set([4401,4403]),y=()=>{A=!0,V({gone:!0})},XQ=()=>{if(A)return;let b=!1;O=new WebSocket(K.toString()),O.onopen=()=>{b=!0,L=setTimeout(()=>{x=0},5000)},O.onmessage=(p)=>{try{let v=JSON.parse(String(p.data));if(v?.type==="poke")V({seq:v.seq})}catch{}},O.onerror=()=>{},O.onclose=(p)=>{if(L!=null)clearTimeout(L),L=null;if(A)return;if(M.has(p.code)){y();return}let v=Math.min(30000,1000*2**x++),$Q=v*0.25*Math.random(),h=()=>{G=setTimeout(XQ,v+$Q)};if(!b&&x>=3)fetch(S).then((a)=>{if(A)return;if(a.status===404)y();else h()}).catch(()=>{if(!A)h()});else h()}};XQ()}else if(H.pollMs&&H.pollMs>0)G=setInterval(()=>V({}),H.pollMs);return()=>{if(A=!0,G!=null)clearTimeout(G),clearInterval(G);if(L!=null)clearTimeout(L);try{O?.close()}catch{}}}}}var k4=$1();export{KQ as initDrop,dX as detectBase,FQ as createDrop,$1 as createClient,k4 as api,k as MetahubError};
|
package/dist/sw.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
function l(Z,Q,$,X){let V=$.get("id"),Y=$.get("db"),W=X??{},J=(
|
|
1
|
+
function l(Z,Q,$,X){let V=$.get("id"),Y=$.get("db"),W=X??{},J=(z)=>z!=null?Number(z):void 0;switch(`${Z} ${Q}`){case"GET /api/databases":return{op:"listDatabases",args:[]};case"POST /api/databases":return{op:"createDatabase",args:[W]};case"PATCH /api/database":return V?{op:"updateDatabase",args:[V,W]}:null;case"POST /api/database/duplicate":return V?{op:"duplicateDatabase",args:[V,W]}:null;case"DELETE /api/database":return V?{op:"deleteDatabase",args:[V]}:null;case"GET /api/database/activity":return Y?{op:"listDatabaseActivity",args:[Y,J($.get("limit"))]}:null;case"GET /api/properties":return Y?{op:"listProperties",args:[Y]}:null;case"POST /api/properties":{let{db:z,...j}=W;return z?{op:"addProperty",args:[z,j]}:null}case"PATCH /api/property":return V?{op:"updateProperty",args:[V,W]}:null;case"PATCH /api/property/width":return V?{op:"setPropertyWidth",args:[V,W.width]}:null;case"POST /api/property/option/rename":{let{from:z,to:j}=W;return V?{op:"renameSelectOption",args:[V,z,j]}:null}case"POST /api/property/option/remove":return V?{op:"removeSelectOption",args:[V,W.name]}:null;case"DELETE /api/property":return V?{op:"removeProperty",args:[V]}:null;case"GET /api/property/history":return V?{op:"listPropertyRevisions",args:[V]}:null;case"POST /api/property/revert":return V?{op:"revertProperty",args:[V,W.to]}:null;case"GET /api/records":return Y?{op:"listRecords",args:[Y,{sort:$.get("sort")??void 0,limit:J($.get("limit"))}]}:null;case"POST /api/records":return Y?{op:"createRecord",args:[Y,W]}:null;case"GET /api/record":return V?{op:"getRecord",args:[V]}:null;case"PATCH /api/record":return V?{op:"updateRecord",args:[V,W]}:null;case"PATCH /api/record/order":{let{target:z,where:j}=W;return V&&z?{op:"moveRecord",args:[V,z,j]}:null}case"GET /api/record/history":return V?{op:"listRecordRevisions",args:[V]}:null;case"GET /api/record/at":return V?{op:"recordAtVersion",args:[V,$.get("version")]}:null;case"GET /api/record/field-history":return V?{op:"recordFieldHistory",args:[V,$.get("prop")]}:null;case"POST /api/record/revert":return V?{op:"revertRecord",args:[V,W.to]}:null;case"DELETE /api/record":return V?{op:"deleteRecord",args:[V]}:null;case"GET /api/documents":return{op:"listDocuments",args:[{database_id:$.get("db")??void 0,parent_id:$.get("parent")??void 0}]};case"POST /api/documents":return{op:"createDocument",args:[W]};case"GET /api/document":return V?{op:"getDocument",args:[V]}:null;case"PATCH /api/document":{let{if_match:z,...j}=W;return V?{op:"updateDocument",args:[V,j,z]}:null}case"POST /api/document/duplicate":return V?{op:"duplicateDocument",args:[V,W]}:null;case"PATCH /api/document/move":{let{target:z,where:j}=W;return V&&z?{op:"moveDocument",args:[V,z,j]}:null}case"GET /api/document/history":return V?{op:"listDocumentRevisions",args:[V]}:null;case"GET /api/document/at":return V?{op:"documentAtVersion",args:[V,$.get("version")]}:null;case"POST /api/document/revert":{let{to:z,if_match:j}=W;return V&&z?{op:"revertDocument",args:[V,z,j]}:null}case"DELETE /api/document":return V?{op:"deleteDocument",args:[V]}:null;case"GET /api/nodes":return{op:"nodes",args:[]};case"GET /api/sync/health":return{op:"dataMap",args:[]};case"GET /api/search":{let z=$.get("q");return z?{op:"search",args:[z,J($.get("limit"))]}:null}case"GET /api/sites":return{op:"listSites",args:[]};case"GET /api/site/files":{let z=$.get("site");return z?{op:"listSiteFiles",args:[z]}:null}case"POST /api/sites":return{op:"createSite",args:[W]};case"PATCH /api/site":return V?{op:"updateSite",args:[V,W]}:null;case"DELETE /api/site":return V?{op:"deleteSite",args:[V]}:null;case"GET /api/site/grants":return V?{op:"getSiteGrants",args:[V]}:null;case"PUT /api/site/grants":return V?{op:"setSiteGrants",args:[V,W]}:null;case"GET /api/site-hosting":return{op:"siteHosting",args:[]};case"PATCH /api/site/channel":{let z=W.id;return z?{op:"revokeSiteChannel",args:[z]}:null}case"DELETE /api/site/file":{let z=$.get("site"),j=$.get("path");return z&&j?{op:"deleteSiteFile",args:[z,j]}:null}case"GET /api/shares":return{op:"listLocalShares",args:[$.get("target")??void 0]};case"POST /api/share":return{op:"createLocalShare",args:[W]};case"DELETE /api/share":case"DELETE /api/share/managed":return $.get("slug")?{op:"revokeLocalShare",args:[$.get("slug")]}:null;default:return null}}function eQ(Z,Q){if(Z===null)return"unknown";if(Z.status>=500)return"unknown";if(Z.ok)return Q?.ok===!0?"server":"none";return"none"}async function VQ(){let Z=null,Q=null;try{Z=await fetch("/health",{cache:"no-store"}),Q=Z.ok?await Z.json().catch(()=>null):null}catch{Z=null}return eQ(Z,Q)}var Q1=Math.floor(167772160);function $1(Z){if(Z instanceof ArrayBuffer)return Z;let Q=new Uint8Array(Z.byteLength);return Q.set(Z),Q.buffer}async function Z1(Z){let Q=await crypto.subtle.digest("SHA-256",$1(Z));return[...new Uint8Array(Q)].map(($)=>$.toString(16).padStart(2,"0")).join("")}async function n(Z,Q){return(await Z1(Z)).slice(0,Q.length)===Q}var X1={png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",webp:"image/webp",avif:"image/avif",svg:"image/svg+xml",pdf:"application/pdf"};function YQ(Z){let Q=Z.lastIndexOf("."),$=Q>=0?Z.slice(Q+1).toLowerCase():"";return X1[$]??"application/octet-stream"}var v=null;function V1(){if(v)return v;return v=new Promise((Z,Q)=>{let $=indexedDB.open("mh-blobs",1);$.onupgradeneeded=()=>{let X=$.result;if(!X.objectStoreNames.contains("spool"))X.createObjectStore("spool",{keyPath:"hash"});if(!X.objectStoreNames.contains("meta"))X.createObjectStore("meta",{keyPath:"hash"})},$.onsuccess=()=>Z($.result),$.onerror=()=>Q($.error)}),v}function q(Z,Q,$){return V1().then((X)=>new Promise((V,Y)=>{let W=$(X.transaction(Z,Q).objectStore(Z));W.onsuccess=()=>V(W.result),W.onerror=()=>Y(W.error)}))}var w=(Z)=>`/blob/${Z}`;async function Y1(Z,Q,$){let X=await q("meta","readonly",(Y)=>Y.get(Z)),V={hash:Z,size:Q,accessed:Date.now(),pinned:X?.pinned??0,content_type:$??X?.content_type};await q("meta","readwrite",(Y)=>Y.put(V))}async function W1(Z){let Q=await q("meta","readonly",($)=>$.get(Z));if(!Q)return;Q.accessed=Date.now(),await q("meta","readwrite",($)=>$.put(Q))}function J1(Z){return Z.trim().toLowerCase().startsWith("text/html")}async function WQ(Z){let Q=await caches.open("mh-blob-v1"),$=await Q.match(w(Z));if(!$)return;if(J1($.headers.get("content-type")??"")){await Q.delete(w(Z)),await q("meta","readwrite",(X)=>X.delete(Z)).catch(()=>{});return}return W1(Z),$}async function p(Z,Q,$){await(await caches.open("mh-blob-v1")).put(w(Z),new Response(Q,{headers:{"content-type":$,"cache-control":"public, max-age=31536000, immutable"}})),await Y1(Z,Q.byteLength,$),await U1()}async function U1(){let Z=await q("meta","readonly",(V)=>V.getAll())??[],Q=Z.reduce((V,Y)=>V+Y.size,0);if(Q<=209715200)return;let $=await caches.open("mh-blob-v1"),X=Z.filter((V)=>!V.pinned).sort((V,Y)=>V.accessed-Y.accessed);for(let V of X){if(Q<=Q1)break;await $.delete(w(V.hash)),await q("meta","readwrite",(Y)=>Y.delete(V.hash)),Q-=V.size}}var JQ='<script src="/mh-runtime.js"></script>';function UQ(Z){let Q=Z.toLowerCase().indexOf("<head>");if(Q>=0)return Z.slice(0,Q+6)+JQ+Z.slice(Q+6);return JQ+Z}class F extends Error{code;constructor(Z,Q){super(Q);this.code=Z;this.name="MhError"}}function S(Z=6){let Q=crypto.getRandomValues(new Uint8Array(Z)),$="";for(let X of Q)$+="0123456789abcdefghijklmnopqrstuvwxyz".charAt(X%36);return $}function b(Z,Q="item"){return Z.normalize("NFKD").replace(/[^\x20-\x7E]/g,"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,32).replace(/-+$/g,"")||Q}var z1=new Set(["db","prop","rec","doc","blk","site","sf","chan"]);function _(Z,Q,$=Z){return`${Z}_${b(Q,$)}-${S()}`}function T(Z){let Q=Z.indexOf("_");if(Q<=0)return null;let $=Z.slice(0,Q);return z1.has($)?$:null}function zQ(Z){let Q=Z.query("SELECT value FROM meta WHERE key = 'node_id'").get();if(Q)return Q.value;let $=S(8);return Z.query("INSERT INTO meta (key, value) VALUES ('node_id', ?)").run($),$}function FQ(Z,Q){if(Q<=65535)return{millis:Z,counter:Q};return{millis:Z+Math.floor(Q/65536),counter:Q%65536}}function GQ(Z){let{millis:Q,counter:$}=FQ(Z.millis,Z.counter);return`${String(Q).padStart(15,"0")}-${$.toString(16).padStart(4,"0")}-${Z.node}`}function F1(Z){let Q=Z.indexOf("-"),$=Z.indexOf("-",Q+1);return{millis:Number(Z.slice(0,Q)),counter:parseInt(Z.slice(Q+1,$),16),node:Z.slice($+1)}}function G1(Z,Q){let $=Z.query("SELECT value FROM meta WHERE key = 'hlc'").get();return $?F1($.value):{millis:0,counter:0,node:Q}}function j1(Z,Q){Z.query("INSERT INTO meta (key, value) VALUES ('hlc', ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value").run(GQ(Q))}function jQ(Z,Q,$=Date.now()){let X=G1(Z,Q),V=Math.max(X.millis,$),Y=V===X.millis?X.counter+1:0,W={...FQ(V,Y),node:Q};return j1(Z,W),GQ(W)}function KQ(Z){let Q=Z.filter((X)=>!!X.text&&X.text.length>0),$=[];return Q.forEach((X,V)=>{$.push(...X.text.split(`
|
|
2
2
|
`));let Y=Math.max(0,X.blankAfter??0);if(V<Q.length-1)$.push("");for(let W=0;W<Y;W++)$.push("")}),$.join(`
|
|
3
|
-
`)}var HQ="intent_receipts";var j1=["hlc","node_id","dataset","row_id","col","value","txn"];var q4=j1.join(", "),w=null,K1=null;function NQ(Z,Q){if(w!==null)return Q();w=(Z?Z+":":"")+R(8);try{return Q()}finally{w=null}}function H(Z,Q=null){return(...$)=>NQ(Q,()=>Z(...$))}var H1={databases:{table:"databases",cols:new Set(["name","icon","meta","created_hlc","__deleted"])},properties:{table:"properties",cols:new Set(["database_id","name","type","config","position","__deleted"])},documents:{table:"documents",cols:new Set(["title","body","database_id","parent_id","created_hlc","order_key","__deleted"])},doc_blocks:{table:"doc_blocks",cols:new Set(["doc_id","text","order_key","blank_after","__deleted"])},sites:{table:"sites",cols:new Set(["name","title","created_hlc","visibility","spa","public_grants","__deleted"])},site_channels:{table:"site_channels",cols:new Set(["site_id","audience","hosting","controller_node_id","target_ref","canonical_url","policy_json","desired_state","created_hlc","__deleted"])},site_files:{table:"site_files",cols:new Set(["site_id","path","content_type","encoding","content","created_hlc","__deleted"])},blob_policy:{table:"blob_policy",cols:new Set(["full_nodes","redundancy","__deleted"])}},D1=new Set(["database_id","created_hlc","order_key","__deleted"]),B1=new Set([HQ]),N1=new Set(["records:__deleted","databases:__deleted","properties:__deleted","documents:__deleted","doc_blocks:__deleted","doc_blocks:blank_after","sites:__deleted","sites:spa","site_channels:__deleted","site_files:__deleted","blob_policy:__deleted"]);function DQ(Z,Q,$){if($!==null)return JSON.parse($);return N1.has(`${Z}:${Q}`)?0:null}function BQ(Z){if(Z===null||Z===void 0)return null;if(typeof Z==="boolean")return Z?1:0;if(typeof Z==="number")return Z;if(typeof Z==="string")return Z;return JSON.stringify(Z)}function m(Z,Q,$){Z.query(`INSERT OR IGNORE INTO ${Q} (id) VALUES (?)`).run($)}function A1(Z,Q){return Z.query("SELECT 1 AS x FROM doc_blocks WHERE doc_id = ? LIMIT 1").get(Q)!=null}function L1(Z,Q){let $=Z.query("SELECT text, blank_after FROM doc_blocks WHERE doc_id = ? AND __deleted = 0 ORDER BY order_key, id").all(Q);m(Z,"documents",Q),Z.query("UPDATE documents SET body = ? WHERE id = ?").run(KQ($.map((X)=>({text:X.text,blankAfter:X.blank_after??0}))),Q)}function O1(Z,Q,$,X,V){if(B1.has(Q))return;if(Q==="records"){if(D1.has(X)){m(Z,"records",$);let J=DQ("records",X,V);Z.query(`UPDATE records SET "${X}" = ? WHERE id = ?`).run(BQ(J),$)}else if(m(Z,"records",$),V===null)Z.query(`UPDATE records SET data = json_remove(data, '$."' || ? || '"') WHERE id = ?`).run(X,$);else Z.query(`UPDATE records SET data = json_set(coalesce(data, '{}'), '$."' || ? || '"', json(?)) WHERE id = ?`).run(X,V,$);return}let Y=H1[Q];if(!Y||!Y.cols.has(X))return;if(Q==="documents"&&X==="body"&&A1(Z,$))return;m(Z,Y.table,$);let W=DQ(Q,X,V);if(Z.query(`UPDATE ${Y.table} SET "${X}" = ? WHERE id = ?`).run(BQ(W),$),Q==="doc_blocks"){let J=Z.query("SELECT doc_id FROM doc_blocks WHERE id = ?").get($);if(J?.doc_id)L1(Z,J.doc_id)}}function _1(Z,Q){let $=Z.query("INSERT OR IGNORE INTO crdt_changes (hlc, node_id, dataset, row_id, col, value, txn) VALUES (?, ?, ?, ?, ?, ?, ?)").run(Q.hlc,Q.node_id,Q.dataset,Q.row_id,Q.col,Q.value,Q.txn??null).changes>0;if(Z.query("SELECT MAX(hlc) AS h FROM crdt_changes WHERE dataset = ? AND row_id = ? AND col = ?").get(Q.dataset,Q.row_id,Q.col).h!==Q.hlc)return{inserted:$,winner:!1};try{O1(Z,Q.dataset,Q.row_id,Q.col,Q.value)}catch(V){if($)Z.query("DELETE FROM crdt_changes WHERE dataset = ? AND row_id = ? AND col = ? AND hlc = ?").run(Q.dataset,Q.row_id,Q.col,Q.hlc);throw V}return{inserted:$,winner:!0}}function F(Z,Q,$,X,V){let Y=K1??zQ(Z),W={hlc:jQ(Z,Y),node_id:Y,dataset:Q,row_id:$,col:X,value:V===void 0?null:JSON.stringify(V),txn:w};return _1(Z,W),W}function AQ(Z){return Z.replace(/[^a-zA-Z0-9_]/g,"_")}function LQ(Z){return Z.replace(/'/g,"''")}function OQ(Z,Q){return`idx_rec_${AQ(Z)}_${AQ(Q)}`}function k1(Z,Q,$){return Z.query("SELECT 1 AS ok FROM sqlite_master WHERE type = 'index' AND name = ?").get(OQ(Q,$))!=null}function i(Z,Q,$){let X=OQ(Q,$);Z.exec(`CREATE INDEX IF NOT EXISTS "${X}" ON records (data ->> '${LQ($)}', created_hlc) WHERE database_id = '${LQ(Q)}' AND __deleted = 0`)}function o(Z,Q,$){if(k1(Z,Q,$.id))return;if($.type!=="relation"){if(Z.query("SELECT COUNT(*) AS c FROM records WHERE database_id = ? AND __deleted = 0").get(Q).c<2000)return}i(Z,Q,$.id)}var _Q=new Set(["text","number","checkbox","select","multi_select","date","relation","url"]),P1=["id","database_id","name","type","config","position"];var kQ=P1.join(", ");function a(Z,Q){if(Z==="select"||Z==="multi_select"){let $=Q?.options;if(!Array.isArray($)||$.length===0||!$.every((X)=>typeof X==="string"))throw new z("invalid_input",`${Z} requires config.options: string[]`)}if(Z==="relation"){if(typeof Q?.database!=="string")throw new z("invalid_input","relation requires config.database (target database id)")}}function q1(Z,Q){return(Z.query("SELECT MAX(position) AS m FROM properties WHERE database_id = ? AND __deleted = 0").get(Q).m??0)+1}var PQ=H(function(Q,$,X){if(!B(Q,$))throw new z("not_found",`no such database: ${$}`);if(!_Q.has(X.type))throw new z("invalid_input",`unknown property type: ${X.type}`);a(X.type,X.config);let V=X.indexed?{...X.config??{},indexed:!0}:X.config??null,Y=_("prop",X.name);if(F(Q,"properties",Y,"database_id",$),F(Q,"properties",Y,"name",X.name),F(Q,"properties",Y,"type",X.type),F(Q,"properties",Y,"config",V),F(Q,"properties",Y,"position",X.position??q1(Q,$)),X.type==="relation"||X.indexed===!0)i(Q,$,Y);return u(Q,Y)});function u(Z,Q){let $=Z.query(`SELECT ${kQ} FROM properties WHERE id = ? AND __deleted = 0`).get(Q);if(!$)return null;return{...$,config:$.config?JSON.parse($.config):null}}function q(Z,Q){return Z.query(`SELECT ${kQ} FROM properties WHERE database_id = ? AND __deleted = 0 ORDER BY position`).all(Q).map((X)=>({...X,config:X.config?JSON.parse(X.config):null}))}var g4=H(function(Q,$,X){let V=u(Q,$);if(!V)throw new z("not_found",`no such property: ${$}`);let Y=X.type!==void 0&&X.type!==V.type;if(X.type!==void 0&&!_Q.has(X.type))throw new z("invalid_input",`unknown property type: ${X.type}`);let W=X.type??V.type;if(X.config!==void 0)a(W,X.config);else if(Y)a(X.type,void 0);if(X.name!==void 0)F(Q,"properties",$,"name",X.name);if(X.type!==void 0)F(Q,"properties",$,"type",X.type);if(X.config!==void 0)F(Q,"properties",$,"config",X.config);if(X.position!==void 0)F(Q,"properties",$,"position",X.position);if(Y){let J=Q.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(V.database_id,$);for(let U of J)F(Q,"records",U.id,$,null)}return u(Q,$)});var y4=H(function(Q,$){let X=u(Q,$);if(!X)return!1;F(Q,"properties",$,"__deleted",1);let V=Q.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(X.database_id,$);for(let Y of V)F(Q,"records",Y.id,$,void 0);return!0});var M1={db:{table:"databases",nameCol:"name",scoped:!1,noun:"database"},prop:{table:"properties",nameCol:"name",scoped:!0,noun:"property"},rec:{table:"records",nameCol:null,scoped:!0,noun:"record"},doc:{table:"documents",nameCol:"title",scoped:!0,noun:"document"}},C1=["db","prop","rec","doc"];function x1(Z){return Z!==null&&Z!=="blk"}var qQ="{";function R1(Z,Q){return Z.query("SELECT id FROM properties WHERE database_id = ? AND type = 'text' AND __deleted = 0 ORDER BY position LIMIT 1").get(Q)?.id??null}function S1(Z,Q,$,X){let V=M1[Q],Y=V.nameCol;if(Q==="rec"&&X){let k=R1(Z,X);if(k)Y=`data ->> '${k.replace(/'/g,"''")}'`}let W=Y??"''",J=[],U=[];J.push("(id >= ? AND id < ?)"),U.push($,$+qQ);let G=`${Q}_${$}`;if(J.push("(id >= ? AND id < ?)"),U.push(G,G+qQ),Y)J.push(`lower(${Y}) = lower(?)`),U.push($);let j=`SELECT id, ${W} AS label FROM ${V.table} WHERE __deleted = 0 AND (${J.join(" OR ")})`;if(V.scoped&&X)j+=" AND database_id = ?",U.push(X);return Z.query(j).all(...U).map((k)=>({kind:Q,id:k.id,label:k.label??""}))}function MQ(Z,Q,$={}){let X=$.kind?[$.kind]:x1(S(Q))?[S(Q)]:C1,V=[],Y=new Set;for(let W of X)for(let J of S1(Z,W,Q,$.databaseId)){if(Y.has(J.id))continue;Y.add(J.id),V.push(J)}return V}function s(Z,Q){if(Q!==null&&Z>=Q)throw Error(`fracdex: ${Z} >= ${Q}`);if(Z.endsWith("0")||Q!==null&&Q.endsWith("0"))throw Error(`fracdex: trailing zero in ${Z}/${Q}`);if(Q!==null){let Y=0;while((Z[Y]??"0")===Q[Y])Y++;if(Y>0)return Q.slice(0,Y)+s(Z.slice(Y),Q.slice(Y))}let X=Z===""?0:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".indexOf(Z[0]),V=Q===null?62:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".indexOf(Q[0]);if(V-X>1)return"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[Math.round(0.5*(X+V))];if(Q!==null&&Q.length>1)return Q.slice(0,1);return"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[X]+s(Z.slice(1),null)}function L(Z,Q){return s(Z??"",Q)}function T(Z,Q,$){if($<=0)return[];if($===1)return[L(Z,Q)];if(Q===null){let Y=L(Z,null),W=[Y];for(let J=1;J<$;J++)Y=L(Y,null),W.push(Y);return W}if(Z===null){let Y=L(null,Q),W=[Y];for(let J=1;J<$;J++)Y=L(null,Y),W.unshift(Y);return W}let X=Math.floor($/2),V=L(Z,Q);return[...T(Z,V,X),V,...T(V,Q,$-X-1)]}function CQ(Z){return typeof Z==="string"||typeof Z==="number"||typeof Z==="boolean"}function T1(Z){return typeof Z==="boolean"?Z?1:0:Z}function E1(Z,Q,$){let X=Q.config?.database;if(!X)return $;let V=MQ(Z,$,{kind:"rec",databaseId:X}),Y=V.find((W)=>W.id===$);if(Y)return Y.id;if(V.length===1)return V[0].id;if(V.length===0){if(S($)==="rec")return $;throw new z("not_found",`${Q.name}: no such record in target database: ${$}`)}throw new z("ambiguous",`${Q.name}: ambiguous relation "${$}" (${V.length} matches); use a full id`)}function d(Z,Q,$){switch(Q.type){case"text":case"url":case"date":{if($===null)return null;if(typeof $!=="string")throw new z("invalid_input",`${Q.name} expects a string`);return $}case"number":{if($===null)return null;let X=typeof $==="number"?$:Number($);if(!Number.isFinite(X))throw new z("invalid_input",`${Q.name} expects a number`);return X}case"checkbox":{if(typeof $==="boolean")return $;if($==="true"||$===1)return!0;if($==="false"||$===0||$===null)return!1;throw new z("invalid_input",`${Q.name} expects a boolean`)}case"select":{if($===null)return null;let X=String($);if(!Q.config?.options?.includes(X))throw new z("invalid_input",`${Q.name}: '${X}' is not an allowed option`);return X}case"multi_select":{let X=$===null?[]:Array.isArray($)?$:[$],V=Q.config?.options??[];for(let Y of X)if(!V.includes(String(Y)))throw new z("invalid_input",`${Q.name}: '${Y}' is not an allowed option`);return X.map(String)}case"relation":return($===null?[]:Array.isArray($)?$:[$]).map((V)=>E1(Z,Q,String(V)))}}function g1(Z){let Q=new Map;for(let $ of Z){let X=$.name.toLowerCase(),V=Q.get(X);if(V)V.push($);else Q.set(X,[$])}return Q}function t(Z,Q){let $=new Map(Z.map((Y)=>[Y.id,Y])),X=g1(Z),V=[];for(let[Y,W]of Object.entries(Q)){let J=$.get(Y);if(!J){let U=X.get(Y.toLowerCase())??[];if(U.length>1)throw new z("ambiguous",`property name "${Y}" matches ${U.length} properties; use a property id`);J=U[0]}if(!J)throw new z("not_found",`unknown property: ${Y}`);V.push({prop:J,value:W})}return V}function SQ(Z,Q,$){return t(q(Z,Q),$).map(({prop:X,value:V})=>({prop:X,value:d(Z,X,V)}))}function TQ(Z,Q){let $=JSON.parse(Z.data||"{}"),X=new Map(Q.map((W)=>[W.id,W])),V={},Y={};for(let[W,J]of Object.entries($)){let U=X.get(W);if(!U)continue;V[U.name]=J,Y[U.id]=J}return{id:Z.id,database_id:Z.database_id,values:V,cells:Y}}function y1(Z,Q){let $=Z.find((X)=>X.prop.type==="text"&&typeof X.value==="string"&&X.value);return _("rec",$?String($.value):"",Q)}function xQ(Z,Q){return Z.query("SELECT 1 AS ok FROM sqlite_master WHERE type = 'table' AND name = ?").get(Q)!=null}function I1(Z){return xQ(Z,"meta")&&xQ(Z,"crdt_changes")}function f1(Z,Q,$,X){if(X)F(Z,"records",Q,"order_key",$);else Z.query("UPDATE records SET order_key = ? WHERE id = ?").run($,Q)}function EQ(Z,Q){return Z.query(`SELECT order_key FROM records
|
|
3
|
+
`)}var HQ="intent_receipts";var K1=["hlc","node_id","dataset","row_id","col","value","txn"];var x4=K1.join(", "),m=null,H1=null;function NQ(Z,Q){if(m!==null)return Q();m=(Z?Z+":":"")+S(8);try{return Q()}finally{m=null}}function H(Z,Q=null){return(...$)=>NQ(Q,()=>Z(...$))}var D1={databases:{table:"databases",cols:new Set(["name","icon","meta","created_hlc","__deleted"])},properties:{table:"properties",cols:new Set(["database_id","name","type","config","position","__deleted"])},documents:{table:"documents",cols:new Set(["title","body","database_id","parent_id","created_hlc","order_key","__deleted"])},doc_blocks:{table:"doc_blocks",cols:new Set(["doc_id","text","order_key","blank_after","__deleted"])},sites:{table:"sites",cols:new Set(["name","title","created_hlc","visibility","spa","public_grants","__deleted"])},site_channels:{table:"site_channels",cols:new Set(["site_id","audience","hosting","controller_node_id","target_ref","canonical_url","policy_json","desired_state","created_hlc","__deleted"])},site_files:{table:"site_files",cols:new Set(["site_id","path","content_type","encoding","content","created_hlc","__deleted"])},blob_policy:{table:"blob_policy",cols:new Set(["full_nodes","redundancy","__deleted"])}},B1=new Set(["database_id","created_hlc","order_key","__deleted"]),N1=new Set([HQ]),A1=new Set(["records:__deleted","databases:__deleted","properties:__deleted","documents:__deleted","doc_blocks:__deleted","doc_blocks:blank_after","sites:__deleted","sites:spa","site_channels:__deleted","site_files:__deleted","blob_policy:__deleted"]);function DQ(Z,Q,$){if($!==null)return JSON.parse($);return A1.has(`${Z}:${Q}`)?0:null}function BQ(Z){if(Z===null||Z===void 0)return null;if(typeof Z==="boolean")return Z?1:0;if(typeof Z==="number")return Z;if(typeof Z==="string")return Z;return JSON.stringify(Z)}function u(Z,Q,$){Z.query(`INSERT OR IGNORE INTO ${Q} (id) VALUES (?)`).run($)}function L1(Z,Q){return Z.query("SELECT 1 AS x FROM doc_blocks WHERE doc_id = ? LIMIT 1").get(Q)!=null}function O1(Z,Q){let $=Z.query("SELECT text, blank_after FROM doc_blocks WHERE doc_id = ? AND __deleted = 0 ORDER BY order_key, id").all(Q);u(Z,"documents",Q),Z.query("UPDATE documents SET body = ? WHERE id = ?").run(KQ($.map((X)=>({text:X.text,blankAfter:X.blank_after??0}))),Q)}function _1(Z,Q,$,X,V){if(N1.has(Q))return;if(Q==="records"){if(B1.has(X)){u(Z,"records",$);let J=DQ("records",X,V);Z.query(`UPDATE records SET "${X}" = ? WHERE id = ?`).run(BQ(J),$)}else if(u(Z,"records",$),V===null)Z.query(`UPDATE records SET data = json_remove(data, '$."' || ? || '"') WHERE id = ?`).run(X,$);else Z.query(`UPDATE records SET data = json_set(coalesce(data, '{}'), '$."' || ? || '"', json(?)) WHERE id = ?`).run(X,V,$);return}let Y=D1[Q];if(!Y||!Y.cols.has(X))return;if(Q==="documents"&&X==="body"&&L1(Z,$))return;u(Z,Y.table,$);let W=DQ(Q,X,V);if(Z.query(`UPDATE ${Y.table} SET "${X}" = ? WHERE id = ?`).run(BQ(W),$),Q==="doc_blocks"){let J=Z.query("SELECT doc_id FROM doc_blocks WHERE id = ?").get($);if(J?.doc_id)O1(Z,J.doc_id)}}function k1(Z,Q){let $=Z.query("INSERT OR IGNORE INTO crdt_changes (hlc, node_id, dataset, row_id, col, value, txn) VALUES (?, ?, ?, ?, ?, ?, ?)").run(Q.hlc,Q.node_id,Q.dataset,Q.row_id,Q.col,Q.value,Q.txn??null).changes>0;if(Z.query("SELECT MAX(hlc) AS h FROM crdt_changes WHERE dataset = ? AND row_id = ? AND col = ?").get(Q.dataset,Q.row_id,Q.col).h!==Q.hlc)return{inserted:$,winner:!1};try{_1(Z,Q.dataset,Q.row_id,Q.col,Q.value)}catch(V){if($)Z.query("DELETE FROM crdt_changes WHERE dataset = ? AND row_id = ? AND col = ? AND hlc = ?").run(Q.dataset,Q.row_id,Q.col,Q.hlc);throw V}return{inserted:$,winner:!0}}function G(Z,Q,$,X,V){let Y=H1??zQ(Z),W={hlc:jQ(Z,Y),node_id:Y,dataset:Q,row_id:$,col:X,value:V===void 0?null:JSON.stringify(V),txn:m};return k1(Z,W),W}function AQ(Z){return Z.replace(/[^a-zA-Z0-9_]/g,"_")}function LQ(Z){return Z.replace(/'/g,"''")}function OQ(Z,Q){return`idx_rec_${AQ(Z)}_${AQ(Q)}`}function q1(Z,Q,$){return Z.query("SELECT 1 AS ok FROM sqlite_master WHERE type = 'index' AND name = ?").get(OQ(Q,$))!=null}function i(Z,Q,$){let X=OQ(Q,$);Z.exec(`CREATE INDEX IF NOT EXISTS "${X}" ON records (data ->> '${LQ($)}', created_hlc) WHERE database_id = '${LQ(Q)}' AND __deleted = 0`)}function o(Z,Q,$){if(q1(Z,Q,$.id))return;if($.type!=="relation"){if(Z.query("SELECT COUNT(*) AS c FROM records WHERE database_id = ? AND __deleted = 0").get(Q).c<2000)return}i(Z,Q,$.id)}var _Q=new Set(["text","number","checkbox","select","multi_select","date","relation","url"]),P1=["id","database_id","name","type","config","position"];var kQ=P1.join(", ");function a(Z,Q){if(Z==="select"||Z==="multi_select"){let $=Q?.options;if(!Array.isArray($)||$.length===0||!$.every((X)=>typeof X==="string"))throw new F("invalid_input",`${Z} requires config.options: string[]`)}if(Z==="relation"){if(typeof Q?.database!=="string")throw new F("invalid_input","relation requires config.database (target database id)")}}function x1(Z,Q){return(Z.query("SELECT MAX(position) AS m FROM properties WHERE database_id = ? AND __deleted = 0").get(Q).m??0)+1}var qQ=H(function(Q,$,X){if(!B(Q,$))throw new F("not_found",`no such database: ${$}`);if(!_Q.has(X.type))throw new F("invalid_input",`unknown property type: ${X.type}`);a(X.type,X.config);let V=X.indexed?{...X.config??{},indexed:!0}:X.config??null,Y=_("prop",X.name);if(G(Q,"properties",Y,"database_id",$),G(Q,"properties",Y,"name",X.name),G(Q,"properties",Y,"type",X.type),G(Q,"properties",Y,"config",V),G(Q,"properties",Y,"position",X.position??x1(Q,$)),X.type==="relation"||X.indexed===!0)i(Q,$,Y);return P(Q,Y)});function P(Z,Q){let $=Z.query(`SELECT ${kQ} FROM properties WHERE id = ? AND __deleted = 0`).get(Q);if(!$)return null;return{...$,config:$.config?JSON.parse($.config):null}}function x(Z,Q){return Z.query(`SELECT ${kQ} FROM properties WHERE database_id = ? AND __deleted = 0 ORDER BY position`).all(Q).map((X)=>({...X,config:X.config?JSON.parse(X.config):null}))}var I4=H(function(Q,$,X){let V=P(Q,$);if(!V)throw new F("not_found",`no such property: ${$}`);let Y=X.type!==void 0&&X.type!==V.type;if(X.type!==void 0&&!_Q.has(X.type))throw new F("invalid_input",`unknown property type: ${X.type}`);let W=X.type??V.type,J;if(X.config!==void 0){let U={...V.config??{}};for(let[z,j]of Object.entries(X.config))if(j===null)delete U[z];else U[z]=j;J=U,a(W,J)}else if(Y)a(X.type,V.config??void 0);if(X.name!==void 0)G(Q,"properties",$,"name",X.name);if(X.type!==void 0)G(Q,"properties",$,"type",X.type);if(J!==void 0)G(Q,"properties",$,"config",J);if(X.position!==void 0)G(Q,"properties",$,"position",X.position);if(Y){let U=Q.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(V.database_id,$);for(let z of U)G(Q,"records",z.id,$,null)}return P(Q,$)});function PQ(Z,Q){let $=P(Z,Q);if(!$)throw new F("not_found",`no such property: ${Q}`);if($.type!=="select"&&$.type!=="multi_select")throw new F("invalid_input",`${$.type} property has no options`);return{prop:$,options:$.config?.options??[]}}var y4=H(function(Q,$,X,V){let{prop:Y,options:W}=PQ(Q,$);if(V=V.trim(),!V)throw new F("invalid_input","option name must not be empty");if(!W.includes(X))throw new F("not_found",`no such option: ${X}`);if(V===X)return{property:Y,renamed:0};if(W.includes(V))throw new F("conflict",`option already exists: ${V}`);G(Q,"properties",$,"config",{...Y.config??{},options:W.map((U)=>U===X?V:U)});let J=0;if(Y.type==="select"){let U=Q.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? = ?").all(Y.database_id,$,X);for(let z of U)G(Q,"records",z.id,$,V);J=U.length}else{let U=Q.query("SELECT id, data ->> ? AS v FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all($,Y.database_id,$);for(let z of U){let j=JSON.parse(z.v);if(!Array.isArray(j)||!j.includes(X))continue;G(Q,"records",z.id,$,[...new Set(j.map((D)=>D===X?V:D))]),J++}}return{property:P(Q,$),renamed:J}}),f4=H(function(Q,$,X){let{prop:V,options:Y}=PQ(Q,$);if(!Y.includes(X))throw new F("not_found",`no such option: ${X}`);if(Y.length===1)throw new F("invalid_input","cannot remove the last option; delete the property instead");G(Q,"properties",$,"config",{...V.config??{},options:Y.filter((J)=>J!==X)});let W=0;if(V.type==="select"){let J=Q.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? = ?").all(V.database_id,$,X);for(let U of J)G(Q,"records",U.id,$,null);W=J.length}else{let J=Q.query("SELECT id, data ->> ? AS v FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all($,V.database_id,$);for(let U of J){let z=JSON.parse(U.v);if(!Array.isArray(z)||!z.includes(X))continue;G(Q,"records",U.id,$,z.filter((j)=>j!==X)),W++}}return{property:P(Q,$),cleared:W}}),v4=H(function(Q,$){let X=P(Q,$);if(!X)return!1;G(Q,"properties",$,"__deleted",1);let V=Q.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(X.database_id,$);for(let Y of V)G(Q,"records",Y.id,$,void 0);return!0});var R1={db:{table:"databases",nameCol:"name",scoped:!1,noun:"database"},prop:{table:"properties",nameCol:"name",scoped:!0,noun:"property"},rec:{table:"records",nameCol:null,scoped:!0,noun:"record"},doc:{table:"documents",nameCol:"title",scoped:!0,noun:"document"}},C1=["db","prop","rec","doc"];function M1(Z){return Z!==null&&Z!=="blk"}var xQ="{";function S1(Z,Q){return Z.query("SELECT id FROM properties WHERE database_id = ? AND type = 'text' AND __deleted = 0 ORDER BY position LIMIT 1").get(Q)?.id??null}function T1(Z,Q,$,X){let V=R1[Q],Y=V.nameCol;if(Q==="rec"&&X){let k=S1(Z,X);if(k)Y=`data ->> '${k.replace(/'/g,"''")}'`}let W=Y??"''",J=[],U=[];J.push("(id >= ? AND id < ?)"),U.push($,$+xQ);let z=`${Q}_${$}`;if(J.push("(id >= ? AND id < ?)"),U.push(z,z+xQ),Y)J.push(`lower(${Y}) = lower(?)`),U.push($);let j=`SELECT id, ${W} AS label FROM ${V.table} WHERE __deleted = 0 AND (${J.join(" OR ")})`;if(V.scoped&&X)j+=" AND database_id = ?",U.push(X);return Z.query(j).all(...U).map((k)=>({kind:Q,id:k.id,label:k.label??""}))}function RQ(Z,Q,$={}){let X=$.kind?[$.kind]:M1(T(Q))?[T(Q)]:C1,V=[],Y=new Set;for(let W of X)for(let J of T1(Z,W,Q,$.databaseId)){if(Y.has(J.id))continue;Y.add(J.id),V.push(J)}return V}function s(Z,Q){if(Q!==null&&Z>=Q)throw Error(`fracdex: ${Z} >= ${Q}`);if(Z.endsWith("0")||Q!==null&&Q.endsWith("0"))throw Error(`fracdex: trailing zero in ${Z}/${Q}`);if(Q!==null){let Y=0;while((Z[Y]??"0")===Q[Y])Y++;if(Y>0)return Q.slice(0,Y)+s(Z.slice(Y),Q.slice(Y))}let X=Z===""?0:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".indexOf(Z[0]),V=Q===null?62:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".indexOf(Q[0]);if(V-X>1)return"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[Math.round(0.5*(X+V))];if(Q!==null&&Q.length>1)return Q.slice(0,1);return"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[X]+s(Z.slice(1),null)}function L(Z,Q){return s(Z??"",Q)}function E(Z,Q,$){if($<=0)return[];if($===1)return[L(Z,Q)];if(Q===null){let Y=L(Z,null),W=[Y];for(let J=1;J<$;J++)Y=L(Y,null),W.push(Y);return W}if(Z===null){let Y=L(null,Q),W=[Y];for(let J=1;J<$;J++)Y=L(null,Y),W.unshift(Y);return W}let X=Math.floor($/2),V=L(Z,Q);return[...E(Z,V,X),V,...E(V,Q,$-X-1)]}function CQ(Z){return typeof Z==="string"||typeof Z==="number"||typeof Z==="boolean"}function E1(Z){return typeof Z==="boolean"?Z?1:0:Z}function g1(Z,Q,$){let X=Q.config?.database;if(!X)return $;let V=RQ(Z,$,{kind:"rec",databaseId:X}),Y=V.find((W)=>W.id===$);if(Y)return Y.id;if(V.length===1)return V[0].id;if(V.length===0){if(T($)==="rec")return $;throw new F("not_found",`${Q.name}: no such record in target database: ${$}`)}throw new F("ambiguous",`${Q.name}: ambiguous relation "${$}" (${V.length} matches); use a full id`)}function t(Z,Q,$){switch(Q.type){case"text":case"url":case"date":{if($===null)return null;if(typeof $!=="string")throw new F("invalid_input",`${Q.name} expects a string`);return $}case"number":{if($===null)return null;let X=typeof $==="number"?$:Number($);if(!Number.isFinite(X))throw new F("invalid_input",`${Q.name} expects a number`);return X}case"checkbox":{if(typeof $==="boolean")return $;if($==="true"||$===1)return!0;if($==="false"||$===0||$===null)return!1;throw new F("invalid_input",`${Q.name} expects a boolean`)}case"select":{if($===null)return null;let X=String($);if(!Q.config?.options?.includes(X))throw new F("invalid_input",`${Q.name}: '${X}' is not an allowed option`);return X}case"multi_select":{let X=$===null?[]:Array.isArray($)?$:[$],V=Q.config?.options??[];for(let Y of X)if(!V.includes(String(Y)))throw new F("invalid_input",`${Q.name}: '${Y}' is not an allowed option`);return X.map(String)}case"relation":return($===null?[]:Array.isArray($)?$:[$]).map((V)=>g1(Z,Q,String(V)))}}function I1(Z){let Q=new Map;for(let $ of Z){let X=$.name.toLowerCase(),V=Q.get(X);if(V)V.push($);else Q.set(X,[$])}return Q}function d(Z,Q){let $=new Map(Z.map((Y)=>[Y.id,Y])),X=I1(Z),V=[];for(let[Y,W]of Object.entries(Q)){let J=$.get(Y);if(!J){let U=X.get(Y.toLowerCase())??[];if(U.length>1)throw new F("ambiguous",`property name "${Y}" matches ${U.length} properties; use a property id`);J=U[0]}if(!J)throw new F("not_found",`unknown property: ${Y}`);V.push({prop:J,value:W})}return V}function TQ(Z,Q,$){return d(x(Z,Q),$).map(({prop:X,value:V})=>({prop:X,value:t(Z,X,V)}))}function EQ(Z,Q){let $=JSON.parse(Z.data||"{}"),X=new Map(Q.map((W)=>[W.id,W])),V={},Y={};for(let[W,J]of Object.entries($)){let U=X.get(W);if(!U)continue;V[U.name]=J,Y[U.id]=J}return{id:Z.id,database_id:Z.database_id,values:V,cells:Y}}function y1(Z,Q){let $=Z.find((X)=>X.prop.type==="text"&&typeof X.value==="string"&&X.value);return _("rec",$?String($.value):"",Q)}function MQ(Z,Q){return Z.query("SELECT 1 AS ok FROM sqlite_master WHERE type = 'table' AND name = ?").get(Q)!=null}function f1(Z){return MQ(Z,"meta")&&MQ(Z,"crdt_changes")}function v1(Z,Q,$,X){if(X)G(Z,"records",Q,"order_key",$);else Z.query("UPDATE records SET order_key = ? WHERE id = ?").run($,Q)}function gQ(Z,Q){return Z.query(`SELECT order_key FROM records
|
|
4
4
|
WHERE database_id = ? AND __deleted = 0 AND order_key IS NOT NULL
|
|
5
5
|
ORDER BY order_key DESC, id DESC LIMIT 1`).get(Q)?.order_key??null}function r(Z,Q){return Z.query(`SELECT id, database_id, created_hlc, order_key FROM records
|
|
6
6
|
WHERE database_id = ? AND __deleted = 0
|
|
7
|
-
ORDER BY order_key IS NULL, order_key, created_hlc, id`).all(Q)}function
|
|
7
|
+
ORDER BY order_key IS NULL, order_key, created_hlc, id`).all(Q)}function w1(Z,Q){let $=r(Z,Q),X=E(null,null,$.length);$.forEach((V,Y)=>{if(V.order_key!==X[Y])G(Z,"records",V.id,"order_key",X[Y])})}var m1=H(function(Q,$){let X=f1(Q),V=$?[{database_id:$}]:Q.query(`SELECT DISTINCT database_id FROM records
|
|
8
8
|
WHERE database_id IS NOT NULL AND __deleted = 0 AND order_key IS NULL`).all();for(let Y of V){let W=Q.query(`SELECT id FROM records
|
|
9
9
|
WHERE database_id = ? AND __deleted = 0 AND order_key IS NULL
|
|
10
|
-
ORDER BY created_hlc, id`).all(Y.database_id);if(!W.length)continue;let J=EQ(Q,Y.database_id),U=T(J,null,W.length);W.forEach((G,j)=>f1(Q,G.id,U[j],X))}}),gQ=H(function(Q,$,X){let V=y1(X,b($.name,"rec")),Y=L(EQ(Q,$.id),null),W=F(Q,"records",V,"database_id",$.id);F(Q,"records",V,"created_hlc",W.hlc),F(Q,"records",V,"order_key",Y);for(let{prop:J,value:U}of X)F(Q,"records",V,J.id,U);return E(Q,V)}),yQ=H(function(Q,$,X){let V=B(Q,$);if(!V)throw new z("not_found",`no such database: ${$}`);return gQ(Q,V,SQ(Q,V.id,X))});function E(Z,Q){let $=Z.query("SELECT id, database_id, data FROM records WHERE id = ? AND __deleted = 0").get(Q);if(!$)return null;return TQ($,q(Z,$.database_id))}function RQ(Z){return Z.replace(/'/g,"''")}function IQ(Z,Q,$={}){let X=q(Z,Q),V=$.filter&&Object.keys($.filter).length?t(X,$.filter).map(({prop:K,value:A})=>({prop:K,value:d(Z,K,A)})):[],Y=V.filter((K)=>CQ(K.value)),W=V.filter((K)=>!CQ(K.value)),J,U=!1;if($.sort){let K=$.sort;if(K.startsWith("-"))U=!0,K=K.slice(1);if(K!=="created"&&K!=="created_hlc"){let A=X.find((x)=>x.id===K);if(!A){let x=X.filter((dQ)=>dQ.name.toLowerCase()===K.toLowerCase());if(x.length>1)throw new z("ambiguous",`sort field "${K}" matches ${x.length} properties; use a property id`);A=x[0]}if(!A)throw new z("not_found",`unknown sort field: ${K}`);J=A}}for(let K of Y)o(Z,Q,K.prop);if(J)o(Z,Q,J);let G=["database_id = ?","__deleted = 0"],j=[Q];for(let K of Y)G.push(`data ->> '${RQ(K.prop.id)}' = ?`),j.push(T1(K.value));let D=$.sort==null,k=J?`data ->> '${RQ(J.id)}'`:"created_hlc",XQ=`SELECT id, database_id, data FROM records WHERE ${G.join(" AND ")} `+(D?"ORDER BY order_key IS NULL, order_key, id":`ORDER BY ${k} ${U?"DESC":"ASC"}, id`);if($.limit!=null&&W.length===0)XQ+=" LIMIT ?",j.push($.limit);let C=Z.query(XQ).all(...j).map((K)=>TQ(K,X));if(W.length){if(C=C.filter((K)=>W.every((A)=>JSON.stringify(K.cells[A.prop.id]??null)===JSON.stringify(A.value))),$.limit!=null)C=C.slice(0,$.limit)}return C}var o4=H(function(Q,$,X,V){if(V!=="before"&&V!=="after")throw new z("invalid_input",`unknown move position: ${V}`);let Y=Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get($);if(!Y)throw new z("not_found",`no such record: ${$}`);let W=Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get(X);if(!W)throw new z("not_found",`no such record: ${X}`);if(Y.database_id!==W.database_id)throw new z("invalid_input","cannot move a record across databases");if($===X)return E(Q,$);w1(Q,Y.database_id);let J=r(Q,Y.database_id).filter((D)=>D.id!==$),U=J.findIndex((D)=>D.id===X);if(U<0)throw new z("not_found",`no such target record: ${X}`);let G=V==="before"?J[U-1]?.order_key??null:J[U].order_key,j=V==="before"?J[U].order_key:J[U+1]?.order_key??null;if(G!==null&&j!==null&&G>=j)v1(Q,Y.database_id),J=r(Q,Y.database_id).filter((D)=>D.id!==$),U=J.findIndex((D)=>D.id===X),G=V==="before"?J[U-1]?.order_key??null:J[U].order_key,j=V==="before"?J[U].order_key:J[U+1]?.order_key??null;return F(Q,"records",$,"order_key",L(G,j)),E(Q,$)}),fQ=H(function(Q,$,X){if(!Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get($))throw new z("not_found",`no such record: ${$}`);for(let{prop:Y,value:W}of X)F(Q,"records",$,Y.id,W);return E(Q,$)}),a4=H(function(Q,$,X){let V=Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get($);if(!V)throw new z("not_found",`no such record: ${$}`);return fQ(Q,$,SQ(Q,V.database_id,X))}),s4=H(function(Q,$){if(!Q.query("SELECT id FROM records WHERE id = ? AND __deleted = 0").get($))return!1;return F(Q,"records",$,"__deleted",1),!0});var m1=["id","name","icon","meta","created_hlc"];var u1=m1.join(", ");function h1(Z){if(!Z)return null;return{...Z,meta:Z.meta===null?null:JSON.parse(Z.meta)}}var c1=H(function(Q,$){let X=_("db",$.name),V=F(Q,"databases",X,"name",$.name);if(F(Q,"databases",X,"created_hlc",V.hlc),$.icon!==void 0)F(Q,"databases",X,"icon",$.icon);return B(Q,X)}),Z8=H(function(Q,$,X){if(!B(Q,$))throw new z("not_found",`no such database: ${$}`);if(X.name!==void 0)F(Q,"databases",$,"name",X.name);if(X.icon!==void 0)F(Q,"databases",$,"icon",X.icon);if(X.meta!==void 0){if(X.meta!==null&&(typeof X.meta!=="object"||Array.isArray(X.meta)))throw new z("invalid_input","meta must be a JSON object or null");F(Q,"databases",$,"meta",X.meta)}return B(Q,$)}),X8=H(function(Q,$,X={}){let V=B(Q,$);if(!V)throw new z("not_found",`no such database: ${$}`);let Y=c1(Q,{name:X.name??V.name,icon:X.icon??V.icon??void 0});if(V.meta!==null){let{collapsed:J,...U}=V.meta;if(Object.keys(U).length)F(Q,"databases",Y.id,"meta",U)}let W=new Map;for(let J of q(Q,$)){let U=J.config?.database===$?{...J.config,database:Y.id}:J.config??void 0,G=PQ(Q,Y.id,{name:J.name,type:J.type,config:U,position:J.position});W.set(J.id,G.id)}for(let J of IQ(Q,$)){let U={};for(let[G,j]of Object.entries(J.cells)){let D=W.get(G);if(D)U[D]=j}yQ(Q,Y.id,U)}return B(Q,Y.id)});function B(Z,Q){return h1(Z.query(`SELECT ${u1} FROM databases WHERE id = ? AND __deleted = 0`).get(Q))}var V8=H(function(Q,$){if(!B(Q,$))return!1;F(Q,"databases",$,"__deleted",1);let X=(V)=>{for(let Y of vQ(Q,V,"database_id",$))F(Q,V,Y,"__deleted",1)};X("properties"),X("records");for(let V of vQ(Q,"documents","database_id",$))F(Q,"documents",V,"database_id",null);return Q.query("DELETE FROM meta WHERE key = 'current_db' AND value = ?").run($),!0});function vQ(Z,Q,$,X){return Z.query(`SELECT id FROM ${Q} WHERE ${$} = ? AND __deleted = 0`).all(X).map((V)=>V.id)}var e=["read","create","update"];function l1(Z){return typeof Z==="string"&&e.includes(Z)}function wQ(Z){let Q=new Map;for(let X of Z){let V=Q.get(X.db)??new Set;for(let Y of X.ops)V.add(Y);Q.set(X.db,V)}let $=[];for(let[X,V]of Q){let Y=e.filter((W)=>V.has(W));if(Y.length)$.push({db:X,ops:Y})}return $.sort((X,V)=>X.db<V.db?-1:X.db>V.db?1:0),{v:1,tables:$}}function mQ(Z){if(typeof Z!=="object"||Z===null||Array.isArray(Z))throw new z("invalid_input","grants must be an object {v:1, tables:[...]}");let Q=Z;if(Q.v!==1)throw new z("invalid_input","grants version must be 1");if(!Array.isArray(Q.tables))throw new z("invalid_input","grants.tables must be an array");let $=[];for(let X of Q.tables){if(typeof X!=="object"||X===null)throw new z("invalid_input","each grant table must be an object {db, ops}");let{db:V,ops:Y}=X;if(typeof V!=="string"||!V)throw new z("invalid_input","grant table `db` must be a database id");if(!Array.isArray(Y)||!Y.every(l1))throw new z("invalid_input",`grant ops must be a subset of ${e.join("|")} (delete is never grantable)`);$.push({db:V,ops:Y})}return wQ($)}function uQ(Z){return JSON.stringify(wQ(Z.tables))}var p1=["id","name","title","created_hlc","visibility","spa","public_grants"];var hQ=p1.join(", "),n1=["id","site_id","path","content_type","encoding","content"];var N8=n1.join(", ");function QQ(Z){let Q=Z.trim().toLowerCase().replace(/[^a-z0-9-]+/g,"-").replace(/^-+|-+$/g,"");if(!Q)throw new z("invalid_input",`invalid site name: ${JSON.stringify(Z)}`);return Q}function b1(Z){let Q=[];for(let $ of Z.split("/")){if($===""||$===".")continue;if($==="..")Q.pop();else Q.push($)}return Q.join("/")}function M(Z,Q){return Z.query(`SELECT ${hQ} FROM sites WHERE id = ? AND __deleted = 0`).get(Q)}function cQ(Z,Q){let $;try{$=QQ(Q)}catch{return null}return Z.query(`SELECT ${hQ} FROM sites WHERE name = ? AND __deleted = 0 ORDER BY created_hlc DESC LIMIT 1`).get($)}function lQ(Z){let Q=atob(Z),$=new Uint8Array(Q.length);for(let X=0;X<Q.length;X++)$[X]=Q.charCodeAt(X);return $}function pQ(Z){if(Z!=="public"&&Z!=="private")throw new z("invalid_input",`visibility must be "public" or "private", got ${JSON.stringify(Z)}`)}var A8=H(function(Q,$){let X=QQ($.name);if(cQ(Q,X))throw new z("conflict",`site name already exists: ${X}`);if($.visibility!==void 0)pQ($.visibility);let V=_("site",X),Y=F(Q,"sites",V,"name",X);if(F(Q,"sites",V,"created_hlc",Y.hlc),$.title!==void 0)F(Q,"sites",V,"title",$.title);if($.visibility!==void 0)F(Q,"sites",V,"visibility",$.visibility);return M(Q,V)}),L8=H(function(Q,$,X){if(!M(Q,$))throw new z("not_found",`no such site: ${$}`);if(X.visibility!==void 0)pQ(X.visibility);if(X.name!==void 0){let V=QQ(X.name),Y=cQ(Q,V);if(Y&&Y.id!==$)throw new z("conflict",`site name already exists: ${V}`);F(Q,"sites",$,"name",V)}if(X.title!==void 0)F(Q,"sites",$,"title",X.title);if(X.visibility!==void 0)F(Q,"sites",$,"visibility",X.visibility);if(X.spa!==void 0)F(Q,"sites",$,"spa",X.spa?1:0);return M(Q,$)}),O8=H(function(Q,$,X){if(!M(Q,$))throw new z("not_found",`no such site: ${$}`);let V=X==null?null:uQ(mQ(X));return F(Q,"sites",$,"public_grants",V),M(Q,$)}),_8=H(function(Q,$){if(!M(Q,$))return!1;let X=Q.query("SELECT id FROM site_files WHERE site_id = ? AND __deleted = 0").all($);for(let V of X)F(Q,"site_files",V.id,"__deleted",1);return F(Q,"sites",$,"__deleted",1),!0});function i1(Z,Q,$){return Z.query("SELECT id FROM site_files WHERE site_id = ? AND path = ? ORDER BY created_hlc LIMIT 1").get(Q,$)?.id??null}var k8=H(function(Q,$,X){let V=i1(Q,$,b1(X));if(!V)return!1;let Y=Q.query("SELECT __deleted AS d FROM site_files WHERE id = ?").get(V);if(!Y||Y.d)return!1;return F(Q,"site_files",V,"__deleted",1),!0});var N=globalThis,O=N.caches,o1="__MH_SW_VERSION__",g=`mh-shell-${o1}`,nQ="mh-api-v1",a1="mh-wasm-v1",sQ=["/","/webui.js","/webui.css","/manifest.webmanifest","/db-worker.js","/mh-runtime.js"],y=3500,s1=12000;function I(Z){return Z.ok&&Z.headers.get("x-mh-unlock")==null}var $Q=null;async function ZQ(){if($Q==null){let Z=await VQ();if(Z==="unknown")return!1;$Q=Z}return $Q==="none"}N.addEventListener("install",(Z)=>{Z.waitUntil((async()=>{try{let Q=await O.open(g);await Promise.allSettled(sQ.map(async($)=>{let X=await fetch($);if(I(X))await Q.put($,X)})),await N.skipWaiting()}catch(Q){try{await(await O.open("mh-debug")).put("/__mh-sw-install-error",new Response(String(Q?.stack??Q)))}catch{}throw Q}})())});N.addEventListener("activate",(Z)=>{Z.waitUntil((async()=>{for(let Q of await O.keys())if(Q.startsWith("mh-shell-")&&Q!==g)await O.delete(Q);await N.clients.claim()})())});function c(Z,Q){return new Promise(($,X)=>{let V=setTimeout(()=>X(Error("sw: network timeout")),Q);fetch(Z).then((Y)=>{clearTimeout(V),$(Y)},(Y)=>{clearTimeout(V),X(Y)})})}async function bQ(Z,Q,$,X){let V=await O.open(Q),Y=X??Z;try{let W=await c(Z,$);if(I(W))await V.put(Y,W.clone());return W}catch(W){let J=await V.match(Y);if(J)return J;throw W}}function r1(Z,Q,$){return new Promise((X,V)=>{let Y=new MessageChannel,W=setTimeout(()=>V(Error("sw: rpc timeout")),s1);Y.port1.onmessage=(J)=>{clearTimeout(W),X(J.data)},Z.postMessage({kind:"mh-rpc",op:Q,args:$},[Y.port2])})}async function h(Z,Q,$){let X=new Set,V=[];if(Z.clientId){let Y=await N.clients.get(Z.clientId);if(Y)V.push(Y)}for(let Y of await N.clients.matchAll({type:"window",includeUncontrolled:!0}))if(!V.some((W)=>W.id===Y.id))V.push(Y);for(let Y of V){if(X.has(Y.id))continue;X.add(Y.id);try{let W=await r1(Y,Q,$);if(!W.ok&&W.error?.code==="unavailable")continue;return W}catch{continue}}return null}var d1={invalid_input:400,not_found:404,ambiguous:400,stale:409,conflict:409,auth:401,network:502};function iQ(Z){if(Z.ok)return new Response(JSON.stringify(Z.result??null),{headers:{"content-type":"application/json","x-mh-source":"replica"}});let Q=Z.error?.code;return new Response(JSON.stringify({error:Z.error?.message??"replica error",code:Q}),{status:Q?d1[Q]??400:502,headers:{"content-type":"application/json","x-mh-source":"replica"}})}async function oQ(Z,Q){let $=Z.request,X=new URL($.url),V=Q??X.pathname,Y=null;if($.method!=="GET"&&($.headers.get("content-type")??"").includes("json"))Y=await $.clone().json().catch(()=>null);if(await ZQ()){let W=l($.method,V,X.searchParams,Y);if(W){let J=await h(Z,W.op,W.args);if(J)return iQ(J)}return new Response(JSON.stringify({error:"no metahub server (bucket-only mode)",code:"network"}),{status:502,headers:{"content-type":"application/json","x-mh-source":"replica"}})}try{let W=$.method==="GET"?await c($,y*2):await fetch($);if($.method==="GET"&&I(W))await(await O.open(nQ)).put($,W.clone());return W}catch(W){let J=l($.method,V,X.searchParams,Y);if(J){let U=await h(Z,J.op,J.args);if(U)return iQ(U)}if($.method==="GET"){let U=await(await O.open(nQ)).match($);if(U)return U}throw W}}async function t1(Z,Q){let $=Q.content_type.includes("text/html"),X=Q.content??"";if(Q.encoding==="blob"){let Y=await rQ(Z,X,Q.content_type);if(!Y)return new Response("blob unavailable offline",{status:404});return new Response(Y.body,{status:Q.status??200,headers:{"content-type":Q.content_type,"x-mh-source":"replica"}})}let V;if(Q.encoding==="utf8")V=$&&!Q.public?UQ(X):X;else V=lQ(X);return new Response(V,{status:Q.status??200,headers:{"content-type":Q.content_type,"x-mh-source":"replica"}})}function e1(Z,Q){let $=`${JSON.stringify(Z)},${JSON.stringify(Q)}`;return new Response(`<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><script src="/mh-runtime.js"></script></head><body><p style="font:14px system-ui;color:#888;margin:2em">正在从本地副本加载…</p><script>__mhOfflineBootstrap(${$})</script></body></html>`,{headers:{"content-type":"text/html; charset=utf-8","x-mh-source":"bootstrap"}})}async function aQ(Z,Q){let $=Q.pathname.slice(7);if($==="")return null;let X=$.indexOf("/");if(X===-1)return Response.redirect(`${Q.origin}/sites/${$}/`,301);let V=decodeURIComponent($.slice(0,X)),Y=decodeURIComponent($.slice(X+1)),W=await h(Z,"siteFile",[V,Y]);if(W?.ok&&W.result)return t1(Z,W.result);if(W?.ok&&W.result==null)return new Response("not found (offline replica)",{status:404});if(Z.request.mode==="navigate")return e1(V,Y);return null}async function Q4(Z){let Q=Z.request,$=new URL(Q.url);if(await ZQ())return await aQ(Z,$)??new Response("not found",{status:404});try{return await c(Q,y)}catch(X){let V=await aQ(Z,$);if(V)return V;throw X}}async function $4(Z){let Q=Z.request,$=new URL(Q.url),X=decodeURIComponent($.pathname.slice(6)),V=X.indexOf("."),Y=(V>=0?X.slice(0,V):X).toLowerCase();if(!/^[0-9a-f]{16,64}$/.test(Y))return fetch(Q);let W=YQ(X);return await rQ(Z,Y,W,Q)??new Response("blob unavailable offline",{status:404})}async function rQ(Z,Q,$,X){let V=await WQ(Q);if(V)return V;if(!await ZQ())try{let W=X?new Request(X,{cache:"no-store"}):new Request(`${N.location.origin}/blob/${Q}`,{cache:"no-store"}),J=await c(W,y*2);if(J.ok){let U=await J.clone().arrayBuffer();if(await p(U,Q))return await n(Q,U,J.headers.get("content-type")??$),J}}catch{}let Y=await h(Z,"blobBytes",[Q]);if(Y?.ok&&Y.result){let W=Y.result;if(await p(W,Q))return await n(Q,W,$),new Response(W,{headers:{"content-type":$,"x-mh-source":"replica"}})}return null}N.addEventListener("fetch",(Z)=>{let Q=Z.request,$=new URL(Q.url);if($.origin!==N.location.origin)return;if($.pathname.startsWith("/api/")){Z.respondWith(oQ(Z));return}let X=/^\/sites\/[^/]+(\/api\/.*)$/.exec($.pathname);if(X){Z.respondWith(oQ(Z,X[1]));return}if(Q.method!=="GET")return;if($.pathname.startsWith("/sites/")){Z.respondWith(Q4(Z));return}if($.pathname.startsWith("/blob/")){Z.respondWith($4(Z));return}if(Q.mode==="navigate"){if($.pathname!=="/")return;Z.respondWith(bQ(Q,g,y,"/"));return}if(sQ.includes($.pathname)||$.pathname.startsWith("/icons/")){Z.respondWith(bQ(Q,g,y));return}if($.pathname.startsWith("/webui-fmt")){Z.respondWith((async()=>{let V=await O.open(g),Y=await V.match(Q);if(Y)return Y;let W=await fetch(Q);if(I(W))await V.put(Q,W.clone());return W})());return}if($.pathname==="/sqlite3.wasm"){Z.respondWith((async()=>{let V=await O.open(a1),Y=await V.match(Q);if(Y)return Y;let W=await fetch(Q);if(I(W))await V.put(Q,W.clone());return W})());return}});
|
|
10
|
+
ORDER BY created_hlc, id`).all(Y.database_id);if(!W.length)continue;let J=gQ(Q,Y.database_id),U=E(J,null,W.length);W.forEach((z,j)=>v1(Q,z.id,U[j],X))}}),IQ=H(function(Q,$,X){let V=y1(X,b($.name,"rec")),Y=L(gQ(Q,$.id),null),W=G(Q,"records",V,"database_id",$.id);G(Q,"records",V,"created_hlc",W.hlc),G(Q,"records",V,"order_key",Y);for(let{prop:J,value:U}of X)G(Q,"records",V,J.id,U);return g(Q,V)}),yQ=H(function(Q,$,X){let V=B(Q,$);if(!V)throw new F("not_found",`no such database: ${$}`);return IQ(Q,V,TQ(Q,V.id,X))});function g(Z,Q){let $=Z.query("SELECT id, database_id, data FROM records WHERE id = ? AND __deleted = 0").get(Q);if(!$)return null;return EQ($,x(Z,$.database_id))}function SQ(Z){return Z.replace(/'/g,"''")}function fQ(Z,Q,$={}){let X=x(Z,Q),V=$.filter&&Object.keys($.filter).length?d(X,$.filter).map(({prop:K,value:A})=>({prop:K,value:t(Z,K,A)})):[],Y=V.filter((K)=>CQ(K.value)),W=V.filter((K)=>!CQ(K.value)),J,U=!1;if($.sort){let K=$.sort;if(K.startsWith("-"))U=!0,K=K.slice(1);if(K!=="created"&&K!=="created_hlc"){let A=X.find((M)=>M.id===K);if(!A){let M=X.filter((dQ)=>dQ.name.toLowerCase()===K.toLowerCase());if(M.length>1)throw new F("ambiguous",`sort field "${K}" matches ${M.length} properties; use a property id`);A=M[0]}if(!A)throw new F("not_found",`unknown sort field: ${K}`);J=A}}for(let K of Y)o(Z,Q,K.prop);if(J)o(Z,Q,J);let z=["database_id = ?","__deleted = 0"],j=[Q];for(let K of Y)z.push(`data ->> '${SQ(K.prop.id)}' = ?`),j.push(E1(K.value));let D=$.sort==null,k=J?`data ->> '${SQ(J.id)}'`:"created_hlc",XQ=`SELECT id, database_id, data FROM records WHERE ${z.join(" AND ")} `+(D?"ORDER BY order_key IS NULL, order_key, id":`ORDER BY ${k} ${U?"DESC":"ASC"}, id`);if($.limit!=null&&W.length===0)XQ+=" LIMIT ?",j.push($.limit);let C=Z.query(XQ).all(...j).map((K)=>EQ(K,X));if(W.length){if(C=C.filter((K)=>W.every((A)=>JSON.stringify(K.cells[A.prop.id]??null)===JSON.stringify(A.value))),$.limit!=null)C=C.slice(0,$.limit)}return C}var r4=H(function(Q,$,X,V){if(V!=="before"&&V!=="after")throw new F("invalid_input",`unknown move position: ${V}`);let Y=Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get($);if(!Y)throw new F("not_found",`no such record: ${$}`);let W=Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get(X);if(!W)throw new F("not_found",`no such record: ${X}`);if(Y.database_id!==W.database_id)throw new F("invalid_input","cannot move a record across databases");if($===X)return g(Q,$);m1(Q,Y.database_id);let J=r(Q,Y.database_id).filter((D)=>D.id!==$),U=J.findIndex((D)=>D.id===X);if(U<0)throw new F("not_found",`no such target record: ${X}`);let z=V==="before"?J[U-1]?.order_key??null:J[U].order_key,j=V==="before"?J[U].order_key:J[U+1]?.order_key??null;if(z!==null&&j!==null&&z>=j)w1(Q,Y.database_id),J=r(Q,Y.database_id).filter((D)=>D.id!==$),U=J.findIndex((D)=>D.id===X),z=V==="before"?J[U-1]?.order_key??null:J[U].order_key,j=V==="before"?J[U].order_key:J[U+1]?.order_key??null;return G(Q,"records",$,"order_key",L(z,j)),g(Q,$)}),vQ=H(function(Q,$,X){if(!Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get($))throw new F("not_found",`no such record: ${$}`);for(let{prop:Y,value:W}of X)G(Q,"records",$,Y.id,W);return g(Q,$)}),t4=H(function(Q,$,X){let V=Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get($);if(!V)throw new F("not_found",`no such record: ${$}`);return vQ(Q,$,TQ(Q,V.database_id,X))}),d4=H(function(Q,$){if(!Q.query("SELECT id FROM records WHERE id = ? AND __deleted = 0").get($))return!1;return G(Q,"records",$,"__deleted",1),!0});var u1=["id","name","icon","meta","created_hlc"];var h1=u1.join(", ");function c1(Z){if(!Z)return null;return{...Z,meta:Z.meta===null?null:JSON.parse(Z.meta)}}var l1=H(function(Q,$){let X=_("db",$.name),V=G(Q,"databases",X,"name",$.name);if(G(Q,"databases",X,"created_hlc",V.hlc),$.icon!==void 0)G(Q,"databases",X,"icon",$.icon);return B(Q,X)}),Y8=H(function(Q,$,X){if(!B(Q,$))throw new F("not_found",`no such database: ${$}`);if(X.name!==void 0)G(Q,"databases",$,"name",X.name);if(X.icon!==void 0)G(Q,"databases",$,"icon",X.icon);if(X.meta!==void 0){if(X.meta!==null&&(typeof X.meta!=="object"||Array.isArray(X.meta)))throw new F("invalid_input","meta must be a JSON object or null");G(Q,"databases",$,"meta",X.meta)}return B(Q,$)}),W8=H(function(Q,$,X={}){let V=B(Q,$);if(!V)throw new F("not_found",`no such database: ${$}`);let Y=l1(Q,{name:X.name??V.name,icon:X.icon??V.icon??void 0});if(V.meta!==null){let{collapsed:J,...U}=V.meta;if(Object.keys(U).length)G(Q,"databases",Y.id,"meta",U)}let W=new Map;for(let J of x(Q,$)){let U=J.config?.database===$?{...J.config,database:Y.id}:J.config??void 0,z=qQ(Q,Y.id,{name:J.name,type:J.type,config:U,position:J.position});W.set(J.id,z.id)}for(let J of fQ(Q,$)){let U={};for(let[z,j]of Object.entries(J.cells)){let D=W.get(z);if(D)U[D]=j}yQ(Q,Y.id,U)}return B(Q,Y.id)});function B(Z,Q){return c1(Z.query(`SELECT ${h1} FROM databases WHERE id = ? AND __deleted = 0`).get(Q))}var J8=H(function(Q,$){if(!B(Q,$))return!1;G(Q,"databases",$,"__deleted",1);let X=(V)=>{for(let Y of wQ(Q,V,"database_id",$))G(Q,V,Y,"__deleted",1)};X("properties"),X("records");for(let V of wQ(Q,"documents","database_id",$))G(Q,"documents",V,"database_id",null);return Q.query("DELETE FROM meta WHERE key = 'current_db' AND value = ?").run($),!0});function wQ(Z,Q,$,X){return Z.query(`SELECT id FROM ${Q} WHERE ${$} = ? AND __deleted = 0`).all(X).map((V)=>V.id)}var e=["read","create","update"];function n1(Z){return typeof Z==="string"&&e.includes(Z)}function mQ(Z){let Q=new Map;for(let X of Z){let V=Q.get(X.db)??new Set;for(let Y of X.ops)V.add(Y);Q.set(X.db,V)}let $=[];for(let[X,V]of Q){let Y=e.filter((W)=>V.has(W));if(Y.length)$.push({db:X,ops:Y})}return $.sort((X,V)=>X.db<V.db?-1:X.db>V.db?1:0),{v:1,tables:$}}function uQ(Z){if(typeof Z!=="object"||Z===null||Array.isArray(Z))throw new F("invalid_input","grants must be an object {v:1, tables:[...]}");let Q=Z;if(Q.v!==1)throw new F("invalid_input","grants version must be 1");if(!Array.isArray(Q.tables))throw new F("invalid_input","grants.tables must be an array");let $=[];for(let X of Q.tables){if(typeof X!=="object"||X===null)throw new F("invalid_input","each grant table must be an object {db, ops}");let{db:V,ops:Y}=X;if(typeof V!=="string"||!V)throw new F("invalid_input","grant table `db` must be a database id");if(!Array.isArray(Y)||!Y.every(n1))throw new F("invalid_input",`grant ops must be a subset of ${e.join("|")} (delete is never grantable)`);$.push({db:V,ops:Y})}return mQ($)}function hQ(Z){return JSON.stringify(mQ(Z.tables))}var p1=["id","name","title","created_hlc","visibility","spa","public_grants"];var cQ=p1.join(", "),b1=["id","site_id","path","content_type","encoding","content"];var O8=b1.join(", ");function QQ(Z){let Q=Z.trim().toLowerCase().replace(/[^a-z0-9-]+/g,"-").replace(/^-+|-+$/g,"");if(!Q)throw new F("invalid_input",`invalid site name: ${JSON.stringify(Z)}`);return Q}function i1(Z){let Q=[];for(let $ of Z.split("/")){if($===""||$===".")continue;if($==="..")Q.pop();else Q.push($)}return Q.join("/")}function R(Z,Q){return Z.query(`SELECT ${cQ} FROM sites WHERE id = ? AND __deleted = 0`).get(Q)}function lQ(Z,Q){let $;try{$=QQ(Q)}catch{return null}return Z.query(`SELECT ${cQ} FROM sites WHERE name = ? AND __deleted = 0 ORDER BY created_hlc DESC LIMIT 1`).get($)}function nQ(Z){let Q=atob(Z),$=new Uint8Array(Q.length);for(let X=0;X<Q.length;X++)$[X]=Q.charCodeAt(X);return $}function pQ(Z){if(Z!=="public"&&Z!=="private")throw new F("invalid_input",`visibility must be "public" or "private", got ${JSON.stringify(Z)}`)}var _8=H(function(Q,$){let X=QQ($.name);if(lQ(Q,X))throw new F("conflict",`site name already exists: ${X}`);if($.visibility!==void 0)pQ($.visibility);let V=_("site",X),Y=G(Q,"sites",V,"name",X);if(G(Q,"sites",V,"created_hlc",Y.hlc),$.title!==void 0)G(Q,"sites",V,"title",$.title);if($.visibility!==void 0)G(Q,"sites",V,"visibility",$.visibility);return R(Q,V)}),k8=H(function(Q,$,X){if(!R(Q,$))throw new F("not_found",`no such site: ${$}`);if(X.visibility!==void 0)pQ(X.visibility);if(X.name!==void 0){let V=QQ(X.name),Y=lQ(Q,V);if(Y&&Y.id!==$)throw new F("conflict",`site name already exists: ${V}`);G(Q,"sites",$,"name",V)}if(X.title!==void 0)G(Q,"sites",$,"title",X.title);if(X.visibility!==void 0)G(Q,"sites",$,"visibility",X.visibility);if(X.spa!==void 0)G(Q,"sites",$,"spa",X.spa?1:0);return R(Q,$)}),q8=H(function(Q,$,X){if(!R(Q,$))throw new F("not_found",`no such site: ${$}`);let V=X==null?null:hQ(uQ(X));return G(Q,"sites",$,"public_grants",V),R(Q,$)}),P8=H(function(Q,$){if(!R(Q,$))return!1;let X=Q.query("SELECT id FROM site_files WHERE site_id = ? AND __deleted = 0").all($);for(let V of X)G(Q,"site_files",V.id,"__deleted",1);return G(Q,"sites",$,"__deleted",1),!0});function o1(Z,Q,$){return Z.query("SELECT id FROM site_files WHERE site_id = ? AND path = ? ORDER BY created_hlc LIMIT 1").get(Q,$)?.id??null}var x8=H(function(Q,$,X){let V=o1(Q,$,i1(X));if(!V)return!1;let Y=Q.query("SELECT __deleted AS d FROM site_files WHERE id = ?").get(V);if(!Y||Y.d)return!1;return G(Q,"site_files",V,"__deleted",1),!0});var N=globalThis,O=N.caches,a1="__MH_SW_VERSION__",I=`mh-shell-${a1}`,bQ="mh-api-v1",s1="mh-wasm-v1",rQ=["/","/webui.js","/webui.css","/manifest.webmanifest","/db-worker.js","/mh-runtime.js"],y=3500,r1=12000;function f(Z){return Z.ok&&Z.headers.get("x-mh-unlock")==null}var $Q=null;async function ZQ(){if($Q==null){let Z=await VQ();if(Z==="unknown")return!1;$Q=Z}return $Q==="none"}N.addEventListener("install",(Z)=>{Z.waitUntil((async()=>{try{let Q=await O.open(I);await Promise.allSettled(rQ.map(async($)=>{let X=await fetch($);if(f(X))await Q.put($,X)})),await N.skipWaiting()}catch(Q){try{await(await O.open("mh-debug")).put("/__mh-sw-install-error",new Response(String(Q?.stack??Q)))}catch{}throw Q}})())});N.addEventListener("activate",(Z)=>{Z.waitUntil((async()=>{for(let Q of await O.keys())if(Q.startsWith("mh-shell-")&&Q!==I)await O.delete(Q);await N.clients.claim()})())});function c(Z,Q){return new Promise(($,X)=>{let V=setTimeout(()=>X(Error("sw: network timeout")),Q);fetch(Z).then((Y)=>{clearTimeout(V),$(Y)},(Y)=>{clearTimeout(V),X(Y)})})}async function iQ(Z,Q,$,X){let V=await O.open(Q),Y=X??Z;try{let W=await c(Z,$);if(f(W))await V.put(Y,W.clone());return W}catch(W){let J=await V.match(Y);if(J)return J;throw W}}function t1(Z,Q,$){return new Promise((X,V)=>{let Y=new MessageChannel,W=setTimeout(()=>V(Error("sw: rpc timeout")),r1);Y.port1.onmessage=(J)=>{clearTimeout(W),X(J.data)},Z.postMessage({kind:"mh-rpc",op:Q,args:$},[Y.port2])})}async function h(Z,Q,$){let X=new Set,V=[];if(Z.clientId){let Y=await N.clients.get(Z.clientId);if(Y)V.push(Y)}for(let Y of await N.clients.matchAll({type:"window",includeUncontrolled:!0}))if(!V.some((W)=>W.id===Y.id))V.push(Y);for(let Y of V){if(X.has(Y.id))continue;X.add(Y.id);try{let W=await t1(Y,Q,$);if(!W.ok&&W.error?.code==="unavailable")continue;return W}catch{continue}}return null}var d1={invalid_input:400,not_found:404,ambiguous:400,stale:409,conflict:409,auth:401,network:502};function oQ(Z){if(Z.ok)return new Response(JSON.stringify(Z.result??null),{headers:{"content-type":"application/json","x-mh-source":"replica"}});let Q=Z.error?.code;return new Response(JSON.stringify({error:Z.error?.message??"replica error",code:Q}),{status:Q?d1[Q]??400:502,headers:{"content-type":"application/json","x-mh-source":"replica"}})}async function aQ(Z,Q){let $=Z.request,X=new URL($.url),V=Q??X.pathname,Y=null;if($.method!=="GET"&&($.headers.get("content-type")??"").includes("json"))Y=await $.clone().json().catch(()=>null);if(await ZQ()){let W=l($.method,V,X.searchParams,Y);if(W){let J=await h(Z,W.op,W.args);if(J)return oQ(J)}return new Response(JSON.stringify({error:"no metahub server (bucket-only mode)",code:"network"}),{status:502,headers:{"content-type":"application/json","x-mh-source":"replica"}})}try{let W=$.method==="GET"?await c($,y*2):await fetch($);if($.method==="GET"&&f(W))await(await O.open(bQ)).put($,W.clone());return W}catch(W){let J=l($.method,V,X.searchParams,Y);if(J){let U=await h(Z,J.op,J.args);if(U)return oQ(U)}if($.method==="GET"){let U=await(await O.open(bQ)).match($);if(U)return U}throw W}}async function e1(Z,Q){let $=Q.content_type.includes("text/html"),X=Q.content??"";if(Q.encoding==="blob"){let Y=await tQ(Z,X,Q.content_type);if(!Y)return new Response("blob unavailable offline",{status:404});return new Response(Y.body,{status:Q.status??200,headers:{"content-type":Q.content_type,"x-mh-source":"replica"}})}let V;if(Q.encoding==="utf8")V=$&&!Q.public?UQ(X):X;else V=nQ(X);return new Response(V,{status:Q.status??200,headers:{"content-type":Q.content_type,"x-mh-source":"replica"}})}function Q4(Z,Q){let $=`${JSON.stringify(Z)},${JSON.stringify(Q)}`;return new Response(`<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><script src="/mh-runtime.js"></script></head><body><p style="font:14px system-ui;color:#888;margin:2em">正在从本地副本加载…</p><script>__mhOfflineBootstrap(${$})</script></body></html>`,{headers:{"content-type":"text/html; charset=utf-8","x-mh-source":"bootstrap"}})}async function sQ(Z,Q){let $=Q.pathname.slice(7);if($==="")return null;let X=$.indexOf("/");if(X===-1)return Response.redirect(`${Q.origin}/sites/${$}/`,301);let V=decodeURIComponent($.slice(0,X)),Y=decodeURIComponent($.slice(X+1)),W=await h(Z,"siteFile",[V,Y]);if(W?.ok&&W.result)return e1(Z,W.result);if(W?.ok&&W.result==null)return new Response("not found (offline replica)",{status:404});if(Z.request.mode==="navigate")return Q4(V,Y);return null}async function $4(Z){let Q=Z.request,$=new URL(Q.url);if(await ZQ())return await sQ(Z,$)??new Response("not found",{status:404});try{return await c(Q,y)}catch(X){let V=await sQ(Z,$);if(V)return V;throw X}}async function Z4(Z){let Q=Z.request,$=new URL(Q.url),X=decodeURIComponent($.pathname.slice(6)),V=X.indexOf("."),Y=(V>=0?X.slice(0,V):X).toLowerCase();if(!/^[0-9a-f]{16,64}$/.test(Y))return fetch(Q);let W=YQ(X);return await tQ(Z,Y,W,Q)??new Response("blob unavailable offline",{status:404})}async function tQ(Z,Q,$,X){let V=await WQ(Q);if(V)return V;if(!await ZQ())try{let W=X?new Request(X,{cache:"no-store"}):new Request(`${N.location.origin}/blob/${Q}`,{cache:"no-store"}),J=await c(W,y*2);if(J.ok){let U=await J.clone().arrayBuffer();if(await n(U,Q))return await p(Q,U,J.headers.get("content-type")??$),J}}catch{}let Y=await h(Z,"blobBytes",[Q]);if(Y?.ok&&Y.result){let W=Y.result;if(await n(W,Q))return await p(Q,W,$),new Response(W,{headers:{"content-type":$,"x-mh-source":"replica"}})}return null}N.addEventListener("fetch",(Z)=>{let Q=Z.request,$=new URL(Q.url);if($.origin!==N.location.origin)return;if($.pathname.startsWith("/api/")){Z.respondWith(aQ(Z));return}let X=/^\/sites\/[^/]+(\/api\/.*)$/.exec($.pathname);if(X){Z.respondWith(aQ(Z,X[1]));return}if(Q.method!=="GET")return;if($.pathname.startsWith("/sites/")){Z.respondWith($4(Z));return}if($.pathname.startsWith("/blob/")){Z.respondWith(Z4(Z));return}if(Q.mode==="navigate"){if($.pathname!=="/")return;Z.respondWith(iQ(Q,I,y,"/"));return}if(rQ.includes($.pathname)||$.pathname.startsWith("/icons/")){Z.respondWith(iQ(Q,I,y));return}if($.pathname.startsWith("/webui-fmt")){Z.respondWith((async()=>{let V=await O.open(I),Y=await V.match(Q);if(Y)return Y;let W=await fetch(Q);if(f(W))await V.put(Q,W.clone());return W})());return}if($.pathname==="/sqlite3.wasm"){Z.respondWith((async()=>{let V=await O.open(s1),Y=await V.match(Q);if(Y)return Y;let W=await fetch(Q);if(f(W))await V.put(Q,W.clone());return W})());return}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/webui/server/routes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,KAAK,EAAiB,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/webui/server/routes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,KAAK,EAAiB,MAAM,2BAA2B,CAAC;AA8arF,eAAO,MAAM,WAAW,EAAE,KAAK,EA8f9B,CAAC"}
|