@tensorix/metahub 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/README.md +23 -10
  2. package/README.zh-CN.md +23 -10
  3. package/dist/cli/edge-worker-script.d.ts +4 -0
  4. package/dist/cli/edge-worker-script.d.ts.map +1 -0
  5. package/dist/cli.js +16882 -8691
  6. package/dist/cli.js.map +109 -59
  7. package/dist/core/access-policy.d.ts +82 -0
  8. package/dist/core/access-policy.d.ts.map +1 -0
  9. package/dist/core/blobs-core.d.ts +19 -0
  10. package/dist/core/blobs-core.d.ts.map +1 -1
  11. package/dist/core/blobs.d.ts.map +1 -1
  12. package/dist/core/compact.d.ts.map +1 -1
  13. package/dist/core/config.d.ts +13 -0
  14. package/dist/core/config.d.ts.map +1 -1
  15. package/dist/core/crdt.d.ts +29 -2
  16. package/dist/core/crdt.d.ts.map +1 -1
  17. package/dist/core/data-map.d.ts +105 -0
  18. package/dist/core/data-map.d.ts.map +1 -0
  19. package/dist/core/db.d.ts +1 -1
  20. package/dist/core/db.d.ts.map +1 -1
  21. package/dist/core/documents.d.ts.map +1 -1
  22. package/dist/core/errors.d.ts +2 -0
  23. package/dist/core/errors.d.ts.map +1 -1
  24. package/dist/core/grants-core.d.ts +132 -0
  25. package/dist/core/grants-core.d.ts.map +1 -0
  26. package/dist/core/guest-intent.d.ts +33 -0
  27. package/dist/core/guest-intent.d.ts.map +1 -0
  28. package/dist/core/hash.d.ts +4 -0
  29. package/dist/core/hash.d.ts.map +1 -0
  30. package/dist/core/history.d.ts.map +1 -1
  31. package/dist/core/hlc.d.ts +5 -0
  32. package/dist/core/hlc.d.ts.map +1 -1
  33. package/dist/core/ids.d.ts +1 -1
  34. package/dist/core/ids.d.ts.map +1 -1
  35. package/dist/core/inject-runtime.d.ts +8 -0
  36. package/dist/core/inject-runtime.d.ts.map +1 -0
  37. package/dist/core/intent-retention.d.ts +23 -0
  38. package/dist/core/intent-retention.d.ts.map +1 -0
  39. package/dist/core/md/inline.d.ts +6 -2
  40. package/dist/core/md/inline.d.ts.map +1 -1
  41. package/dist/core/node.d.ts +13 -0
  42. package/dist/core/node.d.ts.map +1 -1
  43. package/dist/core/records.d.ts +31 -0
  44. package/dist/core/records.d.ts.map +1 -1
  45. package/dist/core/schema-init.d.ts +19 -2
  46. package/dist/core/schema-init.d.ts.map +1 -1
  47. package/dist/core/schema.d.ts +1 -1
  48. package/dist/core/schema.d.ts.map +1 -1
  49. package/dist/core/shares.d.ts +15 -0
  50. package/dist/core/shares.d.ts.map +1 -1
  51. package/dist/core/site-channel-lifecycle.d.ts +10 -0
  52. package/dist/core/site-channel-lifecycle.d.ts.map +1 -0
  53. package/dist/core/site-channel-store.d.ts +120 -0
  54. package/dist/core/site-channel-store.d.ts.map +1 -0
  55. package/dist/core/site-channels.d.ts +65 -0
  56. package/dist/core/site-channels.d.ts.map +1 -0
  57. package/dist/core/sites-core.d.ts +100 -7
  58. package/dist/core/sites-core.d.ts.map +1 -1
  59. package/dist/core/sites.d.ts +65 -2
  60. package/dist/core/sites.d.ts.map +1 -1
  61. package/dist/core/sync/anti-abuse.d.ts +26 -0
  62. package/dist/core/sync/anti-abuse.d.ts.map +1 -0
  63. package/dist/core/sync/auth.d.ts +30 -2
  64. package/dist/core/sync/auth.d.ts.map +1 -1
  65. package/dist/core/sync/blob-routes.d.ts.map +1 -1
  66. package/dist/core/sync/cf-api.d.ts +54 -0
  67. package/dist/core/sync/cf-api.d.ts.map +1 -0
  68. package/dist/core/sync/cf-oauth.d.ts +91 -0
  69. package/dist/core/sync/cf-oauth.d.ts.map +1 -0
  70. package/dist/core/sync/client.d.ts +12 -0
  71. package/dist/core/sync/client.d.ts.map +1 -1
  72. package/dist/core/sync/data-map-db.d.ts +8 -0
  73. package/dist/core/sync/data-map-db.d.ts.map +1 -0
  74. package/dist/core/sync/devices.d.ts +65 -0
  75. package/dist/core/sync/devices.d.ts.map +1 -0
  76. package/dist/core/sync/drop-host.d.ts +40 -0
  77. package/dist/core/sync/drop-host.d.ts.map +1 -0
  78. package/dist/core/sync/drop-keys.d.ts +64 -0
  79. package/dist/core/sync/drop-keys.d.ts.map +1 -0
  80. package/dist/core/sync/drop-protocol.d.ts +94 -0
  81. package/dist/core/sync/drop-protocol.d.ts.map +1 -0
  82. package/dist/core/sync/drop-pull.d.ts +67 -0
  83. package/dist/core/sync/drop-pull.d.ts.map +1 -0
  84. package/dist/core/sync/drop-wire.d.ts +39 -0
  85. package/dist/core/sync/drop-wire.d.ts.map +1 -0
  86. package/dist/core/sync/e2ee.d.ts +3 -0
  87. package/dist/core/sync/e2ee.d.ts.map +1 -1
  88. package/dist/core/sync/edge-config.d.ts +77 -0
  89. package/dist/core/sync/edge-config.d.ts.map +1 -0
  90. package/dist/core/sync/edge-connect.d.ts +13 -0
  91. package/dist/core/sync/edge-connect.d.ts.map +1 -0
  92. package/dist/core/sync/edge-service.d.ts +100 -0
  93. package/dist/core/sync/edge-service.d.ts.map +1 -0
  94. package/dist/core/sync/grants-routes.d.ts +46 -0
  95. package/dist/core/sync/grants-routes.d.ts.map +1 -0
  96. package/dist/core/sync/guest-session.d.ts +29 -0
  97. package/dist/core/sync/guest-session.d.ts.map +1 -0
  98. package/dist/core/sync/html-escape.d.ts +2 -0
  99. package/dist/core/sync/html-escape.d.ts.map +1 -0
  100. package/dist/core/sync/http-status.d.ts +14 -0
  101. package/dist/core/sync/http-status.d.ts.map +1 -0
  102. package/dist/core/sync/http-util.d.ts +6 -0
  103. package/dist/core/sync/http-util.d.ts.map +1 -0
  104. package/dist/core/sync/pairing.d.ts +9 -9
  105. package/dist/core/sync/pairing.d.ts.map +1 -1
  106. package/dist/core/sync/partition.d.ts +77 -0
  107. package/dist/core/sync/partition.d.ts.map +1 -0
  108. package/dist/core/sync/peers-routes.d.ts.map +1 -1
  109. package/dist/core/sync/peers.d.ts +77 -0
  110. package/dist/core/sync/peers.d.ts.map +1 -1
  111. package/dist/core/sync/protocol.d.ts +2 -0
  112. package/dist/core/sync/protocol.d.ts.map +1 -1
  113. package/dist/core/sync/rate-limit.d.ts +20 -0
  114. package/dist/core/sync/rate-limit.d.ts.map +1 -0
  115. package/dist/core/sync/recovery.d.ts +9 -0
  116. package/dist/core/sync/recovery.d.ts.map +1 -0
  117. package/dist/core/sync/room-client.d.ts +50 -0
  118. package/dist/core/sync/room-client.d.ts.map +1 -0
  119. package/dist/core/sync/room-peer.d.ts +62 -0
  120. package/dist/core/sync/room-peer.d.ts.map +1 -0
  121. package/dist/core/sync/room-protocol.d.ts +130 -0
  122. package/dist/core/sync/room-protocol.d.ts.map +1 -0
  123. package/dist/core/sync/room-serve.d.ts +38 -0
  124. package/dist/core/sync/room-serve.d.ts.map +1 -0
  125. package/dist/core/sync/room-url.d.ts +4 -0
  126. package/dist/core/sync/room-url.d.ts.map +1 -0
  127. package/dist/core/sync/routes.d.ts +4 -1
  128. package/dist/core/sync/routes.d.ts.map +1 -1
  129. package/dist/core/sync/seal.d.ts +22 -0
  130. package/dist/core/sync/seal.d.ts.map +1 -0
  131. package/dist/core/sync/server.d.ts +7 -0
  132. package/dist/core/sync/server.d.ts.map +1 -1
  133. package/dist/core/sync/share-actions.d.ts +55 -6
  134. package/dist/core/sync/share-actions.d.ts.map +1 -1
  135. package/dist/core/sync/share-export.d.ts +14 -0
  136. package/dist/core/sync/share-export.d.ts.map +1 -1
  137. package/dist/core/sync/share-render.d.ts +9 -1
  138. package/dist/core/sync/share-render.d.ts.map +1 -1
  139. package/dist/core/sync/share-serve.d.ts +5 -1
  140. package/dist/core/sync/share-serve.d.ts.map +1 -1
  141. package/dist/core/sync/site-channel-reconcile.d.ts +26 -0
  142. package/dist/core/sync/site-channel-reconcile.d.ts.map +1 -0
  143. package/dist/core/sync/site-publish-recovery.d.ts +32 -0
  144. package/dist/core/sync/site-publish-recovery.d.ts.map +1 -0
  145. package/dist/core/sync/site-reachability.d.ts +13 -0
  146. package/dist/core/sync/site-reachability.d.ts.map +1 -0
  147. package/dist/core/sync/sites-routes.d.ts.map +1 -1
  148. package/dist/core/sync/sites-serve.d.ts +24 -1
  149. package/dist/core/sync/sites-serve.d.ts.map +1 -1
  150. package/dist/core/sync/storage-s3-bun.d.ts +1 -24
  151. package/dist/core/sync/storage-s3-bun.d.ts.map +1 -1
  152. package/dist/core/sync/storage-s3-sign.d.ts +43 -0
  153. package/dist/core/sync/storage-s3-sign.d.ts.map +1 -0
  154. package/dist/core/sync/storage.d.ts +59 -0
  155. package/dist/core/sync/storage.d.ts.map +1 -1
  156. package/dist/db-worker.js +206 -76
  157. package/dist/edge-worker.js +3960 -0
  158. package/dist/index.js +13175 -6670
  159. package/dist/index.js.map +87 -41
  160. package/dist/metahub-sdk.js +10 -1
  161. package/dist/mh-runtime.js +1 -1
  162. package/dist/room/do-driver.d.ts +30 -0
  163. package/dist/room/do-driver.d.ts.map +1 -0
  164. package/dist/sw.js +10 -1
  165. package/dist/webui/server/edge-routes.d.ts +3 -0
  166. package/dist/webui/server/edge-routes.d.ts.map +1 -0
  167. package/dist/webui/server/json-handler.d.ts +4 -0
  168. package/dist/webui/server/json-handler.d.ts.map +1 -0
  169. package/dist/webui/server/routes.d.ts.map +1 -1
  170. package/dist/webui/server/share-routes.d.ts.map +1 -1
  171. package/dist/webui/server/site-hosting-routes.d.ts +7 -0
  172. package/dist/webui/server/site-hosting-routes.d.ts.map +1 -0
  173. package/dist/webui.js +192 -137
  174. package/dist/workers/edge-worker.d.ts +66 -0
  175. package/dist/workers/edge-worker.d.ts.map +1 -0
  176. package/dist/workers/room.d.ts +34 -0
  177. package/dist/workers/room.d.ts.map +1 -0
  178. package/package.json +1 -1
@@ -1 +1,10 @@
1
- class Z extends Error{code;status;constructor(I,S,U){super(I);this.code=S;this.status=U;this.name="MetahubError"}}var X="mh_token",A="/auth/token";function C(I={}){let S=(I.baseUrl??"").replace(/\/$/,""),U=()=>{if(I.token)return I.token;try{return typeof localStorage<"u"?localStorage.getItem(X):null}catch{return null}},$=(f)=>{try{localStorage.setItem(X,f)}catch{}};async function z(f,j,B){let V=(Q)=>{let G={};if(B!==void 0)G["content-type"]="application/json";if(Q)G.authorization=`Bearer ${Q}`;return fetch(S+j,{method:f,headers:G,body:B!==void 0?JSON.stringify(B):void 0})},J=U(),F=await V(J);if(F.status===401&&J&&!I.token){let Q=await fetch(S+A,{headers:{authorization:`Bearer ${J}`}}).catch(()=>null),G=Q?.ok?await Q.json():null;if(G?.token)$(G.token),J=G.token,F=await V(J)}let L=await F.json().catch(()=>null);if(!F.ok||L&&L.error)throw new Z(L?.error??`${F.status} ${F.statusText}`,L?.code,F.status);return L}let D=(f)=>encodeURIComponent(f);return{listDatabases:()=>z("GET","/api/databases"),createDatabase:(f)=>z("POST","/api/databases",f),listProperties:(f)=>z("GET",`/api/properties?db=${D(f)}`),listRecords:(f,j={})=>{let B=new URLSearchParams({db:f});if(j.sort)B.set("sort",j.sort);if(j.limit!=null)B.set("limit",String(j.limit));return z("GET",`/api/records?${B}`)},getRecord:(f)=>z("GET",`/api/record?id=${D(f)}`),createRecord:(f,j)=>z("POST",`/api/records?db=${D(f)}`,j),updateRecord:(f,j)=>z("PATCH",`/api/record?id=${D(f)}`,j),deleteRecord:(f)=>z("DELETE",`/api/record?id=${D(f)}`),listDocuments:(f)=>z("GET",f?`/api/documents?db=${D(f)}`:"/api/documents"),getDocument:(f)=>z("GET",`/api/document?id=${D(f)}`),createDocument:(f)=>z("POST","/api/documents",f),updateDocument:(f,j)=>z("PATCH",`/api/document?id=${D(f)}`,j),deleteDocument:(f)=>z("DELETE",`/api/document?id=${D(f)}`),search:(f,j)=>{let B=new URLSearchParams({q:f});if(j!=null)B.set("limit",String(j));return z("GET",`/api/search?${B}`)}}}var H=C();export{C as createClient,H as api,Z as MetahubError};
1
+ class U extends Error{code;constructor(X,Q){super(Q);this.code=X;this.name="MhError"}}function g(X=6){let Q=crypto.getRandomValues(new Uint8Array(X)),$="";for(let Z of Q)$+="0123456789abcdefghijklmnopqrstuvwxyz".charAt(Z%36);return $}function VQ(X,Q="item"){return X.normalize("NFKD").replace(/[^\x20-\x7E]/g,"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,32).replace(/-+$/g,"")||Q}var jX=new Set(["db","prop","rec","doc","blk","site","sf","chan"]);function i(X,Q,$=X){return`${X}_${VQ(Q,$)}-${g()}`}function t(X){let Q=X.indexOf("_");if(Q<=0)return null;let $=X.slice(0,Q);return jX.has($)?$:null}var VX=600000;function BQ(X){let Q=new Uint8Array(X.byteLength);return Q.set(X),Q.buffer}function $Q(X){let Q="";for(let $=0;$<X.length;$++)Q+=String.fromCharCode(X[$]);return btoa(Q)}function ZQ(X){let Q=atob(X),$=new Uint8Array(Q.length);for(let Z=0;Z<Q.length;Z++)$[Z]=Q.charCodeAt(Z);return $}async function OQ(X,Q){let $=await crypto.subtle.importKey("raw",BQ(new TextEncoder().encode(X)),"PBKDF2",!1,["deriveBits"]),Z=await crypto.subtle.deriveBits({name:"PBKDF2",salt:BQ(Q),iterations:VX,hash:"SHA-256"},$,256);return new Uint8Array(Z)}function _Q(X,Q){if(Q<=65535)return{millis:X,counter:Q};return{millis:X+Math.floor(Q/65536),counter:Q%65536}}function CQ(X){let{millis:Q,counter:$}=_Q(X.millis,X.counter);return`${String(Q).padStart(15,"0")}-${$.toString(16).padStart(4,"0")}-${X.node}`}function xQ(X){let Q=X.indexOf("-"),$=X.indexOf("-",Q+1);return{millis:Number(X.slice(0,Q)),counter:parseInt(X.slice(Q+1,$),16),node:X.slice($+1)}}function UX(X,Q){let $=X.query("SELECT value FROM meta WHERE key = 'hlc'").get();return $?xQ($.value):{millis:0,counter:0,node:Q}}function GX(X,Q){X.query("INSERT INTO meta (key, value) VALUES ('hlc', ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value").run(CQ(Q))}function PQ(X,Q,$=Date.now()){let Z=UX(X,Q),W=Math.max(Z.millis,$),z=W===Z.millis?Z.counter+1:0,j={..._Q(W,z),node:Q};return GX(X,j),CQ(j)}function SQ(X){let Q=X.query("SELECT value FROM meta WHERE key = 'node_id'").get();if(Q)return Q.value;let $=g(8);return X.query("INSERT INTO meta (key, value) VALUES ('node_id', ?)").run($),$}function TQ(X){let Q=X.filter((Z)=>!!Z.text&&Z.text.length>0),$=[];return Q.forEach((Z,W)=>{$.push(...Z.text.split(`
2
+ `));let z=Math.max(0,Z.blankAfter??0);if(W<Q.length-1)$.push("");for(let j=0;j<z;j++)$.push("")}),$.join(`
3
+ `)}var RQ="intent_receipts";var YX=["hlc","node_id","dataset","row_id","col","value","txn"];var O1=YX.join(", "),WQ=null,HX=null;function qX(X,Q){if(WQ!==null)return Q();WQ=(X?X+":":"")+g(8);try{return Q()}finally{WQ=null}}function S(X,Q=null){return(...$)=>qX(Q,()=>X(...$))}var LX={databases:{table:"databases",cols:new Set(["name","icon","meta","created_hlc","__deleted"])},properties:{table:"properties",cols:new Set(["database_id","name","type","config","position","__deleted"])},documents:{table:"documents",cols:new Set(["title","body","database_id","parent_id","created_hlc","order_key","__deleted"])},doc_blocks:{table:"doc_blocks",cols:new Set(["doc_id","text","order_key","blank_after","__deleted"])},sites:{table:"sites",cols:new Set(["name","title","created_hlc","visibility","spa","public_grants","__deleted"])},site_channels:{table:"site_channels",cols:new Set(["site_id","audience","hosting","controller_node_id","target_ref","canonical_url","policy_json","desired_state","created_hlc","__deleted"])},site_files:{table:"site_files",cols:new Set(["site_id","path","content_type","encoding","content","created_hlc","__deleted"])},blob_policy:{table:"blob_policy",cols:new Set(["full_nodes","redundancy","__deleted"])}},AX=new Set(["database_id","created_hlc","order_key","__deleted"]),NX=new Set([RQ]),KX=new Set(["records:__deleted","databases:__deleted","properties:__deleted","documents:__deleted","doc_blocks:__deleted","doc_blocks:blank_after","sites:__deleted","sites:spa","site_channels:__deleted","site_files:__deleted","blob_policy:__deleted"]);function MQ(X,Q,$){if($!==null)return JSON.parse($);return KX.has(`${X}:${Q}`)?0:null}function kQ(X){if(X===null||X===void 0)return null;if(typeof X==="boolean")return X?1:0;if(typeof X==="number")return X;if(typeof X==="string")return X;return JSON.stringify(X)}function zQ(X,Q,$){X.query(`INSERT OR IGNORE INTO ${Q} (id) VALUES (?)`).run($)}function DX(X,Q){return X.query("SELECT 1 AS x FROM doc_blocks WHERE doc_id = ? LIMIT 1").get(Q)!=null}function BX(X,Q){let $=X.query("SELECT text, blank_after FROM doc_blocks WHERE doc_id = ? AND __deleted = 0 ORDER BY order_key, id").all(Q);zQ(X,"documents",Q),X.query("UPDATE documents SET body = ? WHERE id = ?").run(TQ($.map((Z)=>({text:Z.text,blankAfter:Z.blank_after??0}))),Q)}function OX(X,Q,$,Z,W){if(NX.has(Q))return;if(Q==="records"){if(AX.has(Z)){zQ(X,"records",$);let J=MQ("records",Z,W);X.query(`UPDATE records SET "${Z}" = ? WHERE id = ?`).run(kQ(J),$)}else if(zQ(X,"records",$),W===null)X.query(`UPDATE records SET data = json_remove(data, '$."' || ? || '"') WHERE id = ?`).run(Z,$);else X.query(`UPDATE records SET data = json_set(coalesce(data, '{}'), '$."' || ? || '"', json(?)) WHERE id = ?`).run(Z,W,$);return}let z=LX[Q];if(!z||!z.cols.has(Z))return;if(Q==="documents"&&Z==="body"&&DX(X,$))return;zQ(X,z.table,$);let j=MQ(Q,Z,W);if(X.query(`UPDATE ${z.table} SET "${Z}" = ? WHERE id = ?`).run(kQ(j),$),Q==="doc_blocks"){let J=X.query("SELECT doc_id FROM doc_blocks WHERE id = ?").get($);if(J?.doc_id)BX(X,J.doc_id)}}function _X(X,Q){let $=X.query("INSERT OR IGNORE INTO crdt_changes (hlc, node_id, dataset, row_id, col, value, txn) VALUES (?, ?, ?, ?, ?, ?, ?)").run(Q.hlc,Q.node_id,Q.dataset,Q.row_id,Q.col,Q.value,Q.txn??null).changes>0;if(X.query("SELECT MAX(hlc) AS h FROM crdt_changes WHERE dataset = ? AND row_id = ? AND col = ?").get(Q.dataset,Q.row_id,Q.col).h!==Q.hlc)return{inserted:$,winner:!1};try{OX(X,Q.dataset,Q.row_id,Q.col,Q.value)}catch(W){if($)X.query("DELETE FROM crdt_changes WHERE dataset = ? AND row_id = ? AND col = ? AND hlc = ?").run(Q.dataset,Q.row_id,Q.col,Q.hlc);throw W}return{inserted:$,winner:!0}}function L(X,Q,$,Z,W){let z=HX??SQ(X),j={hlc:PQ(X,z),node_id:z,dataset:Q,row_id:$,col:Z,value:W===void 0?null:JSON.stringify(W),txn:WQ};return _X(X,j),j}function yQ(X){return X.replace(/[^a-zA-Z0-9_]/g,"_")}function IQ(X){return X.replace(/'/g,"''")}function gQ(X,Q){return`idx_rec_${yQ(X)}_${yQ(Q)}`}function CX(X,Q,$){return X.query("SELECT 1 AS ok FROM sqlite_master WHERE type = 'index' AND name = ?").get(gQ(Q,$))!=null}function UQ(X,Q,$){let Z=gQ(Q,$);X.exec(`CREATE INDEX IF NOT EXISTS "${Z}" ON records (data ->> '${IQ($)}', created_hlc) WHERE database_id = '${IQ(Q)}' AND __deleted = 0`)}function GQ(X,Q,$){if(CX(X,Q,$.id))return;if($.type!=="relation"){if(X.query("SELECT COUNT(*) AS c FROM records WHERE database_id = ? AND __deleted = 0").get(Q).c<2000)return}UQ(X,Q,$.id)}var EQ=new Set(["text","number","checkbox","select","multi_select","date","relation","url"]),xX=["id","database_id","name","type","config","position"];var vQ=xX.join(", ");function YQ(X,Q){if(X==="select"||X==="multi_select"){let $=Q?.options;if(!Array.isArray($)||$.length===0||!$.every((Z)=>typeof Z==="string"))throw new U("invalid_input",`${X} requires config.options: string[]`)}if(X==="relation"){if(typeof Q?.database!=="string")throw new U("invalid_input","relation requires config.database (target database id)")}}function PX(X,Q){return(X.query("SELECT MAX(position) AS m FROM properties WHERE database_id = ? AND __deleted = 0").get(Q).m??0)+1}var wQ=S(function(Q,$,Z){if(!E(Q,$))throw new U("not_found",`no such database: ${$}`);if(!EQ.has(Z.type))throw new U("invalid_input",`unknown property type: ${Z.type}`);YQ(Z.type,Z.config);let W=Z.indexed?{...Z.config??{},indexed:!0}:Z.config??null,z=i("prop",Z.name);if(L(Q,"properties",z,"database_id",$),L(Q,"properties",z,"name",Z.name),L(Q,"properties",z,"type",Z.type),L(Q,"properties",z,"config",W),L(Q,"properties",z,"position",Z.position??PX(Q,$)),Z.type==="relation"||Z.indexed===!0)UQ(Q,$,z);return JQ(Q,z)});function JQ(X,Q){let $=X.query(`SELECT ${vQ} FROM properties WHERE id = ? AND __deleted = 0`).get(Q);if(!$)return null;return{...$,config:$.config?JSON.parse($.config):null}}function n(X,Q){return X.query(`SELECT ${vQ} FROM properties WHERE database_id = ? AND __deleted = 0 ORDER BY position`).all(Q).map((Z)=>({...Z,config:Z.config?JSON.parse(Z.config):null}))}var M1=S(function(Q,$,Z){let W=JQ(Q,$);if(!W)throw new U("not_found",`no such property: ${$}`);let z=Z.type!==void 0&&Z.type!==W.type;if(Z.type!==void 0&&!EQ.has(Z.type))throw new U("invalid_input",`unknown property type: ${Z.type}`);let j=Z.type??W.type;if(Z.config!==void 0)YQ(j,Z.config);else if(z)YQ(Z.type,void 0);if(Z.name!==void 0)L(Q,"properties",$,"name",Z.name);if(Z.type!==void 0)L(Q,"properties",$,"type",Z.type);if(Z.config!==void 0)L(Q,"properties",$,"config",Z.config);if(Z.position!==void 0)L(Q,"properties",$,"position",Z.position);if(z){let J=Q.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(W.database_id,$);for(let V of J)L(Q,"records",V.id,$,null)}return JQ(Q,$)});var k1=S(function(Q,$){let Z=JQ(Q,$);if(!Z)return!1;L(Q,"properties",$,"__deleted",1);let W=Q.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(Z.database_id,$);for(let z of W)L(Q,"records",z.id,$,void 0);return!0});var SX={db:{table:"databases",nameCol:"name",scoped:!1,noun:"database"},prop:{table:"properties",nameCol:"name",scoped:!0,noun:"property"},rec:{table:"records",nameCol:null,scoped:!0,noun:"record"},doc:{table:"documents",nameCol:"title",scoped:!0,noun:"document"}},TX=["db","prop","rec","doc"];function RX(X){return X!==null&&X!=="blk"}var hQ="{";function MX(X,Q){return X.query("SELECT id FROM properties WHERE database_id = ? AND type = 'text' AND __deleted = 0 ORDER BY position LIMIT 1").get(Q)?.id??null}function kX(X,Q,$,Z){let W=SX[Q],z=W.nameCol;if(Q==="rec"&&Z){let O=MX(X,Z);if(O)z=`data ->> '${O.replace(/'/g,"''")}'`}let j=z??"''",J=[],V=[];J.push("(id >= ? AND id < ?)"),V.push($,$+hQ);let B=`${Q}_${$}`;if(J.push("(id >= ? AND id < ?)"),V.push(B,B+hQ),z)J.push(`lower(${z}) = lower(?)`),V.push($);let _=`SELECT id, ${j} AS label FROM ${W.table} WHERE __deleted = 0 AND (${J.join(" OR ")})`;if(W.scoped&&Z)_+=" AND database_id = ?",V.push(Z);return X.query(_).all(...V).map((O)=>({kind:Q,id:O.id,label:O.label??""}))}function mQ(X,Q,$={}){let Z=$.kind?[$.kind]:RX(t(Q))?[t(Q)]:TX,W=[],z=new Set;for(let j of Z)for(let J of kX(X,j,Q,$.databaseId)){if(z.has(J.id))continue;z.add(J.id),W.push(J)}return W}function HQ(X,Q){if(Q!==null&&X>=Q)throw Error(`fracdex: ${X} >= ${Q}`);if(X.endsWith("0")||Q!==null&&Q.endsWith("0"))throw Error(`fracdex: trailing zero in ${X}/${Q}`);if(Q!==null){let z=0;while((X[z]??"0")===Q[z])z++;if(z>0)return Q.slice(0,z)+HQ(X.slice(z),Q.slice(z))}let Z=X===""?0:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".indexOf(X[0]),W=Q===null?62:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".indexOf(Q[0]);if(W-Z>1)return"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[Math.round(0.5*(Z+W))];if(Q!==null&&Q.length>1)return Q.slice(0,1);return"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[Z]+HQ(X.slice(1),null)}function m(X,Q){return HQ(X??"",Q)}function r(X,Q,$){if($<=0)return[];if($===1)return[m(X,Q)];if(Q===null){let z=m(X,null),j=[z];for(let J=1;J<$;J++)z=m(z,null),j.push(z);return j}if(X===null){let z=m(null,Q),j=[z];for(let J=1;J<$;J++)z=m(null,z),j.unshift(z);return j}let Z=Math.floor($/2),W=m(X,Q);return[...r(X,W,Z),W,...r(W,Q,$-Z-1)]}function fQ(X){return typeof X==="string"||typeof X==="number"||typeof X==="boolean"}function yX(X){return typeof X==="boolean"?X?1:0:X}function IX(X,Q,$){let Z=Q.config?.database;if(!Z)return $;let W=mQ(X,$,{kind:"rec",databaseId:Z}),z=W.find((j)=>j.id===$);if(z)return z.id;if(W.length===1)return W[0].id;if(W.length===0){if(t($)==="rec")return $;throw new U("not_found",`${Q.name}: no such record in target database: ${$}`)}throw new U("ambiguous",`${Q.name}: ambiguous relation "${$}" (${W.length} matches); use a full id`)}function LQ(X,Q,$){switch(Q.type){case"text":case"url":case"date":{if($===null)return null;if(typeof $!=="string")throw new U("invalid_input",`${Q.name} expects a string`);return $}case"number":{if($===null)return null;let Z=typeof $==="number"?$:Number($);if(!Number.isFinite(Z))throw new U("invalid_input",`${Q.name} expects a number`);return Z}case"checkbox":{if(typeof $==="boolean")return $;if($==="true"||$===1)return!0;if($==="false"||$===0||$===null)return!1;throw new U("invalid_input",`${Q.name} expects a boolean`)}case"select":{if($===null)return null;let Z=String($);if(!Q.config?.options?.includes(Z))throw new U("invalid_input",`${Q.name}: '${Z}' is not an allowed option`);return Z}case"multi_select":{let Z=$===null?[]:Array.isArray($)?$:[$],W=Q.config?.options??[];for(let z of Z)if(!W.includes(String(z)))throw new U("invalid_input",`${Q.name}: '${z}' is not an allowed option`);return Z.map(String)}case"relation":return($===null?[]:Array.isArray($)?$:[$]).map((W)=>IX(X,Q,String(W)))}}function gX(X){let Q=new Map;for(let $ of X){let Z=$.name.toLowerCase(),W=Q.get(Z);if(W)W.push($);else Q.set(Z,[$])}return Q}function AQ(X,Q){let $=new Map(X.map((z)=>[z.id,z])),Z=gX(X),W=[];for(let[z,j]of Object.entries(Q)){let J=$.get(z);if(!J){let V=Z.get(z.toLowerCase())??[];if(V.length>1)throw new U("ambiguous",`property name "${z}" matches ${V.length} properties; use a property id`);J=V[0]}if(!J)throw new U("not_found",`unknown property: ${z}`);W.push({prop:J,value:j})}return W}function nQ(X,Q,$){return AQ(n(X,Q),$).map(({prop:Z,value:W})=>({prop:Z,value:LQ(X,Z,W)}))}function bQ(X,Q){let $=JSON.parse(X.data||"{}"),Z=new Map(Q.map((j)=>[j.id,j])),W={},z={};for(let[j,J]of Object.entries($)){let V=Z.get(j);if(!V)continue;W[V.name]=J,z[V.id]=J}return{id:X.id,database_id:X.database_id,values:W,cells:z}}function EX(X,Q){let $=X.find((Z)=>Z.prop.type==="text"&&typeof Z.value==="string"&&Z.value);return i("rec",$?String($.value):"",Q)}function uQ(X,Q){return X.query("SELECT 1 AS ok FROM sqlite_master WHERE type = 'table' AND name = ?").get(Q)!=null}function vX(X){return uQ(X,"meta")&&uQ(X,"crdt_changes")}function wX(X,Q,$,Z){if(Z)L(X,"records",Q,"order_key",$);else X.query("UPDATE records SET order_key = ? WHERE id = ?").run($,Q)}function lQ(X,Q){return X.query(`SELECT order_key FROM records
4
+ WHERE database_id = ? AND __deleted = 0 AND order_key IS NOT NULL
5
+ ORDER BY order_key DESC, id DESC LIMIT 1`).get(Q)?.order_key??null}function qQ(X,Q){return X.query(`SELECT id, database_id, created_hlc, order_key FROM records
6
+ WHERE database_id = ? AND __deleted = 0
7
+ ORDER BY order_key IS NULL, order_key, created_hlc, id`).all(Q)}function hX(X,Q){let $=qQ(X,Q),Z=r(null,null,$.length);$.forEach((W,z)=>{if(W.order_key!==Z[z])L(X,"records",W.id,"order_key",Z[z])})}var mX=S(function(Q,$){let Z=vX(Q),W=$?[{database_id:$}]:Q.query(`SELECT DISTINCT database_id FROM records
8
+ WHERE database_id IS NOT NULL AND __deleted = 0 AND order_key IS NULL`).all();for(let z of W){let j=Q.query(`SELECT id FROM records
9
+ WHERE database_id = ? AND __deleted = 0 AND order_key IS NULL
10
+ ORDER BY created_hlc, id`).all(z.database_id);if(!j.length)continue;let J=lQ(Q,z.database_id),V=r(J,null,j.length);j.forEach((B,_)=>wX(Q,B.id,V[_],Z))}}),pQ=S(function(Q,$,Z){let W=EX(Z,VQ($.name,"rec")),z=m(lQ(Q,$.id),null),j=L(Q,"records",W,"database_id",$.id);L(Q,"records",W,"created_hlc",j.hlc),L(Q,"records",W,"order_key",z);for(let{prop:J,value:V}of Z)L(Q,"records",W,J.id,V);return d(Q,W)}),iQ=S(function(Q,$,Z){let W=E(Q,$);if(!W)throw new U("not_found",`no such database: ${$}`);return pQ(Q,W,nQ(Q,W.id,Z))});function d(X,Q){let $=X.query("SELECT id, database_id, data FROM records WHERE id = ? AND __deleted = 0").get(Q);if(!$)return null;return bQ($,n(X,$.database_id))}function cQ(X){return X.replace(/'/g,"''")}function oQ(X,Q,$={}){let Z=n(X,Q),W=$.filter&&Object.keys($.filter).length?AQ(Z,$.filter).map(({prop:K,value:R})=>({prop:K,value:LQ(X,K,R)})):[],z=W.filter((K)=>fQ(K.value)),j=W.filter((K)=>!fQ(K.value)),J,V=!1;if($.sort){let K=$.sort;if(K.startsWith("-"))V=!0,K=K.slice(1);if(K!=="created"&&K!=="created_hlc"){let R=Z.find((v)=>v.id===K);if(!R){let v=Z.filter((u)=>u.name.toLowerCase()===K.toLowerCase());if(v.length>1)throw new U("ambiguous",`sort field "${K}" matches ${v.length} properties; use a property id`);R=v[0]}if(!R)throw new U("not_found",`unknown sort field: ${K}`);J=R}}for(let K of z)GQ(X,Q,K.prop);if(J)GQ(X,Q,J);let B=["database_id = ?","__deleted = 0"],_=[Q];for(let K of z)B.push(`data ->> '${cQ(K.prop.id)}' = ?`),_.push(yX(K.value));let C=$.sort==null,O=J?`data ->> '${cQ(J.id)}'`:"created_hlc",T=`SELECT id, database_id, data FROM records WHERE ${B.join(" AND ")} `+(C?"ORDER BY order_key IS NULL, order_key, id":`ORDER BY ${O} ${V?"DESC":"ASC"}, id`);if($.limit!=null&&j.length===0)T+=" LIMIT ?",_.push($.limit);let y=X.query(T).all(..._).map((K)=>bQ(K,Z));if(j.length){if(y=y.filter((K)=>j.every((R)=>JSON.stringify(K.cells[R.prop.id]??null)===JSON.stringify(R.value))),$.limit!=null)y=y.slice(0,$.limit)}return y}var l1=S(function(Q,$,Z,W){if(W!=="before"&&W!=="after")throw new U("invalid_input",`unknown move position: ${W}`);let z=Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get($);if(!z)throw new U("not_found",`no such record: ${$}`);let j=Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get(Z);if(!j)throw new U("not_found",`no such record: ${Z}`);if(z.database_id!==j.database_id)throw new U("invalid_input","cannot move a record across databases");if($===Z)return d(Q,$);mX(Q,z.database_id);let J=qQ(Q,z.database_id).filter((C)=>C.id!==$),V=J.findIndex((C)=>C.id===Z);if(V<0)throw new U("not_found",`no such target record: ${Z}`);let B=W==="before"?J[V-1]?.order_key??null:J[V].order_key,_=W==="before"?J[V].order_key:J[V+1]?.order_key??null;if(B!==null&&_!==null&&B>=_)hX(Q,z.database_id),J=qQ(Q,z.database_id).filter((C)=>C.id!==$),V=J.findIndex((C)=>C.id===Z),B=W==="before"?J[V-1]?.order_key??null:J[V].order_key,_=W==="before"?J[V].order_key:J[V+1]?.order_key??null;return L(Q,"records",$,"order_key",m(B,_)),d(Q,$)}),sQ=S(function(Q,$,Z){if(!Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get($))throw new U("not_found",`no such record: ${$}`);for(let{prop:z,value:j}of Z)L(Q,"records",$,z.id,j);return d(Q,$)}),p1=S(function(Q,$,Z){let W=Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get($);if(!W)throw new U("not_found",`no such record: ${$}`);return sQ(Q,$,nQ(Q,W.database_id,Z))}),i1=S(function(Q,$){if(!Q.query("SELECT id FROM records WHERE id = ? AND __deleted = 0").get($))return!1;return L(Q,"records",$,"__deleted",1),!0});var fX=["id","name","icon","meta","created_hlc"];var uX=fX.join(", ");function cX(X){if(!X)return null;return{...X,meta:X.meta===null?null:JSON.parse(X.meta)}}var nX=S(function(Q,$){let Z=i("db",$.name),W=L(Q,"databases",Z,"name",$.name);if(L(Q,"databases",Z,"created_hlc",W.hlc),$.icon!==void 0)L(Q,"databases",Z,"icon",$.icon);return E(Q,Z)}),e1=S(function(Q,$,Z){if(!E(Q,$))throw new U("not_found",`no such database: ${$}`);if(Z.name!==void 0)L(Q,"databases",$,"name",Z.name);if(Z.icon!==void 0)L(Q,"databases",$,"icon",Z.icon);if(Z.meta!==void 0){if(Z.meta!==null&&(typeof Z.meta!=="object"||Array.isArray(Z.meta)))throw new U("invalid_input","meta must be a JSON object or null");L(Q,"databases",$,"meta",Z.meta)}return E(Q,$)}),Q4=S(function(Q,$,Z={}){let W=E(Q,$);if(!W)throw new U("not_found",`no such database: ${$}`);let z=nX(Q,{name:Z.name??W.name,icon:Z.icon??W.icon??void 0});if(W.meta!==null){let{collapsed:J,...V}=W.meta;if(Object.keys(V).length)L(Q,"databases",z.id,"meta",V)}let j=new Map;for(let J of n(Q,$)){let V=J.config?.database===$?{...J.config,database:z.id}:J.config??void 0,B=wQ(Q,z.id,{name:J.name,type:J.type,config:V,position:J.position});j.set(J.id,B.id)}for(let J of oQ(Q,$)){let V={};for(let[B,_]of Object.entries(J.cells)){let C=j.get(B);if(C)V[C]=_}iQ(Q,z.id,V)}return E(Q,z.id)});function E(X,Q){return cX(X.query(`SELECT ${uX} FROM databases WHERE id = ? AND __deleted = 0`).get(Q))}var X4=S(function(Q,$){if(!E(Q,$))return!1;L(Q,"databases",$,"__deleted",1);let Z=(W)=>{for(let z of aQ(Q,W,"database_id",$))L(Q,W,z,"__deleted",1)};Z("properties"),Z("records");for(let W of aQ(Q,"documents","database_id",$))L(Q,"documents",W,"database_id",null);return Q.query("DELETE FROM meta WHERE key = 'current_db' AND value = ?").run($),!0});function aQ(X,Q,$,Z){return X.query(`SELECT id FROM ${Q} WHERE ${$} = ? AND __deleted = 0`).all(Z).map((W)=>W.id)}var rQ="sealed-p256";var bX=12,lX="mh-drop-seal-v1",tQ={name:"ECDH",namedCurve:"P-256"};function e(X){let Q=new Uint8Array(X.byteLength);return Q.set(X),Q.buffer}function dQ(...X){let Q=X.reduce((W,z)=>W+z.byteLength,0),$=new Uint8Array(Q),Z=0;for(let W of X)$.set(W,Z),Z+=W.byteLength;return $}async function pX(X,Q,$){let Z=new Uint8Array(await crypto.subtle.digest("SHA-256",e($))),W=dQ(new TextEncoder().encode(lX),Q,Z),z=await crypto.subtle.importKey("raw",X,"HKDF",!1,["deriveKey"]);return crypto.subtle.deriveKey({name:"HKDF",hash:"SHA-256",salt:new Uint8Array(16).buffer,info:e(W)},z,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}async function eQ(X,Q){let $=await crypto.subtle.importKey("raw",e(X),tQ,!1,[]),Z=await crypto.subtle.generateKey(tQ,!0,["deriveBits"]),W=new Uint8Array(await crypto.subtle.exportKey("raw",Z.publicKey)),z=await crypto.subtle.deriveBits({name:"ECDH",public:$},Z.privateKey,256),j=await pX(z,W,X),J=crypto.getRandomValues(new Uint8Array(bX)),V=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:e(J)},j,e(Q)));return dQ(W,J,V)}var QX=/^g[0-9a-z]{8}$/;function iX(){return"e"+g(16)}function XX(){return"g"+g(8)}function oX(X){return new TextEncoder().encode(JSON.stringify(X))}async function $X(X){let Q=await eQ(X.pk,oX(X.payload));return{v:1,envelope_id:iX(),drop_id:X.dropId,enc:rQ,key_id:X.keyId,sealed:$Q(Q),created_at:X.now??Date.now()}}async function NQ(X,Q){return $Q(await OQ(X,ZQ(Q)))}function ZX(){try{if(typeof localStorage<"u"&&localStorage)return localStorage.getItem("mh_drop_probe"),{get:(Q)=>localStorage.getItem(Q),set:(Q,$)=>localStorage.setItem(Q,$)}}catch{}let X=new Map;return{get:(Q)=>X.get(Q)??null,set:(Q,$)=>X.set(Q,$)}}function sX(X){if(X===401)return"auth";if(X===404)return"not_found";if(X===429)return"rate_limited";if(X===400||X===413)return"invalid_input";return"network"}async function KQ(X="mh-drop.json",Q={}){let Z=await(Q.fetcher??fetch)(X);if(!Z.ok)throw new U("not_found",`no drop config at ${X}`);let W=await Z.json().catch(()=>null);if(!W||W.v!==1||!W.endpoint||!W.drop_id||!W.key_id||!W.pk)throw new U("invalid_input","malformed mh-drop.json");return aX(W,Z.headers.get("date"),Q),FQ(W,Q)}function aX(X,Q,$){if(!Q)return;let Z=Date.parse(Q);if(!Number.isFinite(Z))return;let W=$.storage??ZX(),z="mh_drop_clock:"+X.endpoint.replace(/\/+$/,"");if(W.get(z))return;let j=$.now??(()=>Date.now());W.set(z,String(Z-j()))}function FQ(X,Q={}){let $=Q.storage??ZX(),Z=Q.fetcher??fetch,W=Q.now??(()=>Date.now()),z=X.endpoint.replace(/\/+$/,""),j="mh_drop_guest",J=$.get("mh_drop_guest");if(!J||!QX.test(J))J=XX(),$.set("mh_drop_guest",J);let V="mh_drop_clock:"+z,B=Number($.get(V)??"0")||0,_="mh_drop_hlc:"+J,C=/^(\d+):(\d+)$/.exec($.get(_)??""),O=C?{millis:Number(C[1]),counter:Number(C[2])}:{millis:0,counter:0};function T(){let G=W()+B,H=Math.max(O.millis,G),A=H===O.millis?O.counter+1:0;return O={millis:H,counter:A},$.set(_,`${H}:${A}`),`${String(H).padStart(15,"0")}-${A.toString(16).padStart(4,"0")}-${J}`}let o="mh_drop_pending:"+X.drop_id;function y(){try{let G=$.get(o),H=G?JSON.parse(G):[];return Array.isArray(H)?H:[]}catch{return[]}}function K(G){$.set(o,JSON.stringify(G))}function R(G){let H=X.databases??[],A=H.find((N)=>N.id===G)??H.find((N)=>N.name.toLowerCase()===G.toLowerCase());if(!A)throw new U("not_found",`"${G}" is not a submittable table on this page`);return A}function v(G,H){let A=G.properties.find((N)=>N.id===H)??G.properties.find((N)=>N.name.toLowerCase()===H.toLowerCase());if(!A)throw new U("not_found",`unknown column: ${H}`);return A}let u=null;function F(){return u??=(async()=>{if(!Q.password||!X.password_salt)return null;return NQ(Q.password,X.password_salt)})(),u}async function Y(G,H,A={}){let N=R(G),P="rec_"+g(10),x={},M={},I={};for(let[f,c]of Object.entries(H)){let p=v(N,f);x[p.id]=c,M[p.name]=c,I[p.id]=c??null}let QQ=(X.payload_versions??[1]).includes(2),b;if(QQ){let f={intentId:"int_"+g(16),action:"createRecord",table:N.id,recordId:P,payload:I,submittedAt:W()+B};b={v:2,guest_node:J,intents:[f]}}else{let f=[],c=(jQ,a,FX)=>{f.push({hlc:FX,node_id:J,dataset:"records",row_id:P,col:jQ,value:a===void 0||a===null?null:JSON.stringify(a)})},p=T();c("database_id",N.id,p),c("created_hlc",p,T());for(let[jQ,a]of Object.entries(I))c(jQ,a,T());b={v:1,guest_node:J,changes:f}}let l=await $X({dropId:X.drop_id,keyId:X.key_id,pk:ZQ(X.pk),payload:b,now:W()}),w={"content-type":"application/json"},XQ=await F();if(XQ)w["x-drop-pass"]=XQ;if(A.turnstileToken)w["x-turnstile-token"]=A.turnstileToken;let h;try{h=await Z(`${z}/v1/inbox/${encodeURIComponent(X.drop_id)}/envelopes`,{method:"POST",headers:w,body:JSON.stringify(l)})}catch(f){throw new U("network",`drop submission failed: ${f.message}`)}let s=await h.json().catch(()=>null);if(!h.ok)throw new U(sX(h.status),s?.error??`drop submission failed (HTTP ${h.status})`);if(typeof s?.server_time==="number")B=s.server_time-W(),$.set(V,String(B));let DQ={id:P,database_id:N.id,values:M,cells:x,_pending:!0,envelope_id:l.envelope_id,created_at:W()};return K([...y(),DQ]),DQ}function q(G){let H=y();if(!G)return H;let A=R(G).id;return H.filter((N)=>N.database_id===A)}function D(G,H){let A=new Set(G.map((I)=>I.id)),N=y(),P=N.filter((I)=>!A.has(I.id));if(P.length!==N.length)K(P);let x=H?R(H).id:null,M=P.filter((I)=>x===null||I.database_id===x);return[...G,...M]}return{config:X,guest:J,createRecord:Y,pending:q,merge:D}}class k extends Error{code;status;constructor(X,Q,$){super(X);this.code=Q;this.status=$;this.name="MetahubError"}}var WX="mh_token",zX="/auth/token",tX=5000;function rX(X){let Q=X??(typeof location<"u"&&location?location.pathname:""),$=/^\/(sites|share|r)\/[^/]+/.exec(Q);return $?$[0]:""}function JX(X){let Q=X;if(/^https?:\/\//i.test(X))try{Q=new URL(X).pathname.replace(/\/+$/,"")}catch{return!1}return/^\/(sites|share|r)\/[^/]+$/.test(Q)}function dX(X){if(!X||typeof X!=="object"||Array.isArray(X))return!1;let Q=X;return typeof Q.id==="string"&&Q.id.length>0&&typeof Q.name==="string"&&Q.name.length>0&&Array.isArray(Q.properties)&&Q.properties.every(($)=>{if(!$||typeof $!=="object"||Array.isArray($))return!1;let Z=$;return typeof Z.id==="string"&&Z.id.length>0&&typeof Z.name==="string"&&Z.name.length>0&&typeof Z.type==="string"&&Z.type.length>0})}function eX(X){if(!X||typeof X!=="object"||Array.isArray(X))throw new k("malformed mh-manifest.json","invalid_input",500);let Q=X;if(Q.v!==1||Q.mode!=="live"&&Q.mode!=="static-async"||!Number.isInteger(Q.policyRevision)||Q.policyRevision<0||Q.runtimeEndpoint!==void 0&&typeof Q.runtimeEndpoint!=="string"||Q.websocketEndpoint!==void 0&&typeof Q.websocketEndpoint!=="string"||Q.inboxEndpoint!==void 0&&typeof Q.inboxEndpoint!=="string"||Q.fallback!==void 0&&Q.fallback!=="inbox")throw new k("malformed mh-manifest.json","invalid_input",500);if(Q.drop!==void 0){let $=Q.drop;if(!$||typeof $!=="object"||typeof $.drop_id!=="string"||!$.drop_id||typeof $.key_id!=="string"||!$.key_id||typeof $.pk!=="string"||!$.pk||$.payload_versions!==void 0&&(!Array.isArray($.payload_versions)||!$.payload_versions.every((Z)=>Number.isInteger(Z)&&Z>0))||$.databases!==void 0&&(!Array.isArray($.databases)||!$.databases.every(dX))||$.password_salt!==void 0&&(typeof $.password_salt!=="string"||!$.password_salt)||$.turnstile_sitekey!==void 0&&(typeof $.turnstile_sitekey!=="string"||!$.turnstile_sitekey))throw new k("malformed mh-manifest.json drop config","invalid_input",500)}if((Q.mode==="static-async"||Q.fallback==="inbox")&&(!Q.inboxEndpoint||!Q.drop))throw new k("inbox deployment is missing endpoint or drop config","invalid_input",500);return Q}function Q1(X,Q){if(!X)return Q;if(/^https?:\/\//i.test(X))return X.replace(/\/+$/,"");if(/^https?:\/\//i.test(Q))return new URL(X,Q.endsWith("/")?Q:Q+"/").toString().replace(/\/+$/,"");if(X.startsWith("/"))return X.replace(/\/+$/,"");return`${Q}/${X}`.replace(/\/+/g,"/").replace(/\/+$/,"")}function X1(X={}){let Q=(X.baseUrl??rX()).replace(/\/$/,""),$=JX(Q),Z=X.manifestUrl!==void 0||X.baseUrl===void 0||$,W=X.manifestUrl??`${Q}/mh-manifest.json`,z=/^https?:\/\//i.test(Q)?new URL(zX,Q).toString():zX,j=()=>{if(X.token)return X.token;try{return typeof localStorage<"u"?localStorage.getItem(WX):null}catch{return null}},J=(F)=>{try{localStorage.setItem(WX,F)}catch{}};async function V(F,Y,q,D,G={}){let H=(x)=>{let M={...G};if(D!==void 0)M["content-type"]="application/json";if(x)M.authorization=`Bearer ${x}`;return fetch(F+q,{method:Y,headers:M,body:D!==void 0?JSON.stringify(D):void 0})},A=j(),N=await H(A);if(N.status===401&&A&&!X.token){let x=await fetch(z,{headers:{authorization:`Bearer ${A}`}}).catch(()=>null),M=x?.ok?await x.json():null;if(M?.token)J(M.token),A=M.token,N=await H(A)}let P=await N.json().catch(()=>null);if(!N.ok||P&&P.error)throw new k(P?.error??`${N.status} ${N.statusText}`,P?.code,N.status);return P}let B=null,_=()=>{if(!Z)return Promise.resolve(null);if(B)return B;let F=(async()=>{let Y;try{Y=await fetch(W,{signal:typeof AbortSignal<"u"&&typeof AbortSignal.timeout==="function"?AbortSignal.timeout(tX):void 0})}catch(q){throw new k(`deployment manifest unavailable: ${q.message}`,"network",0)}if(Y.status===404)return null;if(!Y.ok)throw new k(`deployment manifest failed (HTTP ${Y.status})`,"network",Y.status);return eX(await Y.json().catch(()=>null))})();return B=F,F.catch(()=>{if(B===F)B=null}),F},C=(F)=>{if(F?.mode==="static-async")throw new k("static-async deployment has no live runtime","invalid_input",400);return Q1(F?.runtimeEndpoint,Q)},O=async(F,Y,q,D)=>{let G=await _();return V(C(G),F,Y,q,D)},T=(F)=>encodeURIComponent(F),o=()=>"int_"+Math.random().toString(36).slice(2,10)+Date.now().toString(36),y=null,K=(F)=>{return y??=(F?.drop&&F.inboxEndpoint?Promise.resolve(FQ({...F.drop,v:1,endpoint:F.inboxEndpoint},{password:X.dropPassword})):KQ(`${Q}/mh-drop.json`,{password:X.dropPassword})).catch(()=>null),y},R=null,v=async(F,Y)=>{let q={};if(Y.turnstileToken)q["x-turnstile-token"]=Y.turnstileToken;let D=F?.drop?.password_salt;if(X.dropPassword&&D)R??=NQ(X.dropPassword,D),q["x-drop-pass"]=await R;return q},u=async(F,Y,q,D,G)=>{let H=C(F),A=JX(H),N=A?{$intent:{id:o(),submittedAt:Date.now()},values:D}:D,P=await v(F,G);try{return await V(H,Y,q,N,P)}catch(x){if(F===null&&A&&x instanceof k&&(x.status===400||x.status===404))return V(H,Y,q,D,P);throw x}};return{listDatabases:()=>O("GET","/api/databases"),createDatabase:(F)=>O("POST","/api/databases",F),listProperties:(F)=>O("GET",`/api/properties?db=${T(F)}`),listRecords:(F,Y={})=>{let q=new URLSearchParams({db:F});if(Y.sort)q.set("sort",Y.sort);if(Y.limit!=null)q.set("limit",String(Y.limit));return O("GET",`/api/records?${q}`)},getRecord:(F)=>O("GET",`/api/record?id=${T(F)}`),createRecord:async(F,Y,q={})=>{let D=await _();if(D?.mode==="static-async"){let G=await K(D);if(!G)throw new k("static-async inbox is unavailable","network",0);return G.createRecord(F,Y,q)}try{return await u(D,"POST",`/api/records?db=${T(F)}`,Y,q)}catch(G){if(!(G instanceof k?G.status===401:!0))throw G;if(D&&D.fallback!=="inbox")throw G;let A=await K(D);if(!A)throw G;return A.createRecord(F,Y,q)}},updateRecord:async(F,Y,q={})=>{let D=await _();if(D?.mode==="static-async")throw new k("static-async deployment does not support updateRecord","invalid_input",400);return u(D,"PATCH",`/api/record?id=${T(F)}`,Y,q)},deleteRecord:async(F)=>{let Y=await _();if(Y?.mode==="static-async")throw new k("static-async deployment does not support deleteRecord","invalid_input",400);return V(C(Y),"DELETE",`/api/record?id=${T(F)}`)},listDocuments:(F)=>O("GET",F?`/api/documents?db=${T(F)}`:"/api/documents"),getDocument:(F)=>O("GET",`/api/document?id=${T(F)}`),createDocument:(F)=>O("POST","/api/documents",F),updateDocument:(F,Y)=>O("PATCH",`/api/document?id=${T(F)}`,Y),deleteDocument:(F)=>O("DELETE",`/api/document?id=${T(F)}`),search:(F,Y)=>{let q=new URLSearchParams({q:F});if(Y!=null)q.set("limit",String(Y));return O("GET",`/api/search?${q}`)},onUpdate(F,Y={}){let q=!1,D=null,G=null,H=null,A=/(^|\/)r\/[^/]+$/.test(Q)?Q:null;if(A&&typeof WebSocket<"u"){let N=/^https?:\/\//i.test(A)?new URL(A+"/ws"):new URL(A+"/ws",typeof location<"u"?location.href:"http://localhost"),P=N.toString();N.protocol=N.protocol==="https:"?"wss:":"ws:";let x=0,M=new Set([4401,4403]),I=()=>{q=!0,F({gone:!0})},QQ=()=>{if(q)return;let b=!1;D=new WebSocket(N.toString()),D.onopen=()=>{b=!0,H=setTimeout(()=>{x=0},5000)},D.onmessage=(l)=>{try{let w=JSON.parse(String(l.data));if(w?.type==="poke")F({seq:w.seq})}catch{}},D.onerror=()=>{},D.onclose=(l)=>{if(H!=null)clearTimeout(H),H=null;if(q)return;if(M.has(l.code)){I();return}let w=Math.min(30000,1000*2**x++),XQ=w*0.25*Math.random(),h=()=>{G=setTimeout(QQ,w+XQ)};if(!b&&x>=3)fetch(P).then((s)=>{if(q)return;if(s.status===404)I();else h()}).catch(()=>{if(!q)h()});else h()}};QQ()}else if(Y.pollMs&&Y.pollMs>0)G=setInterval(()=>F({}),Y.pollMs);return()=>{if(q=!0,G!=null)clearTimeout(G),clearInterval(G);if(H!=null)clearTimeout(H);try{D?.close()}catch{}}}}}var T4=X1();export{KQ as initDrop,rX as detectBase,FQ as createDrop,X1 as createClient,T4 as api,k as MetahubError};
@@ -1 +1 @@
1
- class M extends Error{code;constructor(x,z){super(x);this.code=z;this.name="BusError"}}class Z{ch=null;worker=null;started=!1;leader=!1;nextLocal=0;localPending=new Map;remotePending=new Map;listeners=new Set;start(){if(this.started)return;this.started=!0,this.ch=new BroadcastChannel("mh-replica-bus"),this.ch.onmessage=(z)=>this.onChannel(z.data);let x=navigator.locks;if(x)x.request("mh-replica-leader",()=>{return this.becomeLeader(),new Promise(()=>{})}).catch(()=>{});else this.becomeLeader()}onEvent(x){return this.listeners.add(x),()=>this.listeners.delete(x)}call(x,...z){if(!this.started)this.start();if(this.leader)return this.workerCall(x,z);return this.remoteCall(x,z)}becomeLeader(){if(this.leader)return;this.leader=!0,this.spawnWorker();for(let[x,z]of[...this.remotePending])this.remotePending.delete(x),clearTimeout(z.timer),this.workerCall(z.op,z.args).then(z.resolve,z.reject)}spawnWorker(){if(this.worker)return;this.worker=new Worker("/db-worker.js",{type:"module"}),this.worker.onmessage=(x)=>{let z=x.data;if("id"in z){let C=this.localPending.get(z.id);if(!C)return;if(this.localPending.delete(z.id),z.ok)C.resolve(z.result);else C.reject(new M(z.error.message,z.error.code));return}this.emit(z),this.ch?.postMessage({kind:"event",event:z})},this.worker.onerror=()=>{let x={event:"status",status:{state:"error",paired:!1,node:null,error:"worker crashed"}};this.emit(x),this.ch?.postMessage({kind:"event",event:x})}}workerCall(x,z){if(!this.worker)this.spawnWorker();let C=++this.nextLocal;return new Promise((D,F)=>{this.localPending.set(C,{resolve:D,reject:F}),this.worker.postMessage({id:C,op:x,args:z})})}remoteCall(x,z){let C=`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`;return new Promise((D,F)=>{let G=setTimeout(()=>{if(this.remotePending.delete(C),this.leader){this.workerCall(x,z).then(D,F);return}F(new M("replica leader unavailable","network"))},1e4);this.remotePending.set(C,{resolve:D,reject:F,timer:G,op:x,args:z}),this.ch?.postMessage({kind:"req",id:C,op:x,args:z})})}onChannel(x){if(x.kind==="req"){if(!this.leader)return;this.workerCall(x.op,x.args).then((z)=>this.ch?.postMessage({kind:"res",id:x.id,ok:!0,result:z}),(z)=>this.ch?.postMessage({kind:"res",id:x.id,ok:!1,error:{message:z.message,code:z.code}}));return}if(x.kind==="res"){let z=this.remotePending.get(x.id);if(!z)return;if(this.remotePending.delete(x.id),clearTimeout(z.timer),x.ok)z.resolve(x.result);else z.reject(new M(x.error?.message??"replica error",x.error?.code));return}if(x.kind==="event"&&!this.leader)this.emit(x.event)}emit(x){for(let z of this.listeners)z(x)}stopWorker(){this.worker?.terminate(),this.worker=null,this.localPending.forEach((x)=>x.reject(new M("replica stopped",void 0))),this.localPending.clear()}}function S(){let x=globalThis;return x.__mhReplicaBus??=new Z}var V="mh_token",y="/auth/token",Q=globalThis;function A(x){try{localStorage.setItem(V,x)}catch{}document.cookie=`${V}=${encodeURIComponent(x)}; path=/; SameSite=Strict; Max-Age=31536000`}if(!Q.__mhFetchShim){Q.__mhFetchShim=!0;let x=window.fetch.bind(window),z=function(C,D){D=D??{};let F=null;try{F=localStorage.getItem(V)}catch{}let G=null;try{G=new URL(typeof C==="string"||C instanceof URL?String(C):C.url,location.href)}catch{G=null}let L=G!=null&&G.origin===location.origin;if(L&&F){let I=new Headers(D.headers??(typeof C!=="string"&&!(C instanceof URL)?C.headers:void 0));if(!I.has("authorization"))I.set("authorization",`Bearer ${F}`);D.headers=I}return x(C,D).then((I)=>{let q=D.__mhRetried;if(I.status!==401||!L||!F||q)return I;return x(y,{headers:{authorization:`Bearer ${F}`}}).then((J)=>J.ok?J.json():null).then((J)=>{if(!J?.token)return I;A(J.token);let X=new Headers(D.headers);return X.set("authorization",`Bearer ${J.token}`),D.headers=X,D.__mhRetried=!0,x(C,D)}).catch(()=>I)})};window.fetch=z}if("serviceWorker"in navigator&&window.isSecureContext&&!window.metahubDesktop)navigator.serviceWorker.register("/sw.js").catch((x)=>{console.warn("[mh-runtime] service worker registration failed —",x)});function $(){try{return localStorage.getItem("mh_replica")==="1"&&localStorage.getItem("mh_replica_hydrated")==="1"}catch{return!1}}globalThis.__mhOfflineBootstrap=(x,z)=>{let C=(D)=>{document.body.innerHTML=`<p style="font:14px system-ui;color:#888;margin:2em">${D}</p>`};if(!$()||typeof Worker>"u"){C("当前离线,且此浏览器尚未启用本地副本。请先在线打开 Metahub,在设置中开启「离线副本」。");return}(async()=>{try{let D=S();D.start();let F=await D.call("siteFile",x,z);if(!F){C("离线副本中没有这个页面。");return}if(!F.content_type.includes("text/html")){C("此资源不是页面,无法离线打开。");return}let G=F.encoding==="utf8"?F.content??"":atob(F.content??""),L='<script src="/mh-runtime.js"></script>',I=G.toLowerCase().indexOf("<head>");G=I>=0?G.slice(0,I+6)+L+G.slice(I+6):L+G,document.open(),document.write(G),document.close()}catch(D){C(`离线加载失败:${D.message}`)}})()};if(!Q.__mhSwBridge&&"serviceWorker"in navigator)Q.__mhSwBridge=!0,navigator.serviceWorker.addEventListener("message",(x)=>{let z=x.data,C=x.ports?.[0];if(!z||z.kind!=="mh-rpc"||!C||!z.op)return;if(!$()||typeof Worker>"u"){C.postMessage({ok:!1,error:{message:"replica unavailable",code:"unavailable"}});return}let D=S();D.start(),D.call(z.op,...z.args??[]).then((F)=>C.postMessage({ok:!0,result:F}),(F)=>C.postMessage({ok:!1,error:{message:F.message,code:F.code}}))});
1
+ class Q extends Error{code;constructor(q,x){super(q);this.code=x;this.name="BusError"}}class L{ch=null;worker=null;started=!1;leader=!1;nextLocal=0;localPending=new Map;remotePending=new Map;listeners=new Set;start(){if(this.started)return;this.started=!0,this.ch=new BroadcastChannel("mh-replica-bus"),this.ch.onmessage=(x)=>this.onChannel(x.data);let q=navigator.locks;if(q)q.request("mh-replica-leader",()=>{return this.becomeLeader(),new Promise(()=>{})}).catch(()=>{});else this.becomeLeader()}onEvent(q){return this.listeners.add(q),()=>this.listeners.delete(q)}call(q,...x){if(!this.started)this.start();if(this.leader)return this.workerCall(q,x);return this.remoteCall(q,x)}becomeLeader(){if(this.leader)return;this.leader=!0,this.spawnWorker();for(let[q,x]of[...this.remotePending])this.remotePending.delete(q),clearTimeout(x.timer),this.workerCall(x.op,x.args).then(x.resolve,x.reject)}spawnWorker(){if(this.worker)return;this.worker=new Worker("/db-worker.js",{type:"module"}),this.worker.onmessage=(q)=>{let x=q.data;if("id"in x){let y=this.localPending.get(x.id);if(!y)return;if(this.localPending.delete(x.id),x.ok)y.resolve(x.result);else y.reject(new Q(x.error.message,x.error.code));return}this.emit(x),this.ch?.postMessage({kind:"event",event:x})},this.worker.onerror=()=>{let q={event:"status",status:{state:"error",paired:!1,node:null,error:"worker crashed"}};this.emit(q),this.ch?.postMessage({kind:"event",event:q})}}workerCall(q,x){if(!this.worker)this.spawnWorker();let y=++this.nextLocal;return new Promise((z,C)=>{this.localPending.set(y,{resolve:z,reject:C}),this.worker.postMessage({id:y,op:q,args:x})})}remoteCall(q,x){let y=`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`;return new Promise((z,C)=>{let D=setTimeout(()=>{if(this.remotePending.delete(y),this.leader){this.workerCall(q,x).then(z,C);return}C(new Q("replica leader unavailable","network"))},1e4);this.remotePending.set(y,{resolve:z,reject:C,timer:D,op:q,args:x}),this.ch?.postMessage({kind:"req",id:y,op:q,args:x})})}onChannel(q){if(q.kind==="req"){if(!this.leader)return;this.workerCall(q.op,q.args).then((x)=>this.ch?.postMessage({kind:"res",id:q.id,ok:!0,result:x}),(x)=>this.ch?.postMessage({kind:"res",id:q.id,ok:!1,error:{message:x.message,code:x.code}}));return}if(q.kind==="res"){let x=this.remotePending.get(q.id);if(!x)return;if(this.remotePending.delete(q.id),clearTimeout(x.timer),q.ok)x.resolve(q.result);else x.reject(new Q(q.error?.message??"replica error",q.error?.code));return}if(q.kind==="event"&&!this.leader)this.emit(q.event)}emit(q){for(let x of this.listeners)x(q)}stopWorker(){this.worker?.terminate(),this.worker=null,this.localPending.forEach((q)=>q.reject(new Q("replica stopped",void 0))),this.localPending.clear()}}function Z(){let q=globalThis;return q.__mhReplicaBus??=new L}var W='<script src="/mh-runtime.js"></script>';function G(q){let x=q.toLowerCase().indexOf("<head>");if(x>=0)return q.slice(0,x+6)+W+q.slice(x+6);return W+q}var V="mh_token",I="/auth/token",X=globalThis;function H(q){try{localStorage.setItem(V,q)}catch{}document.cookie=`${V}=${encodeURIComponent(q)}; path=/; SameSite=Strict; Max-Age=31536000`}function M(){try{let q=localStorage.getItem(V);if(q)return q}catch{}for(let q of document.cookie.split(";")){let[x,...y]=q.trim().split("=");if(x===V){let z=decodeURIComponent(y.join("="))||null;if(z)H(z);return z}}return null}if(!X.__mhFetchShim){X.__mhFetchShim=!0;let q=window.fetch.bind(window),x=function(y,z){z=z??{};let C=M(),D=null;try{D=new URL(typeof y==="string"||y instanceof URL?String(y):y.url,location.href)}catch{D=null}let S=D!=null&&D.origin===location.origin;if(S&&C){let F=new Headers(z.headers??(typeof y!=="string"&&!(y instanceof URL)?y.headers:void 0));if(!F.has("authorization"))F.set("authorization",`Bearer ${C}`);z.headers=F}return q(y,z).then((F)=>{let A=z.__mhRetried;if(F.status!==401||!S||!C||A)return F;return q(I,{headers:{authorization:`Bearer ${C}`}}).then((J)=>J.ok?J.json():null).then((J)=>{if(!J?.token)return F;H(J.token);let $=new Headers(z.headers);return $.set("authorization",`Bearer ${J.token}`),z.headers=$,z.__mhRetried=!0,q(y,z)}).catch(()=>F)})};window.fetch=x}if("serviceWorker"in navigator&&window.isSecureContext&&!window.metahubDesktop)navigator.serviceWorker.register("/sw.js").catch((q)=>{console.warn("[mh-runtime] service worker registration failed —",q)});function P(){try{return localStorage.getItem("mh_replica")==="1"&&localStorage.getItem("mh_replica_hydrated")==="1"}catch{return!1}}globalThis.__mhOfflineBootstrap=(q,x)=>{let y=(z)=>{let C=document.createElement("p");C.style.cssText="font:14px system-ui;color:#888;margin:2em",C.textContent=z,document.body.replaceChildren(C)};if(!P()||typeof Worker>"u"){y("当前离线,且此浏览器尚未启用本地副本。请先在线打开 Metahub,在设置中开启「离线副本」。");return}(async()=>{try{let z=Z();z.start();let C=await z.call("siteFile",q,x);if(!C){y("离线副本中没有这个页面。");return}if(!C.content_type.includes("text/html")){y("此资源不是页面,无法离线打开。");return}if(C.encoding==="blob"){y("此页面以二进制块存储,无法离线打开。");return}let D=C.encoding==="utf8"?C.content??"":atob(C.content??""),S=C.public?D:G(D);document.open(),document.write(S),document.close()}catch(z){y(`离线加载失败:${z.message}`)}})()};if(!X.__mhSwBridge&&"serviceWorker"in navigator)X.__mhSwBridge=!0,navigator.serviceWorker.addEventListener("message",(q)=>{let x=q.data,y=q.ports?.[0];if(!x||x.kind!=="mh-rpc"||!y||!x.op)return;if(!P()||typeof Worker>"u"){y.postMessage({ok:!1,error:{message:"replica unavailable",code:"unavailable"}});return}let z=Z();z.start(),z.call(x.op,...x.args??[]).then((C)=>y.postMessage({ok:!0,result:C}),(C)=>y.postMessage({ok:!1,error:{message:C.message,code:C.code}}))});
@@ -0,0 +1,30 @@
1
+ import type { DbDriver, Stmt } from "../core/driver.ts";
2
+ /** The cursor slice this adapter consumes (workerd SqlStorageCursor). */
3
+ export interface SqlCursorLike {
4
+ toArray(): Record<string, unknown>[];
5
+ /** Billing-metric row counter — fallback only, see changes() below. */
6
+ rowsWritten: number;
7
+ }
8
+ /** The slice of DurableObjectStorage this adapter consumes. */
9
+ export interface DoStorageLike {
10
+ sql: {
11
+ exec(query: string, ...bindings: unknown[]): SqlCursorLike;
12
+ };
13
+ transactionSync<T>(closure: () => T): T;
14
+ }
15
+ export declare class DoSqlDriver implements DbDriver {
16
+ private readonly storage;
17
+ /** Whether `SELECT changes()` is authorized in this runtime (probed once).
18
+ * null = unknown, true/false = probe result. */
19
+ private changesFnOk;
20
+ constructor(storage: DoStorageLike);
21
+ query(sql: string): Stmt;
22
+ exec(sql: string): void;
23
+ transaction<A extends unknown[], R>(fn: (...args: A) => R): (...args: A) => R;
24
+ /** SQLite's changes() when available; otherwise the cursor's rowsWritten.
25
+ * rowsWritten is a metering counter that may include index writes, so it is
26
+ * only guaranteed to agree with changes() on the zero/nonzero boundary —
27
+ * which is all the room-side core paths test (`.changes > 0`). */
28
+ private changes;
29
+ }
30
+ //# sourceMappingURL=do-driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"do-driver.d.ts","sourceRoot":"","sources":["../../src/room/do-driver.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAe,MAAM,mBAAmB,CAAC;AAErE,yEAAyE;AACzE,MAAM,WAAW,aAAa;IAC5B,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACrC,uEAAuE;IACvE,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,+DAA+D;AAC/D,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE;QAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE,GAAG,aAAa,CAAA;KAAE,CAAC;IACpE,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;CACzC;AAED,qBAAa,WAAY,YAAW,QAAQ;IAK9B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC;qDACiD;IACjD,OAAO,CAAC,WAAW,CAAwB;gBAEd,OAAO,EAAE,aAAa;IAEnD,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAkBxB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAQvB,WAAW,CAAC,CAAC,SAAS,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC;IAI7E;;;uEAGmE;IACnE,OAAO,CAAC,OAAO;CAYhB"}
package/dist/sw.js CHANGED
@@ -1 +1,10 @@
1
- function A(J,Y,Z,z){let Q=Z.get("id"),$=Z.get("db"),G=z??{},D=(V)=>V!=null?Number(V):void 0;switch(`${J} ${Y}`){case"GET /api/databases":return{op:"listDatabases",args:[]};case"POST /api/databases":return{op:"createDatabase",args:[G]};case"PATCH /api/database":return Q?{op:"updateDatabase",args:[Q,G]}:null;case"POST /api/database/duplicate":return Q?{op:"duplicateDatabase",args:[Q,G]}:null;case"DELETE /api/database":return Q?{op:"deleteDatabase",args:[Q]}:null;case"GET /api/database/activity":return $?{op:"listDatabaseActivity",args:[$,D(Z.get("limit"))]}:null;case"GET /api/properties":return $?{op:"listProperties",args:[$]}:null;case"POST /api/properties":{let{db:V,...X}=G;return V?{op:"addProperty",args:[V,X]}:null}case"PATCH /api/property":return Q?{op:"updateProperty",args:[Q,G]}:null;case"PATCH /api/property/width":return Q?{op:"setPropertyWidth",args:[Q,G.width]}:null;case"DELETE /api/property":return Q?{op:"removeProperty",args:[Q]}:null;case"GET /api/property/history":return Q?{op:"listPropertyRevisions",args:[Q]}:null;case"POST /api/property/revert":return Q?{op:"revertProperty",args:[Q,G.to]}:null;case"GET /api/records":return $?{op:"listRecords",args:[$,{sort:Z.get("sort")??void 0,limit:D(Z.get("limit"))}]}:null;case"POST /api/records":return $?{op:"createRecord",args:[$,G]}:null;case"GET /api/record":return Q?{op:"getRecord",args:[Q]}:null;case"PATCH /api/record":return Q?{op:"updateRecord",args:[Q,G]}:null;case"PATCH /api/record/order":{let{target:V,where:X}=G;return Q&&V?{op:"moveRecord",args:[Q,V,X]}:null}case"GET /api/record/history":return Q?{op:"listRecordRevisions",args:[Q]}:null;case"GET /api/record/at":return Q?{op:"recordAtVersion",args:[Q,Z.get("version")]}:null;case"GET /api/record/field-history":return Q?{op:"recordFieldHistory",args:[Q,Z.get("prop")]}:null;case"POST /api/record/revert":return Q?{op:"revertRecord",args:[Q,G.to]}:null;case"DELETE /api/record":return Q?{op:"deleteRecord",args:[Q]}:null;case"GET /api/documents":return{op:"listDocuments",args:[{database_id:Z.get("db")??void 0,parent_id:Z.get("parent")??void 0}]};case"POST /api/documents":return{op:"createDocument",args:[G]};case"GET /api/document":return Q?{op:"getDocument",args:[Q]}:null;case"PATCH /api/document":{let{if_match:V,...X}=G;return Q?{op:"updateDocument",args:[Q,X,V]}:null}case"POST /api/document/duplicate":return Q?{op:"duplicateDocument",args:[Q,G]}:null;case"PATCH /api/document/move":{let{target:V,where:X}=G;return Q&&V?{op:"moveDocument",args:[Q,V,X]}:null}case"GET /api/document/history":return Q?{op:"listDocumentRevisions",args:[Q]}:null;case"GET /api/document/at":return Q?{op:"documentAtVersion",args:[Q,Z.get("version")]}:null;case"POST /api/document/revert":{let{to:V,if_match:X}=G;return Q&&V?{op:"revertDocument",args:[Q,V,X]}:null}case"DELETE /api/document":return Q?{op:"deleteDocument",args:[Q]}:null;case"GET /api/nodes":return{op:"nodes",args:[]};case"GET /api/search":{let V=Z.get("q");return V?{op:"search",args:[V,D(Z.get("limit"))]}:null}default:return null}}function w(J,Y){if(J===null)return"unknown";if(J.status>=500)return"unknown";if(J.ok)return Y?.ok===!0?"server":"none";return"none"}async function g(){let J=null,Y=null;try{J=await fetch("/health",{cache:"no-store"}),Y=J.ok?await J.json().catch(()=>null):null}catch{J=null}return w(J,Y)}var q=Math.floor(167772160);function u(J){if(J instanceof ArrayBuffer)return J;let Y=new Uint8Array(J.byteLength);return Y.set(J),Y.buffer}async function v(J){let Y=await crypto.subtle.digest("SHA-256",u(J));return[...new Uint8Array(Y)].map((Z)=>Z.toString(16).padStart(2,"0")).join("")}async function M(J,Y){return(await v(J)).slice(0,Y.length)===Y}var m={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 O(J){let Y=J.lastIndexOf("."),Z=Y>=0?J.slice(Y+1).toLowerCase():"";return m[Z]??"application/octet-stream"}var K=null;function y(){if(K)return K;return K=new Promise((J,Y)=>{let Z=indexedDB.open("mh-blobs",1);Z.onupgradeneeded=()=>{let z=Z.result;if(!z.objectStoreNames.contains("spool"))z.createObjectStore("spool",{keyPath:"hash"});if(!z.objectStoreNames.contains("meta"))z.createObjectStore("meta",{keyPath:"hash"})},Z.onsuccess=()=>J(Z.result),Z.onerror=()=>Y(Z.error)}),K}function k(J,Y,Z){return y().then((z)=>new Promise((Q,$)=>{let G=Z(z.transaction(J,Y).objectStore(J));G.onsuccess=()=>Q(G.result),G.onerror=()=>$(G.error)}))}var B=(J)=>`/blob/${J}`;async function b(J,Y,Z){let z=await k("meta","readonly",($)=>$.get(J)),Q={hash:J,size:Y,accessed:Date.now(),pinned:z?.pinned??0,content_type:Z??z?.content_type};await k("meta","readwrite",($)=>$.put(Q))}async function p(J){let Y=await k("meta","readonly",(Z)=>Z.get(J));if(!Y)return;Y.accessed=Date.now(),await k("meta","readwrite",(Z)=>Z.put(Y))}function l(J){return J.trim().toLowerCase().startsWith("text/html")}async function x(J){let Y=await caches.open("mh-blob-v1"),Z=await Y.match(B(J));if(!Z)return;if(l(Z.headers.get("content-type")??"")){await Y.delete(B(J)),await k("meta","readwrite",(z)=>z.delete(J)).catch(()=>{});return}return p(J),Z}async function R(J,Y,Z){await(await caches.open("mh-blob-v1")).put(B(J),new Response(Y,{headers:{"content-type":Z,"cache-control":"public, max-age=31536000, immutable"}})),await b(J,Y.byteLength,Z),await d()}async function d(){let J=await k("meta","readonly",(Q)=>Q.getAll())??[],Y=J.reduce((Q,$)=>Q+$.size,0);if(Y<=209715200)return;let Z=await caches.open("mh-blob-v1"),z=J.filter((Q)=>!Q.pinned).sort((Q,$)=>Q.accessed-$.accessed);for(let Q of z){if(Y<=q)break;await Z.delete(B(Q.hash)),await k("meta","readwrite",($)=>$.delete(Q.hash)),Y-=Q.size}}var F=globalThis,U=F.caches,c="__MH_SW_VERSION__",I=`mh-shell-${c}`,_="mh-api-v1",o="mh-wasm-v1",T=["/","/webui.js","/webui.css","/manifest.webmanifest","/db-worker.js","/mh-runtime.js"],j=3500,i=12000;function N(J){return J.ok&&J.headers.get("x-mh-unlock")==null}var H=null;async function S(){if(H==null){let J=await g();if(J==="unknown")return!1;H=J}return H==="none"}F.addEventListener("install",(J)=>{J.waitUntil((async()=>{try{let Y=await U.open(I);await Promise.allSettled(T.map(async(Z)=>{let z=await fetch(Z);if(N(z))await Y.put(Z,z)})),await F.skipWaiting()}catch(Y){try{await(await U.open("mh-debug")).put("/__mh-sw-install-error",new Response(String(Y?.stack??Y)))}catch{}throw Y}})())});F.addEventListener("activate",(J)=>{J.waitUntil((async()=>{for(let Y of await U.keys())if(Y.startsWith("mh-shell-")&&Y!==I)await U.delete(Y);await F.clients.claim()})())});function P(J,Y){return new Promise((Z,z)=>{let Q=setTimeout(()=>z(Error("sw: network timeout")),Y);fetch(J).then(($)=>{clearTimeout(Q),Z($)},($)=>{clearTimeout(Q),z($)})})}async function f(J,Y,Z,z){let Q=await U.open(Y),$=z??J;try{let G=await P(J,Z);if(N(G))await Q.put($,G.clone());return G}catch(G){let D=await Q.match($);if(D)return D;throw G}}function n(J,Y,Z){return new Promise((z,Q)=>{let $=new MessageChannel,G=setTimeout(()=>Q(Error("sw: rpc timeout")),i);$.port1.onmessage=(D)=>{clearTimeout(G),z(D.data)},J.postMessage({kind:"mh-rpc",op:Y,args:Z},[$.port2])})}async function L(J,Y,Z){let z=new Set,Q=[];if(J.clientId){let $=await F.clients.get(J.clientId);if($)Q.push($)}for(let $ of await F.clients.matchAll({type:"window",includeUncontrolled:!0}))if(!Q.some((G)=>G.id===$.id))Q.push($);for(let $ of Q){if(z.has($.id))continue;z.add($.id);try{let G=await n($,Y,Z);if(!G.ok&&G.error?.code==="unavailable")continue;return G}catch{continue}}return null}var h={invalid_input:400,not_found:404,ambiguous:400,stale:409,conflict:409,auth:401,network:502};function E(J){if(J.ok)return new Response(JSON.stringify(J.result??null),{headers:{"content-type":"application/json","x-mh-source":"replica"}});let Y=J.error?.code;return new Response(JSON.stringify({error:J.error?.message??"replica error",code:Y}),{status:Y?h[Y]??400:502,headers:{"content-type":"application/json","x-mh-source":"replica"}})}async function a(J){let Y=J.request,Z=new URL(Y.url),z=null;if(Y.method!=="GET"&&(Y.headers.get("content-type")??"").includes("json"))z=await Y.clone().json().catch(()=>null);if(await S()){let Q=A(Y.method,Z.pathname,Z.searchParams,z);if(Q){let $=await L(J,Q.op,Q.args);if($)return E($)}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 Q=Y.method==="GET"?await P(Y,j*2):await fetch(Y);if(Y.method==="GET"&&N(Q))await(await U.open(_)).put(Y,Q.clone());return Q}catch(Q){let $=A(Y.method,Z.pathname,Z.searchParams,z);if($){let G=await L(J,$.op,$.args);if(G)return E(G)}if(Y.method==="GET"){let G=await(await U.open(_)).match(Y);if(G)return G}throw Q}}function r(J){let Z=J.toLowerCase().indexOf("<head>");if(Z>=0)return J.slice(0,Z+6)+'<script src="/mh-runtime.js"></script>'+J.slice(Z+6);return'<script src="/mh-runtime.js"></script>'+J}function s(J){let Y=J.content_type.includes("text/html"),Z=J.content??"",z;if(J.encoding==="utf8")z=Y?r(Z):Z;else{let Q=atob(Z),$=new Uint8Array(Q.length);for(let G=0;G<Q.length;G++)$[G]=Q.charCodeAt(G);z=$}return new Response(z,{headers:{"content-type":J.content_type,"x-mh-source":"replica"}})}function t(J,Y){let Z=`${JSON.stringify(J)},${JSON.stringify(Y)}`;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(${Z})</script></body></html>`,{headers:{"content-type":"text/html; charset=utf-8","x-mh-source":"bootstrap"}})}async function C(J,Y){let Z=Y.pathname.slice(7);if(Z==="")return null;let z=Z.indexOf("/");if(z===-1)return Response.redirect(`${Y.origin}/sites/${Z}/`,301);let Q=decodeURIComponent(Z.slice(0,z)),$=decodeURIComponent(Z.slice(z+1)),G=await L(J,"siteFile",[Q,$]);if(G?.ok&&G.result)return s(G.result);if(G?.ok&&G.result==null)return new Response("not found (offline replica)",{status:404});if(J.request.mode==="navigate")return t(Q,$);return null}async function e(J){let Y=J.request,Z=new URL(Y.url);if(await S())return await C(J,Z)??new Response("not found",{status:404});try{return await P(Y,j)}catch(z){let Q=await C(J,Z);if(Q)return Q;throw z}}async function JJ(J){let Y=J.request,Z=new URL(Y.url),z=decodeURIComponent(Z.pathname.slice(6)),Q=z.indexOf("."),$=(Q>=0?z.slice(0,Q):z).toLowerCase();if(!/^[0-9a-f]{16,64}$/.test($))return fetch(Y);let G=O(z),D=await x($);if(D)return D;if(!await S())try{let V=await P(new Request(Y,{cache:"no-store"}),j*2);if(V.ok){let X=await V.clone().arrayBuffer();if(await M(X,$))return await R($,X,V.headers.get("content-type")??G),V}}catch{}let W=await L(J,"blobBytes",[$]);if(W?.ok&&W.result){let V=W.result;if(await M(V,$))return await R($,V,G),new Response(V,{headers:{"content-type":G,"x-mh-source":"replica"}})}return new Response("blob unavailable offline",{status:404})}F.addEventListener("fetch",(J)=>{let Y=J.request,Z=new URL(Y.url);if(Z.origin!==F.location.origin)return;if(Z.pathname.startsWith("/api/")){J.respondWith(a(J));return}if(Y.method!=="GET")return;if(Z.pathname.startsWith("/sites/")){J.respondWith(e(J));return}if(Z.pathname.startsWith("/blob/")){J.respondWith(JJ(J));return}if(Y.mode==="navigate"){if(Z.pathname!=="/")return;J.respondWith(f(Y,I,j,"/"));return}if(T.includes(Z.pathname)||Z.pathname.startsWith("/icons/")){J.respondWith(f(Y,I,j));return}if(Z.pathname.startsWith("/webui-fmt")){J.respondWith((async()=>{let z=await U.open(I),Q=await z.match(Y);if(Q)return Q;let $=await fetch(Y);if(N($))await z.put(Y,$.clone());return $})());return}if(Z.pathname==="/sqlite3.wasm"){J.respondWith((async()=>{let z=await U.open(o),Q=await z.match(Y);if(Q)return Q;let $=await fetch(Y);if(N($))await z.put(Y,$.clone());return $})());return}});
1
+ function l(Z,Q,$,X){let V=$.get("id"),Y=$.get("db"),W=X??{},J=(G)=>G!=null?Number(G):void 0;switch(`${Z} ${Q}`){case"GET /api/databases":return{op:"listDatabases",args:[]};case"POST /api/databases":return{op:"createDatabase",args:[W]};case"PATCH /api/database":return V?{op:"updateDatabase",args:[V,W]}:null;case"POST /api/database/duplicate":return V?{op:"duplicateDatabase",args:[V,W]}:null;case"DELETE /api/database":return V?{op:"deleteDatabase",args:[V]}:null;case"GET /api/database/activity":return Y?{op:"listDatabaseActivity",args:[Y,J($.get("limit"))]}:null;case"GET /api/properties":return Y?{op:"listProperties",args:[Y]}:null;case"POST /api/properties":{let{db:G,...j}=W;return G?{op:"addProperty",args:[G,j]}:null}case"PATCH /api/property":return V?{op:"updateProperty",args:[V,W]}:null;case"PATCH /api/property/width":return V?{op:"setPropertyWidth",args:[V,W.width]}:null;case"DELETE /api/property":return V?{op:"removeProperty",args:[V]}:null;case"GET /api/property/history":return V?{op:"listPropertyRevisions",args:[V]}:null;case"POST /api/property/revert":return V?{op:"revertProperty",args:[V,W.to]}:null;case"GET /api/records":return Y?{op:"listRecords",args:[Y,{sort:$.get("sort")??void 0,limit:J($.get("limit"))}]}:null;case"POST /api/records":return Y?{op:"createRecord",args:[Y,W]}:null;case"GET /api/record":return V?{op:"getRecord",args:[V]}:null;case"PATCH /api/record":return V?{op:"updateRecord",args:[V,W]}:null;case"PATCH /api/record/order":{let{target:G,where:j}=W;return V&&G?{op:"moveRecord",args:[V,G,j]}:null}case"GET /api/record/history":return V?{op:"listRecordRevisions",args:[V]}:null;case"GET /api/record/at":return V?{op:"recordAtVersion",args:[V,$.get("version")]}:null;case"GET /api/record/field-history":return V?{op:"recordFieldHistory",args:[V,$.get("prop")]}:null;case"POST /api/record/revert":return V?{op:"revertRecord",args:[V,W.to]}:null;case"DELETE /api/record":return V?{op:"deleteRecord",args:[V]}:null;case"GET /api/documents":return{op:"listDocuments",args:[{database_id:$.get("db")??void 0,parent_id:$.get("parent")??void 0}]};case"POST /api/documents":return{op:"createDocument",args:[W]};case"GET /api/document":return V?{op:"getDocument",args:[V]}:null;case"PATCH /api/document":{let{if_match:G,...j}=W;return V?{op:"updateDocument",args:[V,j,G]}:null}case"POST /api/document/duplicate":return V?{op:"duplicateDocument",args:[V,W]}:null;case"PATCH /api/document/move":{let{target:G,where:j}=W;return V&&G?{op:"moveDocument",args:[V,G,j]}:null}case"GET /api/document/history":return V?{op:"listDocumentRevisions",args:[V]}:null;case"GET /api/document/at":return V?{op:"documentAtVersion",args:[V,$.get("version")]}:null;case"POST /api/document/revert":{let{to:G,if_match:j}=W;return V&&G?{op:"revertDocument",args:[V,G,j]}:null}case"DELETE /api/document":return V?{op:"deleteDocument",args:[V]}:null;case"GET /api/nodes":return{op:"nodes",args:[]};case"GET /api/sync/health":return{op:"dataMap",args:[]};case"GET /api/search":{let G=$.get("q");return G?{op:"search",args:[G,J($.get("limit"))]}:null}case"GET /api/sites":return{op:"listSites",args:[]};case"GET /api/site/files":{let G=$.get("site");return G?{op:"listSiteFiles",args:[G]}:null}case"POST /api/sites":return{op:"createSite",args:[W]};case"PATCH /api/site":return V?{op:"updateSite",args:[V,W]}:null;case"DELETE /api/site":return V?{op:"deleteSite",args:[V]}:null;case"GET /api/site/grants":return V?{op:"getSiteGrants",args:[V]}:null;case"PUT /api/site/grants":return V?{op:"setSiteGrants",args:[V,W]}:null;case"GET /api/site-hosting":return{op:"siteHosting",args:[]};case"PATCH /api/site/channel":{let G=W.id;return G?{op:"revokeSiteChannel",args:[G]}:null}case"DELETE /api/site/file":{let G=$.get("site"),j=$.get("path");return G&&j?{op:"deleteSiteFile",args:[G,j]}:null}case"GET /api/shares":return{op:"listLocalShares",args:[$.get("target")??void 0]};case"POST /api/share":return{op:"createLocalShare",args:[W]};case"DELETE /api/share":case"DELETE /api/share/managed":return $.get("slug")?{op:"revokeLocalShare",args:[$.get("slug")]}:null;default:return null}}function tQ(Z,Q){if(Z===null)return"unknown";if(Z.status>=500)return"unknown";if(Z.ok)return Q?.ok===!0?"server":"none";return"none"}async function VQ(){let Z=null,Q=null;try{Z=await fetch("/health",{cache:"no-store"}),Q=Z.ok?await Z.json().catch(()=>null):null}catch{Z=null}return tQ(Z,Q)}var eQ=Math.floor(167772160);function Q1(Z){if(Z instanceof ArrayBuffer)return Z;let Q=new Uint8Array(Z.byteLength);return Q.set(Z),Q.buffer}async function $1(Z){let Q=await crypto.subtle.digest("SHA-256",Q1(Z));return[...new Uint8Array(Q)].map(($)=>$.toString(16).padStart(2,"0")).join("")}async function p(Z,Q){return(await $1(Z)).slice(0,Q.length)===Q}var Z1={png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",webp:"image/webp",avif:"image/avif",svg:"image/svg+xml",pdf:"application/pdf"};function YQ(Z){let Q=Z.lastIndexOf("."),$=Q>=0?Z.slice(Q+1).toLowerCase():"";return Z1[$]??"application/octet-stream"}var f=null;function X1(){if(f)return f;return f=new Promise((Z,Q)=>{let $=indexedDB.open("mh-blobs",1);$.onupgradeneeded=()=>{let X=$.result;if(!X.objectStoreNames.contains("spool"))X.createObjectStore("spool",{keyPath:"hash"});if(!X.objectStoreNames.contains("meta"))X.createObjectStore("meta",{keyPath:"hash"})},$.onsuccess=()=>Z($.result),$.onerror=()=>Q($.error)}),f}function P(Z,Q,$){return X1().then((X)=>new Promise((V,Y)=>{let W=$(X.transaction(Z,Q).objectStore(Z));W.onsuccess=()=>V(W.result),W.onerror=()=>Y(W.error)}))}var v=(Z)=>`/blob/${Z}`;async function V1(Z,Q,$){let X=await P("meta","readonly",(Y)=>Y.get(Z)),V={hash:Z,size:Q,accessed:Date.now(),pinned:X?.pinned??0,content_type:$??X?.content_type};await P("meta","readwrite",(Y)=>Y.put(V))}async function Y1(Z){let Q=await P("meta","readonly",($)=>$.get(Z));if(!Q)return;Q.accessed=Date.now(),await P("meta","readwrite",($)=>$.put(Q))}function W1(Z){return Z.trim().toLowerCase().startsWith("text/html")}async function WQ(Z){let Q=await caches.open("mh-blob-v1"),$=await Q.match(v(Z));if(!$)return;if(W1($.headers.get("content-type")??"")){await Q.delete(v(Z)),await P("meta","readwrite",(X)=>X.delete(Z)).catch(()=>{});return}return Y1(Z),$}async function n(Z,Q,$){await(await caches.open("mh-blob-v1")).put(v(Z),new Response(Q,{headers:{"content-type":$,"cache-control":"public, max-age=31536000, immutable"}})),await V1(Z,Q.byteLength,$),await J1()}async function J1(){let Z=await P("meta","readonly",(V)=>V.getAll())??[],Q=Z.reduce((V,Y)=>V+Y.size,0);if(Q<=209715200)return;let $=await caches.open("mh-blob-v1"),X=Z.filter((V)=>!V.pinned).sort((V,Y)=>V.accessed-Y.accessed);for(let V of X){if(Q<=eQ)break;await $.delete(v(V.hash)),await P("meta","readwrite",(Y)=>Y.delete(V.hash)),Q-=V.size}}var JQ='<script src="/mh-runtime.js"></script>';function UQ(Z){let Q=Z.toLowerCase().indexOf("<head>");if(Q>=0)return Z.slice(0,Q+6)+JQ+Z.slice(Q+6);return JQ+Z}class z extends Error{code;constructor(Z,Q){super(Q);this.code=Z;this.name="MhError"}}function R(Z=6){let Q=crypto.getRandomValues(new Uint8Array(Z)),$="";for(let X of Q)$+="0123456789abcdefghijklmnopqrstuvwxyz".charAt(X%36);return $}function b(Z,Q="item"){return Z.normalize("NFKD").replace(/[^\x20-\x7E]/g,"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,32).replace(/-+$/g,"")||Q}var U1=new Set(["db","prop","rec","doc","blk","site","sf","chan"]);function _(Z,Q,$=Z){return`${Z}_${b(Q,$)}-${R()}`}function S(Z){let Q=Z.indexOf("_");if(Q<=0)return null;let $=Z.slice(0,Q);return U1.has($)?$:null}function zQ(Z){let Q=Z.query("SELECT value FROM meta WHERE key = 'node_id'").get();if(Q)return Q.value;let $=R(8);return Z.query("INSERT INTO meta (key, value) VALUES ('node_id', ?)").run($),$}function FQ(Z,Q){if(Q<=65535)return{millis:Z,counter:Q};return{millis:Z+Math.floor(Q/65536),counter:Q%65536}}function GQ(Z){let{millis:Q,counter:$}=FQ(Z.millis,Z.counter);return`${String(Q).padStart(15,"0")}-${$.toString(16).padStart(4,"0")}-${Z.node}`}function z1(Z){let Q=Z.indexOf("-"),$=Z.indexOf("-",Q+1);return{millis:Number(Z.slice(0,Q)),counter:parseInt(Z.slice(Q+1,$),16),node:Z.slice($+1)}}function F1(Z,Q){let $=Z.query("SELECT value FROM meta WHERE key = 'hlc'").get();return $?z1($.value):{millis:0,counter:0,node:Q}}function G1(Z,Q){Z.query("INSERT INTO meta (key, value) VALUES ('hlc', ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value").run(GQ(Q))}function jQ(Z,Q,$=Date.now()){let X=F1(Z,Q),V=Math.max(X.millis,$),Y=V===X.millis?X.counter+1:0,W={...FQ(V,Y),node:Q};return G1(Z,W),GQ(W)}function KQ(Z){let Q=Z.filter((X)=>!!X.text&&X.text.length>0),$=[];return Q.forEach((X,V)=>{$.push(...X.text.split(`
2
+ `));let Y=Math.max(0,X.blankAfter??0);if(V<Q.length-1)$.push("");for(let W=0;W<Y;W++)$.push("")}),$.join(`
3
+ `)}var HQ="intent_receipts";var j1=["hlc","node_id","dataset","row_id","col","value","txn"];var q4=j1.join(", "),w=null,K1=null;function NQ(Z,Q){if(w!==null)return Q();w=(Z?Z+":":"")+R(8);try{return Q()}finally{w=null}}function H(Z,Q=null){return(...$)=>NQ(Q,()=>Z(...$))}var H1={databases:{table:"databases",cols:new Set(["name","icon","meta","created_hlc","__deleted"])},properties:{table:"properties",cols:new Set(["database_id","name","type","config","position","__deleted"])},documents:{table:"documents",cols:new Set(["title","body","database_id","parent_id","created_hlc","order_key","__deleted"])},doc_blocks:{table:"doc_blocks",cols:new Set(["doc_id","text","order_key","blank_after","__deleted"])},sites:{table:"sites",cols:new Set(["name","title","created_hlc","visibility","spa","public_grants","__deleted"])},site_channels:{table:"site_channels",cols:new Set(["site_id","audience","hosting","controller_node_id","target_ref","canonical_url","policy_json","desired_state","created_hlc","__deleted"])},site_files:{table:"site_files",cols:new Set(["site_id","path","content_type","encoding","content","created_hlc","__deleted"])},blob_policy:{table:"blob_policy",cols:new Set(["full_nodes","redundancy","__deleted"])}},D1=new Set(["database_id","created_hlc","order_key","__deleted"]),B1=new Set([HQ]),N1=new Set(["records:__deleted","databases:__deleted","properties:__deleted","documents:__deleted","doc_blocks:__deleted","doc_blocks:blank_after","sites:__deleted","sites:spa","site_channels:__deleted","site_files:__deleted","blob_policy:__deleted"]);function DQ(Z,Q,$){if($!==null)return JSON.parse($);return N1.has(`${Z}:${Q}`)?0:null}function BQ(Z){if(Z===null||Z===void 0)return null;if(typeof Z==="boolean")return Z?1:0;if(typeof Z==="number")return Z;if(typeof Z==="string")return Z;return JSON.stringify(Z)}function m(Z,Q,$){Z.query(`INSERT OR IGNORE INTO ${Q} (id) VALUES (?)`).run($)}function A1(Z,Q){return Z.query("SELECT 1 AS x FROM doc_blocks WHERE doc_id = ? LIMIT 1").get(Q)!=null}function L1(Z,Q){let $=Z.query("SELECT text, blank_after FROM doc_blocks WHERE doc_id = ? AND __deleted = 0 ORDER BY order_key, id").all(Q);m(Z,"documents",Q),Z.query("UPDATE documents SET body = ? WHERE id = ?").run(KQ($.map((X)=>({text:X.text,blankAfter:X.blank_after??0}))),Q)}function O1(Z,Q,$,X,V){if(B1.has(Q))return;if(Q==="records"){if(D1.has(X)){m(Z,"records",$);let J=DQ("records",X,V);Z.query(`UPDATE records SET "${X}" = ? WHERE id = ?`).run(BQ(J),$)}else if(m(Z,"records",$),V===null)Z.query(`UPDATE records SET data = json_remove(data, '$."' || ? || '"') WHERE id = ?`).run(X,$);else Z.query(`UPDATE records SET data = json_set(coalesce(data, '{}'), '$."' || ? || '"', json(?)) WHERE id = ?`).run(X,V,$);return}let Y=H1[Q];if(!Y||!Y.cols.has(X))return;if(Q==="documents"&&X==="body"&&A1(Z,$))return;m(Z,Y.table,$);let W=DQ(Q,X,V);if(Z.query(`UPDATE ${Y.table} SET "${X}" = ? WHERE id = ?`).run(BQ(W),$),Q==="doc_blocks"){let J=Z.query("SELECT doc_id FROM doc_blocks WHERE id = ?").get($);if(J?.doc_id)L1(Z,J.doc_id)}}function _1(Z,Q){let $=Z.query("INSERT OR IGNORE INTO crdt_changes (hlc, node_id, dataset, row_id, col, value, txn) VALUES (?, ?, ?, ?, ?, ?, ?)").run(Q.hlc,Q.node_id,Q.dataset,Q.row_id,Q.col,Q.value,Q.txn??null).changes>0;if(Z.query("SELECT MAX(hlc) AS h FROM crdt_changes WHERE dataset = ? AND row_id = ? AND col = ?").get(Q.dataset,Q.row_id,Q.col).h!==Q.hlc)return{inserted:$,winner:!1};try{O1(Z,Q.dataset,Q.row_id,Q.col,Q.value)}catch(V){if($)Z.query("DELETE FROM crdt_changes WHERE dataset = ? AND row_id = ? AND col = ? AND hlc = ?").run(Q.dataset,Q.row_id,Q.col,Q.hlc);throw V}return{inserted:$,winner:!0}}function F(Z,Q,$,X,V){let Y=K1??zQ(Z),W={hlc:jQ(Z,Y),node_id:Y,dataset:Q,row_id:$,col:X,value:V===void 0?null:JSON.stringify(V),txn:w};return _1(Z,W),W}function AQ(Z){return Z.replace(/[^a-zA-Z0-9_]/g,"_")}function LQ(Z){return Z.replace(/'/g,"''")}function OQ(Z,Q){return`idx_rec_${AQ(Z)}_${AQ(Q)}`}function k1(Z,Q,$){return Z.query("SELECT 1 AS ok FROM sqlite_master WHERE type = 'index' AND name = ?").get(OQ(Q,$))!=null}function i(Z,Q,$){let X=OQ(Q,$);Z.exec(`CREATE INDEX IF NOT EXISTS "${X}" ON records (data ->> '${LQ($)}', created_hlc) WHERE database_id = '${LQ(Q)}' AND __deleted = 0`)}function o(Z,Q,$){if(k1(Z,Q,$.id))return;if($.type!=="relation"){if(Z.query("SELECT COUNT(*) AS c FROM records WHERE database_id = ? AND __deleted = 0").get(Q).c<2000)return}i(Z,Q,$.id)}var _Q=new Set(["text","number","checkbox","select","multi_select","date","relation","url"]),P1=["id","database_id","name","type","config","position"];var kQ=P1.join(", ");function a(Z,Q){if(Z==="select"||Z==="multi_select"){let $=Q?.options;if(!Array.isArray($)||$.length===0||!$.every((X)=>typeof X==="string"))throw new z("invalid_input",`${Z} requires config.options: string[]`)}if(Z==="relation"){if(typeof Q?.database!=="string")throw new z("invalid_input","relation requires config.database (target database id)")}}function q1(Z,Q){return(Z.query("SELECT MAX(position) AS m FROM properties WHERE database_id = ? AND __deleted = 0").get(Q).m??0)+1}var PQ=H(function(Q,$,X){if(!B(Q,$))throw new z("not_found",`no such database: ${$}`);if(!_Q.has(X.type))throw new z("invalid_input",`unknown property type: ${X.type}`);a(X.type,X.config);let V=X.indexed?{...X.config??{},indexed:!0}:X.config??null,Y=_("prop",X.name);if(F(Q,"properties",Y,"database_id",$),F(Q,"properties",Y,"name",X.name),F(Q,"properties",Y,"type",X.type),F(Q,"properties",Y,"config",V),F(Q,"properties",Y,"position",X.position??q1(Q,$)),X.type==="relation"||X.indexed===!0)i(Q,$,Y);return u(Q,Y)});function u(Z,Q){let $=Z.query(`SELECT ${kQ} FROM properties WHERE id = ? AND __deleted = 0`).get(Q);if(!$)return null;return{...$,config:$.config?JSON.parse($.config):null}}function q(Z,Q){return Z.query(`SELECT ${kQ} FROM properties WHERE database_id = ? AND __deleted = 0 ORDER BY position`).all(Q).map((X)=>({...X,config:X.config?JSON.parse(X.config):null}))}var g4=H(function(Q,$,X){let V=u(Q,$);if(!V)throw new z("not_found",`no such property: ${$}`);let Y=X.type!==void 0&&X.type!==V.type;if(X.type!==void 0&&!_Q.has(X.type))throw new z("invalid_input",`unknown property type: ${X.type}`);let W=X.type??V.type;if(X.config!==void 0)a(W,X.config);else if(Y)a(X.type,void 0);if(X.name!==void 0)F(Q,"properties",$,"name",X.name);if(X.type!==void 0)F(Q,"properties",$,"type",X.type);if(X.config!==void 0)F(Q,"properties",$,"config",X.config);if(X.position!==void 0)F(Q,"properties",$,"position",X.position);if(Y){let J=Q.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(V.database_id,$);for(let U of J)F(Q,"records",U.id,$,null)}return u(Q,$)});var y4=H(function(Q,$){let X=u(Q,$);if(!X)return!1;F(Q,"properties",$,"__deleted",1);let V=Q.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(X.database_id,$);for(let Y of V)F(Q,"records",Y.id,$,void 0);return!0});var M1={db:{table:"databases",nameCol:"name",scoped:!1,noun:"database"},prop:{table:"properties",nameCol:"name",scoped:!0,noun:"property"},rec:{table:"records",nameCol:null,scoped:!0,noun:"record"},doc:{table:"documents",nameCol:"title",scoped:!0,noun:"document"}},C1=["db","prop","rec","doc"];function x1(Z){return Z!==null&&Z!=="blk"}var qQ="{";function R1(Z,Q){return Z.query("SELECT id FROM properties WHERE database_id = ? AND type = 'text' AND __deleted = 0 ORDER BY position LIMIT 1").get(Q)?.id??null}function S1(Z,Q,$,X){let V=M1[Q],Y=V.nameCol;if(Q==="rec"&&X){let k=R1(Z,X);if(k)Y=`data ->> '${k.replace(/'/g,"''")}'`}let W=Y??"''",J=[],U=[];J.push("(id >= ? AND id < ?)"),U.push($,$+qQ);let G=`${Q}_${$}`;if(J.push("(id >= ? AND id < ?)"),U.push(G,G+qQ),Y)J.push(`lower(${Y}) = lower(?)`),U.push($);let j=`SELECT id, ${W} AS label FROM ${V.table} WHERE __deleted = 0 AND (${J.join(" OR ")})`;if(V.scoped&&X)j+=" AND database_id = ?",U.push(X);return Z.query(j).all(...U).map((k)=>({kind:Q,id:k.id,label:k.label??""}))}function MQ(Z,Q,$={}){let X=$.kind?[$.kind]:x1(S(Q))?[S(Q)]:C1,V=[],Y=new Set;for(let W of X)for(let J of S1(Z,W,Q,$.databaseId)){if(Y.has(J.id))continue;Y.add(J.id),V.push(J)}return V}function s(Z,Q){if(Q!==null&&Z>=Q)throw Error(`fracdex: ${Z} >= ${Q}`);if(Z.endsWith("0")||Q!==null&&Q.endsWith("0"))throw Error(`fracdex: trailing zero in ${Z}/${Q}`);if(Q!==null){let Y=0;while((Z[Y]??"0")===Q[Y])Y++;if(Y>0)return Q.slice(0,Y)+s(Z.slice(Y),Q.slice(Y))}let X=Z===""?0:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".indexOf(Z[0]),V=Q===null?62:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".indexOf(Q[0]);if(V-X>1)return"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[Math.round(0.5*(X+V))];if(Q!==null&&Q.length>1)return Q.slice(0,1);return"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[X]+s(Z.slice(1),null)}function L(Z,Q){return s(Z??"",Q)}function T(Z,Q,$){if($<=0)return[];if($===1)return[L(Z,Q)];if(Q===null){let Y=L(Z,null),W=[Y];for(let J=1;J<$;J++)Y=L(Y,null),W.push(Y);return W}if(Z===null){let Y=L(null,Q),W=[Y];for(let J=1;J<$;J++)Y=L(null,Y),W.unshift(Y);return W}let X=Math.floor($/2),V=L(Z,Q);return[...T(Z,V,X),V,...T(V,Q,$-X-1)]}function CQ(Z){return typeof Z==="string"||typeof Z==="number"||typeof Z==="boolean"}function T1(Z){return typeof Z==="boolean"?Z?1:0:Z}function E1(Z,Q,$){let X=Q.config?.database;if(!X)return $;let V=MQ(Z,$,{kind:"rec",databaseId:X}),Y=V.find((W)=>W.id===$);if(Y)return Y.id;if(V.length===1)return V[0].id;if(V.length===0){if(S($)==="rec")return $;throw new z("not_found",`${Q.name}: no such record in target database: ${$}`)}throw new z("ambiguous",`${Q.name}: ambiguous relation "${$}" (${V.length} matches); use a full id`)}function d(Z,Q,$){switch(Q.type){case"text":case"url":case"date":{if($===null)return null;if(typeof $!=="string")throw new z("invalid_input",`${Q.name} expects a string`);return $}case"number":{if($===null)return null;let X=typeof $==="number"?$:Number($);if(!Number.isFinite(X))throw new z("invalid_input",`${Q.name} expects a number`);return X}case"checkbox":{if(typeof $==="boolean")return $;if($==="true"||$===1)return!0;if($==="false"||$===0||$===null)return!1;throw new z("invalid_input",`${Q.name} expects a boolean`)}case"select":{if($===null)return null;let X=String($);if(!Q.config?.options?.includes(X))throw new z("invalid_input",`${Q.name}: '${X}' is not an allowed option`);return X}case"multi_select":{let X=$===null?[]:Array.isArray($)?$:[$],V=Q.config?.options??[];for(let Y of X)if(!V.includes(String(Y)))throw new z("invalid_input",`${Q.name}: '${Y}' is not an allowed option`);return X.map(String)}case"relation":return($===null?[]:Array.isArray($)?$:[$]).map((V)=>E1(Z,Q,String(V)))}}function g1(Z){let Q=new Map;for(let $ of Z){let X=$.name.toLowerCase(),V=Q.get(X);if(V)V.push($);else Q.set(X,[$])}return Q}function t(Z,Q){let $=new Map(Z.map((Y)=>[Y.id,Y])),X=g1(Z),V=[];for(let[Y,W]of Object.entries(Q)){let J=$.get(Y);if(!J){let U=X.get(Y.toLowerCase())??[];if(U.length>1)throw new z("ambiguous",`property name "${Y}" matches ${U.length} properties; use a property id`);J=U[0]}if(!J)throw new z("not_found",`unknown property: ${Y}`);V.push({prop:J,value:W})}return V}function SQ(Z,Q,$){return t(q(Z,Q),$).map(({prop:X,value:V})=>({prop:X,value:d(Z,X,V)}))}function TQ(Z,Q){let $=JSON.parse(Z.data||"{}"),X=new Map(Q.map((W)=>[W.id,W])),V={},Y={};for(let[W,J]of Object.entries($)){let U=X.get(W);if(!U)continue;V[U.name]=J,Y[U.id]=J}return{id:Z.id,database_id:Z.database_id,values:V,cells:Y}}function y1(Z,Q){let $=Z.find((X)=>X.prop.type==="text"&&typeof X.value==="string"&&X.value);return _("rec",$?String($.value):"",Q)}function xQ(Z,Q){return Z.query("SELECT 1 AS ok FROM sqlite_master WHERE type = 'table' AND name = ?").get(Q)!=null}function I1(Z){return xQ(Z,"meta")&&xQ(Z,"crdt_changes")}function f1(Z,Q,$,X){if(X)F(Z,"records",Q,"order_key",$);else Z.query("UPDATE records SET order_key = ? WHERE id = ?").run($,Q)}function EQ(Z,Q){return Z.query(`SELECT order_key FROM records
4
+ WHERE database_id = ? AND __deleted = 0 AND order_key IS NOT NULL
5
+ ORDER BY order_key DESC, id DESC LIMIT 1`).get(Q)?.order_key??null}function r(Z,Q){return Z.query(`SELECT id, database_id, created_hlc, order_key FROM records
6
+ WHERE database_id = ? AND __deleted = 0
7
+ ORDER BY order_key IS NULL, order_key, created_hlc, id`).all(Q)}function v1(Z,Q){let $=r(Z,Q),X=T(null,null,$.length);$.forEach((V,Y)=>{if(V.order_key!==X[Y])F(Z,"records",V.id,"order_key",X[Y])})}var w1=H(function(Q,$){let X=I1(Q),V=$?[{database_id:$}]:Q.query(`SELECT DISTINCT database_id FROM records
8
+ WHERE database_id IS NOT NULL AND __deleted = 0 AND order_key IS NULL`).all();for(let Y of V){let W=Q.query(`SELECT id FROM records
9
+ WHERE database_id = ? AND __deleted = 0 AND order_key IS NULL
10
+ ORDER BY created_hlc, id`).all(Y.database_id);if(!W.length)continue;let J=EQ(Q,Y.database_id),U=T(J,null,W.length);W.forEach((G,j)=>f1(Q,G.id,U[j],X))}}),gQ=H(function(Q,$,X){let V=y1(X,b($.name,"rec")),Y=L(EQ(Q,$.id),null),W=F(Q,"records",V,"database_id",$.id);F(Q,"records",V,"created_hlc",W.hlc),F(Q,"records",V,"order_key",Y);for(let{prop:J,value:U}of X)F(Q,"records",V,J.id,U);return E(Q,V)}),yQ=H(function(Q,$,X){let V=B(Q,$);if(!V)throw new z("not_found",`no such database: ${$}`);return gQ(Q,V,SQ(Q,V.id,X))});function E(Z,Q){let $=Z.query("SELECT id, database_id, data FROM records WHERE id = ? AND __deleted = 0").get(Q);if(!$)return null;return TQ($,q(Z,$.database_id))}function RQ(Z){return Z.replace(/'/g,"''")}function IQ(Z,Q,$={}){let X=q(Z,Q),V=$.filter&&Object.keys($.filter).length?t(X,$.filter).map(({prop:K,value:A})=>({prop:K,value:d(Z,K,A)})):[],Y=V.filter((K)=>CQ(K.value)),W=V.filter((K)=>!CQ(K.value)),J,U=!1;if($.sort){let K=$.sort;if(K.startsWith("-"))U=!0,K=K.slice(1);if(K!=="created"&&K!=="created_hlc"){let A=X.find((x)=>x.id===K);if(!A){let x=X.filter((dQ)=>dQ.name.toLowerCase()===K.toLowerCase());if(x.length>1)throw new z("ambiguous",`sort field "${K}" matches ${x.length} properties; use a property id`);A=x[0]}if(!A)throw new z("not_found",`unknown sort field: ${K}`);J=A}}for(let K of Y)o(Z,Q,K.prop);if(J)o(Z,Q,J);let G=["database_id = ?","__deleted = 0"],j=[Q];for(let K of Y)G.push(`data ->> '${RQ(K.prop.id)}' = ?`),j.push(T1(K.value));let D=$.sort==null,k=J?`data ->> '${RQ(J.id)}'`:"created_hlc",XQ=`SELECT id, database_id, data FROM records WHERE ${G.join(" AND ")} `+(D?"ORDER BY order_key IS NULL, order_key, id":`ORDER BY ${k} ${U?"DESC":"ASC"}, id`);if($.limit!=null&&W.length===0)XQ+=" LIMIT ?",j.push($.limit);let C=Z.query(XQ).all(...j).map((K)=>TQ(K,X));if(W.length){if(C=C.filter((K)=>W.every((A)=>JSON.stringify(K.cells[A.prop.id]??null)===JSON.stringify(A.value))),$.limit!=null)C=C.slice(0,$.limit)}return C}var o4=H(function(Q,$,X,V){if(V!=="before"&&V!=="after")throw new z("invalid_input",`unknown move position: ${V}`);let Y=Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get($);if(!Y)throw new z("not_found",`no such record: ${$}`);let W=Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get(X);if(!W)throw new z("not_found",`no such record: ${X}`);if(Y.database_id!==W.database_id)throw new z("invalid_input","cannot move a record across databases");if($===X)return E(Q,$);w1(Q,Y.database_id);let J=r(Q,Y.database_id).filter((D)=>D.id!==$),U=J.findIndex((D)=>D.id===X);if(U<0)throw new z("not_found",`no such target record: ${X}`);let G=V==="before"?J[U-1]?.order_key??null:J[U].order_key,j=V==="before"?J[U].order_key:J[U+1]?.order_key??null;if(G!==null&&j!==null&&G>=j)v1(Q,Y.database_id),J=r(Q,Y.database_id).filter((D)=>D.id!==$),U=J.findIndex((D)=>D.id===X),G=V==="before"?J[U-1]?.order_key??null:J[U].order_key,j=V==="before"?J[U].order_key:J[U+1]?.order_key??null;return F(Q,"records",$,"order_key",L(G,j)),E(Q,$)}),fQ=H(function(Q,$,X){if(!Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get($))throw new z("not_found",`no such record: ${$}`);for(let{prop:Y,value:W}of X)F(Q,"records",$,Y.id,W);return E(Q,$)}),a4=H(function(Q,$,X){let V=Q.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get($);if(!V)throw new z("not_found",`no such record: ${$}`);return fQ(Q,$,SQ(Q,V.database_id,X))}),s4=H(function(Q,$){if(!Q.query("SELECT id FROM records WHERE id = ? AND __deleted = 0").get($))return!1;return F(Q,"records",$,"__deleted",1),!0});var m1=["id","name","icon","meta","created_hlc"];var u1=m1.join(", ");function h1(Z){if(!Z)return null;return{...Z,meta:Z.meta===null?null:JSON.parse(Z.meta)}}var c1=H(function(Q,$){let X=_("db",$.name),V=F(Q,"databases",X,"name",$.name);if(F(Q,"databases",X,"created_hlc",V.hlc),$.icon!==void 0)F(Q,"databases",X,"icon",$.icon);return B(Q,X)}),Z8=H(function(Q,$,X){if(!B(Q,$))throw new z("not_found",`no such database: ${$}`);if(X.name!==void 0)F(Q,"databases",$,"name",X.name);if(X.icon!==void 0)F(Q,"databases",$,"icon",X.icon);if(X.meta!==void 0){if(X.meta!==null&&(typeof X.meta!=="object"||Array.isArray(X.meta)))throw new z("invalid_input","meta must be a JSON object or null");F(Q,"databases",$,"meta",X.meta)}return B(Q,$)}),X8=H(function(Q,$,X={}){let V=B(Q,$);if(!V)throw new z("not_found",`no such database: ${$}`);let Y=c1(Q,{name:X.name??V.name,icon:X.icon??V.icon??void 0});if(V.meta!==null){let{collapsed:J,...U}=V.meta;if(Object.keys(U).length)F(Q,"databases",Y.id,"meta",U)}let W=new Map;for(let J of q(Q,$)){let U=J.config?.database===$?{...J.config,database:Y.id}:J.config??void 0,G=PQ(Q,Y.id,{name:J.name,type:J.type,config:U,position:J.position});W.set(J.id,G.id)}for(let J of IQ(Q,$)){let U={};for(let[G,j]of Object.entries(J.cells)){let D=W.get(G);if(D)U[D]=j}yQ(Q,Y.id,U)}return B(Q,Y.id)});function B(Z,Q){return h1(Z.query(`SELECT ${u1} FROM databases WHERE id = ? AND __deleted = 0`).get(Q))}var V8=H(function(Q,$){if(!B(Q,$))return!1;F(Q,"databases",$,"__deleted",1);let X=(V)=>{for(let Y of vQ(Q,V,"database_id",$))F(Q,V,Y,"__deleted",1)};X("properties"),X("records");for(let V of vQ(Q,"documents","database_id",$))F(Q,"documents",V,"database_id",null);return Q.query("DELETE FROM meta WHERE key = 'current_db' AND value = ?").run($),!0});function vQ(Z,Q,$,X){return Z.query(`SELECT id FROM ${Q} WHERE ${$} = ? AND __deleted = 0`).all(X).map((V)=>V.id)}var e=["read","create","update"];function l1(Z){return typeof Z==="string"&&e.includes(Z)}function wQ(Z){let Q=new Map;for(let X of Z){let V=Q.get(X.db)??new Set;for(let Y of X.ops)V.add(Y);Q.set(X.db,V)}let $=[];for(let[X,V]of Q){let Y=e.filter((W)=>V.has(W));if(Y.length)$.push({db:X,ops:Y})}return $.sort((X,V)=>X.db<V.db?-1:X.db>V.db?1:0),{v:1,tables:$}}function mQ(Z){if(typeof Z!=="object"||Z===null||Array.isArray(Z))throw new z("invalid_input","grants must be an object {v:1, tables:[...]}");let Q=Z;if(Q.v!==1)throw new z("invalid_input","grants version must be 1");if(!Array.isArray(Q.tables))throw new z("invalid_input","grants.tables must be an array");let $=[];for(let X of Q.tables){if(typeof X!=="object"||X===null)throw new z("invalid_input","each grant table must be an object {db, ops}");let{db:V,ops:Y}=X;if(typeof V!=="string"||!V)throw new z("invalid_input","grant table `db` must be a database id");if(!Array.isArray(Y)||!Y.every(l1))throw new z("invalid_input",`grant ops must be a subset of ${e.join("|")} (delete is never grantable)`);$.push({db:V,ops:Y})}return wQ($)}function uQ(Z){return JSON.stringify(wQ(Z.tables))}var p1=["id","name","title","created_hlc","visibility","spa","public_grants"];var hQ=p1.join(", "),n1=["id","site_id","path","content_type","encoding","content"];var N8=n1.join(", ");function QQ(Z){let Q=Z.trim().toLowerCase().replace(/[^a-z0-9-]+/g,"-").replace(/^-+|-+$/g,"");if(!Q)throw new z("invalid_input",`invalid site name: ${JSON.stringify(Z)}`);return Q}function b1(Z){let Q=[];for(let $ of Z.split("/")){if($===""||$===".")continue;if($==="..")Q.pop();else Q.push($)}return Q.join("/")}function M(Z,Q){return Z.query(`SELECT ${hQ} FROM sites WHERE id = ? AND __deleted = 0`).get(Q)}function cQ(Z,Q){let $;try{$=QQ(Q)}catch{return null}return Z.query(`SELECT ${hQ} FROM sites WHERE name = ? AND __deleted = 0 ORDER BY created_hlc DESC LIMIT 1`).get($)}function lQ(Z){let Q=atob(Z),$=new Uint8Array(Q.length);for(let X=0;X<Q.length;X++)$[X]=Q.charCodeAt(X);return $}function pQ(Z){if(Z!=="public"&&Z!=="private")throw new z("invalid_input",`visibility must be "public" or "private", got ${JSON.stringify(Z)}`)}var A8=H(function(Q,$){let X=QQ($.name);if(cQ(Q,X))throw new z("conflict",`site name already exists: ${X}`);if($.visibility!==void 0)pQ($.visibility);let V=_("site",X),Y=F(Q,"sites",V,"name",X);if(F(Q,"sites",V,"created_hlc",Y.hlc),$.title!==void 0)F(Q,"sites",V,"title",$.title);if($.visibility!==void 0)F(Q,"sites",V,"visibility",$.visibility);return M(Q,V)}),L8=H(function(Q,$,X){if(!M(Q,$))throw new z("not_found",`no such site: ${$}`);if(X.visibility!==void 0)pQ(X.visibility);if(X.name!==void 0){let V=QQ(X.name),Y=cQ(Q,V);if(Y&&Y.id!==$)throw new z("conflict",`site name already exists: ${V}`);F(Q,"sites",$,"name",V)}if(X.title!==void 0)F(Q,"sites",$,"title",X.title);if(X.visibility!==void 0)F(Q,"sites",$,"visibility",X.visibility);if(X.spa!==void 0)F(Q,"sites",$,"spa",X.spa?1:0);return M(Q,$)}),O8=H(function(Q,$,X){if(!M(Q,$))throw new z("not_found",`no such site: ${$}`);let V=X==null?null:uQ(mQ(X));return F(Q,"sites",$,"public_grants",V),M(Q,$)}),_8=H(function(Q,$){if(!M(Q,$))return!1;let X=Q.query("SELECT id FROM site_files WHERE site_id = ? AND __deleted = 0").all($);for(let V of X)F(Q,"site_files",V.id,"__deleted",1);return F(Q,"sites",$,"__deleted",1),!0});function i1(Z,Q,$){return Z.query("SELECT id FROM site_files WHERE site_id = ? AND path = ? ORDER BY created_hlc LIMIT 1").get(Q,$)?.id??null}var k8=H(function(Q,$,X){let V=i1(Q,$,b1(X));if(!V)return!1;let Y=Q.query("SELECT __deleted AS d FROM site_files WHERE id = ?").get(V);if(!Y||Y.d)return!1;return F(Q,"site_files",V,"__deleted",1),!0});var N=globalThis,O=N.caches,o1="__MH_SW_VERSION__",g=`mh-shell-${o1}`,nQ="mh-api-v1",a1="mh-wasm-v1",sQ=["/","/webui.js","/webui.css","/manifest.webmanifest","/db-worker.js","/mh-runtime.js"],y=3500,s1=12000;function I(Z){return Z.ok&&Z.headers.get("x-mh-unlock")==null}var $Q=null;async function ZQ(){if($Q==null){let Z=await VQ();if(Z==="unknown")return!1;$Q=Z}return $Q==="none"}N.addEventListener("install",(Z)=>{Z.waitUntil((async()=>{try{let Q=await O.open(g);await Promise.allSettled(sQ.map(async($)=>{let X=await fetch($);if(I(X))await Q.put($,X)})),await N.skipWaiting()}catch(Q){try{await(await O.open("mh-debug")).put("/__mh-sw-install-error",new Response(String(Q?.stack??Q)))}catch{}throw Q}})())});N.addEventListener("activate",(Z)=>{Z.waitUntil((async()=>{for(let Q of await O.keys())if(Q.startsWith("mh-shell-")&&Q!==g)await O.delete(Q);await N.clients.claim()})())});function c(Z,Q){return new Promise(($,X)=>{let V=setTimeout(()=>X(Error("sw: network timeout")),Q);fetch(Z).then((Y)=>{clearTimeout(V),$(Y)},(Y)=>{clearTimeout(V),X(Y)})})}async function bQ(Z,Q,$,X){let V=await O.open(Q),Y=X??Z;try{let W=await c(Z,$);if(I(W))await V.put(Y,W.clone());return W}catch(W){let J=await V.match(Y);if(J)return J;throw W}}function r1(Z,Q,$){return new Promise((X,V)=>{let Y=new MessageChannel,W=setTimeout(()=>V(Error("sw: rpc timeout")),s1);Y.port1.onmessage=(J)=>{clearTimeout(W),X(J.data)},Z.postMessage({kind:"mh-rpc",op:Q,args:$},[Y.port2])})}async function h(Z,Q,$){let X=new Set,V=[];if(Z.clientId){let Y=await N.clients.get(Z.clientId);if(Y)V.push(Y)}for(let Y of await N.clients.matchAll({type:"window",includeUncontrolled:!0}))if(!V.some((W)=>W.id===Y.id))V.push(Y);for(let Y of V){if(X.has(Y.id))continue;X.add(Y.id);try{let W=await r1(Y,Q,$);if(!W.ok&&W.error?.code==="unavailable")continue;return W}catch{continue}}return null}var d1={invalid_input:400,not_found:404,ambiguous:400,stale:409,conflict:409,auth:401,network:502};function iQ(Z){if(Z.ok)return new Response(JSON.stringify(Z.result??null),{headers:{"content-type":"application/json","x-mh-source":"replica"}});let Q=Z.error?.code;return new Response(JSON.stringify({error:Z.error?.message??"replica error",code:Q}),{status:Q?d1[Q]??400:502,headers:{"content-type":"application/json","x-mh-source":"replica"}})}async function oQ(Z,Q){let $=Z.request,X=new URL($.url),V=Q??X.pathname,Y=null;if($.method!=="GET"&&($.headers.get("content-type")??"").includes("json"))Y=await $.clone().json().catch(()=>null);if(await ZQ()){let W=l($.method,V,X.searchParams,Y);if(W){let J=await h(Z,W.op,W.args);if(J)return iQ(J)}return new Response(JSON.stringify({error:"no metahub server (bucket-only mode)",code:"network"}),{status:502,headers:{"content-type":"application/json","x-mh-source":"replica"}})}try{let W=$.method==="GET"?await c($,y*2):await fetch($);if($.method==="GET"&&I(W))await(await O.open(nQ)).put($,W.clone());return W}catch(W){let J=l($.method,V,X.searchParams,Y);if(J){let U=await h(Z,J.op,J.args);if(U)return iQ(U)}if($.method==="GET"){let U=await(await O.open(nQ)).match($);if(U)return U}throw W}}async function t1(Z,Q){let $=Q.content_type.includes("text/html"),X=Q.content??"";if(Q.encoding==="blob"){let Y=await rQ(Z,X,Q.content_type);if(!Y)return new Response("blob unavailable offline",{status:404});return new Response(Y.body,{status:Q.status??200,headers:{"content-type":Q.content_type,"x-mh-source":"replica"}})}let V;if(Q.encoding==="utf8")V=$&&!Q.public?UQ(X):X;else V=lQ(X);return new Response(V,{status:Q.status??200,headers:{"content-type":Q.content_type,"x-mh-source":"replica"}})}function e1(Z,Q){let $=`${JSON.stringify(Z)},${JSON.stringify(Q)}`;return new Response(`<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><script src="/mh-runtime.js"></script></head><body><p style="font:14px system-ui;color:#888;margin:2em">正在从本地副本加载…</p><script>__mhOfflineBootstrap(${$})</script></body></html>`,{headers:{"content-type":"text/html; charset=utf-8","x-mh-source":"bootstrap"}})}async function aQ(Z,Q){let $=Q.pathname.slice(7);if($==="")return null;let X=$.indexOf("/");if(X===-1)return Response.redirect(`${Q.origin}/sites/${$}/`,301);let V=decodeURIComponent($.slice(0,X)),Y=decodeURIComponent($.slice(X+1)),W=await h(Z,"siteFile",[V,Y]);if(W?.ok&&W.result)return t1(Z,W.result);if(W?.ok&&W.result==null)return new Response("not found (offline replica)",{status:404});if(Z.request.mode==="navigate")return e1(V,Y);return null}async function Q4(Z){let Q=Z.request,$=new URL(Q.url);if(await ZQ())return await aQ(Z,$)??new Response("not found",{status:404});try{return await c(Q,y)}catch(X){let V=await aQ(Z,$);if(V)return V;throw X}}async function $4(Z){let Q=Z.request,$=new URL(Q.url),X=decodeURIComponent($.pathname.slice(6)),V=X.indexOf("."),Y=(V>=0?X.slice(0,V):X).toLowerCase();if(!/^[0-9a-f]{16,64}$/.test(Y))return fetch(Q);let W=YQ(X);return await rQ(Z,Y,W,Q)??new Response("blob unavailable offline",{status:404})}async function rQ(Z,Q,$,X){let V=await WQ(Q);if(V)return V;if(!await ZQ())try{let W=X?new Request(X,{cache:"no-store"}):new Request(`${N.location.origin}/blob/${Q}`,{cache:"no-store"}),J=await c(W,y*2);if(J.ok){let U=await J.clone().arrayBuffer();if(await p(U,Q))return await n(Q,U,J.headers.get("content-type")??$),J}}catch{}let Y=await h(Z,"blobBytes",[Q]);if(Y?.ok&&Y.result){let W=Y.result;if(await p(W,Q))return await n(Q,W,$),new Response(W,{headers:{"content-type":$,"x-mh-source":"replica"}})}return null}N.addEventListener("fetch",(Z)=>{let Q=Z.request,$=new URL(Q.url);if($.origin!==N.location.origin)return;if($.pathname.startsWith("/api/")){Z.respondWith(oQ(Z));return}let X=/^\/sites\/[^/]+(\/api\/.*)$/.exec($.pathname);if(X){Z.respondWith(oQ(Z,X[1]));return}if(Q.method!=="GET")return;if($.pathname.startsWith("/sites/")){Z.respondWith(Q4(Z));return}if($.pathname.startsWith("/blob/")){Z.respondWith($4(Z));return}if(Q.mode==="navigate"){if($.pathname!=="/")return;Z.respondWith(bQ(Q,g,y,"/"));return}if(sQ.includes($.pathname)||$.pathname.startsWith("/icons/")){Z.respondWith(bQ(Q,g,y));return}if($.pathname.startsWith("/webui-fmt")){Z.respondWith((async()=>{let V=await O.open(g),Y=await V.match(Q);if(Y)return Y;let W=await fetch(Q);if(I(W))await V.put(Q,W.clone());return W})());return}if($.pathname==="/sqlite3.wasm"){Z.respondWith((async()=>{let V=await O.open(a1),Y=await V.match(Q);if(Y)return Y;let W=await fetch(Q);if(I(W))await V.put(Q,W.clone());return W})());return}});
@@ -0,0 +1,3 @@
1
+ import { type Route } from "../../core/sync/routes.ts";
2
+ export declare const edgeRoutes: Route[];
3
+ //# sourceMappingURL=edge-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edge-routes.d.ts","sourceRoot":"","sources":["../../../src/webui/server/edge-routes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAkGvD,eAAO,MAAM,UAAU,EAAE,KAAK,EA8I7B,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { type Route, type RouteCtx } from "../../core/sync/routes.ts";
2
+ /** Consistent JSON/error envelope for WebUI routes. */
3
+ export declare function jsonHandler(fn: (req: Request, ctx: RouteCtx) => unknown): Route["handler"];
4
+ //# sourceMappingURL=json-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-handler.d.ts","sourceRoot":"","sources":["../../../src/webui/server/json-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,KAAK,EAAE,KAAK,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAErF,uDAAuD;AACvD,wBAAgB,WAAW,CACzB,EAAE,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,KAAK,OAAO,GAC3C,KAAK,CAAC,SAAS,CAAC,CAQlB"}
@@ -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;AAwarF,eAAO,MAAM,WAAW,EAAE,KAAK,EAke9B,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;AA0arF,eAAO,MAAM,WAAW,EAAE,KAAK,EAqe9B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"share-routes.d.ts","sourceRoot":"","sources":["../../../src/webui/server/share-routes.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,KAAK,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAwDtE,eAAO,MAAM,WAAW,EAAE,KAAK,EA8F9B,CAAC"}
1
+ {"version":3,"file":"share-routes.d.ts","sourceRoot":"","sources":["../../../src/webui/server/share-routes.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,KAAK,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAwEtE,eAAO,MAAM,WAAW,EAAE,KAAK,EA0M9B,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type Route } from "../../core/sync/routes.ts";
2
+ export declare function pollSite(url: string, opts?: {
3
+ budgetMs?: number;
4
+ attemptMs?: number;
5
+ }): Promise<boolean>;
6
+ export declare const siteHostingRoutes: Route[];
7
+ //# sourceMappingURL=site-hosting-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"site-hosting-routes.d.ts","sourceRoot":"","sources":["../../../src/webui/server/site-hosting-routes.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,2BAA2B,CAAC;AA4MvD,wBAAsB,QAAQ,CAC5B,GAAG,EAAE,MAAM,EACX,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACnD,OAAO,CAAC,OAAO,CAAC,CAuBlB;AAED,eAAO,MAAM,iBAAiB,EAAE,KAAK,EAiZpC,CAAC"}