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