@tensorix/metahub 0.4.1 → 0.5.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.
Files changed (47) hide show
  1. package/dist/cli.js +6151 -15068
  2. package/dist/cli.js.map +26 -77
  3. package/dist/core/audit.d.ts +97 -0
  4. package/dist/core/audit.d.ts.map +1 -0
  5. package/dist/core/crdt.d.ts +13 -1
  6. package/dist/core/crdt.d.ts.map +1 -1
  7. package/dist/core/databases.d.ts.map +1 -1
  8. package/dist/core/documents.d.ts +6 -0
  9. package/dist/core/documents.d.ts.map +1 -1
  10. package/dist/core/grants-core.d.ts.map +1 -1
  11. package/dist/core/history.d.ts +31 -0
  12. package/dist/core/history.d.ts.map +1 -1
  13. package/dist/core/indexing.d.ts +1 -1
  14. package/dist/core/integrity.d.ts +1 -1
  15. package/dist/core/integrity.d.ts.map +1 -1
  16. package/dist/core/properties.d.ts +1 -1
  17. package/dist/core/properties.d.ts.map +1 -1
  18. package/dist/core/records.d.ts +5 -0
  19. package/dist/core/records.d.ts.map +1 -1
  20. package/dist/core/relation-cells.d.ts +23 -0
  21. package/dist/core/relation-cells.d.ts.map +1 -0
  22. package/dist/core/resolve.d.ts +4 -0
  23. package/dist/core/resolve.d.ts.map +1 -1
  24. package/dist/core/sync/files.d.ts.map +1 -1
  25. package/dist/core/sync/server.d.ts.map +1 -1
  26. package/dist/core/sync/share-serve.d.ts.map +1 -1
  27. package/dist/db-worker.js +96 -98
  28. package/dist/edge-worker.js +135 -87
  29. package/dist/index.js +11712 -20459
  30. package/dist/index.js.map +18 -71
  31. package/dist/metahub-sdk.js +7 -7
  32. package/dist/mh-runtime.js +1 -1
  33. package/dist/sw.js +7 -7
  34. package/dist/webui/server/assets.d.ts +3 -1
  35. package/dist/webui/server/assets.d.ts.map +1 -1
  36. package/dist/webui/server/changes-route.d.ts +7 -0
  37. package/dist/webui/server/changes-route.d.ts.map +1 -0
  38. package/dist/webui/server/routes.d.ts.map +1 -1
  39. package/dist/webui-fmt-clang.js +1 -1
  40. package/dist/webui-fmt-gofmt.js +1 -1
  41. package/dist/webui-fmt-lua.js +2 -2
  42. package/dist/webui-fmt-ruff.js +2 -2
  43. package/dist/webui-fmt-sh.js +8 -8
  44. package/dist/webui-fmt-taplo.js +2 -2
  45. package/dist/webui-fmt.js +346 -346
  46. package/dist/webui.js +182 -178
  47. package/package.json +1 -1
@@ -1,10 +1,10 @@
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
1
+ class d extends Error{code;constructor(n,e){super(e);this.code=n;this.name="MhError"}}function L(n=6){let e=crypto.getRandomValues(new Uint8Array(n)),t="";for(let r of e)t+="0123456789abcdefghijklmnopqrstuvwxyz".charAt(r%36);return t}function de(n,e="item"){return n.normalize("NFKD").replace(/[^\x20-\x7E]/g,"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,32).replace(/-+$/g,"")||e}var ft=new Set(["db","prop","rec","doc","blk","site","sf","chan"]);function J(n,e,t=n){return`${n}_${de(e,t)}-${L()}`}function z(n){let e=n.indexOf("_");if(e<=0)return null;let t=n.slice(0,e);return ft.has(t)?t:null}var gt=600000;function Ee(n){let e=new Uint8Array(n.byteLength);return e.set(n),e.buffer}function oe(n){let e="";for(let t=0;t<n.length;t++)e+=String.fromCharCode(n[t]);return btoa(e)}function ie(n){let e=atob(n),t=new Uint8Array(e.length);for(let r=0;r<e.length;r++)t[r]=e.charCodeAt(r);return t}async function Re(n,e){let t=await crypto.subtle.importKey("raw",Ee(new TextEncoder().encode(n)),"PBKDF2",!1,["deriveBits"]),r=await crypto.subtle.deriveBits({name:"PBKDF2",salt:Ee(e),iterations:gt,hash:"SHA-256"},t,256);return new Uint8Array(r)}function Se(n,e){if(e<=65535)return{millis:n,counter:e};return{millis:n+Math.floor(e/65536),counter:e%65536}}function ve(n){let{millis:e,counter:t}=Se(n.millis,n.counter);return`${String(e).padStart(15,"0")}-${t.toString(16).padStart(4,"0")}-${n.node}`}function xe(n){let e=n.indexOf("-"),t=n.indexOf("-",e+1);return{millis:Number(n.slice(0,e)),counter:parseInt(n.slice(e+1,t),16),node:n.slice(t+1)}}function yt(n,e){let t=n.query("SELECT value FROM meta WHERE key = 'hlc'").get();return t?xe(t.value):{millis:0,counter:0,node:e}}function mt(n,e){n.query("INSERT INTO meta (key, value) VALUES ('hlc', ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value").run(ve(e))}function ke(n,e,t=Date.now()){let r=yt(n,e),o=Math.max(r.millis,t),i=o===r.millis?r.counter+1:0,a={...Se(o,i),node:e};return mt(n,a),ve(a)}function Ae(n){let e=n.query("SELECT value FROM meta WHERE key = 'node_id'").get();if(e)return e.value;let t=L(8);return n.query("INSERT INTO meta (key, value) VALUES ('node_id', ?)").run(t),t}function Te(n){let e=n.filter((r)=>!!r.text&&r.text.length>0),t=[];return e.forEach((r,o)=>{t.push(...r.text.split(`
2
+ `));let i=Math.max(0,r.blankAfter??0);if(o<e.length-1)t.push("");for(let a=0;a<i;a++)t.push("")}),t.join(`
3
+ `)}var Pe="intent_receipts";var wt=["hlc","node_id","dataset","row_id","col","value","txn"];var kn=wt.join(", "),se=null,Ce=null;var _t=null;function ht(n,e){if(se!==null)return e();se=(Ce?Ce+"/":"")+(n?n+":":"")+L(8);try{return e()}finally{se=null}}function x(n,e=null){return(...t)=>ht(e,()=>n(...t))}var bt={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"])}},Dt=new Set(["database_id","created_hlc","order_key","__deleted"]),Et=new Set([Pe]),Rt=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 Oe(n,e,t){if(t!==null)return JSON.parse(t);return Rt.has(`${n}:${e}`)?0:null}function Ne(n){if(n===null||n===void 0)return null;if(typeof n==="boolean")return n?1:0;if(typeof n==="number")return n;if(typeof n==="string")return n;return JSON.stringify(n)}function ae(n,e,t){n.query(`INSERT OR IGNORE INTO ${e} (id) VALUES (?)`).run(t)}function St(n,e){return n.query("SELECT 1 AS x FROM doc_blocks WHERE doc_id = ? LIMIT 1").get(e)!=null}function vt(n,e){let t=n.query("SELECT text, blank_after FROM doc_blocks WHERE doc_id = ? AND __deleted = 0 ORDER BY order_key, id").all(e);ae(n,"documents",e),n.query("UPDATE documents SET body = ? WHERE id = ?").run(Te(t.map((r)=>({text:r.text,blankAfter:r.blank_after??0}))),e)}function xt(n,e,t,r,o){if(Et.has(e))return;if(e==="records"){if(Dt.has(r)){ae(n,"records",t);let s=Oe("records",r,o);n.query(`UPDATE records SET "${r}" = ? WHERE id = ?`).run(Ne(s),t)}else if(ae(n,"records",t),o===null)n.query(`UPDATE records SET data = json_remove(data, '$."' || ? || '"') WHERE id = ?`).run(r,t);else n.query(`UPDATE records SET data = json_set(coalesce(data, '{}'), '$."' || ? || '"', json(?)) WHERE id = ?`).run(r,o,t);return}let i=bt[e];if(!i||!i.cols.has(r))return;if(e==="documents"&&r==="body"&&St(n,t))return;ae(n,i.table,t);let a=Oe(e,r,o);if(n.query(`UPDATE ${i.table} SET "${r}" = ? WHERE id = ?`).run(Ne(a),t),e==="doc_blocks"){let s=n.query("SELECT doc_id FROM doc_blocks WHERE id = ?").get(t);if(s?.doc_id)vt(n,s.doc_id)}}function kt(n,e){let t=n.query("INSERT OR IGNORE INTO crdt_changes (hlc, node_id, dataset, row_id, col, value, txn) VALUES (?, ?, ?, ?, ?, ?, ?)").run(e.hlc,e.node_id,e.dataset,e.row_id,e.col,e.value,e.txn??null).changes>0;if(n.query("SELECT MAX(hlc) AS h FROM crdt_changes WHERE dataset = ? AND row_id = ? AND col = ?").get(e.dataset,e.row_id,e.col).h!==e.hlc)return{inserted:t,winner:!1};try{xt(n,e.dataset,e.row_id,e.col,e.value)}catch(o){if(t)n.query("DELETE FROM crdt_changes WHERE dataset = ? AND row_id = ? AND col = ? AND hlc = ?").run(e.dataset,e.row_id,e.col,e.hlc);throw o}return{inserted:t,winner:!0}}function y(n,e,t,r,o){let i=_t??Ae(n),a={hlc:ke(n,i),node_id:i,dataset:e,row_id:t,col:r,value:o===void 0?null:JSON.stringify(o),txn:se};return kt(n,a),a}function $e(n){return n.replace(/[^a-zA-Z0-9_]/g,"_")}function Le(n){return n.replace(/'/g,"''")}function Ie(n,e){return`idx_rec_${$e(n)}_${$e(e)}`}function At(n,e,t){return n.query("SELECT 1 AS ok FROM sqlite_master WHERE type = 'index' AND name = ?").get(Ie(e,t))!=null}function ue(n,e,t){let r=Ie(e,t);n.exec(`CREATE INDEX IF NOT EXISTS "${r}" ON records (data ->> '${Le(t)}', created_hlc) WHERE database_id = '${Le(e)}' AND __deleted = 0`)}function pe(n,e,t){if(At(n,e,t.id))return;if(t.type!=="relation"&&t.type!=="doc"){if(n.query("SELECT COUNT(*) AS c FROM records WHERE database_id = ? AND __deleted = 0").get(e).c<2000)return}ue(n,e,t.id)}var Me=new Set(["text","number","checkbox","select","multi_select","date","relation","doc","url"]),Tt=["id","database_id","name","type","config","position"];var Ue=Tt.join(", ");function fe(n,e){if(n==="select"||n==="multi_select"){let t=e?.options;if(!Array.isArray(t)||t.length===0||!t.every((r)=>typeof r==="string"))throw new d("invalid_input",`${n} requires config.options: string[]`)}if(n==="relation"){if(typeof e?.database!=="string")throw new d("invalid_input","relation requires config.database (target database id)")}}function Pt(n,e){return(n.query("SELECT MAX(position) AS m FROM properties WHERE database_id = ? AND __deleted = 0").get(e).m??0)+1}var He=x(function(e,t,r){if(!I(e,t))throw new d("not_found",`no such database: ${t}`);if(!Me.has(r.type))throw new d("invalid_input",`unknown property type: ${r.type}`);fe(r.type,r.config);let o=r.indexed?{...r.config??{},indexed:!0}:r.config??null,i=J("prop",r.name);if(y(e,"properties",i,"database_id",t),y(e,"properties",i,"name",r.name),y(e,"properties",i,"type",r.type),y(e,"properties",i,"config",o),y(e,"properties",i,"position",r.position??Pt(e,t)),r.type==="relation"||r.type==="doc"||r.indexed===!0)ue(e,t,i);return W(e,i)});function W(n,e){let t=n.query(`SELECT ${Ue} FROM properties WHERE id = ? AND __deleted = 0`).get(e);if(!t)return null;return{...t,config:t.config?JSON.parse(t.config):null}}function F(n,e){return n.query(`SELECT ${Ue} FROM properties WHERE database_id = ? AND __deleted = 0 ORDER BY position`).all(e).map((r)=>({...r,config:r.config?JSON.parse(r.config):null}))}var Ln=x(function(e,t,r){let o=W(e,t);if(!o)throw new d("not_found",`no such property: ${t}`);let i=r.type!==void 0&&r.type!==o.type;if(r.type!==void 0&&!Me.has(r.type))throw new d("invalid_input",`unknown property type: ${r.type}`);let a=r.type??o.type,s;if(r.config!==void 0){let c={...o.config??{}};for(let[p,u]of Object.entries(r.config))if(u===null)delete c[p];else c[p]=u;s=c,fe(a,s)}else if(i)fe(r.type,o.config??void 0);if(r.name!==void 0)y(e,"properties",t,"name",r.name);if(r.type!==void 0)y(e,"properties",t,"type",r.type);if(s!==void 0)y(e,"properties",t,"config",s);if(r.position!==void 0)y(e,"properties",t,"position",r.position);if(i){let c=e.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(o.database_id,t);for(let p of c)y(e,"records",p.id,t,null)}return W(e,t)});function Ge(n,e){let t=W(n,e);if(!t)throw new d("not_found",`no such property: ${e}`);if(t.type!=="select"&&t.type!=="multi_select")throw new d("invalid_input",`${t.type} property has no options`);return{prop:t,options:t.config?.options??[]}}var In=x(function(e,t,r,o){let{prop:i,options:a}=Ge(e,t);if(o=o.trim(),!o)throw new d("invalid_input","option name must not be empty");if(!a.includes(r))throw new d("not_found",`no such option: ${r}`);if(o===r)return{property:i,renamed:0};if(a.includes(o))throw new d("conflict",`option already exists: ${o}`);y(e,"properties",t,"config",{...i.config??{},options:a.map((c)=>c===r?o:c)});let s=0;if(i.type==="select"){let c=e.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? = ?").all(i.database_id,t,r);for(let p of c)y(e,"records",p.id,t,o);s=c.length}else{let c=e.query("SELECT id, data ->> ? AS v FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(t,i.database_id,t);for(let p of c){let u=JSON.parse(p.v);if(!Array.isArray(u)||!u.includes(r))continue;y(e,"records",p.id,t,[...new Set(u.map((w)=>w===r?o:w))]),s++}}return{property:W(e,t),renamed:s}}),Mn=x(function(e,t,r){let{prop:o,options:i}=Ge(e,t);if(!i.includes(r))throw new d("not_found",`no such option: ${r}`);if(i.length===1)throw new d("invalid_input","cannot remove the last option; delete the property instead");y(e,"properties",t,"config",{...o.config??{},options:i.filter((s)=>s!==r)});let a=0;if(o.type==="select"){let s=e.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? = ?").all(o.database_id,t,r);for(let c of s)y(e,"records",c.id,t,null);a=s.length}else{let s=e.query("SELECT id, data ->> ? AS v FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(t,o.database_id,t);for(let c of s){let p=JSON.parse(c.v);if(!Array.isArray(p)||!p.includes(r))continue;y(e,"records",c.id,t,p.filter((u)=>u!==r)),a++}}return{property:W(e,t),cleared:a}}),Un=x(function(e,t){let r=W(e,t);if(!r)return!1;y(e,"properties",t,"__deleted",1);let o=e.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(r.database_id,t);for(let i of o)y(e,"records",i.id,t,void 0);return!0});var Ct={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"}},Ot=["db","prop","rec","doc"];function Nt(n){return n!==null&&n!=="blk"}var Ke="{";function Be(n,e){return n.query("SELECT id FROM properties WHERE database_id = ? AND type = 'text' AND __deleted = 0 ORDER BY position LIMIT 1").get(e)?.id??null}function $t(n,e,t,r){let o=Ct[e],i=o.nameCol;if(e==="rec"&&r){let R=Be(n,r);if(R)i=`data ->> '${R.replace(/'/g,"''")}'`}let a=i??"''",s=[],c=[];s.push("(id >= ? AND id < ?)"),c.push(t,t+Ke);let p=`${e}_${t}`;if(s.push("(id >= ? AND id < ?)"),c.push(p,p+Ke),i)s.push(`lower(${i}) = lower(?)`),c.push(t);let u=`SELECT id, ${a} AS label FROM ${o.table} WHERE __deleted = 0 AND (${s.join(" OR ")})`;if(o.scoped&&r)u+=" AND database_id = ?",c.push(r);return n.query(u).all(...c).map((R)=>({kind:e,id:R.id,label:R.label??""}))}function ge(n,e,t={}){let r=t.kind?[t.kind]:Nt(z(e))?[z(e)]:Ot,o=[],i=new Set;for(let a of r)for(let s of $t(n,a,e,t.databaseId)){if(i.has(s.id))continue;i.add(s.id),o.push(s)}return o}function ye(n,e){if(e!==null&&n>=e)throw Error(`fracdex: ${n} >= ${e}`);if(n.endsWith("0")||e!==null&&e.endsWith("0"))throw Error(`fracdex: trailing zero in ${n}/${e}`);if(e!==null){let i=0;while((n[i]??"0")===e[i])i++;if(i>0)return e.slice(0,i)+ye(n.slice(i),e.slice(i))}let r=n===""?0:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".indexOf(n[0]),o=e===null?62:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".indexOf(e[0]);if(o-r>1)return"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[Math.round(0.5*(r+o))];if(e!==null&&e.length>1)return e.slice(0,1);return"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[r]+ye(n.slice(1),null)}function G(n,e){return ye(n??"",e)}function Q(n,e,t){if(t<=0)return[];if(t===1)return[G(n,e)];if(e===null){let i=G(n,null),a=[i];for(let s=1;s<t;s++)i=G(i,null),a.push(i);return a}if(n===null){let i=G(null,e),a=[i];for(let s=1;s<t;s++)i=G(null,i),a.unshift(i);return a}let r=Math.floor(t/2),o=G(n,e);return[...Q(n,o,r),o,...Q(o,e,t-r-1)]}function qe(n){return typeof n==="string"||typeof n==="number"||typeof n==="boolean"}function Lt(n){return typeof n==="boolean"?n?1:0:n}function It(n,e,t){let r=e.config?.database;if(!r)return t;let o=ge(n,t,{kind:"rec",databaseId:r}),i=o.find((a)=>a.id===t);if(i)return i.id;if(o.length===1)return o[0].id;if(o.length===0){if(z(t)==="rec")return t;throw new d("not_found",`${e.name}: no such record in target database: ${t}`)}throw new d("ambiguous",`${e.name}: ambiguous relation "${t}" (${o.length} matches); use a full id`)}function Mt(n,e,t){let r=ge(n,t,{kind:"doc"}),o=r.find((i)=>i.id===t);if(o)return o.id;if(r.length===1)return r[0].id;if(r.length===0){if(z(t)==="doc")return t;throw new d("not_found",`${e.name}: no such document: ${t}`)}throw new d("ambiguous",`${e.name}: ambiguous document "${t}" (${r.length} matches); use a full id`)}function we(n,e,t){switch(e.type){case"text":case"url":case"date":{if(t===null)return null;if(typeof t!=="string")throw new d("invalid_input",`${e.name} expects a string`);return t}case"number":{if(t===null)return null;let r=typeof t==="number"?t:Number(t);if(!Number.isFinite(r))throw new d("invalid_input",`${e.name} expects a number`);return r}case"checkbox":{if(typeof t==="boolean")return t;if(t==="true"||t===1)return!0;if(t==="false"||t===0||t===null)return!1;throw new d("invalid_input",`${e.name} expects a boolean`)}case"select":{if(t===null)return null;let r=String(t);if(!e.config?.options?.includes(r))throw new d("invalid_input",`${e.name}: '${r}' is not an allowed option`);return r}case"multi_select":{let r=t===null?[]:Array.isArray(t)?t:[t],o=e.config?.options??[];for(let i of r)if(!o.includes(String(i)))throw new d("invalid_input",`${e.name}: '${i}' is not an allowed option`);return r.map(String)}case"relation":return(t===null?[]:Array.isArray(t)?t:[t]).map((o)=>It(n,e,String(o)));case"doc":return(t===null?[]:Array.isArray(t)?t:[t]).map((o)=>Mt(n,e,String(o)))}}function Ut(n){let e=new Map;for(let t of n){let r=t.name.toLowerCase(),o=e.get(r);if(o)o.push(t);else e.set(r,[t])}return e}function _e(n,e){let t=new Map(n.map((i)=>[i.id,i])),r=Ut(n),o=[];for(let[i,a]of Object.entries(e)){let s=t.get(i);if(!s){let c=r.get(i.toLowerCase())??[];if(c.length>1)throw new d("ambiguous",`property name "${i}" matches ${c.length} properties; use a property id`);s=c[0]}if(!s)throw new d("not_found",`unknown property: ${i}`);o.push({prop:s,value:a})}return o}function je(n,e,t){return _e(F(n,e),t).map(({prop:r,value:o})=>({prop:r,value:we(n,r,o)}))}function Ve(n,e){let t=JSON.parse(n.data||"{}"),r=new Map(e.map((a)=>[a.id,a])),o={},i={};for(let[a,s]of Object.entries(t)){let c=r.get(a);if(!c)continue;o[c.name]=s,i[c.id]=s}return{id:n.id,database_id:n.database_id,values:o,cells:i}}function Ht(n,e){let t=n.find((r)=>r.prop.type==="text"&&typeof r.value==="string"&&r.value);return J("rec",t?String(t.value):"",e)}function We(n,e){return n.query("SELECT 1 AS ok FROM sqlite_master WHERE type = 'table' AND name = ?").get(e)!=null}function Gt(n){return We(n,"meta")&&We(n,"crdt_changes")}function Kt(n,e,t,r){if(r)y(n,"records",e,"order_key",t);else n.query("UPDATE records SET order_key = ? WHERE id = ?").run(t,e)}function Ye(n,e){return n.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($,Q){return $.query(`SELECT id, database_id, created_hlc, order_key FROM records
5
+ ORDER BY order_key DESC, id DESC LIMIT 1`).get(e)?.order_key??null}function me(n,e){return n.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 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
- 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
7
+ ORDER BY order_key IS NULL, order_key, created_hlc, id`).all(e)}function Bt(n,e){let t=me(n,e),r=Q(null,null,t.length);t.forEach((o,i)=>{if(o.order_key!==r[i])y(n,"records",o.id,"order_key",r[i])})}var qt=x(function(e,t){let r=Gt(e),o=t?[{database_id:t}]:e.query(`SELECT DISTINCT database_id FROM records
8
+ WHERE database_id IS NOT NULL AND __deleted = 0 AND order_key IS NULL`).all();for(let i of o){let a=e.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=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};
10
+ ORDER BY created_hlc, id`).all(i.database_id);if(!a.length)continue;let s=Ye(e,i.database_id),c=Q(s,null,a.length);a.forEach((p,u)=>Kt(e,p.id,c[u],r))}}),Je=x(function(e,t,r){let o=Ht(r,de(t.name,"rec")),i=G(Ye(e,t.id),null),a=y(e,"records",o,"database_id",t.id);y(e,"records",o,"created_hlc",a.hlc),y(e,"records",o,"order_key",i);for(let{prop:s,value:c}of r)y(e,"records",o,s.id,c);return ee(e,o)}),ze=x(function(e,t,r){let o=I(e,t);if(!o)throw new d("not_found",`no such database: ${t}`);return Je(e,o,je(e,o.id,r))});function ee(n,e){let t=n.query("SELECT id, database_id, data FROM records WHERE id = ? AND __deleted = 0").get(e);if(!t)return null;return Ve(t,F(n,t.database_id))}function Fe(n){return n.replace(/'/g,"''")}function Xe(n,e,t={}){let r=F(n,e),o=t.filter&&Object.keys(t.filter).length?_e(r,t.filter).map(({prop:D,value:A})=>({prop:D,value:we(n,D,A)})):[],i=o.filter((D)=>qe(D.value)),a=o.filter((D)=>!qe(D.value)),s,c=!1;if(t.sort){let D=t.sort;if(D.startsWith("-"))c=!0,D=D.slice(1);if(D!=="created"&&D!=="created_hlc"){let A=r.find((M)=>M.id===D);if(!A){let M=r.filter((B)=>B.name.toLowerCase()===D.toLowerCase());if(M.length>1)throw new d("ambiguous",`sort field "${D}" matches ${M.length} properties; use a property id`);A=M[0]}if(!A)throw new d("not_found",`unknown sort field: ${D}`);s=A}}for(let D of i)pe(n,e,D.prop);if(s)pe(n,e,s);let p=["database_id = ?","__deleted = 0"],u=[e];for(let D of i)p.push(`data ->> '${Fe(D.prop.id)}' = ?`),u.push(Lt(D.value));let w=t.sort==null,R=s?`data ->> '${Fe(s.id)}'`:"created_hlc",S=`SELECT id, database_id, data FROM records WHERE ${p.join(" AND ")} `+(w?"ORDER BY order_key IS NULL, order_key, id":`ORDER BY ${R} ${c?"DESC":"ASC"}, id`);if(t.limit!=null&&a.length===0)S+=" LIMIT ?",u.push(t.limit);let T=n.query(S).all(...u).map((D)=>Ve(D,r));if(a.length){if(T=T.filter((D)=>a.every((A)=>JSON.stringify(D.cells[A.prop.id]??null)===JSON.stringify(A.value))),t.limit!=null)T=T.slice(0,t.limit)}return T}var Zn=x(function(e,t,r,o){if(o!=="before"&&o!=="after")throw new d("invalid_input",`unknown move position: ${o}`);let i=e.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get(t);if(!i)throw new d("not_found",`no such record: ${t}`);let a=e.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get(r);if(!a)throw new d("not_found",`no such record: ${r}`);if(i.database_id!==a.database_id)throw new d("invalid_input","cannot move a record across databases");if(t===r)return ee(e,t);qt(e,i.database_id);let s=me(e,i.database_id).filter((w)=>w.id!==t),c=s.findIndex((w)=>w.id===r);if(c<0)throw new d("not_found",`no such target record: ${r}`);let p=o==="before"?s[c-1]?.order_key??null:s[c].order_key,u=o==="before"?s[c].order_key:s[c+1]?.order_key??null;if(p!==null&&u!==null&&p>=u)Bt(e,i.database_id),s=me(e,i.database_id).filter((w)=>w.id!==t),c=s.findIndex((w)=>w.id===r),p=o==="before"?s[c-1]?.order_key??null:s[c].order_key,u=o==="before"?s[c].order_key:s[c+1]?.order_key??null;return y(e,"records",t,"order_key",G(p,u)),ee(e,t)}),Ze=x(function(e,t,r){let o=e.query("SELECT id, database_id, data FROM records WHERE id = ? AND __deleted = 0").get(t);if(!o)throw new d("not_found",`no such record: ${t}`);let i=JSON.parse(o.data||"{}");for(let{prop:a,value:s}of r){let c=Object.hasOwn(i,a.id);if(!(s===void 0?!c:c&&JSON.stringify(s)===JSON.stringify(i[a.id])))y(e,"records",t,a.id,s)}return ee(e,t)}),Qe=x(function(e,t,r){let o=e.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get(t);if(!o)throw new d("not_found",`no such record: ${t}`);return Ze(e,t,je(e,o.database_id,r))}),Qn=x(function(e,t){if(!e.query("SELECT id FROM records WHERE id = ? AND __deleted = 0").get(t))return!1;return y(e,"records",t,"__deleted",1),!0});var Wt=["id","name","icon","meta","created_hlc"];var Ft=Wt.join(", ");function jt(n){if(!n)return null;return{...n,meta:n.meta===null?null:JSON.parse(n.meta)}}var Vt=x(function(e,t){let r=J("db",t.name),o=y(e,"databases",r,"name",t.name);if(y(e,"databases",r,"created_hlc",o.hlc),t.icon!==void 0)y(e,"databases",r,"icon",t.icon);return I(e,r)}),sr=x(function(e,t,r){if(!I(e,t))throw new d("not_found",`no such database: ${t}`);if(r.name!==void 0)y(e,"databases",t,"name",r.name);if(r.icon!==void 0)y(e,"databases",t,"icon",r.icon);if(r.meta!==void 0){if(r.meta!==null&&(typeof r.meta!=="object"||Array.isArray(r.meta)))throw new d("invalid_input","meta must be a JSON object or null");y(e,"databases",t,"meta",r.meta)}return I(e,t)}),ar=x(function(e,t,r={}){let o=I(e,t);if(!o)throw new d("not_found",`no such database: ${t}`);let i=Vt(e,{name:r.name??o.name,icon:r.icon??o.icon??void 0});if(o.meta!==null){let{collapsed:u,...w}=o.meta;if(Object.keys(w).length)y(e,"databases",i.id,"meta",w)}let a=new Map,s=new Set;for(let u of F(e,t)){let w=u.type==="relation"&&u.config?.database===t,R=w?{...u.config,database:i.id}:u.config??void 0,S=He(e,i.id,{name:u.name,type:u.type,config:R,position:u.position});if(a.set(u.id,S.id),w)s.add(S.id)}let c=Xe(e,t),p=new Map;for(let u of c){let w={};for(let[R,S]of Object.entries(u.cells)){let O=a.get(R);if(!O)continue;if(s.has(O)&&Array.isArray(S)&&S.length>0)continue;w[O]=S}p.set(u.id,ze(e,i.id,w).id)}for(let u of c){let w={};for(let[R,S]of Object.entries(u.cells)){let O=a.get(R);if(O&&s.has(O)&&Array.isArray(S)&&S.length>0)w[O]=S.map((T)=>p.get(String(T))??T)}if(Object.keys(w).length)Qe(e,p.get(u.id),w)}return I(e,i.id)});function I(n,e){return jt(n.query(`SELECT ${Ft} FROM databases WHERE id = ? AND __deleted = 0`).get(e))}var cr=x(function(e,t){if(!I(e,t))return!1;y(e,"databases",t,"__deleted",1);let r=(o)=>{for(let i of et(e,o,"database_id",t))y(e,o,i,"__deleted",1)};r("properties"),r("records");for(let o of et(e,"documents","database_id",t))y(e,"documents",o,"database_id",null);return e.query("DELETE FROM meta WHERE key = 'current_db' AND value = ?").run(t),!0});function et(n,e,t,r){return n.query(`SELECT id FROM ${e} WHERE ${t} = ? AND __deleted = 0`).all(r).map((o)=>o.id)}var nt="sealed-p256";var Yt=12,Jt="mh-drop-seal-v1",tt={name:"ECDH",namedCurve:"P-256"};function te(n){let e=new Uint8Array(n.byteLength);return e.set(n),e.buffer}function rt(...n){let e=n.reduce((o,i)=>o+i.byteLength,0),t=new Uint8Array(e),r=0;for(let o of n)t.set(o,r),r+=o.byteLength;return t}async function zt(n,e,t){let r=new Uint8Array(await crypto.subtle.digest("SHA-256",te(t))),o=rt(new TextEncoder().encode(Jt),e,r),i=await crypto.subtle.importKey("raw",n,"HKDF",!1,["deriveKey"]);return crypto.subtle.deriveKey({name:"HKDF",hash:"SHA-256",salt:new Uint8Array(16).buffer,info:te(o)},i,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}async function ot(n,e){let t=await crypto.subtle.importKey("raw",te(n),tt,!1,[]),r=await crypto.subtle.generateKey(tt,!0,["deriveBits"]),o=new Uint8Array(await crypto.subtle.exportKey("raw",r.publicKey)),i=await crypto.subtle.deriveBits({name:"ECDH",public:t},r.privateKey,256),a=await zt(i,o,n),s=crypto.getRandomValues(new Uint8Array(Yt)),c=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:te(s)},a,te(e)));return rt(o,s,c)}var it=/^g[0-9a-z]{8}$/;function Xt(){return"e"+L(16)}function st(){return"g"+L(8)}function Zt(n){return new TextEncoder().encode(JSON.stringify(n))}async function at(n){let e=await ot(n.pk,Zt(n.payload));return{v:1,envelope_id:Xt(),drop_id:n.dropId,enc:nt,key_id:n.keyId,sealed:oe(e),created_at:n.now??Date.now()}}async function he(n,e){return oe(await Re(n,ie(e)))}function ct(){try{if(typeof localStorage<"u"&&localStorage)return localStorage.getItem("mh_drop_probe"),{get:(e)=>localStorage.getItem(e),set:(e,t)=>localStorage.setItem(e,t)}}catch{}let n=new Map;return{get:(e)=>n.get(e)??null,set:(e,t)=>n.set(e,t)}}function Qt(n){if(n===401)return"auth";if(n===404)return"not_found";if(n===429)return"rate_limited";if(n===400||n===413)return"invalid_input";return"network"}async function be(n="mh-drop.json",e={}){let r=await(e.fetcher??fetch)(n);if(!r.ok)throw new d("not_found",`no drop config at ${n}`);let o=await r.json().catch(()=>null);if(!o||o.v!==1||!o.endpoint||!o.drop_id||!o.key_id||!o.pk)throw new d("invalid_input","malformed mh-drop.json");return en(o,r.headers.get("date"),e),ce(o,e)}function en(n,e,t){if(!e)return;let r=Date.parse(e);if(!Number.isFinite(r))return;let o=t.storage??ct(),i="mh_drop_clock:"+n.endpoint.replace(/\/+$/,"");if(o.get(i))return;let a=t.now??(()=>Date.now());o.set(i,String(r-a()))}function ce(n,e={}){let t=e.storage??ct(),r=e.fetcher??fetch,o=e.now??(()=>Date.now()),i=n.endpoint.replace(/\/+$/,""),a="mh_drop_guest",s=t.get("mh_drop_guest");if(!s||!it.test(s))s=st(),t.set("mh_drop_guest",s);let c="mh_drop_clock:"+i,p=Number(t.get(c)??"0")||0,u="mh_drop_hlc:"+s,w=/^(\d+):(\d+)$/.exec(t.get(u)??""),R=w?{millis:Number(w[1]),counter:Number(w[2])}:{millis:0,counter:0};function S(){let f=o()+p,m=Math.max(R.millis,f),h=m===R.millis?R.counter+1:0;return R={millis:m,counter:h},t.set(u,`${m}:${h}`),`${String(m).padStart(15,"0")}-${h.toString(16).padStart(4,"0")}-${s}`}let O="mh_drop_pending:"+n.drop_id;function T(){try{let f=t.get(O),m=f?JSON.parse(f):[];return Array.isArray(m)?m:[]}catch{return[]}}function D(f){t.set(O,JSON.stringify(f))}function A(f){let m=n.databases??[],h=m.find((b)=>b.id===f)??m.find((b)=>b.name.toLowerCase()===f.toLowerCase());if(!h)throw new d("not_found",`"${f}" is not a submittable table on this page`);return h}function M(f,m){let h=f.properties.find((b)=>b.id===m)??f.properties.find((b)=>b.name.toLowerCase()===m.toLowerCase());if(!h)throw new d("not_found",`unknown column: ${m}`);return h}let B=null;function l(){return B??=(async()=>{if(!e.password||!n.password_salt)return null;return he(e.password,n.password_salt)})(),B}async function g(f,m,h={}){let b=A(f),k="rec_"+L(10),v={},P={},N={};for(let[K,q]of Object.entries(m)){let Y=M(b,K);v[Y.id]=q,P[Y.name]=q,N[Y.id]=q??null}let ne=(n.payload_versions??[1]).includes(2),j;if(ne){let K={intentId:"int_"+L(16),action:"createRecord",table:b.id,recordId:k,payload:N,submittedAt:o()+p};j={v:2,guest_node:s,intents:[K]}}else{let K=[],q=(le,Z,pt)=>{K.push({hlc:pt,node_id:s,dataset:"records",row_id:k,col:le,value:Z===void 0||Z===null?null:JSON.stringify(Z)})},Y=S();q("database_id",b.id,Y),q("created_hlc",Y,S());for(let[le,Z]of Object.entries(N))q(le,Z,S());j={v:1,guest_node:s,changes:K}}let V=await at({dropId:n.drop_id,keyId:n.key_id,pk:ie(n.pk),payload:j,now:o()}),U={"content-type":"application/json"},re=await l();if(re)U["x-drop-pass"]=re;if(h.turnstileToken)U["x-turnstile-token"]=h.turnstileToken;let H;try{H=await r(`${i}/v1/inbox/${encodeURIComponent(n.drop_id)}/envelopes`,{method:"POST",headers:U,body:JSON.stringify(V)})}catch(K){throw new d("network",`drop submission failed: ${K.message}`)}let X=await H.json().catch(()=>null);if(!H.ok)throw new d(Qt(H.status),X?.error??`drop submission failed (HTTP ${H.status})`);if(typeof X?.server_time==="number")p=X.server_time-o(),t.set(c,String(p));let De={id:k,database_id:b.id,values:P,cells:v,_pending:!0,envelope_id:V.envelope_id,created_at:o()};return D([...T(),De]),De}function _(f){let m=T();if(!f)return m;let h=A(f).id;return m.filter((b)=>b.database_id===h)}function E(f,m){let h=new Set(f.map((N)=>N.id)),b=T(),k=b.filter((N)=>!h.has(N.id));if(k.length!==b.length)D(k);let v=m?A(m).id:null,P=k.filter((N)=>v===null||N.database_id===v);return[...f,...P]}return{config:n,guest:s,createRecord:g,pending:_,merge:E}}class C extends Error{code;status;constructor(n,e,t){super(n);this.code=e;this.status=t;this.name="MetahubError"}}var lt="mh_token",dt="/auth/token",tn=5000;function nn(n){let e=n??(typeof location<"u"&&location?location.pathname:""),t=/^\/(sites|share|r)\/[^/]+/.exec(e);return t?t[0]:""}function ut(n){let e=n;if(/^https?:\/\//i.test(n))try{e=new URL(n).pathname.replace(/\/+$/,"")}catch{return!1}return/^\/(sites|share|r)\/[^/]+$/.test(e)}function rn(n){if(!n||typeof n!=="object"||Array.isArray(n))return!1;let e=n;return typeof e.id==="string"&&e.id.length>0&&typeof e.name==="string"&&e.name.length>0&&Array.isArray(e.properties)&&e.properties.every((t)=>{if(!t||typeof t!=="object"||Array.isArray(t))return!1;let r=t;return typeof r.id==="string"&&r.id.length>0&&typeof r.name==="string"&&r.name.length>0&&typeof r.type==="string"&&r.type.length>0})}function on(n){if(!n||typeof n!=="object"||Array.isArray(n))throw new C("malformed mh-manifest.json","invalid_input",500);let e=n;if(e.v!==1||e.mode!=="live"&&e.mode!=="static-async"||!Number.isInteger(e.policyRevision)||e.policyRevision<0||e.runtimeEndpoint!==void 0&&typeof e.runtimeEndpoint!=="string"||e.websocketEndpoint!==void 0&&typeof e.websocketEndpoint!=="string"||e.inboxEndpoint!==void 0&&typeof e.inboxEndpoint!=="string"||e.fallback!==void 0&&e.fallback!=="inbox")throw new C("malformed mh-manifest.json","invalid_input",500);if(e.drop!==void 0){let t=e.drop;if(!t||typeof t!=="object"||typeof t.drop_id!=="string"||!t.drop_id||typeof t.key_id!=="string"||!t.key_id||typeof t.pk!=="string"||!t.pk||t.payload_versions!==void 0&&(!Array.isArray(t.payload_versions)||!t.payload_versions.every((r)=>Number.isInteger(r)&&r>0))||t.databases!==void 0&&(!Array.isArray(t.databases)||!t.databases.every(rn))||t.password_salt!==void 0&&(typeof t.password_salt!=="string"||!t.password_salt)||t.turnstile_sitekey!==void 0&&(typeof t.turnstile_sitekey!=="string"||!t.turnstile_sitekey))throw new C("malformed mh-manifest.json drop config","invalid_input",500)}if((e.mode==="static-async"||e.fallback==="inbox")&&(!e.inboxEndpoint||!e.drop))throw new C("inbox deployment is missing endpoint or drop config","invalid_input",500);return e}function sn(n,e){if(!n)return e;if(/^https?:\/\//i.test(n))return n.replace(/\/+$/,"");if(/^https?:\/\//i.test(e))return new URL(n,e.endsWith("/")?e:e+"/").toString().replace(/\/+$/,"");if(n.startsWith("/"))return n.replace(/\/+$/,"");return`${e}/${n}`.replace(/\/+/g,"/").replace(/\/+$/,"")}function an(n={}){let e=(n.baseUrl??nn()).replace(/\/$/,""),t=ut(e),r=n.manifestUrl!==void 0||n.baseUrl===void 0||t,o=n.manifestUrl??`${e}/mh-manifest.json`,i=/^https?:\/\//i.test(e)?new URL(dt,e).toString():dt,a=()=>{if(n.token)return n.token;try{return typeof localStorage<"u"?localStorage.getItem(lt):null}catch{return null}},s=(l)=>{try{localStorage.setItem(lt,l)}catch{}};async function c(l,g,_,E,f={}){let m=(v)=>{let P={...f};if(E!==void 0)P["content-type"]="application/json";if(v)P.authorization=`Bearer ${v}`;return fetch(l+_,{method:g,headers:P,body:E!==void 0?JSON.stringify(E):void 0})},h=a(),b=await m(h);if(b.status===401&&h&&!n.token){let v=await fetch(i,{headers:{authorization:`Bearer ${h}`}}).catch(()=>null),P=v?.ok?await v.json():null;if(P?.token)s(P.token),h=P.token,b=await m(h)}let k=await b.json().catch(()=>null);if(!b.ok||k&&k.error)throw new C(k?.error??`${b.status} ${b.statusText}`,k?.code,b.status);return k}let p=null,u=()=>{if(!r)return Promise.resolve(null);if(p)return p;let l=(async()=>{let g;try{g=await fetch(o,{signal:typeof AbortSignal<"u"&&typeof AbortSignal.timeout==="function"?AbortSignal.timeout(tn):void 0})}catch(_){throw new C(`deployment manifest unavailable: ${_.message}`,"network",0)}if(g.status===404)return null;if(!g.ok)throw new C(`deployment manifest failed (HTTP ${g.status})`,"network",g.status);return on(await g.json().catch(()=>null))})();return p=l,l.catch(()=>{if(p===l)p=null}),l},w=(l)=>{if(l?.mode==="static-async")throw new C("static-async deployment has no live runtime","invalid_input",400);return sn(l?.runtimeEndpoint,e)},R=async(l,g,_,E)=>{let f=await u();return c(w(f),l,g,_,E)},S=(l)=>encodeURIComponent(l),O=()=>"int_"+Math.random().toString(36).slice(2,10)+Date.now().toString(36),T=null,D=(l)=>(T??=(l?.drop&&l.inboxEndpoint?Promise.resolve(ce({...l.drop,v:1,endpoint:l.inboxEndpoint},{password:n.dropPassword})):be(`${e}/mh-drop.json`,{password:n.dropPassword})).catch(()=>null),T),A=null,M=async(l,g)=>{let _={};if(g.turnstileToken)_["x-turnstile-token"]=g.turnstileToken;let E=l?.drop?.password_salt;if(n.dropPassword&&E)A??=he(n.dropPassword,E),_["x-drop-pass"]=await A;return _},B=async(l,g,_,E,f)=>{let m=w(l),h=ut(m),b=h?{$intent:{id:O(),submittedAt:Date.now()},values:E}:E,k=await M(l,f);try{return await c(m,g,_,b,k)}catch(v){if(l===null&&h&&v instanceof C&&(v.status===400||v.status===404))return c(m,g,_,E,k);throw v}};return{listDatabases:()=>R("GET","/api/databases"),createDatabase:(l)=>R("POST","/api/databases",l),listProperties:(l)=>R("GET",`/api/properties?db=${S(l)}`),listRecords:(l,g={})=>{let _=new URLSearchParams({db:l});if(g.sort)_.set("sort",g.sort);if(g.limit!=null)_.set("limit",String(g.limit));return R("GET",`/api/records?${_}`)},getRecord:(l)=>R("GET",`/api/record?id=${S(l)}`),createRecord:async(l,g,_={})=>{let E=await u();if(E?.mode==="static-async"){let f=await D(E);if(!f)throw new C("static-async inbox is unavailable","network",0);return f.createRecord(l,g,_)}try{return await B(E,"POST",`/api/records?db=${S(l)}`,g,_)}catch(f){if(!(f instanceof C?f.status===401:!0))throw f;if(E&&E.fallback!=="inbox")throw f;let h=await D(E);if(!h)throw f;return h.createRecord(l,g,_)}},updateRecord:async(l,g,_={})=>{let E=await u();if(E?.mode==="static-async")throw new C("static-async deployment does not support updateRecord","invalid_input",400);return B(E,"PATCH",`/api/record?id=${S(l)}`,g,_)},deleteRecord:async(l)=>{let g=await u();if(g?.mode==="static-async")throw new C("static-async deployment does not support deleteRecord","invalid_input",400);return c(w(g),"DELETE",`/api/record?id=${S(l)}`)},listDocuments:(l)=>R("GET",l?`/api/documents?db=${S(l)}`:"/api/documents"),getDocument:(l)=>R("GET",`/api/document?id=${S(l)}`),createDocument:(l)=>R("POST","/api/documents",l),updateDocument:(l,g)=>R("PATCH",`/api/document?id=${S(l)}`,g),deleteDocument:(l)=>R("DELETE",`/api/document?id=${S(l)}`),search:(l,g)=>{let _=new URLSearchParams({q:l});if(g!=null)_.set("limit",String(g));return R("GET",`/api/search?${_}`)},onUpdate(l,g={}){let _=!1,E=null,f=null,m=null,h=/(^|\/)r\/[^/]+$/.test(e)?e:null;if(h&&typeof WebSocket<"u"){let b=/^https?:\/\//i.test(h)?new URL(h+"/ws"):new URL(h+"/ws",typeof location<"u"?location.href:"http://localhost"),k=b.toString();b.protocol=b.protocol==="https:"?"wss:":"ws:";let v=0,P=new Set([4401,4403]),N=()=>{_=!0,l({gone:!0})},ne=()=>{if(_)return;let j=!1;E=new WebSocket(b.toString()),E.onopen=()=>{j=!0,m=setTimeout(()=>{v=0},5000)},E.onmessage=(V)=>{try{let U=JSON.parse(String(V.data));if(U?.type==="poke")l({seq:U.seq})}catch{}},E.onerror=()=>{},E.onclose=(V)=>{if(m!=null)clearTimeout(m),m=null;if(_)return;if(P.has(V.code)){N();return}let U=Math.min(30000,1000*2**v++),re=U*0.25*Math.random(),H=()=>{f=setTimeout(ne,U+re)};if(!j&&v>=3)fetch(k).then((X)=>{if(_)return;if(X.status===404)N();else H()}).catch(()=>{if(!_)H()});else H()}};ne()}else if(g.pollMs&&g.pollMs>0)f=setInterval(()=>l({}),g.pollMs);return()=>{if(_=!0,f!=null)clearTimeout(f),clearInterval(f);if(m!=null)clearTimeout(m);try{E?.close()}catch{}}}}}var $r=an();export{C as MetahubError,$r as api,an as createClient,ce as createDrop,nn as detectBase,be as initDrop};
@@ -1 +1 @@
1
- class Q extends Error{code;constructor(q,x){super(q);this.code=x;this.name="BusError"}}class L{ch=null;worker=null;started=!1;leader=!1;nextLocal=0;localPending=new Map;remotePending=new Map;listeners=new Set;start(){if(this.started)return;this.started=!0,this.ch=new BroadcastChannel("mh-replica-bus"),this.ch.onmessage=(x)=>this.onChannel(x.data);let q=navigator.locks;if(q)q.request("mh-replica-leader",()=>{return this.becomeLeader(),new Promise(()=>{})}).catch(()=>{});else this.becomeLeader()}onEvent(q){return this.listeners.add(q),()=>this.listeners.delete(q)}call(q,...x){if(!this.started)this.start();if(this.leader)return this.workerCall(q,x);return this.remoteCall(q,x)}becomeLeader(){if(this.leader)return;this.leader=!0,this.spawnWorker();for(let[q,x]of[...this.remotePending])this.remotePending.delete(q),clearTimeout(x.timer),this.workerCall(x.op,x.args).then(x.resolve,x.reject)}spawnWorker(){if(this.worker)return;this.worker=new Worker("/db-worker.js",{type:"module"}),this.worker.onmessage=(q)=>{let x=q.data;if("id"in x){let y=this.localPending.get(x.id);if(!y)return;if(this.localPending.delete(x.id),x.ok)y.resolve(x.result);else y.reject(new Q(x.error.message,x.error.code));return}this.emit(x),this.ch?.postMessage({kind:"event",event:x})},this.worker.onerror=()=>{let q={event:"status",status:{state:"error",paired:!1,node:null,error:"worker crashed"}};this.emit(q),this.ch?.postMessage({kind:"event",event:q})}}workerCall(q,x){if(!this.worker)this.spawnWorker();let y=++this.nextLocal;return new Promise((z,C)=>{this.localPending.set(y,{resolve:z,reject:C}),this.worker.postMessage({id:y,op:q,args:x})})}remoteCall(q,x){let y=`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`;return new Promise((z,C)=>{let D=setTimeout(()=>{if(this.remotePending.delete(y),this.leader){this.workerCall(q,x).then(z,C);return}C(new Q("replica leader unavailable","network"))},1e4);this.remotePending.set(y,{resolve:z,reject:C,timer:D,op:q,args:x}),this.ch?.postMessage({kind:"req",id:y,op:q,args:x})})}onChannel(q){if(q.kind==="req"){if(!this.leader)return;this.workerCall(q.op,q.args).then((x)=>this.ch?.postMessage({kind:"res",id:q.id,ok:!0,result:x}),(x)=>this.ch?.postMessage({kind:"res",id:q.id,ok:!1,error:{message:x.message,code:x.code}}));return}if(q.kind==="res"){let x=this.remotePending.get(q.id);if(!x)return;if(this.remotePending.delete(q.id),clearTimeout(x.timer),q.ok)x.resolve(q.result);else x.reject(new Q(q.error?.message??"replica error",q.error?.code));return}if(q.kind==="event"&&!this.leader)this.emit(q.event)}emit(q){for(let x of this.listeners)x(q)}stopWorker(){this.worker?.terminate(),this.worker=null,this.localPending.forEach((q)=>q.reject(new Q("replica stopped",void 0))),this.localPending.clear()}}function Z(){let q=globalThis;return q.__mhReplicaBus??=new L}var W='<script src="/mh-runtime.js"></script>';function G(q){let x=q.toLowerCase().indexOf("<head>");if(x>=0)return q.slice(0,x+6)+W+q.slice(x+6);return W+q}var V="mh_token",I="/auth/token",X=globalThis;function H(q){try{localStorage.setItem(V,q)}catch{}document.cookie=`${V}=${encodeURIComponent(q)}; path=/; SameSite=Strict; Max-Age=31536000`}function M(){try{let q=localStorage.getItem(V);if(q)return q}catch{}for(let q of document.cookie.split(";")){let[x,...y]=q.trim().split("=");if(x===V){let z=decodeURIComponent(y.join("="))||null;if(z)H(z);return z}}return null}if(!X.__mhFetchShim){X.__mhFetchShim=!0;let q=window.fetch.bind(window),x=function(y,z){z=z??{};let C=M(),D=null;try{D=new URL(typeof y==="string"||y instanceof URL?String(y):y.url,location.href)}catch{D=null}let S=D!=null&&D.origin===location.origin;if(S&&C){let F=new Headers(z.headers??(typeof y!=="string"&&!(y instanceof URL)?y.headers:void 0));if(!F.has("authorization"))F.set("authorization",`Bearer ${C}`);z.headers=F}return q(y,z).then((F)=>{let A=z.__mhRetried;if(F.status!==401||!S||!C||A)return F;return q(I,{headers:{authorization:`Bearer ${C}`}}).then((J)=>J.ok?J.json():null).then((J)=>{if(!J?.token)return F;H(J.token);let $=new Headers(z.headers);return $.set("authorization",`Bearer ${J.token}`),z.headers=$,z.__mhRetried=!0,q(y,z)}).catch(()=>F)})};window.fetch=x}if("serviceWorker"in navigator&&window.isSecureContext&&!window.metahubDesktop)navigator.serviceWorker.register("/sw.js").catch((q)=>{console.warn("[mh-runtime] service worker registration failed —",q)});function P(){try{return localStorage.getItem("mh_replica")==="1"&&localStorage.getItem("mh_replica_hydrated")==="1"}catch{return!1}}globalThis.__mhOfflineBootstrap=(q,x)=>{let y=(z)=>{let C=document.createElement("p");C.style.cssText="font:14px system-ui;color:#888;margin:2em",C.textContent=z,document.body.replaceChildren(C)};if(!P()||typeof Worker>"u"){y("当前离线,且此浏览器尚未启用本地副本。请先在线打开 Metahub,在设置中开启「离线副本」。");return}(async()=>{try{let z=Z();z.start();let C=await z.call("siteFile",q,x);if(!C){y("离线副本中没有这个页面。");return}if(!C.content_type.includes("text/html")){y("此资源不是页面,无法离线打开。");return}if(C.encoding==="blob"){y("此页面以二进制块存储,无法离线打开。");return}let D=C.encoding==="utf8"?C.content??"":atob(C.content??""),S=C.public?D:G(D);document.open(),document.write(S),document.close()}catch(z){y(`离线加载失败:${z.message}`)}})()};if(!X.__mhSwBridge&&"serviceWorker"in navigator)X.__mhSwBridge=!0,navigator.serviceWorker.addEventListener("message",(q)=>{let x=q.data,y=q.ports?.[0];if(!x||x.kind!=="mh-rpc"||!y||!x.op)return;if(!P()||typeof Worker>"u"){y.postMessage({ok:!1,error:{message:"replica unavailable",code:"unavailable"}});return}let z=Z();z.start(),z.call(x.op,...x.args??[]).then((C)=>y.postMessage({ok:!0,result:C}),(C)=>y.postMessage({ok:!1,error:{message:C.message,code:C.code}}))});
1
+ class l extends Error{code;constructor(e,t){super(e);this.code=t;this.name="BusError"}}class m{ch=null;worker=null;started=!1;leader=!1;nextLocal=0;localPending=new Map;remotePending=new Map;listeners=new Set;start(){if(this.started)return;this.started=!0,this.ch=new BroadcastChannel("mh-replica-bus"),this.ch.onmessage=(t)=>this.onChannel(t.data);let e=navigator.locks;if(e)e.request("mh-replica-leader",()=>(this.becomeLeader(),new Promise(()=>{}))).catch(()=>{});else this.becomeLeader()}onEvent(e){return this.listeners.add(e),()=>this.listeners.delete(e)}call(e,...t){if(!this.started)this.start();if(this.leader)return this.workerCall(e,t);return this.remoteCall(e,t)}becomeLeader(){if(this.leader)return;this.leader=!0,this.spawnWorker();for(let[e,t]of[...this.remotePending])this.remotePending.delete(e),clearTimeout(t.timer),this.workerCall(t.op,t.args).then(t.resolve,t.reject)}spawnWorker(){if(this.worker)return;this.worker=new Worker("/db-worker.js",{type:"module"}),this.worker.onmessage=(e)=>{let t=e.data;if("id"in t){let r=this.localPending.get(t.id);if(!r)return;if(this.localPending.delete(t.id),t.ok)r.resolve(t.result);else r.reject(new l(t.error.message,t.error.code));return}this.emit(t),this.ch?.postMessage({kind:"event",event:t})},this.worker.onerror=()=>{let e={event:"status",status:{state:"error",paired:!1,node:null,error:"worker crashed"}};this.emit(e),this.ch?.postMessage({kind:"event",event:e})}}workerCall(e,t){if(!this.worker)this.spawnWorker();let r=++this.nextLocal;return new Promise((n,s)=>{this.localPending.set(r,{resolve:n,reject:s}),this.worker.postMessage({id:r,op:e,args:t})})}remoteCall(e,t){let r=`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`;return new Promise((n,s)=>{let o=setTimeout(()=>{if(this.remotePending.delete(r),this.leader){this.workerCall(e,t).then(n,s);return}s(new l("replica leader unavailable","network"))},1e4);this.remotePending.set(r,{resolve:n,reject:s,timer:o,op:e,args:t}),this.ch?.postMessage({kind:"req",id:r,op:e,args:t})})}onChannel(e){if(e.kind==="req"){if(!this.leader)return;this.workerCall(e.op,e.args).then((t)=>this.ch?.postMessage({kind:"res",id:e.id,ok:!0,result:t}),(t)=>this.ch?.postMessage({kind:"res",id:e.id,ok:!1,error:{message:t.message,code:t.code}}));return}if(e.kind==="res"){let t=this.remotePending.get(e.id);if(!t)return;if(this.remotePending.delete(e.id),clearTimeout(t.timer),e.ok)t.resolve(e.result);else t.reject(new l(e.error?.message??"replica error",e.error?.code));return}if(e.kind==="event"&&!this.leader)this.emit(e.event)}emit(e){for(let t of this.listeners)t(e)}stopWorker(){this.worker?.terminate(),this.worker=null,this.localPending.forEach((e)=>e.reject(new l("replica stopped",void 0))),this.localPending.clear()}}function h(){let e=globalThis;return e.__mhReplicaBus??=new m}var p='<script src="/mh-runtime.js"></script>';function k(e){let t=e.toLowerCase().indexOf("<head>");if(t>=0)return e.slice(0,t+6)+p+e.slice(t+6);return p+e}var d="mh_token",_="/auth/token",u=globalThis;function f(e){try{localStorage.setItem(d,e)}catch{}document.cookie=`${d}=${encodeURIComponent(e)}; path=/; SameSite=Strict; Max-Age=31536000`}function b(){try{let e=localStorage.getItem(d);if(e)return e}catch{}for(let e of document.cookie.split(";")){let[t,...r]=e.trim().split("=");if(t===d){let n=decodeURIComponent(r.join("="))||null;if(n)f(n);return n}}return null}if(!u.__mhFetchShim){u.__mhFetchShim=!0;let e=window.fetch.bind(window),t=function(r,n){n=n??{};let s=b(),o=null;try{o=new URL(typeof r==="string"||r instanceof URL?String(r):r.url,location.href)}catch{o=null}let c=o!=null&&o.origin===location.origin;if(c&&s){let i=new Headers(n.headers??(typeof r!=="string"&&!(r instanceof URL)?r.headers:void 0));if(!i.has("authorization"))i.set("authorization",`Bearer ${s}`);n.headers=i}return e(r,n).then((i)=>{let w=n.__mhRetried;if(i.status!==401||!c||!s||w)return i;return e(_,{headers:{authorization:`Bearer ${s}`}}).then((a)=>a.ok?a.json():null).then((a)=>{if(!a?.token)return i;f(a.token);let g=new Headers(n.headers);return g.set("authorization",`Bearer ${a.token}`),n.headers=g,n.__mhRetried=!0,e(r,n)}).catch(()=>i)})};window.fetch=t}if("serviceWorker"in navigator&&window.isSecureContext&&!window.metahubDesktop)navigator.serviceWorker.register("/sw.js").catch((e)=>{console.warn("[mh-runtime] service worker registration failed —",e)});function v(){try{return localStorage.getItem("mh_replica")==="1"&&localStorage.getItem("mh_replica_hydrated")==="1"}catch{return!1}}globalThis.__mhOfflineBootstrap=(e,t)=>{let r=(n)=>{let s=document.createElement("p");s.style.cssText="font:14px system-ui;color:#888;margin:2em",s.textContent=n,document.body.replaceChildren(s)};if(!v()||typeof Worker>"u"){r("当前离线,且此浏览器尚未启用本地副本。请先在线打开 Metahub,在设置中开启「离线副本」。");return}(async()=>{try{let n=h();n.start();let s=await n.call("siteFile",e,t);if(!s){r("离线副本中没有这个页面。");return}if(!s.content_type.includes("text/html")){r("此资源不是页面,无法离线打开。");return}if(s.encoding==="blob"){r("此页面以二进制块存储,无法离线打开。");return}let o=s.encoding==="utf8"?s.content??"":atob(s.content??""),c=s.public?o:k(o);document.open(),document.write(c),document.close()}catch(n){r(`离线加载失败:${n.message}`)}})()};if(!u.__mhSwBridge&&"serviceWorker"in navigator)u.__mhSwBridge=!0,navigator.serviceWorker.addEventListener("message",(e)=>{let t=e.data,r=e.ports?.[0];if(!t||t.kind!=="mh-rpc"||!r||!t.op)return;if(!v()||typeof Worker>"u"){r.postMessage({ok:!1,error:{message:"replica unavailable",code:"unavailable"}});return}let n=h();n.start(),n.call(t.op,...t.args??[]).then((s)=>r.postMessage({ok:!0,result:s}),(s)=>r.postMessage({ok:!1,error:{message:s.message,code:s.code}}))});
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=(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
- `));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 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
1
+ function j(n,e,t,r){let i=t.get("id"),o=t.get("db"),s=r??{},a=(c)=>c!=null?Number(c):void 0;switch(`${n} ${e}`){case"GET /api/databases":return{op:"listDatabases",args:[]};case"POST /api/databases":return{op:"createDatabase",args:[s]};case"PATCH /api/database":return i?{op:"updateDatabase",args:[i,s]}:null;case"POST /api/database/duplicate":return i?{op:"duplicateDatabase",args:[i,s]}:null;case"DELETE /api/database":return i?{op:"deleteDatabase",args:[i]}:null;case"GET /api/database/activity":return o?{op:"listDatabaseActivity",args:[o,a(t.get("limit"))]}:null;case"GET /api/audit":return{op:"listAuditEntries",args:[{limit:a(t.get("limit")),before:t.get("before")??void 0,actor:t.get("actor")??void 0}]};case"GET /api/audit/entry":{let c=t.get("txn");return c?{op:"auditEntryDetail",args:[c]}:null}case"POST /api/audit/revert":{let c=t.get("txn");return c?{op:"revertChangeGroup",args:[c]}:null}case"GET /api/properties":return o?{op:"listProperties",args:[o]}:null;case"POST /api/properties":{let{db:c,...d}=s;return c?{op:"addProperty",args:[c,d]}:null}case"PATCH /api/property":return i?{op:"updateProperty",args:[i,s]}:null;case"PATCH /api/property/width":return i?{op:"setPropertyWidth",args:[i,s.width]}:null;case"POST /api/property/option/rename":{let{from:c,to:d}=s;return i?{op:"renameSelectOption",args:[i,c,d]}:null}case"POST /api/property/option/remove":return i?{op:"removeSelectOption",args:[i,s.name]}:null;case"DELETE /api/property":return i?{op:"removeProperty",args:[i]}:null;case"GET /api/property/history":return i?{op:"listPropertyRevisions",args:[i]}:null;case"POST /api/property/revert":return i?{op:"revertProperty",args:[i,s.to]}:null;case"GET /api/records":return o?{op:"listRecords",args:[o,{sort:t.get("sort")??void 0,limit:a(t.get("limit"))}]}:null;case"POST /api/records":return o?{op:"createRecord",args:[o,s]}:null;case"GET /api/record":return i?{op:"getRecord",args:[i]}:null;case"PATCH /api/record":return i?{op:"updateRecord",args:[i,s]}:null;case"PATCH /api/record/order":{let{target:c,where:d}=s;return i&&c?{op:"moveRecord",args:[i,c,d]}:null}case"GET /api/record/history":return i?{op:"listRecordRevisions",args:[i]}:null;case"GET /api/record/at":return i?{op:"recordAtVersion",args:[i,t.get("version")]}:null;case"GET /api/record/field-history":return i?{op:"recordFieldHistory",args:[i,t.get("prop")]}:null;case"POST /api/record/revert":return i?{op:"revertRecord",args:[i,s.to]}:null;case"DELETE /api/record":return i?{op:"deleteRecord",args:[i]}:null;case"GET /api/documents":return{op:"listDocuments",args:[{database_id:t.get("db")??void 0,parent_id:t.get("parent")??void 0}]};case"POST /api/documents":return{op:"createDocument",args:[s]};case"GET /api/document":return i?{op:"getDocument",args:[i]}:null;case"PATCH /api/document":{let{if_match:c,...d}=s;return i?{op:"updateDocument",args:[i,d,c]}:null}case"POST /api/document/duplicate":return i?{op:"duplicateDocument",args:[i,s]}:null;case"PATCH /api/document/move":{let{target:c,where:d}=s;return i&&c?{op:"moveDocument",args:[i,c,d]}:null}case"GET /api/document/history":return i?{op:"listDocumentRevisions",args:[i]}:null;case"GET /api/document/at":return i?{op:"documentAtVersion",args:[i,t.get("version")]}:null;case"POST /api/document/revert":{let{to:c,if_match:d}=s;return i&&c?{op:"revertDocument",args:[i,c,d]}:null}case"DELETE /api/document":return i?{op:"deleteDocument",args:[i]}:null;case"GET /api/nodes":return{op:"nodes",args:[]};case"GET /api/sync/health":return{op:"dataMap",args:[]};case"GET /api/search":{let c=t.get("q");return c?{op:"search",args:[c,a(t.get("limit"))]}:null}case"GET /api/sites":return{op:"listSites",args:[]};case"GET /api/site/files":{let c=t.get("site");return c?{op:"listSiteFiles",args:[c]}:null}case"POST /api/sites":return{op:"createSite",args:[s]};case"PATCH /api/site":return i?{op:"updateSite",args:[i,s]}:null;case"DELETE /api/site":return i?{op:"deleteSite",args:[i]}:null;case"GET /api/site/grants":return i?{op:"getSiteGrants",args:[i]}:null;case"PUT /api/site/grants":return i?{op:"setSiteGrants",args:[i,s]}:null;case"GET /api/site-hosting":return{op:"siteHosting",args:[]};case"PATCH /api/site/channel":{let c=s.id;return c?{op:"revokeSiteChannel",args:[c]}:null}case"DELETE /api/site/file":{let c=t.get("site"),d=t.get("path");return c&&d?{op:"deleteSiteFile",args:[c,d]}:null}case"GET /api/shares":return{op:"listLocalShares",args:[t.get("target")??void 0]};case"POST /api/share":return{op:"createLocalShare",args:[s]};case"DELETE /api/share":case"DELETE /api/share/managed":return t.get("slug")?{op:"revokeLocalShare",args:[t.get("slug")]}:null;default:return null}}function it(n,e){if(n===null)return"unknown";if(n.status>=500)return"unknown";if(n.ok)return e?.ok===!0?"server":"none";return"none"}async function ae(){let n=null,e=null;try{n=await fetch("/health",{cache:"no-store"}),e=n.ok?await n.json().catch(()=>null):null}catch{n=null}return it(n,e)}var ot=Math.floor(167772160);function st(n){if(n instanceof ArrayBuffer)return n;let e=new Uint8Array(n.byteLength);return e.set(n),e.buffer}async function at(n){let e=await crypto.subtle.digest("SHA-256",st(n));return[...new Uint8Array(e)].map((t)=>t.toString(16).padStart(2,"0")).join("")}async function z(n,e){return(await at(n)).slice(0,e.length)===e}var ct={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 ce(n){let e=n.lastIndexOf("."),t=e>=0?n.slice(e+1).toLowerCase():"";return ct[t]??"application/octet-stream"}var H=null;function lt(){if(H)return H;return H=new Promise((n,e)=>{let t=indexedDB.open("mh-blobs",1);t.onupgradeneeded=()=>{let r=t.result;if(!r.objectStoreNames.contains("spool"))r.createObjectStore("spool",{keyPath:"hash"});if(!r.objectStoreNames.contains("meta"))r.createObjectStore("meta",{keyPath:"hash"})},t.onsuccess=()=>n(t.result),t.onerror=()=>e(t.error)}),H}function v(n,e,t){return lt().then((r)=>new Promise((i,o)=>{let s=t(r.transaction(n,e).objectStore(n));s.onsuccess=()=>i(s.result),s.onerror=()=>o(s.error)}))}var F=(n)=>`/blob/${n}`;async function ut(n,e,t){let r=await v("meta","readonly",(o)=>o.get(n)),i={hash:n,size:e,accessed:Date.now(),pinned:r?.pinned??0,content_type:t??r?.content_type};await v("meta","readwrite",(o)=>o.put(i))}async function dt(n){let e=await v("meta","readonly",(t)=>t.get(n));if(!e)return;e.accessed=Date.now(),await v("meta","readwrite",(t)=>t.put(e))}function pt(n){return n.trim().toLowerCase().startsWith("text/html")}async function le(n){let e=await caches.open("mh-blob-v1"),t=await e.match(F(n));if(!t)return;if(pt(t.headers.get("content-type")??"")){await e.delete(F(n)),await v("meta","readwrite",(r)=>r.delete(n)).catch(()=>{});return}return dt(n),t}async function K(n,e,t){await(await caches.open("mh-blob-v1")).put(F(n),new Response(e,{headers:{"content-type":t,"cache-control":"public, max-age=31536000, immutable"}})),await ut(n,e.byteLength,t),await ft()}async function ft(){let n=await v("meta","readonly",(i)=>i.getAll())??[],e=n.reduce((i,o)=>i+o.size,0);if(e<=209715200)return;let t=await caches.open("mh-blob-v1"),r=n.filter((i)=>!i.pinned).sort((i,o)=>i.accessed-o.accessed);for(let i of r){if(e<=ot)break;await t.delete(F(i.hash)),await v("meta","readwrite",(o)=>o.delete(i.hash)),e-=i.size}}var ue='<script src="/mh-runtime.js"></script>';function de(n){let e=n.toLowerCase().indexOf("<head>");if(e>=0)return n.slice(0,e+6)+ue+n.slice(e+6);return ue+n}class u extends Error{code;constructor(n,e){super(e);this.code=n;this.name="MhError"}}function L(n=6){let e=crypto.getRandomValues(new Uint8Array(n)),t="";for(let r of e)t+="0123456789abcdefghijklmnopqrstuvwxyz".charAt(r%36);return t}function Y(n,e="item"){return n.normalize("NFKD").replace(/[^\x20-\x7E]/g,"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,32).replace(/-+$/g,"")||e}var gt=new Set(["db","prop","rec","doc","blk","site","sf","chan"]);function x(n,e,t=n){return`${n}_${Y(e,t)}-${L()}`}function A(n){let e=n.indexOf("_");if(e<=0)return null;let t=n.slice(0,e);return gt.has(t)?t:null}function pe(n){let e=n.query("SELECT value FROM meta WHERE key = 'node_id'").get();if(e)return e.value;let t=L(8);return n.query("INSERT INTO meta (key, value) VALUES ('node_id', ?)").run(t),t}function fe(n,e){if(e<=65535)return{millis:n,counter:e};return{millis:n+Math.floor(e/65536),counter:e%65536}}function ge(n){let{millis:e,counter:t}=fe(n.millis,n.counter);return`${String(e).padStart(15,"0")}-${t.toString(16).padStart(4,"0")}-${n.node}`}function mt(n){let e=n.indexOf("-"),t=n.indexOf("-",e+1);return{millis:Number(n.slice(0,e)),counter:parseInt(n.slice(e+1,t),16),node:n.slice(t+1)}}function ht(n,e){let t=n.query("SELECT value FROM meta WHERE key = 'hlc'").get();return t?mt(t.value):{millis:0,counter:0,node:e}}function wt(n,e){n.query("INSERT INTO meta (key, value) VALUES ('hlc', ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value").run(ge(e))}function me(n,e,t=Date.now()){let r=ht(n,e),i=Math.max(r.millis,t),o=i===r.millis?r.counter+1:0,s={...fe(i,o),node:e};return wt(n,s),ge(s)}function he(n){let e=n.filter((r)=>!!r.text&&r.text.length>0),t=[];return e.forEach((r,i)=>{t.push(...r.text.split(`
2
+ `));let o=Math.max(0,r.blankAfter??0);if(i<e.length-1)t.push("");for(let s=0;s<o;s++)t.push("")}),t.join(`
3
+ `)}var we="intent_receipts";var yt=["hlc","node_id","dataset","row_id","col","value","txn"];var Cn=yt.join(", "),W=null,ye=null;var _t=null;function Ee(n,e){if(W!==null)return e();W=(ye?ye+"/":"")+(n?n+":":"")+L(8);try{return e()}finally{W=null}}function m(n,e=null){return(...t)=>Ee(e,()=>n(...t))}var bt={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"])}},Et=new Set(["database_id","created_hlc","order_key","__deleted"]),Rt=new Set([we]),Dt=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 _e(n,e,t){if(t!==null)return JSON.parse(t);return Dt.has(`${n}:${e}`)?0:null}function be(n){if(n===null||n===void 0)return null;if(typeof n==="boolean")return n?1:0;if(typeof n==="number")return n;if(typeof n==="string")return n;return JSON.stringify(n)}function G(n,e,t){n.query(`INSERT OR IGNORE INTO ${e} (id) VALUES (?)`).run(t)}function St(n,e){return n.query("SELECT 1 AS x FROM doc_blocks WHERE doc_id = ? LIMIT 1").get(e)!=null}function xt(n,e){let t=n.query("SELECT text, blank_after FROM doc_blocks WHERE doc_id = ? AND __deleted = 0 ORDER BY order_key, id").all(e);G(n,"documents",e),n.query("UPDATE documents SET body = ? WHERE id = ?").run(he(t.map((r)=>({text:r.text,blankAfter:r.blank_after??0}))),e)}function vt(n,e,t,r,i){if(Rt.has(e))return;if(e==="records"){if(Et.has(r)){G(n,"records",t);let a=_e("records",r,i);n.query(`UPDATE records SET "${r}" = ? WHERE id = ?`).run(be(a),t)}else if(G(n,"records",t),i===null)n.query(`UPDATE records SET data = json_remove(data, '$."' || ? || '"') WHERE id = ?`).run(r,t);else n.query(`UPDATE records SET data = json_set(coalesce(data, '{}'), '$."' || ? || '"', json(?)) WHERE id = ?`).run(r,i,t);return}let o=bt[e];if(!o||!o.cols.has(r))return;if(e==="documents"&&r==="body"&&St(n,t))return;G(n,o.table,t);let s=_e(e,r,i);if(n.query(`UPDATE ${o.table} SET "${r}" = ? WHERE id = ?`).run(be(s),t),e==="doc_blocks"){let a=n.query("SELECT doc_id FROM doc_blocks WHERE id = ?").get(t);if(a?.doc_id)xt(n,a.doc_id)}}function Tt(n,e){let t=n.query("INSERT OR IGNORE INTO crdt_changes (hlc, node_id, dataset, row_id, col, value, txn) VALUES (?, ?, ?, ?, ?, ?, ?)").run(e.hlc,e.node_id,e.dataset,e.row_id,e.col,e.value,e.txn??null).changes>0;if(n.query("SELECT MAX(hlc) AS h FROM crdt_changes WHERE dataset = ? AND row_id = ? AND col = ?").get(e.dataset,e.row_id,e.col).h!==e.hlc)return{inserted:t,winner:!1};try{vt(n,e.dataset,e.row_id,e.col,e.value)}catch(i){if(t)n.query("DELETE FROM crdt_changes WHERE dataset = ? AND row_id = ? AND col = ? AND hlc = ?").run(e.dataset,e.row_id,e.col,e.hlc);throw i}return{inserted:t,winner:!0}}function p(n,e,t,r,i){let o=_t??pe(n),s={hlc:me(n,o),node_id:o,dataset:e,row_id:t,col:r,value:i===void 0?null:JSON.stringify(i),txn:W};return Tt(n,s),s}function Re(n){return n.replace(/[^a-zA-Z0-9_]/g,"_")}function De(n){return n.replace(/'/g,"''")}function Se(n,e){return`idx_rec_${Re(n)}_${Re(e)}`}function Ot(n,e,t){return n.query("SELECT 1 AS ok FROM sqlite_master WHERE type = 'index' AND name = ?").get(Se(e,t))!=null}function V(n,e,t){let r=Se(e,t);n.exec(`CREATE INDEX IF NOT EXISTS "${r}" ON records (data ->> '${De(t)}', created_hlc) WHERE database_id = '${De(e)}' AND __deleted = 0`)}function J(n,e,t){if(Ot(n,e,t.id))return;if(t.type!=="relation"&&t.type!=="doc"){if(n.query("SELECT COUNT(*) AS c FROM records WHERE database_id = ? AND __deleted = 0").get(e).c<2000)return}V(n,e,t.id)}var xe=new Set(["text","number","checkbox","select","multi_select","date","relation","doc","url"]),At=["id","database_id","name","type","config","position"];var ve=At.join(", ");function X(n,e){if(n==="select"||n==="multi_select"){let t=e?.options;if(!Array.isArray(t)||t.length===0||!t.every((r)=>typeof r==="string"))throw new u("invalid_input",`${n} requires config.options: string[]`)}if(n==="relation"){if(typeof e?.database!=="string")throw new u("invalid_input","relation requires config.database (target database id)")}}function Ct(n,e){return(n.query("SELECT MAX(position) AS m FROM properties WHERE database_id = ? AND __deleted = 0").get(e).m??0)+1}var Te=m(function(e,t,r){if(!y(e,t))throw new u("not_found",`no such database: ${t}`);if(!xe.has(r.type))throw new u("invalid_input",`unknown property type: ${r.type}`);X(r.type,r.config);let i=r.indexed?{...r.config??{},indexed:!0}:r.config??null,o=x("prop",r.name);if(p(e,"properties",o,"database_id",t),p(e,"properties",o,"name",r.name),p(e,"properties",o,"type",r.type),p(e,"properties",o,"config",i),p(e,"properties",o,"position",r.position??Ct(e,t)),r.type==="relation"||r.type==="doc"||r.indexed===!0)V(e,t,o);return T(e,o)});function T(n,e){let t=n.query(`SELECT ${ve} FROM properties WHERE id = ? AND __deleted = 0`).get(e);if(!t)return null;return{...t,config:t.config?JSON.parse(t.config):null}}function O(n,e){return n.query(`SELECT ${ve} FROM properties WHERE database_id = ? AND __deleted = 0 ORDER BY position`).all(e).map((r)=>({...r,config:r.config?JSON.parse(r.config):null}))}var In=m(function(e,t,r){let i=T(e,t);if(!i)throw new u("not_found",`no such property: ${t}`);let o=r.type!==void 0&&r.type!==i.type;if(r.type!==void 0&&!xe.has(r.type))throw new u("invalid_input",`unknown property type: ${r.type}`);let s=r.type??i.type,a;if(r.config!==void 0){let l={...i.config??{}};for(let[c,d]of Object.entries(r.config))if(d===null)delete l[c];else l[c]=d;a=l,X(s,a)}else if(o)X(r.type,i.config??void 0);if(r.name!==void 0)p(e,"properties",t,"name",r.name);if(r.type!==void 0)p(e,"properties",t,"type",r.type);if(a!==void 0)p(e,"properties",t,"config",a);if(r.position!==void 0)p(e,"properties",t,"position",r.position);if(o){let l=e.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(i.database_id,t);for(let c of l)p(e,"records",c.id,t,null)}return T(e,t)});function Oe(n,e){let t=T(n,e);if(!t)throw new u("not_found",`no such property: ${e}`);if(t.type!=="select"&&t.type!=="multi_select")throw new u("invalid_input",`${t.type} property has no options`);return{prop:t,options:t.config?.options??[]}}var Hn=m(function(e,t,r,i){let{prop:o,options:s}=Oe(e,t);if(i=i.trim(),!i)throw new u("invalid_input","option name must not be empty");if(!s.includes(r))throw new u("not_found",`no such option: ${r}`);if(i===r)return{property:o,renamed:0};if(s.includes(i))throw new u("conflict",`option already exists: ${i}`);p(e,"properties",t,"config",{...o.config??{},options:s.map((l)=>l===r?i:l)});let a=0;if(o.type==="select"){let l=e.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? = ?").all(o.database_id,t,r);for(let c of l)p(e,"records",c.id,t,i);a=l.length}else{let l=e.query("SELECT id, data ->> ? AS v FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(t,o.database_id,t);for(let c of l){let d=JSON.parse(c.v);if(!Array.isArray(d)||!d.includes(r))continue;p(e,"records",c.id,t,[...new Set(d.map((f)=>f===r?i:f))]),a++}}return{property:T(e,t),renamed:a}}),Fn=m(function(e,t,r){let{prop:i,options:o}=Oe(e,t);if(!o.includes(r))throw new u("not_found",`no such option: ${r}`);if(o.length===1)throw new u("invalid_input","cannot remove the last option; delete the property instead");p(e,"properties",t,"config",{...i.config??{},options:o.filter((a)=>a!==r)});let s=0;if(i.type==="select"){let a=e.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? = ?").all(i.database_id,t,r);for(let l of a)p(e,"records",l.id,t,null);s=a.length}else{let a=e.query("SELECT id, data ->> ? AS v FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(t,i.database_id,t);for(let l of a){let c=JSON.parse(l.v);if(!Array.isArray(c)||!c.includes(r))continue;p(e,"records",l.id,t,c.filter((d)=>d!==r)),s++}}return{property:T(e,t),cleared:s}}),Wn=m(function(e,t){let r=T(e,t);if(!r)return!1;p(e,"properties",t,"__deleted",1);let i=e.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(r.database_id,t);for(let o of i)p(e,"records",o.id,t,void 0);return!0});var kt={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"}},Lt=["db","prop","rec","doc"];function Pt(n){return n!==null&&n!=="blk"}var Ae="{";function Ce(n,e){return n.query("SELECT id FROM properties WHERE database_id = ? AND type = 'text' AND __deleted = 0 ORDER BY position LIMIT 1").get(e)?.id??null}function Nt(n,e,t,r){let i=kt[e],o=i.nameCol;if(e==="rec"&&r){let h=Ce(n,r);if(h)o=`data ->> '${h.replace(/'/g,"''")}'`}let s=o??"''",a=[],l=[];a.push("(id >= ? AND id < ?)"),l.push(t,t+Ae);let c=`${e}_${t}`;if(a.push("(id >= ? AND id < ?)"),l.push(c,c+Ae),o)a.push(`lower(${o}) = lower(?)`),l.push(t);let d=`SELECT id, ${s} AS label FROM ${i.table} WHERE __deleted = 0 AND (${a.join(" OR ")})`;if(i.scoped&&r)d+=" AND database_id = ?",l.push(r);return n.query(d).all(...l).map((h)=>({kind:e,id:h.id,label:h.label??""}))}function Q(n,e,t={}){let r=t.kind?[t.kind]:Pt(A(e))?[A(e)]:Lt,i=[],o=new Set;for(let s of r)for(let a of Nt(n,s,e,t.databaseId)){if(o.has(a.id))continue;o.add(a.id),i.push(a)}return i}function Z(n,e){if(e!==null&&n>=e)throw Error(`fracdex: ${n} >= ${e}`);if(n.endsWith("0")||e!==null&&e.endsWith("0"))throw Error(`fracdex: trailing zero in ${n}/${e}`);if(e!==null){let o=0;while((n[o]??"0")===e[o])o++;if(o>0)return e.slice(0,o)+Z(n.slice(o),e.slice(o))}let r=n===""?0:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".indexOf(n[0]),i=e===null?62:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".indexOf(e[0]);if(i-r>1)return"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[Math.round(0.5*(r+i))];if(e!==null&&e.length>1)return e.slice(0,1);return"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[r]+Z(n.slice(1),null)}function E(n,e){return Z(n??"",e)}function P(n,e,t){if(t<=0)return[];if(t===1)return[E(n,e)];if(e===null){let o=E(n,null),s=[o];for(let a=1;a<t;a++)o=E(o,null),s.push(o);return s}if(n===null){let o=E(null,e),s=[o];for(let a=1;a<t;a++)o=E(null,o),s.unshift(o);return s}let r=Math.floor(t/2),i=E(n,e);return[...P(n,i,r),i,...P(i,e,t-r-1)]}function ke(n){return typeof n==="string"||typeof n==="number"||typeof n==="boolean"}function Mt(n){return typeof n==="boolean"?n?1:0:n}function $t(n,e,t){let r=e.config?.database;if(!r)return t;let i=Q(n,t,{kind:"rec",databaseId:r}),o=i.find((s)=>s.id===t);if(o)return o.id;if(i.length===1)return i[0].id;if(i.length===0){if(A(t)==="rec")return t;throw new u("not_found",`${e.name}: no such record in target database: ${t}`)}throw new u("ambiguous",`${e.name}: ambiguous relation "${t}" (${i.length} matches); use a full id`)}function Bt(n,e,t){let r=Q(n,t,{kind:"doc"}),i=r.find((o)=>o.id===t);if(i)return i.id;if(r.length===1)return r[0].id;if(r.length===0){if(A(t)==="doc")return t;throw new u("not_found",`${e.name}: no such document: ${t}`)}throw new u("ambiguous",`${e.name}: ambiguous document "${t}" (${r.length} matches); use a full id`)}function te(n,e,t){switch(e.type){case"text":case"url":case"date":{if(t===null)return null;if(typeof t!=="string")throw new u("invalid_input",`${e.name} expects a string`);return t}case"number":{if(t===null)return null;let r=typeof t==="number"?t:Number(t);if(!Number.isFinite(r))throw new u("invalid_input",`${e.name} expects a number`);return r}case"checkbox":{if(typeof t==="boolean")return t;if(t==="true"||t===1)return!0;if(t==="false"||t===0||t===null)return!1;throw new u("invalid_input",`${e.name} expects a boolean`)}case"select":{if(t===null)return null;let r=String(t);if(!e.config?.options?.includes(r))throw new u("invalid_input",`${e.name}: '${r}' is not an allowed option`);return r}case"multi_select":{let r=t===null?[]:Array.isArray(t)?t:[t],i=e.config?.options??[];for(let o of r)if(!i.includes(String(o)))throw new u("invalid_input",`${e.name}: '${o}' is not an allowed option`);return r.map(String)}case"relation":return(t===null?[]:Array.isArray(t)?t:[t]).map((i)=>$t(n,e,String(i)));case"doc":return(t===null?[]:Array.isArray(t)?t:[t]).map((i)=>Bt(n,e,String(i)))}}function It(n){let e=new Map;for(let t of n){let r=t.name.toLowerCase(),i=e.get(r);if(i)i.push(t);else e.set(r,[t])}return e}function ne(n,e){let t=new Map(n.map((o)=>[o.id,o])),r=It(n),i=[];for(let[o,s]of Object.entries(e)){let a=t.get(o);if(!a){let l=r.get(o.toLowerCase())??[];if(l.length>1)throw new u("ambiguous",`property name "${o}" matches ${l.length} properties; use a property id`);a=l[0]}if(!a)throw new u("not_found",`unknown property: ${o}`);i.push({prop:a,value:s})}return i}function Ne(n,e,t){return ne(O(n,e),t).map(({prop:r,value:i})=>({prop:r,value:te(n,r,i)}))}function Me(n,e){let t=JSON.parse(n.data||"{}"),r=new Map(e.map((s)=>[s.id,s])),i={},o={};for(let[s,a]of Object.entries(t)){let l=r.get(s);if(!l)continue;i[l.name]=a,o[l.id]=a}return{id:n.id,database_id:n.database_id,values:i,cells:o}}function Ht(n,e){let t=n.find((r)=>r.prop.type==="text"&&typeof r.value==="string"&&r.value);return x("rec",t?String(t.value):"",e)}function Le(n,e){return n.query("SELECT 1 AS ok FROM sqlite_master WHERE type = 'table' AND name = ?").get(e)!=null}function Ft(n){return Le(n,"meta")&&Le(n,"crdt_changes")}function Wt(n,e,t,r){if(r)p(n,"records",e,"order_key",t);else n.query("UPDATE records SET order_key = ? WHERE id = ?").run(t,e)}function $e(n,e){return n.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 r(Z,Q){return Z.query(`SELECT id, database_id, created_hlc, order_key FROM records
5
+ ORDER BY order_key DESC, id DESC LIMIT 1`).get(e)?.order_key??null}function ee(n,e){return n.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 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
- 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
7
+ ORDER BY order_key IS NULL, order_key, created_hlc, id`).all(e)}function Gt(n,e){let t=ee(n,e),r=P(null,null,t.length);t.forEach((i,o)=>{if(i.order_key!==r[o])p(n,"records",i.id,"order_key",r[o])})}var qt=m(function(e,t){let r=Ft(e),i=t?[{database_id:t}]:e.query(`SELECT DISTINCT database_id FROM records
8
+ WHERE database_id IS NOT NULL AND __deleted = 0 AND order_key IS NULL`).all();for(let o of i){let s=e.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=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}});
10
+ ORDER BY created_hlc, id`).all(o.database_id);if(!s.length)continue;let a=$e(e,o.database_id),l=P(a,null,s.length);s.forEach((c,d)=>Wt(e,c.id,l[d],r))}}),Be=m(function(e,t,r){let i=Ht(r,Y(t.name,"rec")),o=E($e(e,t.id),null),s=p(e,"records",i,"database_id",t.id);p(e,"records",i,"created_hlc",s.hlc),p(e,"records",i,"order_key",o);for(let{prop:a,value:l}of r)p(e,"records",i,a.id,l);return N(e,i)}),Ie=m(function(e,t,r){let i=y(e,t);if(!i)throw new u("not_found",`no such database: ${t}`);return Be(e,i,Ne(e,i.id,r))});function N(n,e){let t=n.query("SELECT id, database_id, data FROM records WHERE id = ? AND __deleted = 0").get(e);if(!t)return null;return Me(t,O(n,t.database_id))}function Pe(n){return n.replace(/'/g,"''")}function He(n,e,t={}){let r=O(n,e),i=t.filter&&Object.keys(t.filter).length?ne(r,t.filter).map(({prop:g,value:b})=>({prop:g,value:te(n,g,b)})):[],o=i.filter((g)=>ke(g.value)),s=i.filter((g)=>!ke(g.value)),a,l=!1;if(t.sort){let g=t.sort;if(g.startsWith("-"))l=!0,g=g.slice(1);if(g!=="created"&&g!=="created_hlc"){let b=r.find((k)=>k.id===g);if(!b){let k=r.filter((rt)=>rt.name.toLowerCase()===g.toLowerCase());if(k.length>1)throw new u("ambiguous",`sort field "${g}" matches ${k.length} properties; use a property id`);b=k[0]}if(!b)throw new u("not_found",`unknown sort field: ${g}`);a=b}}for(let g of o)J(n,e,g.prop);if(a)J(n,e,a);let c=["database_id = ?","__deleted = 0"],d=[e];for(let g of o)c.push(`data ->> '${Pe(g.prop.id)}' = ?`),d.push(Mt(g.value));let f=t.sort==null,h=a?`data ->> '${Pe(a.id)}'`:"created_hlc",w=`SELECT id, database_id, data FROM records WHERE ${c.join(" AND ")} `+(f?"ORDER BY order_key IS NULL, order_key, id":`ORDER BY ${h} ${l?"DESC":"ASC"}, id`);if(t.limit!=null&&s.length===0)w+=" LIMIT ?",d.push(t.limit);let S=n.query(w).all(...d).map((g)=>Me(g,r));if(s.length){if(S=S.filter((g)=>s.every((b)=>JSON.stringify(g.cells[b.prop.id]??null)===JSON.stringify(b.value))),t.limit!=null)S=S.slice(0,t.limit)}return S}var tr=m(function(e,t,r,i){if(i!=="before"&&i!=="after")throw new u("invalid_input",`unknown move position: ${i}`);let o=e.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get(t);if(!o)throw new u("not_found",`no such record: ${t}`);let s=e.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get(r);if(!s)throw new u("not_found",`no such record: ${r}`);if(o.database_id!==s.database_id)throw new u("invalid_input","cannot move a record across databases");if(t===r)return N(e,t);qt(e,o.database_id);let a=ee(e,o.database_id).filter((f)=>f.id!==t),l=a.findIndex((f)=>f.id===r);if(l<0)throw new u("not_found",`no such target record: ${r}`);let c=i==="before"?a[l-1]?.order_key??null:a[l].order_key,d=i==="before"?a[l].order_key:a[l+1]?.order_key??null;if(c!==null&&d!==null&&c>=d)Gt(e,o.database_id),a=ee(e,o.database_id).filter((f)=>f.id!==t),l=a.findIndex((f)=>f.id===r),c=i==="before"?a[l-1]?.order_key??null:a[l].order_key,d=i==="before"?a[l].order_key:a[l+1]?.order_key??null;return p(e,"records",t,"order_key",E(c,d)),N(e,t)}),Fe=m(function(e,t,r){let i=e.query("SELECT id, database_id, data FROM records WHERE id = ? AND __deleted = 0").get(t);if(!i)throw new u("not_found",`no such record: ${t}`);let o=JSON.parse(i.data||"{}");for(let{prop:s,value:a}of r){let l=Object.hasOwn(o,s.id);if(!(a===void 0?!l:l&&JSON.stringify(a)===JSON.stringify(o[s.id])))p(e,"records",t,s.id,a)}return N(e,t)}),We=m(function(e,t,r){let i=e.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get(t);if(!i)throw new u("not_found",`no such record: ${t}`);return Fe(e,t,Ne(e,i.database_id,r))}),nr=m(function(e,t){if(!e.query("SELECT id FROM records WHERE id = ? AND __deleted = 0").get(t))return!1;return p(e,"records",t,"__deleted",1),!0});var Ut=["id","name","icon","meta","created_hlc"];var jt=Ut.join(", ");function zt(n){if(!n)return null;return{...n,meta:n.meta===null?null:JSON.parse(n.meta)}}var Kt=m(function(e,t){let r=x("db",t.name),i=p(e,"databases",r,"name",t.name);if(p(e,"databases",r,"created_hlc",i.hlc),t.icon!==void 0)p(e,"databases",r,"icon",t.icon);return y(e,r)}),lr=m(function(e,t,r){if(!y(e,t))throw new u("not_found",`no such database: ${t}`);if(r.name!==void 0)p(e,"databases",t,"name",r.name);if(r.icon!==void 0)p(e,"databases",t,"icon",r.icon);if(r.meta!==void 0){if(r.meta!==null&&(typeof r.meta!=="object"||Array.isArray(r.meta)))throw new u("invalid_input","meta must be a JSON object or null");p(e,"databases",t,"meta",r.meta)}return y(e,t)}),ur=m(function(e,t,r={}){let i=y(e,t);if(!i)throw new u("not_found",`no such database: ${t}`);let o=Kt(e,{name:r.name??i.name,icon:r.icon??i.icon??void 0});if(i.meta!==null){let{collapsed:d,...f}=i.meta;if(Object.keys(f).length)p(e,"databases",o.id,"meta",f)}let s=new Map,a=new Set;for(let d of O(e,t)){let f=d.type==="relation"&&d.config?.database===t,h=f?{...d.config,database:o.id}:d.config??void 0,w=Te(e,o.id,{name:d.name,type:d.type,config:h,position:d.position});if(s.set(d.id,w.id),f)a.add(w.id)}let l=He(e,t),c=new Map;for(let d of l){let f={};for(let[h,w]of Object.entries(d.cells)){let D=s.get(h);if(!D)continue;if(a.has(D)&&Array.isArray(w)&&w.length>0)continue;f[D]=w}c.set(d.id,Ie(e,o.id,f).id)}for(let d of l){let f={};for(let[h,w]of Object.entries(d.cells)){let D=s.get(h);if(D&&a.has(D)&&Array.isArray(w)&&w.length>0)f[D]=w.map((S)=>c.get(String(S))??S)}if(Object.keys(f).length)We(e,c.get(d.id),f)}return y(e,o.id)});function y(n,e){return zt(n.query(`SELECT ${jt} FROM databases WHERE id = ? AND __deleted = 0`).get(e))}var dr=m(function(e,t){if(!y(e,t))return!1;p(e,"databases",t,"__deleted",1);let r=(i)=>{for(let o of Ge(e,i,"database_id",t))p(e,i,o,"__deleted",1)};r("properties"),r("records");for(let i of Ge(e,"documents","database_id",t))p(e,"documents",i,"database_id",null);return e.query("DELETE FROM meta WHERE key = 'current_db' AND value = ?").run(t),!0});function Ge(n,e,t,r){return n.query(`SELECT id FROM ${e} WHERE ${t} = ? AND __deleted = 0`).all(r).map((i)=>i.id)}var re=["read","create","update"];function Yt(n){return typeof n==="string"&&re.includes(n)}function qe(n){let e=new Map;for(let r of n){let i=e.get(r.db)??new Set;for(let o of r.ops)i.add(o);e.set(r.db,i)}let t=[];for(let[r,i]of e){let o=re.filter((s)=>i.has(s));if(o.length)t.push({db:r,ops:o})}return t.sort((r,i)=>r.db<i.db?-1:r.db>i.db?1:0),{v:1,tables:t}}function Ue(n){if(typeof n!=="object"||n===null||Array.isArray(n))throw new u("invalid_input","grants must be an object {v:1, tables:[...]}");let e=n;if(e.v!==1)throw new u("invalid_input","grants version must be 1");if(!Array.isArray(e.tables))throw new u("invalid_input","grants.tables must be an array");let t=[];for(let r of e.tables){if(typeof r!=="object"||r===null)throw new u("invalid_input","each grant table must be an object {db, ops}");let{db:i,ops:o}=r;if(typeof i!=="string"||!i)throw new u("invalid_input","grant table `db` must be a database id");if(!Array.isArray(o)||!o.every(Yt))throw new u("invalid_input",`grant ops must be a subset of ${re.join("|")} (delete is never grantable)`);t.push({db:i,ops:o})}return qe(t)}function je(n){return JSON.stringify(qe(n.tables))}var Vt=["id","name","title","created_hlc","visibility","spa","public_grants"];var ze=Vt.join(", "),Jt=["id","site_id","path","content_type","encoding","content"];var Sr=Jt.join(", ");function ie(n){let e=n.trim().toLowerCase().replace(/[^a-z0-9-]+/g,"-").replace(/^-+|-+$/g,"");if(!e)throw new u("invalid_input",`invalid site name: ${JSON.stringify(n)}`);return e}function Xt(n){let e=[];for(let t of n.split("/")){if(t===""||t===".")continue;if(t==="..")e.pop();else e.push(t)}return e.join("/")}function C(n,e){return n.query(`SELECT ${ze} FROM sites WHERE id = ? AND __deleted = 0`).get(e)}function Ke(n,e){let t;try{t=ie(e)}catch{return null}return n.query(`SELECT ${ze} FROM sites WHERE name = ? AND __deleted = 0 ORDER BY created_hlc DESC LIMIT 1`).get(t)}function Ye(n){let e=atob(n),t=new Uint8Array(e.length);for(let r=0;r<e.length;r++)t[r]=e.charCodeAt(r);return t}function Ve(n){if(n!=="public"&&n!=="private")throw new u("invalid_input",`visibility must be "public" or "private", got ${JSON.stringify(n)}`)}var xr=m(function(e,t){let r=ie(t.name);if(Ke(e,r))throw new u("conflict",`site name already exists: ${r}`);if(t.visibility!==void 0)Ve(t.visibility);let i=x("site",r),o=p(e,"sites",i,"name",r);if(p(e,"sites",i,"created_hlc",o.hlc),t.title!==void 0)p(e,"sites",i,"title",t.title);if(t.visibility!==void 0)p(e,"sites",i,"visibility",t.visibility);return C(e,i)}),vr=m(function(e,t,r){if(!C(e,t))throw new u("not_found",`no such site: ${t}`);if(r.visibility!==void 0)Ve(r.visibility);if(r.name!==void 0){let i=ie(r.name),o=Ke(e,i);if(o&&o.id!==t)throw new u("conflict",`site name already exists: ${i}`);p(e,"sites",t,"name",i)}if(r.title!==void 0)p(e,"sites",t,"title",r.title);if(r.visibility!==void 0)p(e,"sites",t,"visibility",r.visibility);if(r.spa!==void 0)p(e,"sites",t,"spa",r.spa?1:0);return C(e,t)}),Tr=m(function(e,t,r){if(!C(e,t))throw new u("not_found",`no such site: ${t}`);let i=r==null?null:je(Ue(r));return p(e,"sites",t,"public_grants",i),C(e,t)}),Or=m(function(e,t){if(!C(e,t))return!1;let r=e.query("SELECT id FROM site_files WHERE site_id = ? AND __deleted = 0").all(t);for(let i of r)p(e,"site_files",i.id,"__deleted",1);return p(e,"sites",t,"__deleted",1),!0});function Qt(n,e,t){return n.query("SELECT id FROM site_files WHERE site_id = ? AND path = ? ORDER BY created_hlc LIMIT 1").get(e,t)?.id??null}var Ar=m(function(e,t,r){let i=Qt(e,t,Xt(r));if(!i)return!1;let o=e.query("SELECT __deleted AS d FROM site_files WHERE id = ?").get(i);if(!o||o.d)return!1;return p(e,"site_files",i,"__deleted",1),!0});var _=globalThis,R=_.caches,Zt="__MH_SW_VERSION__",M=`mh-shell-${Zt}`,Je="mh-api-v1",en="mh-wasm-v1",tt=["/","/webui.js","/webui.css","/manifest.webmanifest","/db-worker.js","/mh-runtime.js"],B=3500,tn=12000;function I(n){return n.ok&&n.headers.get("x-mh-unlock")==null}var oe=null;async function se(){if(oe==null){let n=await ae();if(n==="unknown")return!1;oe=n}return oe==="none"}_.addEventListener("install",(n)=>{n.waitUntil((async()=>{try{let e=await R.open(M);await Promise.allSettled(tt.map(async(t)=>{let r=await fetch(t);if(I(r))await e.put(t,r)})),await _.skipWaiting()}catch(e){try{await(await R.open("mh-debug")).put("/__mh-sw-install-error",new Response(String(e?.stack??e)))}catch{}throw e}})())});_.addEventListener("activate",(n)=>{n.waitUntil((async()=>{for(let e of await R.keys())if(e.startsWith("mh-shell-")&&e!==M)await R.delete(e);await _.clients.claim()})())});function U(n,e){return new Promise((t,r)=>{let i=setTimeout(()=>r(Error("sw: network timeout")),e);fetch(n).then((o)=>{clearTimeout(i),t(o)},(o)=>{clearTimeout(i),r(o)})})}async function Xe(n,e,t,r){let i=await R.open(e),o=r??n;try{let s=await U(n,t);if(I(s))await i.put(o,s.clone());return s}catch(s){let a=await i.match(o);if(a)return a;throw s}}function nn(n,e,t){return new Promise((r,i)=>{let o=new MessageChannel,s=setTimeout(()=>i(Error("sw: rpc timeout")),tn);o.port1.onmessage=(a)=>{clearTimeout(s),r(a.data)},n.postMessage({kind:"mh-rpc",op:e,args:t},[o.port2])})}async function q(n,e,t){let r=new Set,i=[];if(n.clientId){let o=await _.clients.get(n.clientId);if(o)i.push(o)}for(let o of await _.clients.matchAll({type:"window",includeUncontrolled:!0}))if(!i.some((s)=>s.id===o.id))i.push(o);for(let o of i){if(r.has(o.id))continue;r.add(o.id);try{let s=await nn(o,e,t);if(!s.ok&&s.error?.code==="unavailable")continue;return s}catch{continue}}return null}var rn={invalid_input:400,not_found:404,ambiguous:400,stale:409,conflict:409,auth:401,network:502};function Qe(n){if(n.ok)return new Response(JSON.stringify(n.result??null),{headers:{"content-type":"application/json","x-mh-source":"replica"}});let e=n.error?.code;return new Response(JSON.stringify({error:n.error?.message??"replica error",code:e}),{status:e?rn[e]??400:502,headers:{"content-type":"application/json","x-mh-source":"replica"}})}async function Ze(n,e){let t=n.request,r=new URL(t.url),i=e??r.pathname,o=null;if(t.method!=="GET"&&(t.headers.get("content-type")??"").includes("json"))o=await t.clone().json().catch(()=>null);if(await se()){let s=j(t.method,i,r.searchParams,o);if(s){let a=await q(n,s.op,s.args);if(a)return Qe(a)}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 s=t.method==="GET"?await U(t,B*2):await fetch(t);if(t.method==="GET"&&I(s))await(await R.open(Je)).put(t,s.clone());return s}catch(s){let a=j(t.method,i,r.searchParams,o);if(a){let l=await q(n,a.op,a.args);if(l)return Qe(l)}if(t.method==="GET"){let l=await(await R.open(Je)).match(t);if(l)return l}throw s}}async function on(n,e){let t=e.content_type.includes("text/html"),r=e.content??"";if(e.encoding==="blob"){let o=await nt(n,r,e.content_type);if(!o)return new Response("blob unavailable offline",{status:404});return new Response(o.body,{status:e.status??200,headers:{"content-type":e.content_type,"x-mh-source":"replica"}})}let i;if(e.encoding==="utf8")i=t&&!e.public?de(r):r;else i=Ye(r);return new Response(i,{status:e.status??200,headers:{"content-type":e.content_type,"x-mh-source":"replica"}})}function sn(n,e){let t=`${JSON.stringify(n)},${JSON.stringify(e)}`;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(${t})</script></body></html>`,{headers:{"content-type":"text/html; charset=utf-8","x-mh-source":"bootstrap"}})}async function et(n,e){let t=e.pathname.slice(7);if(t==="")return null;let r=t.indexOf("/");if(r===-1)return Response.redirect(`${e.origin}/sites/${t}/`,301);let i=decodeURIComponent(t.slice(0,r)),o=decodeURIComponent(t.slice(r+1)),s=await q(n,"siteFile",[i,o]);if(s?.ok&&s.result)return on(n,s.result);if(s?.ok&&s.result==null)return new Response("not found (offline replica)",{status:404});if(n.request.mode==="navigate")return sn(i,o);return null}async function an(n){let e=n.request,t=new URL(e.url);if(await se())return await et(n,t)??new Response("not found",{status:404});try{return await U(e,B)}catch(r){let i=await et(n,t);if(i)return i;throw r}}async function cn(n){let e=n.request,t=new URL(e.url),r=decodeURIComponent(t.pathname.slice(6)),i=r.indexOf("."),o=(i>=0?r.slice(0,i):r).toLowerCase();if(!/^[0-9a-f]{16,64}$/.test(o))return fetch(e);let s=ce(r);return await nt(n,o,s,e)??new Response("blob unavailable offline",{status:404})}async function nt(n,e,t,r){let i=await le(e);if(i)return i;if(!await se())try{let s=r?new Request(r,{cache:"no-store"}):new Request(`${_.location.origin}/blob/${e}`,{cache:"no-store"}),a=await U(s,B*2);if(a.ok){let l=await a.clone().arrayBuffer();if(await z(l,e))return await K(e,l,a.headers.get("content-type")??t),a}}catch{}let o=await q(n,"blobBytes",[e]);if(o?.ok&&o.result){let s=o.result;if(await z(s,e))return await K(e,s,t),new Response(s,{headers:{"content-type":t,"x-mh-source":"replica"}})}return null}_.addEventListener("fetch",(n)=>{let e=n.request,t=new URL(e.url);if(t.origin!==_.location.origin)return;if(t.pathname==="/api/changes")return;if(t.pathname.startsWith("/api/")){n.respondWith(Ze(n));return}let r=/^\/sites\/[^/]+(\/api\/.*)$/.exec(t.pathname);if(r){n.respondWith(Ze(n,r[1]));return}if(e.method!=="GET")return;if(t.pathname.startsWith("/sites/")){n.respondWith(an(n));return}if(t.pathname.startsWith("/blob/")){n.respondWith(cn(n));return}if(e.mode==="navigate"){if(t.pathname!=="/")return;n.respondWith(Xe(e,M,B,"/"));return}if(tt.includes(t.pathname)||t.pathname.startsWith("/icons/")){n.respondWith(Xe(e,M,B));return}if(t.pathname.startsWith("/webui-fmt")){n.respondWith((async()=>{let i=await R.open(M),o=await i.match(e);if(o)return o;let s=await fetch(e);if(I(s))await i.put(e,s.clone());return s})());return}if(t.pathname==="/sqlite3.wasm"){n.respondWith((async()=>{let i=await R.open(en),o=await i.match(e);if(o)return o;let s=await fetch(e);if(I(s))await i.put(e,s.clone());return s})());return}});
@@ -4,7 +4,9 @@ export declare function setWebuiBundle(bundle: {
4
4
  dbWorker: string;
5
5
  runtime: string;
6
6
  sdk: string;
7
- wasm: Uint8Array;
7
+ /** sqlite3.wasm bytes, or a loader resolved on the first /sqlite3.wasm
8
+ * request — lets embedders keep the ~1MB read off their startup path. */
9
+ wasm: Uint8Array | (() => Promise<Uint8Array>);
8
10
  /** Lazy 格式化 provider assets keyed by serve route (fmt/manifest.ts).
9
11
  * Optional so embedders built before a provider existed keep working — a
10
12
  * missing asset 500s only when that language's 格式化 is actually used. */
@@ -1 +1 @@
1
- {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../../src/webui/server/assets.ts"],"names":[],"mappings":"AAiFA,wBAAgB,cAAc,CAAC,MAAM,EAAE;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,UAAU,CAAC;IACjB;;6EAEyE;IACzE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACtC,GAAG,IAAI,CAaP;AAsKD;;;;2EAI2E;AAC3E,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAM/C;AAUD;0CAC0C;AAC1C,wBAAsB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CA6DvE"}
1
+ {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../../src/webui/server/assets.ts"],"names":[],"mappings":"AAoFA,wBAAgB,cAAc,CAAC,MAAM,EAAE;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ;8EAC0E;IAC1E,IAAI,EAAE,UAAU,GAAG,CAAC,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IAC/C;;6EAEyE;IACzE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACtC,GAAG,IAAI,CAmBP;AAsLD;;;;2EAI2E;AAC3E,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAM/C;AA6BD;0CAC0C;AAC1C,wBAAsB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CA6DvE"}
@@ -0,0 +1,7 @@
1
+ import type { Route } from "../../core/sync/routes.ts";
2
+ /** Test hook: live subscriber count for a DB (0 = poller torn down). */
3
+ export declare function activeSubscribers(db: object): number;
4
+ /** Test hook: run one poll tick now instead of waiting out POLL_MS. */
5
+ export declare function pokeNow(db: object): void;
6
+ export declare const changesRoutes: Route[];
7
+ //# sourceMappingURL=changes-route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changes-route.d.ts","sourceRoot":"","sources":["../../../src/webui/server/changes-route.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAY,MAAM,2BAA2B,CAAC;AA8GjE,wEAAwE;AACxE,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,uEAAuE;AACvE,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAGxC;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,EA0DhC,CAAC"}
@@ -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;AA8arF,eAAO,MAAM,WAAW,EAAE,KAAK,EA8f9B,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;AAmerF,eAAO,MAAM,WAAW,EAAE,KAAK,EA8hB9B,CAAC"}