@tensorix/metahub 0.5.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +5743 -14958
- package/dist/cli.js.map +20 -74
- package/dist/core/audit.d.ts.map +1 -1
- package/dist/core/blobs-core.d.ts.map +1 -1
- package/dist/core/crdt.d.ts.map +1 -1
- package/dist/core/db.d.ts +1 -1
- package/dist/core/db.d.ts.map +1 -1
- package/dist/core/integrity.d.ts +5 -0
- package/dist/core/integrity.d.ts.map +1 -1
- package/dist/core/node.d.ts +52 -6
- package/dist/core/node.d.ts.map +1 -1
- package/dist/core/schema-init.d.ts +3 -0
- package/dist/core/schema-init.d.ts.map +1 -1
- package/dist/core/schema.d.ts +1 -1
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/snapshot.d.ts.map +1 -1
- package/dist/core/sync/devices.d.ts +6 -0
- package/dist/core/sync/devices.d.ts.map +1 -1
- package/dist/core/sync/peers-routes.d.ts.map +1 -1
- package/dist/core/sync/peers.d.ts +2 -0
- package/dist/core/sync/peers.d.ts.map +1 -1
- package/dist/core/sync/server.d.ts.map +1 -1
- package/dist/core/sync/storage.d.ts +4 -0
- package/dist/core/sync/storage.d.ts.map +1 -1
- package/dist/core/tables.d.ts +16 -0
- package/dist/core/tables.d.ts.map +1 -0
- package/dist/db-worker.js +112 -100
- package/dist/edge-worker.js +96 -68
- package/dist/index.js +2797 -12021
- package/dist/index.js.map +17 -71
- package/dist/metahub-sdk.js +5 -5
- package/dist/sw.js +5 -5
- package/dist/webui/server/routes.d.ts.map +1 -1
- package/dist/webui-fmt-clang.js +1 -1
- package/dist/webui-fmt-sh.js +5 -5
- package/dist/webui-fmt.js +113 -113
- package/dist/webui.js +138 -137
- package/package.json +1 -1
package/dist/metahub-sdk.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
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
|
|
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 gt=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 gt.has(t)?t:null}var mt=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:mt,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 xe(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 ve(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?ve(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(xe(e))}function Ae(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 wt(n,a),xe(a)}function ke(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 Pe(n){let e=n.filter((r)=>!!r.text&&r.text.length>0),t=[];return e.forEach((r,o)=>{t.push(...r.text.split(`
|
|
2
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
|
|
3
|
+
`)}var Ce="intent_receipts";var _t=["hlc","node_id","dataset","row_id","col","value","txn"];var kn=_t.join(", "),se=null,Oe=null;var ht=null;function Te(n,e){if(se!==null)return e();se=(Oe?Oe+"/":"")+(n?n+":":"")+L(8);try{return e()}finally{se=null}}function v(n,e=null){return(...t)=>Te(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"])},nodes:{table:"nodes",cols:new Set(["label","platform","form","app","first_seen","__deleted"])}},Dt=new Set(["database_id","created_hlc","order_key","__deleted"]),Et=new Set([Ce]),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","nodes:__deleted"]);function Ne(n,e,t){if(t!==null)return JSON.parse(t);return Rt.has(`${n}:${e}`)?0:null}function $e(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 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);ae(n,"documents",e),n.query("UPDATE documents SET body = ? WHERE id = ?").run(Pe(t.map((r)=>({text:r.text,blankAfter:r.blank_after??0}))),e)}function vt(n,e,t,r,o){if(Et.has(e))return;if(e==="records"){if(Dt.has(r)){ae(n,"records",t);let s=Ne("records",r,o);n.query(`UPDATE records SET "${r}" = ? WHERE id = ?`).run($e(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=Ne(e,r,o);if(n.query(`UPDATE ${i.table} SET "${r}" = ? WHERE id = ?`).run($e(a),t),e==="doc_blocks"){let s=n.query("SELECT doc_id FROM doc_blocks WHERE id = ?").get(t);if(s?.doc_id)xt(n,s.doc_id)}}function At(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(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 m(n,e,t,r,o){let i=ht??ke(n),a={hlc:Ae(n,i),node_id:i,dataset:e,row_id:t,col:r,value:o===void 0?null:JSON.stringify(o),txn:se};return At(n,a),a}function Le(n){return n.replace(/[^a-zA-Z0-9_]/g,"_")}function Me(n){return n.replace(/'/g,"''")}function Ie(n,e){return`idx_rec_${Le(n)}_${Le(e)}`}function kt(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 ->> '${Me(t)}', created_hlc) WHERE database_id = '${Me(e)}' AND __deleted = 0`)}function pe(n,e,t){if(kt(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 Ue=new Set(["text","number","checkbox","select","multi_select","date","relation","doc","url"]),Tt=["id","database_id","name","type","config","position"];var He=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 Ge=v(function(e,t,r){if(!M(e,t))throw new d("not_found",`no such database: ${t}`);if(!Ue.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(m(e,"properties",i,"database_id",t),m(e,"properties",i,"name",r.name),m(e,"properties",i,"type",r.type),m(e,"properties",i,"config",o),m(e,"properties",i,"position",r.position??Pt(e,t)),r.type==="relation"||r.type==="doc"||r.indexed===!0)ue(e,t,i);return F(e,i)});function F(n,e){let t=n.query(`SELECT ${He} FROM properties WHERE id = ? AND __deleted = 0`).get(e);if(!t)return null;return{...t,config:t.config?JSON.parse(t.config):null}}function W(n,e){return n.query(`SELECT ${He} 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 Mn=v(function(e,t,r){let o=F(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&&!Ue.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 l={...o.config??{}};for(let[p,u]of Object.entries(r.config))if(u===null)delete l[p];else l[p]=u;s=l,fe(a,s)}else if(i)fe(r.type,o.config??void 0);if(r.name!==void 0)m(e,"properties",t,"name",r.name);if(r.type!==void 0)m(e,"properties",t,"type",r.type);if(s!==void 0)m(e,"properties",t,"config",s);if(r.position!==void 0)m(e,"properties",t,"position",r.position);if(i){let l=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 l)m(e,"records",p.id,t,null)}return F(e,t)});function Ke(n,e){let t=F(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=v(function(e,t,r,o){let{prop:i,options:a}=Ke(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}`);m(e,"properties",t,"config",{...i.config??{},options:a.map((l)=>l===r?o:l)});let s=0;if(i.type==="select"){let l=e.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? = ?").all(i.database_id,t,r);for(let p of l)m(e,"records",p.id,t,o);s=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,i.database_id,t);for(let p of l){let u=JSON.parse(p.v);if(!Array.isArray(u)||!u.includes(r))continue;m(e,"records",p.id,t,[...new Set(u.map((w)=>w===r?o:w))]),s++}}return{property:F(e,t),renamed:s}}),Un=v(function(e,t,r){let{prop:o,options:i}=Ke(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");m(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 l of s)m(e,"records",l.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 l of s){let p=JSON.parse(l.v);if(!Array.isArray(p)||!p.includes(r))continue;m(e,"records",l.id,t,p.filter((u)=>u!==r)),a++}}return{property:F(e,t),cleared:a}}),Hn=v(function(e,t){let r=F(e,t);if(!r)return!1;m(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)m(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 qe="{";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=[],l=[];s.push("(id >= ? AND id < ?)"),l.push(t,t+qe);let p=`${e}_${t}`;if(s.push("(id >= ? AND id < ?)"),l.push(p,p+qe),i)s.push(`lower(${i}) = lower(?)`),l.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 = ?",l.push(r);return n.query(u).all(...l).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 me(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)+me(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]+me(n.slice(1),null)}function G(n,e){return me(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 Fe(n){return typeof n==="string"||typeof n==="number"||typeof n==="boolean"}function Lt(n){return typeof n==="boolean"?n?1:0:n}function Mt(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 It(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)=>Mt(n,e,String(o)));case"doc":return(t===null?[]:Array.isArray(t)?t:[t]).map((o)=>It(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 l=r.get(i.toLowerCase())??[];if(l.length>1)throw new d("ambiguous",`property name "${i}" matches ${l.length} properties; use a property id`);s=l[0]}if(!s)throw new d("not_found",`unknown property: ${i}`);o.push({prop:s,value:a})}return o}function Ve(n,e,t){return _e(W(n,e),t).map(({prop:r,value:o})=>({prop:r,value:we(n,r,o)}))}function Ye(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 l=r.get(a);if(!l)continue;o[l.name]=s,i[l.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)m(n,"records",e,"order_key",t);else n.query("UPDATE records SET order_key = ? WHERE id = ?").run(t,e)}function Je(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(e)?.order_key??null}function
|
|
5
|
+
ORDER BY order_key DESC, id DESC LIMIT 1`).get(e)?.order_key??null}function ye(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(e)}function
|
|
7
|
+
ORDER BY order_key IS NULL, order_key, created_hlc, id`).all(e)}function qt(n,e){let t=ye(n,e),r=Q(null,null,t.length);t.forEach((o,i)=>{if(o.order_key!==r[i])m(n,"records",o.id,"order_key",r[i])})}var Bt=v(function(e,t){let r=Gt(e),o=t?[{database_id:t}]:e.query(`SELECT DISTINCT database_id FROM records
|
|
8
8
|
WHERE database_id IS NOT NULL AND __deleted = 0 AND order_key IS NULL`).all();for(let 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(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};
|
|
10
|
+
ORDER BY created_hlc, id`).all(i.database_id);if(!a.length)continue;let s=Je(e,i.database_id),l=Q(s,null,a.length);a.forEach((p,u)=>Kt(e,p.id,l[u],r))}}),ze=v(function(e,t,r){let o=Ht(r,de(t.name,"rec")),i=G(Je(e,t.id),null),a=m(e,"records",o,"database_id",t.id);m(e,"records",o,"created_hlc",a.hlc),m(e,"records",o,"order_key",i);for(let{prop:s,value:l}of r)m(e,"records",o,s.id,l);return ee(e,o)}),Xe=v(function(e,t,r){let o=M(e,t);if(!o)throw new d("not_found",`no such database: ${t}`);return ze(e,o,Ve(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 Ye(t,W(n,t.database_id))}function je(n){return n.replace(/'/g,"''")}function Ze(n,e,t={}){let r=W(n,e),o=t.filter&&Object.keys(t.filter).length?_e(r,t.filter).map(({prop:D,value:k})=>({prop:D,value:we(n,D,k)})):[],i=o.filter((D)=>Fe(D.value)),a=o.filter((D)=>!Fe(D.value)),s,l=!1;if(t.sort){let D=t.sort;if(D.startsWith("-"))l=!0,D=D.slice(1);if(D!=="created"&&D!=="created_hlc"){let k=r.find((I)=>I.id===D);if(!k){let I=r.filter((q)=>q.name.toLowerCase()===D.toLowerCase());if(I.length>1)throw new d("ambiguous",`sort field "${D}" matches ${I.length} properties; use a property id`);k=I[0]}if(!k)throw new d("not_found",`unknown sort field: ${D}`);s=k}}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 ->> '${je(D.prop.id)}' = ?`),u.push(Lt(D.value));let w=t.sort==null,R=s?`data ->> '${je(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} ${l?"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)=>Ye(D,r));if(a.length){if(T=T.filter((D)=>a.every((k)=>JSON.stringify(D.cells[k.prop.id]??null)===JSON.stringify(k.value))),t.limit!=null)T=T.slice(0,t.limit)}return T}var Qn=v(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);Bt(e,i.database_id);let s=ye(e,i.database_id).filter((w)=>w.id!==t),l=s.findIndex((w)=>w.id===r);if(l<0)throw new d("not_found",`no such target record: ${r}`);let p=o==="before"?s[l-1]?.order_key??null:s[l].order_key,u=o==="before"?s[l].order_key:s[l+1]?.order_key??null;if(p!==null&&u!==null&&p>=u)qt(e,i.database_id),s=ye(e,i.database_id).filter((w)=>w.id!==t),l=s.findIndex((w)=>w.id===r),p=o==="before"?s[l-1]?.order_key??null:s[l].order_key,u=o==="before"?s[l].order_key:s[l+1]?.order_key??null;return m(e,"records",t,"order_key",G(p,u)),ee(e,t)}),Qe=v(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 l=Object.hasOwn(i,a.id);if(!(s===void 0?!l:l&&JSON.stringify(s)===JSON.stringify(i[a.id])))m(e,"records",t,a.id,s)}return ee(e,t)}),et=v(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 Qe(e,t,Ve(e,o.database_id,r))}),er=v(function(e,t){if(!e.query("SELECT id FROM records WHERE id = ? AND __deleted = 0").get(t))return!1;return m(e,"records",t,"__deleted",1),!0});var Ft=["id","name","icon","meta","created_hlc"];var Wt=Ft.join(", ");function jt(n){if(!n)return null;return{...n,meta:n.meta===null?null:JSON.parse(n.meta)}}var Vt=v(function(e,t){let r=J("db",t.name),o=m(e,"databases",r,"name",t.name);if(m(e,"databases",r,"created_hlc",o.hlc),t.icon!==void 0)m(e,"databases",r,"icon",t.icon);return M(e,r)}),ar=v(function(e,t,r){if(!M(e,t))throw new d("not_found",`no such database: ${t}`);if(r.name!==void 0)m(e,"databases",t,"name",r.name);if(r.icon!==void 0)m(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");m(e,"databases",t,"meta",r.meta)}return M(e,t)}),lr=v(function(e,t,r={}){let o=M(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)m(e,"databases",i.id,"meta",w)}let a=new Map,s=new Set;for(let u of W(e,t)){let w=u.type==="relation"&&u.config?.database===t,R=w?{...u.config,database:i.id}:u.config??void 0,S=Ge(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 l=Ze(e,t),p=new Map;for(let u of l){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,Xe(e,i.id,w).id)}for(let u of l){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)et(e,p.get(u.id),w)}return M(e,i.id)});function M(n,e){return jt(n.query(`SELECT ${Wt} FROM databases WHERE id = ? AND __deleted = 0`).get(e))}var cr=v(function(e,t){if(!M(e,t))return!1;m(e,"databases",t,"__deleted",1);let r=(o)=>{for(let i of tt(e,o,"database_id",t))m(e,o,i,"__deleted",1)};r("properties"),r("records");for(let o of tt(e,"documents","database_id",t))m(e,"documents",o,"database_id",null);return e.query("DELETE FROM meta WHERE key = 'current_db' AND value = ?").run(t),!0});function tt(n,e,t,r){return n.query(`SELECT id FROM ${e} WHERE ${t} = ? AND __deleted = 0`).all(r).map((o)=>o.id)}var rt="sealed-p256";var Yt=12,Jt="mh-drop-seal-v1",nt={name:"ECDH",namedCurve:"P-256"};function te(n){let e=new Uint8Array(n.byteLength);return e.set(n),e.buffer}function ot(...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=ot(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 it(n,e){let t=await crypto.subtle.importKey("raw",te(n),nt,!1,[]),r=await crypto.subtle.generateKey(nt,!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)),l=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:te(s)},a,te(e)));return ot(o,s,l)}var st=/^g[0-9a-z]{8}$/;function Xt(){return"e"+L(16)}function at(){return"g"+L(8)}function Zt(n){return new TextEncoder().encode(JSON.stringify(n))}async function lt(n){let e=await it(n.pk,Zt(n.payload));return{v:1,envelope_id:Xt(),drop_id:n.dropId,enc:rt,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),le(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 le(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||!st.test(s))s=at(),t.set("mh_drop_guest",s);let l="mh_drop_clock:"+i,p=Number(t.get(l)??"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,y=Math.max(R.millis,f),h=y===R.millis?R.counter+1:0;return R={millis:y,counter:h},t.set(u,`${y}:${h}`),`${String(y).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),y=f?JSON.parse(f):[];return Array.isArray(y)?y:[]}catch{return[]}}function D(f){t.set(O,JSON.stringify(f))}function k(f){let y=n.databases??[],h=y.find((b)=>b.id===f)??y.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 I(f,y){let h=f.properties.find((b)=>b.id===y)??f.properties.find((b)=>b.name.toLowerCase()===y.toLowerCase());if(!h)throw new d("not_found",`unknown column: ${y}`);return h}let q=null;function c(){return q??=(async()=>{if(!e.password||!n.password_salt)return null;return he(e.password,n.password_salt)})(),q}async function g(f,y,h={}){let b=k(f),A="rec_"+L(10),x={},P={},N={};for(let[K,B]of Object.entries(y)){let Y=I(b,K);x[Y.id]=B,P[Y.name]=B,N[Y.id]=B??null}let ne=(n.payload_versions??[1]).includes(2),j;if(ne){let K={intentId:"int_"+L(16),action:"createRecord",table:b.id,recordId:A,payload:N,submittedAt:o()+p};j={v:2,guest_node:s,intents:[K]}}else{let K=[],B=(ce,Z,ft)=>{K.push({hlc:ft,node_id:s,dataset:"records",row_id:A,col:ce,value:Z===void 0||Z===null?null:JSON.stringify(Z)})},Y=S();B("database_id",b.id,Y),B("created_hlc",Y,S());for(let[ce,Z]of Object.entries(N))B(ce,Z,S());j={v:1,guest_node:s,changes:K}}let V=await lt({dropId:n.drop_id,keyId:n.key_id,pk:ie(n.pk),payload:j,now:o()}),U={"content-type":"application/json"},re=await c();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(l,String(p));let De={id:A,database_id:b.id,values:P,cells:x,_pending:!0,envelope_id:V.envelope_id,created_at:o()};return D([...T(),De]),De}function _(f){let y=T();if(!f)return y;let h=k(f).id;return y.filter((b)=>b.database_id===h)}function E(f,y){let h=new Set(f.map((N)=>N.id)),b=T(),A=b.filter((N)=>!h.has(N.id));if(A.length!==b.length)D(A);let x=y?k(y).id:null,P=A.filter((N)=>x===null||N.database_id===x);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 dt="mh_token",ut="/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 pt(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=pt(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(ut,e).toString():ut,a=()=>{if(n.token)return n.token;try{return typeof localStorage<"u"?localStorage.getItem(dt):null}catch{return null}},s=(c)=>{try{localStorage.setItem(dt,c)}catch{}};async function l(c,g,_,E,f={}){let y=(x)=>{let P={...f};if(E!==void 0)P["content-type"]="application/json";if(x)P.authorization=`Bearer ${x}`;return fetch(c+_,{method:g,headers:P,body:E!==void 0?JSON.stringify(E):void 0})},h=a(),b=await y(h);if(b.status===401&&h&&!n.token){let x=await fetch(i,{headers:{authorization:`Bearer ${h}`}}).catch(()=>null),P=x?.ok?await x.json():null;if(P?.token)s(P.token),h=P.token,b=await y(h)}let A=await b.json().catch(()=>null);if(!b.ok||A&&A.error)throw new C(A?.error??`${b.status} ${b.statusText}`,A?.code,b.status);return A}let p=null,u=()=>{if(!r)return Promise.resolve(null);if(p)return p;let c=(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=c,c.catch(()=>{if(p===c)p=null}),c},w=(c)=>{if(c?.mode==="static-async")throw new C("static-async deployment has no live runtime","invalid_input",400);return sn(c?.runtimeEndpoint,e)},R=async(c,g,_,E)=>{let f=await u();return l(w(f),c,g,_,E)},S=(c)=>encodeURIComponent(c),O=()=>"int_"+Math.random().toString(36).slice(2,10)+Date.now().toString(36),T=null,D=(c)=>(T??=(c?.drop&&c.inboxEndpoint?Promise.resolve(le({...c.drop,v:1,endpoint:c.inboxEndpoint},{password:n.dropPassword})):be(`${e}/mh-drop.json`,{password:n.dropPassword})).catch(()=>null),T),k=null,I=async(c,g)=>{let _={};if(g.turnstileToken)_["x-turnstile-token"]=g.turnstileToken;let E=c?.drop?.password_salt;if(n.dropPassword&&E)k??=he(n.dropPassword,E),_["x-drop-pass"]=await k;return _},q=async(c,g,_,E,f)=>{let y=w(c),h=pt(y),b=h?{$intent:{id:O(),submittedAt:Date.now()},values:E}:E,A=await I(c,f);try{return await l(y,g,_,b,A)}catch(x){if(c===null&&h&&x instanceof C&&(x.status===400||x.status===404))return l(y,g,_,E,A);throw x}};return{listDatabases:()=>R("GET","/api/databases"),createDatabase:(c)=>R("POST","/api/databases",c),listProperties:(c)=>R("GET",`/api/properties?db=${S(c)}`),listRecords:(c,g={})=>{let _=new URLSearchParams({db:c});if(g.sort)_.set("sort",g.sort);if(g.limit!=null)_.set("limit",String(g.limit));return R("GET",`/api/records?${_}`)},getRecord:(c)=>R("GET",`/api/record?id=${S(c)}`),createRecord:async(c,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(c,g,_)}try{return await q(E,"POST",`/api/records?db=${S(c)}`,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(c,g,_)}},updateRecord:async(c,g,_={})=>{let E=await u();if(E?.mode==="static-async")throw new C("static-async deployment does not support updateRecord","invalid_input",400);return q(E,"PATCH",`/api/record?id=${S(c)}`,g,_)},deleteRecord:async(c)=>{let g=await u();if(g?.mode==="static-async")throw new C("static-async deployment does not support deleteRecord","invalid_input",400);return l(w(g),"DELETE",`/api/record?id=${S(c)}`)},listDocuments:(c)=>R("GET",c?`/api/documents?db=${S(c)}`:"/api/documents"),getDocument:(c)=>R("GET",`/api/document?id=${S(c)}`),createDocument:(c)=>R("POST","/api/documents",c),updateDocument:(c,g)=>R("PATCH",`/api/document?id=${S(c)}`,g),deleteDocument:(c)=>R("DELETE",`/api/document?id=${S(c)}`),search:(c,g)=>{let _=new URLSearchParams({q:c});if(g!=null)_.set("limit",String(g));return R("GET",`/api/search?${_}`)},onUpdate(c,g={}){let _=!1,E=null,f=null,y=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"),A=b.toString();b.protocol=b.protocol==="https:"?"wss:":"ws:";let x=0,P=new Set([4401,4403]),N=()=>{_=!0,c({gone:!0})},ne=()=>{if(_)return;let j=!1;E=new WebSocket(b.toString()),E.onopen=()=>{j=!0,y=setTimeout(()=>{x=0},5000)},E.onmessage=(V)=>{try{let U=JSON.parse(String(V.data));if(U?.type==="poke")c({seq:U.seq})}catch{}},E.onerror=()=>{},E.onclose=(V)=>{if(y!=null)clearTimeout(y),y=null;if(_)return;if(P.has(V.code)){N();return}let U=Math.min(30000,1000*2**x++),re=U*0.25*Math.random(),H=()=>{f=setTimeout(ne,U+re)};if(!j&&x>=3)fetch(A).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(()=>c({}),g.pollMs);return()=>{if(_=!0,f!=null)clearTimeout(f),clearInterval(f);if(y!=null)clearTimeout(y);try{E?.close()}catch{}}}}}var Lr=an();export{C as MetahubError,Lr as api,an as createClient,le as createDrop,nn as detectBase,be as initDrop};
|
package/dist/sw.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
function
|
|
1
|
+
function U(n,e,t,r){let i=t.get("id"),o=t.get("db"),s=r??{},a=(l)=>l!=null?Number(l):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 l=t.get("txn");return l?{op:"auditEntryDetail",args:[l]}:null}case"POST /api/audit/revert":{let l=t.get("txn");return l?{op:"revertChangeGroup",args:[l]}:null}case"GET /api/properties":return o?{op:"listProperties",args:[o]}:null;case"POST /api/properties":{let{db:l,...p}=s;return l?{op:"addProperty",args:[l,p]}: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:l,to:p}=s;return i?{op:"renameSelectOption",args:[i,l,p]}: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:l,where:p}=s;return i&&l?{op:"moveRecord",args:[i,l,p]}: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:l,...p}=s;return i?{op:"updateDocument",args:[i,p,l]}:null}case"POST /api/document/duplicate":return i?{op:"duplicateDocument",args:[i,s]}:null;case"PATCH /api/document/move":{let{target:l,where:p}=s;return i&&l?{op:"moveDocument",args:[i,l,p]}: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:l,if_match:p}=s;return i&&l?{op:"revertDocument",args:[i,l,p]}: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 l=t.get("q");return l?{op:"search",args:[l,a(t.get("limit"))]}:null}case"GET /api/sites":return{op:"listSites",args:[]};case"GET /api/site/files":{let l=t.get("site");return l?{op:"listSiteFiles",args:[l]}: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 l=s.id;return l?{op:"revokeSiteChannel",args:[l]}:null}case"DELETE /api/site/file":{let l=t.get("site"),p=t.get("path");return l&&p?{op:"deleteSiteFile",args:[l,p]}: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 le(){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 lt={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 lt[t]??"application/octet-stream"}var F=null;function ct(){if(F)return F;return F=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)}),F}function v(n,e,t){return ct().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 H=(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 ue(n){let e=await caches.open("mh-blob-v1"),t=await e.match(H(n));if(!t)return;if(pt(t.headers.get("content-type")??"")){await e.delete(H(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(H(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(H(i.hash)),await v("meta","readwrite",(o)=>o.delete(i.hash)),e-=i.size}}var de='<script src="/mh-runtime.js"></script>';function pe(n){let e=n.toLowerCase().indexOf("<head>");if(e>=0)return n.slice(0,e+6)+de+n.slice(e+6);return de+n}class u extends Error{code;constructor(n,e){super(e);this.code=n;this.name="MhError"}}function N(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)}-${N()}`}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 fe(n){let e=n.query("SELECT value FROM meta WHERE key = 'node_id'").get();if(e)return e.value;let t=N(8);return n.query("INSERT INTO meta (key, value) VALUES ('node_id', ?)").run(t),t}function ge(n,e){if(e<=65535)return{millis:n,counter:e};return{millis:n+Math.floor(e/65536),counter:e%65536}}function me(n){let{millis:e,counter:t}=ge(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 wt(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 ht(n,e){n.query("INSERT INTO meta (key, value) VALUES ('hlc', ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value").run(me(e))}function we(n,e,t=Date.now()){let r=wt(n,e),i=Math.max(r.millis,t),o=i===r.millis?r.counter+1:0,s={...ge(i,o),node:e};return ht(n,s),me(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
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
|
|
3
|
+
`)}var ye="intent_receipts";var yt=["hlc","node_id","dataset","row_id","col","value","txn"];var Ln=yt.join(", "),W=null,_e=null;var _t=null;function V(n,e){if(W!==null)return e();W=(_e?_e+"/":"")+(n?n+":":"")+N(8);try{return e()}finally{W=null}}function m(n,e=null){return(...t)=>V(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"])},nodes:{table:"nodes",cols:new Set(["label","platform","form","app","first_seen","__deleted"])}},Et=new Set(["database_id","created_hlc","order_key","__deleted"]),Rt=new Set([ye]),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","nodes:__deleted"]);function be(n,e,t){if(t!==null)return JSON.parse(t);return Dt.has(`${n}:${e}`)?0:null}function Ee(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=be("records",r,i);n.query(`UPDATE records SET "${r}" = ? WHERE id = ?`).run(Ee(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=be(e,r,i);if(n.query(`UPDATE ${o.table} SET "${r}" = ? WHERE id = ?`).run(Ee(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 d(n,e,t,r,i){let o=_t??fe(n),s={hlc:we(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 J(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 X(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}J(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 Q(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}`);Q(r.type,r.config);let i=r.indexed?{...r.config??{},indexed:!0}:r.config??null,o=x("prop",r.name);if(d(e,"properties",o,"database_id",t),d(e,"properties",o,"name",r.name),d(e,"properties",o,"type",r.type),d(e,"properties",o,"config",i),d(e,"properties",o,"position",r.position??Ct(e,t)),r.type==="relation"||r.type==="doc"||r.indexed===!0)J(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 Fn=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 c={...i.config??{}};for(let[l,p]of Object.entries(r.config))if(p===null)delete c[l];else c[l]=p;a=c,Q(s,a)}else if(o)Q(r.type,i.config??void 0);if(r.name!==void 0)d(e,"properties",t,"name",r.name);if(r.type!==void 0)d(e,"properties",t,"type",r.type);if(a!==void 0)d(e,"properties",t,"config",a);if(r.position!==void 0)d(e,"properties",t,"position",r.position);if(o){let c=e.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(i.database_id,t);for(let l of c)d(e,"records",l.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}`);d(e,"properties",t,"config",{...o.config??{},options:s.map((c)=>c===r?i:c)});let a=0;if(o.type==="select"){let c=e.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? = ?").all(o.database_id,t,r);for(let l of c)d(e,"records",l.id,t,i);a=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,o.database_id,t);for(let l of c){let p=JSON.parse(l.v);if(!Array.isArray(p)||!p.includes(r))continue;d(e,"records",l.id,t,[...new Set(p.map((f)=>f===r?i:f))]),a++}}return{property:T(e,t),renamed:a}}),Wn=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");d(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 c of a)d(e,"records",c.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 c of a){let l=JSON.parse(c.v);if(!Array.isArray(l)||!l.includes(r))continue;d(e,"records",c.id,t,l.filter((p)=>p!==r)),s++}}return{property:T(e,t),cleared:s}}),Gn=m(function(e,t){let r=T(e,t);if(!r)return!1;d(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)d(e,"records",o.id,t,void 0);return!0});var Lt={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"}},Nt=["db","prop","rec","doc"];function kt(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 Pt(n,e,t,r){let i=Lt[e],o=i.nameCol;if(e==="rec"&&r){let w=Ce(n,r);if(w)o=`data ->> '${w.replace(/'/g,"''")}'`}let s=o??"''",a=[],c=[];a.push("(id >= ? AND id < ?)"),c.push(t,t+Ae);let l=`${e}_${t}`;if(a.push("(id >= ? AND id < ?)"),c.push(l,l+Ae),o)a.push(`lower(${o}) = lower(?)`),c.push(t);let p=`SELECT id, ${s} AS label FROM ${i.table} WHERE __deleted = 0 AND (${a.join(" OR ")})`;if(i.scoped&&r)p+=" AND database_id = ?",c.push(r);return n.query(p).all(...c).map((w)=>({kind:e,id:w.id,label:w.label??""}))}function Z(n,e,t={}){let r=t.kind?[t.kind]:kt(A(e))?[A(e)]:Nt,i=[],o=new Set;for(let s of r)for(let a of Pt(n,s,e,t.databaseId)){if(o.has(a.id))continue;o.add(a.id),i.push(a)}return i}function ee(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)+ee(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]+ee(n.slice(1),null)}function E(n,e){return ee(n??"",e)}function k(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[...k(n,i,r),i,...k(i,e,t-r-1)]}function Le(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=Z(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=Z(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 ne(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 re(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 c=r.get(o.toLowerCase())??[];if(c.length>1)throw new u("ambiguous",`property name "${o}" matches ${c.length} properties; use a property id`);a=c[0]}if(!a)throw new u("not_found",`unknown property: ${o}`);i.push({prop:a,value:s})}return i}function Pe(n,e,t){return re(O(n,e),t).map(({prop:r,value:i})=>({prop:r,value:ne(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 c=r.get(s);if(!c)continue;i[c.name]=a,o[c.id]=a}return{id:n.id,database_id:n.database_id,values:i,cells:o}}function Ft(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 Ne(n,e){return n.query("SELECT 1 AS ok FROM sqlite_master WHERE type = 'table' AND name = ?").get(e)!=null}function Ht(n){return Ne(n,"meta")&&Ne(n,"crdt_changes")}function Wt(n,e,t,r){if(r)d(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(e)?.order_key??null}function
|
|
5
|
+
ORDER BY order_key DESC, id DESC LIMIT 1`).get(e)?.order_key??null}function te(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(e)}function Gt(n,e){let t=
|
|
7
|
+
ORDER BY order_key IS NULL, order_key, created_hlc, id`).all(e)}function Gt(n,e){let t=te(n,e),r=k(null,null,t.length);t.forEach((i,o)=>{if(i.order_key!==r[o])d(n,"records",i.id,"order_key",r[o])})}var qt=m(function(e,t){let r=Ht(e),i=t?[{database_id:t}]:e.query(`SELECT DISTINCT database_id FROM records
|
|
8
8
|
WHERE database_id IS NOT NULL AND __deleted = 0 AND order_key IS NULL`).all();for(let 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(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}});
|
|
10
|
+
ORDER BY created_hlc, id`).all(o.database_id);if(!s.length)continue;let a=$e(e,o.database_id),c=k(a,null,s.length);s.forEach((l,p)=>Wt(e,l.id,c[p],r))}}),Be=m(function(e,t,r){let i=Ft(r,Y(t.name,"rec")),o=E($e(e,t.id),null),s=d(e,"records",i,"database_id",t.id);d(e,"records",i,"created_hlc",s.hlc),d(e,"records",i,"order_key",o);for(let{prop:a,value:c}of r)d(e,"records",i,a.id,c);return P(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,Pe(e,i.id,r))});function P(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 ke(n){return n.replace(/'/g,"''")}function Fe(n,e,t={}){let r=O(n,e),i=t.filter&&Object.keys(t.filter).length?re(r,t.filter).map(({prop:g,value:b})=>({prop:g,value:ne(n,g,b)})):[],o=i.filter((g)=>Le(g.value)),s=i.filter((g)=>!Le(g.value)),a,c=!1;if(t.sort){let g=t.sort;if(g.startsWith("-"))c=!0,g=g.slice(1);if(g!=="created"&&g!=="created_hlc"){let b=r.find((L)=>L.id===g);if(!b){let L=r.filter((rt)=>rt.name.toLowerCase()===g.toLowerCase());if(L.length>1)throw new u("ambiguous",`sort field "${g}" matches ${L.length} properties; use a property id`);b=L[0]}if(!b)throw new u("not_found",`unknown sort field: ${g}`);a=b}}for(let g of o)X(n,e,g.prop);if(a)X(n,e,a);let l=["database_id = ?","__deleted = 0"],p=[e];for(let g of o)l.push(`data ->> '${ke(g.prop.id)}' = ?`),p.push(Mt(g.value));let f=t.sort==null,w=a?`data ->> '${ke(a.id)}'`:"created_hlc",h=`SELECT id, database_id, data FROM records WHERE ${l.join(" AND ")} `+(f?"ORDER BY order_key IS NULL, order_key, id":`ORDER BY ${w} ${c?"DESC":"ASC"}, id`);if(t.limit!=null&&s.length===0)h+=" LIMIT ?",p.push(t.limit);let S=n.query(h).all(...p).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 nr=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 P(e,t);qt(e,o.database_id);let a=te(e,o.database_id).filter((f)=>f.id!==t),c=a.findIndex((f)=>f.id===r);if(c<0)throw new u("not_found",`no such target record: ${r}`);let l=i==="before"?a[c-1]?.order_key??null:a[c].order_key,p=i==="before"?a[c].order_key:a[c+1]?.order_key??null;if(l!==null&&p!==null&&l>=p)Gt(e,o.database_id),a=te(e,o.database_id).filter((f)=>f.id!==t),c=a.findIndex((f)=>f.id===r),l=i==="before"?a[c-1]?.order_key??null:a[c].order_key,p=i==="before"?a[c].order_key:a[c+1]?.order_key??null;return d(e,"records",t,"order_key",E(l,p)),P(e,t)}),He=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 c=Object.hasOwn(o,s.id);if(!(a===void 0?!c:c&&JSON.stringify(a)===JSON.stringify(o[s.id])))d(e,"records",t,s.id,a)}return P(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 He(e,t,Pe(e,i.database_id,r))}),rr=m(function(e,t){if(!e.query("SELECT id FROM records WHERE id = ? AND __deleted = 0").get(t))return!1;return d(e,"records",t,"__deleted",1),!0});var jt=["id","name","icon","meta","created_hlc"];var Ut=jt.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=d(e,"databases",r,"name",t.name);if(d(e,"databases",r,"created_hlc",i.hlc),t.icon!==void 0)d(e,"databases",r,"icon",t.icon);return y(e,r)}),ur=m(function(e,t,r){if(!y(e,t))throw new u("not_found",`no such database: ${t}`);if(r.name!==void 0)d(e,"databases",t,"name",r.name);if(r.icon!==void 0)d(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");d(e,"databases",t,"meta",r.meta)}return y(e,t)}),dr=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:p,...f}=i.meta;if(Object.keys(f).length)d(e,"databases",o.id,"meta",f)}let s=new Map,a=new Set;for(let p of O(e,t)){let f=p.type==="relation"&&p.config?.database===t,w=f?{...p.config,database:o.id}:p.config??void 0,h=Te(e,o.id,{name:p.name,type:p.type,config:w,position:p.position});if(s.set(p.id,h.id),f)a.add(h.id)}let c=Fe(e,t),l=new Map;for(let p of c){let f={};for(let[w,h]of Object.entries(p.cells)){let D=s.get(w);if(!D)continue;if(a.has(D)&&Array.isArray(h)&&h.length>0)continue;f[D]=h}l.set(p.id,Ie(e,o.id,f).id)}for(let p of c){let f={};for(let[w,h]of Object.entries(p.cells)){let D=s.get(w);if(D&&a.has(D)&&Array.isArray(h)&&h.length>0)f[D]=h.map((S)=>l.get(String(S))??S)}if(Object.keys(f).length)We(e,l.get(p.id),f)}return y(e,o.id)});function y(n,e){return zt(n.query(`SELECT ${Ut} FROM databases WHERE id = ? AND __deleted = 0`).get(e))}var pr=m(function(e,t){if(!y(e,t))return!1;d(e,"databases",t,"__deleted",1);let r=(i)=>{for(let o of Ge(e,i,"database_id",t))d(e,i,o,"__deleted",1)};r("properties"),r("records");for(let i of Ge(e,"documents","database_id",t))d(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 ie=["read","create","update"];function Yt(n){return typeof n==="string"&&ie.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=ie.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 je(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 ${ie.join("|")} (delete is never grantable)`);t.push({db:i,ops:o})}return qe(t)}function Ue(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 xr=Jt.join(", ");function oe(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=oe(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 vr=m(function(e,t){let r=oe(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=d(e,"sites",i,"name",r);if(d(e,"sites",i,"created_hlc",o.hlc),t.title!==void 0)d(e,"sites",i,"title",t.title);if(t.visibility!==void 0)d(e,"sites",i,"visibility",t.visibility);return C(e,i)}),Tr=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=oe(r.name),o=Ke(e,i);if(o&&o.id!==t)throw new u("conflict",`site name already exists: ${i}`);d(e,"sites",t,"name",i)}if(r.title!==void 0)d(e,"sites",t,"title",r.title);if(r.visibility!==void 0)d(e,"sites",t,"visibility",r.visibility);if(r.spa!==void 0)d(e,"sites",t,"spa",r.spa?1:0);return C(e,t)}),Or=m(function(e,t,r){if(!C(e,t))throw new u("not_found",`no such site: ${t}`);let i=r==null?null:Ue(je(r));return d(e,"sites",t,"public_grants",i),C(e,t)}),Ar=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)d(e,"site_files",i.id,"__deleted",1);return d(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 Cr=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 d(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 se=null;async function ae(){if(se==null){let n=await le();if(n==="unknown")return!1;se=n}return se==="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 j(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 j(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 ae()){let s=U(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 j(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=U(t.method,i,r.searchParams,o);if(a){let c=await q(n,a.op,a.args);if(c)return Qe(c)}if(t.method==="GET"){let c=await(await R.open(Je)).match(t);if(c)return c}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?pe(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 ae())return await et(n,t)??new Response("not found",{status:404});try{return await j(e,B)}catch(r){let i=await et(n,t);if(i)return i;throw r}}async function ln(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 ue(e);if(i)return i;if(!await ae())try{let s=r?new Request(r,{cache:"no-store"}):new Request(`${_.location.origin}/blob/${e}`,{cache:"no-store"}),a=await j(s,B*2);if(a.ok){let c=await a.clone().arrayBuffer();if(await z(c,e))return await K(e,c,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(ln(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}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/webui/server/routes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,KAAK,EAAiB,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/webui/server/routes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,KAAK,EAAiB,MAAM,2BAA2B,CAAC;AAserF,eAAO,MAAM,WAAW,EAAE,KAAK,EAkiB9B,CAAC"}
|