@tensorix/metahub 0.4.0 → 0.5.0

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