@lpdjs/firestore-repo-service 2.2.4 → 2.2.5
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 +40 -19
- package/dist/create-servers-D4-NGpKm.d.ts +105 -0
- package/dist/create-servers-DmggzSb3.d.cts +105 -0
- package/dist/{index-BiWZwHS_.d.ts → index-Cvip2Sgt.d.ts} +1 -1
- package/dist/{index-B3-vAYx0.d.cts → index-DpD4DEqH.d.cts} +1 -1
- package/dist/index.cjs +137 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +137 -47
- package/dist/index.js.map +1 -1
- package/dist/openapi-B3P2F8op.d.ts +69 -0
- package/dist/openapi-UJJ1aCFk.d.cts +69 -0
- package/dist/queue-D_-aMf4H.d.ts +52 -0
- package/dist/queue-Dk1Ezhkf.d.cts +52 -0
- package/dist/servers/admin/index.d.cts +1 -1
- package/dist/servers/admin/index.d.ts +1 -1
- package/dist/servers/crud/index.d.cts +5 -69
- package/dist/servers/crud/index.d.ts +5 -69
- package/dist/servers/index.cjs +157 -67
- package/dist/servers/index.cjs.map +1 -1
- package/dist/servers/index.d.cts +9 -4
- package/dist/servers/index.d.ts +9 -4
- package/dist/servers/index.js +157 -67
- 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 +33 -33
- package/dist/sync/index.cjs.map +1 -1
- package/dist/sync/index.d.cts +5 -107
- package/dist/sync/index.d.ts +5 -107
- package/dist/sync/index.js +33 -33
- package/dist/sync/index.js.map +1 -1
- package/dist/{types-BbCdscqh.d.cts → types-CX5AbZWV.d.cts} +1 -1
- package/dist/{types-BbCdscqh.d.ts → types-CX5AbZWV.d.ts} +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,94 @@
|
|
|
1
|
-
import {Timestamp}from'firebase-admin/firestore';import {z as z$1}from'zod';import {jsx,jsxs,Fragment}from'hono/jsx/jsx-runtime';import {renderToString}from'hono/jsx/dom/server';function an(e,t){let n=[];for(let r=0;r<e.length;r+=t)n.push(e.slice(r,r+t));return n}function ge(e,t){return t.orderBy&&t.orderBy.forEach(n=>{e=e.orderBy(String(n.field),n.direction??"asc");}),t.limit&&(e=e.limit(t.limit)),t.offset&&(e=e.offset(t.offset)),t.select&&t.select.length>0&&(e=e.select(...t.select.map(n=>String(n)))),t.startAt&&(e=Array.isArray(t.startAt)?e.startAt(...t.startAt):e.startAt(t.startAt)),t.startAfter&&(e=Array.isArray(t.startAfter)?e.startAfter(...t.startAfter):e.startAfter(t.startAfter)),t.endAt&&(e=Array.isArray(t.endAt)?e.endAt(...t.endAt):e.endAt(t.endAt)),t.endBefore&&(e=Array.isArray(t.endBefore)?e.endBefore(...t.endBefore):e.endBefore(t.endBefore)),e}function Ie(e){let[,t,n]=e;return (t==="in"||t==="array-contains-any")&&Array.isArray(n)&&n.length>30}function ft(e){let[t,n,r]=e;return Ie(e)?an(r,30).map(s=>[t,n,s]):[e]}function Oe(e,t){let n=e;for(let[r,o,s]of t)n=n.where(String(r),o,s);return n}async function yt(e){let t=await Promise.all(e.map(o=>o.get())),n=new Map;t.forEach(o=>{o.docs.forEach(s=>{n.has(s.id)||n.set(s.id,s);});});let r=t[0];if(!r)throw new Error("No snapshots returned");return {...r,docs:Array.from(n.values()),size:n.size,empty:n.size===0}}async function ae(e,t){let n=t.orWhere&&t.orWhere.length>0,r=t.orWhereGroups&&t.orWhereGroups.length>0;if(!n&&!r){if(!t.where||t.where.length===0)return ge(e,t).get();if(!t.where.some(Ie)){let m=Oe(e,t.where);return m=ge(m,t),m.get()}let i=t.where.map(ft),u=Ne(i).map(m=>{let c=Oe(e,m);return c=ge(c,t),c});return yt(u)}let o=t.where??[],s=[...t.orWhere?.map(d=>[d])??[],...t.orWhereGroups??[]],a=[];for(let d of s){let i=[...o,...d];if(i.some(Ie)){let u=i.map(ft),c=Ne(u).map(p=>{let y=Oe(e,p);return y=ge(y,t),y});a.push(...c);}else {let u=Oe(e,i);u=ge(u,t),a.push(u);}}return yt(a)}function Ne(e){if(e.length===0)return [[]];let t=e[0];if(e.length===1&&t)return t.map(s=>[s]);if(!t)return [[]];let n=e.slice(1),r=Ne(n),o=[];for(let s of t)for(let a of r)o.push([s,...a]);return o}var Fe="preserve";function ln(e){Fe=e;}function Ze(){return Fe}function cn(e){return typeof e=="object"&&e!==null&&typeof e._seconds=="number"&&typeof e._nanoseconds=="number"}function ze(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(cn(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 dn(e){if(typeof e!="object"||e===null)return false;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function Ae(e){if(e instanceof Timestamp)return e.toDate();if(Array.isArray(e))return e.map(t=>Ae(t));if(dn(e)){let t={};for(let[n,r]of Object.entries(e))t[n]=Ae(r);return t}return e}function _(e){return Fe==="normalize"?Ae(e):e}function gt(e,t){let n=[];for(let r=0;r<e.length;r+=t)n.push(e.slice(r,r+t));return n}function J(e){return e.charAt(0).toUpperCase()+e.slice(1)}function Y(e,t){return t.where&&t.where.forEach(([n,r,o])=>{e=e.where(String(n),r,o);}),t.orderBy&&t.orderBy.forEach(n=>{e=e.orderBy(String(n.field),n.direction??"asc");}),t.limit&&(e=e.limit(t.limit)),t.offset&&(e=e.offset(t.offset)),t.select&&t.select.length>0&&(e=e.select(...t.select.map(n=>String(n)))),t.startAt&&(e=Array.isArray(t.startAt)?e.startAt(...t.startAt):e.startAt(t.startAt)),t.startAfter&&(e=Array.isArray(t.startAfter)?e.startAfter(...t.startAfter):e.startAfter(t.startAfter)),t.endAt&&(e=Array.isArray(t.endAt)?e.endAt(...t.endAt):e.endAt(t.endAt)),t.endBefore&&(e=Array.isArray(t.endBefore)?e.endBefore(...t.endBefore):e.endBefore(t.endBefore)),e}async function $e(e,t){let n={...t,limit:t.pageSize+1};t.cursor&&(t.direction==="prev"?n.endBefore=t.cursor:n.startAfter=t.cursor);let o=(await ae(e,n)).docs,s=o.length>t.pageSize,a=s?o.slice(0,t.pageSize):o,d=a.map(l=>_({...l.data(),docId:l.id})),i=t.direction==="prev";return {data:d,nextCursor:i?a.length>0?a[a.length-1]:void 0:s?a[a.length-1]:void 0,prevCursor:i?s?a[0]:void 0:a[0],hasNextPage:i?!!t.cursor:s,hasPrevPage:i?s:!!t.cursor,pageSize:d.length}}async function*je(e,t){let n,r=true;for(;r;){let o=await $e(e,{...t,cursor:n,direction:"next"});yield o,r=o.hasNextPage,n=o.nextCursor;}}function ht(e){return {count:async(t={})=>{let n=e;return n=Y(n,t),(await n.count().get()).data().count},sum:async(t,n={})=>{let r=e;r=Y(r,n);let o=await r.get(),s=0;return o.forEach(a=>{let d=a.data()[t];typeof d=="number"&&(s+=d);}),s},average:async(t,n={})=>{let r=e;r=Y(r,n);let o=await r.get();if(o.empty)return null;let s=0,a=0;return o.forEach(d=>{let i=d.data()[t];typeof i=="number"&&(s+=i,a++);}),a>0?s/a:null}}}function bt(e,t,n,r,o,s){let a=()=>new Date;return {create:()=>{let d=e.batch();return {batch:d,set:(...i)=>{let l=i[i.length-1],u=typeof l=="object"&&l!==null&&"merge"in l,m=u?i[i.length-2]:i[i.length-1],c=u?i.slice(0,-2):i.slice(0,-1),p=u?l:{merge:true},y=t(...c),g={...m},f=c[c.length-1];n&&f&&(g[n]=f),r&&(g[r]=y.path),o&&(g[o]=a()),s&&(g[s]=a()),d.set(y,g,p);},update:(...i)=>{let l=i.pop(),m=t(...i),c={...l};s&&(c[s]=a()),d.update(m,c);},delete:(...i)=>{let l=t(...i);d.delete(l);},commit:async()=>{await d.commit();}}}}}function xt(e,t,n){let r=()=>new Date;return {set:async o=>{let s=e.bulkWriter(),a=0;for(let d of o){if(!d)continue;let{docRef:i,data:l,merge:u=true}=d,m={...l};t&&(m[t]=r()),n&&(m[n]=r()),s.set(i,m,{merge:u}),a++,a>=500&&(await s.flush(),a=0);}await s.close();},update:async o=>{let s=e.bulkWriter(),a=0;for(let d of o){if(!d)continue;let{docRef:i,data:l}=d,u={...l};n&&(u[n]=r()),s.update(i,u),a++,a>=500&&(await s.flush(),a=0);}await s.close();},delete:async o=>{let s=e.bulkWriter(),a=0;for(let d of o)d&&(s.delete(d),a++,a>=500&&(await s.flush(),a=0));await s.close();}}}function vt(e,t,n,r,o,s){let a=()=>new Date;return {create:async m=>{if(!e)throw new Error("Cannot use create() on collection groups. Use set() with a specific document ID instead.");let c,p,y={...m};if(o&&(y[o]=a()),s&&(y[s]=a()),m[n]){p=m[n],c=e.doc(p);let f=r?{...y,[r]:c.path}:y;await c.set(f);}else {c=await e.add(y),p=c.id;let f={[n]:p};r&&(f[r]=c.path),await c.update(f);}let g=await c.get();return _(g.data())},set:async(...m)=>{let c=m[m.length-1],p=typeof c=="object"&&c!==null&&"merge"in c,y=p?m[m.length-2]:m[m.length-1],g=p?m.slice(0,-2):m.slice(0,-1),f=p?c:{merge:true},b={...y};s&&(b[s]=a());let x=t(...g),h=g[g.length-1];n&&h!=null&&(b[n]=h),r&&(b[r]=x.path),await x.set(b,f);let v=await x.get();return _(v.data())},update:async(...m)=>{let c=m.pop(),p=m,y={...c};s&&(y[s]=a());let g=t(...p);await g.update(y);let f=await g.get();return _(f.data())},delete:async(...m)=>{await t(...m).delete();}}}function Rt(e,t,n,r,o){let s={};return s.byList=async(a,d,i="in",l={})=>{if(d.length===0)return [];let u=[],m=gt(d,30);for(let c of m){let p=e;p=p.where(a,i,c),l.select&&l.select.length>0&&(p=p.select(...l.select.map(g=>String(g)))),(await p.get()).forEach(g=>{let f=_(g.data());u.push(l.returnDoc?{data:f,doc:g}:f);});}return u},t.forEach(a=>{let d=`by${J(String(a))}`;s[d]=async(i,l={})=>{let u=typeof l=="boolean"?{returnDoc:l}:l;if(String(a)===o){let f=await r(i).get();if(!f.exists)return null;let b=_(f.data());return u.returnDoc?{data:b,doc:f}:b}let m=e;m=m.where(String(a),"==",i).limit(1),u.select&&u.select.length>0&&(m=m.select(...u.select.map(g=>String(g))));let c=await m.get();if(c.empty)return null;let p=c.docs[0];if(!p)return null;let y=_(p.data());return u.returnDoc?{data:y,doc:p}:y};}),s}function wt(e,t,n,r){let o={},s=async(a,d)=>{if(!n||!r||d.length===0)return a;let i=d.map(l=>typeof l=="string"?{key:l}:{key:l.relation,select:l.select});return Promise.all(a.map(async l=>{let u=await Promise.all(i.map(async({key:c,select:p})=>{let y=n[c];if(!y)return [c,void 0];let g=r[y.repo];if(!g)return [c,void 0];let f=l[c];if(f==null)return [c,y.type==="one"?null:[]];let b=p?{select:p}:void 0;try{if(y.type==="one"){let x=`by${J(y.key)}`,h=typeof g.get?.[x]=="function"?await g.get[x](f,b):null;return [c,h]}else {let x=`by${J(y.key)}`,h=typeof g.query?.[x]=="function"?await g.query[x](f,b):[];return [c,h]}}catch(x){return console.error(`[include] Error populating "${c}":`,x),[c,y.type==="one"?null:[]]}})),m={};for(let[c,p]of u)c!==void 0&&(m[c]=p);return {...l,populated:m}}))};return t.forEach(a=>{let d=`by${J(a)}`;o[d]=async(i,l={})=>{let u={...l,where:[[a,"==",i],...l.where??[]]};return (await ae(e,u)).docs.map(c=>_(c.data()))};}),o.by=async a=>(await ae(e,a)).docs.map(i=>_(i.data())),o.getAll=async(a={})=>(await ae(e,a)).docs.map(i=>_(i.data())),o.onSnapshot=(a,d,i)=>Y(e,a).onSnapshot(u=>{d(u.docs.map(m=>_(m.data())));},i),o.paginate=async a=>{let{include:d,...i}=a,l=await $e(e,i);if(d&&d.length>0){let u=await s(l.data,d);return {...l,data:u}}return l},o.paginateAll=async function*(a){let{include:d,...i}=a;for await(let l of je(e,i))if(d&&d.length>0){let u=await s(l.data,d);yield {...l,data:u};}else yield l;},o}function Tt(e,t){return {populate:async(n,r)=>{if(!e.relationalKeys)return {...n,populated:{}};let o,s={};if(typeof r=="object"&&!Array.isArray(r))if("relation"in r){let i=r;o=[i.relation],i.select&&(s[i.relation]=i.select);}else if("relations"in r){let i=r;o=Array.isArray(i.relations)?i.relations:[i.relations],s=i.select??{};}else o=[];else o=Array.isArray(r)?r:[r];let a=await Promise.all(o.map(async i=>{let l=e.relationalKeys?.[i];if(!l)return console.warn(`[populate] Relation "${i}" not found in config`),[i,void 0];let u=t[l.repo];if(!u)return console.warn(`[populate] Repository "${l.repo}" not found in mapping`),[i,void 0];let m=n[i];if(m==null)return [i,l.type==="one"?null:[]];let c=s[i],p=c?{select:c}:void 0;try{if(l.type==="one"){let y=`by${J(l.key)}`,g=typeof u.get?.[y]=="function"?await u.get[y](m,p):null;return [i,g]}else {let y=`by${J(l.key)}`,g=typeof u.query?.[y]=="function"?await u.query[y](m,p):[];return [i,g]}}catch(y){return console.error(`[populate] Error populating "${i}":`,y),[i,l.type==="one"?null:[]]}})),d={};for(let[i,l]of a)l!==void 0&&(d[i]=l);return {...n,populated:d}}}}function St(e,t){return {run:async n=>e.runTransaction(async r=>n({get:async(...s)=>{let a=t(...s),d=await r.get(a);return d.exists?_({...d.data(),docId:d.id}):null},set:(...s)=>{let a=s[s.length-1],d=typeof a=="object"&&a!==null&&"merge"in a,i=d?s[s.length-2]:s[s.length-1],l=d?s.slice(0,-2):s.slice(0,-1),u=d?a:{merge:true},m=t(...l);r.set(m,i,u);},update:(...s)=>{let a=s[s.length-1],d=s.slice(0,-1),i=t(...d);r.update(i,a);},delete:(...s)=>{let a=t(...s);r.delete(a);},raw:r}))}}function un(e){if(typeof e!="function")return [];let n=e.toString().match(/^\s*(?:function\s*\w*\s*)?\(([^)]*)\)/);if(!n?.[1])return [];let r=n[1].split(",").map(o=>o.trim().replace(/\s*[:=].*$/,"").trim()).filter(Boolean);return r.length<=2?[]:r.slice(1,-1)}function Me(e,t,n={}){let r=t.isGroup?e.collectionGroup(t.path):e.collection(t.path),o=t.isGroup?null:e.collection(t.path),s=(...y)=>t.refCb(e,...y),a=Rt(r,t.foreignKeys,o,s,t.documentKey),d=wt(r,t.queryKeys,t.relationalKeys,n),i=ht(r),l=vt(o,s,t.documentKey,t.pathKey,t.createdKey,t.updatedKey),u=bt(e,s,t.documentKey,t.pathKey,t.createdKey,t.updatedKey),m=St(e,s),c=xt(e,t.createdKey,t.updatedKey),p=Tt(t,n);return {ref:r,documentRef:s,get:a,query:d,aggregate:i,...l,batch:u,transaction:m,bulk:c,...p,schema:t.schema,relationalKeys:t.relationalKeys,_systemKeys:[t.documentKey,t.pathKey,t.createdKey,t.updatedKey].filter(y=>typeof y=="string"),_pathKey:t.pathKey??null,_isGroup:!!t.isGroup,_parentKeys:t.isGroup?un(t.refCb):[],_createdKey:t.createdKey??null}}var pn={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 Z(e){let t=e,n=t._zod?.def?.type;if(n)return pn[n]??`Zod${n.charAt(0).toUpperCase()}${n.slice(1)}`;let r=t._def?.typeName;return r||""}function K(e){let t=e;if(t._zod?.def?.innerType)return t._zod.def.innerType;if(t._def?.innerType)return t._def.innerType}function Ct(e){let t=e;if(t._zod?.def?.element)return t._zod.def.element;if(t._def?.type)return t._def.type}function Ot(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 he(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 be(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 xe(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 ke(e){let t=e;return Array.isArray(t._zod?.def?.values)?t._zod.def.values[0]:t._def?.value}function At(e){let t=e,n=[],r=t._zod?.def?.checks;if(Array.isArray(r)){for(let s of r)s.format&&n.push(s.format);if(n.length>0)return n}let o=t._def?.checks;if(Array.isArray(o))for(let s of o)s.kind&&n.push(s.kind);return n}function fn(e){return e.replace(/([A-Z])/g," $1").replace(/_/g," ").replace(/^\s/,"").replace(/^./,t=>t.toUpperCase())}function $t(e){let t=e,n=true,r=false,o;for(;;){let s=Z(t);if(s==="ZodOptional")n=false,t=K(t);else if(s==="ZodNullable")n=false,r=true,t=K(t);else if(s==="ZodDefault")n=false,o=Ot(t),t=K(t);else break}return {inner:t,required:n,nullable:r,defaultValue:o}}function W(e,t=""){if(Z(e)==="ZodObject"){let r=he(e);return Object.entries(r).map(([o,s])=>kt(t?`${t}.${o}`:o,o,s))}return [kt(t||"value",t||"value",e)]}function kt(e,t,n){let{inner:r,required:o,nullable:s,defaultValue:a}=$t(n),d=Z(r),i=fn(t.split(".").pop()??t);switch(d){case "ZodString":{let l=At(r),u=l.includes("email"),m=l.includes("url");return {name:e,label:i,type:"text",required:o,nullable:s,defaultValue:a,hint:u?"email":m?"url":void 0}}case "ZodNumber":case "ZodBigInt":return {name:e,label:i,type:"number",required:o,nullable:s,defaultValue:a};case "ZodBoolean":return {name:e,label:i,type:"checkbox",required:o,nullable:s,defaultValue:a};case "ZodDate":case "ZodCoerce":return {name:e,label:i,type:"datetime-local",required:o,nullable:s,defaultValue:a};case "ZodEnum":{let l=be(r);return {name:e,label:i,type:"select",required:o,nullable:s,defaultValue:a,options:l}}case "ZodNativeEnum":{let l=xe(r),u=Object.values(l).filter(m=>typeof m=="string");return {name:e,label:i,type:"select",required:o,nullable:s,defaultValue:a,options:u}}case "ZodLiteral":{let l=String(ke(r)??"");return {name:e,label:i,type:"select",required:o,nullable:s,defaultValue:a,options:[l]}}case "ZodObject":{let l=W(r,e);return {name:e,label:i,type:"textarea",required:o,nullable:s,defaultValue:a,nested:l,hint:"JSON object"}}case "ZodArray":{let l=Ct(r);if(!l)return {name:e,label:i,type:"textarea",required:o,nullable:s,defaultValue:a,hint:"JSON array"};let{inner:u}=$t(l),m=Z(u),c,p,y;switch(m){case "ZodString":c="text";break;case "ZodNumber":case "ZodBigInt":c="number";break;case "ZodBoolean":c="checkbox";break;case "ZodDate":c="datetime-local";break;case "ZodEnum":c="select",p=be(u);break;case "ZodNativeEnum":c="select",p=Object.values(xe(u)).filter(g=>typeof g=="string");break;case "ZodObject":c="object",y=W(u);break;default:return {name:e,label:i,type:"textarea",required:o,nullable:s,defaultValue:a,hint:"JSON array"}}return {name:e,label:i,type:"textarea",required:o,nullable:s,defaultValue:a,arrayElementType:c,arrayElementOptions:p,arrayElementFields:y}}default:return {name:e,label:i,type:"textarea",required:o,nullable:s,defaultValue:a,hint:"JSON"}}}function Be(e,t=0){let n=t>0?`ml-${t*4}`:"",r=`field_${e.name.replace(/\./g,"__")}`,o=e.name,s=e.required?" required":"",a=e.defaultValue==="__null__",d=!a&&e.defaultValue!=null?String(e.defaultValue):"",i=e.nullable&&e.type!=="checkbox"?`<span class="flex items-center gap-1 shrink-0">
|
|
1
|
+
import {Timestamp}from'firebase-admin/firestore';import {z}from'zod';import {jsx,jsxs,Fragment}from'hono/jsx/jsx-runtime';import {renderToString}from'hono/jsx/dom/server';function kn(e,t){let n=[];for(let r=0;r<e.length;r+=t)n.push(e.slice(r,r+t));return n}function we(e,t){return t.orderBy&&t.orderBy.forEach(n=>{e=e.orderBy(String(n.field),n.direction??"asc");}),t.limit&&(e=e.limit(t.limit)),t.offset&&(e=e.offset(t.offset)),t.select&&t.select.length>0&&(e=e.select(...t.select.map(n=>String(n)))),t.startAt&&(e=Array.isArray(t.startAt)?e.startAt(...t.startAt):e.startAt(t.startAt)),t.startAfter&&(e=Array.isArray(t.startAfter)?e.startAfter(...t.startAfter):e.startAfter(t.startAfter)),t.endAt&&(e=Array.isArray(t.endAt)?e.endAt(...t.endAt):e.endAt(t.endAt)),t.endBefore&&(e=Array.isArray(t.endBefore)?e.endBefore(...t.endBefore):e.endBefore(t.endBefore)),e}function qe(e){let[,t,n]=e;return (t==="in"||t==="array-contains-any")&&Array.isArray(n)&&n.length>30}function wt(e){let[t,n,r]=e;return qe(e)?kn(r,30).map(s=>[t,n,s]):[e]}function Ie(e,t){let n=e;for(let[r,o,s]of t)n=n.where(String(r),o,s);return n}async function St(e){let t=await Promise.all(e.map(o=>o.get())),n=new Map;t.forEach(o=>{o.docs.forEach(s=>{n.has(s.id)||n.set(s.id,s);});});let r=t[0];if(!r)throw new Error("No snapshots returned");return {...r,docs:Array.from(n.values()),size:n.size,empty:n.size===0}}async function ue(e,t){let n=t.orWhere&&t.orWhere.length>0,r=t.orWhereGroups&&t.orWhereGroups.length>0;if(!n&&!r){if(!t.where||t.where.length===0)return we(e,t).get();if(!t.where.some(qe)){let h=Ie(e,t.where);return h=we(h,t),h.get()}let i=t.where.map(wt),y=Qe(i).map(h=>{let c=Ie(e,h);return c=we(c,t),c});return St(y)}let o=t.where??[],s=[...t.orWhere?.map(u=>[u])??[],...t.orWhereGroups??[]],a=[];for(let u of s){let i=[...o,...u];if(i.some(qe)){let y=i.map(wt),c=Qe(y).map(d=>{let p=Ie(e,d);return p=we(p,t),p});a.push(...c);}else {let y=Ie(e,i);y=we(y,t),a.push(y);}}return St(a)}function Qe(e){if(e.length===0)return [[]];let t=e[0];if(e.length===1&&t)return t.map(s=>[s]);if(!t)return [[]];let n=e.slice(1),r=Qe(n),o=[];for(let s of t)for(let a of r)o.push([s,...a]);return o}var Ue="preserve";function An(e){Ue=e;}function Le(){return Ue}function Pn(e){return typeof e=="object"&&e!==null&&typeof e._seconds=="number"&&typeof e._nanoseconds=="number"}function Ge(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(Pn(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 En(e){if(typeof e!="object"||e===null)return false;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function Ne(e){if(e instanceof Timestamp)return e.toDate();if(Array.isArray(e))return e.map(t=>Ne(t));if(En(e)){let t={};for(let[n,r]of Object.entries(e))t[n]=Ne(r);return t}return e}function F(e){return Ue==="normalize"?Ne(e):e}function Ct(e,t){let n=[];for(let r=0;r<e.length;r+=t)n.push(e.slice(r,r+t));return n}function ee(e){return e.charAt(0).toUpperCase()+e.slice(1)}function ne(e,t){return t.where&&t.where.forEach(([n,r,o])=>{e=e.where(String(n),r,o);}),t.orderBy&&t.orderBy.forEach(n=>{e=e.orderBy(String(n.field),n.direction??"asc");}),t.limit&&(e=e.limit(t.limit)),t.offset&&(e=e.offset(t.offset)),t.select&&t.select.length>0&&(e=e.select(...t.select.map(n=>String(n)))),t.startAt&&(e=Array.isArray(t.startAt)?e.startAt(...t.startAt):e.startAt(t.startAt)),t.startAfter&&(e=Array.isArray(t.startAfter)?e.startAfter(...t.startAfter):e.startAfter(t.startAfter)),t.endAt&&(e=Array.isArray(t.endAt)?e.endAt(...t.endAt):e.endAt(t.endAt)),t.endBefore&&(e=Array.isArray(t.endBefore)?e.endBefore(...t.endBefore):e.endBefore(t.endBefore)),e}async function _e(e,t){let n={...t,limit:t.pageSize+1};t.cursor&&(t.direction==="prev"?n.endBefore=t.cursor:n.startAfter=t.cursor);let o=(await ue(e,n)).docs,s=o.length>t.pageSize,a=s?o.slice(0,t.pageSize):o,u=a.map(l=>F({...l.data(),docId:l.id})),i=t.direction==="prev";return {data:u,nextCursor:i?a.length>0?a[a.length-1]:void 0:s?a[a.length-1]:void 0,prevCursor:i?s?a[0]:void 0:a[0],hasNextPage:i?!!t.cursor:s,hasPrevPage:i?s:!!t.cursor,pageSize:u.length}}async function*He(e,t){let n,r=true;for(;r;){let o=await _e(e,{...t,cursor:n,direction:"next"});yield o,r=o.hasNextPage,n=o.nextCursor;}}function $t(e){return {count:async(t={})=>{let n=e;return n=ne(n,t),(await n.count().get()).data().count},sum:async(t,n={})=>{let r=e;r=ne(r,n);let o=await r.get(),s=0;return o.forEach(a=>{let u=a.data()[t];typeof u=="number"&&(s+=u);}),s},average:async(t,n={})=>{let r=e;r=ne(r,n);let o=await r.get();if(o.empty)return null;let s=0,a=0;return o.forEach(u=>{let i=u.data()[t];typeof i=="number"&&(s+=i,a++);}),a>0?s/a:null}}}function Ot(e,t,n,r,o,s){let a=()=>new Date;return {create:()=>{let u=e.batch();return {batch:u,set:(...i)=>{let l=i[i.length-1],y=typeof l=="object"&&l!==null&&"merge"in l,h=y?i[i.length-2]:i[i.length-1],c=y?i.slice(0,-2):i.slice(0,-1),d=y?l:{merge:true},p=t(...c),m={...h},f=c[c.length-1];n&&f&&(m[n]=f),r&&(m[r]=p.path),o&&(m[o]=a()),s&&(m[s]=a()),u.set(p,m,d);},update:(...i)=>{let l=i.pop(),h=t(...i),c={...l};s&&(c[s]=a()),u.update(h,c);},delete:(...i)=>{let l=t(...i);u.delete(l);},commit:async()=>{await u.commit();}}}}}function kt(e,t,n){let r=()=>new Date;return {set:async o=>{let s=e.bulkWriter(),a=0;for(let u of o){if(!u)continue;let{docRef:i,data:l,merge:y=true}=u,h={...l};t&&(h[t]=r()),n&&(h[n]=r()),s.set(i,h,{merge:y}),a++,a>=500&&(await s.flush(),a=0);}await s.close();},update:async o=>{let s=e.bulkWriter(),a=0;for(let u of o){if(!u)continue;let{docRef:i,data:l}=u,y={...l};n&&(y[n]=r()),s.update(i,y),a++,a>=500&&(await s.flush(),a=0);}await s.close();},delete:async o=>{let s=e.bulkWriter(),a=0;for(let u of o)u&&(s.delete(u),a++,a>=500&&(await s.flush(),a=0));await s.close();}}}function At(e,t,n,r,o,s){let a=()=>new Date;return {create:async h=>{if(!e)throw new Error("Cannot use create() on collection groups. Use set() with a specific document ID instead.");let c,d,p={...h};if(o&&(p[o]=a()),s&&(p[s]=a()),h[n]){d=h[n],c=e.doc(d);let f=r?{...p,[r]:c.path}:p;await c.set(f);}else {c=await e.add(p),d=c.id;let f={[n]:d};r&&(f[r]=c.path),await c.update(f);}let m=await c.get();return F(m.data())},set:async(...h)=>{let c=h[h.length-1],d=typeof c=="object"&&c!==null&&"merge"in c,p=d?h[h.length-2]:h[h.length-1],m=d?h.slice(0,-2):h.slice(0,-1),f=d?c:{merge:true},v={...p};s&&(v[s]=a());let g=t(...m),b=m[m.length-1];n&&b!=null&&(v[n]=b),r&&(v[r]=g.path),await g.set(v,f);let R=await g.get();return F(R.data())},update:async(...h)=>{let c=h.pop(),d=h,p={...c};s&&(p[s]=a());let m=t(...d);await m.update(p);let f=await m.get();return F(f.data())},delete:async(...h)=>{await t(...h).delete();}}}function Pt(e,t,n,r,o){let s={};return s.byList=async(a,u,i="in",l={})=>{if(u.length===0)return [];let y=[],h=Ct(u,30);for(let c of h){let d=e;d=d.where(a,i,c),l.select&&l.select.length>0&&(d=d.select(...l.select.map(m=>String(m)))),(await d.get()).forEach(m=>{let f=F(m.data());y.push(l.returnDoc?{data:f,doc:m}:f);});}return y},t.forEach(a=>{let u=`by${ee(String(a))}`;s[u]=async(i,l={})=>{let y=typeof l=="boolean"?{returnDoc:l}:l;if(String(a)===o){let f=await r(i).get();if(!f.exists)return null;let v=F(f.data());return y.returnDoc?{data:v,doc:f}:v}let h=e;h=h.where(String(a),"==",i).limit(1),y.select&&y.select.length>0&&(h=h.select(...y.select.map(m=>String(m))));let c=await h.get();if(c.empty)return null;let d=c.docs[0];if(!d)return null;let p=F(d.data());return y.returnDoc?{data:p,doc:d}:p};}),s}function Et(e,t,n,r){let o={},s=async(a,u)=>{if(!n||!r||u.length===0)return a;let i=u.map(l=>typeof l=="string"?{key:l}:{key:l.relation,select:l.select});return Promise.all(a.map(async l=>{let y=await Promise.all(i.map(async({key:c,select:d})=>{let p=n[c];if(!p)return [c,void 0];let m=r[p.repo];if(!m)return [c,void 0];let f=l[c];if(f==null)return [c,p.type==="one"?null:[]];let v=d?{select:d}:void 0;try{if(p.type==="one"){let g=`by${ee(p.key)}`,b=typeof m.get?.[g]=="function"?await m.get[g](f,v):null;return [c,b]}else {let g=`by${ee(p.key)}`,b=typeof m.query?.[g]=="function"?await m.query[g](f,v):[];return [c,b]}}catch(g){return console.error(`[include] Error populating "${c}":`,g),[c,p.type==="one"?null:[]]}})),h={};for(let[c,d]of y)c!==void 0&&(h[c]=d);return {...l,populated:h}}))};return t.forEach(a=>{let u=`by${ee(a)}`;o[u]=async(i,l={})=>{let y={...l,where:[[a,"==",i],...l.where??[]]};return (await ue(e,y)).docs.map(c=>F(c.data()))};}),o.by=async a=>(await ue(e,a)).docs.map(i=>F(i.data())),o.getAll=async(a={})=>(await ue(e,a)).docs.map(i=>F(i.data())),o.onSnapshot=(a,u,i)=>ne(e,a).onSnapshot(y=>{u(y.docs.map(h=>F(h.data())));},i),o.paginate=async a=>{let{include:u,...i}=a,l=await _e(e,i);if(u&&u.length>0){let y=await s(l.data,u);return {...l,data:y}}return l},o.paginateAll=async function*(a){let{include:u,...i}=a;for await(let l of He(e,i))if(u&&u.length>0){let y=await s(l.data,u);yield {...l,data:y};}else yield l;},o}function Dt(e,t){return {populate:async(n,r)=>{if(!e.relationalKeys)return {...n,populated:{}};let o,s={};if(typeof r=="object"&&!Array.isArray(r))if("relation"in r){let i=r;o=[i.relation],i.select&&(s[i.relation]=i.select);}else if("relations"in r){let i=r;o=Array.isArray(i.relations)?i.relations:[i.relations],s=i.select??{};}else o=[];else o=Array.isArray(r)?r:[r];let a=await Promise.all(o.map(async i=>{let l=e.relationalKeys?.[i];if(!l)return console.warn(`[populate] Relation "${i}" not found in config`),[i,void 0];let y=t[l.repo];if(!y)return console.warn(`[populate] Repository "${l.repo}" not found in mapping`),[i,void 0];let h=n[i];if(h==null)return [i,l.type==="one"?null:[]];let c=s[i],d=c?{select:c}:void 0;try{if(l.type==="one"){let p=`by${ee(l.key)}`,m=typeof y.get?.[p]=="function"?await y.get[p](h,d):null;return [i,m]}else {let p=`by${ee(l.key)}`,m=typeof y.query?.[p]=="function"?await y.query[p](h,d):[];return [i,m]}}catch(p){return console.error(`[populate] Error populating "${i}":`,p),[i,l.type==="one"?null:[]]}})),u={};for(let[i,l]of a)l!==void 0&&(u[i]=l);return {...n,populated:u}}}}function It(e,t){return {run:async n=>e.runTransaction(async r=>n({get:async(...s)=>{let a=t(...s),u=await r.get(a);return u.exists?F({...u.data(),docId:u.id}):null},set:(...s)=>{let a=s[s.length-1],u=typeof a=="object"&&a!==null&&"merge"in a,i=u?s[s.length-2]:s[s.length-1],l=u?s.slice(0,-2):s.slice(0,-1),y=u?a:{merge:true},h=t(...l);r.set(h,i,y);},update:(...s)=>{let a=s[s.length-1],u=s.slice(0,-1),i=t(...u);r.update(i,a);},delete:(...s)=>{let a=t(...s);r.delete(a);},raw:r}))}}function Dn(e){if(typeof e!="function")return [];let n=e.toString().match(/^\s*(?:function\s*\w*\s*)?\(([^)]*)\)/);if(!n?.[1])return [];let r=n[1].split(",").map(o=>o.trim().replace(/\s*[:=].*$/,"").trim()).filter(Boolean);return r.length<=2?[]:r.slice(1,-1)}function We(e,t,n={}){let r=t.isGroup?e.collectionGroup(t.path):e.collection(t.path),o=t.isGroup?null:e.collection(t.path),s=(...p)=>t.refCb(e,...p),a=Pt(r,t.foreignKeys,o,s,t.documentKey),u=Et(r,t.queryKeys,t.relationalKeys,n),i=$t(r),l=At(o,s,t.documentKey,t.pathKey,t.createdKey,t.updatedKey),y=Ot(e,s,t.documentKey,t.pathKey,t.createdKey,t.updatedKey),h=It(e,s),c=kt(e,t.createdKey,t.updatedKey),d=Dt(t,n);return {ref:r,documentRef:s,get:a,query:u,aggregate:i,...l,batch:y,transaction:h,bulk:c,...d,schema:t.schema,relationalKeys:t.relationalKeys,_systemKeys:[t.documentKey,t.pathKey,t.createdKey,t.updatedKey].filter(p=>typeof p=="string"),_pathKey:t.pathKey??null,_isGroup:!!t.isGroup,_parentKeys:t.isGroup?Dn(t.refCb):[],_createdKey:t.createdKey??null}}function In(e){let t=[],n=e.replace(/[.*+?^${}()|[\]\\]/g,r=>r===":"?r:`\\${r}`).replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g,(r,o)=>(t.push(o),"([^/]+)"));return {pattern:new RegExp(`^${n}$`),paramNames:t}}function Nn(e){let t=e.path??e.url??"/",n=t.indexOf("?");return n===-1?t:t.slice(0,n)}var G=class{constructor(){this.routes=[];this.middlewares=[];this.notFoundHandler=(t,n)=>{n.status(404).send("Not Found");};this.errorHandler=(t,n,r)=>{console.error("[MiniRouter]",t),r.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,r){let{pattern:o,paramNames:s}=In(n);return this.routes.push({method:t.toUpperCase(),pattern:o,paramNames:s,handler:r}),this}async handle(t,n){let r=(t.method??"GET").toUpperCase(),o=Nn(t),s=null,a={};for(let l of this.routes){if(l.method!==r)continue;let y=o.match(l.pattern);if(y){s=l,a={},l.paramNames.forEach((h,c)=>{a[h]=decodeURIComponent(y[c+1]??"");});break}}let u=Object.assign(t,{params:a}),i=s?s.handler:this.notFoundHandler;try{await this.runMiddlewareChain(u,n,i);}catch(l){this.errorHandler(l,t,n);}}async runMiddlewareChain(t,n,r){let o=0,s=async()=>{if(o<this.middlewares.length){let a=this.middlewares[o++];await a(t,n,s);}else await r(t,n);};await s();}};var _n={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 j(e){let t=e,n=t._zod?.def?.type;if(n)return _n[n]??`Zod${n.charAt(0).toUpperCase()}${n.slice(1)}`;let r=t._def?.typeName;return r||""}function q(e){let t=e;if(t._zod?.def?.innerType)return t._zod.def.innerType;if(t._def?.innerType)return t._def.innerType}function Nt(e){let t=e;if(t._zod?.def?.element)return t._zod.def.element;if(t._def?.type)return t._def.type}function _t(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 re(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 Se(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 Te(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 je(e){let t=e;return Array.isArray(t._zod?.def?.values)?t._zod.def.values[0]:t._def?.value}function jt(e){let t=e,n=[],r=t._zod?.def?.checks;if(Array.isArray(r)){for(let s of r)s.format&&n.push(s.format);if(n.length>0)return n}let o=t._def?.checks;if(Array.isArray(o))for(let s of o)s.kind&&n.push(s.kind);return n}var oe="__sync_version";var jn=new Set(["ZodOptional","ZodNullable","ZodDefault"]);function Fn(e){let t=e,n=false;for(;;){let r=j(t);if(!jn.has(r))break;(r==="ZodOptional"||r==="ZodNullable")&&(n=true);let o=q(t);if(!o)break;t=o;}return {inner:t,nullable:n}}var zn={ZodString:"string",ZodNumber:"number",ZodBigInt:"bigint",ZodBoolean:"boolean",ZodDate:"timestamp",ZodEnum:"string",ZodNativeEnum:"string",ZodLiteral:"string"};function Ft(e,t,n,r,o,s,a,u){for(let[i,l]of Object.entries(e)){let y=n?`${n}__${i}`:i;if(o.has(i)||o.has(y))continue;let{inner:h,nullable:c}=Fn(l),d=j(h),p=r||c;if(d==="ZodObject"){let g=re(h);Ft(g,t,y,p,o,s,a,u);continue}let m=zn[d]??"json",f=y===a||i===a,v=s[y]??s[i]??y;u.push({name:v,sqlType:t.mapType(m),nullable:f?false:p,isPrimaryKey:f});}}function Fe(e,t,n={}){let{primaryKey:r,exclude:o=[],columnMap:s={}}=n,a=new Set(o),u=re(e),i=[];return Ft(u,t,"",false,a,s,r,i),i.some(l=>l.name===oe)||i.push({name:oe,sqlType:t.mapType("bigint"),nullable:true,isPrimaryKey:false,description:"Monotonic publish version (Date.now() ms). Internal."}),i}function zt(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(zt)):e}function Zt(e,t,n){for(let[r,o]of Object.entries(e)){let s=t?`${t}__${r}`:r;o!=null&&typeof o=="object"&&!Array.isArray(o)&&!(o instanceof Date)&&!Buffer.isBuffer(o)&&!(o instanceof Uint8Array)&&typeof o.toDate!="function"&&!("latitude"in o&&"longitude"in o)?Zt(o,s,n):n[s]=zt(o);}}function Ce(e,t){let n=new Set(t?.exclude),r=t?.columnMap??{},o={};Zt(e,"",o);let s={};for(let[a,u]of Object.entries(o)){if(n.has(a))continue;let i=a.split("__")[0];if(i!==a&&n.has(i))continue;let l=r[a]??(a.includes("__")?r[a.split("__").pop()]:void 0)??a;s[l]=u;}return s}function pe(e,t){if(process.env.FUNCTIONS_EMULATOR==="true"){let o=process.env.GCLOUD_PROJECT??process.env.GOOGLE_CLOUD_PROJECT??"demo-project",s=process.env.FUNCTION_REGION??"us-central1",a=(process.env.FUNCTION_TARGET??"").replace(/\./g,"-");return `/${o}/${s}/${a}${t}`}let n=process.env.K_SERVICE,r=e.hostname??e.headers?.host??"";return n&&r.includes("cloudfunctions.net")?`/${n.toLowerCase()}${t}`:t}function W(e,t,n){return `<!DOCTYPE html>
|
|
2
|
+
<html lang="en"><head>
|
|
3
|
+
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
4
|
+
<title>${e} \u2014 Sync Admin</title>
|
|
5
|
+
<style>
|
|
6
|
+
*{box-sizing:border-box;margin:0;padding:0}
|
|
7
|
+
body{font-family:system-ui,-apple-system,sans-serif;background:#f5f5f5;color:#1a1a1a;padding:2rem}
|
|
8
|
+
a{color:#0969da;text-decoration:none}a:hover{text-decoration:underline}
|
|
9
|
+
h1{margin-bottom:1rem}h2{margin:1.5rem 0 .75rem}
|
|
10
|
+
table{border-collapse:collapse;width:100%;margin-bottom:1rem}
|
|
11
|
+
th,td{text-align:left;padding:.5rem .75rem;border:1px solid #d0d7de}
|
|
12
|
+
th{background:#f6f8fa;font-weight:600}
|
|
13
|
+
tr:nth-child(even){background:#fafbfc}
|
|
14
|
+
.badge{display:inline-block;padding:.15rem .5rem;border-radius:1rem;font-size:.8rem;font-weight:600}
|
|
15
|
+
.badge-ok{background:#dafbe1;color:#1a7f37}
|
|
16
|
+
.badge-warn{background:#fff8c5;color:#9a6700}
|
|
17
|
+
.badge-err{background:#ffebe9;color:#cf222e}
|
|
18
|
+
.btn{display:inline-block;padding:.4rem 1rem;border:1px solid #d0d7de;border-radius:.375rem;
|
|
19
|
+
background:#fff;cursor:pointer;font-size:.85rem;text-decoration:none;color:#1a1a1a}
|
|
20
|
+
.btn:hover{background:#f3f4f6}.btn-primary{background:#0969da;color:#fff;border-color:#0969da}
|
|
21
|
+
.btn-primary:hover{background:#0860ca}
|
|
22
|
+
nav{margin-bottom:1.5rem}nav a{margin-right:1rem}
|
|
23
|
+
.card{background:#fff;border:1px solid #d0d7de;border-radius:.5rem;padding:1.25rem;margin-bottom:1rem}
|
|
24
|
+
pre{background:#f6f8fa;padding:1rem;border-radius:.375rem;overflow-x:auto;font-size:.85rem}
|
|
25
|
+
.muted{color:#656d76;font-size:.85rem}
|
|
26
|
+
</style>
|
|
27
|
+
</head><body>
|
|
28
|
+
<nav><a href="${t}/">\u2190 Dashboard</a></nav>
|
|
29
|
+
<h1>${e}</h1>
|
|
30
|
+
${n}
|
|
31
|
+
</body></html>`}function V(e,t,n=200){e.status(n).set("Content-Type","text/html; charset=utf-8").send(t);}function fe(e,t,n=200){e.status(n).set("Content-Type","application/json").send(JSON.stringify(t,null,2));}function $e(e){return (e.headers?.accept??"").includes("application/json")}function Mt(e,t,n,r,o,s,a,u){let i=(o.basePath??"/").replace(/\/$/,"")||"",l=o.featuresFlag??{},y=[];for(let[c,d]of Object.entries(e)){let p=s[c];y.push({name:c,schema:d.schema??null,documentKey:d._systemKeys?.[0]??d.documentKey??"docId",tableName:p?.tableName??c,isGroup:!!d._isGroup,repoCfg:p,repo:d});}let h=new G;if(o.auth)if(typeof o.auth=="function")h.use(o.auth);else {let c=o.auth.realm??"Sync Admin",d="Basic "+Buffer.from(`${o.auth.username}:${o.auth.password}`).toString("base64");h.use((p,m,f)=>{if((p.headers?.authorization??"")!==d){m.status(401).set("WWW-Authenticate",`Basic realm="${c}"`).set("Content-Type","text/plain").send("Unauthorized");return}f();});}return h.get(`${i}/`,(c,d)=>{let p=pe(c,i),m=y.map(b=>{let R=[];return l.healthCheck&&R.push(`<a class="btn" href="${p}/${b.name}/health">Health</a>`),l.manualSync&&R.push(`<a class="btn btn-primary" href="${p}/${b.name}/force-sync">Force Sync</a>`),`<tr>
|
|
32
|
+
<td><strong>${b.name}</strong></td>
|
|
33
|
+
<td>${b.tableName}</td>
|
|
34
|
+
<td>${b.isGroup?'<span class="badge badge-warn">group</span>':'<span class="badge badge-ok">collection</span>'}</td>
|
|
35
|
+
<td>${b.schema?"\u2713":"\u2717"}</td>
|
|
36
|
+
<td>${R.join(" ")}</td>
|
|
37
|
+
</tr>`}).join(`
|
|
38
|
+
`),f=l.viewQueue?`<p><a class="btn" href="${p}/queues">View Queues</a></p>`:"",v=l.configCheck?`<p style="margin-top:.5rem"><a class="btn" href="${p}/config-check">\u2699 Config Check</a></p>`:"",g=W("Sync Dashboard",p,`<div class="card">
|
|
39
|
+
<table>
|
|
40
|
+
<thead><tr><th>Repository</th><th>Table</th><th>Type</th><th>Schema</th><th>Actions</th></tr></thead>
|
|
41
|
+
<tbody>${m}</tbody>
|
|
42
|
+
</table>
|
|
43
|
+
${f}
|
|
44
|
+
${v}
|
|
45
|
+
</div>`);V(d,g);}),h.get(`${i}`,(c,d)=>{let p=pe(c,i);d.status(302).set("Location",`${p}/`).send("");}),l.healthCheck&&h.get(`${i}/:repoName/health`,async(c,d)=>{let p=pe(c,i),m=y.find($=>$.name===c.params.repoName);if(!m){V(d,W("Not Found",p,`<p>Unknown repo: ${c.params.repoName}</p>`),404);return}if(!m.schema){V(d,W("Health Check",p,`<p class="badge badge-warn">No Zod schema attached to "${m.name}"</p>`));return}let f=Fe(m.schema,t.dialect,{primaryKey:m.documentKey,exclude:m.repoCfg?.exclude,columnMap:m.repoCfg?.columnMap}),v=[],g=false,b=null;try{g=await t.tableExists(m.tableName),g&&(v=await t.getTableColumns(m.tableName));}catch($){b=$?.message??String($);}let R=new Set(v),x=new Set(f.map($=>$.name)),S=f.filter($=>!R.has($.name)),C=v.filter($=>!x.has($)),P=f.filter($=>R.has($.name)),w=g&&S.length===0&&!b;if($e(c)){fe(d,{repo:m.name,table:m.tableName,tableExists:g,healthy:w,error:b,columns:{expected:f.map($=>({name:$.name,type:$.sqlType,nullable:$.nullable,isPrimaryKey:$.isPrimaryKey})),actual:v,matched:P.map($=>$.name),missing:S.map($=>({name:$.name,type:$.sqlType})),extra:C}});return}let T=w?'<span class="badge badge-ok">Healthy</span>':'<span class="badge badge-err">Unhealthy</span>',O=f.map($=>{let K=R.has($.name)?'<span class="badge badge-ok">OK</span>':'<span class="badge badge-err">MISSING</span>';return `<tr><td>${$.name}</td><td>${$.sqlType}</td><td>${$.nullable?"Yes":"No"}</td><td>${$.isPrimaryKey?"\u2713":""}</td><td>${K}</td></tr>`}).join(`
|
|
46
|
+
`),k=C.map($=>`<tr><td>${$}</td><td colspan="3" class="muted">not in schema</td><td><span class="badge badge-warn">EXTRA</span></td></tr>`).join(`
|
|
47
|
+
`),I=W(`Health: ${m.name}`,p,`<div class="card">
|
|
48
|
+
<p>Table: <code>${m.tableName}</code> ${g?T:'<span class="badge badge-err">NOT FOUND</span>'}</p>
|
|
49
|
+
${b?`<p class="badge badge-err">Error: ${b}</p>`:""}
|
|
50
|
+
<h2>Columns</h2>
|
|
51
|
+
<table>
|
|
52
|
+
<thead><tr><th>Column</th><th>SQL Type</th><th>Nullable</th><th>PK</th><th>Status</th></tr></thead>
|
|
53
|
+
<tbody>${O}${k}</tbody>
|
|
54
|
+
</table>
|
|
55
|
+
</div>`);V(d,I);}),l.manualSync&&(h.get(`${i}/:repoName/force-sync`,(c,d)=>{let p=pe(c,i),m=y.find(v=>v.name===c.params.repoName);if(!m){V(d,W("Not Found",p,`<p>Unknown repo: ${c.params.repoName}</p>`),404);return}let f=W(`Force Sync: ${m.name}`,p,`<div class="card">
|
|
56
|
+
<p>This will read <strong>all</strong> documents from the <code>${m.name}</code> Firestore collection
|
|
57
|
+
and upsert them into the <code>${m.tableName}</code> SQL table.</p>
|
|
58
|
+
<p class="muted" style="margin:.75rem 0">This may take a while for large collections.</p>
|
|
59
|
+
<form method="POST" action="${p}/${m.name}/force-sync">
|
|
60
|
+
<button type="submit" class="btn btn-primary">Start Force Sync</button>
|
|
61
|
+
</form>
|
|
62
|
+
</div>`);V(d,f);}),h.post(`${i}/:repoName/force-sync`,async(c,d)=>{let p=pe(c,i),m=y.find(w=>w.name===c.params.repoName);if(!m){fe(d,{error:`Unknown repo: ${c.params.repoName}`},404);return}let f=m.repo.ref;if(!f){fe(d,{error:`No collection reference for "${m.name}"`},400);return}let v=0,g=0,b=[],R=500,x=f.limit(R),S=null;try{for(;;){let O=await(S?x.startAfter(S):x).get();if(O.empty)break;for(let k of O.docs){let I=k.data(),$=String(I[m.documentKey]??k.id),K=Ce(I,{exclude:m.repoCfg?.exclude,columnMap:m.repoCfg?.columnMap});try{await r({operation:"UPSERT",repoName:m.name,docId:$,data:K,timestamp:new Date().toISOString()}),v++;}catch(_){g++;let te=_?.message??String(_);console.error(`[ForceSync:${m.name}] doc=${$} failed:`,_),b.length<5&&b.push(`${$}: ${te}`);}}if(S=O.docs[O.docs.length-1],O.docs.length<R)break}let w=n.get(m.name);w&&await w.flush();}catch(w){if($e(c)){fe(d,{error:w?.message??String(w),synced:v,errors:g},500);return}V(d,W(`Force Sync: ${m.name}`,p,`<div class="card">
|
|
63
|
+
<p class="badge badge-err">Error: ${w?.message??String(w)}</p>
|
|
64
|
+
<p>Synced ${v} docs before failure (${g} errors).</p>
|
|
65
|
+
</div>`),500);return}if($e(c)){fe(d,{repo:m.name,table:m.tableName,synced:v,errors:g,...b.length>0&&{errorSamples:b}});return}let C=b.length>0?`<details style="margin-top:1rem"><summary>First ${b.length} error(s)</summary>
|
|
66
|
+
<pre style="white-space:pre-wrap">${b.map(w=>w.replace(/[<>&]/g,T=>`&#${T.charCodeAt(0)};`)).join(`
|
|
67
|
+
|
|
68
|
+
`)}</pre></details>`:"",P=W(`Force Sync: ${m.name}`,p,`<div class="card">
|
|
69
|
+
<p class="badge ${g>0?"badge-warn":"badge-ok"}">${g>0?"Completed with errors":"Complete"}</p>
|
|
70
|
+
<p>Synced <strong>${v}</strong> documents to <code>${m.tableName}</code>.</p>
|
|
71
|
+
${g>0?`<p class="badge badge-warn">${g} error(s)</p>`:""}
|
|
72
|
+
${C}
|
|
73
|
+
</div>`);V(d,P);})),l.viewQueue&&h.get(`${i}/queues`,(c,d)=>{let p=pe(c,i),m=[];for(let g of y){let b=n.get(g.name);m.push({repo:g.name,table:g.tableName,pending:b?b.size:0});}if($e(c)){fe(d,{queues:m});return}let f=m.map(g=>`<tr><td>${g.repo}</td><td>${g.table}</td><td>${g.pending===0?'<span class="badge badge-ok">0</span>':`<span class="badge badge-warn">${g.pending}</span>`}</td></tr>`).join(`
|
|
74
|
+
`),v=W("Sync Queues",p,`<div class="card">
|
|
75
|
+
<table>
|
|
76
|
+
<thead><tr><th>Repository</th><th>Table</th><th>Pending</th></tr></thead>
|
|
77
|
+
<tbody>${f}</tbody>
|
|
78
|
+
</table>
|
|
79
|
+
</div>`);V(d,v);}),l.configCheck&&h.get(`${i}/config-check`,async(c,d)=>{let p=pe(c,i),m=process.env.GCLOUD_PROJECT??process.env.GOOGLE_CLOUD_PROJECT??process.env.GCP_PROJECT??"unknown",f="https://console.cloud.google.com",v=u??"firestore-sync",g=[];try{await t.tableExists("__nonexistent_health_check__"),g.push({name:"BigQuery API",category:"bigquery",status:"ok",message:"BigQuery API is reachable"});}catch(w){let T=w?.message??String(w),O=T.toLowerCase(),k=O.includes("disabled")||O.includes("has not been used")||O.includes("accessnotconfigured"),I=O.includes("permission")||T.includes("403")||O.includes("access denied"),$=O.includes("project")&&O.includes("not found"),K=O.includes("not found")||T.includes("404");k?g.push({name:"BigQuery API",category:"bigquery",status:"error",message:"BigQuery API is not enabled",fix:{gcloud:`gcloud services enable bigquery.googleapis.com --project=${m}`,console:`${f}/apis/library/bigquery.googleapis.com?project=${m}`}}):$?g.push({name:"BigQuery Project",category:"bigquery",status:"error",message:T,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:`${f}/home/dashboard`}}):I?g.push({name:"BigQuery API",category:"bigquery",status:"error",message:`Permission denied: ${T}`,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=${m})`,`gcloud projects add-iam-policy-binding ${m} --member="serviceAccount:$SA" --role="roles/bigquery.dataEditor"`,`gcloud projects add-iam-policy-binding ${m} --member="serviceAccount:$SA" --role="roles/bigquery.jobUser"`].join(`
|
|
80
|
+
`),console:`${f}/iam-admin/iam?project=${m}`}}):K?g.push({name:"BigQuery Dataset",category:"bigquery",status:"error",message:`Dataset not found: ${T}`,fix:{hint:"Create the dataset first",gcloud:`bq mk --dataset ${m}:YOUR_DATASET_ID`,console:`${f}/bigquery?project=${m}`}}):g.push({name:"BigQuery API",category:"bigquery",status:"ok",message:"BigQuery API is reachable (table lookup returned expected error)"});}for(let w of y)try{let T=await t.tableExists(w.tableName);g.push({name:`Table: ${w.tableName}`,category:"bigquery",status:T?"ok":"warn",message:T?`Table \`${w.tableName}\` exists`:`Table \`${w.tableName}\` does not exist yet`,...!T&&{fix:{hint:"Table will be auto-created on first sync if autoMigrate is enabled. Or create it manually."}}});}catch(T){g.push({name:`Table: ${w.tableName}`,category:"bigquery",status:"error",message:T?.message??String(T)});}if(a)for(let w of y){let T=`${v}-${w.name}`;try{let O=a.topic(T);if(typeof O.exists=="function"){let[k]=await O.exists();g.push({name:`Topic: ${T}`,category:"pubsub",status:k?"ok":"error",message:k?`Topic \`${T}\` exists`:`Topic \`${T}\` does not exist`,...!k&&{fix:{gcloud:`gcloud pubsub topics create ${T} --project=${m}`,console:`${f}/cloudpubsub/topic/list?project=${m}`}}});}else g.push({name:`Topic: ${T}`,category:"pubsub",status:"warn",message:"Cannot verify topic existence (PubSub client doesn't expose .exists())",fix:{gcloud:`gcloud pubsub topics create ${T} --project=${m}`,console:`${f}/cloudpubsub/topic/list?project=${m}`,hint:"Ensure the topic exists. It is auto-created by the Firebase emulator but must exist in production."}});}catch(O){let k=O?.message??String(O),I=k.includes("disabled")||k.includes("has not been used");if(g.push({name:I?"Pub/Sub API":`Topic: ${T}`,category:"pubsub",status:"error",message:I?"Pub/Sub API is not enabled":k,fix:I?{gcloud:`gcloud services enable pubsub.googleapis.com --project=${m}`,console:`${f}/apis/library/pubsub.googleapis.com?project=${m}`}:{gcloud:`gcloud pubsub topics create ${T} --project=${m}`,console:`${f}/cloudpubsub/topic/list?project=${m}`}}),I)break}}else g.push({name:"Pub/Sub Client",category:"pubsub",status:"warn",message:"PubSub client not available for config check"});if($e(c)){let w=g.every(T=>T.status==="ok");fe(d,{project:m,healthy:w,checks:g});return}let b=w=>w==="ok"?'<span class="badge badge-ok">OK</span>':w==="warn"?'<span class="badge badge-warn">WARN</span>':'<span class="badge badge-err">ERROR</span>',R={bigquery:g.filter(w=>w.category==="bigquery"),pubsub:g.filter(w=>w.category==="pubsub"),firestore:g.filter(w=>w.category==="firestore")},x=(w,T)=>{if(T.length===0)return "";let O=T.map(k=>{let I="";if(k.fix){let $=[];k.fix.hint&&$.push(`<p class="muted">${k.fix.hint}</p>`),k.fix.gcloud&&$.push(`<pre>$ ${k.fix.gcloud}</pre>`),k.fix.console&&$.push(`<p><a href="${k.fix.console}" target="_blank">Open GCP Console \u2192</a></p>`),I=`<div style="margin-top:.5rem">${$.join("")}</div>`;}return `<tr>
|
|
81
|
+
<td>${b(k.status)}</td>
|
|
82
|
+
<td><strong>${k.name}</strong><br><span class="muted">${k.message}</span>${I}</td>
|
|
83
|
+
</tr>`}).join(`
|
|
84
|
+
`);return `<h2>${w}</h2>
|
|
85
|
+
<table><thead><tr><th style="width:80px">Status</th><th>Check</th></tr></thead>
|
|
86
|
+
<tbody>${O}</tbody></table>`},C=g.every(w=>w.status==="ok")?'<span class="badge badge-ok">All checks passed</span>':'<span class="badge badge-warn">Some issues found</span>',P=W("Config Check",p,`<div class="card">
|
|
87
|
+
<p>Project: <code>${m}</code> ${C}</p>
|
|
88
|
+
${x("BigQuery",R.bigquery)}
|
|
89
|
+
${x("Pub/Sub",R.pubsub)}
|
|
90
|
+
${x("Firestore",R.firestore)}
|
|
91
|
+
</div>`);V(d,P);}),async(c,d)=>{await h.handle(c,d);}}var Zn="firestore-sync";function Mn(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 Bt(e,t){let{onDocumentCreated:n,onDocumentUpdated:r,onDocumentDeleted:o}=t.deps.firestoreTriggers,s=t.deps.pubsub,a=t?.topicPrefix??Zn,u={},i=new Map;function l(h){let c=i.get(h);return c||(c=s.topic(h),i.set(h,c),c)}async function y(h,c){await l(h).publishMessage({json:c});}for(let[h,c]of Object.entries(e)){let d=t?.repos?.[h],p;if(c._isGroup){if(!d?.triggerPath){console.warn(`[SyncTriggers] Skipping collection-group repo "${h}". Provide a triggerPath in the sync repos config for group collections.`);continue}p=d.triggerPath;}else p=d?.triggerPath??Mn(h,c);if(!p)continue;let m=c._systemKeys?.[0]??"docId",f=`${a}-${h}`;u[`${h}_onCreate`]=n(p,async v=>{let g=v.data;if(!g)return;let b=g.data();if(!b)return;let R=String(b[m]??g.id),x=Ce(b,{exclude:d?.exclude,columnMap:d?.columnMap}),S={operation:"INSERT",repoName:h,docId:R,data:x,timestamp:new Date().toISOString(),version:Date.now()};await y(f,S);}),u[`${h}_onUpdate`]=r(p,async v=>{let g=v.data?.after;if(!g)return;let b=g.data();if(!b)return;let R=String(b[m]??g.id),x=Ce(b,{exclude:d?.exclude,columnMap:d?.columnMap}),S={operation:"UPSERT",repoName:h,docId:R,data:x,timestamp:new Date().toISOString(),version:Date.now()};await y(f,S);}),u[`${h}_onDelete`]=o(p,async v=>{let g=v.data;if(!g)return;let b=g.data(),R=String(b?.[m]??g.id),x={operation:"DELETE",repoName:h,docId:R,data:null,timestamp:new Date().toISOString(),version:Date.now()};await y(f,x);});}return u}var ze=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,r=[];for(let s of t)if(s.operation==="DELETE")r.push(s.docId),n.delete(s.docId);else if(s.data){let a=n.get(s.docId);if(!a)n.set(s.docId,s.data);else {let u=Number(a[oe]??0);Number(s.data[oe]??0)>=u&&n.set(s.docId,s.data);}}let o=Array.from(n.values());o.length>0&&await this.adapter.upsertRows(this.tableName,o,this.primaryKey),r.length>0&&await this.adapter.deleteRows(this.tableName,this.primaryKey,r);}catch(n){this.onFlushError?await this.onFlushError(t,n).catch(r=>{console.error(`[SyncQueue] Flush error for ${this.tableName}:`,n),console.error("[SyncQueue] Error handler also failed:",r);}):(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 Kt=new Set;async function Bn(e,t,n,r,o,s,a){if(Kt.has(e))return;let u=Fe(n,t.dialect,{primaryKey:o,exclude:s,columnMap:a});if(!await t.tableExists(r))await t.createTable({tableName:r,columns:u});else {let l=new Set(await t.getTableColumns(r)),y=u.filter(h=>!l.has(h.name));y.length>0&&await t.addColumns(r,y);}Kt.add(e);}function qt(e,t){let{deps:n,adapter:r,batchSize:o=100,flushIntervalMs:s=5e3,autoMigrate:a=false,topicPrefix:u="firestore-sync",workerOptions:i,repos:l={}}=t,y=new Map;function h(p,m){let f=y.get(p);if(f)return f;let g=l[p]?.tableName??p,b=async(R,x)=>{console.error(`[SyncWorker] Flush failed for "${p}" (${R.length} events):`,x);try{let S=`${u}-${p}-dlq`,C=n.pubsub.topic(S),[P]=await C.exists();P||(await C.create(),console.info(`[SyncWorker] Created DLQ topic "${S}"`));for(let w of R)await C.publishMessage({json:w});}catch(S){console.error(`[SyncWorker] Dead-letter publish also failed for ${p}:`,S);}};return f=new ze({adapter:r,tableName:g,primaryKey:m,batchSize:o,flushIntervalMs:s,onFlushError:b}),y.set(p,f),f}async function c(p){let{repoName:m}=p,f=e[m];if(!f){console.warn(`[SyncWorker] Unknown repo "${m}", skipping event`);return}let v=f._systemKeys?.[0]??f.documentKey??"docId",g=l[m],b=g?.columnMap,R=b?.[v]??v;if(a){let S=f.schema??void 0;if(S){let C=g?.tableName??m;await Bn(m,r,S,C,v,g?.exclude,b);}}let x=h(m,R);p.data&&(p.data[oe]=p.version??Date.now()),x.enqueue(p);}function d(p){let m=async f=>{let v=f.data?.message?.json??f.data?.json;if(!v){console.warn("[SyncWorker] Received empty PubSub message");return}await c(v);let g=y.get(v.repoName);g&&await g.flush();};return i?n.pubsubHandler.onMessagePublished({topic:p,...i},m):n.pubsubHandler.onMessagePublished(p,m)}return {handleMessage:c,createHandler:d,queues:y,async shutdown(){let p=[];for(let m of y.values())p.push(m.shutdown());await Promise.all(p);}}}var Kn="firestore-sync";function Qt(e){if(typeof e!="function")return e;let t=e,n;return new Proxy({},{get(r,o){return n||(n=t()),n[o]},has(r,o){return n||(n=t()),o in n}})}function Ut(e,t){let{deps:n,adapter:r,topicPrefix:o=Kn,batchSize:s,flushIntervalMs:a,autoMigrate:u,admin:i,workerOptions:l,repos:y}=t,h=Qt(n.pubsub),c=Qt(r),d=Bt(e,{deps:{firestoreTriggers:n.firestoreTriggers,pubsub:h},topicPrefix:o,repos:y}),p=qt(e,{deps:{pubsubHandler:n.pubsubHandler,pubsub:h},adapter:c,batchSize:s,flushIntervalMs:a,autoMigrate:u,topicPrefix:o,workerOptions:l,repos:y}),m={};for(let g of Object.keys(e))m[`sync_${g}`]=p.createHandler(`${o}-${g}`);let f=null;i&&(f=Mt(e,c,p.queues,p.handleMessage,i,y??{},h,o),m.adminsync=i.onRequest?i.httpsOptions?i.onRequest(i.httpsOptions,f):i.onRequest(f):f);let v={functions:{...d,...m},adminHandler:f,handleMessage:p.handleMessage,queues:p.queues,shutdown:p.shutdown};for(let g of ["adminHandler","handleMessage","queues","shutdown"])Object.defineProperty(v,g,{enumerable:false});return v}function qn(e){return e.replace(/([A-Z])/g," $1").replace(/_/g," ").replace(/^\s/,"").replace(/^./,t=>t.toUpperCase())}function Lt(e){let t=e,n=true,r=false,o;for(;;){let s=j(t);if(s==="ZodOptional")n=false,t=q(t);else if(s==="ZodNullable")n=false,r=true,t=q(t);else if(s==="ZodDefault")n=false,o=_t(t),t=q(t);else break}return {inner:t,required:n,nullable:r,defaultValue:o}}function J(e,t=""){if(j(e)==="ZodObject"){let r=re(e);return Object.entries(r).map(([o,s])=>Gt(t?`${t}.${o}`:o,o,s))}return [Gt(t||"value",t||"value",e)]}function Gt(e,t,n){let{inner:r,required:o,nullable:s,defaultValue:a}=Lt(n),u=j(r),i=qn(t.split(".").pop()??t);switch(u){case "ZodString":{let l=jt(r),y=l.includes("email"),h=l.includes("url");return {name:e,label:i,type:"text",required:o,nullable:s,defaultValue:a,hint:y?"email":h?"url":void 0}}case "ZodNumber":case "ZodBigInt":return {name:e,label:i,type:"number",required:o,nullable:s,defaultValue:a};case "ZodBoolean":return {name:e,label:i,type:"checkbox",required:o,nullable:s,defaultValue:a};case "ZodDate":case "ZodCoerce":return {name:e,label:i,type:"datetime-local",required:o,nullable:s,defaultValue:a};case "ZodEnum":{let l=Se(r);return {name:e,label:i,type:"select",required:o,nullable:s,defaultValue:a,options:l}}case "ZodNativeEnum":{let l=Te(r),y=Object.values(l).filter(h=>typeof h=="string");return {name:e,label:i,type:"select",required:o,nullable:s,defaultValue:a,options:y}}case "ZodLiteral":{let l=String(je(r)??"");return {name:e,label:i,type:"select",required:o,nullable:s,defaultValue:a,options:[l]}}case "ZodObject":{let l=J(r,e);return {name:e,label:i,type:"textarea",required:o,nullable:s,defaultValue:a,nested:l,hint:"JSON object"}}case "ZodArray":{let l=Nt(r);if(!l)return {name:e,label:i,type:"textarea",required:o,nullable:s,defaultValue:a,hint:"JSON array"};let{inner:y}=Lt(l),h=j(y),c,d,p;switch(h){case "ZodString":c="text";break;case "ZodNumber":case "ZodBigInt":c="number";break;case "ZodBoolean":c="checkbox";break;case "ZodDate":c="datetime-local";break;case "ZodEnum":c="select",d=Se(y);break;case "ZodNativeEnum":c="select",d=Object.values(Te(y)).filter(m=>typeof m=="string");break;case "ZodObject":c="object",p=J(y);break;default:return {name:e,label:i,type:"textarea",required:o,nullable:s,defaultValue:a,hint:"JSON array"}}return {name:e,label:i,type:"textarea",required:o,nullable:s,defaultValue:a,arrayElementType:c,arrayElementOptions:d,arrayElementFields:p}}default:return {name:e,label:i,type:"textarea",required:o,nullable:s,defaultValue:a,hint:"JSON"}}}function Ve(e,t=0){let n=t>0?`ml-${t*4}`:"",r=`field_${e.name.replace(/\./g,"__")}`,o=e.name,s=e.required?" required":"",a=e.defaultValue==="__null__",u=!a&&e.defaultValue!=null?String(e.defaultValue):"",i=e.nullable&&e.type!=="checkbox"?`<span class="flex items-center gap-1 shrink-0">
|
|
2
92
|
<input type="hidden" id="${r}__isnull" name="${o}__isnull" value="${a?"1":""}">
|
|
3
93
|
<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">
|
|
4
94
|
<input type="checkbox" class="checkbox checkbox-xs" ${a?"checked":""}
|
|
@@ -10,59 +100,59 @@ import {Timestamp}from'firebase-admin/firestore';import {z as z$1}from'zod';impo
|
|
|
10
100
|
})(this)">
|
|
11
101
|
<span>null</span>
|
|
12
102
|
</label>
|
|
13
|
-
</span>`:"",l;switch(e.type){case "checkbox":if(e.nullable){let
|
|
103
|
+
</span>`:"",l;switch(e.type){case "checkbox":if(e.nullable){let y=a?"__null__":u==="true"?"true":u==="false"?"false":"__null__";return `
|
|
14
104
|
<div class="form-control mb-3 ${n}">
|
|
15
105
|
<label for="${r}" class="label pb-1">
|
|
16
106
|
<span class="label-text font-medium">
|
|
17
|
-
${
|
|
107
|
+
${A(e.label)}
|
|
18
108
|
<span class="text-base-content/40 text-xs ml-1">(nullable)</span>
|
|
19
109
|
</span>
|
|
20
110
|
</label>
|
|
21
111
|
<select id="${r}" name="${o}" class="select select-bordered select-sm w-full">
|
|
22
|
-
<option value="__null__"${
|
|
23
|
-
<option value="true"${
|
|
24
|
-
<option value="false"${
|
|
112
|
+
<option value="__null__"${y==="__null__"?" selected":""}>\u2014 null \u2014</option>
|
|
113
|
+
<option value="true"${y==="true"?" selected":""}>\u2713 true</option>
|
|
114
|
+
<option value="false"${y==="false"?" selected":""}>\u2717 false</option>
|
|
25
115
|
</select>
|
|
26
116
|
</div>`}return `
|
|
27
117
|
<div class="form-control ${n}">
|
|
28
118
|
<label class="label cursor-pointer justify-start gap-3">
|
|
29
|
-
<input type="checkbox" id="${r}" name="${o}" value="true"${
|
|
119
|
+
<input type="checkbox" id="${r}" name="${o}" value="true"${u==="true"?" checked":""} class="checkbox checkbox-primary checkbox-sm">
|
|
30
120
|
<span class="label-text font-medium">
|
|
31
|
-
${
|
|
121
|
+
${A(e.label)}${e.required?' <span class="text-error">*</span>':""}
|
|
32
122
|
</span>
|
|
33
123
|
</label>
|
|
34
124
|
</div>`;case "select":l=`<select id="${r}" name="${o}"${s}${a?' disabled style="opacity:0.35"':""} class="select select-bordered select-sm w-full">
|
|
35
125
|
${e.required&&!e.nullable?"":'<option value="">\u2014 optional \u2014</option>'}
|
|
36
|
-
${(e.options??[]).map(
|
|
126
|
+
${(e.options??[]).map(y=>`<option value="${A(y)}"${u===y?" selected":""}>${A(y)}</option>`).join(`
|
|
37
127
|
`)}
|
|
38
|
-
</select>`;break;case "textarea":if(e.arrayElementType)return
|
|
128
|
+
</select>`;break;case "textarea":if(e.arrayElementType)return Qn(e,t);if(e.nested&&e.nested.length>0){let y=e.nested.map(h=>Ve(h,t+1)).join(`
|
|
39
129
|
`);return `
|
|
40
130
|
<fieldset class="fieldset border border-base-300 rounded-box p-3 mb-3 ${n}">
|
|
41
131
|
<legend class="fieldset-legend text-xs font-semibold text-base-content/60 px-1">
|
|
42
|
-
${
|
|
132
|
+
${A(e.label)}${e.required?' <span class="text-error">*</span>':""}
|
|
43
133
|
</legend>
|
|
44
|
-
${
|
|
134
|
+
${y}
|
|
45
135
|
</fieldset>`}l=`<textarea id="${r}" name="${o}"${s} rows="3"${a?' disabled style="opacity:0.35"':""}
|
|
46
136
|
data-json
|
|
47
137
|
class="textarea textarea-bordered textarea-sm w-full font-mono text-xs"
|
|
48
|
-
placeholder="${
|
|
49
|
-
value="${
|
|
138
|
+
placeholder="${A(e.hint??"JSON")}">${A(u)}</textarea>`;break;default:l=`<input type="${e.type}" id="${r}" name="${o}"${s}${a?' disabled style="opacity:0.35"':""}
|
|
139
|
+
value="${A(u)}"
|
|
50
140
|
class="input input-bordered input-sm w-full"${e.hint==="email"?' autocomplete="email"':e.hint==="url"?' autocomplete="url"':""}>`;}return `
|
|
51
141
|
<div class="form-control mb-3 ${n}">
|
|
52
142
|
<label for="${r}" class="label pb-1">
|
|
53
143
|
<span class="label-text font-medium">
|
|
54
|
-
${
|
|
55
|
-
${e.hint?`<span class="text-base-content/40 text-xs ml-1">(${
|
|
144
|
+
${A(e.label)}${e.required?' <span class="text-error">*</span>':""}
|
|
145
|
+
${e.hint?`<span class="text-base-content/40 text-xs ml-1">(${A(e.hint)})</span>`:""}
|
|
56
146
|
</span>
|
|
57
147
|
</label>
|
|
58
148
|
<div class="flex items-center gap-2">
|
|
59
149
|
<div class="flex-1 min-w-0">${l}</div>
|
|
60
150
|
${i}
|
|
61
151
|
</div>
|
|
62
|
-
</div>`}function
|
|
63
|
-
`):a.map(
|
|
64
|
-
`),i=s?
|
|
65
|
-
<input type="hidden" id="${r}__isnull" name="${
|
|
152
|
+
</div>`}function A(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function Qn(e,t){let n=t>0?`ml-${t*4}`:"",r=`field_${e.name.replace(/\./g,"__")}`,o=e.defaultValue==="__null__",s=e.arrayElementType==="object",a=[];if(e.defaultValue!=null&&e.defaultValue!==""&&e.defaultValue!=="__null__")try{a=JSON.parse(String(e.defaultValue));}catch{}Array.isArray(a)||(a=[]);let u=s?a.map(y=>Wt(e,y??{})).join(`
|
|
153
|
+
`):a.map(y=>Ht(e,y)).join(`
|
|
154
|
+
`),i=s?Wt(e,{}):Ht(e,""),l=e.nullable?`<span class="flex items-center gap-1 mt-2">
|
|
155
|
+
<input type="hidden" id="${r}__isnull" name="${A(e.name)}__isnull" value="${o?"1":""}">
|
|
66
156
|
<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">
|
|
67
157
|
<input type="checkbox" class="checkbox checkbox-xs" ${o?"checked":""}
|
|
68
158
|
onchange="(function(cb){
|
|
@@ -76,64 +166,64 @@ import {Timestamp}from'firebase-admin/firestore';import {z as z$1}from'zod';impo
|
|
|
76
166
|
</label>
|
|
77
167
|
</span>`:"";return `
|
|
78
168
|
<fieldset class="fieldset border border-base-300 rounded-box p-3 mb-3 ${n}"
|
|
79
|
-
data-frs-array="${
|
|
169
|
+
data-frs-array="${A(e.name)}" data-frs-array-type="${A(e.arrayElementType??"text")}">
|
|
80
170
|
<legend class="fieldset-legend text-xs font-semibold text-base-content/60 px-1">
|
|
81
|
-
${
|
|
171
|
+
${A(e.label)}${e.required?' <span class="text-error">*</span>':""}
|
|
82
172
|
</legend>
|
|
83
|
-
<input type="hidden" id="${r}" name="${
|
|
173
|
+
<input type="hidden" id="${r}" name="${A(e.name)}" value="${A(JSON.stringify(a))}"${o?" disabled":""}>
|
|
84
174
|
<div data-frs-array-items${o?' style="opacity:0.35"':""}>
|
|
85
|
-
${
|
|
175
|
+
${u}
|
|
86
176
|
</div>
|
|
87
177
|
<template data-frs-array-tpl>${i}</template>
|
|
88
178
|
<button type="button" class="btn btn-xs btn-outline mt-1" data-frs-array-add>+ Add</button>
|
|
89
179
|
${l}
|
|
90
|
-
</fieldset>`}function
|
|
180
|
+
</fieldset>`}function Ht(e,t){let n=t!=null?String(t):"",r;switch(e.arrayElementType){case "select":r=`<select data-frs-val class="select select-bordered select-sm flex-1">
|
|
91
181
|
<option value="">\u2014</option>
|
|
92
|
-
${(e.arrayElementOptions??[]).map(o=>`<option value="${
|
|
182
|
+
${(e.arrayElementOptions??[]).map(o=>`<option value="${A(o)}"${n===o?" selected":""}>${A(o)}</option>`).join("")}
|
|
93
183
|
</select>`;break;case "checkbox":r=`<label class="flex items-center gap-2 flex-1 cursor-pointer">
|
|
94
184
|
<input type="checkbox" data-frs-val class="checkbox checkbox-sm checkbox-primary"${n==="true"?" checked":""}>
|
|
95
185
|
<span class="text-sm">true</span>
|
|
96
|
-
</label>`;break;case "number":r=`<input type="number" data-frs-val value="${
|
|
186
|
+
</label>`;break;case "number":r=`<input type="number" data-frs-val value="${A(n)}" class="input input-bordered input-sm flex-1">`;break;case "datetime-local":r=`<input type="datetime-local" data-frs-val value="${A(n)}" class="input input-bordered input-sm flex-1">`;break;default:r=`<input type="text" data-frs-val value="${A(n)}" class="input input-bordered input-sm flex-1">`;}return `<div class="flex items-center gap-2 mb-2" data-frs-array-item>
|
|
97
187
|
${r}
|
|
98
188
|
<button type="button" class="btn btn-xs btn-ghost text-error" data-frs-array-rm>×</button>
|
|
99
|
-
</div>`}function
|
|
189
|
+
</div>`}function Wt(e,t){return `<div class="border border-base-200 rounded p-3 mb-2" data-frs-array-item>
|
|
100
190
|
<div class="flex justify-end mb-1">
|
|
101
191
|
<button type="button" class="btn btn-xs btn-ghost text-error" data-frs-array-rm>×</button>
|
|
102
192
|
</div>
|
|
103
193
|
${(e.arrayElementFields??[]).map(o=>{let s=t[o.name],a=s==null?"":typeof s=="object"?JSON.stringify(s):String(s);switch(o.type){case "checkbox":return `<div class="form-control mb-2">
|
|
104
194
|
<label class="label cursor-pointer justify-start gap-3">
|
|
105
|
-
<input type="checkbox" data-frs-key="${
|
|
106
|
-
<span class="label-text text-sm">${
|
|
195
|
+
<input type="checkbox" data-frs-key="${A(o.name)}" class="checkbox checkbox-sm checkbox-primary"${a==="true"?" checked":""}>
|
|
196
|
+
<span class="label-text text-sm">${A(o.label)}</span>
|
|
107
197
|
</label>
|
|
108
198
|
</div>`;case "select":return `<div class="form-control mb-2">
|
|
109
|
-
<label class="label pb-1"><span class="label-text text-sm">${
|
|
110
|
-
<select data-frs-key="${
|
|
199
|
+
<label class="label pb-1"><span class="label-text text-sm">${A(o.label)}</span></label>
|
|
200
|
+
<select data-frs-key="${A(o.name)}" class="select select-bordered select-sm w-full">
|
|
111
201
|
${o.required?"":'<option value="">\u2014</option>'}
|
|
112
|
-
${(o.options??[]).map(
|
|
202
|
+
${(o.options??[]).map(u=>`<option value="${A(u)}"${a===u?" selected":""}>${A(u)}</option>`).join("")}
|
|
113
203
|
</select>
|
|
114
204
|
</div>`;case "number":return `<div class="form-control mb-2">
|
|
115
|
-
<label class="label pb-1"><span class="label-text text-sm">${
|
|
116
|
-
<input type="number" data-frs-key="${
|
|
205
|
+
<label class="label pb-1"><span class="label-text text-sm">${A(o.label)}</span></label>
|
|
206
|
+
<input type="number" data-frs-key="${A(o.name)}" value="${A(a)}" class="input input-bordered input-sm w-full">
|
|
117
207
|
</div>`;case "datetime-local":return `<div class="form-control mb-2">
|
|
118
|
-
<label class="label pb-1"><span class="label-text text-sm">${
|
|
119
|
-
<input type="datetime-local" data-frs-key="${
|
|
208
|
+
<label class="label pb-1"><span class="label-text text-sm">${A(o.label)}</span></label>
|
|
209
|
+
<input type="datetime-local" data-frs-key="${A(o.name)}" value="${A(a)}" class="input input-bordered input-sm w-full">
|
|
120
210
|
</div>`;case "textarea":return `<div class="form-control mb-2">
|
|
121
|
-
<label class="label pb-1"><span class="label-text text-sm">${
|
|
122
|
-
<textarea data-frs-key="${
|
|
211
|
+
<label class="label pb-1"><span class="label-text text-sm">${A(o.label)}</span></label>
|
|
212
|
+
<textarea data-frs-key="${A(o.name)}" rows="2" class="textarea textarea-bordered textarea-sm w-full font-mono text-xs" placeholder="JSON">${A(a)}</textarea>
|
|
123
213
|
</div>`;default:return `<div class="form-control mb-2">
|
|
124
|
-
<label class="label pb-1"><span class="label-text text-sm">${
|
|
125
|
-
<input type="text" data-frs-key="${
|
|
214
|
+
<label class="label pb-1"><span class="label-text text-sm">${A(o.label)}</span></label>
|
|
215
|
+
<input type="text" data-frs-key="${A(o.name)}" value="${A(a)}" class="input input-bordered input-sm w-full">
|
|
126
216
|
</div>`}}).join(`
|
|
127
217
|
`)}
|
|
128
|
-
</div>`}function
|
|
218
|
+
</div>`}function se(e,t,n,r="Save"){let o=e.map(s=>Ve(s)).join(`
|
|
129
219
|
`);return `
|
|
130
|
-
<form action="${
|
|
220
|
+
<form action="${A(t)}" method="${n}" novalidate data-frs-form>
|
|
131
221
|
${o}
|
|
132
222
|
<div class="flex gap-2 mt-4 pt-4 border-t border-base-200">
|
|
133
|
-
<button type="submit" class="btn btn-primary btn-sm">${
|
|
223
|
+
<button type="submit" class="btn btn-primary btn-sm">${A(r)}</button>
|
|
134
224
|
<button type="button" class="btn btn-ghost btn-sm" onclick="history.back()">Cancel</button>
|
|
135
225
|
</div>
|
|
136
|
-
</form>`}function
|
|
226
|
+
</form>`}function Vt({val:e}){return jsx("span",{class:"text-sm text-base-content/80 font-mono tabular-nums whitespace-nowrap",children:e.toLocaleString()})}function Je({val: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(Vt,{val:e});if(typeof e=="object"&&e!==null&&typeof e.toDate=="function")return jsx(Vt,{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,r)=>jsx("li",{class:"break-all",children:typeof n=="object"?JSON.stringify(n):String(n)},r)),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(([r,o])=>jsxs(Fragment,{children:[jsx("dt",{class:"text-base-content/50 font-semibold whitespace-nowrap",children:r}),jsx("dd",{class:"break-all",children:String(o??"")})]})),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 Jt=`// \u2500\u2500 Form validation + array serialization \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
|
|
137
227
|
document.addEventListener("submit", function (e) {
|
|
138
228
|
var form = e.target;
|
|
139
229
|
if (!form.hasAttribute("data-frs-form")) return;
|
|
@@ -552,7 +642,7 @@ function initColumnReorder(table) {
|
|
|
552
642
|
});
|
|
553
643
|
});
|
|
554
644
|
}
|
|
555
|
-
`;function Re(){return jsx("script",{dangerouslySetInnerHTML:{__html:_t}})}function te(e){return "<!DOCTYPE html>"+renderToString(e)}var ne=({opts:e,children:t})=>{let{title:n,breadcrumb:r,flash:o,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("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:[jsx("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"})})}),jsxs("main",{class:"px-6 py-8 w-full flex-1",children:[r&&r.length>0&&jsx("div",{class:"text-sm breadcrumbs mb-4",children:jsx("ul",{children:r.map((a,d)=>a.href?jsx("li",{children:jsx("a",{href:a.href,children:a.label})},d):jsx("li",{class:"text-base-content/60",children:a.label},d))})}),jsx("h1",{class:"text-2xl font-bold mb-6",children:n}),o&&jsxs("div",{role:"alert",class:`alert ${o.type==="success"?"alert-success":o.type==="warning"?"alert-warning":"alert-error"} mb-6`,children:[jsx("span",{class:"flex-1",children:o.message}),o.action&&jsx("a",{href:o.action.href,...o.action.external?{target:"_blank",rel:"noopener noreferrer"}:{},class:"btn btn-sm btn-outline",children:o.action.label})]}),t]}),jsx(Re,{})]})]})};function Qe(e,t){return te(jsx(ne,{opts:t,children:jsx("div",{dangerouslySetInnerHTML:{__html:e}})}))}function qe(e,t){return te(jsx(ne,{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 Nt=[{value:"==",label:"="},{value:"!=",label:"\u2260"},{value:"in",label:"in"},{value:"not-in",label:"not in"}],xn=[{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"}],vn=[{value:"array-contains",label:"contains"},{value:"array-contains-any",label:"contains any"}];function Rn(e){switch(e){case "ZodNumber":case "ZodBigInt":case "ZodDate":return xn;case "ZodBoolean":return Nt;case "ZodArray":return vn;default:return Nt}}var re="__null__";function wn(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="${re}"]');if(!o){o=document.createElement('option');o.value='${re}';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='${re}';i.readOnly=true;}i.style.opacity='0.55';}else{i.style.opacity='';if(i.tagName==='SELECT'){var o2=i.querySelector('option[value="${re}"][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!=='${re}')?i.dataset._prev:'';}}})(this)`}function Tn(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 we({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:wn(e)}),jsx("span",{children:"\u2205"})]})}function Sn({col:e,active:t}){let n=t?.value??"",r=n===re,o=`fv_input_${e.name.replace(/\./g,"__")}`,s=t?.op,a=s==="in"||s==="not-in";if(e.enumValues&&e.enumValues.length>0){if(a){let d=new Set(n.split(",").map(l=>l.trim()).filter(Boolean)),i=`eg_${e.name.replace(/\./g,"__")}`;return jsxs("div",{class:"flex flex-wrap items-center gap-1 w-full",children:[jsx("input",{type:"hidden",id:o,name:`fv_${e.name}`,value:n}),e.enumValues.map(l=>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:l,checked:d.has(l),"data-enum-group":i,onchange:Tn(o,i)}),jsx("span",{children:l})]},l))]})}return jsxs("div",{class:"flex items-center gap-1 w-full",children:[jsxs("select",{id:o,name:`fv_${e.name}`,class:"select select-sm select-bordered w-full",style:r?"opacity:0.55":void 0,children:[jsx("option",{value:"",selected:n===""&&!r,children:"\u2014"}),e.enumValues.map(d=>jsx("option",{value:d,selected:n===d,children:d},d)),e.nullable&&jsx("option",{value:re,"data-_auto":"1",selected:r,children:"\u2205 null"})]}),e.nullable&&jsx(we,{inputId:o,active:r})]})}if(e.zodType==="ZodBoolean")return jsxs("div",{class:"flex items-center gap-1 w-full",children:[jsxs("select",{id:o,name:`fv_${e.name}`,class:"select select-sm select-bordered w-full",style:r?"opacity:0.55":void 0,children:[jsx("option",{value:"",selected:n===""&&!r,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:re,"data-_auto":"1",selected:r,children:"\u2205 null"})]}),e.nullable&&jsx(we,{inputId:o,active:r})]});if(e.zodType==="ZodArray"){let d=t?.op==="array-contains-any";return jsx("input",{id:o,type:"text",name:`fv_${e.name}`,value:n,placeholder:d?"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:o,type:r?"text":"number",name:`fv_${e.name}`,value:n,placeholder:"value",class:"input input-sm input-bordered w-full",readOnly:r,style:r?"opacity:0.55":void 0,"data-_type":r?"number":void 0}),e.nullable&&jsx(we,{inputId:o,active:r})]}):e.zodType==="ZodDate"?jsxs("div",{class:"flex items-center gap-1 w-full",children:[jsx("input",{id:o,type:r?"text":"datetime-local",name:`fv_${e.name}`,value:n,class:"input input-sm input-bordered w-full",readOnly:r,style:r?"opacity:0.55":void 0,"data-_type":r?"datetime-local":void 0}),e.nullable&&jsx(we,{inputId:o,active:r})]}):jsxs("div",{class:"flex items-center gap-1 w-full",children:[jsx("input",{id:o,type:"text",name:`fv_${e.name}`,value:n,placeholder:"value",class:"input input-sm input-bordered w-full",readOnly:r,style:r?"opacity:0.55":void 0}),e.nullable&&jsx(we,{inputId:o,active:r})]})}function Ue({action:e,columnMeta:t,activeFilters:n,isGroup:r}){let o=Object.fromEntries(n.map(i=>[i.field,i])),s=n.length>0,a=n.length>=2||r&&s,d=t.filter(i=>i.zodType!=="ZodObject"&&i.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:d.map(i=>{let l=Rn(i.zodType),u=o[i.name],m=u?.op??l[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:i.name}),jsxs("div",{class:"flex gap-1.5",children:[l.length>1?jsx("select",{name:`fo_${i.name}`,class:"select select-sm select-bordered w-20 shrink-0",children:l.map(c=>jsx("option",{value:c.value,selected:c.value===m,children:c.label},c.value))}):jsx("input",{type:"hidden",name:`fo_${i.name}`,value:l[0].value}),jsx(Sn,{col:i,active:u})]})]},i.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"}),a&&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"})}),r?"Collection group queries require a composite index":"Multiple filters may require a composite index"]})]})]})})]})}function Ge(e,t,n,r,o,s){let a=n==="create"?`Create ${e}`:`Edit ${e} / ${r??""}`,d=n==="create"?[{label:"Repositories",href:o},{label:e,href:`${o}/${e}`},{label:"New document"}]:[{label:"Repositories",href:o},{label:e,href:`${o}/${e}`},{label:`Edit ${r??""}`}];return te(jsx(ne,{opts:{title:a,breadcrumb:d,basePath:o,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}})})})}))}function We(e,t,n){let r=new URLSearchParams;for(let o of e)r.set(`fv_${o.field}`,o.value),r.set(`fo_${o.field}`,o.op);return t&&(r.set("ob",t.field),r.set("od",t.dir)),n&&r.set("ps",String(n)),r}function Ft(e,t,n,r,o){let s=We(e,r,o);return s.set("cursor",t),s.set("dir",n),`?${s.toString()}`}function Cn(e,t,n,r){let o=We(n,void 0,r);return t?.field===e?t.dir==="asc"&&(o.set("ob",e),o.set("od","desc")):(o.set("ob",e),o.set("od","asc")),`?${o.toString()}`}function On(e,t,n){return `?${We(t,n,e).toString()}`}function Le(e,t,n,r,o,s,a=[],d=[],i=false,l=[],u,m,c,p){let y=`${r}/${e}`,g=`${y}/create`;return te(jsxs(ne,{opts:{title:e,breadcrumb:[{label:"Repositories",href:r},{label:e}],basePath:r,flash:s},children:[a.length>0&&jsx(Ue,{action:y,columnMeta:a,activeFilters:d,isGroup:p}),c&&jsxs("div",{role:"alert",class:`alert ${c.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:c.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:c.type==="index"?"Composite index required":"Query failed"}),jsx("div",{class:"text-sm",children:c.message})]}),c.indexUrl&&jsx("a",{href:c.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",children:[jsxs("div",{class:"flex items-center gap-3",children:[jsxs("span",{class:"text-sm text-base-content/60",children:[t.length," document",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(f=>jsx("a",{href:On(f,d,u),class:`join-item btn btn-xs ${m===f?"btn-active btn-primary":"btn-outline"}`,children:f},f))})]})]}),jsx("a",{href:g,class:"btn btn-primary btn-sm",children:"+ New"})]}),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:[[...n].map((f,b)=>{let x=u?.field===f,h=x?u.dir==="asc"?" \u25B2":" \u25BC":"";return jsx("th",{class:"text-xs font-semibold text-base-content/60 uppercase tracking-wide",children:jsxs("a",{href:Cn(f,u,d,m),class:`hover:text-base-content inline-flex items-center gap-0.5${x?" text-primary font-bold":""}`,children:[f,h]})},b)}),l.map((f,b)=>jsx("th",{class:"text-xs font-semibold text-base-content/60 uppercase tracking-wide",children:f.column},`rel-${b}`)),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+l.length+1,class:"text-center py-16 text-base-content/40",children:"No documents found"})}):t.map((f,b)=>{let x=String(f.docId??f.id??""),h=`${r}/${e}/${encodeURIComponent(x)}/edit`,v=`${r}/${e}/${encodeURIComponent(x)}/delete`;return jsxs("tr",{class:"hover",children:[n.map((R,w)=>jsx("td",{class:"align-top py-2",children:jsx(Ke,{val:f[R]})},w)),l.map((R,w)=>{let T=f[R.key];if(T==null||T==="")return jsx("td",{class:"py-2"},`rel-${w}`);let k=`${r}/${R.targetRepo}?fv_${R.targetKey}=${encodeURIComponent(String(T))}`;return jsx("td",{class:"align-middle py-2",children:jsx("a",{href:k,class:"btn btn-xs btn-ghost btn-outline",children:R.column})},`rel-${w}`)}),jsx("td",{class:"align-middle text-right whitespace-nowrap py-2",children:jsxs("div",{class:"flex gap-1 justify-end",children:[jsx("a",{href:h,class:"btn btn-xs btn-outline",children:"Edit"}),i&&jsx("form",{method:"post",action:v,onsubmit:"return confirm('Delete this document?')",children:jsx("button",{type:"submit",class:"btn btn-xs btn-error btn-outline",children:"Delete"})})]})})]},b)})})]})}),(o.hasPrev||o.hasNext)&&jsxs("div",{class:"flex justify-center items-center mt-6 gap-2",children:[o.hasPrev?jsx("a",{href:Ft(d,o.prevCursor,"prev",u,m),class:"btn btn-sm btn-outline",children:"\u2190 Previous"}):jsx("button",{class:"btn btn-sm btn-outline",disabled:true,children:"\u2190 Previous"}),o.hasNext?jsx("a",{href:Ft(d,o.nextCursor,"next",u,m),class:"btn btn-sm btn-outline",children:"Next \u2192"}):jsx("button",{class:"btn btn-sm btn-outline",disabled:true,children:"Next \u2192"})]})]}))}function De(e,t){return Qe(e,t)}function He(e,t){return qe(e,t)}function Ve(e,t,n,r,o,s,a,d,i,l,u,m,c,p){return Le(e,t,n,r,o,s,a,d,i,l,u,m,c,p)}function oe(e,t,n,r,o,s){return Ge(e,t,n,r,o,s)}var An=new Set(["<","<=",">",">=","!="]),$n=new Set(["array-contains","array-contains-any"]);function Je(e){return e==="desc"?"DESCENDING":"ASCENDING"}function kn(e){let t=e.split("/").filter(Boolean);return t[t.length-1]??e}function Pn(e,t,n,r,o){let s=[],a=new Set;for(let i of r)if(i.op==="=="||i.op==="in"||i.op==="not-in"){if(a.has(i.field))continue;a.add(i.field),s.push({fieldPath:i.field,order:"ASCENDING"});}for(let i of r)if($n.has(i.op)){if(a.has(i.field))continue;a.add(i.field),s.push({fieldPath:i.field,arrayConfig:"CONTAINS"});}for(let i of r)if(An.has(i.op)){if(a.has(i.field))continue;a.add(i.field);let l=o?.field===i.field?Je(o.dir):"ASCENDING";s.push({fieldPath:i.field,order:l});}if(o&&!a.has(o.field)&&s.push({fieldPath:o.field,order:Je(o.dir)}),s.length===1&&n)return _n(e,t,s[0]);let d=o&&s.some(i=>i.fieldPath===o.field)?Je(o.dir):"ASCENDING";return s.push({fieldPath:"__name__",order:d}),Dn(e,t,n,s)}function Dn(e,t,n,r,o="(default)"){let s=`projects/${e}/databases/${o}/collectionGroups/${t}/indexes/_`,a=[...et(1,s),...Ee(2,n?2:1)];for(let l of r)a.push(...Zt(3,zt(l)));let d=o==="(default)"?"-default-":o,i=encodeURIComponent(jt(a));return `https://console.firebase.google.com/project/${e}/firestore/databases/${d}/indexes?create_composite=${i}`}function En(e){return e.match(/https:\/\/console\.firebase\.google\.com[^\s)"]*/)?.[0]}function Xe(e){let t=[],n=e>>>0;for(;n>=128;)t.push(n&127|128),n>>>=7;return t.push(n&127),t}function Ye(e,t){return e<<3|t}function et(e,t){let n=Array.from(new TextEncoder().encode(t));return [Ye(e,2),...Xe(n.length),...n]}function Ee(e,t){return [Ye(e,0),...Xe(t)]}function Zt(e,t){return [Ye(e,2),...Xe(t.length),...t]}function zt(e){let t=[...et(1,e.fieldPath)];return e.arrayConfig==="CONTAINS"?t.push(...Ee(3,1)):t.push(...Ee(2,e.order==="DESCENDING"?2:1)),t}function jt(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 _n(e,t,n,r="(default)"){let o=`projects/${e}/databases/${r}/collectionGroups/${t}/fields/${n.fieldPath}`,s=[...et(1,o),...Ee(2,2),...Zt(3,zt(n))],a=r==="(default)"?"-default-":r,d=encodeURIComponent(jt(s));return `https://console.firebase.google.com/project/${e}/firestore/databases/${a}/indexes/automatic?create_exemption=${d}`}function In(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 o of n)if(typeof o=="string"&&o.length>0)return o;return process.env.GCLOUD_PROJECT||process.env.GOOGLE_CLOUD_PROJECT||process.env.FIREBASE_PROJECT_ID||void 0}function le(e){let t=e;return t?t.code===9?true:typeof t.message=="string"?t.message.includes("requires an index"):false:false}function Te(e,t){let n=e??{},r=le(e),o;if(r&&(o=n.message?En(n.message):void 0,!o)){let s=In(t.ref);if(s){let a=kn(t.path);o=Pn(s,a,t.isGroup,t.filters,t.sort);}}return {type:r?"index":"error",message:r?"This query requires a composite index that does not exist yet.":n.message??"Query failed",indexUrl:o}}var Mt="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";function Fn(){let e="";for(let t=0;t<20;t++)e+=Mt.charAt(Math.floor(Math.random()*Mt.length));return e}function Bt(e,t){if(!t)return;let n=e[t];if(typeof n!="string"||!n)return;let r=n.split("/").filter(Boolean),o=[];for(let s=1;s<r.length;s+=2)o.push(r[s]);return o.length>0?o:void 0}async function tt(e,t){let n=e.documentKey??"docId",r=`by${n.charAt(0).toUpperCase()}${n.slice(1)}`;if(typeof e.repo.get[r]=="function")try{let s=await e.repo.get[r](t);if(s)return s}catch{}return (await e.repo.query.by({where:[[n,"==",t]],limit:1}))[0]??null}function nt(e,t,n){let r=e.documentKey??"docId",o=Te(n,{ref:e.repo.ref,path:e.path,isGroup:!!e.isGroup,filters:[{field:r,op:"==",value:t}]});return o.type==="index"?{type:"warning",message:"Loading this document requires a composite index that does not exist yet.",...o.indexUrl?{action:{href:o.indexUrl,label:"Create Index \u2192",external:true}}:{}}:{type:"error",message:o.message}}function P(e,t,n=200){e.status(n).set("Content-Type","text/html; charset=utf-8").send(t);}function rt(e,t){e.status(302).set("Location",t).send("");}function ot(e,t){let n=t.shape,r={};for(let[o,s]of Object.entries(n)){let a=at(s);if(a==="ZodObject"){if(e[o+"__isnull"]==="1"){r[o]=null;continue}let l={},u=false;for(let[p,y]of Object.entries(e))p.startsWith(`${o}.`)&&(l[p.slice(o.length+1)]=y,u=true);if(u){let p=s;for(;;){let y=Z(p);if(y==="ZodOptional"||y==="ZodNullable"||y==="ZodDefault")p=K(p);else break}r[o]=ot(l,p);continue}let m=e[o],c=Array.isArray(m)?m[m.length-1]:m;if(c)try{r[o]=JSON.parse(c);}catch{r[o]=c;}continue}let d=e[o],i=Array.isArray(d)?d[d.length-1]:d;if(e[o+"__isnull"]==="1"){r[o]=null;continue}if(i===void 0||i===""){a==="ZodBoolean"&&(r[o]=false);continue}switch(a){case "ZodBoolean":i==="__null__"?r[o]=null:r[o]=i==="true"||i==="on"||i==="1";break;case "ZodNumber":case "ZodBigInt":r[o]=Number(i);break;case "ZodDate":r[o]=new Date(i);break;case "ZodArray":try{r[o]=JSON.parse(i);}catch{r[o]=i;}break;default:if(i.startsWith("{")||i.startsWith("["))try{r[o]=JSON.parse(i);break}catch{}r[o]=i;}}return r}function Kt(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 r=new Date(e);isNaN(r.getTime())||(t=r);}if(!t||isNaN(t.getTime()))return null;let n=r=>String(r).padStart(2,"0");return `${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())}T${n(t.getHours())}:${n(t.getMinutes())}`}function at(e){let t=e;for(;;){let n=Z(t);if(n==="ZodOptional"||n==="ZodNullable"||n==="ZodDefault")t=K(t);else return n}}function Zn(e){let t=e;for(;;){let n=Z(t);if(n==="ZodOptional"||n==="ZodNullable"||n==="ZodDefault")t=K(t);else return t}}function Qt(e){let t=e;for(;;){let n=Z(t);if(n==="ZodOptional"||n==="ZodNullable")return true;if(n==="ZodDefault"){t=K(t);continue}return false}}function qt(e){let t=Zn(e),n=Z(t);if(n==="ZodEnum"){let r=be(t);return r.length>0?r:void 0}if(n==="ZodNativeEnum"){let r=xe(t),o=Object.values(r).filter(s=>typeof s=="string");return o.length>0?o:void 0}if(n==="ZodLiteral"){let r=ke(t);return typeof r=="string"?[r]:void 0}}function Ut(e,t,n=""){let r={};for(let o of Object.keys(t.shape)){let s=n?`${n}.${o}`:o,a=e[o];if(a===null){r[s]="__null__";continue}if(a===void 0)continue;let d=t.shape[o];for(;;){let l=Z(d);if(l==="ZodOptional"||l==="ZodNullable"||l==="ZodDefault")d=K(d);else break}let i=Z(d);if(i==="ZodObject"&&typeof a=="object"&&a!==null&&!Array.isArray(a)){let l=Ut(a,d,s);Object.assign(r,l);}else if(i==="ZodDate"){let l=Kt(a);l!==null&&(r[s]=l);}else if(typeof a=="object"&&a!==null&&!Array.isArray(a)&&("_seconds"in a||typeof a.toDate=="function")){let l=Kt(a);r[s]=l??JSON.stringify(a,null,2);}else typeof a=="object"?r[s]=JSON.stringify(a,null,2):r[s]=String(a);}return r}function st(e,t){return e.map(n=>({...n,defaultValue:t[n.name]??n.defaultValue,nested:n.nested?st(n.nested,t):void 0}))}function zn(e,t){let n=new Set(["==","!=","<","<=",">",">=","in","not-in","array-contains","array-contains-any"]),r=[];for(let[o,s]of Object.entries(e)){if(!o.startsWith("fv_"))continue;let a=o.slice(3);if(!t.has(a))continue;let d=(s??"").trim();if(!d)continue;let i=e[`fo_${a}`]??"==",l=n.has(i)?i:"==";r.push({field:a,op:l,value:d});}return r}function jn(e){let t="__null__",n=r=>r===t?null:r==="true"?true:r==="false"?false:r!==""&&!isNaN(Number(r))?Number(r):r;return e.map(r=>{if(r.op==="array-contains-any"||r.op==="in"||r.op==="not-in"){let o=r.value.split(",").map(s=>s.trim()).filter(s=>s!==""&&s!==t).map(s=>n(s));return [r.field,r.op,o]}return [r.field,r.op,n(r.value)]})}function Gt(e,t,n=""){let r=[];for(let o of e){let s=n?`${n}.${o}`:o,a=t.shape[o];if(!a){r.push({name:s,zodType:"ZodString"});continue}let d=at(a);if(d==="ZodObject"){let i=a;for(;;){let u=Z(i);if(u==="ZodOptional"||u==="ZodNullable"||u==="ZodDefault")i=K(i);else break}let l=he(i);r.push(...Gt(Object.keys(l),i,s));}else r.push({name:s,zodType:d,nullable:Qt(a),enumValues:qt(a)});}return r}function Mn(e,t){let n=t.split("."),r=e;for(let o of n){for(;;){let a=Z(r);if(a==="ZodOptional"||a==="ZodNullable"||a==="ZodDefault")r=K(r);else break}let s=he(r);if(!(o in s))return null;r=s[o];}return r}function de(e,t){if(!t||t.length===0)return e;let n=[],r=new Map;for(let s of t){let a=s.indexOf(".");if(a===-1)n.push(s);else {let d=s.slice(0,a),i=s.slice(a+1);r.has(d)||r.set(d,[]),r.get(d).push(i);}}let o={};for(let s of n)s in e.shape&&(o[s]=e.shape[s]);for(let[s,a]of r){if(!(s in e.shape))continue;let d=e.shape[s];for(;;){let i=Z(d);if(i==="ZodOptional"||i==="ZodNullable"||i==="ZodDefault")d=K(d);else break}if(Z(d)!=="ZodObject"){o[s]=e.shape[s];continue}o[s]=de(d,a);}return z$1.object(o)}function ce(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",a=process.env.FUNCTION_REGION??"us-central1",d=(process.env.FUNCTION_TARGET??"").replace(/\./g,"-");return `/${s}/${a}/${d}${n}`}let r=process.env.K_SERVICE,o=e.hostname??e.headers?.host??"";return r&&o.includes("cloudfunctions.net")?`/${r.toLowerCase()}${n}`:n}function Wt(e,t){return {handleDashboard:(l,u)=>{let m=ce(l,t),c=Object.values(e).map(p=>({name:p.name,path:p.path}));P(u,He(c,m));},handleList:async(l,u)=>{let m=l.params.repoName;if(!m){P(u,"Bad request",400);return}let c=e[m];if(!c){P(u,"Repository not found",404);return}let p=c.pageSize??25,y=l.query??{},g=y.cursor,f=y.dir==="prev"?"prev":"next",b=y.ob??"",x=y.od==="desc"?"desc":"asc",h=b?{field:b,dir:x}:void 0,v=parseInt(y.ps??""),R=Number.isFinite(v)&&v>0?Math.min(v,200):p,w=c.listColumns??Object.keys(c.schema.shape),T=c.documentKey??"docId",k=[T,...w.filter(j=>j!==T)],C=c.filterableFields?(()=>{let j=[];for(let V of c.filterableFields)(V.includes(".")||w.includes(V))&&j.push(V);return j})():w,O=(()=>{let j=[];for(let V of C)if(V.includes(".")){let pe=Mn(c.schema,V);j.push({name:V,zodType:pe?at(pe):"ZodString",nullable:pe?Qt(pe):false,enumValues:pe?qt(pe):void 0});}else j.push(...Gt([V],c.schema));return j})(),D=new Set(O.map(j=>j.name)),N=zn(y,D),U=jn(N),M;if(g)try{let j=c.repo.ref;typeof j.doc=="function"&&(M=await j.doc(g).get());}catch{}let H=await c.repo.query.paginate({pageSize:R,cursor:M,direction:f,...U.length>0?{where:U}:{},...h?{orderBy:[{field:h.field,direction:h.dir}]}:{}}).catch(j=>({queryError:Te(j,{ref:c.repo.ref,path:c.path,isGroup:!!c.isGroup,filters:N,sort:h})})),E="queryError"in H,ue=E?[]:H.data,nn=E?"":H.nextCursor?.id??"",rn=E?"":H.prevCursor?.id??"",on=E?H.queryError:void 0,sn=ce(l,t);P(u,Ve(c.name,ue,k,sn,{hasPrev:E?false:H.hasPrevPage,hasNext:E?false:H.hasNextPage,prevCursor:rn,nextCursor:nn},void 0,O,N,c.allowDelete??false,c.relationalMeta,h,R,on,c.isGroup));},handleCreateForm:(l,u)=>{let m=l.params.repoName;if(!m){P(u,"Bad request",400);return}let c=e[m];if(!c){P(u,"Repository not found",404);return}let p=ce(l,t),y=de(c.schema,c.createFields),g=W(y),f=`${p}/${c.name}/create`,b=ee(g,f,"POST","Create document");P(u,oe(c.name,b,"create",null,p));},handleCreateSubmit:async(l,u)=>{let m=l.params.repoName;if(!m){P(u,"Bad request",400);return}let c=e[m];if(!c){P(u,"Repository not found",404);return}let p=ce(l,t),y=l.body??{},g=ot(y,c.schema),f=de(c.schema,c.createFields),b=f.safeParse(g);if(!b.success){let x=W(f),h=`${p}/${c.name}/create`,v=ee(x,h,"POST","Create document"),R=b.error.issues.map(w=>`${w.path.join(".")}: ${w.message}`).join(", ");P(u,oe(c.name,v,"create",null,p,{type:"error",message:`Validation error: ${R}`}),422);return}try{if(c.isGroup&&c.parentKeys&&c.parentKeys.length>0){let x={...b.data};c.createdKey&&(x[c.createdKey]=new Date);let h=c.parentKeys.filter(T=>!x[T]);if(h.length>0)throw new Error(`Missing parent key(s) for subcollection create: ${h.join(", ")}`);let v=c.parentKeys.map(T=>x[T]),R=c.documentKey??"docId",w=x[R]||Fn();await c.repo.set(...v,w,x);}else await c.repo.create(b.data);rt(u,`${p}/${c.name}?flash=created`);}catch(x){let h=de(c.schema,c.createFields),v=W(h),R=`${p}/${c.name}/create`,w=ee(v,R,"POST","Create document");P(u,oe(c.name,w,"create",null,p,{type:"error",message:`Save error: ${x.message}`}),500);}},handleEditForm:async(l,u)=>{let m=l.params.repoName,c=l.params.id;if(!m||!c){P(u,"Bad request",400);return}let p=e[m];if(!p){P(u,"Repository not found",404);return}let y=ce(l,t),g=null;try{g=await tt(p,c);}catch(R){let w=nt(p,c,R),T=le(R)?424:500;P(u,De("",{title:`Edit ${p.name} / ${c}`,basePath:y,breadcrumb:[{label:"Repositories",href:y},{label:p.name,href:`${y}/${p.name}`},{label:`Edit ${c}`}],flash:w}),T);return}if(!g){P(u,"Document not found",404);return}let f=Ut(g,p.schema),b=de(p.schema,p.mutableFields),x=st(W(b),f),h=`${y}/${p.name}/${encodeURIComponent(c)}/edit`,v=ee(x,h,"POST","Save changes");P(u,oe(p.name,v,"edit",c,y));},handleEditSubmit:async(l,u)=>{let m=l.params.repoName,c=l.params.id;if(!m||!c){P(u,"Bad request",400);return}let p=e[m];if(!p){P(u,"Repository not found",404);return}let y=ce(l,t),g=l.body??{},f=ot(g,p.schema),b=de(p.schema,p.mutableFields),h=b.partial().safeParse(f);if(!h.success){let v=Object.fromEntries(Object.entries(g).map(([C,O])=>[C,Array.isArray(O)?O.join(","):O??""])),R=st(W(b),v),w=`${y}/${p.name}/${encodeURIComponent(c)}/edit`,T=ee(R,w,"POST","Save changes"),k=h.error.issues.map(C=>`${C.path.join(".")}: ${C.message}`).join(", ");P(u,oe(p.name,T,"edit",c,y,{type:"error",message:`Validation error: ${k}`}),422);return}try{let v=await tt(p,c),R=(v&&Bt(v,p.pathKey))??[c];await p.repo.update(...R,h.data),rt(u,`${y}/${p.name}?flash=updated`);}catch(v){let R=de(p.schema,p.mutableFields),w=W(R),T=`${y}/${p.name}/${encodeURIComponent(c)}/edit`,k=ee(w,T,"POST","Save changes"),C=le(v)?nt(p,c,v):{type:"error",message:`Save error: ${v.message}`},O=le(v)?424:500;P(u,oe(p.name,k,"edit",c,y,C),O);}},handleDelete:async(l,u)=>{let m=l.params.repoName,c=l.params.id;if(!m||!c){P(u,"Bad request",400);return}let p=e[m];if(!p){P(u,"Repository not found",404);return}if(!p.allowDelete){P(u,"Delete is not allowed for this repository",403);return}let y=ce(l,t);try{let g=await tt(p,c),f=(g&&Bt(g,p.pathKey))??[c];await p.repo.delete(...f),rt(u,`${y}/${p.name}?flash=deleted`);}catch(g){let f=le(g)?nt(p,c,g):{type:"error",message:`Delete error: ${g.message}`},b=le(g)?424:500;P(u,De("",{title:`Delete ${p.name} / ${c}`,basePath:y,breadcrumb:[{label:"Repositories",href:y},{label:p.name,href:`${y}/${p.name}`},{label:`Delete ${c}`}],flash:f}),b);}}}}function Bn(e){let t=[],n=e.replace(/[.*+?^${}()|[\]\\]/g,r=>r===":"?r:`\\${r}`).replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g,(r,o)=>(t.push(o),"([^/]+)"));return {pattern:new RegExp(`^${n}$`),paramNames:t}}function Kn(e){let t=e.path??e.url??"/",n=t.indexOf("?");return n===-1?t:t.slice(0,n)}var X=class{constructor(){this.routes=[];this.middlewares=[];this.notFoundHandler=(t,n)=>{n.status(404).send("Not Found");};this.errorHandler=(t,n,r)=>{console.error("[MiniRouter]",t),r.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,r){let{pattern:o,paramNames:s}=Bn(n);return this.routes.push({method:t.toUpperCase(),pattern:o,paramNames:s,handler:r}),this}async handle(t,n){let r=(t.method??"GET").toUpperCase(),o=Kn(t),s=null,a={};for(let l of this.routes){if(l.method!==r)continue;let u=o.match(l.pattern);if(u){s=l,a={},l.paramNames.forEach((m,c)=>{a[m]=decodeURIComponent(u[c+1]??"");});break}}let d=Object.assign(t,{params:a}),i=s?s.handler:this.notFoundHandler;try{await this.runMiddlewareChain(d,n,i);}catch(l){this.errorHandler(l,t,n);}}async runMiddlewareChain(t,n,r){let o=0,s=async()=>{if(o<this.middlewares.length){let a=this.middlewares[o++];await a(t,n,s);}else await r(t,n);};await s();}};async function Qn(e){return typeof e.rawBody=="string"?e.rawBody:Buffer.isBuffer(e.rawBody)?e.rawBody.toString("utf8"):""}function qn(e){let t={};if(!e)return t;for(let n of e.split("&")){let r=n.indexOf("=");if(r===-1)continue;let o=decodeURIComponent(n.slice(0,r).replace(/\+/g," ")),s=decodeURIComponent(n.slice(r+1).replace(/\+/g," ")),a=t[o];a===void 0?t[o]=s:Array.isArray(a)?a.push(s):t[o]=[a,s];}return t}function Lt(e){let{basePath:t="/",repos:n,parseBody:r=true,auth:o,middleware:s=[],httpsOptions:a}=e,d=t==="/"?"":t.replace(/\/$/,""),i={};for(let[c,p]of Object.entries(n)){let y=p.schema??p.repo.schema??null;if(!y)throw new Error(`[createAdminServer] Repository "${c}" has no Zod schema. Either use createRepositoryConfig(schema)(config) or pass schema: explicitly.`);let g,f,b;if(p.fieldsConfig){let v=p.fieldsConfig;g=[],f=[],b=[];for(let[R,w]of Object.entries(v))for(let T of w)T==="filterable"?g.push(R):T==="mutable"?f.push(R):T==="create"&&b.push(R);g.length===0&&(g=void 0),f.length===0&&(f=void 0),b.length===0&&(b=void 0);}let x=(()=>{let v=p.repo._parentKeys;return v&&v.length>0?v:void 0})();if(x&&b)for(let v of x)b.includes(v)||b.push(v);let h={name:c,path:p.path,repo:p.repo,schema:y,documentKey:p.documentKey??"docId",pathKey:p.repo._pathKey??void 0,isGroup:!!p.repo._isGroup,parentKeys:x,createdKey:p.repo._createdKey??void 0,listColumns:p.listColumns,pageSize:p.pageSize,filterableFields:g,mutableFields:f,createFields:b,allowDelete:p.allowDelete??false,relationalMeta:(()=>{if(!p.relationalFields||p.relationalFields.length===0)return;let v=p.repo.relationalKeys??{},R=[];for(let w of p.relationalFields){let T=v[w.key];T&&R.push({key:w.key,column:w.column,targetRepo:String(T.repo),targetKey:String(T.key),type:T.type});}return R.length>0?R:void 0})()};i[c]=h;}let l=Wt(i,d),u=new X;if(r&&u.use(async(c,p,y)=>{let g=c,f=String(g.headers?.["content-type"]??"");if(f.includes("application/x-www-form-urlencoded")){let b=await Qn(g);c.body=qn(b);}else if(f.includes("application/json")&&typeof g.body=="string")try{c.body=JSON.parse(g.body);}catch{}await y();}),o)if(typeof o=="function")u.use(o);else {let c=o.realm??"Admin",p="Basic "+Buffer.from(`${o.username}:${o.password}`).toString("base64");u.use((y,g,f)=>{if((y.headers?.authorization??"")!==p){g.status(401).set("WWW-Authenticate",`Basic realm="${c}"`).set("Content-Type","text/plain").send("Unauthorized");return}f();});}for(let c of s)u.use(c);u.get(`${d}/`,l.handleDashboard),u.get(`${d}`,l.handleDashboard),u.get(`${d}/:repoName`,l.handleList),u.get(`${d}/:repoName/create`,l.handleCreateForm),u.post(`${d}/:repoName/create`,l.handleCreateSubmit),u.get(`${d}/:repoName/:id/edit`,l.handleEditForm),u.post(`${d}/:repoName/:id/edit`,l.handleEditSubmit),u.post(`${d}/:repoName/:id/delete`,l.handleDelete);let m=async(c,p)=>{await u.handle(c,p);};return a&&(m.httpsOptions=a),m}function lt(e,t,n=200){let r=_(t);e.status(n).set("Content-Type","application/json; charset=utf-8").send(JSON.stringify(r));}function ye(e,t,n,r=200){lt(e,{success:true,data:t,meta:n},r);}function z(e,t,n=400){lt(e,{success:false,error:t},n);}function it(e,t,n,r,o){let s=Te(t,n),a=s.type==="index",d=a?424:500,l={success:false,error:a?s.message:o&&t instanceof Error?t.message:r};a&&(l.errorType="index",s.indexUrl&&(l.indexUrl=s.indexUrl)),lt(e,l,d);}var Ht="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";function Un(){let e="";for(let t=0;t<20;t++)e+=Ht.charAt(Math.floor(Math.random()*Ht.length));return e}function me(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(r=>ze(r)??r,e);if(n==="ZodObject"||n==="object"){let r=e.shape,o={};for(let[s,a]of Object.entries(r))o[s]=me(a);return z$1.object(o)}if(n==="ZodArray"||n==="array"){let r=t.element??t.type;if(r)return z$1.array(me(r))}if(n==="ZodOptional"||n==="optional"){let r=t.innerType;if(r)return me(r).optional()}if(n==="ZodNullable"||n==="nullable"){let r=t.innerType;if(r)return me(r).nullable()}if(n==="ZodDefault"||n==="default"){let r=t.innerType,o=t.defaultValue;if(r){let s=me(r);return typeof o=="function"?s.default(o()):s.default(o)}}return e}function Gn(e,t,n=[]){let r=e.shape,o={},s=t&&t.length>0?t:Object.keys(r);for(let a of s){if(n.includes(a))continue;let d=a.split(".")[0];d&&r[d]&&(o[d]=r[d]);}return z$1.object(o)}function Vt(e,t,n,r=false,o=[]){try{let s=Gn(e,n,o),a=r?s.partial():s;return {success:!0,data:(Ze()==="normalize"?me(a):a).parse(t)}}catch(s){return s instanceof z$1.ZodError?{success:false,error:`Validation failed: ${s.issues.map(d=>`${d.path.join(".")}: ${d.message}`).join(", ")}`}:{success:false,error:"Validation failed"}}}function Wn(e,t){let n=[],r=t?new Set(t):null,o={eq:"==",ne:"!=",lt:"<",lte:"<=",gt:">",gte:">=",in:"in",nin:"not-in",contains:"array-contains",containsAny:"array-contains-any"};for(let[s,a]of Object.entries(e)){if(a===void 0||["cursor","limit","pageSize","orderBy","orderDir","select"].includes(s))continue;let d=Array.isArray(a)?a[0]:a;if(d===void 0||d==="")continue;let i=s.match(/^(\w+)__(\w+)$/),l,u="==";if(i&&i[1]&&i[2]){l=i[1];let c=i[2];if(o[c])u=o[c];else continue}else if(!i)l=s;else continue;if(r&&!r.has(l))continue;let m=d;u==="in"||u==="not-in"||u==="array-contains-any"?m=d.split(",").map(c=>Jt(c.trim())):m=Jt(d),n.push({field:l,op:u,value:m});}return n}function Jt(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 _e(e){return e?{docId:e.id}:null}async function Xt(e,t){if(!t||typeof t!="object")return;let n=t.docId;if(typeof n=="string")try{let r=e.repo.ref;if(typeof r.doc!="function")return;let o=await r.doc(n).get();return o.exists?o:void 0}catch{return}}function Yt(e,t,n){function r(p,y){return !p||!e[p]?(z(y,`Repository "${p}" not found`,404),null):e[p]}function o(p,y){if(!y)return;let g=p[y];if(typeof g!="string"||!g)return;let f=g.split("/").filter(Boolean),b=[];for(let x=1;x<f.length;x+=2)b.push(f[x]);return b.length>0?b:void 0}async function s(p,y){let g=`by${p.documentKey.charAt(0).toUpperCase()}${p.documentKey.slice(1)}`,f=p.repo.get[g];if(typeof f=="function")try{let x=await f(y);if(x)return x}catch{}return (await p.repo.query.by({where:[[p.documentKey,"==",y]],limit:1}))[0]??null}async function a(p,y){let g=p.params||{},f=r(g.repoName,y);if(!f)return;let b=[],x;try{let h=p.query??{},v=Math.min(Number(h.pageSize)||f.pageSize,100),R=h.cursor,w=h.direction?.toLowerCase()==="prev"?"prev":"next",T=h.orderBy,k=h.orderDir?.toLowerCase()==="desc"?"desc":"asc",C=h.select,O=C?C.split(",").map(E=>E.trim()):void 0,D;f.allowedIncludes&&h.includes&&(D=(typeof h.includes=="string"?h.includes.split(",").map(ue=>ue.trim()):Array.isArray(h.includes)?h.includes:[]).filter(ue=>typeof ue=="string"&&f.allowedIncludes.includes(ue)),D?.length===0&&(D=void 0));let N=Wn(h,f.filterableFields);b=N.map(E=>({field:E.field,op:E.op,value:String(E.value??"")})),T&&(x={field:T,dir:k});let U={pageSize:v,direction:w};if(R)try{let E=typeof R=="string"?JSON.parse(R):R;U.cursor=await Xt(f,E);}catch{}T&&(U.orderBy=[{field:T,direction:k}]),N.length>0&&(U.where=N.map(E=>[E.field,E.op,E.value])),O&&(U.select=O),D&&(U.include=D);let M=await f.repo.query.paginate(U),H={items:M.data,hasNextPage:M.hasNextPage,hasPrevPage:M.hasPrevPage,nextCursor:_e(M.nextCursor),prevCursor:_e(M.prevCursor)};ye(y,H,{pageSize:v,hasMore:M.hasNextPage});}catch(h){it(y,h,{ref:f.repo.ref,path:f.path,isGroup:!!f.isGroup,filters:b,sort:x},"Failed to fetch documents",n);}}async function d(p,y){let g=p.params||{},f=r(g.repoName,y);if(!f)return;let b=[],x;try{let h=p.body??{},v=Math.min(h.pageSize||f.pageSize,100),R=h.direction==="prev"?"prev":"next";h.where&&(b=h.where.map(C=>({field:String(C[0]),op:C[1],value:String(C[2]??"")}))),h.orderBy&&h.orderBy[0]&&(x={field:h.orderBy[0].field,dir:h.orderBy[0].direction==="desc"?"desc":"asc"});let w={pageSize:v,direction:R};if(h.cursor)try{let C=typeof h.cursor=="string"?JSON.parse(h.cursor):h.cursor;w.cursor=await Xt(f,C);}catch{}if(f.allowedIncludes&&h.includes&&h.includes.length>0){let C=h.includes.filter(O=>typeof O=="string"?f.allowedIncludes.includes(O):typeof O=="object"&&O!==null&&"relation"in O&&typeof O.relation=="string"?f.allowedIncludes.includes(O.relation):!1);C.length>0&&(w.include=C);}if(h.where&&h.where.length>0){if(f.filterableFields){let C=new Set(f.filterableFields),O=h.where.filter(D=>!C.has(D[0]));if(O.length>0){z(y,`Fields not filterable: ${O.map(D=>D[0]).join(", ")}`,400);return}}w.where=h.where;}if(h.orWhere&&h.orWhere.length>0){if(f.filterableFields){let C=new Set(f.filterableFields),O=h.orWhere.filter(D=>!C.has(D[0]));if(O.length>0){z(y,`Fields not filterable: ${O.map(D=>D[0]).join(", ")}`,400);return}}w.orWhere=h.orWhere;}if(h.orWhereGroups&&h.orWhereGroups.length>0){if(f.filterableFields){let C=new Set(f.filterableFields);for(let O of h.orWhereGroups){let D=O.filter(N=>!C.has(N[0]));if(D.length>0){z(y,`Fields not filterable: ${D.map(N=>N[0]).join(", ")}`,400);return}}}w.orWhereGroups=h.orWhereGroups;}h.orderBy&&h.orderBy.length>0&&(w.orderBy=h.orderBy),h.select&&h.select.length>0&&(w.select=h.select);let T=await f.repo.query.paginate(w),k={items:T.data,hasNextPage:T.hasNextPage,hasPrevPage:T.hasPrevPage,nextCursor:_e(T.nextCursor),prevCursor:_e(T.prevCursor)};ye(y,k,{pageSize:v,hasMore:T.hasNextPage});}catch(h){it(y,h,{ref:f.repo.ref,path:f.path,isGroup:!!f.isGroup,filters:b,sort:x},"Failed to query documents",n);}}async function i(p,y){let g=p.params||{},f=r(g.repoName,y);if(!f)return;let b=g.id;if(!b){z(y,"Document ID required",400);return}try{let x=await s(f,b);if(!x){z(y,"Document not found",404);return}ye(y,x);}catch(x){it(y,x,{ref:f.repo.ref,path:f.path,isGroup:!!f.isGroup,filters:[{field:f.documentKey,op:"==",value:b}]},"Failed to fetch document",n);}}async function l(p,y){let g=p.params||{},f=r(g.repoName,y);if(f)try{let b=p.body??{},x=Vt(f.schema,b,f.createFields,!1,f.systemKeys);if(!x.success){z(y,x.error,400);return}if(f.validate){let v=await f.validate(x.data,"create");if(v){z(y,v,400);return}}let h;if(f.isGroup&&f.parentKeys&&f.parentKeys.length>0){let v={...x.data};f.createdKey&&(v[f.createdKey]=new Date);let R=f.parentKeys.filter(k=>!v[k]);if(R.length>0){z(y,`Missing parent key(s) for subcollection create: ${R.join(", ")}`,400);return}let w=f.parentKeys.map(k=>v[k]),T=v[f.documentKey]||Un();h=await f.repo.set(...w,T,v);}else h=await f.repo.create(x.data);ye(y,h,void 0,201);}catch(b){let x=n&&b instanceof Error?b.message:"Failed to create document";z(y,x,500);}}async function u(p,y,g){let f=p.params||{},b=r(f.repoName,y);if(!b)return;let x=f.id;if(!x){z(y,"Document ID required",400);return}try{let h=p.body??{},v=Vt(b.schema,h,b.mutableFields,g,b.systemKeys);if(!v.success){z(y,v.error,400);return}if(b.validate){let k=await b.validate(v.data,"update");if(k){z(y,k,400);return}}let R=await s(b,x),w=(R&&o(R,b.pathKey))??[x],T=await b.repo.update(...w,v.data);ye(y,T);}catch(h){let v=n&&h instanceof Error?h.message:"Failed to update document";z(y,v,500);}}async function m(p,y){let g=p.params||{},f=r(g.repoName,y);if(!f)return;if(!f.allowDelete){z(y,"Delete not allowed for this repository",403);return}let b=g.id;if(!b){z(y,"Document ID required",400);return}try{let x=await s(f,b),h=(x&&o(x,f.pathKey))??[b];await f.repo.delete(...h),ye(y,{deleted:!0});}catch(x){let h=n&&x instanceof Error?x.message:"Failed to delete document";z(y,h,500);}}function c(p,y){y.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:a,handleQuery:d,handleGet:i,handleCreate:l,handleUpdate:u,handleDelete:m,handleOptions:c}}function ct(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 G(e){return {$ref:`#/components/schemas/${e}`}}function B(e){return {description:e,content:{"application/json":{schema:G("ErrorResponse")}}}}function Ce(e,t){return {description:e,content:{"application/json":{schema:{type:"object",properties:{success:{type:"boolean",enum:[true]},data:t},required:["success","data"]}}}}}function en(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 Ln(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 Hn(e){let t=e.filterableFields??Object.keys(e.schema.shape),n=["eq","ne","lt","lte","gt","gte","in","nin","contains"],r=[];for(let o of t){r.push({name:o,in:"query",schema:{type:"string"},description:`Filter by ${o} (equality)`});for(let s of n)r.push({name:`${o}__${s}`,in:"query",schema:{type:"string"},description:`Filter ${o} with operator ${s}`});}return r}function Vn(){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 Jn(e,t,n,r,o){let s={},a=e.name,d=`${t}/${e.name}`,i=`${d}/{${e.documentKey}}`,l={name:e.documentKey,in:"path",required:true,schema:{type:"string"},description:"Unique document identifier"};s[d]={get:{operationId:`list${se(e.name)}`,summary:`List ${e.name} (paginated)`,tags:[a],parameters:[...Ln(e),...Hn(e)],responses:{200:en(G(n)),500:B("Internal server error")}},post:{operationId:`create${se(e.name)}`,summary:`Create a ${L(e.name)}`,tags:[a],requestBody:{required:true,content:{"application/json":{schema:G(r??n)}}},responses:{201:Ce("Document created",G(n)),400:B("Validation error"),500:B("Internal server error")}}},s[`${d}/query`]={post:{operationId:`query${se(e.name)}`,summary:`Query ${e.name} with advanced filters`,tags:[a],requestBody:{required:true,content:{"application/json":{schema:G("QueryRequestBody")}}},responses:{200:en(G(n)),400:B("Invalid query"),500:B("Internal server error")}}};let u={};return u.get={operationId:`get${se(L(e.name))}`,summary:`Get a single ${L(e.name)}`,tags:[a],parameters:[l],responses:{200:Ce("Document found",G(n)),404:B("Document not found"),500:B("Internal server error")}},u.put={operationId:`update${se(L(e.name))}`,summary:`Update a ${L(e.name)} (full replace)`,tags:[a],parameters:[l],requestBody:{required:true,content:{"application/json":{schema:G(o??n)}}},responses:{200:Ce("Document updated",G(n)),400:B("Validation error"),404:B("Document not found"),500:B("Internal server error")}},u.patch={operationId:`patch${se(L(e.name))}`,summary:`Partially update a ${L(e.name)}`,tags:[a],parameters:[l],requestBody:{required:true,content:{"application/json":{schema:{allOf:[G(o??n)],description:"All fields are optional for partial updates"}}}},responses:{200:Ce("Document patched",G(n)),400:B("Validation error"),404:B("Document not found"),500:B("Internal server error")}},e.allowDelete&&(u.delete={operationId:`delete${se(L(e.name))}`,summary:`Delete a ${L(e.name)}`,tags:[a],parameters:[l],responses:{200:Ce("Document deleted",{type:"object",properties:{id:{type:"string"}}}),404:B("Document not found"),500:B("Internal server error")}}),s[i]=u,s}function ut(e,t,n={}){let{title:r="CRUD API",version:o="1.0.0",description:s,servers:a,auth:d=false}=n,i=t==="/"?"":t.replace(/\/$/,""),l={},u={},m=[];l.ErrorResponse={type:"object",properties:{success:{type:"boolean",enum:[false]},error:{type:"string"}},required:["success","error"]},l.QueryRequestBody=Vn();for(let[g,f]of Object.entries(e)){let b=se(L(g)),x=`${b}Create`,h=`${b}Update`;l[b]=ct(f.schema);let v=O=>{let D=O&&O.length>0?O:Object.keys(f.schema.shape),N={};for(let U of D){let M=U.split(".")[0];M&&f.schema.shape[M]&&!f.systemKeys.includes(M)&&(N[M]=f.schema.shape[M]);}return N},R=null,w=v(f.createFields);Object.keys(w).length>0&&(l[x]=ct(z$1.object(w)),R=x);let T=null,k=v(f.mutableFields);Object.keys(k).length>0&&(l[h]=ct(z$1.object(k)),T=h);let C=Jn(f,i,b,R,T);Object.assign(u,C),m.push({name:g,description:`Operations on ${g} (collection: ${f.path})`});}let c={},p;return d==="basic"?(c.basicAuth={type:"http",scheme:"basic"},p=[{basicAuth:[]}]):d==="bearer"&&(c.bearerAuth={type:"http",scheme:"bearer",bearerFormat:"JWT"},p=[{bearerAuth:[]}]),{openapi:"3.1.0",info:{title:r,version:o,...s?{description:s}:{}},...a&&a.length>0?{servers:a}:{},paths:u,components:{schemas:l,...Object.keys(c).length>0?{securitySchemes:c}:{}},...p?{security:p}:{},tags:m}}function se(e){return e.charAt(0).toUpperCase()+e.slice(1)}function L(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 Xn(e,t){return `<!DOCTYPE html>
|
|
645
|
+
`;function ke(){return jsx("script",{dangerouslySetInnerHTML:{__html:Jt}})}function ae(e){return "<!DOCTYPE html>"+renderToString(e)}var ie=({opts:e,children:t})=>{let{title:n,breadcrumb:r,flash:o,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("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:[jsx("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"})})}),jsxs("main",{class:"px-6 py-8 w-full flex-1",children:[r&&r.length>0&&jsx("div",{class:"text-sm breadcrumbs mb-4",children:jsx("ul",{children:r.map((a,u)=>a.href?jsx("li",{children:jsx("a",{href:a.href,children:a.label})},u):jsx("li",{class:"text-base-content/60",children:a.label},u))})}),jsx("h1",{class:"text-2xl font-bold mb-6",children:n}),o&&jsxs("div",{role:"alert",class:`alert ${o.type==="success"?"alert-success":o.type==="warning"?"alert-warning":"alert-error"} mb-6`,children:[jsx("span",{class:"flex-1",children:o.message}),o.action&&jsx("a",{href:o.action.href,...o.action.external?{target:"_blank",rel:"noopener noreferrer"}:{},class:"btn btn-sm btn-outline",children:o.action.label})]}),t]}),jsx(ke,{})]})]})};function Xe(e,t){return ae(jsx(ie,{opts:t,children:jsx("div",{dangerouslySetInnerHTML:{__html:e}})}))}function Ye(e,t){return ae(jsx(ie,{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 Yt=[{value:"==",label:"="},{value:"!=",label:"\u2260"},{value:"in",label:"in"},{value:"not-in",label:"not in"}],Wn=[{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"}],Vn=[{value:"array-contains",label:"contains"},{value:"array-contains-any",label:"contains any"}];function Jn(e){switch(e){case "ZodNumber":case "ZodBigInt":case "ZodDate":return Wn;case "ZodBoolean":return Yt;case "ZodArray":return Vn;default:return Yt}}var ce="__null__";function Xn(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="${ce}"]');if(!o){o=document.createElement('option');o.value='${ce}';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='${ce}';i.readOnly=true;}i.style.opacity='0.55';}else{i.style.opacity='';if(i.tagName==='SELECT'){var o2=i.querySelector('option[value="${ce}"][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!=='${ce}')?i.dataset._prev:'';}}})(this)`}function Yn(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 Ae({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:Xn(e)}),jsx("span",{children:"\u2205"})]})}function er({col:e,active:t}){let n=t?.value??"",r=n===ce,o=`fv_input_${e.name.replace(/\./g,"__")}`,s=t?.op,a=s==="in"||s==="not-in";if(e.enumValues&&e.enumValues.length>0){if(a){let u=new Set(n.split(",").map(l=>l.trim()).filter(Boolean)),i=`eg_${e.name.replace(/\./g,"__")}`;return jsxs("div",{class:"flex flex-wrap items-center gap-1 w-full",children:[jsx("input",{type:"hidden",id:o,name:`fv_${e.name}`,value:n}),e.enumValues.map(l=>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:l,checked:u.has(l),"data-enum-group":i,onchange:Yn(o,i)}),jsx("span",{children:l})]},l))]})}return jsxs("div",{class:"flex items-center gap-1 w-full",children:[jsxs("select",{id:o,name:`fv_${e.name}`,class:"select select-sm select-bordered w-full",style:r?"opacity:0.55":void 0,children:[jsx("option",{value:"",selected:n===""&&!r,children:"\u2014"}),e.enumValues.map(u=>jsx("option",{value:u,selected:n===u,children:u},u)),e.nullable&&jsx("option",{value:ce,"data-_auto":"1",selected:r,children:"\u2205 null"})]}),e.nullable&&jsx(Ae,{inputId:o,active:r})]})}if(e.zodType==="ZodBoolean")return jsxs("div",{class:"flex items-center gap-1 w-full",children:[jsxs("select",{id:o,name:`fv_${e.name}`,class:"select select-sm select-bordered w-full",style:r?"opacity:0.55":void 0,children:[jsx("option",{value:"",selected:n===""&&!r,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:ce,"data-_auto":"1",selected:r,children:"\u2205 null"})]}),e.nullable&&jsx(Ae,{inputId:o,active:r})]});if(e.zodType==="ZodArray"){let u=t?.op==="array-contains-any";return jsx("input",{id:o,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:o,type:r?"text":"number",name:`fv_${e.name}`,value:n,placeholder:"value",class:"input input-sm input-bordered w-full",readOnly:r,style:r?"opacity:0.55":void 0,"data-_type":r?"number":void 0}),e.nullable&&jsx(Ae,{inputId:o,active:r})]}):e.zodType==="ZodDate"?jsxs("div",{class:"flex items-center gap-1 w-full",children:[jsx("input",{id:o,type:r?"text":"datetime-local",name:`fv_${e.name}`,value:n,class:"input input-sm input-bordered w-full",readOnly:r,style:r?"opacity:0.55":void 0,"data-_type":r?"datetime-local":void 0}),e.nullable&&jsx(Ae,{inputId:o,active:r})]}):jsxs("div",{class:"flex items-center gap-1 w-full",children:[jsx("input",{id:o,type:"text",name:`fv_${e.name}`,value:n,placeholder:"value",class:"input input-sm input-bordered w-full",readOnly:r,style:r?"opacity:0.55":void 0}),e.nullable&&jsx(Ae,{inputId:o,active:r})]})}function et({action:e,columnMeta:t,activeFilters:n,isGroup:r}){let o=Object.fromEntries(n.map(i=>[i.field,i])),s=n.length>0,a=n.length>=2||r&&s,u=t.filter(i=>i.zodType!=="ZodObject"&&i.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(i=>{let l=Jn(i.zodType),y=o[i.name],h=y?.op??l[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:i.name}),jsxs("div",{class:"flex gap-1.5",children:[l.length>1?jsx("select",{name:`fo_${i.name}`,class:"select select-sm select-bordered w-20 shrink-0",children:l.map(c=>jsx("option",{value:c.value,selected:c.value===h,children:c.label},c.value))}):jsx("input",{type:"hidden",name:`fo_${i.name}`,value:l[0].value}),jsx(er,{col:i,active:y})]})]},i.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"}),a&&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"})}),r?"Collection group queries require a composite index":"Multiple filters may require a composite index"]})]})]})})]})}function tt(e,t,n,r,o,s){let a=n==="create"?`Create ${e}`:`Edit ${e} / ${r??""}`,u=n==="create"?[{label:"Repositories",href:o},{label:e,href:`${o}/${e}`},{label:"New document"}]:[{label:"Repositories",href:o},{label:e,href:`${o}/${e}`},{label:`Edit ${r??""}`}];return ae(jsx(ie,{opts:{title:a,breadcrumb:u,basePath:o,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}})})})}))}function nt(e,t,n){let r=new URLSearchParams;for(let o of e)r.set(`fv_${o.field}`,o.value),r.set(`fo_${o.field}`,o.op);return t&&(r.set("ob",t.field),r.set("od",t.dir)),n&&r.set("ps",String(n)),r}function en(e,t,n,r,o){let s=nt(e,r,o);return s.set("cursor",t),s.set("dir",n),`?${s.toString()}`}function tr(e,t,n,r){let o=nt(n,void 0,r);return t?.field===e?t.dir==="asc"&&(o.set("ob",e),o.set("od","desc")):(o.set("ob",e),o.set("od","asc")),`?${o.toString()}`}function nr(e,t,n){return `?${nt(t,n,e).toString()}`}function rt(e,t,n,r,o,s,a=[],u=[],i=false,l=[],y,h,c,d){let p=`${r}/${e}`,m=`${p}/create`;return ae(jsxs(ie,{opts:{title:e,breadcrumb:[{label:"Repositories",href:r},{label:e}],basePath:r,flash:s},children:[a.length>0&&jsx(et,{action:p,columnMeta:a,activeFilters:u,isGroup:d}),c&&jsxs("div",{role:"alert",class:`alert ${c.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:c.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:c.type==="index"?"Composite index required":"Query failed"}),jsx("div",{class:"text-sm",children:c.message})]}),c.indexUrl&&jsx("a",{href:c.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",children:[jsxs("div",{class:"flex items-center gap-3",children:[jsxs("span",{class:"text-sm text-base-content/60",children:[t.length," document",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(f=>jsx("a",{href:nr(f,u,y),class:`join-item btn btn-xs ${h===f?"btn-active btn-primary":"btn-outline"}`,children:f},f))})]})]}),jsx("a",{href:m,class:"btn btn-primary btn-sm",children:"+ New"})]}),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:[[...n].map((f,v)=>{let g=y?.field===f,b=g?y.dir==="asc"?" \u25B2":" \u25BC":"";return jsx("th",{class:"text-xs font-semibold text-base-content/60 uppercase tracking-wide",children:jsxs("a",{href:tr(f,y,u,h),class:`hover:text-base-content inline-flex items-center gap-0.5${g?" text-primary font-bold":""}`,children:[f,b]})},v)}),l.map((f,v)=>jsx("th",{class:"text-xs font-semibold text-base-content/60 uppercase tracking-wide",children:f.column},`rel-${v}`)),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+l.length+1,class:"text-center py-16 text-base-content/40",children:"No documents found"})}):t.map((f,v)=>{let g=String(f.docId??f.id??""),b=`${r}/${e}/${encodeURIComponent(g)}/edit`,R=`${r}/${e}/${encodeURIComponent(g)}/delete`;return jsxs("tr",{class:"hover",children:[n.map((x,S)=>jsx("td",{class:"align-top py-2",children:jsx(Je,{val:f[x]})},S)),l.map((x,S)=>{let C=f[x.key];if(C==null||C==="")return jsx("td",{class:"py-2"},`rel-${S}`);let P=`${r}/${x.targetRepo}?fv_${x.targetKey}=${encodeURIComponent(String(C))}`;return jsx("td",{class:"align-middle py-2",children:jsx("a",{href:P,class:"btn btn-xs btn-ghost btn-outline",children:x.column})},`rel-${S}`)}),jsx("td",{class:"align-middle text-right whitespace-nowrap py-2",children:jsxs("div",{class:"flex gap-1 justify-end",children:[jsx("a",{href:b,class:"btn btn-xs btn-outline",children:"Edit"}),i&&jsx("form",{method:"post",action:R,onsubmit:"return confirm('Delete this document?')",children:jsx("button",{type:"submit",class:"btn btn-xs btn-error btn-outline",children:"Delete"})})]})})]},v)})})]})}),(o.hasPrev||o.hasNext)&&jsxs("div",{class:"flex justify-center items-center mt-6 gap-2",children:[o.hasPrev?jsx("a",{href:en(u,o.prevCursor,"prev",y,h),class:"btn btn-sm btn-outline",children:"\u2190 Previous"}):jsx("button",{class:"btn btn-sm btn-outline",disabled:true,children:"\u2190 Previous"}),o.hasNext?jsx("a",{href:en(u,o.nextCursor,"next",y,h),class:"btn btn-sm btn-outline",children:"Next \u2192"}):jsx("button",{class:"btn btn-sm btn-outline",disabled:true,children:"Next \u2192"})]})]}))}function Me(e,t){return Xe(e,t)}function ot(e,t){return Ye(e,t)}function st(e,t,n,r,o,s,a,u,i,l,y,h,c,d){return rt(e,t,n,r,o,s,a,u,i,l,y,h,c,d)}function le(e,t,n,r,o,s){return tt(e,t,n,r,o,s)}var rr=new Set(["<","<=",">",">=","!="]),or=new Set(["array-contains","array-contains-any"]);function at(e){return e==="desc"?"DESCENDING":"ASCENDING"}function sr(e){let t=e.split("/").filter(Boolean);return t[t.length-1]??e}function ar(e,t,n,r,o){let s=[],a=new Set;for(let i of r)if(i.op==="=="||i.op==="in"||i.op==="not-in"){if(a.has(i.field))continue;a.add(i.field),s.push({fieldPath:i.field,order:"ASCENDING"});}for(let i of r)if(or.has(i.op)){if(a.has(i.field))continue;a.add(i.field),s.push({fieldPath:i.field,arrayConfig:"CONTAINS"});}for(let i of r)if(rr.has(i.op)){if(a.has(i.field))continue;a.add(i.field);let l=o?.field===i.field?at(o.dir):"ASCENDING";s.push({fieldPath:i.field,order:l});}if(o&&!a.has(o.field)&&s.push({fieldPath:o.field,order:at(o.dir)}),s.length===1&&n)return lr(e,t,s[0]);let u=o&&s.some(i=>i.fieldPath===o.field)?at(o.dir):"ASCENDING";return s.push({fieldPath:"__name__",order:u}),ir(e,t,n,s)}function ir(e,t,n,r,o="(default)"){let s=`projects/${e}/databases/${o}/collectionGroups/${t}/indexes/_`,a=[...lt(1,s),...Be(2,n?2:1)];for(let l of r)a.push(...tn(3,nn(l)));let u=o==="(default)"?"-default-":o,i=encodeURIComponent(rn(a));return `https://console.firebase.google.com/project/${e}/firestore/databases/${u}/indexes?create_composite=${i}`}function cr(e){return e.match(/https:\/\/console\.firebase\.google\.com[^\s)"]*/)?.[0]}function it(e){let t=[],n=e>>>0;for(;n>=128;)t.push(n&127|128),n>>>=7;return t.push(n&127),t}function ct(e,t){return e<<3|t}function lt(e,t){let n=Array.from(new TextEncoder().encode(t));return [ct(e,2),...it(n.length),...n]}function Be(e,t){return [ct(e,0),...it(t)]}function tn(e,t){return [ct(e,2),...it(t.length),...t]}function nn(e){let t=[...lt(1,e.fieldPath)];return e.arrayConfig==="CONTAINS"?t.push(...Be(3,1)):t.push(...Be(2,e.order==="DESCENDING"?2:1)),t}function rn(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 lr(e,t,n,r="(default)"){let o=`projects/${e}/databases/${r}/collectionGroups/${t}/fields/${n.fieldPath}`,s=[...lt(1,o),...Be(2,2),...tn(3,nn(n))],a=r==="(default)"?"-default-":r,u=encodeURIComponent(rn(s));return `https://console.firebase.google.com/project/${e}/firestore/databases/${a}/indexes/automatic?create_exemption=${u}`}function dr(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 o of n)if(typeof o=="string"&&o.length>0)return o;return process.env.GCLOUD_PROJECT||process.env.GOOGLE_CLOUD_PROJECT||process.env.FIREBASE_PROJECT_ID||void 0}function me(e){let t=e;return t?t.code===9?true:typeof t.message=="string"?t.message.includes("requires an index"):false:false}function Pe(e,t){let n=e??{},r=me(e),o;if(r&&(o=n.message?cr(n.message):void 0,!o)){let s=dr(t.ref);if(s){let a=sr(t.path);o=ar(s,a,t.isGroup,t.filters,t.sort);}}return {type:r?"index":"error",message:r?"This query requires a composite index that does not exist yet.":n.message??"Query failed",indexUrl:o}}var on="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";function pr(){let e="";for(let t=0;t<20;t++)e+=on.charAt(Math.floor(Math.random()*on.length));return e}function sn(e,t){if(!t)return;let n=e[t];if(typeof n!="string"||!n)return;let r=n.split("/").filter(Boolean),o=[];for(let s=1;s<r.length;s+=2)o.push(r[s]);return o.length>0?o:void 0}async function dt(e,t){let n=e.documentKey??"docId",r=`by${n.charAt(0).toUpperCase()}${n.slice(1)}`;if(typeof e.repo.get[r]=="function")try{let s=await e.repo.get[r](t);if(s)return s}catch{}return (await e.repo.query.by({where:[[n,"==",t]],limit:1}))[0]??null}function ut(e,t,n){let r=e.documentKey??"docId",o=Pe(n,{ref:e.repo.ref,path:e.path,isGroup:!!e.isGroup,filters:[{field:r,op:"==",value:t}]});return o.type==="index"?{type:"warning",message:"Loading this document requires a composite index that does not exist yet.",...o.indexUrl?{action:{href:o.indexUrl,label:"Create Index \u2192",external:true}}:{}}:{type:"error",message:o.message}}function N(e,t,n=200){e.status(n).set("Content-Type","text/html; charset=utf-8").send(t);}function pt(e,t){e.status(302).set("Location",t).send("");}function ft(e,t){let n=t.shape,r={};for(let[o,s]of Object.entries(n)){let a=mt(s);if(a==="ZodObject"){if(e[o+"__isnull"]==="1"){r[o]=null;continue}let l={},y=false;for(let[d,p]of Object.entries(e))d.startsWith(`${o}.`)&&(l[d.slice(o.length+1)]=p,y=true);if(y){let d=s;for(;;){let p=j(d);if(p==="ZodOptional"||p==="ZodNullable"||p==="ZodDefault")d=q(d);else break}r[o]=ft(l,d);continue}let h=e[o],c=Array.isArray(h)?h[h.length-1]:h;if(c)try{r[o]=JSON.parse(c);}catch{r[o]=c;}continue}let u=e[o],i=Array.isArray(u)?u[u.length-1]:u;if(e[o+"__isnull"]==="1"){r[o]=null;continue}if(i===void 0||i===""){a==="ZodBoolean"&&(r[o]=false);continue}switch(a){case "ZodBoolean":i==="__null__"?r[o]=null:r[o]=i==="true"||i==="on"||i==="1";break;case "ZodNumber":case "ZodBigInt":r[o]=Number(i);break;case "ZodDate":r[o]=new Date(i);break;case "ZodArray":try{r[o]=JSON.parse(i);}catch{r[o]=i;}break;default:if(i.startsWith("{")||i.startsWith("["))try{r[o]=JSON.parse(i);break}catch{}r[o]=i;}}return r}function an(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 r=new Date(e);isNaN(r.getTime())||(t=r);}if(!t||isNaN(t.getTime()))return null;let n=r=>String(r).padStart(2,"0");return `${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())}T${n(t.getHours())}:${n(t.getMinutes())}`}function mt(e){let t=e;for(;;){let n=j(t);if(n==="ZodOptional"||n==="ZodNullable"||n==="ZodDefault")t=q(t);else return n}}function fr(e){let t=e;for(;;){let n=j(t);if(n==="ZodOptional"||n==="ZodNullable"||n==="ZodDefault")t=q(t);else return t}}function cn(e){let t=e;for(;;){let n=j(t);if(n==="ZodOptional"||n==="ZodNullable")return true;if(n==="ZodDefault"){t=q(t);continue}return false}}function ln(e){let t=fr(e),n=j(t);if(n==="ZodEnum"){let r=Se(t);return r.length>0?r:void 0}if(n==="ZodNativeEnum"){let r=Te(t),o=Object.values(r).filter(s=>typeof s=="string");return o.length>0?o:void 0}if(n==="ZodLiteral"){let r=je(t);return typeof r=="string"?[r]:void 0}}function dn(e,t,n=""){let r={};for(let o of Object.keys(t.shape)){let s=n?`${n}.${o}`:o,a=e[o];if(a===null){r[s]="__null__";continue}if(a===void 0)continue;let u=t.shape[o];for(;;){let l=j(u);if(l==="ZodOptional"||l==="ZodNullable"||l==="ZodDefault")u=q(u);else break}let i=j(u);if(i==="ZodObject"&&typeof a=="object"&&a!==null&&!Array.isArray(a)){let l=dn(a,u,s);Object.assign(r,l);}else if(i==="ZodDate"){let l=an(a);l!==null&&(r[s]=l);}else if(typeof a=="object"&&a!==null&&!Array.isArray(a)&&("_seconds"in a||typeof a.toDate=="function")){let l=an(a);r[s]=l??JSON.stringify(a,null,2);}else typeof a=="object"?r[s]=JSON.stringify(a,null,2):r[s]=String(a);}return r}function yt(e,t){return e.map(n=>({...n,defaultValue:t[n.name]??n.defaultValue,nested:n.nested?yt(n.nested,t):void 0}))}function yr(e,t){let n=new Set(["==","!=","<","<=",">",">=","in","not-in","array-contains","array-contains-any"]),r=[];for(let[o,s]of Object.entries(e)){if(!o.startsWith("fv_"))continue;let a=o.slice(3);if(!t.has(a))continue;let u=(s??"").trim();if(!u)continue;let i=e[`fo_${a}`]??"==",l=n.has(i)?i:"==";r.push({field:a,op:l,value:u});}return r}function mr(e){let t="__null__",n=r=>r===t?null:r==="true"?true:r==="false"?false:r!==""&&!isNaN(Number(r))?Number(r):r;return e.map(r=>{if(r.op==="array-contains-any"||r.op==="in"||r.op==="not-in"){let o=r.value.split(",").map(s=>s.trim()).filter(s=>s!==""&&s!==t).map(s=>n(s));return [r.field,r.op,o]}return [r.field,r.op,n(r.value)]})}function un(e,t,n=""){let r=[];for(let o of e){let s=n?`${n}.${o}`:o,a=t.shape[o];if(!a){r.push({name:s,zodType:"ZodString"});continue}let u=mt(a);if(u==="ZodObject"){let i=a;for(;;){let y=j(i);if(y==="ZodOptional"||y==="ZodNullable"||y==="ZodDefault")i=q(i);else break}let l=re(i);r.push(...un(Object.keys(l),i,s));}else r.push({name:s,zodType:u,nullable:cn(a),enumValues:ln(a)});}return r}function gr(e,t){let n=t.split("."),r=e;for(let o of n){for(;;){let a=j(r);if(a==="ZodOptional"||a==="ZodNullable"||a==="ZodDefault")r=q(r);else break}let s=re(r);if(!(o in s))return null;r=s[o];}return r}function he(e,t){if(!t||t.length===0)return e;let n=[],r=new Map;for(let s of t){let a=s.indexOf(".");if(a===-1)n.push(s);else {let u=s.slice(0,a),i=s.slice(a+1);r.has(u)||r.set(u,[]),r.get(u).push(i);}}let o={};for(let s of n)s in e.shape&&(o[s]=e.shape[s]);for(let[s,a]of r){if(!(s in e.shape))continue;let u=e.shape[s];for(;;){let i=j(u);if(i==="ZodOptional"||i==="ZodNullable"||i==="ZodDefault")u=q(u);else break}if(j(u)!=="ZodObject"){o[s]=e.shape[s];continue}o[s]=he(u,a);}return z.object(o)}function ge(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",a=process.env.FUNCTION_REGION??"us-central1",u=(process.env.FUNCTION_TARGET??"").replace(/\./g,"-");return `/${s}/${a}/${u}${n}`}let r=process.env.K_SERVICE,o=e.hostname??e.headers?.host??"";return r&&o.includes("cloudfunctions.net")?`/${r.toLowerCase()}${n}`:n}function pn(e,t){return {handleDashboard:(l,y)=>{let h=ge(l,t),c=Object.values(e).map(d=>({name:d.name,path:d.path}));N(y,ot(c,h));},handleList:async(l,y)=>{let h=l.params.repoName;if(!h){N(y,"Bad request",400);return}let c=e[h];if(!c){N(y,"Repository not found",404);return}let d=c.pageSize??25,p=l.query??{},m=p.cursor,f=p.dir==="prev"?"prev":"next",v=p.ob??"",g=p.od==="desc"?"desc":"asc",b=v?{field:v,dir:g}:void 0,R=parseInt(p.ps??""),x=Number.isFinite(R)&&R>0?Math.min(R,200):d,S=c.listColumns??Object.keys(c.schema.shape),C=c.documentKey??"docId",P=[C,...S.filter(B=>B!==C)],w=c.filterableFields?(()=>{let B=[];for(let Y of c.filterableFields)(Y.includes(".")||S.includes(Y))&&B.push(Y);return B})():S,T=(()=>{let B=[];for(let Y of w)if(Y.includes(".")){let be=gr(c.schema,Y);B.push({name:Y,zodType:be?mt(be):"ZodString",nullable:be?cn(be):false,enumValues:be?ln(be):void 0});}else B.push(...un([Y],c.schema));return B})(),O=new Set(T.map(B=>B.name)),k=yr(p,O),I=mr(k),$;if(m)try{let B=c.repo.ref;typeof B.doc=="function"&&($=await B.doc(m).get());}catch{}let K=await c.repo.query.paginate({pageSize:x,cursor:$,direction:f,...I.length>0?{where:I}:{},...b?{orderBy:[{field:b.field,direction:b.dir}]}:{}}).catch(B=>({queryError:Pe(B,{ref:c.repo.ref,path:c.path,isGroup:!!c.isGroup,filters:k,sort:b})})),_="queryError"in K,te=_?[]:K.data,Tn=_?"":K.nextCursor?.id??"",Cn=_?"":K.prevCursor?.id??"",$n=_?K.queryError:void 0,On=ge(l,t);N(y,st(c.name,te,P,On,{hasPrev:_?false:K.hasPrevPage,hasNext:_?false:K.hasNextPage,prevCursor:Cn,nextCursor:Tn},void 0,T,k,c.allowDelete??false,c.relationalMeta,b,x,$n,c.isGroup));},handleCreateForm:(l,y)=>{let h=l.params.repoName;if(!h){N(y,"Bad request",400);return}let c=e[h];if(!c){N(y,"Repository not found",404);return}let d=ge(l,t),p=he(c.schema,c.createFields),m=J(p),f=`${d}/${c.name}/create`,v=se(m,f,"POST","Create document");N(y,le(c.name,v,"create",null,d));},handleCreateSubmit:async(l,y)=>{let h=l.params.repoName;if(!h){N(y,"Bad request",400);return}let c=e[h];if(!c){N(y,"Repository not found",404);return}let d=ge(l,t),p=l.body??{},m=ft(p,c.schema),f=he(c.schema,c.createFields),v=f.safeParse(m);if(!v.success){let g=J(f),b=`${d}/${c.name}/create`,R=se(g,b,"POST","Create document"),x=v.error.issues.map(S=>`${S.path.join(".")}: ${S.message}`).join(", ");N(y,le(c.name,R,"create",null,d,{type:"error",message:`Validation error: ${x}`}),422);return}try{if(c.isGroup&&c.parentKeys&&c.parentKeys.length>0){let g={...v.data};c.createdKey&&(g[c.createdKey]=new Date);let b=c.parentKeys.filter(C=>!g[C]);if(b.length>0)throw new Error(`Missing parent key(s) for subcollection create: ${b.join(", ")}`);let R=c.parentKeys.map(C=>g[C]),x=c.documentKey??"docId",S=g[x]||pr();await c.repo.set(...R,S,g);}else await c.repo.create(v.data);pt(y,`${d}/${c.name}?flash=created`);}catch(g){let b=he(c.schema,c.createFields),R=J(b),x=`${d}/${c.name}/create`,S=se(R,x,"POST","Create document");N(y,le(c.name,S,"create",null,d,{type:"error",message:`Save error: ${g.message}`}),500);}},handleEditForm:async(l,y)=>{let h=l.params.repoName,c=l.params.id;if(!h||!c){N(y,"Bad request",400);return}let d=e[h];if(!d){N(y,"Repository not found",404);return}let p=ge(l,t),m=null;try{m=await dt(d,c);}catch(x){let S=ut(d,c,x),C=me(x)?424:500;N(y,Me("",{title:`Edit ${d.name} / ${c}`,basePath:p,breadcrumb:[{label:"Repositories",href:p},{label:d.name,href:`${p}/${d.name}`},{label:`Edit ${c}`}],flash:S}),C);return}if(!m){N(y,"Document not found",404);return}let f=dn(m,d.schema),v=he(d.schema,d.mutableFields),g=yt(J(v),f),b=`${p}/${d.name}/${encodeURIComponent(c)}/edit`,R=se(g,b,"POST","Save changes");N(y,le(d.name,R,"edit",c,p));},handleEditSubmit:async(l,y)=>{let h=l.params.repoName,c=l.params.id;if(!h||!c){N(y,"Bad request",400);return}let d=e[h];if(!d){N(y,"Repository not found",404);return}let p=ge(l,t),m=l.body??{},f=ft(m,d.schema),v=he(d.schema,d.mutableFields),b=v.partial().safeParse(f);if(!b.success){let R=Object.fromEntries(Object.entries(m).map(([w,T])=>[w,Array.isArray(T)?T.join(","):T??""])),x=yt(J(v),R),S=`${p}/${d.name}/${encodeURIComponent(c)}/edit`,C=se(x,S,"POST","Save changes"),P=b.error.issues.map(w=>`${w.path.join(".")}: ${w.message}`).join(", ");N(y,le(d.name,C,"edit",c,p,{type:"error",message:`Validation error: ${P}`}),422);return}try{let R=await dt(d,c),x=(R&&sn(R,d.pathKey))??[c];await d.repo.update(...x,b.data),pt(y,`${p}/${d.name}?flash=updated`);}catch(R){let x=he(d.schema,d.mutableFields),S=J(x),C=`${p}/${d.name}/${encodeURIComponent(c)}/edit`,P=se(S,C,"POST","Save changes"),w=me(R)?ut(d,c,R):{type:"error",message:`Save error: ${R.message}`},T=me(R)?424:500;N(y,le(d.name,P,"edit",c,p,w),T);}},handleDelete:async(l,y)=>{let h=l.params.repoName,c=l.params.id;if(!h||!c){N(y,"Bad request",400);return}let d=e[h];if(!d){N(y,"Repository not found",404);return}if(!d.allowDelete){N(y,"Delete is not allowed for this repository",403);return}let p=ge(l,t);try{let m=await dt(d,c),f=(m&&sn(m,d.pathKey))??[c];await d.repo.delete(...f),pt(y,`${p}/${d.name}?flash=deleted`);}catch(m){let f=me(m)?ut(d,c,m):{type:"error",message:`Delete error: ${m.message}`},v=me(m)?424:500;N(y,Me("",{title:`Delete ${d.name} / ${c}`,basePath:p,breadcrumb:[{label:"Repositories",href:p},{label:d.name,href:`${p}/${d.name}`},{label:`Delete ${c}`}],flash:f}),v);}}}}async function hr(e){return typeof e.rawBody=="string"?e.rawBody:Buffer.isBuffer(e.rawBody)?e.rawBody.toString("utf8"):""}function br(e){let t={};if(!e)return t;for(let n of e.split("&")){let r=n.indexOf("=");if(r===-1)continue;let o=decodeURIComponent(n.slice(0,r).replace(/\+/g," ")),s=decodeURIComponent(n.slice(r+1).replace(/\+/g," ")),a=t[o];a===void 0?t[o]=s:Array.isArray(a)?a.push(s):t[o]=[a,s];}return t}function fn(e){let{basePath:t="/",repos:n,parseBody:r=true,auth:o,middleware:s=[],httpsOptions:a}=e,u=t==="/"?"":t.replace(/\/$/,""),i={};for(let[c,d]of Object.entries(n)){let p=d.schema??d.repo.schema??null;if(!p)throw new Error(`[createAdminServer] Repository "${c}" has no Zod schema. Either use createRepositoryConfig(schema)(config) or pass schema: explicitly.`);let m,f,v;if(d.fieldsConfig){let R=d.fieldsConfig;m=[],f=[],v=[];for(let[x,S]of Object.entries(R))for(let C of S)C==="filterable"?m.push(x):C==="mutable"?f.push(x):C==="create"&&v.push(x);m.length===0&&(m=void 0),f.length===0&&(f=void 0),v.length===0&&(v=void 0);}let g=(()=>{let R=d.repo._parentKeys;return R&&R.length>0?R:void 0})();if(g&&v)for(let R of g)v.includes(R)||v.push(R);let b={name:c,path:d.path,repo:d.repo,schema:p,documentKey:d.documentKey??"docId",pathKey:d.repo._pathKey??void 0,isGroup:!!d.repo._isGroup,parentKeys:g,createdKey:d.repo._createdKey??void 0,listColumns:d.listColumns,pageSize:d.pageSize,filterableFields:m,mutableFields:f,createFields:v,allowDelete:d.allowDelete??false,relationalMeta:(()=>{if(!d.relationalFields||d.relationalFields.length===0)return;let R=d.repo.relationalKeys??{},x=[];for(let S of d.relationalFields){let C=R[S.key];C&&x.push({key:S.key,column:S.column,targetRepo:String(C.repo),targetKey:String(C.key),type:C.type});}return x.length>0?x:void 0})()};i[c]=b;}let l=pn(i,u),y=new G;if(r&&y.use(async(c,d,p)=>{let m=c,f=String(m.headers?.["content-type"]??"");if(f.includes("application/x-www-form-urlencoded")){let v=await hr(m);c.body=br(v);}else if(f.includes("application/json")&&typeof m.body=="string")try{c.body=JSON.parse(m.body);}catch{}await p();}),o)if(typeof o=="function")y.use(o);else {let c=o.realm??"Admin",d="Basic "+Buffer.from(`${o.username}:${o.password}`).toString("base64");y.use((p,m,f)=>{if((p.headers?.authorization??"")!==d){m.status(401).set("WWW-Authenticate",`Basic realm="${c}"`).set("Content-Type","text/plain").send("Unauthorized");return}f();});}for(let c of s)y.use(c);y.get(`${u}/`,l.handleDashboard),y.get(`${u}`,l.handleDashboard),y.get(`${u}/:repoName`,l.handleList),y.get(`${u}/:repoName/create`,l.handleCreateForm),y.post(`${u}/:repoName/create`,l.handleCreateSubmit),y.get(`${u}/:repoName/:id/edit`,l.handleEditForm),y.post(`${u}/:repoName/:id/edit`,l.handleEditSubmit),y.post(`${u}/:repoName/:id/delete`,l.handleDelete);let h=async(c,d)=>{await y.handle(c,d);};return a&&(h.httpsOptions=a),h}function ht(e,t,n=200){let r=F(t);e.status(n).set("Content-Type","application/json; charset=utf-8").send(JSON.stringify(r));}function Re(e,t,n,r=200){ht(e,{success:true,data:t,meta:n},r);}function M(e,t,n=400){ht(e,{success:false,error:t},n);}function gt(e,t,n,r,o){let s=Pe(t,n),a=s.type==="index",u=a?424:500,l={success:false,error:a?s.message:o&&t instanceof Error?t.message:r};a&&(l.errorType="index",s.indexUrl&&(l.indexUrl=s.indexUrl)),ht(e,l,u);}var yn="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";function vr(){let e="";for(let t=0;t<20;t++)e+=yn.charAt(Math.floor(Math.random()*yn.length));return e}function xe(e){let t=e._def??e.def;if(!t)return e;let n=t.typeName??t.type;if(n==="ZodDate"||n==="date")return z.preprocess(r=>Ge(r)??r,e);if(n==="ZodObject"||n==="object"){let r=e.shape,o={};for(let[s,a]of Object.entries(r))o[s]=xe(a);return z.object(o)}if(n==="ZodArray"||n==="array"){let r=t.element??t.type;if(r)return z.array(xe(r))}if(n==="ZodOptional"||n==="optional"){let r=t.innerType;if(r)return xe(r).optional()}if(n==="ZodNullable"||n==="nullable"){let r=t.innerType;if(r)return xe(r).nullable()}if(n==="ZodDefault"||n==="default"){let r=t.innerType,o=t.defaultValue;if(r){let s=xe(r);return typeof o=="function"?s.default(o()):s.default(o)}}return e}function Rr(e,t,n=[]){let r=e.shape,o={},s=t&&t.length>0?t:Object.keys(r);for(let a of s){if(n.includes(a))continue;let u=a.split(".")[0];u&&r[u]&&(o[u]=r[u]);}return z.object(o)}function mn(e,t,n,r=false,o=[]){try{let s=Rr(e,n,o),a=r?s.partial():s;return {success:!0,data:(Le()==="normalize"?xe(a):a).parse(t)}}catch(s){return s instanceof z.ZodError?{success:false,error:`Validation failed: ${s.issues.map(u=>`${u.path.join(".")}: ${u.message}`).join(", ")}`}:{success:false,error:"Validation failed"}}}function xr(e,t){let n=[],r=t?new Set(t):null,o={eq:"==",ne:"!=",lt:"<",lte:"<=",gt:">",gte:">=",in:"in",nin:"not-in",contains:"array-contains",containsAny:"array-contains-any"};for(let[s,a]of Object.entries(e)){if(a===void 0||["cursor","limit","pageSize","orderBy","orderDir","select"].includes(s))continue;let u=Array.isArray(a)?a[0]:a;if(u===void 0||u==="")continue;let i=s.match(/^(\w+)__(\w+)$/),l,y="==";if(i&&i[1]&&i[2]){l=i[1];let c=i[2];if(o[c])y=o[c];else continue}else if(!i)l=s;else continue;if(r&&!r.has(l))continue;let h=u;y==="in"||y==="not-in"||y==="array-contains-any"?h=u.split(",").map(c=>gn(c.trim())):h=gn(u),n.push({field:l,op:y,value:h});}return n}function gn(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 Ke(e){return e?{docId:e.id}:null}async function hn(e,t){if(!t||typeof t!="object")return;let n=t.docId;if(typeof n=="string")try{let r=e.repo.ref;if(typeof r.doc!="function")return;let o=await r.doc(n).get();return o.exists?o:void 0}catch{return}}function bn(e,t,n){function r(d,p){return !d||!e[d]?(M(p,`Repository "${d}" not found`,404),null):e[d]}function o(d,p){if(!p)return;let m=d[p];if(typeof m!="string"||!m)return;let f=m.split("/").filter(Boolean),v=[];for(let g=1;g<f.length;g+=2)v.push(f[g]);return v.length>0?v:void 0}async function s(d,p){let m=`by${d.documentKey.charAt(0).toUpperCase()}${d.documentKey.slice(1)}`,f=d.repo.get[m];if(typeof f=="function")try{let g=await f(p);if(g)return g}catch{}return (await d.repo.query.by({where:[[d.documentKey,"==",p]],limit:1}))[0]??null}async function a(d,p){let m=d.params||{},f=r(m.repoName,p);if(!f)return;let v=[],g;try{let b=d.query??{},R=Math.min(Number(b.pageSize)||f.pageSize,100),x=b.cursor,S=b.direction?.toLowerCase()==="prev"?"prev":"next",C=b.orderBy,P=b.orderDir?.toLowerCase()==="desc"?"desc":"asc",w=b.select,T=w?w.split(",").map(_=>_.trim()):void 0,O;f.allowedIncludes&&b.includes&&(O=(typeof b.includes=="string"?b.includes.split(",").map(te=>te.trim()):Array.isArray(b.includes)?b.includes:[]).filter(te=>typeof te=="string"&&f.allowedIncludes.includes(te)),O?.length===0&&(O=void 0));let k=xr(b,f.filterableFields);v=k.map(_=>({field:_.field,op:_.op,value:String(_.value??"")})),C&&(g={field:C,dir:P});let I={pageSize:R,direction:S};if(x)try{let _=typeof x=="string"?JSON.parse(x):x;I.cursor=await hn(f,_);}catch{}C&&(I.orderBy=[{field:C,direction:P}]),k.length>0&&(I.where=k.map(_=>[_.field,_.op,_.value])),T&&(I.select=T),O&&(I.include=O);let $=await f.repo.query.paginate(I),K={items:$.data,hasNextPage:$.hasNextPage,hasPrevPage:$.hasPrevPage,nextCursor:Ke($.nextCursor),prevCursor:Ke($.prevCursor)};Re(p,K,{pageSize:R,hasMore:$.hasNextPage});}catch(b){gt(p,b,{ref:f.repo.ref,path:f.path,isGroup:!!f.isGroup,filters:v,sort:g},"Failed to fetch documents",n);}}async function u(d,p){let m=d.params||{},f=r(m.repoName,p);if(!f)return;let v=[],g;try{let b=d.body??{},R=Math.min(b.pageSize||f.pageSize,100),x=b.direction==="prev"?"prev":"next";b.where&&(v=b.where.map(w=>({field:String(w[0]),op:w[1],value:String(w[2]??"")}))),b.orderBy&&b.orderBy[0]&&(g={field:b.orderBy[0].field,dir:b.orderBy[0].direction==="desc"?"desc":"asc"});let S={pageSize:R,direction:x};if(b.cursor)try{let w=typeof b.cursor=="string"?JSON.parse(b.cursor):b.cursor;S.cursor=await hn(f,w);}catch{}if(f.allowedIncludes&&b.includes&&b.includes.length>0){let w=b.includes.filter(T=>typeof T=="string"?f.allowedIncludes.includes(T):typeof T=="object"&&T!==null&&"relation"in T&&typeof T.relation=="string"?f.allowedIncludes.includes(T.relation):!1);w.length>0&&(S.include=w);}if(b.where&&b.where.length>0){if(f.filterableFields){let w=new Set(f.filterableFields),T=b.where.filter(O=>!w.has(O[0]));if(T.length>0){M(p,`Fields not filterable: ${T.map(O=>O[0]).join(", ")}`,400);return}}S.where=b.where;}if(b.orWhere&&b.orWhere.length>0){if(f.filterableFields){let w=new Set(f.filterableFields),T=b.orWhere.filter(O=>!w.has(O[0]));if(T.length>0){M(p,`Fields not filterable: ${T.map(O=>O[0]).join(", ")}`,400);return}}S.orWhere=b.orWhere;}if(b.orWhereGroups&&b.orWhereGroups.length>0){if(f.filterableFields){let w=new Set(f.filterableFields);for(let T of b.orWhereGroups){let O=T.filter(k=>!w.has(k[0]));if(O.length>0){M(p,`Fields not filterable: ${O.map(k=>k[0]).join(", ")}`,400);return}}}S.orWhereGroups=b.orWhereGroups;}b.orderBy&&b.orderBy.length>0&&(S.orderBy=b.orderBy),b.select&&b.select.length>0&&(S.select=b.select);let C=await f.repo.query.paginate(S),P={items:C.data,hasNextPage:C.hasNextPage,hasPrevPage:C.hasPrevPage,nextCursor:Ke(C.nextCursor),prevCursor:Ke(C.prevCursor)};Re(p,P,{pageSize:R,hasMore:C.hasNextPage});}catch(b){gt(p,b,{ref:f.repo.ref,path:f.path,isGroup:!!f.isGroup,filters:v,sort:g},"Failed to query documents",n);}}async function i(d,p){let m=d.params||{},f=r(m.repoName,p);if(!f)return;let v=m.id;if(!v){M(p,"Document ID required",400);return}try{let g=await s(f,v);if(!g){M(p,"Document not found",404);return}Re(p,g);}catch(g){gt(p,g,{ref:f.repo.ref,path:f.path,isGroup:!!f.isGroup,filters:[{field:f.documentKey,op:"==",value:v}]},"Failed to fetch document",n);}}async function l(d,p){let m=d.params||{},f=r(m.repoName,p);if(f)try{let v=d.body??{},g=mn(f.schema,v,f.createFields,!1,f.systemKeys);if(!g.success){M(p,g.error,400);return}if(f.validate){let R=await f.validate(g.data,"create");if(R){M(p,R,400);return}}let b;if(f.isGroup&&f.parentKeys&&f.parentKeys.length>0){let R={...g.data};f.createdKey&&(R[f.createdKey]=new Date);let x=f.parentKeys.filter(P=>!R[P]);if(x.length>0){M(p,`Missing parent key(s) for subcollection create: ${x.join(", ")}`,400);return}let S=f.parentKeys.map(P=>R[P]),C=R[f.documentKey]||vr();b=await f.repo.set(...S,C,R);}else b=await f.repo.create(g.data);Re(p,b,void 0,201);}catch(v){let g=n&&v instanceof Error?v.message:"Failed to create document";M(p,g,500);}}async function y(d,p,m){let f=d.params||{},v=r(f.repoName,p);if(!v)return;let g=f.id;if(!g){M(p,"Document ID required",400);return}try{let b=d.body??{},R=mn(v.schema,b,v.mutableFields,m,v.systemKeys);if(!R.success){M(p,R.error,400);return}if(v.validate){let P=await v.validate(R.data,"update");if(P){M(p,P,400);return}}let x=await s(v,g),S=(x&&o(x,v.pathKey))??[g],C=await v.repo.update(...S,R.data);Re(p,C);}catch(b){let R=n&&b instanceof Error?b.message:"Failed to update document";M(p,R,500);}}async function h(d,p){let m=d.params||{},f=r(m.repoName,p);if(!f)return;if(!f.allowDelete){M(p,"Delete not allowed for this repository",403);return}let v=m.id;if(!v){M(p,"Document ID required",400);return}try{let g=await s(f,v),b=(g&&o(g,f.pathKey))??[v];await f.repo.delete(...b),Re(p,{deleted:!0});}catch(g){let b=n&&g instanceof Error?g.message:"Failed to delete document";M(p,b,500);}}function c(d,p){p.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:a,handleQuery:u,handleGet:i,handleCreate:l,handleUpdate:y,handleDelete:h,handleOptions:c}}function bt(e){try{return z.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 H(e){return {$ref:`#/components/schemas/${e}`}}function Q(e){return {description:e,content:{"application/json":{schema:H("ErrorResponse")}}}}function De(e,t){return {description:e,content:{"application/json":{schema:{type:"object",properties:{success:{type:"boolean",enum:[true]},data:t},required:["success","data"]}}}}}function vn(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 Sr(e){let t=e.filterableFields??Object.keys(e.schema.shape),n=["eq","ne","lt","lte","gt","gte","in","nin","contains"],r=[];for(let o of t){r.push({name:o,in:"query",schema:{type:"string"},description:`Filter by ${o} (equality)`});for(let s of n)r.push({name:`${o}__${s}`,in:"query",schema:{type:"string"},description:`Filter ${o} with operator ${s}`});}return r}function Tr(){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 Cr(e,t,n,r,o){let s={},a=e.name,u=`${t}/${e.name}`,i=`${u}/{${e.documentKey}}`,l={name:e.documentKey,in:"path",required:true,schema:{type:"string"},description:"Unique document identifier"};s[u]={get:{operationId:`list${de(e.name)}`,summary:`List ${e.name} (paginated)`,tags:[a],parameters:[...wr(e),...Sr(e)],responses:{200:vn(H(n)),500:Q("Internal server error")}},post:{operationId:`create${de(e.name)}`,summary:`Create a ${X(e.name)}`,tags:[a],requestBody:{required:true,content:{"application/json":{schema:H(r??n)}}},responses:{201:De("Document created",H(n)),400:Q("Validation error"),500:Q("Internal server error")}}},s[`${u}/query`]={post:{operationId:`query${de(e.name)}`,summary:`Query ${e.name} with advanced filters`,tags:[a],requestBody:{required:true,content:{"application/json":{schema:H("QueryRequestBody")}}},responses:{200:vn(H(n)),400:Q("Invalid query"),500:Q("Internal server error")}}};let y={};return y.get={operationId:`get${de(X(e.name))}`,summary:`Get a single ${X(e.name)}`,tags:[a],parameters:[l],responses:{200:De("Document found",H(n)),404:Q("Document not found"),500:Q("Internal server error")}},y.put={operationId:`update${de(X(e.name))}`,summary:`Update a ${X(e.name)} (full replace)`,tags:[a],parameters:[l],requestBody:{required:true,content:{"application/json":{schema:H(o??n)}}},responses:{200:De("Document updated",H(n)),400:Q("Validation error"),404:Q("Document not found"),500:Q("Internal server error")}},y.patch={operationId:`patch${de(X(e.name))}`,summary:`Partially update a ${X(e.name)}`,tags:[a],parameters:[l],requestBody:{required:true,content:{"application/json":{schema:{allOf:[H(o??n)],description:"All fields are optional for partial updates"}}}},responses:{200:De("Document patched",H(n)),400:Q("Validation error"),404:Q("Document not found"),500:Q("Internal server error")}},e.allowDelete&&(y.delete={operationId:`delete${de(X(e.name))}`,summary:`Delete a ${X(e.name)}`,tags:[a],parameters:[l],responses:{200:De("Document deleted",{type:"object",properties:{id:{type:"string"}}}),404:Q("Document not found"),500:Q("Internal server error")}}),s[i]=y,s}function Rt(e,t,n={}){let{title:r="CRUD API",version:o="1.0.0",description:s,servers:a,auth:u=false}=n,i=t==="/"?"":t.replace(/\/$/,""),l={},y={},h=[];l.ErrorResponse={type:"object",properties:{success:{type:"boolean",enum:[false]},error:{type:"string"}},required:["success","error"]},l.QueryRequestBody=Tr();for(let[m,f]of Object.entries(e)){let v=de(X(m)),g=`${v}Create`,b=`${v}Update`;l[v]=bt(f.schema);let R=T=>{let O=T&&T.length>0?T:Object.keys(f.schema.shape),k={};for(let I of O){let $=I.split(".")[0];$&&f.schema.shape[$]&&!f.systemKeys.includes($)&&(k[$]=f.schema.shape[$]);}return k},x=null,S=R(f.createFields);Object.keys(S).length>0&&(l[g]=bt(z.object(S)),x=g);let C=null,P=R(f.mutableFields);Object.keys(P).length>0&&(l[b]=bt(z.object(P)),C=b);let w=Cr(f,i,v,x,C);Object.assign(y,w),h.push({name:m,description:`Operations on ${m} (collection: ${f.path})`});}let c={},d;return u==="basic"?(c.basicAuth={type:"http",scheme:"basic"},d=[{basicAuth:[]}]):u==="bearer"&&(c.bearerAuth={type:"http",scheme:"bearer",bearerFormat:"JWT"},d=[{bearerAuth:[]}]),{openapi:"3.1.0",info:{title:r,version:o,...s?{description:s}:{}},...a&&a.length>0?{servers:a}:{},paths:y,components:{schemas:l,...Object.keys(c).length>0?{securitySchemes:c}:{}},...d?{security:d}:{},tags:h}}function de(e){return e.charAt(0).toUpperCase()+e.slice(1)}function X(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 $r(e,t){return `<!DOCTYPE html>
|
|
556
646
|
<html lang="en">
|
|
557
647
|
<head>
|
|
558
648
|
<meta charset="utf-8" />
|
|
@@ -563,5 +653,5 @@ function initColumnReorder(table) {
|
|
|
563
653
|
<script id="api-reference" data-url="${t}"></script>
|
|
564
654
|
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
|
|
565
655
|
</body>
|
|
566
|
-
</html>`}function
|
|
656
|
+
</html>`}function Or(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",a=process.env.FUNCTION_REGION??"us-central1",u=process.env.FUNCTION_TARGET??"";return `/${s}/${a}/${u}${n}`}let r=process.env.K_SERVICE,o=e?.hostname??e?.headers?.host??"";return r&&o.includes("cloudfunctions.net")?`/${r.toLowerCase()}${n}`:n}async function kr(e){return typeof e.rawBody=="string"?e.rawBody:Buffer.isBuffer(e.rawBody)?e.rawBody.toString("utf8"):""}function Rn(e){let{basePath:t="/",repos:n,parseBody:r=true,auth:o,middleware:s=[],verbose:a=false,httpsOptions:u}=e,i=t==="/"?"":t.replace(/\/$/,""),l={};for(let[v,g]of Object.entries(n)){let b=g.schema??g.repo.schema??null;if(!b)throw new Error(`[createCrudServer] Repository "${v}" has no Zod schema. Either use createRepositoryConfig(schema)(config) or pass schema: explicitly.`);let R,x,S;if(g.fieldsConfig){let w=g.fieldsConfig;R=[],x=[],S=[];for(let[T,O]of Object.entries(w))for(let k of O)k==="filterable"?R.push(T):k==="mutable"?x.push(T):k==="create"&&S.push(T);R.length===0&&(R=void 0),x.length===0&&(x=void 0),S.length===0&&(S=void 0);}let C=(()=>{let w=g.repo._parentKeys;return w&&w.length>0?w:void 0})();if(C&&S)for(let w of C)S.includes(w)||S.push(w);let P={name:v,path:g.path,repo:g.repo,schema:b,systemKeys:g.repo._systemKeys??[g.documentKey??"docId"],documentKey:g.documentKey??"docId",pathKey:g.repo._pathKey??void 0,isGroup:!!g.repo._isGroup,parentKeys:C,createdKey:g.repo._createdKey??void 0,pageSize:g.pageSize??25,filterableFields:R,mutableFields:x,createFields:S,allowDelete:g.allowDelete??false,allowedIncludes:g.allowedIncludes,validate:g.validate};l[v]=P;}let y=bn(l,i,a),h=e.openapi,c=h&&typeof h=="object"?h:{},d=null;function p(){if(!d){let v=o&&typeof o!="function"?"basic":o?"bearer":false;d=Rt(l,i,{...c,auth:c.auth??v});}return d}let m=new G;if(m.use((v,g,b)=>{g.set("Access-Control-Allow-Origin","*"),g.set("Access-Control-Allow-Credentials","true"),b();}),r&&m.use(async(v,g,b)=>{let R=v;if(String(R.headers?.["content-type"]??"").includes("application/json")){if(typeof R.body=="string")try{v.body=JSON.parse(R.body);}catch{}else if(Buffer.isBuffer(v.rawBody))try{let S=await kr(R);v.body=JSON.parse(S);}catch{}}await b();}),o)if(typeof o=="function")m.use(o);else {let v=o.realm??"API",g="Basic "+Buffer.from(`${o.username}:${o.password}`).toString("base64");m.use((b,R,x)=>{if((b.headers?.authorization??"")!==g){R.status(401).set("WWW-Authenticate",`Basic realm="${v}"`).set("Content-Type","application/json").send(JSON.stringify({success:false,error:"Unauthorized"}));return}x();});}for(let v of s)m.use(v);if(h!==false){let v=`${i}/__spec.json`,g=`${i}/__docs`;m.get(v,(b,R)=>{let x=p();R.status(200).set("Content-Type","application/json; charset=utf-8").send(JSON.stringify(x,null,2));}),m.get(g,(b,R)=>{let x=Or(b,i)+"/__spec.json",S=$r(c.title??"CRUD API",x);R.status(200).set("Content-Type","text/html; charset=utf-8").send(S);});}m.use((v,g,b)=>{if(v.method==="OPTIONS"){y.handleOptions(v,g);return}b();}),m.get(`${i}/:repoName`,y.handleList),m.post(`${i}/:repoName/query`,y.handleQuery),m.get(`${i}/:repoName/:id`,y.handleGet),m.post(`${i}/:repoName`,y.handleCreate),m.put(`${i}/:repoName/:id`,(v,g)=>y.handleUpdate(v,g,false)),m.patch(`${i}/:repoName/:id`,(v,g)=>y.handleUpdate(v,g,true)),m.delete(`${i}/:repoName/:id`,y.handleDelete);let f=async(v,g)=>{await m.handle(v,g);};return f.spec=p,u&&(f.httpsOptions=u),f}function xn(e,t){if(!t.onRequest)return e;let n=e.httpsOptions??t.httpsOptions;return n?t.onRequest(n,e):t.onRequest(e)}function wn(e,t,n){let r={};for(let[o,s]of Object.entries(t)){if(!s)continue;let a=e[o];if(!a)throw new Error(`[createServers.${n}] Unknown repo "${o}" \u2014 not present in the registry passed to createServers().`);r[o]={...s,repo:a};}return r}function Sn(e,t={}){return {admin(n){let r=wn(e,n.repos,"admin"),o=fn({...n,repos:r,httpsOptions:n.httpsOptions??t.httpsOptions});return xn(o,t)},crud(n){let r=wn(e,n.repos,"crud"),o=Rn({...n,repos:r,httpsOptions:n.httpsOptions??t.httpsOptions});return xn(o,t)},sync(n){let r={...n};return t.onRequest&&r.admin&&!r.admin.onRequest&&(r.admin={...r.admin,onRequest:t.onRequest,httpsOptions:r.admin.httpsOptions??t.httpsOptions}),Ut(e,r)}}}function Vs(e){return t=>({...t,schema:e,type:null,documentRef:null,update:null})}function Js(e,t){let n={...e};for(let r in t)t[r]&&(n[r]={...e[r],relationalKeys:t[r]});return n}var xt=class{constructor(t,n){this.repositoryCache=new Map;this.allRepositories={};this.db=t,this.mapping=n,this.initializeRepositories();}initializeRepositories(){for(let t of Object.keys(this.mapping))this.allRepositories[t]=We(this.db,this.mapping[t],{});for(let t of Object.keys(this.mapping))this.allRepositories[t]=We(this.db,this.mapping[t],this.allRepositories);}getRepository(t){return this.allRepositories[t]}};function Xs(e,t){let n=new xt(e,t),r=Object.keys(t);return new Proxy(n,{get(o,s){return typeof s=="string"&&s in t?o.getRepository(s):o[s]},ownKeys(){return r},getOwnPropertyDescriptor(o,s){if(typeof s=="string"&&s in t)return {configurable:true,enumerable:true,writable:false}}})}export{G as MiniRouter,xt as RepositoryMapping,ne as applyPaginationQueryOptions,ue as buildAndExecuteQuery,Js as buildRepositoryRelations,Ge as coerceToDate,He as createPaginationIterator,Vs as createRepositoryConfig,Xs as createRepositoryMapping,Sn as createServers,_e as executePaginatedQuery,Le as getDateHandling,Ne as normalizeTimestamps,An as setDateHandling};//# sourceMappingURL=index.js.map
|
|
567
657
|
//# sourceMappingURL=index.js.map
|