@lpdjs/firestore-repo-service 2.3.1 → 2.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/{create-servers-Bm58QZze.d.cts → create-servers-CFZ_ZQzB.d.cts} +2 -2
- package/dist/{create-servers-BbsqzP1y.d.ts → create-servers-DLEocmga.d.ts} +2 -2
- package/dist/index.cjs +31 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +31 -38
- package/dist/index.js.map +1 -1
- package/dist/{queue-CC5cnIFv.d.cts → queue-BTe8rqCq.d.cts} +1 -1
- package/dist/{queue-7d2-Y-o-.d.ts → queue-V0OPbQa0.d.ts} +1 -1
- package/dist/servers/index.cjs +38 -45
- package/dist/servers/index.cjs.map +1 -1
- package/dist/servers/index.d.cts +3 -3
- package/dist/servers/index.d.ts +3 -3
- package/dist/servers/index.js +38 -45
- package/dist/servers/index.js.map +1 -1
- package/dist/sync/bigquery.d.cts +1 -1
- package/dist/sync/bigquery.d.ts +1 -1
- package/dist/sync/index.cjs +43 -50
- package/dist/sync/index.cjs.map +1 -1
- package/dist/sync/index.d.cts +5 -6
- package/dist/sync/index.d.ts +5 -6
- package/dist/sync/index.js +43 -50
- package/dist/sync/index.js.map +1 -1
- package/dist/{types-BTt_FmeC.d.cts → types-BW592RAZ.d.cts} +0 -2
- package/dist/{types-DXoT10nB.d.ts → types-CBwcflkG.d.ts} +0 -2
- package/package.json +1 -1
package/dist/servers/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {jsx,jsxs,Fragment}from'hono/jsx/jsx-runtime';import {Timestamp}from'firebase-admin/firestore';import {randomUUID}from'crypto';import {z as z$1}from'zod';import {renderToString}from'hono/jsx/dom/server';var Mn=Object.defineProperty;var Ve=(e,t)=>()=>(e&&(t=e(e=0)),t);var qn=(e,t)=>{for(var n in t)Mn(e,n,{get:t[n],enumerable:true});};function H(e){let t=e,n=t._zod?.def?.type;if(n)return Qn[n]??`Zod${n.charAt(0).toUpperCase()}${n.slice(1)}`;let o=t._def?.typeName;return o||""}function G(e){let t=e;if(t._zod?.def?.innerType)return t._zod.def.innerType;if(t._def?.innerType)return t._def.innerType}function Bt(e){let t=e;if(t._zod?.def?.element)return t._zod.def.element;if(t._def?.type)return t._def.type}function Mt(e){let t=e;if(t._zod?.def?.defaultValue!==void 0)return t._zod.def.defaultValue;let n=t._def?.defaultValue;return typeof n=="function"?n():n}function te(e){let t=e;return t.shape&&typeof t.shape=="object"?t.shape:t._zod?.def?.shape&&typeof t._zod.def.shape=="object"?t._zod.def.shape:t._def?.shape?typeof t._def.shape=="function"?t._def.shape():t._def.shape:{}}function _e(e){let t=e;return Array.isArray(t.options)?t.options:t._zod?.def?.entries?Object.values(t._zod.def.entries):Array.isArray(t._def?.values)?t._def.values:[]}function De(e){let t=e;return t._zod?.def?.entries?t._zod.def.entries:t.enum&&typeof t.enum=="object"?t.enum:t._def?.values&&typeof t._def.values=="object"?t._def.values:{}}function Ge(e){let t=e;return Array.isArray(t._zod?.def?.values)?t._zod.def.values[0]:t._def?.value}function qt(e){let t=e,n=[],o=t._zod?.def?.checks;if(Array.isArray(o)){for(let i of o)i.format&&n.push(i.format);if(n.length>0)return n}let r=t._def?.checks;if(Array.isArray(r))for(let i of r)i.kind&&n.push(i.kind);return n}var Qn,je=Ve(()=>{Qn={string:"ZodString",number:"ZodNumber",bigint:"ZodBigInt",boolean:"ZodBoolean",date:"ZodDate",enum:"ZodEnum",nativeEnum:"ZodNativeEnum",literal:"ZodLiteral",object:"ZodObject",array:"ZodArray",optional:"ZodOptional",nullable:"ZodNullable",default:"ZodDefault",coerce:"ZodCoerce",union:"ZodUnion",undefined:"ZodUndefined",unknown:"ZodUnknown",any:"ZodAny",record:"ZodRecord"};});function sn({val:e}){return jsx("span",{class:"text-sm text-base-content/80 font-mono tabular-nums whitespace-nowrap",children:e.toLocaleString()})}function yr({message:e}){return jsx("span",{class:"tooltip tooltip-warning tooltip-right inline-flex align-middle ml-1 text-warning","data-tip":e,role:"img","aria-label":e,children:jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor",class:"size-3.5",children:jsx("path",{d:"M12 2 1 22h22L12 2zm0 6 7.5 13h-15L12 8zm-1 4v4h2v-4h-2zm0 5v2h2v-2h-2z"})})})}function Te({val:e,mismatch:t}){let n=gr(e);return t?jsxs("span",{class:"inline-flex items-start gap-0.5",children:[n,jsx(yr,{message:t})]}):n}function gr(e){if(e==null)return jsx("span",{class:"opacity-30 italic text-xs",children:"\u2014"});if(typeof e=="boolean")return e?jsx("span",{class:"badge badge-success badge-sm",children:"true"}):jsx("span",{class:"badge badge-error badge-sm",children:"false"});if(e instanceof Date)return jsx(sn,{val:e});if(typeof e=="object"&&e!==null&&typeof e.toDate=="function")return jsx(sn,{val:e.toDate()});if(typeof e=="number")return jsx("span",{class:"text-sm font-mono tabular-nums",children:String(e)});if(Array.isArray(e))return e.length===0?jsx("span",{class:"text-xs text-base-content/30",children:"[]"}):jsxs("ul",{class:"list-none p-0 m-0 space-y-0.5 text-xs",children:[e.slice(0,8).map((n,o)=>jsx("li",{class:"break-all",children:typeof n=="object"?JSON.stringify(n):String(n)},o)),e.length>8&&jsxs("li",{class:"text-base-content/40 italic",children:["+",e.length-8," more\u2026"]})]});if(typeof e=="object"&&e!==null){let n=Object.entries(e);return n.length===0?jsx("span",{class:"text-xs text-base-content/30",children:"{}"}):jsxs("dl",{class:"grid grid-cols-[auto_1fr] gap-x-2 gap-y-0.5 text-xs m-0",children:[n.slice(0,8).map(([o,r])=>jsxs(Fragment,{children:[jsx("dt",{class:"text-base-content/50 font-semibold whitespace-nowrap",children:o}),jsx("dd",{class:"break-all",children:String(r??"")})]})),n.length>8&&jsxs("dt",{class:"col-span-2 text-base-content/40 italic",children:["+",n.length-8," more\u2026"]})]})}let t=String(e);return jsx("span",{class:"text-sm break-all",children:t})}var Xe=Ve(()=>{});function Oe(e){if(!e)return "unknown";let t=ct(e);switch(H(t)){case "ZodString":return "string";case "ZodNumber":return "number";case "ZodBigInt":return "bigint";case "ZodBoolean":return "boolean";case "ZodDate":return "date";case "ZodArray":return "array";case "ZodObject":case "ZodRecord":return "object";case "ZodEnum":case "ZodNativeEnum":return "enum";case "ZodLiteral":return "literal";default:return "unknown"}}function ct(e){let t=H(e);if(t==="ZodOptional"||t==="ZodNullable"||t==="ZodDefault"){let n=G(e);return n?ct(n):e}return e}function Ee(e,t){if(!e)return;let n=t.split("."),o=e;for(let r of n){if(!o)return;let i=ct(o);if(H(i)!=="ZodObject")return;o=te(i)[r];}return o}function xr(e){return e==null?"null":e instanceof Date?"date":Array.isArray(e)?"array":typeof e=="string"?"string":typeof e=="boolean"?"boolean":typeof e=="bigint"?"bigint":typeof e=="number"?"number":typeof e=="object"?typeof e.toDate=="function"?"date":"object":"unknown"}function Me(e,t){if(e==="unknown")return null;let n=xr(t);return n==="null"?null:e==="enum"||e==="literal"?n==="string"||n==="number"?null:`Expected ${e} (string/number), got ${n}`:e===n||e==="number"&&n==="bigint"||e==="bigint"&&n==="number"?null:`Expected ${e}, got ${n}`}var dt=Ve(()=>{je();});var cn={};qn(cn,{PanelMany:()=>Sr,PanelOne:()=>wr,RightPanel:()=>ut});function wr({doc:e,repoName:t,basePath:n,schema:o,columns:r}){if(!e)return jsx("div",{class:"text-center py-12 text-base-content/50",children:"Document not found."});let i=String(e.docId??e.id??""),l=`${n}/${t}/${encodeURIComponent(i)}/edit`,u=ln(o,r);return jsxs("div",{class:"space-y-4",children:[jsxs("div",{class:"flex items-center justify-between gap-2",children:[jsxs("div",{class:"text-xs text-base-content/60",children:[jsx("span",{class:"font-mono",children:t}),jsx("span",{class:"opacity-50",children:" \xB7 "}),jsx("span",{class:"font-mono break-all",children:i})]}),jsx("a",{href:l,class:"btn btn-sm btn-primary",children:"Edit \u2192"})]}),jsx("dl",{class:"grid grid-cols-[max-content_1fr] gap-x-4 gap-y-2 border border-base-300 rounded-box p-4 bg-base-100",children:r.map(c=>{let y=e[c],g=u[c],C=g?Me(g,y):null;return jsxs(Fragment,{children:[jsx("dt",{class:"text-xs font-semibold text-base-content/60 uppercase tracking-wide pt-0.5",children:c}),jsx("dd",{class:"min-w-0",children:jsx(Te,{val:y,mismatch:C})})]})})})]})}function Sr({docs:e,repoName:t,basePath:n,fk:o,fv:r,columns:i,schema:l,pagination:u}){let c=`${n}/${t}?fv_${o}=${encodeURIComponent(r)}`,y=ln(l,i);return jsxs("div",{class:"space-y-4",children:[jsxs("div",{class:"flex items-center justify-between gap-2",children:[jsxs("div",{class:"text-xs text-base-content/60",children:[jsx("span",{class:"font-mono",children:t}),jsx("span",{class:"opacity-50",children:" where "}),jsx("span",{class:"font-mono",children:o}),jsx("span",{class:"opacity-50",children:" = "}),jsx("span",{class:"font-mono break-all",children:r}),jsx("span",{class:"opacity-50",children:" \xB7 "}),jsxs("span",{children:[e.length," doc",e.length!==1?"s":""]})]}),jsx("a",{href:c,class:"btn btn-sm btn-outline",children:"Full view \u2192"})]}),jsx("div",{class:"overflow-x-auto rounded-box border border-base-300 bg-base-100",children:jsxs("table",{class:"table table-xs w-full",children:[jsx("thead",{children:jsxs("tr",{class:"bg-base-200/50",children:[i.map((g,C)=>jsx("th",{class:"text-xs font-semibold text-base-content/60 uppercase tracking-wide",children:g},C)),jsx("th",{})]})}),jsx("tbody",{children:e.length===0?jsx("tr",{children:jsx("td",{colspan:i.length+1,class:"text-center py-10 text-base-content/40",children:"No related documents"})}):e.map((g,C)=>{let h=String(g.docId??g.id??""),x=`${n}/${t}/${encodeURIComponent(h)}/edit`;return jsxs("tr",{class:"hover",children:[i.map((v,b)=>{let S=g[v],p=y[v],a=p?Me(p,S):null;return jsx("td",{class:"align-top py-1.5",children:jsx(Te,{val:S,mismatch:a})},b)}),jsx("td",{class:"text-right py-1.5",children:jsx("a",{href:x,class:"btn btn-xs btn-ghost",children:"Edit"})})]},C)})})]})}),(u.hasPrev||u.hasNext)&&jsxs("div",{class:"flex justify-center items-center gap-2",children:[u.hasPrev?jsx("button",{type:"button",class:"btn btn-xs btn-outline","data-frs-panel-page":"prev","data-cursor":u.prevCursor,children:"\u2190 Previous"}):jsx("button",{class:"btn btn-xs btn-outline",disabled:true,children:"\u2190 Previous"}),u.hasNext?jsx("button",{type:"button",class:"btn btn-xs btn-outline","data-frs-panel-page":"next","data-cursor":u.nextCursor,children:"Next \u2192"}):jsx("button",{class:"btn btn-xs btn-outline",disabled:true,children:"Next \u2192"})]})]})}function ln(e,t){if(!e)return {};let n={};for(let o of t)n[o]=Oe(Ee(e,o));return n}var ut,pt=Ve(()=>{Xe();dt();ut=({basePath:e=""})=>jsxs("div",{class:"fixed inset-0 z-[100] hidden pointer-events-none","data-frs-panel-root":true,"data-frs-base-path":e,"aria-hidden":"true",children:[jsx("div",{class:"absolute inset-0 bg-black/30 opacity-0 transition-opacity duration-200 pointer-events-auto","data-frs-panel-backdrop":true}),jsxs("aside",{class:"absolute top-0 right-0 h-full w-full md:w-1/2 bg-base-100 shadow-2xl border-l border-base-300 translate-x-full transition-transform duration-200 pointer-events-auto flex flex-col","data-frs-panel":true,role:"dialog","aria-label":"Relation preview",children:[jsxs("header",{class:"flex items-center justify-between px-5 py-3 border-b border-base-300 bg-base-200/40 shrink-0",children:[jsx("h2",{class:"font-semibold text-base truncate","data-frs-panel-title":true,children:"Relation"}),jsx("button",{type:"button",class:"btn btn-sm btn-ghost btn-circle","data-frs-panel-close":true,"aria-label":"Close panel",children:"\u2715"})]}),jsx("div",{class:"flex-1 overflow-auto p-5 text-sm","data-frs-panel-body":true,children:jsx("div",{class:"flex items-center justify-center py-12 text-base-content/40",children:jsx("span",{class:"loading loading-spinner loading-md"})})})]})]});});function It(e){if(e===null)return "null";if(e===void 0)return "undefined";if(e instanceof Timestamp)return "timestamp";if(e instanceof Date)return "date";if(Array.isArray(e))return "array";let t=typeof e;return t==="string"||t==="number"||t==="boolean"?t:"object"}function Nt(e,t){if(e===t)return true;if(e===null||t===null||e===void 0||t===void 0)return e===t;if(e instanceof Timestamp&&t instanceof Timestamp)return e.isEqual(t);if(e instanceof Date&&t instanceof Date)return e.getTime()===t.getTime();if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return false;for(let n=0;n<e.length;n++)if(!Nt(e[n],t[n]))return false;return true}if(typeof e=="object"&&typeof t=="object")try{return JSON.stringify(e)===JSON.stringify(t)}catch{return false}return false}function _t(e,t,n={}){let o=new Set([...n.exclude??[],...n.metaFields??[],...n.systemKeys??[]]),r=n.include?new Set(n.include):null,i=e??{},l=t??{},u=new Set([...Object.keys(i),...Object.keys(l)]),c={};for(let y of u){if(o.has(y)||r&&!r.has(y))continue;let g=i[y],C=l[y];Nt(g,C)||(c[y]={oldValue:g===void 0?null:g,newValue:C===void 0?null:C,type:{old:It(g),new:It(C)}});}return c}var Ln=7e5;function Dt(e){let t=e.ttlOverride??e.config.ttl,o={schemaVersion:2,historyDocId:randomUUID(),historyToObjectId:e.entityId,historySetAt:Timestamp.now(),operation:e.operation,meta:e.meta,changes:e.changes};t&&(o.expiresAt=Timestamp.fromMillis(Date.now()+t.days*24*60*60*1e3));let r=i=>{try{return Buffer.byteLength(JSON.stringify(i,(l,u)=>u instanceof Timestamp?u.toMillis():u),"utf8")}catch{return 0}};if(r(o.changes)>Ln){let i={};for(let[l,u]of Object.entries(o.changes)){let c=r(u.oldValue),y=r(u.newValue);i[l]={oldValue:c>5e4?"[truncated]":u.oldValue,newValue:y>5e4?"[truncated]":u.newValue,type:u.type};}o.changes=i,o._truncated=true;}return o}async function jt(e,t,n,o){let r=t;return n.onBeforeWrite&&(r=await n.onBeforeWrite(t,o)),r?(await e.doc(r.historyDocId).set(r),{written:true,entry:r}):{written:false,reason:"dropped-by-onBeforeWrite"}}function Ft(e,t){let n=e??{},o={},r=t.meta;if(!r)return o;let i=g=>{if(!g)return;let C=n[g];return C===void 0||C===null?null:String(C)},l=i(r.userId);l!==void 0&&(o.userId=l);let u=i(r.userEmail);u!==void 0&&(o.userEmail=u);let c=i(r.reason);c!==void 0&&(o.reason=c);let y=i(r.comment);if(y!==void 0&&(o.comment=y),r.extras&&r.extras.length>0){let g={},C=false;for(let h of r.extras)h in n&&(g[h]=n[h],C=true);C&&(o.extras=g);}return o}function zt(e){let t=e.meta;if(!t)return [];let n=[];return t.userId&&n.push(t.userId),t.userEmail&&n.push(t.userEmail),t.reason&&n.push(t.reason),t.comment&&n.push(t.comment),t.extras&&n.push(...t.extras),n}var Un="history";function Kn(e,t){let n=t.ref?.path??void 0;return n?`${n}/{docId}`:(console.warn(`[HistoryTriggers] Cannot determine collection path for "${e}". Skipping.`),null)}function Zt(e,t){let{onDocumentWritten:n}=t.deps,o={};for(let[r,i]of Object.entries(e)){let l=i._historyConfig??(typeof i.history=="object"&&i.history!==null&&"enabled"in i.history?i.history:void 0);if(!l?.enabled)continue;let u=l.subcollection??Un,c=l.ttl??t.defaults?.ttl,y=t.repos?.[r],g;if(i._isGroup){if(!y?.triggerPath){console.warn(`[HistoryTriggers] Skipping collection-group repo "${r}". Provide a triggerPath in the history triggers repos override.`);continue}g=y.triggerPath;}else g=y?.triggerPath??Kn(r,i);if(!g)continue;let C=i._systemKeys??[],h=C[0]??"docId",x=zt(l);o[`${r}_onHistory`]=n(g,async v=>{try{let b=v.data?.before?.data(),S=v.data?.after?.data(),p;if(!b&&S)p="create";else if(b&&!S)p="delete";else if(b&&S)p="update";else return;let a=String(S?.[h]??b?.[h]??v.params?.docId??v.data?.after?.id??v.data?.before?.id??"");if(!a)return;let f=_t(b??{},S??{},{include:l.include,exclude:l.exclude,metaFields:x,systemKeys:C});if(p==="update"&&Object.keys(f).length===0)return;let s=Ft(S??b??null,l),d=Dt({entityId:a,operation:p,changes:f,meta:s,config:l,ttlOverride:c}),m=v.data?.after?.ref??v.data?.before?.ref;if(!m)return;let k=m.collection(u);await jt(k,d,l,{repoName:r,docId:a,before:b??null,after:S??null});}catch(b){console.error(`[HistoryTriggers] Failed to record history for "${r}":`,b);}});}return o}function Vn(e){let t=[],n=e.replace(/[.*+?^${}()|[\]\\]/g,o=>o===":"?o:`\\${o}`).replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g,(o,r)=>(t.push(r),"([^/]+)"));return {pattern:new RegExp(`^${n}$`),paramNames:t}}function Gn(e){let t=e.path??e.url??"/",n=t.indexOf("?");return n===-1?t:t.slice(0,n)}var se=class{constructor(){this.routes=[];this.middlewares=[];this.notFoundHandler=(t,n)=>{n.status(404).send("Not Found");};this.errorHandler=(t,n,o)=>{console.error("[MiniRouter]",t),o.status(500).send("Internal Server Error");};}use(t){return this.middlewares.push(t),this}get(t,n){return this.addRoute("GET",t,n)}post(t,n){return this.addRoute("POST",t,n)}put(t,n){return this.addRoute("PUT",t,n)}patch(t,n){return this.addRoute("PATCH",t,n)}delete(t,n){return this.addRoute("DELETE",t,n)}onNotFound(t){return this.notFoundHandler=t,this}onError(t){return this.errorHandler=t,this}addRoute(t,n,o){let{pattern:r,paramNames:i}=Vn(n);return this.routes.push({method:t.toUpperCase(),pattern:r,paramNames:i,handler:o}),this}async handle(t,n){let o=(t.method??"GET").toUpperCase(),r=Gn(t),i=null,l={};for(let y of this.routes){if(y.method!==o)continue;let g=r.match(y.pattern);if(g){i=y,l={},y.paramNames.forEach((C,h)=>{l[C]=decodeURIComponent(g[h+1]??"");});break}}let u=Object.assign(t,{params:l}),c=i?i.handler:this.notFoundHandler;try{await this.runMiddlewareChain(u,n,c);}catch(y){this.errorHandler(y,t,n);}}async runMiddlewareChain(t,n,o){let r=0,i=async()=>{if(r<this.middlewares.length){let l=this.middlewares[r++];await l(t,n,i);}else await o(t,n);};await i();}};function ee(e,t){let n=t==="/"?"":t.replace(/\/$/,"");if(process.env.FUNCTIONS_EMULATOR==="true"){let i=process.env.GCLOUD_PROJECT??process.env.GOOGLE_CLOUD_PROJECT??"demo-project",l=process.env.FUNCTION_REGION??"us-central1",u=(process.env.FUNCTION_TARGET??"").replace(/\./g,"-");return `/${i}/${l}/${u}${n}`}let o=process.env.K_SERVICE,r=e?.hostname??e?.headers?.host??"";return o&&typeof r=="string"&&r.includes("cloudfunctions.net")?`/${o.toLowerCase()}${n}`:n}function fe(e){return !!e&&typeof e=="object"&&e.__authExtension===true}je();var me="__sync_version";var Xn=new Set(["ZodOptional","ZodNullable","ZodDefault"]);function Yn(e){let t=e,n=false;for(;;){let o=H(t);if(!Xn.has(o))break;(o==="ZodOptional"||o==="ZodNullable")&&(n=true);let r=G(t);if(!r)break;t=r;}return {inner:t,nullable:n}}var er={ZodString:"string",ZodNumber:"number",ZodBigInt:"bigint",ZodBoolean:"boolean",ZodDate:"timestamp",ZodEnum:"string",ZodNativeEnum:"string",ZodLiteral:"string"};function Ht(e,t,n,o,r,i,l,u){for(let[c,y]of Object.entries(e)){let g=n?`${n}__${c}`:c;if(r.has(c)||r.has(g))continue;let{inner:C,nullable:h}=Yn(y),x=H(C),v=o||h;if(x==="ZodObject"){let a=te(C);Ht(a,t,g,v,r,i,l,u);continue}let b=er[x]??"json",S=g===l||c===l,p=i[g]??i[c]??g;u.push({name:p,sqlType:t.mapType(b),nullable:S?false:v,isPrimaryKey:S});}}function Je(e,t,n={}){let{primaryKey:o,exclude:r=[],columnMap:i={}}=n,l=new Set(r),u=te(e),c=[];return Ht(u,t,"",false,l,i,o,c),c.some(y=>y.name===me)||c.push({name:me,sqlType:t.mapType("bigint"),nullable:true,isPrimaryKey:false,description:"Monotonic publish version (Date.now() ms). Internal."}),c}function Lt(e){if(e==null)return null;if(typeof e=="object"&&typeof e.toDate=="function")return e.toDate().toISOString();if(e instanceof Date)return e.toISOString();if(Buffer.isBuffer(e))return e.toString("base64");if(e instanceof Uint8Array)return Buffer.from(e).toString("base64");if(typeof e=="object"&&"latitude"in e&&"longitude"in e){let t=e;return JSON.stringify({lat:t.latitude,lng:t.longitude})}return Array.isArray(e)?JSON.stringify(e.map(Lt)):e}function Ut(e,t,n){for(let[o,r]of Object.entries(e)){let i=t?`${t}__${o}`:o;r!=null&&typeof r=="object"&&!Array.isArray(r)&&!(r instanceof Date)&&!Buffer.isBuffer(r)&&!(r instanceof Uint8Array)&&typeof r.toDate!="function"&&!("latitude"in r&&"longitude"in r)?Ut(r,i,n):n[i]=Lt(r);}}function Fe(e,t){let n=new Set(t?.exclude),o=t?.columnMap??{},r={};Ut(e,"",r);let i={};for(let[l,u]of Object.entries(r)){if(n.has(l))continue;let c=l.split("__")[0];if(c!==l&&n.has(c))continue;let y=o[l]??(l.includes("__")?o[l.split("__").pop()]:void 0)??l;i[y]=u;}return i}function ae(e,t,n){return `<!DOCTYPE html>
|
|
1
|
+
import {jsx,jsxs,Fragment}from'hono/jsx/jsx-runtime';import {Timestamp}from'firebase-admin/firestore';import {randomUUID}from'crypto';import {z as z$1}from'zod';import {renderToString}from'hono/jsx/dom/server';var Mn=Object.defineProperty;var Ke=(e,t)=>()=>(e&&(t=e(e=0)),t);var qn=(e,t)=>{for(var n in t)Mn(e,n,{get:t[n],enumerable:true});};function H(e){let t=e,n=t._zod?.def?.type;if(n)return Qn[n]??`Zod${n.charAt(0).toUpperCase()}${n.slice(1)}`;let o=t._def?.typeName;return o||""}function G(e){let t=e;if(t._zod?.def?.innerType)return t._zod.def.innerType;if(t._def?.innerType)return t._def.innerType}function Bt(e){let t=e;if(t._zod?.def?.element)return t._zod.def.element;if(t._def?.type)return t._def.type}function Mt(e){let t=e;if(t._zod?.def?.defaultValue!==void 0)return t._zod.def.defaultValue;let n=t._def?.defaultValue;return typeof n=="function"?n():n}function te(e){let t=e;return t.shape&&typeof t.shape=="object"?t.shape:t._zod?.def?.shape&&typeof t._zod.def.shape=="object"?t._zod.def.shape:t._def?.shape?typeof t._def.shape=="function"?t._def.shape():t._def.shape:{}}function _e(e){let t=e;return Array.isArray(t.options)?t.options:t._zod?.def?.entries?Object.values(t._zod.def.entries):Array.isArray(t._def?.values)?t._def.values:[]}function De(e){let t=e;return t._zod?.def?.entries?t._zod.def.entries:t.enum&&typeof t.enum=="object"?t.enum:t._def?.values&&typeof t._def.values=="object"?t._def.values:{}}function Ve(e){let t=e;return Array.isArray(t._zod?.def?.values)?t._zod.def.values[0]:t._def?.value}function qt(e){let t=e,n=[],o=t._zod?.def?.checks;if(Array.isArray(o)){for(let s of o)s.format&&n.push(s.format);if(n.length>0)return n}let r=t._def?.checks;if(Array.isArray(r))for(let s of r)s.kind&&n.push(s.kind);return n}var Qn,je=Ke(()=>{Qn={string:"ZodString",number:"ZodNumber",bigint:"ZodBigInt",boolean:"ZodBoolean",date:"ZodDate",enum:"ZodEnum",nativeEnum:"ZodNativeEnum",literal:"ZodLiteral",object:"ZodObject",array:"ZodArray",optional:"ZodOptional",nullable:"ZodNullable",default:"ZodDefault",coerce:"ZodCoerce",union:"ZodUnion",undefined:"ZodUndefined",unknown:"ZodUnknown",any:"ZodAny",record:"ZodRecord"};});function sn({val:e}){return jsx("span",{class:"text-sm text-base-content/80 font-mono tabular-nums whitespace-nowrap",children:e.toLocaleString()})}function yr({message:e}){return jsx("span",{class:"tooltip tooltip-warning tooltip-right inline-flex align-middle ml-1 text-warning","data-tip":e,role:"img","aria-label":e,children:jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor",class:"size-3.5",children:jsx("path",{d:"M12 2 1 22h22L12 2zm0 6 7.5 13h-15L12 8zm-1 4v4h2v-4h-2zm0 5v2h2v-2h-2z"})})})}function Te({val:e,mismatch:t}){let n=gr(e);return t?jsxs("span",{class:"inline-flex items-start gap-0.5",children:[n,jsx(yr,{message:t})]}):n}function gr(e){if(e==null)return jsx("span",{class:"opacity-30 italic text-xs",children:"\u2014"});if(typeof e=="boolean")return e?jsx("span",{class:"badge badge-success badge-sm",children:"true"}):jsx("span",{class:"badge badge-error badge-sm",children:"false"});if(e instanceof Date)return jsx(sn,{val:e});if(typeof e=="object"&&e!==null&&typeof e.toDate=="function")return jsx(sn,{val:e.toDate()});if(typeof e=="number")return jsx("span",{class:"text-sm font-mono tabular-nums",children:String(e)});if(Array.isArray(e))return e.length===0?jsx("span",{class:"text-xs text-base-content/30",children:"[]"}):jsxs("ul",{class:"list-none p-0 m-0 space-y-0.5 text-xs",children:[e.slice(0,8).map((n,o)=>jsx("li",{class:"break-all",children:typeof n=="object"?JSON.stringify(n):String(n)},o)),e.length>8&&jsxs("li",{class:"text-base-content/40 italic",children:["+",e.length-8," more\u2026"]})]});if(typeof e=="object"&&e!==null){let n=Object.entries(e);return n.length===0?jsx("span",{class:"text-xs text-base-content/30",children:"{}"}):jsxs("dl",{class:"grid grid-cols-[auto_1fr] gap-x-2 gap-y-0.5 text-xs m-0",children:[n.slice(0,8).map(([o,r])=>jsxs(Fragment,{children:[jsx("dt",{class:"text-base-content/50 font-semibold whitespace-nowrap",children:o}),jsx("dd",{class:"break-all",children:String(r??"")})]})),n.length>8&&jsxs("dt",{class:"col-span-2 text-base-content/40 italic",children:["+",n.length-8," more\u2026"]})]})}let t=String(e);return jsx("span",{class:"text-sm break-all",children:t})}var Xe=Ke(()=>{});function Oe(e){if(!e)return "unknown";let t=ct(e);switch(H(t)){case "ZodString":return "string";case "ZodNumber":return "number";case "ZodBigInt":return "bigint";case "ZodBoolean":return "boolean";case "ZodDate":return "date";case "ZodArray":return "array";case "ZodObject":case "ZodRecord":return "object";case "ZodEnum":case "ZodNativeEnum":return "enum";case "ZodLiteral":return "literal";default:return "unknown"}}function ct(e){let t=H(e);if(t==="ZodOptional"||t==="ZodNullable"||t==="ZodDefault"){let n=G(e);return n?ct(n):e}return e}function Ee(e,t){if(!e)return;let n=t.split("."),o=e;for(let r of n){if(!o)return;let s=ct(o);if(H(s)!=="ZodObject")return;o=te(s)[r];}return o}function xr(e){return e==null?"null":e instanceof Date?"date":Array.isArray(e)?"array":typeof e=="string"?"string":typeof e=="boolean"?"boolean":typeof e=="bigint"?"bigint":typeof e=="number"?"number":typeof e=="object"?typeof e.toDate=="function"?"date":"object":"unknown"}function Be(e,t){if(e==="unknown")return null;let n=xr(t);return n==="null"?null:e==="enum"||e==="literal"?n==="string"||n==="number"?null:`Expected ${e} (string/number), got ${n}`:e===n||e==="number"&&n==="bigint"||e==="bigint"&&n==="number"?null:`Expected ${e}, got ${n}`}var dt=Ke(()=>{je();});var cn={};qn(cn,{PanelMany:()=>Sr,PanelOne:()=>wr,RightPanel:()=>ut});function wr({doc:e,repoName:t,basePath:n,schema:o,columns:r}){if(!e)return jsx("div",{class:"text-center py-12 text-base-content/50",children:"Document not found."});let s=String(e.docId??e.id??""),l=`${n}/${t}/${encodeURIComponent(s)}/edit`,u=ln(o,r);return jsxs("div",{class:"space-y-4",children:[jsxs("div",{class:"flex items-center justify-between gap-2",children:[jsxs("div",{class:"text-xs text-base-content/60",children:[jsx("span",{class:"font-mono",children:t}),jsx("span",{class:"opacity-50",children:" \xB7 "}),jsx("span",{class:"font-mono break-all",children:s})]}),jsx("a",{href:l,class:"btn btn-sm btn-primary",children:"Edit \u2192"})]}),jsx("dl",{class:"grid grid-cols-[max-content_1fr] gap-x-4 gap-y-2 border border-base-300 rounded-box p-4 bg-base-100",children:r.map(c=>{let y=e[c],g=u[c],C=g?Be(g,y):null;return jsxs(Fragment,{children:[jsx("dt",{class:"text-xs font-semibold text-base-content/60 uppercase tracking-wide pt-0.5",children:c}),jsx("dd",{class:"min-w-0",children:jsx(Te,{val:y,mismatch:C})})]})})})]})}function Sr({docs:e,repoName:t,basePath:n,fk:o,fv:r,columns:s,schema:l,pagination:u}){let c=`${n}/${t}?fv_${o}=${encodeURIComponent(r)}`,y=ln(l,s);return jsxs("div",{class:"space-y-4",children:[jsxs("div",{class:"flex items-center justify-between gap-2",children:[jsxs("div",{class:"text-xs text-base-content/60",children:[jsx("span",{class:"font-mono",children:t}),jsx("span",{class:"opacity-50",children:" where "}),jsx("span",{class:"font-mono",children:o}),jsx("span",{class:"opacity-50",children:" = "}),jsx("span",{class:"font-mono break-all",children:r}),jsx("span",{class:"opacity-50",children:" \xB7 "}),jsxs("span",{children:[e.length," doc",e.length!==1?"s":""]})]}),jsx("a",{href:c,class:"btn btn-sm btn-outline",children:"Full view \u2192"})]}),jsx("div",{class:"overflow-x-auto rounded-box border border-base-300 bg-base-100",children:jsxs("table",{class:"table table-xs w-full",children:[jsx("thead",{children:jsxs("tr",{class:"bg-base-200/50",children:[s.map((g,C)=>jsx("th",{class:"text-xs font-semibold text-base-content/60 uppercase tracking-wide",children:g},C)),jsx("th",{})]})}),jsx("tbody",{children:e.length===0?jsx("tr",{children:jsx("td",{colspan:s.length+1,class:"text-center py-10 text-base-content/40",children:"No related documents"})}):e.map((g,C)=>{let h=String(g.docId??g.id??""),w=`${n}/${t}/${encodeURIComponent(h)}/edit`;return jsxs("tr",{class:"hover",children:[s.map((v,b)=>{let S=g[v],p=y[v],i=p?Be(p,S):null;return jsx("td",{class:"align-top py-1.5",children:jsx(Te,{val:S,mismatch:i})},b)}),jsx("td",{class:"text-right py-1.5",children:jsx("a",{href:w,class:"btn btn-xs btn-ghost",children:"Edit"})})]},C)})})]})}),(u.hasPrev||u.hasNext)&&jsxs("div",{class:"flex justify-center items-center gap-2",children:[u.hasPrev?jsx("button",{type:"button",class:"btn btn-xs btn-outline","data-frs-panel-page":"prev","data-cursor":u.prevCursor,children:"\u2190 Previous"}):jsx("button",{class:"btn btn-xs btn-outline",disabled:true,children:"\u2190 Previous"}),u.hasNext?jsx("button",{type:"button",class:"btn btn-xs btn-outline","data-frs-panel-page":"next","data-cursor":u.nextCursor,children:"Next \u2192"}):jsx("button",{class:"btn btn-xs btn-outline",disabled:true,children:"Next \u2192"})]})]})}function ln(e,t){if(!e)return {};let n={};for(let o of t)n[o]=Oe(Ee(e,o));return n}var ut,pt=Ke(()=>{Xe();dt();ut=({basePath:e=""})=>jsxs("div",{class:"fixed inset-0 z-[100] hidden pointer-events-none","data-frs-panel-root":true,"data-frs-base-path":e,"aria-hidden":"true",children:[jsx("div",{class:"absolute inset-0 bg-black/30 opacity-0 transition-opacity duration-200 pointer-events-auto","data-frs-panel-backdrop":true}),jsxs("aside",{class:"absolute top-0 right-0 h-full w-full md:w-1/2 bg-base-100 shadow-2xl border-l border-base-300 translate-x-full transition-transform duration-200 pointer-events-auto flex flex-col","data-frs-panel":true,role:"dialog","aria-label":"Relation preview",children:[jsxs("header",{class:"flex items-center justify-between px-5 py-3 border-b border-base-300 bg-base-200/40 shrink-0",children:[jsx("h2",{class:"font-semibold text-base truncate","data-frs-panel-title":true,children:"Relation"}),jsx("button",{type:"button",class:"btn btn-sm btn-ghost btn-circle","data-frs-panel-close":true,"aria-label":"Close panel",children:"\u2715"})]}),jsx("div",{class:"flex-1 overflow-auto p-5 text-sm","data-frs-panel-body":true,children:jsx("div",{class:"flex items-center justify-center py-12 text-base-content/40",children:jsx("span",{class:"loading loading-spinner loading-md"})})})]})]});});function It(e){if(e===null)return "null";if(e===void 0)return "undefined";if(e instanceof Timestamp)return "timestamp";if(e instanceof Date)return "date";if(Array.isArray(e))return "array";let t=typeof e;return t==="string"||t==="number"||t==="boolean"?t:"object"}function Nt(e,t){if(e===t)return true;if(e===null||t===null||e===void 0||t===void 0)return e===t;if(e instanceof Timestamp&&t instanceof Timestamp)return e.isEqual(t);if(e instanceof Date&&t instanceof Date)return e.getTime()===t.getTime();if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return false;for(let n=0;n<e.length;n++)if(!Nt(e[n],t[n]))return false;return true}if(typeof e=="object"&&typeof t=="object")try{return JSON.stringify(e)===JSON.stringify(t)}catch{return false}return false}function _t(e,t,n={}){let o=new Set([...n.exclude??[],...n.metaFields??[],...n.systemKeys??[]]),r=n.include?new Set(n.include):null,s=e??{},l=t??{},u=new Set([...Object.keys(s),...Object.keys(l)]),c={};for(let y of u){if(o.has(y)||r&&!r.has(y))continue;let g=s[y],C=l[y];Nt(g,C)||(c[y]={oldValue:g===void 0?null:g,newValue:C===void 0?null:C,type:{old:It(g),new:It(C)}});}return c}var Ln=7e5;function Dt(e){let t=e.ttlOverride??e.config.ttl,o={schemaVersion:2,historyDocId:randomUUID(),historyToObjectId:e.entityId,historySetAt:Timestamp.now(),operation:e.operation,meta:e.meta,changes:e.changes};t&&(o.expiresAt=Timestamp.fromMillis(Date.now()+t.days*24*60*60*1e3));let r=s=>{try{return Buffer.byteLength(JSON.stringify(s,(l,u)=>u instanceof Timestamp?u.toMillis():u),"utf8")}catch{return 0}};if(r(o.changes)>Ln){let s={};for(let[l,u]of Object.entries(o.changes)){let c=r(u.oldValue),y=r(u.newValue);s[l]={oldValue:c>5e4?"[truncated]":u.oldValue,newValue:y>5e4?"[truncated]":u.newValue,type:u.type};}o.changes=s,o._truncated=true;}return o}async function jt(e,t,n,o){let r=t;return n.onBeforeWrite&&(r=await n.onBeforeWrite(t,o)),r?(await e.doc(r.historyDocId).set(r),{written:true,entry:r}):{written:false,reason:"dropped-by-onBeforeWrite"}}function Ft(e,t){let n=e??{},o={},r=t.meta;if(!r)return o;let s=g=>{if(!g)return;let C=n[g];return C===void 0||C===null?null:String(C)},l=s(r.userId);l!==void 0&&(o.userId=l);let u=s(r.userEmail);u!==void 0&&(o.userEmail=u);let c=s(r.reason);c!==void 0&&(o.reason=c);let y=s(r.comment);if(y!==void 0&&(o.comment=y),r.extras&&r.extras.length>0){let g={},C=false;for(let h of r.extras)h in n&&(g[h]=n[h],C=true);C&&(o.extras=g);}return o}function zt(e){let t=e.meta;if(!t)return [];let n=[];return t.userId&&n.push(t.userId),t.userEmail&&n.push(t.userEmail),t.reason&&n.push(t.reason),t.comment&&n.push(t.comment),t.extras&&n.push(...t.extras),n}var Un="history";function Kn(e,t){let n=t.ref?.path??void 0;return n?`${n}/{docId}`:(console.warn(`[HistoryTriggers] Cannot determine collection path for "${e}". Skipping.`),null)}function Zt(e,t){let{onDocumentWritten:n}=t.deps,o={};for(let[r,s]of Object.entries(e)){let l=s._historyConfig??(typeof s.history=="object"&&s.history!==null&&"enabled"in s.history?s.history:void 0);if(!l?.enabled)continue;let u=l.subcollection??Un,c=l.ttl??t.defaults?.ttl,y=t.repos?.[r],g;if(s._isGroup){if(!y?.triggerPath){console.warn(`[HistoryTriggers] Skipping collection-group repo "${r}". Provide a triggerPath in the history triggers repos override.`);continue}g=y.triggerPath;}else g=y?.triggerPath??Kn(r,s);if(!g)continue;let C=s._systemKeys??[],h=C[0]??"docId",w=zt(l);o[`${r}_onHistory`]=n(g,async v=>{try{let b=v.data?.before?.data(),S=v.data?.after?.data(),p;if(!b&&S)p="create";else if(b&&!S)p="delete";else if(b&&S)p="update";else return;let i=String(S?.[h]??b?.[h]??v.params?.docId??v.data?.after?.id??v.data?.before?.id??"");if(!i)return;let m=_t(b??{},S??{},{include:l.include,exclude:l.exclude,metaFields:w,systemKeys:C});if(p==="update"&&Object.keys(m).length===0)return;let a=Ft(S??b??null,l),d=Dt({entityId:i,operation:p,changes:m,meta:a,config:l,ttlOverride:c}),f=v.data?.after?.ref??v.data?.before?.ref;if(!f)return;let k=f.collection(u);await jt(k,d,l,{repoName:r,docId:i,before:b??null,after:S??null});}catch(b){console.error(`[HistoryTriggers] Failed to record history for "${r}":`,b);}});}return o}function Vn(e){let t=[],n=e.replace(/[.*+?^${}()|[\]\\]/g,o=>o===":"?o:`\\${o}`).replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g,(o,r)=>(t.push(r),"([^/]+)"));return {pattern:new RegExp(`^${n}$`),paramNames:t}}function Gn(e){let t=e.path??e.url??"/",n=t.indexOf("?");return n===-1?t:t.slice(0,n)}var se=class{constructor(){this.routes=[];this.middlewares=[];this.notFoundHandler=(t,n)=>{n.status(404).send("Not Found");};this.errorHandler=(t,n,o)=>{console.error("[MiniRouter]",t),o.status(500).send("Internal Server Error");};}use(t){return this.middlewares.push(t),this}get(t,n){return this.addRoute("GET",t,n)}post(t,n){return this.addRoute("POST",t,n)}put(t,n){return this.addRoute("PUT",t,n)}patch(t,n){return this.addRoute("PATCH",t,n)}delete(t,n){return this.addRoute("DELETE",t,n)}onNotFound(t){return this.notFoundHandler=t,this}onError(t){return this.errorHandler=t,this}addRoute(t,n,o){let{pattern:r,paramNames:s}=Vn(n);return this.routes.push({method:t.toUpperCase(),pattern:r,paramNames:s,handler:o}),this}async handle(t,n){let o=(t.method??"GET").toUpperCase(),r=Gn(t),s=null,l={};for(let y of this.routes){if(y.method!==o)continue;let g=r.match(y.pattern);if(g){s=y,l={},y.paramNames.forEach((C,h)=>{l[C]=decodeURIComponent(g[h+1]??"");});break}}let u=Object.assign(t,{params:l}),c=s?s.handler:this.notFoundHandler;try{await this.runMiddlewareChain(u,n,c);}catch(y){this.errorHandler(y,t,n);}}async runMiddlewareChain(t,n,o){let r=0,s=async()=>{if(r<this.middlewares.length){let l=this.middlewares[r++];await l(t,n,s);}else await o(t,n);};await s();}};function ee(e,t){let n=t==="/"?"":t.replace(/\/$/,"");if(process.env.FUNCTIONS_EMULATOR==="true"){let s=process.env.GCLOUD_PROJECT??process.env.GOOGLE_CLOUD_PROJECT??"demo-project",l=process.env.FUNCTION_REGION??"us-central1",u=(process.env.FUNCTION_TARGET??"").replace(/\./g,"-");return `/${s}/${l}/${u}${n}`}let o=process.env.K_SERVICE,r=e?.hostname??e?.headers?.host??"";return o&&typeof r=="string"&&r.includes("cloudfunctions.net")?`/${o.toLowerCase()}${n}`:n}function fe(e){return !!e&&typeof e=="object"&&e.__authExtension===true}je();var me="__sync_version";var Xn=new Set(["ZodOptional","ZodNullable","ZodDefault"]);function Yn(e){let t=e,n=false;for(;;){let o=H(t);if(!Xn.has(o))break;(o==="ZodOptional"||o==="ZodNullable")&&(n=true);let r=G(t);if(!r)break;t=r;}return {inner:t,nullable:n}}var er={ZodString:"string",ZodNumber:"number",ZodBigInt:"bigint",ZodBoolean:"boolean",ZodDate:"timestamp",ZodEnum:"string",ZodNativeEnum:"string",ZodLiteral:"string"};function Ht(e,t,n,o,r,s,l,u){for(let[c,y]of Object.entries(e)){let g=n?`${n}__${c}`:c;if(r.has(c)||r.has(g))continue;let{inner:C,nullable:h}=Yn(y),w=H(C),v=o||h;if(w==="ZodObject"){let i=te(C);Ht(i,t,g,v,r,s,l,u);continue}let b=er[w]??"json",S=g===l||c===l,p=s[g]??s[c]??g;u.push({name:p,sqlType:t.mapType(b),nullable:S?false:v,isPrimaryKey:S});}}function Ge(e,t,n={}){let{primaryKey:o,exclude:r=[],columnMap:s={}}=n,l=new Set(r),u=te(e),c=[];return Ht(u,t,"",false,l,s,o,c),c.some(y=>y.name===me)||c.push({name:me,sqlType:t.mapType("bigint"),nullable:true,isPrimaryKey:false,description:"Monotonic publish version (Date.now() ms). Internal."}),c}function Lt(e){if(e==null)return null;if(typeof e=="object"&&typeof e.toDate=="function")return e.toDate().toISOString();if(e instanceof Date)return e.toISOString();if(Buffer.isBuffer(e))return e.toString("base64");if(e instanceof Uint8Array)return Buffer.from(e).toString("base64");if(typeof e=="object"&&"latitude"in e&&"longitude"in e){let t=e;return JSON.stringify({lat:t.latitude,lng:t.longitude})}return Array.isArray(e)?JSON.stringify(e.map(Lt)):e}function Ut(e,t,n){for(let[o,r]of Object.entries(e)){let s=t?`${t}__${o}`:o;r!=null&&typeof r=="object"&&!Array.isArray(r)&&!(r instanceof Date)&&!Buffer.isBuffer(r)&&!(r instanceof Uint8Array)&&typeof r.toDate!="function"&&!("latitude"in r&&"longitude"in r)?Ut(r,s,n):n[s]=Lt(r);}}function Fe(e,t){let n=new Set(t?.exclude),o=t?.columnMap??{},r={};Ut(e,"",r);let s={};for(let[l,u]of Object.entries(r)){if(n.has(l))continue;let c=l.split("__")[0];if(c!==l&&n.has(c))continue;let y=o[l]??(l.includes("__")?o[l.split("__").pop()]:void 0)??l;s[y]=u;}return s}function ce(e,t,n){return `<!DOCTYPE html>
|
|
2
2
|
<html lang="en"><head>
|
|
3
3
|
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
4
4
|
<title>${e} \u2014 Sync Admin</title>
|
|
@@ -28,67 +28,60 @@ import {jsx,jsxs,Fragment}from'hono/jsx/jsx-runtime';import {Timestamp}from'fire
|
|
|
28
28
|
<nav><a href="${t}/">\u2190 Dashboard</a></nav>
|
|
29
29
|
<h1>${e}</h1>
|
|
30
30
|
${n}
|
|
31
|
-
</body></html>`}function
|
|
32
|
-
<td><strong>${
|
|
33
|
-
<td>${
|
|
34
|
-
<td>${
|
|
35
|
-
<td>${
|
|
36
|
-
<td>${
|
|
31
|
+
</body></html>`}function de(e,t,n=200){e.status(n).set("Content-Type","text/html; charset=utf-8").send(t);}function $e(e,t,n=200){e.status(n).set("Content-Type","application/json").send(JSON.stringify(t,null,2));}function Je(e){return (e.headers?.accept??"").includes("application/json")}function Kt(e,t,n,o,r,s,l,u){let c=(r.basePath??"/").replace(/\/$/,"")||"",y=r.featuresFlag??{},g=[];for(let[h,w]of Object.entries(e)){let v=s[h];g.push({name:h,schema:w.schema??null,documentKey:w._systemKeys?.[0]??w.documentKey??"docId",tableName:v?.tableName??h,isGroup:!!w._isGroup,repoCfg:v,repo:w});}let C=new se;if(r.auth)if(fe(r.auth)){let h=r.auth;for(let w of h.routes){let v=`${c}${w.path}`;w.method==="GET"?C.get(v,w.handler):C.post(v,w.handler);}C.use(h.middleware);}else if(typeof r.auth=="function")C.use(r.auth);else {let h=r.auth.realm??"Sync Admin",w="Basic "+Buffer.from(`${r.auth.username}:${r.auth.password}`).toString("base64");C.use((v,b,S)=>{if((v.headers?.authorization??"")!==w){b.status(401).set("WWW-Authenticate",`Basic realm="${h}"`).set("Content-Type","text/plain").send("Unauthorized");return}S();});}return C.get(`${c}/`,(h,w)=>{let v=ee(h,c),b=g.map(i=>{let m=[];return y.healthCheck&&m.push(`<a class="btn" href="${v}/${i.name}/health">Health</a>`),y.manualSync&&m.push(`<a class="btn btn-primary" href="${v}/${i.name}/force-sync">Force Sync</a>`),`<tr>
|
|
32
|
+
<td><strong>${i.name}</strong></td>
|
|
33
|
+
<td>${i.tableName}</td>
|
|
34
|
+
<td>${i.isGroup?'<span class="badge badge-warn">group</span>':'<span class="badge badge-ok">collection</span>'}</td>
|
|
35
|
+
<td>${i.schema?"\u2713":"\u2717"}</td>
|
|
36
|
+
<td>${m.join(" ")}</td>
|
|
37
37
|
</tr>`}).join(`
|
|
38
|
-
`),S=y.
|
|
38
|
+
`),S=y.configCheck?`<p style="margin-top:.5rem"><a class="btn" href="${v}/config-check">\u2699 Config Check</a></p>`:"",p=ce("Sync Dashboard",v,`<div class="card">
|
|
39
39
|
<table>
|
|
40
40
|
<thead><tr><th>Repository</th><th>Table</th><th>Type</th><th>Schema</th><th>Actions</th></tr></thead>
|
|
41
41
|
<tbody>${b}</tbody>
|
|
42
42
|
</table>
|
|
43
43
|
${S}
|
|
44
|
-
|
|
45
|
-
</div>`);ie(x,a);}),C.get(`${c}`,(h,x)=>{let v=ee(h,c);x.status(302).set("Location",`${v}/`).send("");}),y.healthCheck&&C.get(`${c}/:repoName/health`,async(h,x)=>{let v=ee(h,c),b=g.find(O=>O.name===h.params.repoName);if(!b){ie(x,ae("Not Found",v,`<p>Unknown repo: ${h.params.repoName}</p>`),404);return}if(!b.schema){ie(x,ae("Health Check",v,`<p class="badge badge-warn">No Zod schema attached to "${b.name}"</p>`));return}let S=Je(b.schema,t.dialect,{primaryKey:b.documentKey,exclude:b.repoCfg?.exclude,columnMap:b.repoCfg?.columnMap}),p=[],a=false,f=null;try{a=await t.tableExists(b.tableName),a&&(p=await t.getTableColumns(b.tableName));}catch(O){f=O?.message??String(O);}let s=new Set(p),d=new Set(S.map(O=>O.name)),m=S.filter(O=>!s.has(O.name)),k=p.filter(O=>!d.has(O)),w=S.filter(O=>s.has(O.name)),$=a&&m.length===0&&!f;if(ze(h)){we(x,{repo:b.name,table:b.tableName,tableExists:a,healthy:$,error:f,columns:{expected:S.map(O=>({name:O.name,type:O.sqlType,nullable:O.nullable,isPrimaryKey:O.isPrimaryKey})),actual:p,matched:w.map(O=>O.name),missing:m.map(O=>({name:O.name,type:O.sqlType})),extra:k}});return}let R=$?'<span class="badge badge-ok">Healthy</span>':'<span class="badge badge-err">Unhealthy</span>',T=S.map(O=>{let N=s.has(O.name)?'<span class="badge badge-ok">OK</span>':'<span class="badge badge-err">MISSING</span>';return `<tr><td>${O.name}</td><td>${O.sqlType}</td><td>${O.nullable?"Yes":"No"}</td><td>${O.isPrimaryKey?"\u2713":""}</td><td>${N}</td></tr>`}).join(`
|
|
44
|
+
</div>`);de(w,p);}),C.get(`${c}`,(h,w)=>{let v=ee(h,c);w.status(302).set("Location",`${v}/`).send("");}),y.healthCheck&&C.get(`${c}/:repoName/health`,async(h,w)=>{let v=ee(h,c),b=g.find(O=>O.name===h.params.repoName);if(!b){de(w,ce("Not Found",v,`<p>Unknown repo: ${h.params.repoName}</p>`),404);return}if(!b.schema){de(w,ce("Health Check",v,`<p class="badge badge-warn">No Zod schema attached to "${b.name}"</p>`));return}let S=Ge(b.schema,t.dialect,{primaryKey:b.documentKey,exclude:b.repoCfg?.exclude,columnMap:b.repoCfg?.columnMap}),p=[],i=false,m=null;try{i=await t.tableExists(b.tableName),i&&(p=await t.getTableColumns(b.tableName));}catch(O){m=O?.message??String(O);}let a=new Set(p),d=new Set(S.map(O=>O.name)),f=S.filter(O=>!a.has(O.name)),k=p.filter(O=>!d.has(O)),x=S.filter(O=>a.has(O.name)),$=i&&f.length===0&&!m;if(Je(h)){$e(w,{repo:b.name,table:b.tableName,tableExists:i,healthy:$,error:m,columns:{expected:S.map(O=>({name:O.name,type:O.sqlType,nullable:O.nullable,isPrimaryKey:O.isPrimaryKey})),actual:p,matched:x.map(O=>O.name),missing:f.map(O=>({name:O.name,type:O.sqlType})),extra:k}});return}let R=$?'<span class="badge badge-ok">Healthy</span>':'<span class="badge badge-err">Unhealthy</span>',T=S.map(O=>{let N=a.has(O.name)?'<span class="badge badge-ok">OK</span>':'<span class="badge badge-err">MISSING</span>';return `<tr><td>${O.name}</td><td>${O.sqlType}</td><td>${O.nullable?"Yes":"No"}</td><td>${O.isPrimaryKey?"\u2713":""}</td><td>${N}</td></tr>`}).join(`
|
|
46
45
|
`),A=k.map(O=>`<tr><td>${O}</td><td colspan="3" class="muted">not in schema</td><td><span class="badge badge-warn">EXTRA</span></td></tr>`).join(`
|
|
47
|
-
`),E=
|
|
48
|
-
<p>Table: <code>${b.tableName}</code> ${
|
|
49
|
-
${
|
|
46
|
+
`),E=ce(`Health: ${b.name}`,v,`<div class="card">
|
|
47
|
+
<p>Table: <code>${b.tableName}</code> ${i?R:'<span class="badge badge-err">NOT FOUND</span>'}</p>
|
|
48
|
+
${m?`<p class="badge badge-err">Error: ${m}</p>`:""}
|
|
50
49
|
<h2>Columns</h2>
|
|
51
50
|
<table>
|
|
52
51
|
<thead><tr><th>Column</th><th>SQL Type</th><th>Nullable</th><th>PK</th><th>Status</th></tr></thead>
|
|
53
52
|
<tbody>${T}${A}</tbody>
|
|
54
53
|
</table>
|
|
55
|
-
</div>`);
|
|
54
|
+
</div>`);de(w,E);}),y.manualSync&&(C.get(`${c}/:repoName/force-sync`,(h,w)=>{let v=ee(h,c),b=g.find(p=>p.name===h.params.repoName);if(!b){de(w,ce("Not Found",v,`<p>Unknown repo: ${h.params.repoName}</p>`),404);return}let S=ce(`Force Sync: ${b.name}`,v,`<div class="card">
|
|
56
55
|
<p>This will read <strong>all</strong> documents from the <code>${b.name}</code> Firestore collection
|
|
57
56
|
and upsert them into the <code>${b.tableName}</code> SQL table.</p>
|
|
58
57
|
<p class="muted" style="margin:.75rem 0">This may take a while for large collections.</p>
|
|
59
58
|
<form method="POST" action="${v}/${b.name}/force-sync">
|
|
60
59
|
<button type="submit" class="btn btn-primary">Start Force Sync</button>
|
|
61
60
|
</form>
|
|
62
|
-
</div>`);
|
|
61
|
+
</div>`);de(w,S);}),C.post(`${c}/:repoName/force-sync`,async(h,w)=>{let v=ee(h,c),b=g.find($=>$.name===h.params.repoName);if(!b){$e(w,{error:`Unknown repo: ${h.params.repoName}`},404);return}let S=b.repo.ref;if(!S){$e(w,{error:`No collection reference for "${b.name}"`},400);return}let p=0,i=0,m=[],a=500,d=S.limit(a),f=null;try{for(;;){let T=await(f?d.startAfter(f):d).get();if(T.empty)break;for(let A of T.docs){let E=A.data(),O=String(E[b.documentKey]??A.id),N=Fe(E,{exclude:b.repoCfg?.exclude,columnMap:b.repoCfg?.columnMap});try{await o({operation:"UPSERT",repoName:b.name,docId:O,data:N,timestamp:new Date().toISOString()}),p++;}catch(j){i++;let I=j?.message??String(j);console.error(`[ForceSync:${b.name}] doc=${O} failed:`,j),m.length<5&&m.push(`${O}: ${I}`);}}if(f=T.docs[T.docs.length-1],T.docs.length<a)break}let $=n.get(b.name);$&&await $.flush();}catch($){if(Je(h)){$e(w,{error:$?.message??String($),synced:p,errors:i},500);return}de(w,ce(`Force Sync: ${b.name}`,v,`<div class="card">
|
|
63
62
|
<p class="badge badge-err">Error: ${$?.message??String($)}</p>
|
|
64
|
-
<p>Synced ${p} docs before failure (${
|
|
65
|
-
</div>`),500);return}if(
|
|
66
|
-
<pre style="white-space:pre-wrap">${
|
|
63
|
+
<p>Synced ${p} docs before failure (${i} errors).</p>
|
|
64
|
+
</div>`),500);return}if(Je(h)){$e(w,{repo:b.name,table:b.tableName,synced:p,errors:i,...m.length>0&&{errorSamples:m}});return}let k=m.length>0?`<details style="margin-top:1rem"><summary>First ${m.length} error(s)</summary>
|
|
65
|
+
<pre style="white-space:pre-wrap">${m.map($=>$.replace(/[<>&]/g,R=>`&#${R.charCodeAt(0)};`)).join(`
|
|
67
66
|
|
|
68
|
-
`)}</pre></details>`:"",
|
|
69
|
-
<p class="badge ${
|
|
67
|
+
`)}</pre></details>`:"",x=ce(`Force Sync: ${b.name}`,v,`<div class="card">
|
|
68
|
+
<p class="badge ${i>0?"badge-warn":"badge-ok"}">${i>0?"Completed with errors":"Complete"}</p>
|
|
70
69
|
<p>Synced <strong>${p}</strong> documents to <code>${b.tableName}</code>.</p>
|
|
71
|
-
${
|
|
70
|
+
${i>0?`<p class="badge badge-warn">${i} error(s)</p>`:""}
|
|
72
71
|
${k}
|
|
73
|
-
</div>`);
|
|
74
|
-
`),p=
|
|
75
|
-
|
|
76
|
-
<thead><tr><th>Repository</th><th>Table</th><th>Pending</th></tr></thead>
|
|
77
|
-
<tbody>${S}</tbody>
|
|
78
|
-
</table>
|
|
79
|
-
</div>`);ie(x,p);}),y.configCheck&&C.get(`${c}/config-check`,async(h,x)=>{let v=ee(h,c),b=process.env.GCLOUD_PROJECT??process.env.GOOGLE_CLOUD_PROJECT??process.env.GCP_PROJECT??"unknown",S="https://console.cloud.google.com",p=u??"firestore-sync",a=[];try{await t.tableExists("__nonexistent_health_check__"),a.push({name:"BigQuery API",category:"bigquery",status:"ok",message:"BigQuery API is reachable"});}catch($){let R=$?.message??String($),T=R.toLowerCase(),A=T.includes("disabled")||T.includes("has not been used")||T.includes("accessnotconfigured"),E=T.includes("permission")||R.includes("403")||T.includes("access denied"),O=T.includes("project")&&T.includes("not found"),N=T.includes("not found")||R.includes("404");A?a.push({name:"BigQuery API",category:"bigquery",status:"error",message:"BigQuery API is not enabled",fix:{gcloud:`gcloud services enable bigquery.googleapis.com --project=${b}`,console:`${S}/apis/library/bigquery.googleapis.com?project=${b}`}}):O?a.push({name:"BigQuery Project",category:"bigquery",status:"error",message:R,fix:{hint:"The GCP project does not exist or the credentials don't have access to it. In the Firebase emulator, GCLOUD_PROJECT may override the configured projectId. Ensure you pass the correct projectId to the BigQuery constructor and have valid credentials.",console:`${S}/home/dashboard`}}):E?a.push({name:"BigQuery API",category:"bigquery",status:"error",message:`Permission denied: ${R}`,fix:{hint:"Grant the service account BigQuery Data Editor + BigQuery Job User roles",gcloud:[`SA=$(gcloud run services describe YOUR_SERVICE --region=YOUR_REGION --format="value(spec.template.spec.serviceAccountName)" --project=${b})`,`gcloud projects add-iam-policy-binding ${b} --member="serviceAccount:$SA" --role="roles/bigquery.dataEditor"`,`gcloud projects add-iam-policy-binding ${b} --member="serviceAccount:$SA" --role="roles/bigquery.jobUser"`].join(`
|
|
80
|
-
`),console:`${S}/iam-admin/iam?project=${b}`}}):N?a.push({name:"BigQuery Dataset",category:"bigquery",status:"error",message:`Dataset not found: ${R}`,fix:{hint:"Create the dataset first",gcloud:`bq mk --dataset ${b}:YOUR_DATASET_ID`,console:`${S}/bigquery?project=${b}`}}):a.push({name:"BigQuery API",category:"bigquery",status:"ok",message:"BigQuery API is reachable (table lookup returned expected error)"});}for(let $ of g)try{let R=await t.tableExists($.tableName);a.push({name:`Table: ${$.tableName}`,category:"bigquery",status:R?"ok":"warn",message:R?`Table \`${$.tableName}\` exists`:`Table \`${$.tableName}\` does not exist yet`,...!R&&{fix:{hint:"Table will be auto-created on first sync if autoMigrate is enabled. Or create it manually."}}});}catch(R){a.push({name:`Table: ${$.tableName}`,category:"bigquery",status:"error",message:R?.message??String(R)});}if(l)for(let $ of g){let R=`${p}-${$.name}`;try{let T=l.topic(R);if(typeof T.exists=="function"){let[A]=await T.exists();a.push({name:`Topic: ${R}`,category:"pubsub",status:A?"ok":"error",message:A?`Topic \`${R}\` exists`:`Topic \`${R}\` does not exist`,...!A&&{fix:{gcloud:`gcloud pubsub topics create ${R} --project=${b}`,console:`${S}/cloudpubsub/topic/list?project=${b}`}}});}else a.push({name:`Topic: ${R}`,category:"pubsub",status:"warn",message:"Cannot verify topic existence (PubSub client doesn't expose .exists())",fix:{gcloud:`gcloud pubsub topics create ${R} --project=${b}`,console:`${S}/cloudpubsub/topic/list?project=${b}`,hint:"Ensure the topic exists. It is auto-created by the Firebase emulator but must exist in production."}});}catch(T){let A=T?.message??String(T),E=A.includes("disabled")||A.includes("has not been used");if(a.push({name:E?"Pub/Sub API":`Topic: ${R}`,category:"pubsub",status:"error",message:E?"Pub/Sub API is not enabled":A,fix:E?{gcloud:`gcloud services enable pubsub.googleapis.com --project=${b}`,console:`${S}/apis/library/pubsub.googleapis.com?project=${b}`}:{gcloud:`gcloud pubsub topics create ${R} --project=${b}`,console:`${S}/cloudpubsub/topic/list?project=${b}`}}),E)break}}else a.push({name:"Pub/Sub Client",category:"pubsub",status:"warn",message:"PubSub client not available for config check"});if(ze(h)){let $=a.every(R=>R.status==="ok");we(x,{project:b,healthy:$,checks:a});return}let f=$=>$==="ok"?'<span class="badge badge-ok">OK</span>':$==="warn"?'<span class="badge badge-warn">WARN</span>':'<span class="badge badge-err">ERROR</span>',s={bigquery:a.filter($=>$.category==="bigquery"),pubsub:a.filter($=>$.category==="pubsub"),firestore:a.filter($=>$.category==="firestore")},d=($,R)=>{if(R.length===0)return "";let T=R.map(A=>{let E="";if(A.fix){let O=[];A.fix.hint&&O.push(`<p class="muted">${A.fix.hint}</p>`),A.fix.gcloud&&O.push(`<pre>$ ${A.fix.gcloud}</pre>`),A.fix.console&&O.push(`<p><a href="${A.fix.console}" target="_blank">Open GCP Console \u2192</a></p>`),E=`<div style="margin-top:.5rem">${O.join("")}</div>`;}return `<tr>
|
|
81
|
-
<td>${f(A.status)}</td>
|
|
72
|
+
</div>`);de(w,x);})),y.configCheck&&C.get(`${c}/config-check`,async(h,w)=>{let v=ee(h,c),b=process.env.GCLOUD_PROJECT??process.env.GOOGLE_CLOUD_PROJECT??process.env.GCP_PROJECT??"unknown",S="https://console.cloud.google.com",p=u??"firestore-sync",i=[];try{await t.tableExists("__nonexistent_health_check__"),i.push({name:"BigQuery API",category:"bigquery",status:"ok",message:"BigQuery API is reachable"});}catch($){let R=$?.message??String($),T=R.toLowerCase(),A=T.includes("disabled")||T.includes("has not been used")||T.includes("accessnotconfigured"),E=T.includes("permission")||R.includes("403")||T.includes("access denied"),O=T.includes("project")&&T.includes("not found"),N=T.includes("not found")||R.includes("404");A?i.push({name:"BigQuery API",category:"bigquery",status:"error",message:"BigQuery API is not enabled",fix:{gcloud:`gcloud services enable bigquery.googleapis.com --project=${b}`,console:`${S}/apis/library/bigquery.googleapis.com?project=${b}`}}):O?i.push({name:"BigQuery Project",category:"bigquery",status:"error",message:R,fix:{hint:"The GCP project does not exist or the credentials don't have access to it. In the Firebase emulator, GCLOUD_PROJECT may override the configured projectId. Ensure you pass the correct projectId to the BigQuery constructor and have valid credentials.",console:`${S}/home/dashboard`}}):E?i.push({name:"BigQuery API",category:"bigquery",status:"error",message:`Permission denied: ${R}`,fix:{hint:"Grant the service account BigQuery Data Editor + BigQuery Job User roles",gcloud:[`SA=$(gcloud run services describe YOUR_SERVICE --region=YOUR_REGION --format="value(spec.template.spec.serviceAccountName)" --project=${b})`,`gcloud projects add-iam-policy-binding ${b} --member="serviceAccount:$SA" --role="roles/bigquery.dataEditor"`,`gcloud projects add-iam-policy-binding ${b} --member="serviceAccount:$SA" --role="roles/bigquery.jobUser"`].join(`
|
|
73
|
+
`),console:`${S}/iam-admin/iam?project=${b}`}}):N?i.push({name:"BigQuery Dataset",category:"bigquery",status:"error",message:`Dataset not found: ${R}`,fix:{hint:"Create the dataset first",gcloud:`bq mk --dataset ${b}:YOUR_DATASET_ID`,console:`${S}/bigquery?project=${b}`}}):i.push({name:"BigQuery API",category:"bigquery",status:"ok",message:"BigQuery API is reachable (table lookup returned expected error)"});}for(let $ of g)try{let R=await t.tableExists($.tableName);i.push({name:`Table: ${$.tableName}`,category:"bigquery",status:R?"ok":"warn",message:R?`Table \`${$.tableName}\` exists`:`Table \`${$.tableName}\` does not exist yet`,...!R&&{fix:{hint:"Table will be auto-created on first sync if autoMigrate is enabled. Or create it manually."}}});}catch(R){i.push({name:`Table: ${$.tableName}`,category:"bigquery",status:"error",message:R?.message??String(R)});}if(l)for(let $ of g){let R=`${p}-${$.name}`;try{let T=l.topic(R);if(typeof T.exists=="function"){let[A]=await T.exists();i.push({name:`Topic: ${R}`,category:"pubsub",status:A?"ok":"error",message:A?`Topic \`${R}\` exists`:`Topic \`${R}\` does not exist`,...!A&&{fix:{gcloud:`gcloud pubsub topics create ${R} --project=${b}`,console:`${S}/cloudpubsub/topic/list?project=${b}`}}});}else i.push({name:`Topic: ${R}`,category:"pubsub",status:"warn",message:"Cannot verify topic existence (PubSub client doesn't expose .exists())",fix:{gcloud:`gcloud pubsub topics create ${R} --project=${b}`,console:`${S}/cloudpubsub/topic/list?project=${b}`,hint:"Ensure the topic exists. It is auto-created by the Firebase emulator but must exist in production."}});}catch(T){let A=T?.message??String(T),E=A.includes("disabled")||A.includes("has not been used");if(i.push({name:E?"Pub/Sub API":`Topic: ${R}`,category:"pubsub",status:"error",message:E?"Pub/Sub API is not enabled":A,fix:E?{gcloud:`gcloud services enable pubsub.googleapis.com --project=${b}`,console:`${S}/apis/library/pubsub.googleapis.com?project=${b}`}:{gcloud:`gcloud pubsub topics create ${R} --project=${b}`,console:`${S}/cloudpubsub/topic/list?project=${b}`}}),E)break}}else i.push({name:"Pub/Sub Client",category:"pubsub",status:"warn",message:"PubSub client not available for config check"});if(Je(h)){let $=i.every(R=>R.status==="ok");$e(w,{project:b,healthy:$,checks:i});return}let m=$=>$==="ok"?'<span class="badge badge-ok">OK</span>':$==="warn"?'<span class="badge badge-warn">WARN</span>':'<span class="badge badge-err">ERROR</span>',a={bigquery:i.filter($=>$.category==="bigquery"),pubsub:i.filter($=>$.category==="pubsub"),firestore:i.filter($=>$.category==="firestore")},d=($,R)=>{if(R.length===0)return "";let T=R.map(A=>{let E="";if(A.fix){let O=[];A.fix.hint&&O.push(`<p class="muted">${A.fix.hint}</p>`),A.fix.gcloud&&O.push(`<pre>$ ${A.fix.gcloud}</pre>`),A.fix.console&&O.push(`<p><a href="${A.fix.console}" target="_blank">Open GCP Console \u2192</a></p>`),E=`<div style="margin-top:.5rem">${O.join("")}</div>`;}return `<tr>
|
|
74
|
+
<td>${m(A.status)}</td>
|
|
82
75
|
<td><strong>${A.name}</strong><br><span class="muted">${A.message}</span>${E}</td>
|
|
83
76
|
</tr>`}).join(`
|
|
84
77
|
`);return `<h2>${$}</h2>
|
|
85
78
|
<table><thead><tr><th style="width:80px">Status</th><th>Check</th></tr></thead>
|
|
86
|
-
<tbody>${T}</tbody></table>`},k=
|
|
79
|
+
<tbody>${T}</tbody></table>`},k=i.every($=>$.status==="ok")?'<span class="badge badge-ok">All checks passed</span>':'<span class="badge badge-warn">Some issues found</span>',x=ce("Config Check",v,`<div class="card">
|
|
87
80
|
<p>Project: <code>${b}</code> ${k}</p>
|
|
88
|
-
${d("BigQuery",
|
|
89
|
-
${d("Pub/Sub",
|
|
90
|
-
${d("Firestore",
|
|
91
|
-
</div>`);
|
|
81
|
+
${d("BigQuery",a.bigquery)}
|
|
82
|
+
${d("Pub/Sub",a.pubsub)}
|
|
83
|
+
${d("Firestore",a.firestore)}
|
|
84
|
+
</div>`);de(w,x);}),async(h,w)=>{await C.handle(h,w);}}var tr="firestore-sync";function nr(e,t){let n=t.ref?.path??void 0;return n?`${n}/{docId}`:(console.warn(`[SyncTriggers] Cannot determine collection path for "${e}". Skipping.`),null)}function Vt(e,t){let{onDocumentCreated:n,onDocumentUpdated:o,onDocumentDeleted:r}=t.deps.firestoreTriggers,s=t.deps.pubsub,l=t?.topicPrefix??tr,u={},c=new Map;function y(C){let h=c.get(C);return h||(h=s.topic(C),c.set(C,h),h)}async function g(C,h){await y(C).publishMessage({json:h});}for(let[C,h]of Object.entries(e)){let w=t?.repos?.[C],v;if(h._isGroup){if(!w?.triggerPath){console.warn(`[SyncTriggers] Skipping collection-group repo "${C}". Provide a triggerPath in the sync repos config for group collections.`);continue}v=w.triggerPath;}else v=w?.triggerPath??nr(C,h);if(!v)continue;let b=h._systemKeys?.[0]??"docId",S=`${l}-${C}`;u[`${C}_onCreate`]=n(v,async p=>{let i=p.data;if(!i)return;let m=i.data();if(!m)return;let a=String(m[b]??i.id),d=Fe(m,{exclude:w?.exclude,columnMap:w?.columnMap}),f={operation:"INSERT",repoName:C,docId:a,data:d,timestamp:new Date().toISOString(),version:Date.now()};await g(S,f);}),u[`${C}_onUpdate`]=o(v,async p=>{let i=p.data?.after;if(!i)return;let m=i.data();if(!m)return;let a=String(m[b]??i.id),d=Fe(m,{exclude:w?.exclude,columnMap:w?.columnMap}),f={operation:"UPSERT",repoName:C,docId:a,data:d,timestamp:new Date().toISOString(),version:Date.now()};await g(S,f);}),u[`${C}_onDelete`]=r(v,async p=>{let i=p.data;if(!i)return;let m=i.data(),a=String(m?.[b]??i.id),d={operation:"DELETE",repoName:C,docId:a,data:null,timestamp:new Date().toISOString(),version:Date.now()};await g(S,d);});}return u}var We=class{constructor(t){this.buffer=[];this.flushing=false;this.timer=null;this.adapter=t.adapter,this.tableName=t.tableName,this.primaryKey=t.primaryKey,this.batchSize=t.batchSize??100,this.onFlushError=t.onFlushError;let n=t.flushIntervalMs??5e3;n>0&&(this.timer=setInterval(()=>{this.flush();},n),typeof this.timer=="object"&&"unref"in this.timer&&this.timer.unref());}get size(){return this.buffer.length}enqueue(...t){this.buffer.push(...t),this.buffer.length>=this.batchSize&&this.flush();}async flush(){if(this.flushing||this.buffer.length===0)return;this.flushing=true;let t=this.buffer.splice(0,this.batchSize);try{let n=new Map,o=[];for(let s of t)if(s.operation==="DELETE")o.push(s.docId),n.delete(s.docId);else if(s.data){let l=n.get(s.docId);if(!l)n.set(s.docId,s.data);else {let u=Number(l[me]??0);Number(s.data[me]??0)>=u&&n.set(s.docId,s.data);}}let r=Array.from(n.values());r.length>0&&await this.adapter.upsertRows(this.tableName,r,this.primaryKey),o.length>0&&await this.adapter.deleteRows(this.tableName,this.primaryKey,o);}catch(n){this.onFlushError?await this.onFlushError(t,n).catch(o=>{console.error(`[SyncQueue] Flush error for ${this.tableName}:`,n),console.error("[SyncQueue] Error handler also failed:",o);}):(this.buffer.unshift(...t),console.error(`[SyncQueue] Flush failed for ${this.tableName}:`,n));}finally{this.flushing=false;}}async shutdown(){this.timer&&(clearInterval(this.timer),this.timer=null),await this.flush();}};var Gt=new Set;async function rr(e,t,n,o,r,s,l){if(Gt.has(e))return;let u=Ge(n,t.dialect,{primaryKey:r,exclude:s,columnMap:l});if(!await t.tableExists(o))await t.createTable({tableName:o,columns:u});else {let y=new Set(await t.getTableColumns(o)),g=u.filter(C=>!y.has(C.name));g.length>0&&await t.addColumns(o,g);}Gt.add(e);}function Jt(e,t){let{deps:n,adapter:o,batchSize:r=100,flushIntervalMs:s=5e3,autoMigrate:l=false,topicPrefix:u="firestore-sync",workerOptions:c,repos:y={}}=t,g=new Map;function C(v,b){let S=g.get(v);if(S)return S;let i=y[v]?.tableName??v,m=async(a,d)=>{console.error(`[SyncWorker] Flush failed for "${v}" (${a.length} events):`,d);try{let f=`${u}-${v}-dlq`,k=n.pubsub.topic(f),[x]=await k.exists();x||(await k.create(),console.info(`[SyncWorker] Created DLQ topic "${f}"`));for(let $ of a)await k.publishMessage({json:$});}catch(f){console.error(`[SyncWorker] Dead-letter publish also failed for ${v}:`,f);}};return S=new We({adapter:o,tableName:i,primaryKey:b,batchSize:r,flushIntervalMs:s,onFlushError:m}),g.set(v,S),S}async function h(v){let{repoName:b}=v,S=e[b];if(!S){console.warn(`[SyncWorker] Unknown repo "${b}", skipping event`);return}let p=S._systemKeys?.[0]??S.documentKey??"docId",i=y[b],m=i?.columnMap,a=m?.[p]??p;if(l){let f=S.schema??void 0;if(f){let k=i?.tableName??b;await rr(b,o,f,k,p,i?.exclude,m);}}let d=C(b,a);v.data&&(v.data[me]=v.version??Date.now()),d.enqueue(v);}function w(v){let b=async S=>{let p=S.data?.message?.json??S.data?.json;if(!p){console.warn("[SyncWorker] Received empty PubSub message");return}await h(p);let i=g.get(p.repoName);i&&await i.flush();};return c?n.pubsubHandler.onMessagePublished({topic:v,...c},b):n.pubsubHandler.onMessagePublished(v,b)}return {handleMessage:h,createHandler:w,queues:g,async shutdown(){let v=[];for(let b of g.values())v.push(b.shutdown());await Promise.all(v);}}}var or="firestore-sync";function Wt(e){if(typeof e!="function")return e;let t=e,n;return new Proxy({},{get(o,r){return n||(n=t()),n[r]},has(o,r){return n||(n=t()),r in n}})}function Qt(e,t){let{deps:n,adapter:o,topicPrefix:r=or,batchSize:s,flushIntervalMs:l,autoMigrate:u,admin:c,workerOptions:y,repos:g}=t,C=Wt(n.pubsub),h=Wt(o),w=Vt(e,{deps:{firestoreTriggers:n.firestoreTriggers,pubsub:C},topicPrefix:r,repos:g}),v=Jt(e,{deps:{pubsubHandler:n.pubsubHandler,pubsub:C},adapter:h,batchSize:s,flushIntervalMs:l,autoMigrate:u,topicPrefix:r,workerOptions:y,repos:g}),b={};for(let i of Object.keys(e))b[`sync_${i}`]=v.createHandler(`${r}-${i}`);let S=null;c&&(S=Kt(e,h,v.queues,v.handleMessage,c,g??{},C,r),b.adminsync=c.onRequest?c.httpsOptions?c.onRequest(c.httpsOptions,S):c.onRequest(S):S);let p={functions:{...w,...b},adminHandler:S,handleMessage:v.handleMessage,queues:v.queues,shutdown:v.shutdown};for(let i of ["adminHandler","handleMessage","queues","shutdown"])Object.defineProperty(p,i,{enumerable:false});return p}je();je();function sr(e){return e.replace(/([A-Z])/g," $1").replace(/_/g," ").replace(/^\s/,"").replace(/^./,t=>t.toUpperCase())}function Xt(e){let t=e,n=true,o=false,r;for(;;){let s=H(t);if(s==="ZodOptional")n=false,t=G(t);else if(s==="ZodNullable")n=false,o=true,t=G(t);else if(s==="ZodDefault")n=false,r=Mt(t),t=G(t);else break}return {inner:t,required:n,nullable:o,defaultValue:r}}function ae(e,t=""){if(H(e)==="ZodObject"){let o=te(e);return Object.entries(o).map(([r,s])=>Yt(t?`${t}.${r}`:r,r,s))}return [Yt(t||"value",t||"value",e)]}function Yt(e,t,n){let{inner:o,required:r,nullable:s,defaultValue:l}=Xt(n),u=H(o),c=sr(t.split(".").pop()??t);switch(u){case "ZodString":{let y=qt(o),g=y.includes("email"),C=y.includes("url");return {name:e,label:c,type:"text",required:r,nullable:s,defaultValue:l,hint:g?"email":C?"url":void 0}}case "ZodNumber":case "ZodBigInt":return {name:e,label:c,type:"number",required:r,nullable:s,defaultValue:l};case "ZodBoolean":return {name:e,label:c,type:"checkbox",required:r,nullable:s,defaultValue:l};case "ZodDate":case "ZodCoerce":return {name:e,label:c,type:"datetime-local",required:r,nullable:s,defaultValue:l};case "ZodEnum":{let y=_e(o);return {name:e,label:c,type:"select",required:r,nullable:s,defaultValue:l,options:y}}case "ZodNativeEnum":{let y=De(o),g=Object.values(y).filter(C=>typeof C=="string");return {name:e,label:c,type:"select",required:r,nullable:s,defaultValue:l,options:g}}case "ZodLiteral":{let y=String(Ve(o)??"");return {name:e,label:c,type:"select",required:r,nullable:s,defaultValue:l,options:[y]}}case "ZodObject":{let y=ae(o,e);return {name:e,label:c,type:"textarea",required:r,nullable:s,defaultValue:l,nested:y,hint:"JSON object"}}case "ZodArray":{let y=Bt(o);if(!y)return {name:e,label:c,type:"textarea",required:r,nullable:s,defaultValue:l,hint:"JSON array"};let{inner:g}=Xt(y),C=H(g),h,w,v;switch(C){case "ZodString":h="text";break;case "ZodNumber":case "ZodBigInt":h="number";break;case "ZodBoolean":h="checkbox";break;case "ZodDate":h="datetime-local";break;case "ZodEnum":h="select",w=_e(g);break;case "ZodNativeEnum":h="select",w=Object.values(De(g)).filter(b=>typeof b=="string");break;case "ZodObject":h="object",v=ae(g);break;default:return {name:e,label:c,type:"textarea",required:r,nullable:s,defaultValue:l,hint:"JSON array"}}return {name:e,label:c,type:"textarea",required:r,nullable:s,defaultValue:l,arrayElementType:h,arrayElementOptions:w,arrayElementFields:v}}default:return {name:e,label:c,type:"textarea",required:r,nullable:s,defaultValue:l,hint:"JSON"}}}function ot(e,t=0){let n=t>0?`ml-${t*4}`:"",o=`field_${e.name.replace(/\./g,"__")}`,r=e.name,s=e.required?" required":"",l=e.defaultValue==="__null__",u=!l&&e.defaultValue!=null?String(e.defaultValue):"",c=e.nullable&&e.type!=="checkbox"?`<span class="flex items-center gap-1 shrink-0">
|
|
92
85
|
<input type="hidden" id="${o}__isnull" name="${r}__isnull" value="${l?"1":""}">
|
|
93
86
|
<label class="flex items-center gap-1 cursor-pointer select-none text-xs text-base-content/40 hover:text-base-content/70 border border-base-300 rounded px-2 py-1">
|
|
94
87
|
<input type="checkbox" class="checkbox checkbox-xs" ${l?"checked":""}
|
|
@@ -121,7 +114,7 @@ ${n}
|
|
|
121
114
|
${D(e.label)}${e.required?' <span class="text-error">*</span>':""}
|
|
122
115
|
</span>
|
|
123
116
|
</label>
|
|
124
|
-
</div>`;case "select":y=`<select id="${o}" name="${r}"${
|
|
117
|
+
</div>`;case "select":y=`<select id="${o}" name="${r}"${s}${l?' disabled style="opacity:0.35"':""} class="select select-bordered select-sm w-full">
|
|
125
118
|
${e.required&&!e.nullable?"":'<option value="">\u2014 optional \u2014</option>'}
|
|
126
119
|
${(e.options??[]).map(g=>`<option value="${D(g)}"${u===g?" selected":""}>${D(g)}</option>`).join(`
|
|
127
120
|
`)}
|
|
@@ -132,10 +125,10 @@ ${n}
|
|
|
132
125
|
${D(e.label)}${e.required?' <span class="text-error">*</span>':""}
|
|
133
126
|
</legend>
|
|
134
127
|
${g}
|
|
135
|
-
</fieldset>`}y=`<textarea id="${o}" name="${r}"${
|
|
128
|
+
</fieldset>`}y=`<textarea id="${o}" name="${r}"${s} rows="3"${l?' disabled style="opacity:0.35"':""}
|
|
136
129
|
data-json
|
|
137
130
|
class="textarea textarea-bordered textarea-sm w-full font-mono text-xs"
|
|
138
|
-
placeholder="${D(e.hint??"JSON")}">${D(u)}</textarea>`;break;default:y=`<input type="${e.type}" id="${o}" name="${r}"${
|
|
131
|
+
placeholder="${D(e.hint??"JSON")}">${D(u)}</textarea>`;break;default:y=`<input type="${e.type}" id="${o}" name="${r}"${s}${l?' disabled style="opacity:0.35"':""}
|
|
139
132
|
value="${D(u)}"
|
|
140
133
|
class="input input-bordered input-sm w-full"${e.hint==="email"?' autocomplete="email"':e.hint==="url"?' autocomplete="url"':""}>`;}return `
|
|
141
134
|
<div class="form-control mb-3 ${n}">
|
|
@@ -149,9 +142,9 @@ ${n}
|
|
|
149
142
|
<div class="flex-1 min-w-0">${y}</div>
|
|
150
143
|
${c}
|
|
151
144
|
</div>
|
|
152
|
-
</div>`}function D(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function ar(e,t){let n=t>0?`ml-${t*4}`:"",o=`field_${e.name.replace(/\./g,"__")}`,r=e.defaultValue==="__null__",
|
|
145
|
+
</div>`}function D(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function ar(e,t){let n=t>0?`ml-${t*4}`:"",o=`field_${e.name.replace(/\./g,"__")}`,r=e.defaultValue==="__null__",s=e.arrayElementType==="object",l=[];if(e.defaultValue!=null&&e.defaultValue!==""&&e.defaultValue!=="__null__")try{l=JSON.parse(String(e.defaultValue));}catch{}Array.isArray(l)||(l=[]);let u=s?l.map(g=>tn(e,g??{})).join(`
|
|
153
146
|
`):l.map(g=>en(e,g)).join(`
|
|
154
|
-
`),c=
|
|
147
|
+
`),c=s?tn(e,{}):en(e,""),y=e.nullable?`<span class="flex items-center gap-1 mt-2">
|
|
155
148
|
<input type="hidden" id="${o}__isnull" name="${D(e.name)}__isnull" value="${r?"1":""}">
|
|
156
149
|
<label class="flex items-center gap-1 cursor-pointer select-none text-xs text-base-content/40 hover:text-base-content/70 border border-base-300 rounded px-2 py-1">
|
|
157
150
|
<input type="checkbox" class="checkbox checkbox-xs" ${r?"checked":""}
|
|
@@ -190,7 +183,7 @@ ${n}
|
|
|
190
183
|
<div class="flex justify-end mb-1">
|
|
191
184
|
<button type="button" class="btn btn-xs btn-ghost text-error" data-frs-array-rm>×</button>
|
|
192
185
|
</div>
|
|
193
|
-
${(e.arrayElementFields??[]).map(r=>{let
|
|
186
|
+
${(e.arrayElementFields??[]).map(r=>{let s=t[r.name],l=s==null?"":typeof s=="object"?JSON.stringify(s):String(s);switch(r.type){case "checkbox":return `<div class="form-control mb-2">
|
|
194
187
|
<label class="label cursor-pointer justify-start gap-3">
|
|
195
188
|
<input type="checkbox" data-frs-key="${D(r.name)}" class="checkbox checkbox-sm checkbox-primary"${l==="true"?" checked":""}>
|
|
196
189
|
<span class="label-text text-sm">${D(r.label)}</span>
|
|
@@ -215,7 +208,7 @@ ${n}
|
|
|
215
208
|
<input type="text" data-frs-key="${D(r.name)}" value="${D(l)}" class="input input-bordered input-sm w-full">
|
|
216
209
|
</div>`}}).join(`
|
|
217
210
|
`)}
|
|
218
|
-
</div>`}function ye(e,t,n,o="Save"){let r=e.map(
|
|
211
|
+
</div>`}function ye(e,t,n,o="Save"){let r=e.map(s=>ot(s)).join(`
|
|
219
212
|
`);return `
|
|
220
213
|
<form action="${D(t)}" method="${n}" novalidate data-frs-form>
|
|
221
214
|
${r}
|
|
@@ -223,7 +216,7 @@ ${n}
|
|
|
223
216
|
<button type="submit" class="btn btn-primary btn-sm">${D(o)}</button>
|
|
224
217
|
<button type="button" class="btn btn-ghost btn-sm" onclick="history.back()">Cancel</button>
|
|
225
218
|
</div>
|
|
226
|
-
</form>`}var ir=new Set(["<","<=",">",">=","!="]),lr=new Set(["array-contains","array-contains-any"]);function st(e){return e==="desc"?"DESCENDING":"ASCENDING"}function cr(e){let t=e.split("/").filter(Boolean);return t[t.length-1]??e}function dr(e,t,n,o,r){let
|
|
219
|
+
</form>`}var ir=new Set(["<","<=",">",">=","!="]),lr=new Set(["array-contains","array-contains-any"]);function st(e){return e==="desc"?"DESCENDING":"ASCENDING"}function cr(e){let t=e.split("/").filter(Boolean);return t[t.length-1]??e}function dr(e,t,n,o,r){let s=[],l=new Set;for(let c of o)if(c.op==="=="||c.op==="in"||c.op==="not-in"){if(l.has(c.field))continue;l.add(c.field),s.push({fieldPath:c.field,order:"ASCENDING"});}for(let c of o)if(lr.has(c.op)){if(l.has(c.field))continue;l.add(c.field),s.push({fieldPath:c.field,arrayConfig:"CONTAINS"});}for(let c of o)if(ir.has(c.op)){if(l.has(c.field))continue;l.add(c.field);let y=r?.field===c.field?st(r.dir):"ASCENDING";s.push({fieldPath:c.field,order:y});}if(r&&!l.has(r.field)&&s.push({fieldPath:r.field,order:st(r.dir)}),s.length===1&&n)return fr(e,t,s[0]);let u=r&&s.some(c=>c.fieldPath===r.field)?st(r.dir):"ASCENDING";return s.push({fieldPath:"__name__",order:u}),ur(e,t,n,s)}function ur(e,t,n,o,r="(default)"){let s=`projects/${e}/databases/${r}/collectionGroups/${t}/indexes/_`,l=[...lt(1,s),...Qe(2,n?2:1)];for(let y of o)l.push(...nn(3,rn(y)));let u=r==="(default)"?"-default-":r,c=encodeURIComponent(on(l));return `https://console.firebase.google.com/project/${e}/firestore/databases/${u}/indexes?create_composite=${c}`}function pr(e){return e.match(/https:\/\/console\.firebase\.google\.com[^\s)"]*/)?.[0]}function at(e){let t=[],n=e>>>0;for(;n>=128;)t.push(n&127|128),n>>>=7;return t.push(n&127),t}function it(e,t){return e<<3|t}function lt(e,t){let n=Array.from(new TextEncoder().encode(t));return [it(e,2),...at(n.length),...n]}function Qe(e,t){return [it(e,0),...at(t)]}function nn(e,t){return [it(e,2),...at(t.length),...t]}function rn(e){let t=[...lt(1,e.fieldPath)];return e.arrayConfig==="CONTAINS"?t.push(...Qe(3,1)):t.push(...Qe(2,e.order==="DESCENDING"?2:1)),t}function on(e){let t=String.fromCharCode(...e),n;if(typeof Buffer<"u")n=Buffer.from(e).toString("base64");else if(typeof btoa<"u")n=btoa(t);else throw new Error("No base64 encoder available");return n.replace(/=+$/,"")}function fr(e,t,n,o="(default)"){let r=`projects/${e}/databases/${o}/collectionGroups/${t}/fields/${n.fieldPath}`,s=[...lt(1,r),...Qe(2,2),...nn(3,rn(n))],l=o==="(default)"?"-default-":o,u=encodeURIComponent(on(s));return `https://console.firebase.google.com/project/${e}/firestore/databases/${l}/indexes/automatic?create_exemption=${u}`}function mr(e){let t=e,n=[t?.firestore?.projectId,t?.firestore?.app?.options?.projectId,t?.firestore?._settings?.projectId,t?.firestore?.databaseId?.projectId,t?._firestore?.projectId];for(let r of n)if(typeof r=="string"&&r.length>0)return r;return process.env.GCLOUD_PROJECT||process.env.GOOGLE_CLOUD_PROJECT||process.env.FIREBASE_PROJECT_ID||void 0}function we(e){let t=e;return t?t.code===9?true:typeof t.message=="string"?t.message.includes("requires an index"):false:false}function ze(e,t){let n=e??{},o=we(e),r;if(o&&(r=n.message?pr(n.message):void 0,!r)){let s=mr(t.ref);if(s){let l=cr(t.path);r=dr(s,l,t.isGroup,t.filters,t.sort);}}return {type:o?"index":"error",message:o?"This query requires a composite index that does not exist yet.":n.message??"Query failed",indexUrl:r}}Xe();var an=`// \u2500\u2500 Shared helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
227
220
|
function frsGetBasePath() {
|
|
228
221
|
var root = document.querySelector("[data-frs-panel-root]");
|
|
229
222
|
var bp = root && root.getAttribute("data-frs-base-path");
|
|
@@ -1150,7 +1143,7 @@ function initColumnReorder(table) {
|
|
|
1150
1143
|
});
|
|
1151
1144
|
});
|
|
1152
1145
|
}
|
|
1153
|
-
`;function Be(){return jsx("script",{dangerouslySetInnerHTML:{__html:an}})}pt();function ge(e){return "<!DOCTYPE html>"+renderToString(e)}var Cr=["corporate","silk","dark"],$r=()=>jsxs("div",{class:"dropdown dropdown-end","data-frs-theme-switcher":true,children:[jsxs("button",{type:"button",tabIndex:0,class:"btn btn-sm btn-ghost text-neutral-content gap-1.5","aria-label":"Switch theme",children:[jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2",class:"size-4",children:[jsx("circle",{cx:"12",cy:"12",r:"4"}),jsx("path",{d:"M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"})]}),jsx("span",{class:"text-xs hidden sm:inline","data-frs-theme-current":true,children:"Theme"})]}),jsx("ul",{tabIndex:0,class:"dropdown-content menu menu-sm bg-base-100 text-base-content rounded-box z-50 mt-2 w-40 p-1 shadow-lg border border-base-300",children:Cr.map(e=>jsx("li",{children:jsxs("button",{type:"button","data-frs-theme":e,class:"capitalize justify-between",children:[jsx("span",{children:e}),jsx("span",{class:"hidden text-primary","data-frs-theme-check":e,children:"\u2713"})]})},e))})]}),he=({opts:e,children:t})=>{let{title:n,breadcrumb:o,flash:r,basePath:i="/"}=e;return jsxs("html",{lang:"en","data-theme":"corporate",children:[jsxs("head",{children:[jsx("meta",{charset:"UTF-8"}),jsx("meta",{name:"viewport",content:"width=device-width, initial-scale=1"}),jsxs("title",{children:[n," \u2014 FRS Admin"]}),jsx("script",{dangerouslySetInnerHTML:{__html:"(function(){try{var t=localStorage.getItem('frs-admin-theme');if(t){document.documentElement.setAttribute('data-theme',t);}}catch(_){}})();"}}),jsx("link",{href:"https://cdn.jsdelivr.net/npm/daisyui@5/themes.css",rel:"stylesheet",type:"text/css"}),jsx("link",{href:"https://cdn.jsdelivr.net/npm/daisyui@5/daisyui.css",rel:"stylesheet",type:"text/css"}),jsx("script",{src:"https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"})]}),jsxs("body",{class:"bg-base-200/50 min-h-screen flex flex-col",children:[jsxs("div",{class:"navbar bg-neutral text-neutral-content shadow-sm sticky top-0 z-50 px-6",children:[jsx("div",{class:"flex-1",children:jsx("a",{href:i,class:"font-bold text-lg tracking-tight hover:opacity-80 transition-opacity",children:"FRS Admin"})}),jsx("div",{class:"flex-none",children:jsx($r,{})})]}),jsxs("main",{class:"px-6 py-8 w-full flex-1",children:[o&&o.length>0&&jsx("div",{class:"text-sm breadcrumbs mb-4",children:jsx("ul",{children:o.map((l,u)=>l.href?jsx("li",{children:jsx("a",{href:l.href,children:l.label})},u):jsx("li",{class:"text-base-content/60",children:l.label},u))})}),jsx("h1",{class:"text-2xl font-bold mb-6",children:n}),r&&jsxs("div",{role:"alert",class:`alert ${r.type==="success"?"alert-success":r.type==="warning"?"alert-warning":"alert-error"} mb-6`,children:[jsx("span",{class:"flex-1",children:r.message}),r.action&&jsx("a",{href:r.action.href,...r.action.external?{target:"_blank",rel:"noopener noreferrer"}:{},class:"btn btn-sm btn-outline",children:r.action.label})]}),t]}),jsx(ut,{basePath:i}),jsx(Be,{})]})]})};function ft(e,t){return ge(jsx(he,{opts:t,children:jsx("div",{dangerouslySetInnerHTML:{__html:e}})}))}function mt(e,t){return ge(jsx(he,{opts:{title:"Repositories",basePath:t},children:e.length===0?jsxs("div",{class:"text-center py-20 text-base-content/50",children:[jsx("p",{class:"text-lg font-medium mb-1",children:"No repositories configured"}),jsx("p",{class:"text-sm",children:"Add a repository to your FRS config to get started."})]}):jsx("div",{class:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4",children:e.map(n=>jsx("a",{href:`${t}/${n.name}`,class:"card bg-base-100 border border-base-300 hover:shadow-md no-underline transition-shadow",children:jsxs("div",{class:"card-body p-5",children:[jsx("h2",{class:"card-title text-sm font-semibold",children:n.name}),jsx("p",{class:"text-xs text-base-content/50 font-mono",children:n.path})]})},n.name))})}))}var un=[{value:"==",label:"="},{value:"!=",label:"\u2260"},{value:"in",label:"in"},{value:"not-in",label:"not in"}],Ar=[{value:"==",label:"="},{value:"!=",label:"\u2260"},{value:"<",label:"<"},{value:"<=",label:"\u2264"},{value:">",label:">"},{value:">=",label:"\u2265"},{value:"in",label:"in"},{value:"not-in",label:"not in"}],Tr=[{value:"array-contains",label:"contains"},{value:"array-contains-any",label:"contains any"}];function Or(e){switch(e){case "ZodNumber":case "ZodBigInt":case "ZodDate":return Ar;case "ZodBoolean":return un;case "ZodArray":return Tr;default:return un}}var be="__null__";function Er(e){return `(function(cb){var i=document.getElementById('${e}');if(!i)return;if(cb.checked){i.dataset._prev=i.value;if(i.tagName==='SELECT'){var o=i.querySelector('option[value="${be}"]');if(!o){o=document.createElement('option');o.value='${be}';o.textContent='\u2205 null';o.dataset._auto='1';i.appendChild(o);}o.selected=true;}else{if(i.type==='number'||i.type==='datetime-local'){i.dataset._type=i.type;i.type='text';}i.value='${be}';i.readOnly=true;}i.style.opacity='0.55';}else{i.style.opacity='';if(i.tagName==='SELECT'){var o2=i.querySelector('option[value="${be}"][data-_auto="1"]');if(o2)o2.remove();var prev=i.dataset._prev||'';for(var k=0;k<i.options.length;k++)i.options[k].selected=(i.options[k].value===prev);}else{if(i.dataset._type){i.type=i.dataset._type;delete i.dataset._type;}i.readOnly=false;i.value=(i.dataset._prev&&i.dataset._prev!=='${be}')?i.dataset._prev:'';}}})(this)`}function Pr(e,t){return `(function(){var h=document.getElementById('${e}');var boxes=document.querySelectorAll('input[data-enum-group="${t}"]');h.value=Array.from(boxes).filter(function(b){return b.checked;}).map(function(b){return b.value;}).join(',');})()`}function qe({inputId:e,active:t}){return jsxs("label",{class:"flex items-center gap-1 cursor-pointer select-none text-xs text-base-content/60 hover:text-base-content border border-base-300 rounded-md px-1.5 py-1 shrink-0 leading-none h-8",title:"Filter where field IS NULL",children:[jsx("input",{type:"checkbox",class:"checkbox checkbox-xs",checked:t,onchange:Er(e)}),jsx("span",{children:"\u2205"})]})}function Ir({col:e,active:t}){let n=t?.value??"",o=n===be,r=`fv_input_${e.name.replace(/\./g,"__")}`,i=t?.op,l=i==="in"||i==="not-in";if(e.enumValues&&e.enumValues.length>0){if(l){let u=new Set(n.split(",").map(y=>y.trim()).filter(Boolean)),c=`eg_${e.name.replace(/\./g,"__")}`;return jsxs("div",{class:"flex flex-wrap items-center gap-1 w-full",children:[jsx("input",{type:"hidden",id:r,name:`fv_${e.name}`,value:n}),e.enumValues.map(y=>jsxs("label",{class:"flex items-center gap-1 text-xs border border-base-300 rounded px-2 cursor-pointer hover:bg-base-200",children:[jsx("input",{type:"checkbox",class:"checkbox checkbox-xs",value:y,checked:u.has(y),"data-enum-group":c,onchange:Pr(r,c)}),jsx("span",{children:y})]},y))]})}return jsxs("div",{class:"flex items-center gap-1 w-full",children:[jsxs("select",{id:r,name:`fv_${e.name}`,class:"select select-sm select-bordered w-full",style:o?"opacity:0.55":void 0,children:[jsx("option",{value:"",selected:n===""&&!o,children:"\u2014"}),e.enumValues.map(u=>jsx("option",{value:u,selected:n===u,children:u},u)),e.nullable&&jsx("option",{value:be,"data-_auto":"1",selected:o,children:"\u2205 null"})]}),e.nullable&&jsx(qe,{inputId:r,active:o})]})}if(e.zodType==="ZodBoolean")return jsxs("div",{class:"flex items-center gap-1 w-full",children:[jsxs("select",{id:r,name:`fv_${e.name}`,class:"select select-sm select-bordered w-full",style:o?"opacity:0.55":void 0,children:[jsx("option",{value:"",selected:n===""&&!o,children:"\u2014"}),jsx("option",{value:"true",selected:n==="true",children:"true"}),jsx("option",{value:"false",selected:n==="false",children:"false"}),e.nullable&&jsx("option",{value:be,"data-_auto":"1",selected:o,children:"\u2205 null"})]}),e.nullable&&jsx(qe,{inputId:r,active:o})]});if(e.zodType==="ZodArray"){let u=t?.op==="array-contains-any";return jsx("input",{id:r,type:"text",name:`fv_${e.name}`,value:n,placeholder:u?"val1, val2, \u2026":"value",class:"input input-sm input-bordered w-full"})}return e.zodType==="ZodNumber"||e.zodType==="ZodBigInt"?jsxs("div",{class:"flex items-center gap-1 w-full",children:[jsx("input",{id:r,type:o?"text":"number",name:`fv_${e.name}`,value:n,placeholder:"value",class:"input input-sm input-bordered w-full",readOnly:o||void 0,style:o?"opacity:0.55":void 0,"data-_type":o?"number":void 0}),e.nullable&&jsx(qe,{inputId:r,active:o})]}):e.zodType==="ZodDate"?jsxs("div",{class:"flex items-center gap-1 w-full",children:[jsx("input",{id:r,type:o?"text":"datetime-local",name:`fv_${e.name}`,value:n,class:"input input-sm input-bordered w-full",readOnly:o||void 0,style:o?"opacity:0.55":void 0,"data-_type":o?"datetime-local":void 0}),e.nullable&&jsx(qe,{inputId:r,active:o})]}):jsxs("div",{class:"flex items-center gap-1 w-full",children:[jsx("input",{id:r,type:"text",name:`fv_${e.name}`,value:n,placeholder:"value",class:"input input-sm input-bordered w-full",readOnly:o||void 0,style:o?"opacity:0.55":void 0}),e.nullable&&jsx(qe,{inputId:r,active:o})]})}function yt({action:e,columnMeta:t,activeFilters:n,isGroup:o}){let r=Object.fromEntries(n.map(c=>[c.field,c])),i=n.length>0,l=n.length>=2||o&&i,u=t.filter(c=>c.zodType!=="ZodObject"&&c.zodType!=="ZodRecord");return jsxs("details",{class:"collapse collapse-arrow bg-base-100 border border-base-300 rounded-box mb-6 shadow-sm",open:i?true:void 0,children:[jsxs("summary",{class:"collapse-title text-sm font-medium py-2 min-h-0",children:["Filters",i&&jsxs("span",{class:"badge badge-primary badge-sm ml-2",children:[n.length," active"]})]}),jsx("div",{class:"collapse-content pb-4 pt-2",children:jsxs("form",{method:"get",action:e,children:[jsx("div",{class:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4",children:u.map(c=>{let y=Or(c.zodType),g=r[c.name],C=g?.op??y[0].value;return jsxs("div",{class:"flex flex-col gap-1.5",children:[jsx("label",{class:"text-xs font-semibold text-base-content/60 uppercase tracking-wide",children:c.name}),jsxs("div",{class:"flex gap-1.5",children:[y.length>1?jsx("select",{name:`fo_${c.name}`,class:"select select-sm select-bordered w-20 shrink-0",children:y.map(h=>jsx("option",{value:h.value,selected:h.value===C,children:h.label},h.value))}):jsx("input",{type:"hidden",name:`fo_${c.name}`,value:y[0].value}),jsx(Ir,{col:c,active:g})]})]},c.name)})}),jsxs("div",{class:"flex flex-wrap gap-2 mt-4 pt-3 border-t border-base-200 items-center",children:[jsx("button",{type:"submit",class:"btn btn-sm btn-primary",children:"Apply"}),i&&jsx("a",{href:e,class:"btn btn-sm btn-ghost",children:"Clear"}),l&&jsxs("span",{class:"text-xs text-warning ml-auto flex items-center gap-1",children:[jsx("svg",{xmlns:"http://www.w3.org/2000/svg",class:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:jsx("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"})}),o?"Collection group queries require a composite index":"Multiple filters may require a composite index"]})]})]})})]})}function gt(e,t,n,o,r,i){let l=n==="create"?`Create ${e}`:`Edit ${e} / ${o??""}`,u=n==="create"?[{label:"Repositories",href:r},{label:e,href:`${r}/${e}`},{label:"New document"}]:[{label:"Repositories",href:r},{label:e,href:`${r}/${e}`},{label:`Edit ${o??""}`}];return ge(jsx(he,{opts:{title:l,breadcrumb:u,basePath:r,flash:i},children:jsx("div",{class:"card bg-base-100 border border-base-300",children:jsx("div",{class:"card-body p-6",children:jsx("div",{dangerouslySetInnerHTML:{__html:t}})})})}))}Xe();dt();function ht(e,t,n){let o=new URLSearchParams;for(let r of e)o.set(`fv_${r.field}`,r.value),o.set(`fo_${r.field}`,r.op);return t&&(o.set("ob",t.field),o.set("od",t.dir)),n&&o.set("ps",String(n)),o}function pn(e,t,n,o,r){let i=ht(e,o,r);return i.set("cursor",t),i.set("dir",n),`?${i.toString()}`}function Nr(e,t,n,o){let r=ht(n,void 0,o);return t?.field===e?t.dir==="asc"&&(r.set("ob",e),r.set("od","desc")):(r.set("ob",e),r.set("od","asc")),`?${r.toString()}`}function _r(e,t,n){return `?${ht(t,n,e).toString()}`}function bt(e,t,n,o,r,i,l=[],u=[],c=false,y=[],g,C,h,x,v,b,S,p=false){let a=`${o}/${e}`,f=`${a}/create`,s={};if(S)for(let R of n)s[R]=Oe(Ee(S,R));let d=(b??[]).filter(R=>{let T=s[R]??Oe(Ee(S,R));return T==="string"||T==="number"||T==="bigint"||T==="boolean"||T==="enum"||T==="literal"}),m=d.length>0,k=c,w=k||m,$=d.map(R=>{let T=Ee(S,R),A=Oe(T),E=l.find(O=>O.name===R);return {name:R,type:A,enumValues:E?.enumValues??null,nullable:E?.nullable??false}});return ge(jsxs(he,{opts:{title:e,breadcrumb:[{label:"Repositories",href:o},{label:e}],basePath:o,flash:i},children:[l.length>0&&jsx(yt,{action:a,columnMeta:l,activeFilters:u,isGroup:x}),h&&jsxs("div",{role:"alert",class:`alert ${h.type==="index"?"alert-warning":"alert-error"} mb-6 shadow-sm`,children:[jsx("svg",{xmlns:"http://www.w3.org/2000/svg",class:"h-6 w-6 shrink-0 stroke-current",fill:"none",viewBox:"0 0 24 24",children:h.type==="index"?jsx("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"}):jsx("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"})}),jsxs("div",{class:"flex-1",children:[jsx("h3",{class:"font-bold",children:h.type==="index"?"Composite index required":"Query failed"}),jsx("div",{class:"text-sm",children:h.message})]}),h.indexUrl&&jsx("a",{href:h.indexUrl,target:"_blank",rel:"noopener noreferrer",class:"btn btn-sm btn-outline",children:"Create Index \u2192"})]}),jsxs("div",{class:"flex flex-wrap justify-between items-center mb-4 gap-3","data-frs-toolbar":true,children:[jsxs("div",{class:"flex items-center gap-3",children:[jsxs("span",{class:"text-sm text-base-content/60",children:[t.length,typeof v=="number"&&jsxs(Fragment,{children:[" ","of ",jsx("span",{class:"font-semibold text-base-content/80",children:v})]})," ","document",(typeof v=="number"?v:t.length)!==1&&"s"]}),jsxs("div",{class:"flex items-center gap-1.5 text-sm text-base-content/60",children:[jsx("span",{children:"Rows"}),jsx("div",{class:"join",children:[10,25,50,100].map(R=>jsx("a",{href:_r(R,u,g),class:`join-item btn btn-xs ${C===R?"btn-active btn-primary":"btn-outline"}`,children:R},R))})]})]}),jsx("a",{href:f,class:"btn btn-primary btn-sm",children:"+ New"})]}),w&&jsxs("div",{class:"hidden mb-3 alert alert-info py-2 px-3","data-frs-bulk-bar":true,"data-frs-repo":e,"data-frs-total":typeof v=="number"?String(v):"","data-frs-page-size":String(C??t.length),"data-frs-allow-delete":k?"1":"0","data-frs-allow-update":m?"1":"0","data-frs-fields":JSON.stringify($),"data-frs-filters":JSON.stringify(u),children:[jsxs("div",{class:"flex-1 text-sm",children:[jsx("span",{"data-frs-bulk-summary":true,children:"0 selected"}),typeof v=="number"&&v>t.length&&jsxs("button",{type:"button",class:"ml-3 link link-primary text-sm hidden","data-frs-bulk-select-all":true,children:["Select all ",v," matching documents"]}),jsxs("span",{class:"hidden ml-3 italic","data-frs-bulk-all-active":true,children:["All ",v??"?"," matching documents are selected."," ",jsx("button",{type:"button",class:"link","data-frs-bulk-clear":true,children:"Clear selection"})]})]}),jsxs("div",{class:"flex gap-2",children:[m&&jsx("button",{type:"button",class:"btn btn-sm btn-outline","data-frs-bulk-action":"update",children:"Update field\u2026"}),k&&jsx("button",{type:"button",class:"btn btn-sm btn-error btn-outline","data-frs-bulk-action":"delete",children:"Delete"})]})]}),jsx("div",{class:"overflow-x-auto rounded-box border border-base-300 bg-base-100","data-frs-table-wrap":true,children:jsxs("table",{class:"table table-sm w-full","data-frs-table":true,"data-frs-repo":e,"data-frs-colcount":n.length,children:[jsx("thead",{children:jsxs("tr",{class:"bg-base-200/50",children:[w&&jsx("th",{class:"w-8",children:jsx("input",{type:"checkbox",class:"checkbox checkbox-xs checkbox-primary","data-frs-select-page":true,"aria-label":"Select all on this page"})}),[...n].map((R,T)=>{let A=g?.field===R,E=A?g.dir==="asc"?" \u25B2":" \u25BC":"";return jsx("th",{class:"text-xs font-semibold text-base-content/60 uppercase tracking-wide",children:jsxs("a",{href:Nr(R,g,u,C),class:`hover:text-base-content inline-flex items-center gap-0.5${A?" text-primary font-bold":""}`,children:[R,E]})},T)}),y.map((R,T)=>jsx("th",{class:"text-xs font-semibold text-base-content/60 uppercase tracking-wide",children:R.column},`rel-${T}`)),jsx("th",{class:"text-xs font-semibold text-base-content/60 uppercase tracking-wide text-right",children:"Actions"})]})}),jsx("tbody",{children:t.length===0?jsx("tr",{children:jsx("td",{colspan:n.length+y.length+1+(w?1:0),class:"text-center py-16 text-base-content/40",children:"No documents found"})}):t.map((R,T)=>{let A=String(R.docId??R.id??""),E=`${o}/${e}/${encodeURIComponent(A)}/edit`,O=`${o}/${e}/${encodeURIComponent(A)}/delete`;return jsxs("tr",{class:"hover","data-frs-row-id":A,children:[w&&jsx("td",{class:"align-middle py-2",children:jsx("input",{type:"checkbox",class:"checkbox checkbox-xs checkbox-primary","data-frs-select-row":true,value:A,"aria-label":`Select ${A}`})}),n.map((N,j)=>{let I=R[N],P=s[N],q=P?Me(P,I):null;return jsx("td",{class:"align-top py-2",children:jsx(Te,{val:I,mismatch:q})},j)}),y.map((N,j)=>{let I=R[N.key];if(I==null||I==="")return jsx("td",{class:"py-2"},`rel-${j}`);let P=N.type==="one"?`${o}/${N.targetRepo}/${encodeURIComponent(String(I))}/edit`:`${o}/${N.targetRepo}?fv_${N.targetKey}=${encodeURIComponent(String(I))}`;return jsx("td",{class:"align-middle py-2",children:jsx("a",{href:P,class:"btn btn-xs btn-ghost btn-outline","data-frs-relation":true,"data-frs-rel-type":N.type,"data-frs-rel-repo":N.targetRepo,"data-frs-rel-fk":N.targetKey,"data-frs-rel-val":String(I),"data-frs-rel-label":N.column,children:N.column})},`rel-${j}`)}),jsx("td",{class:"align-middle text-right whitespace-nowrap py-2",children:jsxs("div",{class:"flex gap-1 justify-end",children:[jsx("a",{href:E,class:"btn btn-xs btn-outline",children:"Edit"}),p&&jsx("a",{href:`${o}/${e}/${encodeURIComponent(A)}/history`,class:"btn btn-xs btn-outline",title:"View change history",children:"History"}),c&&jsx("form",{method:"post",action:O,onsubmit:"return confirm('Delete this document?')",children:jsx("button",{type:"submit",class:"btn btn-xs btn-error btn-outline",children:"Delete"})})]})})]},T)})})]})}),(r.hasPrev||r.hasNext)&&jsxs("div",{class:"flex flex-col items-center mt-6 gap-2",children:[jsxs("div",{class:"flex justify-center items-center gap-2",children:[r.hasPrev?jsx("a",{href:pn(u,r.prevCursor,"prev",g,C),class:"btn btn-sm btn-outline",children:"\u2190 Previous"}):jsx("button",{class:"btn btn-sm btn-outline",disabled:true,children:"\u2190 Previous"}),r.hasNext?jsx("a",{href:pn(u,r.nextCursor,"next",g,C),class:"btn btn-sm btn-outline",children:"Next \u2192"}):jsx("button",{class:"btn btn-sm btn-outline",disabled:true,children:"Next \u2192"})]}),typeof v=="number"&&jsxs("div",{class:"text-xs text-base-content/50",children:[v," total document",v!==1?"s":"",u.length>0?" matching filters":""]})]}),w&&m&&jsxs("dialog",{id:"frs-bulk-update-modal",class:"modal",children:[jsxs("div",{class:"modal-box",children:[jsx("h3",{class:"font-bold text-lg mb-3",children:"Bulk update field"}),jsx("p",{class:"text-sm text-base-content/60 mb-4","data-frs-bulk-update-summary":true,children:"Update one field on the selected documents."}),jsxs("form",{method:"dialog","data-frs-bulk-update-form":true,children:[jsxs("label",{class:"form-control w-full mb-3",children:[jsx("div",{class:"label",children:jsx("span",{class:"label-text text-xs uppercase tracking-wide",children:"Field"})}),jsxs("select",{class:"select select-bordered select-sm w-full",name:"field",required:true,"data-frs-bulk-field-select":true,children:[jsx("option",{value:"",children:"\u2014 Select a field \u2014"}),d.map(R=>jsx("option",{value:R,children:R},R))]})]}),jsx("div",{class:"mb-4","data-frs-bulk-value-container":true}),jsxs("div",{class:"modal-action",children:[jsx("button",{type:"button",class:"btn btn-sm btn-ghost","data-frs-bulk-update-cancel":true,children:"Cancel"}),jsx("button",{type:"submit",class:"btn btn-sm btn-primary","data-frs-bulk-update-submit":true,children:"Apply"})]})]})]}),jsx("form",{method:"dialog",class:"modal-backdrop",children:jsx("button",{children:"close"})})]})]}))}var jr="";function He(e,t){return ft(e,t)}function vt(e,t){return mt(e,t)}function xt(e,t,n,o,r,i,l,u,c,y,g,C,h,x,v,b,S,p){return bt(e,t,n,o,r,i,l,u,c,y,g,C,h,x,v,b,S,p)}function ve(e,t,n,o,r,i){return gt(e,t,n,o,r,i)}var fn="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";function zr(){let e="";for(let t=0;t<20;t++)e+=fn.charAt(Math.floor(Math.random()*fn.length));return e}function et(e,t){if(!t)return;let n=e[t];if(typeof n!="string"||!n)return;let o=n.split("/").filter(Boolean),r=[];for(let i=1;i<o.length;i+=2)r.push(o[i]);return r.length>0?r:void 0}async function Pe(e,t){let n=e.documentKey??"docId",o=`by${n.charAt(0).toUpperCase()}${n.slice(1)}`;if(typeof e.repo.get[o]=="function")try{let i=await e.repo.get[o](t);if(i)return i}catch{}return (await e.repo.query.by({where:[[n,"==",t]],limit:1}))[0]??null}function wt(e,t,n){let o=e.documentKey??"docId",r=Ze(n,{ref:e.repo.ref,path:e.path,isGroup:!!e.isGroup,filters:[{field:o,op:"==",value:t}]});return r.type==="index"?{type:"warning",message:"Loading this document requires a composite index that does not exist yet.",...r.indexUrl?{action:{href:r.indexUrl,label:"Create Index \u2192",external:true}}:{}}:{type:"error",message:r.message}}function z(e,t,n=200){e.status(n).set("Content-Type","text/html; charset=utf-8").send(t);}function St(e,t){e.status(302).set("Location",t).send("");}function kt(e,t){let n=t.shape,o={};for(let[r,i]of Object.entries(n)){let l=Ct(i);if(l==="ZodObject"){if(e[r+"__isnull"]==="1"){o[r]=null;continue}let y={},g=false;for(let[x,v]of Object.entries(e))x.startsWith(`${r}.`)&&(y[x.slice(r.length+1)]=v,g=true);if(g){let x=i;for(;;){let v=H(x);if(v==="ZodOptional"||v==="ZodNullable"||v==="ZodDefault")x=G(x);else break}o[r]=kt(y,x);continue}let C=e[r],h=Array.isArray(C)?C[C.length-1]:C;if(h)try{o[r]=JSON.parse(h);}catch{o[r]=h;}continue}let u=e[r],c=Array.isArray(u)?u[u.length-1]:u;if(e[r+"__isnull"]==="1"){o[r]=null;continue}if(c===void 0||c===""){l==="ZodBoolean"&&(o[r]=false);continue}switch(l){case "ZodBoolean":c==="__null__"?o[r]=null:o[r]=c==="true"||c==="on"||c==="1";break;case "ZodNumber":case "ZodBigInt":o[r]=Number(c);break;case "ZodDate":o[r]=new Date(c);break;case "ZodArray":try{o[r]=JSON.parse(c);}catch{o[r]=c;}break;default:if(c.startsWith("{")||c.startsWith("["))try{o[r]=JSON.parse(c);break}catch{}o[r]=c;}}return o}function mn(e){let t=null;if(e instanceof Date)t=e;else if(typeof e=="object"&&e!==null&&typeof e.toDate=="function")t=e.toDate();else if(typeof e=="object"&&e!==null&&"_seconds"in e&&"_nanoseconds"in e)t=new Date(e._seconds*1e3+Math.floor(e._nanoseconds/1e6));else if(typeof e=="string"||typeof e=="number"){let o=new Date(e);isNaN(o.getTime())||(t=o);}if(!t||isNaN(t.getTime()))return null;let n=o=>String(o).padStart(2,"0");return `${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())}T${n(t.getHours())}:${n(t.getMinutes())}`}function Ct(e){let t=e;for(;;){let n=H(t);if(n==="ZodOptional"||n==="ZodNullable"||n==="ZodDefault")t=G(t);else return n}}function Zr(e){let t=e;for(;;){let n=H(t);if(n==="ZodOptional"||n==="ZodNullable"||n==="ZodDefault")t=G(t);else return t}}function gn(e){let t=e;for(;;){let n=H(t);if(n==="ZodOptional"||n==="ZodNullable")return true;if(n==="ZodDefault"){t=G(t);continue}return false}}function hn(e){let t=Zr(e),n=H(t);if(n==="ZodEnum"){let o=_e(t);return o.length>0?o:void 0}if(n==="ZodNativeEnum"){let o=De(t),r=Object.values(o).filter(i=>typeof i=="string");return r.length>0?r:void 0}if(n==="ZodLiteral"){let o=Ge(t);return typeof o=="string"?[o]:void 0}}function bn(e,t,n=""){let o={};for(let r of Object.keys(t.shape)){let i=n?`${n}.${r}`:r,l=e[r];if(l===null){o[i]="__null__";continue}if(l===void 0)continue;let u=t.shape[r];for(;;){let y=H(u);if(y==="ZodOptional"||y==="ZodNullable"||y==="ZodDefault")u=G(u);else break}let c=H(u);if(c==="ZodObject"&&typeof l=="object"&&l!==null&&!Array.isArray(l)){let y=bn(l,u,i);Object.assign(o,y);}else if(c==="ZodDate"){let y=mn(l);y!==null&&(o[i]=y);}else if(typeof l=="object"&&l!==null&&!Array.isArray(l)&&("_seconds"in l||typeof l.toDate=="function")){let y=mn(l);o[i]=y??JSON.stringify(l,null,2);}else typeof l=="object"?o[i]=JSON.stringify(l,null,2):o[i]=String(l);}return o}function Rt(e,t){return e.map(n=>({...n,defaultValue:t[n.name]??n.defaultValue,nested:n.nested?Rt(n.nested,t):void 0}))}function Br(e,t){let n=new Set(["==","!=","<","<=",">",">=","in","not-in","array-contains","array-contains-any"]),o=[];for(let[r,i]of Object.entries(e)){if(!r.startsWith("fv_"))continue;let l=r.slice(3);if(!t.has(l))continue;let u=(i??"").trim();if(!u)continue;let c=e[`fo_${l}`]??"==",y=n.has(c)?c:"==";o.push({field:l,op:y,value:u});}return o}function yn(e){let t="__null__",n=o=>o===t?null:o==="true"?true:o==="false"?false:o!==""&&!isNaN(Number(o))?Number(o):o;return e.map(o=>{if(o.op==="array-contains-any"||o.op==="in"||o.op==="not-in"){let r=o.value.split(",").map(i=>i.trim()).filter(i=>i!==""&&i!==t).map(i=>n(i));return [o.field,o.op,r]}return [o.field,o.op,n(o.value)]})}function vn(e,t,n=""){let o=[];for(let r of e){let i=n?`${n}.${r}`:r,l=t.shape[r];if(!l){o.push({name:i,zodType:"ZodString"});continue}let u=Ct(l);if(u==="ZodObject"){let c=l;for(;;){let g=H(c);if(g==="ZodOptional"||g==="ZodNullable"||g==="ZodDefault")c=G(c);else break}let y=te(c);o.push(...vn(Object.keys(y),c,i));}else o.push({name:i,zodType:u,nullable:gn(l),enumValues:hn(l)});}return o}function Mr(e,t){let n=t.split("."),o=e;for(let r of n){for(;;){let l=H(o);if(l==="ZodOptional"||l==="ZodNullable"||l==="ZodDefault")o=G(o);else break}let i=te(o);if(!(r in i))return null;o=i[r];}return o}function Re(e,t){if(!t||t.length===0)return e;let n=[],o=new Map;for(let i of t){let l=i.indexOf(".");if(l===-1)n.push(i);else {let u=i.slice(0,l),c=i.slice(l+1);o.has(u)||o.set(u,[]),o.get(u).push(c);}}let r={};for(let i of n)i in e.shape&&(r[i]=e.shape[i]);for(let[i,l]of o){if(!(i in e.shape))continue;let u=e.shape[i];for(;;){let c=H(u);if(c==="ZodOptional"||c==="ZodNullable"||c==="ZodDefault")u=G(u);else break}if(H(u)!=="ZodObject"){r[i]=e.shape[i];continue}r[i]=Re(u,l);}return z$1.object(r)}function ue(e,t){return ee(e,t)}function xn(e,t){let n=(p,a)=>{let f=ue(p,t),s=Object.values(e).map(d=>({name:d.name,path:d.path}));z(a,vt(s,f));},o=async(p,a)=>{let f=p.params.repoName;if(!f){z(a,"Bad request",400);return}let s=e[f];if(!s){z(a,"Repository not found",404);return}let d=s.pageSize??25,m=p.query??{},k=m.cursor,w=m.dir==="prev"?"prev":"next",$=m.ob??"",R=m.od==="desc"?"desc":"asc",T=$?{field:$,dir:R}:void 0,A=parseInt(m.ps??""),E=Number.isFinite(A)&&A>0?Math.min(A,200):d,O=s.listColumns??Object.keys(s.schema.shape),N=s.documentKey??"docId",j=[N,...O.filter(W=>W!==N)],I=s.filterableFields?(()=>{let W=[];for(let de of s.filterableFields)(de.includes(".")||O.includes(de))&&W.push(de);return W})():O,P=(()=>{let W=[];for(let de of I)if(de.includes(".")){let $e=Mr(s.schema,de);W.push({name:de,zodType:$e?Ct($e):"ZodString",nullable:$e?gn($e):false,enumValues:$e?hn($e):void 0});}else W.push(...vn([de],s.schema));return W})(),q=new Set(P.map(W=>W.name)),pe=Br(m,q),oe=yn(pe),K;if(k)try{let W=s.repo.ref;typeof W.doc=="function"&&(K=await W.doc(k).get());}catch{}let[U,Ke]=await Promise.all([s.repo.query.paginate({pageSize:E,cursor:K,direction:w,...oe.length>0?{where:oe}:{},...T?{orderBy:[{field:T.field,direction:T.dir}]}:{}}).catch(W=>({queryError:Ze(W,{ref:s.repo.ref,path:s.path,isGroup:!!s.isGroup,filters:pe,sort:T})})),s.repo.aggregate.count(oe.length>0?{where:oe}:{}).catch(()=>{})]),Ce="queryError"in U,jn=Ce?[]:U.data,Fn=Ce?"":U.nextCursor?.id??"",zn=Ce?"":U.prevCursor?.id??"",Zn=Ce?U.queryError:void 0,Bn=ue(p,t);z(a,xt(s.name,jn,j,Bn,{hasPrev:Ce?false:U.hasPrevPage,hasNext:Ce?false:U.hasNextPage,prevCursor:zn,nextCursor:Fn},void 0,P,pe,s.allowDelete??false,s.relationalMeta,T,E,Zn,s.isGroup,Ke,s.mutableFields,s.schema,s.historyEnabled));},r=(p,a)=>{let f=p.params.repoName;if(!f){z(a,"Bad request",400);return}let s=e[f];if(!s){z(a,"Repository not found",404);return}let d=ue(p,t),m=Re(s.schema,s.createFields),k=le(m),w=`${d}/${s.name}/create`,$=ye(k,w,"POST","Create document");z(a,ve(s.name,$,"create",null,d));},i=async(p,a)=>{let f=p.params.repoName;if(!f){z(a,"Bad request",400);return}let s=e[f];if(!s){z(a,"Repository not found",404);return}let d=ue(p,t),m=p.body??{},k=kt(m,s.schema),w=Re(s.schema,s.createFields),$=w.safeParse(k);if(!$.success){let R=le(w),T=`${d}/${s.name}/create`,A=ye(R,T,"POST","Create document"),E=$.error.issues.map(O=>`${O.path.join(".")}: ${O.message}`).join(", ");z(a,ve(s.name,A,"create",null,d,{type:"error",message:`Validation error: ${E}`}),422);return}try{if(s.isGroup&&s.parentKeys&&s.parentKeys.length>0){let R={...$.data};s.createdKey&&(R[s.createdKey]=new Date);let T=s.parentKeys.filter(N=>!R[N]);if(T.length>0)throw new Error(`Missing parent key(s) for subcollection create: ${T.join(", ")}`);let A=s.parentKeys.map(N=>R[N]),E=s.documentKey??"docId",O=R[E]||zr();await s.repo.set(...A,O,R);}else await s.repo.create($.data);St(a,`${d}/${s.name}?flash=created`);}catch(R){let T=Re(s.schema,s.createFields),A=le(T),E=`${d}/${s.name}/create`,O=ye(A,E,"POST","Create document");z(a,ve(s.name,O,"create",null,d,{type:"error",message:`Save error: ${R.message}`}),500);}},l=async(p,a)=>{let f=p.params.repoName,s=p.params.id;if(!f||!s){z(a,"Bad request",400);return}let d=e[f];if(!d){z(a,"Repository not found",404);return}let m=ue(p,t),k=null;try{k=await Pe(d,s);}catch(E){let O=wt(d,s,E),N=Se(E)?424:500;z(a,He("",{title:`Edit ${d.name} / ${s}`,basePath:m,breadcrumb:[{label:"Repositories",href:m},{label:d.name,href:`${m}/${d.name}`},{label:`Edit ${s}`}],flash:O}),N);return}if(!k){z(a,"Document not found",404);return}let w=bn(k,d.schema),$=Re(d.schema,d.mutableFields),R=Rt(le($),w),T=`${m}/${d.name}/${encodeURIComponent(s)}/edit`,A=ye(R,T,"POST","Save changes");z(a,ve(d.name,A,"edit",s,m));},u=async(p,a)=>{let f=p.params.repoName,s=p.params.id;if(!f||!s){z(a,"Bad request",400);return}let d=e[f];if(!d){z(a,"Repository not found",404);return}let m=ue(p,t),k=p.body??{},w=kt(k,d.schema),$=Re(d.schema,d.mutableFields),T=$.partial().safeParse(w);if(!T.success){let A=Object.fromEntries(Object.entries(k).map(([I,P])=>[I,Array.isArray(P)?P.join(","):P??""])),E=Rt(le($),A),O=`${m}/${d.name}/${encodeURIComponent(s)}/edit`,N=ye(E,O,"POST","Save changes"),j=T.error.issues.map(I=>`${I.path.join(".")}: ${I.message}`).join(", ");z(a,ve(d.name,N,"edit",s,m,{type:"error",message:`Validation error: ${j}`}),422);return}try{let A=await Pe(d,s),E=(A&&et(A,d.pathKey))??[s];await d.repo.update(...E,T.data),St(a,`${m}/${d.name}?flash=updated`);}catch(A){let E=Re(d.schema,d.mutableFields),O=le(E),N=`${m}/${d.name}/${encodeURIComponent(s)}/edit`,j=ye(O,N,"POST","Save changes"),I=Se(A)?wt(d,s,A):{type:"error",message:`Save error: ${A.message}`},P=Se(A)?424:500;z(a,ve(d.name,j,"edit",s,m,I),P);}},c=async(p,a)=>{let f=p.params.repoName,s=p.params.id;if(!f||!s){z(a,"Bad request",400);return}let d=e[f];if(!d){z(a,"Repository not found",404);return}if(!d.allowDelete){z(a,"Delete is not allowed for this repository",403);return}let m=ue(p,t);try{let k=await Pe(d,s),w=(k&&et(k,d.pathKey))??[s];await d.repo.delete(...w),St(a,`${m}/${d.name}?flash=deleted`);}catch(k){let w=Se(k)?wt(d,s,k):{type:"error",message:`Delete error: ${k.message}`},$=Se(k)?424:500;z(a,He("",{title:`Delete ${d.name} / ${s}`,basePath:m,breadcrumb:[{label:"Repositories",href:m},{label:d.name,href:`${m}/${d.name}`},{label:`Delete ${s}`}],flash:w}),$);}},y=async(p,a)=>{let f=p.params.repoName;if(!f){z(a,"Bad request",400);return}let s=e[f];if(!s){z(a,"Repository not found",404);return}let d=ue(p,t),m=p.query,k=m?.type==="many"?"many":"one",w=Math.max(1,Math.min(100,Number(m?.ps??25)||25)),$=s.listColumns??Object.keys(te(s.schema)),{PanelOne:R,PanelMany:T}=await Promise.resolve().then(()=>(pt(),cn)),{renderToString:A}=await import('hono/jsx/dom/server');if(k==="one"){let P=String(m?.id??"");if(!P){z(a,"<div class='p-6 text-error'>Missing id parameter.</div>",400);return}try{let q=await Pe(s,P),pe=A(R({doc:q,repoName:s.name,basePath:d,schema:s.schema,columns:$}));z(a,pe);}catch(q){z(a,`<div class='p-6 text-error text-sm'>Error: ${q.message}</div>`,500);}return}let E=String(m?.fk??""),O=String(m?.fv??"");if(!E||!O){z(a,"<div class='p-6 text-error'>Missing fk/fv parameters.</div>",400);return}let N=m?.cursor??"",j=m?.dir==="prev"?"prev":"next",I;if(N)try{let P=s.repo.ref;typeof P.doc=="function"&&(I=await P.doc(N).get());}catch{}try{let P=await s.repo.query.paginate({pageSize:w,cursor:I,direction:j,where:[[E,"==",qr(O)]]}),q=A(T({docs:P.data,repoName:s.name,basePath:d,fk:E,fv:O,columns:$,schema:s.schema,pagination:{hasPrev:P.hasPrevPage,hasNext:P.hasNextPage,prevCursor:P.prevCursor?.id??"",nextCursor:P.nextCursor?.id??"",pageSize:w}}));z(a,q);}catch(P){z(a,`<div class='p-6 text-error text-sm'>Error: ${P.message}</div>`,500);}},g=async(p,a)=>{let f=[];for(let s of a){let d;if(p.isGroup||p.parentKeys?.length){let m=await Pe(p,s);d=m?et(m,p.pathKey):void 0;}d||(d=[s]);try{let m=p.repo.documentRef(...d);m&&f.push(m);}catch{}}return f},C=async(p,a)=>{let f=yn(a),s=p.documentKey??"docId",d=[],m;for(;;){let k=await p.repo.query.paginate({pageSize:500,cursor:m,direction:"next",...f.length>0?{where:f}:{}});for(let w of k.data){let $=String(w[s]??w.id??"");$&&d.push($);}if(!k.hasNextPage||!k.nextCursor)break;m=k.nextCursor;}return d},h=async(p,a)=>{let f=p.params.repoName;if(!f){Y(a,{error:"Bad request"},400);return}let s=e[f];if(!s){Y(a,{error:"Repository not found"},404);return}if(!s.allowDelete){Y(a,{error:"Delete is not allowed for this repository"},403);return}let d=p.body??{};try{let m=await v(s,d);if(m.length===0){Y(a,{deleted:0});return}let k=await g(s,m);for(let w=0;w<k.length;w+=500)await s.repo.bulk.delete(k.slice(w,w+500));Y(a,{deleted:k.length});}catch(m){Y(a,{error:m.message},500);}},x=async(p,a)=>{let f=p.params.repoName;if(!f){Y(a,{error:"Bad request"},400);return}let s=e[f];if(!s){Y(a,{error:"Repository not found"},404);return}let d=p.body??{},m=String(d.field??"");if(!m){Y(a,{error:"Missing 'field'"},400);return}if(!s.mutableFields||!s.mutableFields.includes(m)){Y(a,{error:`Field '${m}' is not bulk-updatable`},403);return}let k=s.schema.shape?.[m],w=d.value;if(k){let $=k.safeParse(d.value);if(!$.success){Y(a,{error:`Invalid value for '${m}': ${$.error.message}`},400);return}w=$.data;}try{let $=await v(s,d);if($.length===0){Y(a,{updated:0});return}let T=(await g(s,$)).map(A=>({docRef:A,data:{[m]:w}}));for(let A=0;A<T.length;A+=500)await s.repo.bulk.update(T.slice(A,A+500));Y(a,{updated:T.length});}catch($){Y(a,{error:$.message},500);}};async function v(p,a){if(a.selectAll){let f=b(a.filters,p);return await C(p,f)}return Array.isArray(a.ids)?a.ids.filter(f=>typeof f=="string"&&!!f):[]}function b(p,a){if(!Array.isArray(p))return [];let f=new Set((a.filterableFields??Object.keys(te(a.schema))).map(m=>String(m))),s=new Set(["==","!=","<","<=",">",">=","in","not-in","array-contains","array-contains-any"]),d=[];for(let m of p)m&&typeof m=="object"&&typeof m.field=="string"&&f.has(m.field)&&typeof m.value=="string"&&s.has(String(m.op))&&d.push({field:m.field,op:m.op,value:m.value});return d}return {handleDashboard:n,handleList:o,handleCreateForm:r,handleCreateSubmit:i,handleEditForm:l,handleEditSubmit:u,handleDelete:c,handlePanel:y,handleBulkDelete:h,handleBulkUpdate:x,handleHistory:async(p,a)=>{let f=p.params.repoName,s=p.params.id;if(!f||!s){z(a,"Bad request",400);return}let d=e[f];if(!d){z(a,"Repository not found",404);return}if(!d.historyEnabled||!d.repo.history){z(a,"History not enabled for this repository",404);return}let m=ue(p,t),k=d.historySubcollection??"history",w=[s];try{let P=await Pe(d,s),q=P?et(P,d.pathKey):void 0;q&&q.length>0&&(w=q);}catch{}let $=parseInt(String(p.query?.limit??"")),R=Number.isFinite($)&&$>0?Math.min($,500):100,T=[],A;try{T=await d.repo.history.list(...w,{limit:R});}catch(P){A=P.message;}let E=P=>String(P??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""),O=P=>{if(P===void 0)return '<span class="opacity-40">undefined</span>';if(P===null)return '<span class="opacity-40">null</span>';if(typeof P=="object")try{return `<code class="text-xs">${E(JSON.stringify(P))}</code>`}catch{return E(String(P))}return E(String(P))},N=P=>P?typeof P.toDate=="function"?P.toDate().toISOString():P instanceof Date?P.toISOString():E(String(P)):"",j=P=>`<span class="badge badge-sm ${P==="create"?"badge-success":P==="delete"?"badge-error":"badge-info"}">${E(P)}</span>`,I="";if(I+='<div class="flex items-center justify-between mb-4">',I+=`<a href="${m}/${d.name}/${encodeURIComponent(s)}/edit" class="btn btn-sm btn-outline">\u2190 Back to edit</a>`,I+=`<a href="${m}/${d.name}" class="btn btn-sm btn-outline">\u2190 Back to list</a>`,I+="</div>",I+=`<p class="text-sm text-base-content/60 mb-4">Subcollection: <code>${E(k)}</code> \xB7 Showing up to ${R} entries.</p>`,A)I+=`<div class="alert alert-error mb-4">${E(A)}</div>`;else if(T.length===0)I+='<div class="alert">No history entries found.</div>';else {I+='<div class="overflow-x-auto"><table class="table table-zebra table-sm">',I+="<thead><tr><th>When</th><th>Op</th><th>User</th><th>Reason / Comment</th><th>Changes</th></tr></thead><tbody>";for(let P of T){let q=P.meta??{},pe=[q.reason,q.comment].filter(U=>U!=null&&U!=="").map(U=>E(String(U))).join(" \u2014 "),oe="",K=Object.keys(P.changes??{});K.length===0?oe='<span class="opacity-40">\u2014</span>':oe='<ul class="space-y-1">'+K.map(U=>{let Ke=P.changes[U];return `<li><strong>${E(U)}</strong>: ${O(Ke.oldValue)} \u2192 ${O(Ke.newValue)}</li>`}).join("")+"</ul>",I+="<tr>",I+=`<td class="whitespace-nowrap text-xs font-mono">${E(N(P.historySetAt))}</td>`,I+=`<td>${j(P.operation??"update")}</td>`,I+=`<td class="text-xs">${E(q.userEmail??q.userId??"")}</td>`,I+=`<td class="text-xs">${pe}</td>`,I+=`<td>${oe}</td>`,I+="</tr>";}I+="</tbody></table></div>";}z(a,He(I,{title:`History \u2014 ${d.name} / ${s}`,basePath:m,breadcrumb:[{label:"Repositories",href:m},{label:d.name,href:`${m}/${d.name}`},{label:`History ${s}`}]}));}}}function Y(e,t,n=200){e.status(n).set("Content-Type","application/json; charset=utf-8").send(JSON.stringify(t));}function qr(e){return e==="true"?true:e==="false"?false:e!==""&&!isNaN(Number(e))?Number(e):e}async function Hr(e){return typeof e.rawBody=="string"?e.rawBody:Buffer.isBuffer(e.rawBody)?e.rawBody.toString("utf8"):""}function Lr(e){let t={};if(!e)return t;for(let n of e.split("&")){let o=n.indexOf("=");if(o===-1)continue;let r=decodeURIComponent(n.slice(0,o).replace(/\+/g," ")),i=decodeURIComponent(n.slice(o+1).replace(/\+/g," ")),l=t[r];l===void 0?t[r]=i:Array.isArray(l)?l.push(i):t[r]=[l,i];}return t}function wn(e){let{basePath:t="/",repos:n,parseBody:o=true,auth:r,middleware:i=[],httpsOptions:l}=e,u=t==="/"?"":t.replace(/\/$/,""),c={};for(let[h,x]of Object.entries(n)){let v=x.schema??x.repo.schema??null;if(!v)throw new Error(`[createAdminServer] Repository "${h}" has no Zod schema. Either use createRepositoryConfig(schema)(config) or pass schema: explicitly.`);let b,S,p;if(x.fieldsConfig){let s=x.fieldsConfig;b=[],S=[],p=[];for(let[d,m]of Object.entries(s))for(let k of m)k==="filterable"?b.push(d):k==="mutable"?S.push(d):k==="create"&&p.push(d);b.length===0&&(b=void 0),S.length===0&&(S=void 0),p.length===0&&(p=void 0);}let a=(()=>{let s=x.repo._parentKeys;return s&&s.length>0?s:void 0})();if(a&&p)for(let s of a)p.includes(s)||p.push(s);let f={name:h,path:x.path,repo:x.repo,schema:v,documentKey:x.documentKey??"docId",pathKey:x.repo._pathKey??void 0,isGroup:!!x.repo._isGroup,parentKeys:a,createdKey:x.repo._createdKey??void 0,listColumns:x.listColumns,pageSize:x.pageSize,filterableFields:b,mutableFields:S,createFields:p,allowDelete:x.allowDelete??false,historyEnabled:!!x.repo.history,historySubcollection:(x.repo.history&&x.repo._historySubcollection)??void 0,relationalMeta:(()=>{if(!x.relationalFields||x.relationalFields.length===0)return;let s=x.repo.relationalKeys??{},d=[];for(let m of x.relationalFields){let k=s[m.key];k&&d.push({key:m.key,column:m.column,targetRepo:String(k.repo),targetKey:String(k.key),type:k.type});}return d.length>0?d:void 0})()};c[h]=f;}let y=xn(c,u),g=new se;if(o&&g.use(async(h,x,v)=>{let b=h,S=String(b.headers?.["content-type"]??"");if(S.includes("application/x-www-form-urlencoded")){let p=await Hr(b);h.body=Lr(p);}else if(S.includes("application/json")&&typeof b.body=="string")try{h.body=JSON.parse(b.body);}catch{}await v();}),r)if(fe(r)){for(let h of r.routes){let x=`${u}${h.path}`;h.method==="GET"?g.get(x,h.handler):g.post(x,h.handler);}g.use(r.middleware);}else if(typeof r=="function")g.use(r);else {let h=r.realm??"Admin",x="Basic "+Buffer.from(`${r.username}:${r.password}`).toString("base64");g.use((v,b,S)=>{if((v.headers?.authorization??"")!==x){b.status(401).set("WWW-Authenticate",`Basic realm="${h}"`).set("Content-Type","text/plain").send("Unauthorized");return}S();});}for(let h of i)g.use(h);g.get(`${u}/`,y.handleDashboard),g.get(`${u}`,y.handleDashboard),g.get(`${u}/:repoName/_panel`,y.handlePanel),g.post(`${u}/:repoName/_bulk/delete`,y.handleBulkDelete),g.post(`${u}/:repoName/_bulk/update`,y.handleBulkUpdate),g.get(`${u}/:repoName`,y.handleList),g.get(`${u}/:repoName/create`,y.handleCreateForm),g.post(`${u}/:repoName/create`,y.handleCreateSubmit),g.get(`${u}/:repoName/:id/edit`,y.handleEditForm),g.post(`${u}/:repoName/:id/edit`,y.handleEditSubmit),g.get(`${u}/:repoName/:id/history`,y.handleHistory),g.post(`${u}/:repoName/:id/delete`,y.handleDelete);let C=async(h,x)=>{await g.handle(h,x);};return l&&(C.httpsOptions=l),C}var kn="preserve";function Rn(){return kn}function Ur(e){return typeof e=="object"&&e!==null&&typeof e._seconds=="number"&&typeof e._nanoseconds=="number"}function Cn(e){if(e==null)return null;if(e instanceof Date)return Number.isNaN(e.getTime())?null:e;if(e instanceof Timestamp)return e.toDate();if(Ur(e))return new Date(e._seconds*1e3+Math.floor(e._nanoseconds/1e6));if(typeof e=="string"){let t=new Date(e);return Number.isNaN(t.getTime())?null:t}if(typeof e=="number"){let t=new Date(e);return Number.isNaN(t.getTime())?null:t}return null}function $n(e){return e}function Tt(e,t,n=200){let o=$n(t);e.status(n).set("Content-Type","application/json; charset=utf-8").send(JSON.stringify(o));}function Ie(e,t,n,o=200){Tt(e,{success:true,data:t,meta:n},o);}function L(e,t,n=400){Tt(e,{success:false,error:t},n);}function At(e,t,n,o,r){let i=Ze(t,n),l=i.type==="index",u=l?424:500,y={success:false,error:l?i.message:r&&t instanceof Error?t.message:o};l&&(y.errorType="index",i.indexUrl&&(y.indexUrl=i.indexUrl)),Tt(e,y,u);}var An="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";function Vr(){let e="";for(let t=0;t<20;t++)e+=An.charAt(Math.floor(Math.random()*An.length));return e}function Ne(e){let t=e._def??e.def;if(!t)return e;let n=t.typeName??t.type;if(n==="ZodDate"||n==="date")return z$1.preprocess(o=>Cn(o)??o,e);if(n==="ZodObject"||n==="object"){let o=e.shape,r={};for(let[i,l]of Object.entries(o))r[i]=Ne(l);return z$1.object(r)}if(n==="ZodArray"||n==="array"){let o=t.element??t.type;if(o)return z$1.array(Ne(o))}if(n==="ZodOptional"||n==="optional"){let o=t.innerType;if(o)return Ne(o).optional()}if(n==="ZodNullable"||n==="nullable"){let o=t.innerType;if(o)return Ne(o).nullable()}if(n==="ZodDefault"||n==="default"){let o=t.innerType,r=t.defaultValue;if(o){let i=Ne(o);return typeof r=="function"?i.default(r()):i.default(r)}}return e}function Gr(e,t,n=[]){let o=e.shape,r={},i=t&&t.length>0?t:Object.keys(o);for(let l of i){if(n.includes(l))continue;let u=l.split(".")[0];u&&o[u]&&(r[u]=o[u]);}return z$1.object(r)}function Tn(e,t,n,o=false,r=[]){try{let i=Gr(e,n,r),l=o?i.partial():i;return {success:!0,data:(Rn()==="normalize"?Ne(l):l).parse(t)}}catch(i){return i instanceof z$1.ZodError?{success:false,error:`Validation failed: ${i.issues.map(u=>`${u.path.join(".")}: ${u.message}`).join(", ")}`}:{success:false,error:"Validation failed"}}}function Jr(e,t){let n=[],o=t?new Set(t):null,r={eq:"==",ne:"!=",lt:"<",lte:"<=",gt:">",gte:">=",in:"in",nin:"not-in",contains:"array-contains",containsAny:"array-contains-any"};for(let[i,l]of Object.entries(e)){if(l===void 0||["cursor","limit","pageSize","orderBy","orderDir","select"].includes(i))continue;let u=Array.isArray(l)?l[0]:l;if(u===void 0||u==="")continue;let c=i.match(/^(\w+)__(\w+)$/),y,g="==";if(c&&c[1]&&c[2]){y=c[1];let h=c[2];if(r[h])g=r[h];else continue}else if(!c)y=i;else continue;if(o&&!o.has(y))continue;let C=u;g==="in"||g==="not-in"||g==="array-contains-any"?C=u.split(",").map(h=>On(h.trim())):C=On(u),n.push({field:y,op:g,value:C});}return n}function On(e){if(e==="true")return true;if(e==="false")return false;if(e==="null")return null;let t=Number(e);return !isNaN(t)&&e!==""?t:e}function tt(e){return e?{docId:e.id}:null}async function En(e,t){if(!t||typeof t!="object")return;let n=t.docId;if(typeof n=="string")try{let o=e.repo.ref;if(typeof o.doc!="function")return;let r=await o.doc(n).get();return r.exists?r:void 0}catch{return}}function Pn(e,t,n,o=false){async function r(p,a,f,s){if(!o)return true;let d=a.rules?.[f];if(!d)return L(p,`Operation "${f}" is not allowed for this repository`,403),false;try{return await d(s)?!0:(L(p,"Forbidden",403),!1)}catch(m){let k=n&&m instanceof Error?m.message:"Forbidden";return L(p,k,403),false}}async function i(p,a,f,s){if(!o)return s;let d=p.rules?.filter;if(!d)return s;let m=[];for(let k of s)try{await d({user:a,doc:k,params:f})&&m.push(k);}catch{}return m}function l(p){return p?.user??null}function u(p,a){return !p||!e[p]?(L(a,`Repository "${p}" not found`,404),null):e[p]}function c(p,a){if(!a)return;let f=p[a];if(typeof f!="string"||!f)return;let s=f.split("/").filter(Boolean),d=[];for(let m=1;m<s.length;m+=2)d.push(s[m]);return d.length>0?d:void 0}async function y(p,a){let f=`by${p.documentKey.charAt(0).toUpperCase()}${p.documentKey.slice(1)}`,s=p.repo.get[f];if(typeof s=="function")try{let m=await s(a);if(m)return m}catch{}return (await p.repo.query.by({where:[[p.documentKey,"==",a]],limit:1}))[0]??null}async function g(p,a){let f=p.params||{},s=u(f.repoName,a);if(!s)return;let d=l(p);if(!await r(a,s,"list",{user:d,query:p.query??{},params:f}))return;let m=[],k;try{let w=p.query??{},$=Math.min(Number(w.pageSize)||s.pageSize,100),R=w.cursor,T=w.direction?.toLowerCase()==="prev"?"prev":"next",A=w.orderBy,E=w.orderDir?.toLowerCase()==="desc"?"desc":"asc",O=w.select,N=O?O.split(",").map(K=>K.trim()):void 0,j;s.allowedIncludes&&w.includes&&(j=(typeof w.includes=="string"?w.includes.split(",").map(U=>U.trim()):Array.isArray(w.includes)?w.includes:[]).filter(U=>typeof U=="string"&&s.allowedIncludes.includes(U)),j?.length===0&&(j=void 0));let I=Jr(w,s.filterableFields);m=I.map(K=>({field:K.field,op:K.op,value:String(K.value??"")})),A&&(k={field:A,dir:E});let P={pageSize:$,direction:T};if(R)try{let K=typeof R=="string"?JSON.parse(R):R;P.cursor=await En(s,K);}catch{}A&&(P.orderBy=[{field:A,direction:E}]),I.length>0&&(P.where=I.map(K=>[K.field,K.op,K.value])),N&&(P.select=N),j&&(P.include=j);let q=await s.repo.query.paginate(P),oe={items:await i(s,l(p),f,q.data),hasNextPage:q.hasNextPage,hasPrevPage:q.hasPrevPage,nextCursor:tt(q.nextCursor),prevCursor:tt(q.prevCursor)};Ie(a,oe,{pageSize:$,hasMore:q.hasNextPage});}catch(w){At(a,w,{ref:s.repo.ref,path:s.path,isGroup:!!s.isGroup,filters:m,sort:k},"Failed to fetch documents",n);}}async function C(p,a){let f=p.params||{},s=u(f.repoName,a);if(!s)return;let d=l(p);if(!await r(a,s,"list",{user:d,query:p.body??{},params:f}))return;let m=[],k;try{let w=p.body??{},$=Math.min(w.pageSize||s.pageSize,100),R=w.direction==="prev"?"prev":"next";w.where&&(m=w.where.map(N=>({field:String(N[0]),op:N[1],value:String(N[2]??"")}))),w.orderBy&&w.orderBy[0]&&(k={field:w.orderBy[0].field,dir:w.orderBy[0].direction==="desc"?"desc":"asc"});let T={pageSize:$,direction:R};if(w.cursor)try{let N=typeof w.cursor=="string"?JSON.parse(w.cursor):w.cursor;T.cursor=await En(s,N);}catch{}if(s.allowedIncludes&&w.includes&&w.includes.length>0){let N=w.includes.filter(j=>typeof j=="string"?s.allowedIncludes.includes(j):typeof j=="object"&&j!==null&&"relation"in j&&typeof j.relation=="string"?s.allowedIncludes.includes(j.relation):!1);N.length>0&&(T.include=N);}if(w.where&&w.where.length>0){if(s.filterableFields){let N=new Set(s.filterableFields),j=w.where.filter(I=>!N.has(I[0]));if(j.length>0){L(a,`Fields not filterable: ${j.map(I=>I[0]).join(", ")}`,400);return}}T.where=w.where;}if(w.orWhere&&w.orWhere.length>0){if(s.filterableFields){let N=new Set(s.filterableFields),j=w.orWhere.filter(I=>!N.has(I[0]));if(j.length>0){L(a,`Fields not filterable: ${j.map(I=>I[0]).join(", ")}`,400);return}}T.orWhere=w.orWhere;}if(w.orWhereGroups&&w.orWhereGroups.length>0){if(s.filterableFields){let N=new Set(s.filterableFields);for(let j of w.orWhereGroups){let I=j.filter(P=>!N.has(P[0]));if(I.length>0){L(a,`Fields not filterable: ${I.map(P=>P[0]).join(", ")}`,400);return}}}T.orWhereGroups=w.orWhereGroups;}w.orderBy&&w.orderBy.length>0&&(T.orderBy=w.orderBy),w.select&&w.select.length>0&&(T.select=w.select);let A=await s.repo.query.paginate(T),O={items:await i(s,l(p),f,A.data),hasNextPage:A.hasNextPage,hasPrevPage:A.hasPrevPage,nextCursor:tt(A.nextCursor),prevCursor:tt(A.prevCursor)};Ie(a,O,{pageSize:$,hasMore:A.hasNextPage});}catch(w){At(a,w,{ref:s.repo.ref,path:s.path,isGroup:!!s.isGroup,filters:m,sort:k},"Failed to query documents",n);}}async function h(p,a){let f=p.params||{},s=u(f.repoName,a);if(!s)return;let d=f.id;if(!d){L(a,"Document ID required",400);return}try{let m=await y(s,d);if(!m){L(a,"Document not found",404);return}let k=l(p);if(!await r(a,s,"get",{user:k,doc:m,params:f}))return;if(o&&s.rules?.filter)try{if(!await s.rules.filter({user:k,doc:m,params:f})){L(a,"Document not found",404);return}}catch{L(a,"Document not found",404);return}Ie(a,m);}catch(m){At(a,m,{ref:s.repo.ref,path:s.path,isGroup:!!s.isGroup,filters:[{field:s.documentKey,op:"==",value:d}]},"Failed to fetch document",n);}}async function x(p,a){let f=p.params||{},s=u(f.repoName,a);if(s)try{let d=p.body??{},m=l(p);if(!await r(a,s,"create",{user:m,body:d,params:f}))return;let k=Tn(s.schema,d,s.createFields,!1,s.systemKeys);if(!k.success){L(a,k.error,400);return}if(s.validate){let $=await s.validate(k.data,"create");if($){L(a,$,400);return}}let w;if(s.isGroup&&s.parentKeys&&s.parentKeys.length>0){let $={...k.data};s.createdKey&&($[s.createdKey]=new Date);let R=s.parentKeys.filter(E=>!$[E]);if(R.length>0){L(a,`Missing parent key(s) for subcollection create: ${R.join(", ")}`,400);return}let T=s.parentKeys.map(E=>$[E]),A=$[s.documentKey]||Vr();w=await s.repo.set(...T,A,$);}else w=await s.repo.create(k.data);Ie(a,w,void 0,201);}catch(d){let m=n&&d instanceof Error?d.message:"Failed to create document";L(a,m,500);}}async function v(p,a,f){let s=p.params||{},d=u(s.repoName,a);if(!d)return;let m=s.id;if(!m){L(a,"Document ID required",400);return}try{let k=p.body??{},w=await y(d,m);if(!w){L(a,"Document not found",404);return}let $=l(p);if(!await r(a,d,"update",{user:$,doc:w,body:k,params:s}))return;let R=Tn(d.schema,k,d.mutableFields,f,d.systemKeys);if(!R.success){L(a,R.error,400);return}if(d.validate){let E=await d.validate(R.data,"update");if(E){L(a,E,400);return}}let T=c(w,d.pathKey)??[m],A=await d.repo.update(...T,R.data);Ie(a,A);}catch(k){let w=n&&k instanceof Error?k.message:"Failed to update document";L(a,w,500);}}async function b(p,a){let f=p.params||{},s=u(f.repoName,a);if(!s)return;if(!s.allowDelete){L(a,"Delete not allowed for this repository",403);return}let d=f.id;if(!d){L(a,"Document ID required",400);return}try{let m=await y(s,d);if(!m){L(a,"Document not found",404);return}let k=l(p);if(!await r(a,s,"delete",{user:k,doc:m,params:f}))return;let w=c(m,s.pathKey)??[d];await s.repo.delete(...w),Ie(a,{deleted:!0});}catch(m){let k=n&&m instanceof Error?m.message:"Failed to delete document";L(a,k,500);}}function S(p,a){a.status(204).set("Access-Control-Allow-Methods","GET, POST, PUT, PATCH, DELETE, OPTIONS").set("Access-Control-Allow-Headers","Content-Type, Authorization").set("Access-Control-Max-Age","86400").send("");}return {handleList:g,handleQuery:C,handleGet:h,handleCreate:x,handleUpdate:v,handleDelete:b,handleOptions:S}}function Ot(e){try{return z$1.toJSONSchema(e,{target:"openapi-3.1",unrepresentable:"any",override:t=>{let n=t.zodSchema?._zod?.def;n&&(n.type==="date"?(t.jsonSchema.type="string",t.jsonSchema.format="date-time"):n.type==="bigint"&&(t.jsonSchema.type="string",t.jsonSchema.format="int64"));}})}catch(t){return typeof console<"u"&&console.warn&&console.warn("[generateOpenAPISpec] Failed to convert Zod schema to JSON Schema; falling back to {type:object}.",t),{type:"object"}}}function re(e){return {$ref:`#/components/schemas/${e}`}}function X(e){return {description:e,content:{"application/json":{schema:re("ErrorResponse")}}}}function Ue(e,t){return {description:e,content:{"application/json":{schema:{type:"object",properties:{success:{type:"boolean",enum:[true]},data:t},required:["success","data"]}}}}}function In(e){return {description:"Paginated list of documents",content:{"application/json":{schema:{type:"object",properties:{success:{type:"boolean",enum:[true]},data:{type:"object",properties:{items:{type:"array",items:e},nextCursor:{oneOf:[{type:"object"},{type:"null"}]},prevCursor:{oneOf:[{type:"object"},{type:"null"}]},hasNextPage:{type:"boolean"},hasPrevPage:{type:"boolean"}},required:["items","hasNextPage","hasPrevPage"]},meta:{type:"object",properties:{pageSize:{type:"integer"},hasMore:{type:"boolean"},cursor:{oneOf:[{type:"string"},{type:"null"}]}}}},required:["success","data"]}}}}}function Wr(e){return [{name:"pageSize",in:"query",schema:{type:"integer",default:e.pageSize,maximum:100},description:"Number of items per page"},{name:"cursor",in:"query",schema:{type:"string"},description:"Base64 pagination cursor"},{name:"orderBy",in:"query",schema:{type:"string"},description:"Field name to order by"},{name:"orderDir",in:"query",schema:{type:"string",enum:["asc","desc"]},description:"Order direction"},{name:"select",in:"query",schema:{type:"string"},description:"Comma-separated list of fields to return"}]}function Qr(e){let t=e.filterableFields??Object.keys(e.schema.shape),n=["eq","ne","lt","lte","gt","gte","in","nin","contains"],o=[];for(let r of t){o.push({name:r,in:"query",schema:{type:"string"},description:`Filter by ${r} (equality)`});for(let i of n)o.push({name:`${r}__${i}`,in:"query",schema:{type:"string"},description:`Filter ${r} with operator ${i}`});}return o}function Xr(){return {type:"object",properties:{where:{type:"array",items:{type:"array",items:{},minItems:3,maxItems:3},description:"AND conditions: [field, operator, value][]"},orWhere:{type:"array",items:{type:"array",items:{},minItems:3,maxItems:3},description:"Simple OR conditions (each independently OR'd)"},orWhereGroups:{type:"array",items:{type:"array",items:{type:"array",items:{},minItems:3,maxItems:3}},description:"Advanced OR groups (AND within, OR across groups)"},orderBy:{type:"array",items:{type:"object",properties:{field:{type:"string"},direction:{type:"string",enum:["asc","desc"]}},required:["field"]}},select:{type:"array",items:{type:"string"},description:"Fields to select (projection)"},pageSize:{type:"integer",maximum:100,description:"Number of items per page"},cursor:{oneOf:[{type:"string"},{type:"object"}],description:"Pagination cursor"},direction:{type:"string",enum:["next","prev"],description:"Pagination direction"},includes:{type:"array",items:{oneOf:[{type:"string"},{type:"object",properties:{relation:{type:"string"},select:{type:"array",items:{type:"string"}}},required:["relation"]}]},description:"Relations to include (populate)"}}}}function Yr(e,t,n,o,r){let i={},l=e.name,u=`${t}/${e.name}`,c=`${u}/{${e.documentKey}}`,y={name:e.documentKey,in:"path",required:true,schema:{type:"string"},description:"Unique document identifier"};i[u]={get:{operationId:`list${xe(e.name)}`,summary:`List ${e.name} (paginated)`,tags:[l],parameters:[...Wr(e),...Qr(e)],responses:{200:In(re(n)),500:X("Internal server error")}},post:{operationId:`create${xe(e.name)}`,summary:`Create a ${ce(e.name)}`,tags:[l],requestBody:{required:true,content:{"application/json":{schema:re(o??n)}}},responses:{201:Ue("Document created",re(n)),400:X("Validation error"),500:X("Internal server error")}}},i[`${u}/query`]={post:{operationId:`query${xe(e.name)}`,summary:`Query ${e.name} with advanced filters`,tags:[l],requestBody:{required:true,content:{"application/json":{schema:re("QueryRequestBody")}}},responses:{200:In(re(n)),400:X("Invalid query"),500:X("Internal server error")}}};let g={};return g.get={operationId:`get${xe(ce(e.name))}`,summary:`Get a single ${ce(e.name)}`,tags:[l],parameters:[y],responses:{200:Ue("Document found",re(n)),404:X("Document not found"),500:X("Internal server error")}},g.put={operationId:`update${xe(ce(e.name))}`,summary:`Update a ${ce(e.name)} (full replace)`,tags:[l],parameters:[y],requestBody:{required:true,content:{"application/json":{schema:re(r??n)}}},responses:{200:Ue("Document updated",re(n)),400:X("Validation error"),404:X("Document not found"),500:X("Internal server error")}},g.patch={operationId:`patch${xe(ce(e.name))}`,summary:`Partially update a ${ce(e.name)}`,tags:[l],parameters:[y],requestBody:{required:true,content:{"application/json":{schema:{allOf:[re(r??n)],description:"All fields are optional for partial updates"}}}},responses:{200:Ue("Document patched",re(n)),400:X("Validation error"),404:X("Document not found"),500:X("Internal server error")}},e.allowDelete&&(g.delete={operationId:`delete${xe(ce(e.name))}`,summary:`Delete a ${ce(e.name)}`,tags:[l],parameters:[y],responses:{200:Ue("Document deleted",{type:"object",properties:{id:{type:"string"}}}),404:X("Document not found"),500:X("Internal server error")}}),i[c]=g,i}function Pt(e,t,n={}){let{title:o="CRUD API",version:r="1.0.0",description:i,servers:l,auth:u=false}=n,c=t==="/"?"":t.replace(/\/$/,""),y={},g={},C=[];y.ErrorResponse={type:"object",properties:{success:{type:"boolean",enum:[false]},error:{type:"string"}},required:["success","error"]},y.QueryRequestBody=Xr();for(let[b,S]of Object.entries(e)){let p=xe(ce(b)),a=`${p}Create`,f=`${p}Update`;y[p]=Ot(S.schema);let s=R=>{let T=R&&R.length>0?R:Object.keys(S.schema.shape),A={};for(let E of T){let O=E.split(".")[0];O&&S.schema.shape[O]&&!S.systemKeys.includes(O)&&(A[O]=S.schema.shape[O]);}return A},d=null,m=s(S.createFields);Object.keys(m).length>0&&(y[a]=Ot(z$1.object(m)),d=a);let k=null,w=s(S.mutableFields);Object.keys(w).length>0&&(y[f]=Ot(z$1.object(w)),k=f);let $=Yr(S,c,p,d,k);Object.assign(g,$),C.push({name:b,description:`Operations on ${b} (collection: ${S.path})`});}let h={},x;return u==="basic"?(h.basicAuth={type:"http",scheme:"basic"},x=[{basicAuth:[]}]):u==="bearer"&&(h.bearerAuth={type:"http",scheme:"bearer",bearerFormat:"JWT"},x=[{bearerAuth:[]}]),{openapi:"3.1.0",info:{title:o,version:r,...i?{description:i}:{}},...l&&l.length>0?{servers:l}:{},paths:g,components:{schemas:y,...Object.keys(h).length>0?{securitySchemes:h}:{}},...x?{security:x}:{},tags:C}}function xe(e){return e.charAt(0).toUpperCase()+e.slice(1)}function ce(e){return e.endsWith("ies")?e.slice(0,-3)+"y":e.endsWith("ses")||e.endsWith("xes")||e.endsWith("zes")?e.slice(0,-2):e.endsWith("s")&&!e.endsWith("ss")?e.slice(0,-1):e}function eo(e,t){return `<!DOCTYPE html>
|
|
1146
|
+
`;function Ze(){return jsx("script",{dangerouslySetInnerHTML:{__html:an}})}pt();function ge(e){return "<!DOCTYPE html>"+renderToString(e)}var Cr=["corporate","silk","dark"],$r=()=>jsxs("div",{class:"dropdown dropdown-end","data-frs-theme-switcher":true,children:[jsxs("button",{type:"button",tabIndex:0,class:"btn btn-sm btn-ghost text-neutral-content gap-1.5","aria-label":"Switch theme",children:[jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2",class:"size-4",children:[jsx("circle",{cx:"12",cy:"12",r:"4"}),jsx("path",{d:"M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"})]}),jsx("span",{class:"text-xs hidden sm:inline","data-frs-theme-current":true,children:"Theme"})]}),jsx("ul",{tabIndex:0,class:"dropdown-content menu menu-sm bg-base-100 text-base-content rounded-box z-50 mt-2 w-40 p-1 shadow-lg border border-base-300",children:Cr.map(e=>jsx("li",{children:jsxs("button",{type:"button","data-frs-theme":e,class:"capitalize justify-between",children:[jsx("span",{children:e}),jsx("span",{class:"hidden text-primary","data-frs-theme-check":e,children:"\u2713"})]})},e))})]}),he=({opts:e,children:t})=>{let{title:n,breadcrumb:o,flash:r,basePath:s="/"}=e;return jsxs("html",{lang:"en","data-theme":"corporate",children:[jsxs("head",{children:[jsx("meta",{charset:"UTF-8"}),jsx("meta",{name:"viewport",content:"width=device-width, initial-scale=1"}),jsxs("title",{children:[n," \u2014 FRS Admin"]}),jsx("script",{dangerouslySetInnerHTML:{__html:"(function(){try{var t=localStorage.getItem('frs-admin-theme');if(t){document.documentElement.setAttribute('data-theme',t);}}catch(_){}})();"}}),jsx("link",{href:"https://cdn.jsdelivr.net/npm/daisyui@5/themes.css",rel:"stylesheet",type:"text/css"}),jsx("link",{href:"https://cdn.jsdelivr.net/npm/daisyui@5/daisyui.css",rel:"stylesheet",type:"text/css"}),jsx("script",{src:"https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"})]}),jsxs("body",{class:"bg-base-200/50 min-h-screen flex flex-col",children:[jsxs("div",{class:"navbar bg-neutral text-neutral-content shadow-sm sticky top-0 z-50 px-6",children:[jsx("div",{class:"flex-1",children:jsx("a",{href:s,class:"font-bold text-lg tracking-tight hover:opacity-80 transition-opacity",children:"FRS Admin"})}),jsx("div",{class:"flex-none",children:jsx($r,{})})]}),jsxs("main",{class:"px-6 py-8 w-full flex-1",children:[o&&o.length>0&&jsx("div",{class:"text-sm breadcrumbs mb-4",children:jsx("ul",{children:o.map((l,u)=>l.href?jsx("li",{children:jsx("a",{href:l.href,children:l.label})},u):jsx("li",{class:"text-base-content/60",children:l.label},u))})}),jsx("h1",{class:"text-2xl font-bold mb-6",children:n}),r&&jsxs("div",{role:"alert",class:`alert ${r.type==="success"?"alert-success":r.type==="warning"?"alert-warning":"alert-error"} mb-6`,children:[jsx("span",{class:"flex-1",children:r.message}),r.action&&jsx("a",{href:r.action.href,...r.action.external?{target:"_blank",rel:"noopener noreferrer"}:{},class:"btn btn-sm btn-outline",children:r.action.label})]}),t]}),jsx(ut,{basePath:s}),jsx(Ze,{})]})]})};function ft(e,t){return ge(jsx(he,{opts:t,children:jsx("div",{dangerouslySetInnerHTML:{__html:e}})}))}function mt(e,t){return ge(jsx(he,{opts:{title:"Repositories",basePath:t},children:e.length===0?jsxs("div",{class:"text-center py-20 text-base-content/50",children:[jsx("p",{class:"text-lg font-medium mb-1",children:"No repositories configured"}),jsx("p",{class:"text-sm",children:"Add a repository to your FRS config to get started."})]}):jsx("div",{class:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4",children:e.map(n=>jsx("a",{href:`${t}/${n.name}`,class:"card bg-base-100 border border-base-300 hover:shadow-md no-underline transition-shadow",children:jsxs("div",{class:"card-body p-5",children:[jsx("h2",{class:"card-title text-sm font-semibold",children:n.name}),jsx("p",{class:"text-xs text-base-content/50 font-mono",children:n.path})]})},n.name))})}))}var un=[{value:"==",label:"="},{value:"!=",label:"\u2260"},{value:"in",label:"in"},{value:"not-in",label:"not in"}],Ar=[{value:"==",label:"="},{value:"!=",label:"\u2260"},{value:"<",label:"<"},{value:"<=",label:"\u2264"},{value:">",label:">"},{value:">=",label:"\u2265"},{value:"in",label:"in"},{value:"not-in",label:"not in"}],Tr=[{value:"array-contains",label:"contains"},{value:"array-contains-any",label:"contains any"}];function Or(e){switch(e){case "ZodNumber":case "ZodBigInt":case "ZodDate":return Ar;case "ZodBoolean":return un;case "ZodArray":return Tr;default:return un}}var be="__null__";function Er(e){return `(function(cb){var i=document.getElementById('${e}');if(!i)return;if(cb.checked){i.dataset._prev=i.value;if(i.tagName==='SELECT'){var o=i.querySelector('option[value="${be}"]');if(!o){o=document.createElement('option');o.value='${be}';o.textContent='\u2205 null';o.dataset._auto='1';i.appendChild(o);}o.selected=true;}else{if(i.type==='number'||i.type==='datetime-local'){i.dataset._type=i.type;i.type='text';}i.value='${be}';i.readOnly=true;}i.style.opacity='0.55';}else{i.style.opacity='';if(i.tagName==='SELECT'){var o2=i.querySelector('option[value="${be}"][data-_auto="1"]');if(o2)o2.remove();var prev=i.dataset._prev||'';for(var k=0;k<i.options.length;k++)i.options[k].selected=(i.options[k].value===prev);}else{if(i.dataset._type){i.type=i.dataset._type;delete i.dataset._type;}i.readOnly=false;i.value=(i.dataset._prev&&i.dataset._prev!=='${be}')?i.dataset._prev:'';}}})(this)`}function Pr(e,t){return `(function(){var h=document.getElementById('${e}');var boxes=document.querySelectorAll('input[data-enum-group="${t}"]');h.value=Array.from(boxes).filter(function(b){return b.checked;}).map(function(b){return b.value;}).join(',');})()`}function Me({inputId:e,active:t}){return jsxs("label",{class:"flex items-center gap-1 cursor-pointer select-none text-xs text-base-content/60 hover:text-base-content border border-base-300 rounded-md px-1.5 py-1 shrink-0 leading-none h-8",title:"Filter where field IS NULL",children:[jsx("input",{type:"checkbox",class:"checkbox checkbox-xs",checked:t,onchange:Er(e)}),jsx("span",{children:"\u2205"})]})}function Ir({col:e,active:t}){let n=t?.value??"",o=n===be,r=`fv_input_${e.name.replace(/\./g,"__")}`,s=t?.op,l=s==="in"||s==="not-in";if(e.enumValues&&e.enumValues.length>0){if(l){let u=new Set(n.split(",").map(y=>y.trim()).filter(Boolean)),c=`eg_${e.name.replace(/\./g,"__")}`;return jsxs("div",{class:"flex flex-wrap items-center gap-1 w-full",children:[jsx("input",{type:"hidden",id:r,name:`fv_${e.name}`,value:n}),e.enumValues.map(y=>jsxs("label",{class:"flex items-center gap-1 text-xs border border-base-300 rounded px-2 cursor-pointer hover:bg-base-200",children:[jsx("input",{type:"checkbox",class:"checkbox checkbox-xs",value:y,checked:u.has(y),"data-enum-group":c,onchange:Pr(r,c)}),jsx("span",{children:y})]},y))]})}return jsxs("div",{class:"flex items-center gap-1 w-full",children:[jsxs("select",{id:r,name:`fv_${e.name}`,class:"select select-sm select-bordered w-full",style:o?"opacity:0.55":void 0,children:[jsx("option",{value:"",selected:n===""&&!o,children:"\u2014"}),e.enumValues.map(u=>jsx("option",{value:u,selected:n===u,children:u},u)),e.nullable&&jsx("option",{value:be,"data-_auto":"1",selected:o,children:"\u2205 null"})]}),e.nullable&&jsx(Me,{inputId:r,active:o})]})}if(e.zodType==="ZodBoolean")return jsxs("div",{class:"flex items-center gap-1 w-full",children:[jsxs("select",{id:r,name:`fv_${e.name}`,class:"select select-sm select-bordered w-full",style:o?"opacity:0.55":void 0,children:[jsx("option",{value:"",selected:n===""&&!o,children:"\u2014"}),jsx("option",{value:"true",selected:n==="true",children:"true"}),jsx("option",{value:"false",selected:n==="false",children:"false"}),e.nullable&&jsx("option",{value:be,"data-_auto":"1",selected:o,children:"\u2205 null"})]}),e.nullable&&jsx(Me,{inputId:r,active:o})]});if(e.zodType==="ZodArray"){let u=t?.op==="array-contains-any";return jsx("input",{id:r,type:"text",name:`fv_${e.name}`,value:n,placeholder:u?"val1, val2, \u2026":"value",class:"input input-sm input-bordered w-full"})}return e.zodType==="ZodNumber"||e.zodType==="ZodBigInt"?jsxs("div",{class:"flex items-center gap-1 w-full",children:[jsx("input",{id:r,type:o?"text":"number",name:`fv_${e.name}`,value:n,placeholder:"value",class:"input input-sm input-bordered w-full",readOnly:o||void 0,style:o?"opacity:0.55":void 0,"data-_type":o?"number":void 0}),e.nullable&&jsx(Me,{inputId:r,active:o})]}):e.zodType==="ZodDate"?jsxs("div",{class:"flex items-center gap-1 w-full",children:[jsx("input",{id:r,type:o?"text":"datetime-local",name:`fv_${e.name}`,value:n,class:"input input-sm input-bordered w-full",readOnly:o||void 0,style:o?"opacity:0.55":void 0,"data-_type":o?"datetime-local":void 0}),e.nullable&&jsx(Me,{inputId:r,active:o})]}):jsxs("div",{class:"flex items-center gap-1 w-full",children:[jsx("input",{id:r,type:"text",name:`fv_${e.name}`,value:n,placeholder:"value",class:"input input-sm input-bordered w-full",readOnly:o||void 0,style:o?"opacity:0.55":void 0}),e.nullable&&jsx(Me,{inputId:r,active:o})]})}function yt({action:e,columnMeta:t,activeFilters:n,isGroup:o}){let r=Object.fromEntries(n.map(c=>[c.field,c])),s=n.length>0,l=n.length>=2||o&&s,u=t.filter(c=>c.zodType!=="ZodObject"&&c.zodType!=="ZodRecord");return jsxs("details",{class:"collapse collapse-arrow bg-base-100 border border-base-300 rounded-box mb-6 shadow-sm",open:s?true:void 0,children:[jsxs("summary",{class:"collapse-title text-sm font-medium py-2 min-h-0",children:["Filters",s&&jsxs("span",{class:"badge badge-primary badge-sm ml-2",children:[n.length," active"]})]}),jsx("div",{class:"collapse-content pb-4 pt-2",children:jsxs("form",{method:"get",action:e,children:[jsx("div",{class:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4",children:u.map(c=>{let y=Or(c.zodType),g=r[c.name],C=g?.op??y[0].value;return jsxs("div",{class:"flex flex-col gap-1.5",children:[jsx("label",{class:"text-xs font-semibold text-base-content/60 uppercase tracking-wide",children:c.name}),jsxs("div",{class:"flex gap-1.5",children:[y.length>1?jsx("select",{name:`fo_${c.name}`,class:"select select-sm select-bordered w-20 shrink-0",children:y.map(h=>jsx("option",{value:h.value,selected:h.value===C,children:h.label},h.value))}):jsx("input",{type:"hidden",name:`fo_${c.name}`,value:y[0].value}),jsx(Ir,{col:c,active:g})]})]},c.name)})}),jsxs("div",{class:"flex flex-wrap gap-2 mt-4 pt-3 border-t border-base-200 items-center",children:[jsx("button",{type:"submit",class:"btn btn-sm btn-primary",children:"Apply"}),s&&jsx("a",{href:e,class:"btn btn-sm btn-ghost",children:"Clear"}),l&&jsxs("span",{class:"text-xs text-warning ml-auto flex items-center gap-1",children:[jsx("svg",{xmlns:"http://www.w3.org/2000/svg",class:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:jsx("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"})}),o?"Collection group queries require a composite index":"Multiple filters may require a composite index"]})]})]})})]})}function gt(e,t,n,o,r,s){let l=n==="create"?`Create ${e}`:`Edit ${e} / ${o??""}`,u=n==="create"?[{label:"Repositories",href:r},{label:e,href:`${r}/${e}`},{label:"New document"}]:[{label:"Repositories",href:r},{label:e,href:`${r}/${e}`},{label:`Edit ${o??""}`}];return ge(jsx(he,{opts:{title:l,breadcrumb:u,basePath:r,flash:s},children:jsx("div",{class:"card bg-base-100 border border-base-300",children:jsx("div",{class:"card-body p-6",children:jsx("div",{dangerouslySetInnerHTML:{__html:t}})})})}))}Xe();dt();function ht(e,t,n){let o=new URLSearchParams;for(let r of e)o.set(`fv_${r.field}`,r.value),o.set(`fo_${r.field}`,r.op);return t&&(o.set("ob",t.field),o.set("od",t.dir)),n&&o.set("ps",String(n)),o}function pn(e,t,n,o,r){let s=ht(e,o,r);return s.set("cursor",t),s.set("dir",n),`?${s.toString()}`}function Nr(e,t,n,o){let r=ht(n,void 0,o);return t?.field===e?t.dir==="asc"&&(r.set("ob",e),r.set("od","desc")):(r.set("ob",e),r.set("od","asc")),`?${r.toString()}`}function _r(e,t,n){return `?${ht(t,n,e).toString()}`}function bt(e,t,n,o,r,s,l=[],u=[],c=false,y=[],g,C,h,w,v,b,S,p=false){let i=`${o}/${e}`,m=`${i}/create`,a={};if(S)for(let R of n)a[R]=Oe(Ee(S,R));let d=(b??[]).filter(R=>{let T=a[R]??Oe(Ee(S,R));return T==="string"||T==="number"||T==="bigint"||T==="boolean"||T==="enum"||T==="literal"}),f=d.length>0,k=c,x=k||f,$=d.map(R=>{let T=Ee(S,R),A=Oe(T),E=l.find(O=>O.name===R);return {name:R,type:A,enumValues:E?.enumValues??null,nullable:E?.nullable??false}});return ge(jsxs(he,{opts:{title:e,breadcrumb:[{label:"Repositories",href:o},{label:e}],basePath:o,flash:s},children:[l.length>0&&jsx(yt,{action:i,columnMeta:l,activeFilters:u,isGroup:w}),h&&jsxs("div",{role:"alert",class:`alert ${h.type==="index"?"alert-warning":"alert-error"} mb-6 shadow-sm`,children:[jsx("svg",{xmlns:"http://www.w3.org/2000/svg",class:"h-6 w-6 shrink-0 stroke-current",fill:"none",viewBox:"0 0 24 24",children:h.type==="index"?jsx("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"}):jsx("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"})}),jsxs("div",{class:"flex-1",children:[jsx("h3",{class:"font-bold",children:h.type==="index"?"Composite index required":"Query failed"}),jsx("div",{class:"text-sm",children:h.message})]}),h.indexUrl&&jsx("a",{href:h.indexUrl,target:"_blank",rel:"noopener noreferrer",class:"btn btn-sm btn-outline",children:"Create Index \u2192"})]}),jsxs("div",{class:"flex flex-wrap justify-between items-center mb-4 gap-3","data-frs-toolbar":true,children:[jsxs("div",{class:"flex items-center gap-3",children:[jsxs("span",{class:"text-sm text-base-content/60",children:[t.length,typeof v=="number"&&jsxs(Fragment,{children:[" ","of ",jsx("span",{class:"font-semibold text-base-content/80",children:v})]})," ","document",(typeof v=="number"?v:t.length)!==1&&"s"]}),jsxs("div",{class:"flex items-center gap-1.5 text-sm text-base-content/60",children:[jsx("span",{children:"Rows"}),jsx("div",{class:"join",children:[10,25,50,100].map(R=>jsx("a",{href:_r(R,u,g),class:`join-item btn btn-xs ${C===R?"btn-active btn-primary":"btn-outline"}`,children:R},R))})]})]}),jsx("a",{href:m,class:"btn btn-primary btn-sm",children:"+ New"})]}),x&&jsxs("div",{class:"hidden mb-3 alert alert-info py-2 px-3","data-frs-bulk-bar":true,"data-frs-repo":e,"data-frs-total":typeof v=="number"?String(v):"","data-frs-page-size":String(C??t.length),"data-frs-allow-delete":k?"1":"0","data-frs-allow-update":f?"1":"0","data-frs-fields":JSON.stringify($),"data-frs-filters":JSON.stringify(u),children:[jsxs("div",{class:"flex-1 text-sm",children:[jsx("span",{"data-frs-bulk-summary":true,children:"0 selected"}),typeof v=="number"&&v>t.length&&jsxs("button",{type:"button",class:"ml-3 link link-primary text-sm hidden","data-frs-bulk-select-all":true,children:["Select all ",v," matching documents"]}),jsxs("span",{class:"hidden ml-3 italic","data-frs-bulk-all-active":true,children:["All ",v??"?"," matching documents are selected."," ",jsx("button",{type:"button",class:"link","data-frs-bulk-clear":true,children:"Clear selection"})]})]}),jsxs("div",{class:"flex gap-2",children:[f&&jsx("button",{type:"button",class:"btn btn-sm btn-outline","data-frs-bulk-action":"update",children:"Update field\u2026"}),k&&jsx("button",{type:"button",class:"btn btn-sm btn-error btn-outline","data-frs-bulk-action":"delete",children:"Delete"})]})]}),jsx("div",{class:"overflow-x-auto rounded-box border border-base-300 bg-base-100","data-frs-table-wrap":true,children:jsxs("table",{class:"table table-sm w-full","data-frs-table":true,"data-frs-repo":e,"data-frs-colcount":n.length,children:[jsx("thead",{children:jsxs("tr",{class:"bg-base-200/50",children:[x&&jsx("th",{class:"w-8",children:jsx("input",{type:"checkbox",class:"checkbox checkbox-xs checkbox-primary","data-frs-select-page":true,"aria-label":"Select all on this page"})}),[...n].map((R,T)=>{let A=g?.field===R,E=A?g.dir==="asc"?" \u25B2":" \u25BC":"";return jsx("th",{class:"text-xs font-semibold text-base-content/60 uppercase tracking-wide",children:jsxs("a",{href:Nr(R,g,u,C),class:`hover:text-base-content inline-flex items-center gap-0.5${A?" text-primary font-bold":""}`,children:[R,E]})},T)}),y.map((R,T)=>jsx("th",{class:"text-xs font-semibold text-base-content/60 uppercase tracking-wide",children:R.column},`rel-${T}`)),jsx("th",{class:"text-xs font-semibold text-base-content/60 uppercase tracking-wide text-right",children:"Actions"})]})}),jsx("tbody",{children:t.length===0?jsx("tr",{children:jsx("td",{colspan:n.length+y.length+1+(x?1:0),class:"text-center py-16 text-base-content/40",children:"No documents found"})}):t.map((R,T)=>{let A=String(R.docId??R.id??""),E=`${o}/${e}/${encodeURIComponent(A)}/edit`,O=`${o}/${e}/${encodeURIComponent(A)}/delete`;return jsxs("tr",{class:"hover","data-frs-row-id":A,children:[x&&jsx("td",{class:"align-middle py-2",children:jsx("input",{type:"checkbox",class:"checkbox checkbox-xs checkbox-primary","data-frs-select-row":true,value:A,"aria-label":`Select ${A}`})}),n.map((N,j)=>{let I=R[N],P=a[N],q=P?Be(P,I):null;return jsx("td",{class:"align-top py-2",children:jsx(Te,{val:I,mismatch:q})},j)}),y.map((N,j)=>{let I=R[N.key];if(I==null||I==="")return jsx("td",{class:"py-2"},`rel-${j}`);let P=N.type==="one"?`${o}/${N.targetRepo}/${encodeURIComponent(String(I))}/edit`:`${o}/${N.targetRepo}?fv_${N.targetKey}=${encodeURIComponent(String(I))}`;return jsx("td",{class:"align-middle py-2",children:jsx("a",{href:P,class:"btn btn-xs btn-ghost btn-outline","data-frs-relation":true,"data-frs-rel-type":N.type,"data-frs-rel-repo":N.targetRepo,"data-frs-rel-fk":N.targetKey,"data-frs-rel-val":String(I),"data-frs-rel-label":N.column,children:N.column})},`rel-${j}`)}),jsx("td",{class:"align-middle text-right whitespace-nowrap py-2",children:jsxs("div",{class:"flex gap-1 justify-end",children:[jsx("a",{href:E,class:"btn btn-xs btn-outline",children:"Edit"}),p&&jsx("a",{href:`${o}/${e}/${encodeURIComponent(A)}/history`,class:"btn btn-xs btn-outline",title:"View change history",children:"History"}),c&&jsx("form",{method:"post",action:O,onsubmit:"return confirm('Delete this document?')",children:jsx("button",{type:"submit",class:"btn btn-xs btn-error btn-outline",children:"Delete"})})]})})]},T)})})]})}),(r.hasPrev||r.hasNext)&&jsxs("div",{class:"flex flex-col items-center mt-6 gap-2",children:[jsxs("div",{class:"flex justify-center items-center gap-2",children:[r.hasPrev?jsx("a",{href:pn(u,r.prevCursor,"prev",g,C),class:"btn btn-sm btn-outline",children:"\u2190 Previous"}):jsx("button",{class:"btn btn-sm btn-outline",disabled:true,children:"\u2190 Previous"}),r.hasNext?jsx("a",{href:pn(u,r.nextCursor,"next",g,C),class:"btn btn-sm btn-outline",children:"Next \u2192"}):jsx("button",{class:"btn btn-sm btn-outline",disabled:true,children:"Next \u2192"})]}),typeof v=="number"&&jsxs("div",{class:"text-xs text-base-content/50",children:[v," total document",v!==1?"s":"",u.length>0?" matching filters":""]})]}),x&&f&&jsxs("dialog",{id:"frs-bulk-update-modal",class:"modal",children:[jsxs("div",{class:"modal-box",children:[jsx("h3",{class:"font-bold text-lg mb-3",children:"Bulk update field"}),jsx("p",{class:"text-sm text-base-content/60 mb-4","data-frs-bulk-update-summary":true,children:"Update one field on the selected documents."}),jsxs("form",{method:"dialog","data-frs-bulk-update-form":true,children:[jsxs("label",{class:"form-control w-full mb-3",children:[jsx("div",{class:"label",children:jsx("span",{class:"label-text text-xs uppercase tracking-wide",children:"Field"})}),jsxs("select",{class:"select select-bordered select-sm w-full",name:"field",required:true,"data-frs-bulk-field-select":true,children:[jsx("option",{value:"",children:"\u2014 Select a field \u2014"}),d.map(R=>jsx("option",{value:R,children:R},R))]})]}),jsx("div",{class:"mb-4","data-frs-bulk-value-container":true}),jsxs("div",{class:"modal-action",children:[jsx("button",{type:"button",class:"btn btn-sm btn-ghost","data-frs-bulk-update-cancel":true,children:"Cancel"}),jsx("button",{type:"submit",class:"btn btn-sm btn-primary","data-frs-bulk-update-submit":true,children:"Apply"})]})]})]}),jsx("form",{method:"dialog",class:"modal-backdrop",children:jsx("button",{children:"close"})})]})]}))}var jr="";function qe(e,t){return ft(e,t)}function vt(e,t){return mt(e,t)}function xt(e,t,n,o,r,s,l,u,c,y,g,C,h,w,v,b,S,p){return bt(e,t,n,o,r,s,l,u,c,y,g,C,h,w,v,b,S,p)}function ve(e,t,n,o,r,s){return gt(e,t,n,o,r,s)}var fn="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";function zr(){let e="";for(let t=0;t<20;t++)e+=fn.charAt(Math.floor(Math.random()*fn.length));return e}function et(e,t){if(!t)return;let n=e[t];if(typeof n!="string"||!n)return;let o=n.split("/").filter(Boolean),r=[];for(let s=1;s<o.length;s+=2)r.push(o[s]);return r.length>0?r:void 0}async function Pe(e,t){let n=e.documentKey??"docId",o=`by${n.charAt(0).toUpperCase()}${n.slice(1)}`;if(typeof e.repo.get[o]=="function")try{let s=await e.repo.get[o](t);if(s)return s}catch{}return (await e.repo.query.by({where:[[n,"==",t]],limit:1}))[0]??null}function wt(e,t,n){let o=e.documentKey??"docId",r=ze(n,{ref:e.repo.ref,path:e.path,isGroup:!!e.isGroup,filters:[{field:o,op:"==",value:t}]});return r.type==="index"?{type:"warning",message:"Loading this document requires a composite index that does not exist yet.",...r.indexUrl?{action:{href:r.indexUrl,label:"Create Index \u2192",external:true}}:{}}:{type:"error",message:r.message}}function z(e,t,n=200){e.status(n).set("Content-Type","text/html; charset=utf-8").send(t);}function St(e,t){e.status(302).set("Location",t).send("");}function kt(e,t){let n=t.shape,o={};for(let[r,s]of Object.entries(n)){let l=Ct(s);if(l==="ZodObject"){if(e[r+"__isnull"]==="1"){o[r]=null;continue}let y={},g=false;for(let[w,v]of Object.entries(e))w.startsWith(`${r}.`)&&(y[w.slice(r.length+1)]=v,g=true);if(g){let w=s;for(;;){let v=H(w);if(v==="ZodOptional"||v==="ZodNullable"||v==="ZodDefault")w=G(w);else break}o[r]=kt(y,w);continue}let C=e[r],h=Array.isArray(C)?C[C.length-1]:C;if(h)try{o[r]=JSON.parse(h);}catch{o[r]=h;}continue}let u=e[r],c=Array.isArray(u)?u[u.length-1]:u;if(e[r+"__isnull"]==="1"){o[r]=null;continue}if(c===void 0||c===""){l==="ZodBoolean"&&(o[r]=false);continue}switch(l){case "ZodBoolean":c==="__null__"?o[r]=null:o[r]=c==="true"||c==="on"||c==="1";break;case "ZodNumber":case "ZodBigInt":o[r]=Number(c);break;case "ZodDate":o[r]=new Date(c);break;case "ZodArray":try{o[r]=JSON.parse(c);}catch{o[r]=c;}break;default:if(c.startsWith("{")||c.startsWith("["))try{o[r]=JSON.parse(c);break}catch{}o[r]=c;}}return o}function mn(e){let t=null;if(e instanceof Date)t=e;else if(typeof e=="object"&&e!==null&&typeof e.toDate=="function")t=e.toDate();else if(typeof e=="object"&&e!==null&&"_seconds"in e&&"_nanoseconds"in e)t=new Date(e._seconds*1e3+Math.floor(e._nanoseconds/1e6));else if(typeof e=="string"||typeof e=="number"){let o=new Date(e);isNaN(o.getTime())||(t=o);}if(!t||isNaN(t.getTime()))return null;let n=o=>String(o).padStart(2,"0");return `${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())}T${n(t.getHours())}:${n(t.getMinutes())}`}function Ct(e){let t=e;for(;;){let n=H(t);if(n==="ZodOptional"||n==="ZodNullable"||n==="ZodDefault")t=G(t);else return n}}function Zr(e){let t=e;for(;;){let n=H(t);if(n==="ZodOptional"||n==="ZodNullable"||n==="ZodDefault")t=G(t);else return t}}function gn(e){let t=e;for(;;){let n=H(t);if(n==="ZodOptional"||n==="ZodNullable")return true;if(n==="ZodDefault"){t=G(t);continue}return false}}function hn(e){let t=Zr(e),n=H(t);if(n==="ZodEnum"){let o=_e(t);return o.length>0?o:void 0}if(n==="ZodNativeEnum"){let o=De(t),r=Object.values(o).filter(s=>typeof s=="string");return r.length>0?r:void 0}if(n==="ZodLiteral"){let o=Ve(t);return typeof o=="string"?[o]:void 0}}function bn(e,t,n=""){let o={};for(let r of Object.keys(t.shape)){let s=n?`${n}.${r}`:r,l=e[r];if(l===null){o[s]="__null__";continue}if(l===void 0)continue;let u=t.shape[r];for(;;){let y=H(u);if(y==="ZodOptional"||y==="ZodNullable"||y==="ZodDefault")u=G(u);else break}let c=H(u);if(c==="ZodObject"&&typeof l=="object"&&l!==null&&!Array.isArray(l)){let y=bn(l,u,s);Object.assign(o,y);}else if(c==="ZodDate"){let y=mn(l);y!==null&&(o[s]=y);}else if(typeof l=="object"&&l!==null&&!Array.isArray(l)&&("_seconds"in l||typeof l.toDate=="function")){let y=mn(l);o[s]=y??JSON.stringify(l,null,2);}else typeof l=="object"?o[s]=JSON.stringify(l,null,2):o[s]=String(l);}return o}function Rt(e,t){return e.map(n=>({...n,defaultValue:t[n.name]??n.defaultValue,nested:n.nested?Rt(n.nested,t):void 0}))}function Br(e,t){let n=new Set(["==","!=","<","<=",">",">=","in","not-in","array-contains","array-contains-any"]),o=[];for(let[r,s]of Object.entries(e)){if(!r.startsWith("fv_"))continue;let l=r.slice(3);if(!t.has(l))continue;let u=(s??"").trim();if(!u)continue;let c=e[`fo_${l}`]??"==",y=n.has(c)?c:"==";o.push({field:l,op:y,value:u});}return o}function yn(e){let t="__null__",n=o=>o===t?null:o==="true"?true:o==="false"?false:o!==""&&!isNaN(Number(o))?Number(o):o;return e.map(o=>{if(o.op==="array-contains-any"||o.op==="in"||o.op==="not-in"){let r=o.value.split(",").map(s=>s.trim()).filter(s=>s!==""&&s!==t).map(s=>n(s));return [o.field,o.op,r]}return [o.field,o.op,n(o.value)]})}function vn(e,t,n=""){let o=[];for(let r of e){let s=n?`${n}.${r}`:r,l=t.shape[r];if(!l){o.push({name:s,zodType:"ZodString"});continue}let u=Ct(l);if(u==="ZodObject"){let c=l;for(;;){let g=H(c);if(g==="ZodOptional"||g==="ZodNullable"||g==="ZodDefault")c=G(c);else break}let y=te(c);o.push(...vn(Object.keys(y),c,s));}else o.push({name:s,zodType:u,nullable:gn(l),enumValues:hn(l)});}return o}function Mr(e,t){let n=t.split("."),o=e;for(let r of n){for(;;){let l=H(o);if(l==="ZodOptional"||l==="ZodNullable"||l==="ZodDefault")o=G(o);else break}let s=te(o);if(!(r in s))return null;o=s[r];}return o}function ke(e,t){if(!t||t.length===0)return e;let n=[],o=new Map;for(let s of t){let l=s.indexOf(".");if(l===-1)n.push(s);else {let u=s.slice(0,l),c=s.slice(l+1);o.has(u)||o.set(u,[]),o.get(u).push(c);}}let r={};for(let s of n)s in e.shape&&(r[s]=e.shape[s]);for(let[s,l]of o){if(!(s in e.shape))continue;let u=e.shape[s];for(;;){let c=H(u);if(c==="ZodOptional"||c==="ZodNullable"||c==="ZodDefault")u=G(u);else break}if(H(u)!=="ZodObject"){r[s]=e.shape[s];continue}r[s]=ke(u,l);}return z$1.object(r)}function ue(e,t){return ee(e,t)}function xn(e,t){let n=(p,i)=>{let m=ue(p,t),a=Object.values(e).map(d=>({name:d.name,path:d.path}));z(i,vt(a,m));},o=async(p,i)=>{let m=p.params.repoName;if(!m){z(i,"Bad request",400);return}let a=e[m];if(!a){z(i,"Repository not found",404);return}let d=a.pageSize??25,f=p.query??{},k=f.cursor,x=f.dir==="prev"?"prev":"next",$=f.ob??"",R=f.od==="desc"?"desc":"asc",T=$?{field:$,dir:R}:void 0,A=parseInt(f.ps??""),E=Number.isFinite(A)&&A>0?Math.min(A,200):d,O=a.listColumns??Object.keys(a.schema.shape),N=a.documentKey??"docId",j=[N,...O.filter(W=>W!==N)],I=a.filterableFields?(()=>{let W=[];for(let le of a.filterableFields)(le.includes(".")||O.includes(le))&&W.push(le);return W})():O,P=(()=>{let W=[];for(let le of I)if(le.includes(".")){let Ce=Mr(a.schema,le);W.push({name:le,zodType:Ce?Ct(Ce):"ZodString",nullable:Ce?gn(Ce):false,enumValues:Ce?hn(Ce):void 0});}else W.push(...vn([le],a.schema));return W})(),q=new Set(P.map(W=>W.name)),pe=Br(f,q),oe=yn(pe),K;if(k)try{let W=a.repo.ref;typeof W.doc=="function"&&(K=await W.doc(k).get());}catch{}let[U,Ue]=await Promise.all([a.repo.query.paginate({pageSize:E,cursor:K,direction:x,...oe.length>0?{where:oe}:{},...T?{orderBy:[{field:T.field,direction:T.dir}]}:{}}).catch(W=>({queryError:ze(W,{ref:a.repo.ref,path:a.path,isGroup:!!a.isGroup,filters:pe,sort:T})})),a.repo.aggregate.count(oe.length>0?{where:oe}:{}).catch(()=>{})]),Re="queryError"in U,jn=Re?[]:U.data,Fn=Re?"":U.nextCursor?.id??"",zn=Re?"":U.prevCursor?.id??"",Zn=Re?U.queryError:void 0,Bn=ue(p,t);z(i,xt(a.name,jn,j,Bn,{hasPrev:Re?false:U.hasPrevPage,hasNext:Re?false:U.hasNextPage,prevCursor:zn,nextCursor:Fn},void 0,P,pe,a.allowDelete??false,a.relationalMeta,T,E,Zn,a.isGroup,Ue,a.mutableFields,a.schema,a.historyEnabled));},r=(p,i)=>{let m=p.params.repoName;if(!m){z(i,"Bad request",400);return}let a=e[m];if(!a){z(i,"Repository not found",404);return}let d=ue(p,t),f=ke(a.schema,a.createFields),k=ae(f),x=`${d}/${a.name}/create`,$=ye(k,x,"POST","Create document");z(i,ve(a.name,$,"create",null,d));},s=async(p,i)=>{let m=p.params.repoName;if(!m){z(i,"Bad request",400);return}let a=e[m];if(!a){z(i,"Repository not found",404);return}let d=ue(p,t),f=p.body??{},k=kt(f,a.schema),x=ke(a.schema,a.createFields),$=x.safeParse(k);if(!$.success){let R=ae(x),T=`${d}/${a.name}/create`,A=ye(R,T,"POST","Create document"),E=$.error.issues.map(O=>`${O.path.join(".")}: ${O.message}`).join(", ");z(i,ve(a.name,A,"create",null,d,{type:"error",message:`Validation error: ${E}`}),422);return}try{if(a.isGroup&&a.parentKeys&&a.parentKeys.length>0){let R={...$.data};a.createdKey&&(R[a.createdKey]=new Date);let T=a.parentKeys.filter(N=>!R[N]);if(T.length>0)throw new Error(`Missing parent key(s) for subcollection create: ${T.join(", ")}`);let A=a.parentKeys.map(N=>R[N]),E=a.documentKey??"docId",O=R[E]||zr();await a.repo.set(...A,O,R);}else await a.repo.create($.data);St(i,`${d}/${a.name}?flash=created`);}catch(R){let T=ke(a.schema,a.createFields),A=ae(T),E=`${d}/${a.name}/create`,O=ye(A,E,"POST","Create document");z(i,ve(a.name,O,"create",null,d,{type:"error",message:`Save error: ${R.message}`}),500);}},l=async(p,i)=>{let m=p.params.repoName,a=p.params.id;if(!m||!a){z(i,"Bad request",400);return}let d=e[m];if(!d){z(i,"Repository not found",404);return}let f=ue(p,t),k=null;try{k=await Pe(d,a);}catch(E){let O=wt(d,a,E),N=we(E)?424:500;z(i,qe("",{title:`Edit ${d.name} / ${a}`,basePath:f,breadcrumb:[{label:"Repositories",href:f},{label:d.name,href:`${f}/${d.name}`},{label:`Edit ${a}`}],flash:O}),N);return}if(!k){z(i,"Document not found",404);return}let x=bn(k,d.schema),$=ke(d.schema,d.mutableFields),R=Rt(ae($),x),T=`${f}/${d.name}/${encodeURIComponent(a)}/edit`,A=ye(R,T,"POST","Save changes");z(i,ve(d.name,A,"edit",a,f));},u=async(p,i)=>{let m=p.params.repoName,a=p.params.id;if(!m||!a){z(i,"Bad request",400);return}let d=e[m];if(!d){z(i,"Repository not found",404);return}let f=ue(p,t),k=p.body??{},x=kt(k,d.schema),$=ke(d.schema,d.mutableFields),T=$.partial().safeParse(x);if(!T.success){let A=Object.fromEntries(Object.entries(k).map(([I,P])=>[I,Array.isArray(P)?P.join(","):P??""])),E=Rt(ae($),A),O=`${f}/${d.name}/${encodeURIComponent(a)}/edit`,N=ye(E,O,"POST","Save changes"),j=T.error.issues.map(I=>`${I.path.join(".")}: ${I.message}`).join(", ");z(i,ve(d.name,N,"edit",a,f,{type:"error",message:`Validation error: ${j}`}),422);return}try{let A=await Pe(d,a),E=(A&&et(A,d.pathKey))??[a];await d.repo.update(...E,T.data),St(i,`${f}/${d.name}?flash=updated`);}catch(A){let E=ke(d.schema,d.mutableFields),O=ae(E),N=`${f}/${d.name}/${encodeURIComponent(a)}/edit`,j=ye(O,N,"POST","Save changes"),I=we(A)?wt(d,a,A):{type:"error",message:`Save error: ${A.message}`},P=we(A)?424:500;z(i,ve(d.name,j,"edit",a,f,I),P);}},c=async(p,i)=>{let m=p.params.repoName,a=p.params.id;if(!m||!a){z(i,"Bad request",400);return}let d=e[m];if(!d){z(i,"Repository not found",404);return}if(!d.allowDelete){z(i,"Delete is not allowed for this repository",403);return}let f=ue(p,t);try{let k=await Pe(d,a),x=(k&&et(k,d.pathKey))??[a];await d.repo.delete(...x),St(i,`${f}/${d.name}?flash=deleted`);}catch(k){let x=we(k)?wt(d,a,k):{type:"error",message:`Delete error: ${k.message}`},$=we(k)?424:500;z(i,qe("",{title:`Delete ${d.name} / ${a}`,basePath:f,breadcrumb:[{label:"Repositories",href:f},{label:d.name,href:`${f}/${d.name}`},{label:`Delete ${a}`}],flash:x}),$);}},y=async(p,i)=>{let m=p.params.repoName;if(!m){z(i,"Bad request",400);return}let a=e[m];if(!a){z(i,"Repository not found",404);return}let d=ue(p,t),f=p.query,k=f?.type==="many"?"many":"one",x=Math.max(1,Math.min(100,Number(f?.ps??25)||25)),$=a.listColumns??Object.keys(te(a.schema)),{PanelOne:R,PanelMany:T}=await Promise.resolve().then(()=>(pt(),cn)),{renderToString:A}=await import('hono/jsx/dom/server');if(k==="one"){let P=String(f?.id??"");if(!P){z(i,"<div class='p-6 text-error'>Missing id parameter.</div>",400);return}try{let q=await Pe(a,P),pe=A(R({doc:q,repoName:a.name,basePath:d,schema:a.schema,columns:$}));z(i,pe);}catch(q){z(i,`<div class='p-6 text-error text-sm'>Error: ${q.message}</div>`,500);}return}let E=String(f?.fk??""),O=String(f?.fv??"");if(!E||!O){z(i,"<div class='p-6 text-error'>Missing fk/fv parameters.</div>",400);return}let N=f?.cursor??"",j=f?.dir==="prev"?"prev":"next",I;if(N)try{let P=a.repo.ref;typeof P.doc=="function"&&(I=await P.doc(N).get());}catch{}try{let P=await a.repo.query.paginate({pageSize:x,cursor:I,direction:j,where:[[E,"==",qr(O)]]}),q=A(T({docs:P.data,repoName:a.name,basePath:d,fk:E,fv:O,columns:$,schema:a.schema,pagination:{hasPrev:P.hasPrevPage,hasNext:P.hasNextPage,prevCursor:P.prevCursor?.id??"",nextCursor:P.nextCursor?.id??"",pageSize:x}}));z(i,q);}catch(P){z(i,`<div class='p-6 text-error text-sm'>Error: ${P.message}</div>`,500);}},g=async(p,i)=>{let m=[];for(let a of i){let d;if(p.isGroup||p.parentKeys?.length){let f=await Pe(p,a);d=f?et(f,p.pathKey):void 0;}d||(d=[a]);try{let f=p.repo.documentRef(...d);f&&m.push(f);}catch{}}return m},C=async(p,i)=>{let m=yn(i),a=p.documentKey??"docId",d=[],f;for(;;){let k=await p.repo.query.paginate({pageSize:500,cursor:f,direction:"next",...m.length>0?{where:m}:{}});for(let x of k.data){let $=String(x[a]??x.id??"");$&&d.push($);}if(!k.hasNextPage||!k.nextCursor)break;f=k.nextCursor;}return d},h=async(p,i)=>{let m=p.params.repoName;if(!m){Y(i,{error:"Bad request"},400);return}let a=e[m];if(!a){Y(i,{error:"Repository not found"},404);return}if(!a.allowDelete){Y(i,{error:"Delete is not allowed for this repository"},403);return}let d=p.body??{};try{let f=await v(a,d);if(f.length===0){Y(i,{deleted:0});return}let k=await g(a,f);for(let x=0;x<k.length;x+=500)await a.repo.bulk.delete(k.slice(x,x+500));Y(i,{deleted:k.length});}catch(f){Y(i,{error:f.message},500);}},w=async(p,i)=>{let m=p.params.repoName;if(!m){Y(i,{error:"Bad request"},400);return}let a=e[m];if(!a){Y(i,{error:"Repository not found"},404);return}let d=p.body??{},f=String(d.field??"");if(!f){Y(i,{error:"Missing 'field'"},400);return}if(!a.mutableFields||!a.mutableFields.includes(f)){Y(i,{error:`Field '${f}' is not bulk-updatable`},403);return}let k=a.schema.shape?.[f],x=d.value;if(k){let $=k.safeParse(d.value);if(!$.success){Y(i,{error:`Invalid value for '${f}': ${$.error.message}`},400);return}x=$.data;}try{let $=await v(a,d);if($.length===0){Y(i,{updated:0});return}let T=(await g(a,$)).map(A=>({docRef:A,data:{[f]:x}}));for(let A=0;A<T.length;A+=500)await a.repo.bulk.update(T.slice(A,A+500));Y(i,{updated:T.length});}catch($){Y(i,{error:$.message},500);}};async function v(p,i){if(i.selectAll){let m=b(i.filters,p);return await C(p,m)}return Array.isArray(i.ids)?i.ids.filter(m=>typeof m=="string"&&!!m):[]}function b(p,i){if(!Array.isArray(p))return [];let m=new Set((i.filterableFields??Object.keys(te(i.schema))).map(f=>String(f))),a=new Set(["==","!=","<","<=",">",">=","in","not-in","array-contains","array-contains-any"]),d=[];for(let f of p)f&&typeof f=="object"&&typeof f.field=="string"&&m.has(f.field)&&typeof f.value=="string"&&a.has(String(f.op))&&d.push({field:f.field,op:f.op,value:f.value});return d}return {handleDashboard:n,handleList:o,handleCreateForm:r,handleCreateSubmit:s,handleEditForm:l,handleEditSubmit:u,handleDelete:c,handlePanel:y,handleBulkDelete:h,handleBulkUpdate:w,handleHistory:async(p,i)=>{let m=p.params.repoName,a=p.params.id;if(!m||!a){z(i,"Bad request",400);return}let d=e[m];if(!d){z(i,"Repository not found",404);return}if(!d.historyEnabled||!d.repo.history){z(i,"History not enabled for this repository",404);return}let f=ue(p,t),k=d.historySubcollection??"history",x=[a];try{let P=await Pe(d,a),q=P?et(P,d.pathKey):void 0;q&&q.length>0&&(x=q);}catch{}let $=parseInt(String(p.query?.limit??"")),R=Number.isFinite($)&&$>0?Math.min($,500):100,T=[],A;try{T=await d.repo.history.list(...x,{limit:R});}catch(P){A=P.message;}let E=P=>String(P??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""),O=P=>{if(P===void 0)return '<span class="opacity-40">undefined</span>';if(P===null)return '<span class="opacity-40">null</span>';if(typeof P=="object")try{return `<code class="text-xs">${E(JSON.stringify(P))}</code>`}catch{return E(String(P))}return E(String(P))},N=P=>P?typeof P.toDate=="function"?P.toDate().toISOString():P instanceof Date?P.toISOString():E(String(P)):"",j=P=>`<span class="badge badge-sm ${P==="create"?"badge-success":P==="delete"?"badge-error":"badge-info"}">${E(P)}</span>`,I="";if(I+='<div class="flex items-center justify-between mb-4">',I+=`<a href="${f}/${d.name}/${encodeURIComponent(a)}/edit" class="btn btn-sm btn-outline">\u2190 Back to edit</a>`,I+=`<a href="${f}/${d.name}" class="btn btn-sm btn-outline">\u2190 Back to list</a>`,I+="</div>",I+=`<p class="text-sm text-base-content/60 mb-4">Subcollection: <code>${E(k)}</code> \xB7 Showing up to ${R} entries.</p>`,A)I+=`<div class="alert alert-error mb-4">${E(A)}</div>`;else if(T.length===0)I+='<div class="alert">No history entries found.</div>';else {I+='<div class="overflow-x-auto"><table class="table table-zebra table-sm">',I+="<thead><tr><th>When</th><th>Op</th><th>User</th><th>Reason / Comment</th><th>Changes</th></tr></thead><tbody>";for(let P of T){let q=P.meta??{},pe=[q.reason,q.comment].filter(U=>U!=null&&U!=="").map(U=>E(String(U))).join(" \u2014 "),oe="",K=Object.keys(P.changes??{});K.length===0?oe='<span class="opacity-40">\u2014</span>':oe='<ul class="space-y-1">'+K.map(U=>{let Ue=P.changes[U];return `<li><strong>${E(U)}</strong>: ${O(Ue.oldValue)} \u2192 ${O(Ue.newValue)}</li>`}).join("")+"</ul>",I+="<tr>",I+=`<td class="whitespace-nowrap text-xs font-mono">${E(N(P.historySetAt))}</td>`,I+=`<td>${j(P.operation??"update")}</td>`,I+=`<td class="text-xs">${E(q.userEmail??q.userId??"")}</td>`,I+=`<td class="text-xs">${pe}</td>`,I+=`<td>${oe}</td>`,I+="</tr>";}I+="</tbody></table></div>";}z(i,qe(I,{title:`History \u2014 ${d.name} / ${a}`,basePath:f,breadcrumb:[{label:"Repositories",href:f},{label:d.name,href:`${f}/${d.name}`},{label:`History ${a}`}]}));}}}function Y(e,t,n=200){e.status(n).set("Content-Type","application/json; charset=utf-8").send(JSON.stringify(t));}function qr(e){return e==="true"?true:e==="false"?false:e!==""&&!isNaN(Number(e))?Number(e):e}async function Hr(e){return typeof e.rawBody=="string"?e.rawBody:Buffer.isBuffer(e.rawBody)?e.rawBody.toString("utf8"):""}function Lr(e){let t={};if(!e)return t;for(let n of e.split("&")){let o=n.indexOf("=");if(o===-1)continue;let r=decodeURIComponent(n.slice(0,o).replace(/\+/g," ")),s=decodeURIComponent(n.slice(o+1).replace(/\+/g," ")),l=t[r];l===void 0?t[r]=s:Array.isArray(l)?l.push(s):t[r]=[l,s];}return t}function wn(e){let{basePath:t="/",repos:n,parseBody:o=true,auth:r,middleware:s=[],httpsOptions:l}=e,u=t==="/"?"":t.replace(/\/$/,""),c={};for(let[h,w]of Object.entries(n)){let v=w.schema??w.repo.schema??null;if(!v)throw new Error(`[createAdminServer] Repository "${h}" has no Zod schema. Either use createRepositoryConfig(schema)(config) or pass schema: explicitly.`);let b,S,p;if(w.fieldsConfig){let a=w.fieldsConfig;b=[],S=[],p=[];for(let[d,f]of Object.entries(a))for(let k of f)k==="filterable"?b.push(d):k==="mutable"?S.push(d):k==="create"&&p.push(d);b.length===0&&(b=void 0),S.length===0&&(S=void 0),p.length===0&&(p=void 0);}let i=(()=>{let a=w.repo._parentKeys;return a&&a.length>0?a:void 0})();if(i&&p)for(let a of i)p.includes(a)||p.push(a);let m={name:h,path:w.path,repo:w.repo,schema:v,documentKey:w.documentKey??"docId",pathKey:w.repo._pathKey??void 0,isGroup:!!w.repo._isGroup,parentKeys:i,createdKey:w.repo._createdKey??void 0,listColumns:w.listColumns,pageSize:w.pageSize,filterableFields:b,mutableFields:S,createFields:p,allowDelete:w.allowDelete??false,historyEnabled:!!w.repo.history,historySubcollection:(w.repo.history&&w.repo._historySubcollection)??void 0,relationalMeta:(()=>{if(!w.relationalFields||w.relationalFields.length===0)return;let a=w.repo.relationalKeys??{},d=[];for(let f of w.relationalFields){let k=a[f.key];k&&d.push({key:f.key,column:f.column,targetRepo:String(k.repo),targetKey:String(k.key),type:k.type});}return d.length>0?d:void 0})()};c[h]=m;}let y=xn(c,u),g=new se;if(o&&g.use(async(h,w,v)=>{let b=h,S=String(b.headers?.["content-type"]??"");if(S.includes("application/x-www-form-urlencoded")){let p=await Hr(b);h.body=Lr(p);}else if(S.includes("application/json")&&typeof b.body=="string")try{h.body=JSON.parse(b.body);}catch{}await v();}),r)if(fe(r)){for(let h of r.routes){let w=`${u}${h.path}`;h.method==="GET"?g.get(w,h.handler):g.post(w,h.handler);}g.use(r.middleware);}else if(typeof r=="function")g.use(r);else {let h=r.realm??"Admin",w="Basic "+Buffer.from(`${r.username}:${r.password}`).toString("base64");g.use((v,b,S)=>{if((v.headers?.authorization??"")!==w){b.status(401).set("WWW-Authenticate",`Basic realm="${h}"`).set("Content-Type","text/plain").send("Unauthorized");return}S();});}for(let h of s)g.use(h);g.get(`${u}/`,y.handleDashboard),g.get(`${u}`,y.handleDashboard),g.get(`${u}/:repoName/_panel`,y.handlePanel),g.post(`${u}/:repoName/_bulk/delete`,y.handleBulkDelete),g.post(`${u}/:repoName/_bulk/update`,y.handleBulkUpdate),g.get(`${u}/:repoName`,y.handleList),g.get(`${u}/:repoName/create`,y.handleCreateForm),g.post(`${u}/:repoName/create`,y.handleCreateSubmit),g.get(`${u}/:repoName/:id/edit`,y.handleEditForm),g.post(`${u}/:repoName/:id/edit`,y.handleEditSubmit),g.get(`${u}/:repoName/:id/history`,y.handleHistory),g.post(`${u}/:repoName/:id/delete`,y.handleDelete);let C=async(h,w)=>{await g.handle(h,w);};return l&&(C.httpsOptions=l),C}var kn="preserve";function Rn(){return kn}function Ur(e){return typeof e=="object"&&e!==null&&typeof e._seconds=="number"&&typeof e._nanoseconds=="number"}function Cn(e){if(e==null)return null;if(e instanceof Date)return Number.isNaN(e.getTime())?null:e;if(e instanceof Timestamp)return e.toDate();if(Ur(e))return new Date(e._seconds*1e3+Math.floor(e._nanoseconds/1e6));if(typeof e=="string"){let t=new Date(e);return Number.isNaN(t.getTime())?null:t}if(typeof e=="number"){let t=new Date(e);return Number.isNaN(t.getTime())?null:t}return null}function $n(e){return e}function Tt(e,t,n=200){let o=$n(t);e.status(n).set("Content-Type","application/json; charset=utf-8").send(JSON.stringify(o));}function Ie(e,t,n,o=200){Tt(e,{success:true,data:t,meta:n},o);}function L(e,t,n=400){Tt(e,{success:false,error:t},n);}function At(e,t,n,o,r){let s=ze(t,n),l=s.type==="index",u=l?424:500,y={success:false,error:l?s.message:r&&t instanceof Error?t.message:o};l&&(y.errorType="index",s.indexUrl&&(y.indexUrl=s.indexUrl)),Tt(e,y,u);}var An="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";function Vr(){let e="";for(let t=0;t<20;t++)e+=An.charAt(Math.floor(Math.random()*An.length));return e}function Ne(e){let t=e._def??e.def;if(!t)return e;let n=t.typeName??t.type;if(n==="ZodDate"||n==="date")return z$1.preprocess(o=>Cn(o)??o,e);if(n==="ZodObject"||n==="object"){let o=e.shape,r={};for(let[s,l]of Object.entries(o))r[s]=Ne(l);return z$1.object(r)}if(n==="ZodArray"||n==="array"){let o=t.element??t.type;if(o)return z$1.array(Ne(o))}if(n==="ZodOptional"||n==="optional"){let o=t.innerType;if(o)return Ne(o).optional()}if(n==="ZodNullable"||n==="nullable"){let o=t.innerType;if(o)return Ne(o).nullable()}if(n==="ZodDefault"||n==="default"){let o=t.innerType,r=t.defaultValue;if(o){let s=Ne(o);return typeof r=="function"?s.default(r()):s.default(r)}}return e}function Gr(e,t,n=[]){let o=e.shape,r={},s=t&&t.length>0?t:Object.keys(o);for(let l of s){if(n.includes(l))continue;let u=l.split(".")[0];u&&o[u]&&(r[u]=o[u]);}return z$1.object(r)}function Tn(e,t,n,o=false,r=[]){try{let s=Gr(e,n,r),l=o?s.partial():s;return {success:!0,data:(Rn()==="normalize"?Ne(l):l).parse(t)}}catch(s){return s instanceof z$1.ZodError?{success:false,error:`Validation failed: ${s.issues.map(u=>`${u.path.join(".")}: ${u.message}`).join(", ")}`}:{success:false,error:"Validation failed"}}}function Jr(e,t){let n=[],o=t?new Set(t):null,r={eq:"==",ne:"!=",lt:"<",lte:"<=",gt:">",gte:">=",in:"in",nin:"not-in",contains:"array-contains",containsAny:"array-contains-any"};for(let[s,l]of Object.entries(e)){if(l===void 0||["cursor","limit","pageSize","orderBy","orderDir","select"].includes(s))continue;let u=Array.isArray(l)?l[0]:l;if(u===void 0||u==="")continue;let c=s.match(/^(\w+)__(\w+)$/),y,g="==";if(c&&c[1]&&c[2]){y=c[1];let h=c[2];if(r[h])g=r[h];else continue}else if(!c)y=s;else continue;if(o&&!o.has(y))continue;let C=u;g==="in"||g==="not-in"||g==="array-contains-any"?C=u.split(",").map(h=>On(h.trim())):C=On(u),n.push({field:y,op:g,value:C});}return n}function On(e){if(e==="true")return true;if(e==="false")return false;if(e==="null")return null;let t=Number(e);return !isNaN(t)&&e!==""?t:e}function tt(e){return e?{docId:e.id}:null}async function En(e,t){if(!t||typeof t!="object")return;let n=t.docId;if(typeof n=="string")try{let o=e.repo.ref;if(typeof o.doc!="function")return;let r=await o.doc(n).get();return r.exists?r:void 0}catch{return}}function Pn(e,t,n,o=false){async function r(p,i,m,a){if(!o)return true;let d=i.rules?.[m];if(!d)return L(p,`Operation "${m}" is not allowed for this repository`,403),false;try{return await d(a)?!0:(L(p,"Forbidden",403),!1)}catch(f){let k=n&&f instanceof Error?f.message:"Forbidden";return L(p,k,403),false}}async function s(p,i,m,a){if(!o)return a;let d=p.rules?.filter;if(!d)return a;let f=[];for(let k of a)try{await d({user:i,doc:k,params:m})&&f.push(k);}catch{}return f}function l(p){return p?.user??null}function u(p,i){return !p||!e[p]?(L(i,`Repository "${p}" not found`,404),null):e[p]}function c(p,i){if(!i)return;let m=p[i];if(typeof m!="string"||!m)return;let a=m.split("/").filter(Boolean),d=[];for(let f=1;f<a.length;f+=2)d.push(a[f]);return d.length>0?d:void 0}async function y(p,i){let m=`by${p.documentKey.charAt(0).toUpperCase()}${p.documentKey.slice(1)}`,a=p.repo.get[m];if(typeof a=="function")try{let f=await a(i);if(f)return f}catch{}return (await p.repo.query.by({where:[[p.documentKey,"==",i]],limit:1}))[0]??null}async function g(p,i){let m=p.params||{},a=u(m.repoName,i);if(!a)return;let d=l(p);if(!await r(i,a,"list",{user:d,query:p.query??{},params:m}))return;let f=[],k;try{let x=p.query??{},$=Math.min(Number(x.pageSize)||a.pageSize,100),R=x.cursor,T=x.direction?.toLowerCase()==="prev"?"prev":"next",A=x.orderBy,E=x.orderDir?.toLowerCase()==="desc"?"desc":"asc",O=x.select,N=O?O.split(",").map(K=>K.trim()):void 0,j;a.allowedIncludes&&x.includes&&(j=(typeof x.includes=="string"?x.includes.split(",").map(U=>U.trim()):Array.isArray(x.includes)?x.includes:[]).filter(U=>typeof U=="string"&&a.allowedIncludes.includes(U)),j?.length===0&&(j=void 0));let I=Jr(x,a.filterableFields);f=I.map(K=>({field:K.field,op:K.op,value:String(K.value??"")})),A&&(k={field:A,dir:E});let P={pageSize:$,direction:T};if(R)try{let K=typeof R=="string"?JSON.parse(R):R;P.cursor=await En(a,K);}catch{}A&&(P.orderBy=[{field:A,direction:E}]),I.length>0&&(P.where=I.map(K=>[K.field,K.op,K.value])),N&&(P.select=N),j&&(P.include=j);let q=await a.repo.query.paginate(P),oe={items:await s(a,l(p),m,q.data),hasNextPage:q.hasNextPage,hasPrevPage:q.hasPrevPage,nextCursor:tt(q.nextCursor),prevCursor:tt(q.prevCursor)};Ie(i,oe,{pageSize:$,hasMore:q.hasNextPage});}catch(x){At(i,x,{ref:a.repo.ref,path:a.path,isGroup:!!a.isGroup,filters:f,sort:k},"Failed to fetch documents",n);}}async function C(p,i){let m=p.params||{},a=u(m.repoName,i);if(!a)return;let d=l(p);if(!await r(i,a,"list",{user:d,query:p.body??{},params:m}))return;let f=[],k;try{let x=p.body??{},$=Math.min(x.pageSize||a.pageSize,100),R=x.direction==="prev"?"prev":"next";x.where&&(f=x.where.map(N=>({field:String(N[0]),op:N[1],value:String(N[2]??"")}))),x.orderBy&&x.orderBy[0]&&(k={field:x.orderBy[0].field,dir:x.orderBy[0].direction==="desc"?"desc":"asc"});let T={pageSize:$,direction:R};if(x.cursor)try{let N=typeof x.cursor=="string"?JSON.parse(x.cursor):x.cursor;T.cursor=await En(a,N);}catch{}if(a.allowedIncludes&&x.includes&&x.includes.length>0){let N=x.includes.filter(j=>typeof j=="string"?a.allowedIncludes.includes(j):typeof j=="object"&&j!==null&&"relation"in j&&typeof j.relation=="string"?a.allowedIncludes.includes(j.relation):!1);N.length>0&&(T.include=N);}if(x.where&&x.where.length>0){if(a.filterableFields){let N=new Set(a.filterableFields),j=x.where.filter(I=>!N.has(I[0]));if(j.length>0){L(i,`Fields not filterable: ${j.map(I=>I[0]).join(", ")}`,400);return}}T.where=x.where;}if(x.orWhere&&x.orWhere.length>0){if(a.filterableFields){let N=new Set(a.filterableFields),j=x.orWhere.filter(I=>!N.has(I[0]));if(j.length>0){L(i,`Fields not filterable: ${j.map(I=>I[0]).join(", ")}`,400);return}}T.orWhere=x.orWhere;}if(x.orWhereGroups&&x.orWhereGroups.length>0){if(a.filterableFields){let N=new Set(a.filterableFields);for(let j of x.orWhereGroups){let I=j.filter(P=>!N.has(P[0]));if(I.length>0){L(i,`Fields not filterable: ${I.map(P=>P[0]).join(", ")}`,400);return}}}T.orWhereGroups=x.orWhereGroups;}x.orderBy&&x.orderBy.length>0&&(T.orderBy=x.orderBy),x.select&&x.select.length>0&&(T.select=x.select);let A=await a.repo.query.paginate(T),O={items:await s(a,l(p),m,A.data),hasNextPage:A.hasNextPage,hasPrevPage:A.hasPrevPage,nextCursor:tt(A.nextCursor),prevCursor:tt(A.prevCursor)};Ie(i,O,{pageSize:$,hasMore:A.hasNextPage});}catch(x){At(i,x,{ref:a.repo.ref,path:a.path,isGroup:!!a.isGroup,filters:f,sort:k},"Failed to query documents",n);}}async function h(p,i){let m=p.params||{},a=u(m.repoName,i);if(!a)return;let d=m.id;if(!d){L(i,"Document ID required",400);return}try{let f=await y(a,d);if(!f){L(i,"Document not found",404);return}let k=l(p);if(!await r(i,a,"get",{user:k,doc:f,params:m}))return;if(o&&a.rules?.filter)try{if(!await a.rules.filter({user:k,doc:f,params:m})){L(i,"Document not found",404);return}}catch{L(i,"Document not found",404);return}Ie(i,f);}catch(f){At(i,f,{ref:a.repo.ref,path:a.path,isGroup:!!a.isGroup,filters:[{field:a.documentKey,op:"==",value:d}]},"Failed to fetch document",n);}}async function w(p,i){let m=p.params||{},a=u(m.repoName,i);if(a)try{let d=p.body??{},f=l(p);if(!await r(i,a,"create",{user:f,body:d,params:m}))return;let k=Tn(a.schema,d,a.createFields,!1,a.systemKeys);if(!k.success){L(i,k.error,400);return}if(a.validate){let $=await a.validate(k.data,"create");if($){L(i,$,400);return}}let x;if(a.isGroup&&a.parentKeys&&a.parentKeys.length>0){let $={...k.data};a.createdKey&&($[a.createdKey]=new Date);let R=a.parentKeys.filter(E=>!$[E]);if(R.length>0){L(i,`Missing parent key(s) for subcollection create: ${R.join(", ")}`,400);return}let T=a.parentKeys.map(E=>$[E]),A=$[a.documentKey]||Vr();x=await a.repo.set(...T,A,$);}else x=await a.repo.create(k.data);Ie(i,x,void 0,201);}catch(d){let f=n&&d instanceof Error?d.message:"Failed to create document";L(i,f,500);}}async function v(p,i,m){let a=p.params||{},d=u(a.repoName,i);if(!d)return;let f=a.id;if(!f){L(i,"Document ID required",400);return}try{let k=p.body??{},x=await y(d,f);if(!x){L(i,"Document not found",404);return}let $=l(p);if(!await r(i,d,"update",{user:$,doc:x,body:k,params:a}))return;let R=Tn(d.schema,k,d.mutableFields,m,d.systemKeys);if(!R.success){L(i,R.error,400);return}if(d.validate){let E=await d.validate(R.data,"update");if(E){L(i,E,400);return}}let T=c(x,d.pathKey)??[f],A=await d.repo.update(...T,R.data);Ie(i,A);}catch(k){let x=n&&k instanceof Error?k.message:"Failed to update document";L(i,x,500);}}async function b(p,i){let m=p.params||{},a=u(m.repoName,i);if(!a)return;if(!a.allowDelete){L(i,"Delete not allowed for this repository",403);return}let d=m.id;if(!d){L(i,"Document ID required",400);return}try{let f=await y(a,d);if(!f){L(i,"Document not found",404);return}let k=l(p);if(!await r(i,a,"delete",{user:k,doc:f,params:m}))return;let x=c(f,a.pathKey)??[d];await a.repo.delete(...x),Ie(i,{deleted:!0});}catch(f){let k=n&&f instanceof Error?f.message:"Failed to delete document";L(i,k,500);}}function S(p,i){i.status(204).set("Access-Control-Allow-Methods","GET, POST, PUT, PATCH, DELETE, OPTIONS").set("Access-Control-Allow-Headers","Content-Type, Authorization").set("Access-Control-Max-Age","86400").send("");}return {handleList:g,handleQuery:C,handleGet:h,handleCreate:w,handleUpdate:v,handleDelete:b,handleOptions:S}}function Ot(e){try{return z$1.toJSONSchema(e,{target:"openapi-3.1",unrepresentable:"any",override:t=>{let n=t.zodSchema?._zod?.def;n&&(n.type==="date"?(t.jsonSchema.type="string",t.jsonSchema.format="date-time"):n.type==="bigint"&&(t.jsonSchema.type="string",t.jsonSchema.format="int64"));}})}catch(t){return typeof console<"u"&&console.warn&&console.warn("[generateOpenAPISpec] Failed to convert Zod schema to JSON Schema; falling back to {type:object}.",t),{type:"object"}}}function re(e){return {$ref:`#/components/schemas/${e}`}}function X(e){return {description:e,content:{"application/json":{schema:re("ErrorResponse")}}}}function Le(e,t){return {description:e,content:{"application/json":{schema:{type:"object",properties:{success:{type:"boolean",enum:[true]},data:t},required:["success","data"]}}}}}function In(e){return {description:"Paginated list of documents",content:{"application/json":{schema:{type:"object",properties:{success:{type:"boolean",enum:[true]},data:{type:"object",properties:{items:{type:"array",items:e},nextCursor:{oneOf:[{type:"object"},{type:"null"}]},prevCursor:{oneOf:[{type:"object"},{type:"null"}]},hasNextPage:{type:"boolean"},hasPrevPage:{type:"boolean"}},required:["items","hasNextPage","hasPrevPage"]},meta:{type:"object",properties:{pageSize:{type:"integer"},hasMore:{type:"boolean"},cursor:{oneOf:[{type:"string"},{type:"null"}]}}}},required:["success","data"]}}}}}function Wr(e){return [{name:"pageSize",in:"query",schema:{type:"integer",default:e.pageSize,maximum:100},description:"Number of items per page"},{name:"cursor",in:"query",schema:{type:"string"},description:"Base64 pagination cursor"},{name:"orderBy",in:"query",schema:{type:"string"},description:"Field name to order by"},{name:"orderDir",in:"query",schema:{type:"string",enum:["asc","desc"]},description:"Order direction"},{name:"select",in:"query",schema:{type:"string"},description:"Comma-separated list of fields to return"}]}function Qr(e){let t=e.filterableFields??Object.keys(e.schema.shape),n=["eq","ne","lt","lte","gt","gte","in","nin","contains"],o=[];for(let r of t){o.push({name:r,in:"query",schema:{type:"string"},description:`Filter by ${r} (equality)`});for(let s of n)o.push({name:`${r}__${s}`,in:"query",schema:{type:"string"},description:`Filter ${r} with operator ${s}`});}return o}function Xr(){return {type:"object",properties:{where:{type:"array",items:{type:"array",items:{},minItems:3,maxItems:3},description:"AND conditions: [field, operator, value][]"},orWhere:{type:"array",items:{type:"array",items:{},minItems:3,maxItems:3},description:"Simple OR conditions (each independently OR'd)"},orWhereGroups:{type:"array",items:{type:"array",items:{type:"array",items:{},minItems:3,maxItems:3}},description:"Advanced OR groups (AND within, OR across groups)"},orderBy:{type:"array",items:{type:"object",properties:{field:{type:"string"},direction:{type:"string",enum:["asc","desc"]}},required:["field"]}},select:{type:"array",items:{type:"string"},description:"Fields to select (projection)"},pageSize:{type:"integer",maximum:100,description:"Number of items per page"},cursor:{oneOf:[{type:"string"},{type:"object"}],description:"Pagination cursor"},direction:{type:"string",enum:["next","prev"],description:"Pagination direction"},includes:{type:"array",items:{oneOf:[{type:"string"},{type:"object",properties:{relation:{type:"string"},select:{type:"array",items:{type:"string"}}},required:["relation"]}]},description:"Relations to include (populate)"}}}}function Yr(e,t,n,o,r){let s={},l=e.name,u=`${t}/${e.name}`,c=`${u}/{${e.documentKey}}`,y={name:e.documentKey,in:"path",required:true,schema:{type:"string"},description:"Unique document identifier"};s[u]={get:{operationId:`list${xe(e.name)}`,summary:`List ${e.name} (paginated)`,tags:[l],parameters:[...Wr(e),...Qr(e)],responses:{200:In(re(n)),500:X("Internal server error")}},post:{operationId:`create${xe(e.name)}`,summary:`Create a ${ie(e.name)}`,tags:[l],requestBody:{required:true,content:{"application/json":{schema:re(o??n)}}},responses:{201:Le("Document created",re(n)),400:X("Validation error"),500:X("Internal server error")}}},s[`${u}/query`]={post:{operationId:`query${xe(e.name)}`,summary:`Query ${e.name} with advanced filters`,tags:[l],requestBody:{required:true,content:{"application/json":{schema:re("QueryRequestBody")}}},responses:{200:In(re(n)),400:X("Invalid query"),500:X("Internal server error")}}};let g={};return g.get={operationId:`get${xe(ie(e.name))}`,summary:`Get a single ${ie(e.name)}`,tags:[l],parameters:[y],responses:{200:Le("Document found",re(n)),404:X("Document not found"),500:X("Internal server error")}},g.put={operationId:`update${xe(ie(e.name))}`,summary:`Update a ${ie(e.name)} (full replace)`,tags:[l],parameters:[y],requestBody:{required:true,content:{"application/json":{schema:re(r??n)}}},responses:{200:Le("Document updated",re(n)),400:X("Validation error"),404:X("Document not found"),500:X("Internal server error")}},g.patch={operationId:`patch${xe(ie(e.name))}`,summary:`Partially update a ${ie(e.name)}`,tags:[l],parameters:[y],requestBody:{required:true,content:{"application/json":{schema:{allOf:[re(r??n)],description:"All fields are optional for partial updates"}}}},responses:{200:Le("Document patched",re(n)),400:X("Validation error"),404:X("Document not found"),500:X("Internal server error")}},e.allowDelete&&(g.delete={operationId:`delete${xe(ie(e.name))}`,summary:`Delete a ${ie(e.name)}`,tags:[l],parameters:[y],responses:{200:Le("Document deleted",{type:"object",properties:{id:{type:"string"}}}),404:X("Document not found"),500:X("Internal server error")}}),s[c]=g,s}function Pt(e,t,n={}){let{title:o="CRUD API",version:r="1.0.0",description:s,servers:l,auth:u=false}=n,c=t==="/"?"":t.replace(/\/$/,""),y={},g={},C=[];y.ErrorResponse={type:"object",properties:{success:{type:"boolean",enum:[false]},error:{type:"string"}},required:["success","error"]},y.QueryRequestBody=Xr();for(let[b,S]of Object.entries(e)){let p=xe(ie(b)),i=`${p}Create`,m=`${p}Update`;y[p]=Ot(S.schema);let a=R=>{let T=R&&R.length>0?R:Object.keys(S.schema.shape),A={};for(let E of T){let O=E.split(".")[0];O&&S.schema.shape[O]&&!S.systemKeys.includes(O)&&(A[O]=S.schema.shape[O]);}return A},d=null,f=a(S.createFields);Object.keys(f).length>0&&(y[i]=Ot(z$1.object(f)),d=i);let k=null,x=a(S.mutableFields);Object.keys(x).length>0&&(y[m]=Ot(z$1.object(x)),k=m);let $=Yr(S,c,p,d,k);Object.assign(g,$),C.push({name:b,description:`Operations on ${b} (collection: ${S.path})`});}let h={},w;return u==="basic"?(h.basicAuth={type:"http",scheme:"basic"},w=[{basicAuth:[]}]):u==="bearer"&&(h.bearerAuth={type:"http",scheme:"bearer",bearerFormat:"JWT"},w=[{bearerAuth:[]}]),{openapi:"3.1.0",info:{title:o,version:r,...s?{description:s}:{}},...l&&l.length>0?{servers:l}:{},paths:g,components:{schemas:y,...Object.keys(h).length>0?{securitySchemes:h}:{}},...w?{security:w}:{},tags:C}}function xe(e){return e.charAt(0).toUpperCase()+e.slice(1)}function ie(e){return e.endsWith("ies")?e.slice(0,-3)+"y":e.endsWith("ses")||e.endsWith("xes")||e.endsWith("zes")?e.slice(0,-2):e.endsWith("s")&&!e.endsWith("ss")?e.slice(0,-1):e}function eo(e,t){return `<!DOCTYPE html>
|
|
1154
1147
|
<html lang="en">
|
|
1155
1148
|
<head>
|
|
1156
1149
|
<meta charset="utf-8" />
|
|
@@ -1161,5 +1154,5 @@ function initColumnReorder(table) {
|
|
|
1161
1154
|
<script id="api-reference" data-url="${t}"></script>
|
|
1162
1155
|
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
|
|
1163
1156
|
</body>
|
|
1164
|
-
</html>`}async function to(e){return typeof e.rawBody=="string"?e.rawBody:Buffer.isBuffer(e.rawBody)?e.rawBody.toString("utf8"):""}function Nn(e){let{basePath:t="/",repos:n,parseBody:o=true,auth:r,middleware:
|
|
1157
|
+
</html>`}async function to(e){return typeof e.rawBody=="string"?e.rawBody:Buffer.isBuffer(e.rawBody)?e.rawBody.toString("utf8"):""}function Nn(e){let{basePath:t="/",repos:n,parseBody:o=true,auth:r,middleware:s=[],verbose:l=false,httpsOptions:u}=e,c=t==="/"?"":t.replace(/\/$/,""),y={};for(let[i,m]of Object.entries(n)){let a=m.schema??m.repo.schema??null;if(!a)throw new Error(`[createCrudServer] Repository "${i}" has no Zod schema. Either use createRepositoryConfig(schema)(config) or pass schema: explicitly.`);let d,f,k;if(m.fieldsConfig){let R=m.fieldsConfig;d=[],f=[],k=[];for(let[T,A]of Object.entries(R))for(let E of A)E==="filterable"?d.push(T):E==="mutable"?f.push(T):E==="create"&&k.push(T);d.length===0&&(d=void 0),f.length===0&&(f=void 0),k.length===0&&(k=void 0);}let x=(()=>{let R=m.repo._parentKeys;return R&&R.length>0?R:void 0})();if(x&&k)for(let R of x)k.includes(R)||k.push(R);let $={name:i,path:m.path,repo:m.repo,schema:a,systemKeys:m.repo._systemKeys??[m.documentKey??"docId"],documentKey:m.documentKey??"docId",pathKey:m.repo._pathKey??void 0,isGroup:!!m.repo._isGroup,parentKeys:x,createdKey:m.repo._createdKey??void 0,pageSize:m.pageSize??25,filterableFields:d,mutableFields:f,createFields:k,allowDelete:m.allowDelete??false,allowedIncludes:m.allowedIncludes,validate:m.validate,rules:m.rules};y[i]=$;}let C=Pn(y,c,l,!!r),h=e.openapi,w=h&&typeof h=="object"?h:{},v=null;function b(){if(!v){let i=r?fe(r)||typeof r=="function"?"bearer":"basic":false;v=Pt(y,c,{...w,auth:w.auth??i});}return v}let S=new se;if(S.use((i,m,a)=>{m.set("Access-Control-Allow-Origin","*"),m.set("Access-Control-Allow-Credentials","true"),a();}),o&&S.use(async(i,m,a)=>{let d=i;if(String(d.headers?.["content-type"]??"").includes("application/json")){if(typeof d.body=="string")try{i.body=JSON.parse(d.body);}catch{}else if(Buffer.isBuffer(i.rawBody))try{let k=await to(d);i.body=JSON.parse(k);}catch{}}await a();}),r)if(fe(r)){for(let i of r.routes){let m=`${c}${i.path}`;i.method==="GET"?S.get(m,i.handler):S.post(m,i.handler);}S.use(r.middleware);}else if(typeof r=="function")S.use(r);else {let i=r.realm??"API",m="Basic "+Buffer.from(`${r.username}:${r.password}`).toString("base64");S.use((a,d,f)=>{if((a.headers?.authorization??"")!==m){d.status(401).set("WWW-Authenticate",`Basic realm="${i}"`).set("Content-Type","application/json").send(JSON.stringify({success:false,error:"Unauthorized"}));return}f();});}for(let i of s)S.use(i);if(h!==false){let i=`${c}/__spec.json`,m=`${c}/__docs`;S.get(i,(a,d)=>{let f=b();d.status(200).set("Content-Type","application/json; charset=utf-8").send(JSON.stringify(f,null,2));}),S.get(m,(a,d)=>{let f=ee(a,c)+"/__spec.json",k=eo(w.title??"CRUD API",f);d.status(200).set("Content-Type","text/html; charset=utf-8").send(k);});}S.use((i,m,a)=>{if(i.method==="OPTIONS"){C.handleOptions(i,m);return}a();}),S.get(`${c}/:repoName`,C.handleList),S.post(`${c}/:repoName/query`,C.handleQuery),S.get(`${c}/:repoName/:id`,C.handleGet),S.post(`${c}/:repoName`,C.handleCreate),S.put(`${c}/:repoName/:id`,(i,m)=>C.handleUpdate(i,m,false)),S.patch(`${c}/:repoName/:id`,(i,m)=>C.handleUpdate(i,m,true)),S.delete(`${c}/:repoName/:id`,C.handleDelete);let p=async(i,m)=>{await S.handle(i,m);};return p.spec=b,u&&(p.httpsOptions=u),p}function _n(e,t){if(!t.onRequest)return e;let n=e.httpsOptions??t.httpsOptions;return n?t.onRequest(n,e):t.onRequest(e)}function Dn(e,t,n){let o={};for(let[r,s]of Object.entries(t)){if(!s)continue;let l=e[r];if(!l)throw new Error(`[createServers.${n}] Unknown repo "${r}" \u2014 not present in the registry passed to createServers().`);o[r]={...s,repo:l};}return o}function no(e,t={}){return {admin(n){let o=Dn(e,n.repos,"admin"),r=wn({...n,repos:o,httpsOptions:n.httpsOptions??t.httpsOptions});return _n(r,t)},crud(n){let o=Dn(e,n.repos,"crud"),r=Nn({...n,repos:o,httpsOptions:n.httpsOptions??t.httpsOptions});return _n(r,t)},sync(n){let o={...n};return t.onRequest&&o.admin&&!o.admin.onRequest&&(o.admin={...o.admin,onRequest:t.onRequest,httpsOptions:o.admin.httpsOptions??t.httpsOptions}),Qt(e,o)},history(n){return Zt(e,n)}}}export{jr as CSS,Ze as ClientScript,se as MiniRouter,no as createServers,vt as renderDashboard,ot as renderField,ye as renderForm,ve as renderFormPage,xt as renderList,qe as renderPage,ae as zodToFields};//# sourceMappingURL=index.js.map
|
|
1165
1158
|
//# sourceMappingURL=index.js.map
|