@stacksjs/orm 0.73.2 → 0.74.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/routes.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- var He=Object.defineProperty;var Je=(e)=>e;function qe(e,t){this[e]=Je.bind(null,t)}var dt=(e,t)=>{for(var n in t)He(e,n,{get:t[n],enumerable:!0,configurable:!0,set:qe.bind(t,n)})};var ft=(e,t)=>()=>(e&&(t=e(e=0)),t);var he=import.meta.require;import{route as M}from"@stacksjs/router";import{env as L}from"@stacksjs/env";import{projectPath as Ue,storagePath as ot}from"@stacksjs/path";import{createQueryBuilder as it,defaultConfig as Ie,setConfig as Ee}from"@stacksjs/query-builder";import{HttpError as U}from"@stacksjs/error-handling";import{log as Z}from"@stacksjs/logging";function Ve(e){let t=e;return t?.code==="SQLITE_CONSTRAINT_UNIQUE"||t?.code==="SQLITE_CONSTRAINT"||t?.code==="23505"||t?.errno===1062||/unique|duplicate/i.test(t?.message??"")}function ae(e,t,n){let r=e;if(e instanceof Error&&typeof r.status==="number"&&Number.isInteger(r.status)&&r.status>=400&&r.status<600){let s={error:e.message};if(r.details!==void 0)s.details=r.details;return{status:r.status,body:s}}if(Ve(e))return{status:409,body:{error:`${t} already exists`}};return{status:500,body:{error:`Failed to ${n} ${t}`,detail:String(e)}}}function k(e){return e.replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/([A-Z])([A-Z][a-z])/g,"$1_$2").toLowerCase()}function ue(e){let t={};for(let[n,r]of Object.entries(e))t[k(n)]=r;return t}function Re(e,t){let n=String(t||"").replace(/^\/+|\/+$/g,""),r=String(e).replace(/^\/+/,"");return`/api/${n?`${n}/`:""}${r}`}function ke(e){if(!e)return null;let t=e.attributes??{};if(Object.prototype.hasOwnProperty.call(t,"teamId")||Object.prototype.hasOwnProperty.call(t,"team_id"))return"team_id";return e.belongsTo?.some((n)=>n==="Team")?"team_id":null}function _e(e,t,n){let r=Object.keys(e).find((o)=>k(o)===k(t));if(Array.isArray(n)){if(r===void 0)return{data:e,error:"Ownership value is required"};if(!n.some((o)=>String(o)===String(e[r])))return{data:e,error:"Ownership value is not available to this caller"};return{data:{...e,[t]:e[r]}}}if(n===null||n===void 0)return{data:e,error:"Caller has no ownership identity"};let s={...e};for(let o of Object.keys(s))if(k(o)===k(t))delete s[o];return s[t]=n,{data:s}}function Se(e){if(!e)return[];let t=Object.entries(e.attributes??{}).filter(([,n])=>n?.fillable===!0).map(([n])=>n);for(let n of e.belongsTo??[]){if(typeof n!=="string"||!n.trim())continue;let r=k(n.trim()).split("_").filter(Boolean);if(r.length===0)continue;let s=`${r[0]}${r.slice(1).map((o)=>`${o[0]?.toUpperCase()}${o.slice(1)}`).join("")}Id`;t.push(s)}return[...new Set(t)]}function ce(e,t){if(!e||t.length===0)return{};let n={};for(let r of t){if(r in e){n[r]=e[r];continue}let s=k(r);if(s!==r&&s in e)n[r]=e[s]}return n}function Xe(e,t){if(e?.name!=="date"||t instanceof Date||typeof t!=="string")return t;let n=/^(\d{4})-(\d{2})-(\d{2})$/.exec(t);if(!n)return t;let r=Number(n[1]),s=Number(n[2]),o=Number(n[3]),a=new Date(Date.UTC(r,s-1,o));if(a.getUTCFullYear()!==r||a.getUTCMonth()!==s-1||a.getUTCDate()!==o)return t;return a}function le(e,t){if(!t.length)return e;let n={...e};for(let r of t)delete n[r],delete n[k(r)];return n}function q(e,t){if(!e||t.length===0)return e;let n={...e};for(let r of t)delete n[r],delete n[k(r)];return n}var Ge=["id","uuid","created_at","updated_at","deleted_at"];function xe(e,t){let n=new Map;for(let r of[...Object.keys(e??{}),...Ge]){let s=k(r);if(!/^\w+$/.test(s))continue;n.set(r,s),n.set(s,s)}for(let r of t)n.delete(r),n.delete(k(r));return n}function Oe(e,t,n){if(!t)return e;let r=String(t).split(",").map((o)=>o.trim()).filter(Boolean),s=e;for(let o of r){let a=o.startsWith("-"),p=a?o.slice(1):o;if(!/^\w+$/.test(p))continue;let w=n.get(p);if(!w)continue;s=s.orderBy(w,a?"desc":"asc")}return s}var Ke={string:{get:(e)=>e!=null?String(e):null,set:(e)=>e!=null?String(e):null},number:{get:(e)=>e!=null?Number(e):null,set:(e)=>e!=null?Number(e):null},integer:{get:(e)=>e!=null?Math.trunc(Number(e)):null,set:(e)=>e!=null?Math.trunc(Number(e)):null},float:{get:(e)=>e!=null?Number.parseFloat(String(e)):null,set:(e)=>e!=null?Number.parseFloat(String(e)):null},boolean:{get:(e)=>e===1||e==="1"||e===!0||e==="true",set:(e)=>e===!0||e===1||e==="1"||e==="true"?1:0},json:{get:(e)=>e==null?null:typeof e==="string"?Ye(e):e,set:(e)=>e==null?null:typeof e==="string"?e:JSON.stringify(e)},datetime:{get:(e)=>e?new Date(e):null,set:(e)=>e instanceof Date?e.toISOString():e},date:{get:(e)=>e?new Date(e):null,set:(e)=>e instanceof Date?e.toISOString().split("T")[0]:e},array:{get:(e)=>e==null?[]:Array.isArray(e)?e:typeof e==="string"?Ze(e):[],set:(e)=>e==null?null:Array.isArray(e)?JSON.stringify(e):e}};function Ye(e){try{return JSON.parse(e)}catch{return e}}function Ze(e){try{return JSON.parse(e)}catch{return[]}}function de(e,t,n){if(!e||typeof e!=="object"||!t||Object.keys(t).length===0)return e;let r={...e};for(let[s,o]of Object.entries(t)){let a=typeof o==="string"?Ke[o]:o;if(!a||typeof a[n]!=="function")continue;if(Object.prototype.hasOwnProperty.call(r,s))r[s]=a[n](r[s]);let p=k(s);if(p!==s&&Object.prototype.hasOwnProperty.call(r,p))r[p]=a[n](r[p])}return r}function fe(e,t,n){let r=t?.attributes??{},s={};for(let[o,a]of Object.entries(r)){let p=a?.validation?.rule;if(!p||typeof p.validate!=="function")continue;let w=Object.prototype.hasOwnProperty.call(e,o);if(!w&&n==="updating")continue;let l=a!==null&&typeof a==="object"&&Object.prototype.hasOwnProperty.call(a,"default"),I=w?e[o]:l?a.default:void 0,E=Xe(p,I),D=p.validate(E);if(!D?.valid&&Array.isArray(D?.errors)&&D.errors.length>0)s[o]=D.errors.map((B)=>a?.validation?.message?.[B?.code]??B?.message??"invalid")}return Object.keys(s).length===0?{valid:!0}:{valid:!1,errors:s}}function Te(e,t,n){let r=we(n);return e.find((s)=>s.method===t&&we(String(s.path??""))===r)}function we(e){return e.replace(/\{[^}]*\}/g,"{}").replace(/:[^/]+/g,"{}")}function ie(e){if(Array.isArray(e))return e.filter((t)=>typeof t==="string"&&t.length>0);return typeof e==="string"&&e?[e]:[]}function De(e){let t=typeof e==="object"&&e!==null&&"middleware"in e,n=e?.middleware;if(!t)return{read:["auth"],write:["auth"],declared:!1};if(n&&typeof n==="object"&&!Array.isArray(n)){let s=n;return{read:"read"in s?ie(s.read):["auth"],write:"write"in s?ie(s.write):["auth"],declared:!0}}let r=ie(n);return{read:r,write:r,declared:!0}}var be=15,et=100;function Ne(e){let t=Number.parseInt(e.get("page")||String(1),10),n=Number.isFinite(t)?Math.max(1,t):1,r=Number.parseInt(e.get("per_page")||String(be),10),s=Math.min(Number.isFinite(r)?Math.max(1,r):be,et);return{page:n,perPage:s,offset:(n-1)*s}}function te(e,t){let n=new URL(e.toString());return n.searchParams.set("page",String(t)),`${n.pathname}${n.search}`}function ne(e,t,n,r,s,o){let a=(t-1)*n,p=r===0,w={page:t,per_page:n,from:p?null:a+1,to:p?null:a+r,has_more_pages:s,prev_page_url:t>1?te(e,t-1):null,next_page_url:s?te(e,t+1):null};if(o!==void 0&&!Number.isNaN(o)){let l=Math.max(1,Math.ceil(o/n));w.total=o,w.last_page=l,w.first_page_url=te(e,1),w.last_page_url=te(e,l)}return w}function ge(e,t,n,r,s,o){let{page:a,...p}=ne(e,t,n,r,s,o);return{current_page:a,...p}}import{readdirSync as tt}from"fs";import{basename as nt,extname as $e,join as rt}from"path";function st(e){let t=[],n=(r)=>{let s;try{s=tt(r,{withFileTypes:!0})}catch{return}for(let o of s){let a=rt(r,o.name);if(o.isDirectory()){n(a);continue}if(![".ts",".js"].includes($e(o.name)))continue;if(o.name.startsWith(".")||o.name.startsWith("index"))continue;t.push(a)}};return n(e),t.sort()}async function Ae(e,t,n){for(let r of st(e))try{let s=$e(r),o=await import(`${r}?t=${Date.now()}`),a=o.default??o,p=a.name??nt(r,s);t[p]={...a,name:p}}catch(s){n?.(r,s)}}async function Pe(e){let t={};return await Ae(e.defaultsRoot,t,e.onImportError),await Ae(e.userRoot,t,e.onImportError),t}var at=Ue("config/qb.ts");try{let e=(await import(at)).default;Ee(e??Ie)}catch{Z.debug("[orm] No config/qb.ts override found - deriving config from DB_CONNECTION");let e=L.DB_CONNECTION||"sqlite";Ee({...Ie,dialect:e,database:e==="sqlite"?{database:L.DB_DATABASE_PATH||"database/stacks.sqlite"}:{database:L.DB_DATABASE||"stacks",host:L.DB_HOST||"127.0.0.1",port:L.DB_PORT||(e==="postgres"?5432:3306),username:L.DB_USERNAME||(e==="postgres"?"postgres":"root"),password:L.DB_PASSWORD||""}})}var pe=await Pe({defaultsRoot:ot("framework/defaults/app/Models"),userRoot:Ue("app/Models"),onImportError:(e,t)=>Z.warn(`[orm] Could not load model ${e}: ${t.message}`)}),ut=it(),T=ut;function z(e,t){let n=Te(M.routes,e,t);if(!n)return!1;let r=String(n.path??"");return Z.info(`[orm] Skipping generated ${e} ${t} - already defined${r&&r!==t?` as ${r}`:""}.`),!0}function Be(e){if(!e.attributes)return[];return Object.entries(e.attributes).filter(([t,n])=>n.hidden===!0).map(([t])=>t)}function Ce(e){if(e.endsWith("y")&&!/[aeiou]y$/i.test(e))return`${e.slice(0,-1)}ies`;if(/(?:s|x|z|ch|sh)$/i.test(e))return`${e}es`;return`${e}s`}async function je(e,t,n,r){if(!e.length)return e;let s=n.split(",").map((l)=>l.trim()).filter(Boolean);if(!s.length)return e;let o=Array.isArray(t.belongsTo)?t.belongsTo:[],a=Array.isArray(t.hasMany)?t.hasMany:[],p=Array.isArray(t.hasOne)?t.hasOne:[],w=new Map;for(let l of o)w.set(k(l),{kind:"belongsTo",modelName:l});for(let l of p)w.set(k(l),{kind:"hasOne",modelName:l});for(let l of a)w.set(Ce(k(l)),{kind:"hasMany",modelName:l});for(let l of s){let I=w.get(l);if(!I)continue;let E=r[I.modelName];if(!E)continue;let D=E.table||Ce(k(I.modelName)),B=Be(E),oe=(Q)=>q(Y(Q,E),B);if(I.kind==="belongsTo"||I.kind==="hasOne"){let Q=`${k(I.modelName)}_id`,j=[...new Set(e.map((S)=>S[Q]).filter((S)=>S!=null))];if(!j.length){for(let S of e)S[l]=null;continue}let H=await T.selectFrom(D).whereIn("id",j).get(),A=new Map;for(let S of H??[])A.set(String(S.id),oe(S));for(let S of e)S[l]=A.get(String(S[Q]))??null}else{let Q=String(t.name??""),j=`${k(Q)}_id`,H=[...new Set(e.map((c)=>c.id).filter((c)=>c!=null))];if(!H.length){for(let c of e)c[l]=[];continue}let A=await T.selectFrom(D).whereIn(j,H).get(),S=new Map;for(let c of A??[]){let i=String(c[j]),u=S.get(i)??[];u.push(oe(c)),S.set(i,u)}for(let c of e)c[l]=S.get(String(c.id))??[]}}return e}async function ve(e,t){let n=t?.set;if(!n||typeof n!=="object")return e;let r={...e};for(let[s,o]of Object.entries(n)){if(typeof o!=="function"||!(s in r))continue;try{r[s]=await o(r)}catch{}}return r}function Fe(e,t){return de(e,t?.casts,"set")}function Y(e,t){return de(e,t?.casts,"get")}function d(e,t=200){return new Response(JSON.stringify(e),{status:t,headers:{"Content-Type":"application/json"}})}var re=1048576;async function ye(e){if(Number(e.headers?.get?.("content-length")??0)>re)throw new U(413,`Request body exceeds ${re}-byte limit`);if(e.jsonBody&&typeof e.jsonBody==="object")return e.jsonBody;if(e.formBody&&typeof e.formBody==="object")return e.formBody;try{let n=await e.clone().text();if(n.length>re)throw new U(413,`Request body exceeds ${re}-byte limit`);if(!n)return{};let r=JSON.parse(n);return r&&typeof r==="object"&&!Array.isArray(r)?r:{}}catch(n){if(n instanceof U)throw n;throw new U(400,`Invalid JSON body: ${n.message}`)}}function se(e){if(e==null)return null;if(typeof e==="number")return Number.isFinite(e)&&e>0?e:null;if(typeof e==="string"){let t=e.trim();if(!t)return null;if(/^\d+$/.test(t)){let n=Number(t);return Number.isFinite(n)&&n>0?n:null}return t}return null}function Qe(e){let t=e.bearerToken;if(typeof t==="function"){let r=t.call(e);if(r)return r}let n=e.headers?.get?.("authorization")||e.headers?.get?.("Authorization")||"";if(typeof n==="string"&&n.startsWith("Bearer "))return n.substring(7);return null}async function V(e){let t=e._authenticatedUser;if(t)return t;let n=Qe(e);if(!n)return null;try{let{Auth:r}=await import("@stacksjs/auth"),s=await r.getUserFromToken(n);if(s)e._authenticatedUser=s;return s||null}catch{return null}}function K(e,t){if(e==null||t==null)return!1;if(Array.isArray(t))return t.some((n)=>String(n)===String(e));return String(e)===String(t)}function ct(e){let t=Qe(e),n=e.headers?.get?.("cookie")||"";return{bearerToken:()=>t,cookies:{get:(r)=>{for(let s of n.split(";")){let o=s.indexOf("=");if(o===-1)continue;if(s.slice(0,o).trim()===r)return decodeURIComponent(s.slice(o+1).trim())}return null}}}}function We(e){if(e?.ownership)return e.ownership;let t=ke(e);if(!t)return null;return{field:t,resolve:async(n,r)=>{let{resolveAuthenticatedTeamId:s}=await import("@stacksjs/auth");return s(ct(r))}}}async function X(e,t,n){let r=We(e);if(!r||!r.field||typeof r.resolve!=="function")return{enforced:!1,value:null,field:"",bypass:!1};let s=typeof r.bypass==="function"?!!r.bypass(t,n):!1,o=null;try{o=await r.resolve(t,n)}catch{o=null}return{enforced:!0,value:o,field:String(r.field),bypass:s}}async function Me(e,t,n,r){let s=e?.authedFill?.[t];if(!s)return{};if(typeof s==="function")try{let o=await s(n,r);return o&&typeof o==="object"?o:{}}catch{return{}}if(typeof s==="object"){let o={};for(let[a,p]of Object.entries(s))try{o[a]=typeof p==="function"?await p(n,r):p}catch{}return o}return{}}for(let[e,t]of Object.entries(pe)){let n=t.traits?.useApi;if(!n)continue;let r=typeof n==="object"?n:{},s=r.uri||t.table||e.toLowerCase()+"s",o=r.routes||["index","show","store","update","destroy"],a=t.table||s,p=Se(t),w=Be(t),l=Re(s,r.prefix),I=xe(t.attributes,w),{read:E,write:D,declared:B}=De(n);if(["store","update","destroy"].some((c)=>o.includes(c))&&B&&D.length===0)Z.warn(`[orm] ${e}: registering UNAUTHENTICATED mutating routes at ${l} (explicit \`middleware: []\` opt-out)`);if(["index","show"].some((c)=>o.includes(c))&&B&&E.length===0)Z.debug(`[orm] ${e}: registering public read routes at ${l} (declared \`middleware.read: []\`)`);let j=!!We(t),H=j&&!E.includes("auth")?["auth",...E]:E,A=(c,i=H)=>{let u=c;for(let f of i)if(u&&typeof u.middleware==="function")u=u.middleware(f);return u};if(o.includes("index")&&!z("GET",l))A(M.get(l,async(c)=>{try{let i=new URL(c.url),{page:u,perPage:f,offset:h}=Ne(i.searchParams),m=i.searchParams.get("sort"),g=T.selectFrom(a);g=Oe(g,m,I);let P=new Set(["page","per_page","sort","fields","search","include","limit","offset","with_count","withTrashed","onlyTrashed"]);for(let[x,O]of i.searchParams.entries()){if(P.has(x)||!O)continue;if(!/^[a-z_][a-z0-9_]*$/i.test(x))continue;let W=I.get(x);if(W)g=g.where(W,"=",O)}let R=i.searchParams.get("search");if(R&&p.length>0){let x=p.slice(0,5);g=g.where((O)=>{for(let W of x)O=O.orWhere(k(W),"like",`%${R}%`);return O})}let _=i.searchParams.get("fields");if(_){let x=_.split(",").map((O)=>O.trim()).filter((O)=>/^[a-z_][a-z0-9_]*$/i.test(O)).map((O)=>k(O));if(x.length>0)g=g.select(x)}let N=!!t.traits?.useSoftDeletes,b=i.searchParams.get("withTrashed")==="true",C=i.searchParams.get("onlyTrashed")==="true";if(N&&!b)g=C?g.whereNotNull("deleted_at"):g.whereNull("deleted_at");let y=j?await X(t,await V(c),c):{enforced:!1,value:null,field:"",bypass:!1};if(y.enforced&&!y.bypass){if(y.value==null||Array.isArray(y.value)&&y.value.length===0){let x=ge(i,u,f,0,!1,void 0);return new Response(JSON.stringify({data:[],...x,meta:ne(i,u,f,0,!1,void 0)}),{status:200,headers:{"Content-Type":"application/json","Cache-Control":"private, no-store",Vary:"Authorization"}})}g=Array.isArray(y.value)?g.where(y.field,"in",y.value):g.where(y.field,"=",y.value)}let v=await g.limit(f+1).offset(h).get()||[],F=v.length>f,G=(F?v.slice(0,f):v).map((x)=>q(Y(x,t),w)),me=i.searchParams.get("include");if(me)G=await je(G,t,me,pe);let Le=i.searchParams.get("with_count")==="true",J;if(Le)try{let x=T.selectFrom(a);if(y.enforced&&!y.bypass&&y.value!=null)x=Array.isArray(y.value)?x.where(y.field,"in",y.value):x.where(y.field,"=",y.value);let O=await x.count(),W=typeof O==="number"?O:Number(O?.count??O);if(Number.isFinite(W))J=W}catch{}let ee={"Content-Type":"application/json"};if(J!==void 0&&!Number.isNaN(J))ee["X-Total-Count"]=String(J);ee["Cache-Control"]=y.enforced&&!y.bypass?"private, no-store":"public, max-age=15, must-revalidate",ee.Vary="Authorization";let ze=ge(i,u,f,G.length,F,J);return new Response(JSON.stringify({data:G,...ze,meta:ne(i,u,f,G.length,F,J)}),{status:200,headers:ee})}catch(i){if(i instanceof U){let u={error:i.message};if(i.details!==void 0)u.details=i.details;return d(u,i.status||400)}return d({error:`Failed to fetch ${s}`,detail:String(i)},500)}}));if(o.includes("show")&&!z("GET",`${l}/{id}`))A(M.get(`${l}/{id}`,async(c)=>{try{let i=se(c.params?.id);if(i==null)return d({error:"Invalid ID parameter"},400);let u=await T.selectFrom(a).where({id:i}).executeTakeFirst();if(!u)return d({error:`${e} not found`},404);let f=new URL(c.url);if(t.traits?.useSoftDeletes&&u.deleted_at&&f.searchParams.get("withTrashed")!=="true")return d({error:`${e} not found`},404);let h=j?await X(t,await V(c),c):{enforced:!1,value:null,field:"",bypass:!1};if(h.enforced&&!h.bypass){if(h.value==null||!K(u[h.field],h.value))return d({error:`${e} not found`},404)}let m=q(Y(u,t),w),g=f.searchParams.get("include");if(g){let[b]=await je([m],t,g,pe);m=b}let P=m?.updated_at||m?.created_at,R=P?`W/"${m.id}-${String(P)}"`:void 0,_=c.headers?.get?.("if-none-match");if(R&&_&&_===R)return new Response(null,{status:304,headers:{ETag:R}});let N={"Content-Type":"application/json"};if(R)N.ETag=R;return N["Cache-Control"]=h.enforced&&!h.bypass?"private, no-store":"public, max-age=30, must-revalidate",N.Vary="Authorization",new Response(JSON.stringify({data:m}),{status:200,headers:N})}catch(i){if(i instanceof U){let u={error:i.message};if(i.details!==void 0)u.details=i.details;return d(u,i.status||400)}return d({error:`Failed to fetch ${e}`,detail:String(i)},500)}}));if(o.includes("store")&&!z("POST",l))A(M.post(l,async(c)=>{try{let i=await ye(c),u=le(i,w),f=ce(u,p),h=await V(c);if(h){let b=await Me(t,"creating",h,c);for(let[C,y]of Object.entries(b))if(y!==void 0&&y!==null&&f[C]===void 0)f[C]=y}let m=await X(t,h,c);if(m.enforced&&!m.bypass){if(!h)return d({error:"Auth required"},401);let b=_e(f,m.field,m.value);if(b.error)return d({error:b.error},403);f=b.data}if(Object.keys(f).length===0)return d({error:"No fillable fields provided"},422);let g=fe(f,t,"creating");if(!g.valid)return d({success:!1,message:"Validation failed",errors:g.errors},422);if(t.traits?.useTimestamps!==!1){let b=new Date().toISOString();f.created_at=b,f.updated_at=b}let P=await ve(f,t),R=ue(Fe(P,t)),_=await T.insertInto(a).values(R).execute(),N=R;try{let b=_?.lastInsertRowid??_?.insertId??_;if(b){let C=await T.selectFrom(a).where({id:b}).executeTakeFirst();if(C)N=C}}catch{}return d({data:q(Y(N,t),w)},201)}catch(i){let{status:u,body:f}=ae(i,e,"create");return d(f,u)}}),D);if(o.includes("update")){let c=async(i)=>{try{let u=se(i.params?.id);if(u==null)return d({error:"Invalid ID parameter"},400);let f=await ye(i),h=le(f,w),m=ce(h,p),g=await V(i);if(g){let y=await Me(t,"updating",g,i);for(let[v,F]of Object.entries(y))if(F!==void 0&&F!==null&&m[v]===void 0)m[v]=F}if(Object.keys(m).length===0)return d({error:"No fillable fields provided"},422);let P=fe(m,t,"updating");if(!P.valid)return d({success:!1,message:"Validation failed",errors:P.errors},422);let R=await T.selectFrom(a).where({id:u}).executeTakeFirst();if(!R)return d({error:`${e} not found`},404);let _=await X(t,g,i);if(_.enforced&&!_.bypass){if(!g)return d({error:"Auth required"},401);let y=R[_.field];if(!K(y,_.value))return d({error:`Not your ${e}`},403);let v=Object.keys(m).find((F)=>k(F)===k(_.field));if(v!==void 0&&!K(m[v],_.value))return d({error:`Cannot reassign ${e} ownership`},403)}if(t.traits?.useTimestamps!==!1)m.updated_at=new Date().toISOString();let N=await ve(m,t),b=ue(Fe(N,t));await T.updateTable(a).set(b).where({id:u}).execute();let C={...R,...b};try{let y=await T.selectFrom(a).where({id:u}).executeTakeFirst();if(y)C=y}catch{}return d({data:q(Y(C,t),w)})}catch(u){let{status:f,body:h}=ae(u,e,"update");return d(h,f)}};if(!z("PUT",`${l}/{id}`))A(M.put(`${l}/{id}`,c),D);if(!z("PATCH",`${l}/{id}`))A(M.patch(`${l}/{id}`,c),D)}let S=!!t.traits?.useSoftDeletes;if(o.includes("destroy")&&!z("DELETE",`${l}/{id}`))A(M.delete(`${l}/{id}`,async(c)=>{try{let i=se(c.params?.id);if(i==null)return d({error:"Invalid ID parameter"},400);let u=await T.selectFrom(a).where({id:i}).executeTakeFirst();if(!u)return d({error:`${e} not found`},404);let f=await V(c),h=await X(t,f,c);if(h.enforced&&!h.bypass){if(!f)return d({error:"Auth required"},401);let m=u[h.field];if(!K(m,h.value))return d({error:`Not your ${e}`},403)}if(S){let m=new Date().toISOString();await T.updateTable(a).set({deleted_at:m,updated_at:m}).where({id:i}).execute()}else await T.deleteFrom(a).where({id:i}).execute();return new Response(null,{status:204})}catch(i){if(i instanceof U){let u={error:i.message};if(i.details!==void 0)u.details=i.details;return d(u,i.status||400)}return d({error:`Failed to delete ${e}`,detail:String(i)},500)}}),D);if(o.includes("destroy")&&!z("POST",`${l}/bulk-delete`))A(M.post(`${l}/bulk-delete`,async(c)=>{try{let u=(await ye(c))?.ids;if(!Array.isArray(u)||u.length===0)return d({error:"An array of IDs is required"},422);if(u.length>100)return d({error:"Cannot delete more than 100 records at once"},422);let f=[],h=[];for(let R of u){let _=se(R);if(_!=null)f.push(_);else h.push(R)}if(h.length>0)return d({error:"Invalid IDs in batch",invalid:h},422);let m=await V(c),g=await X(t,m,c);if(g.enforced&&!g.bypass){if(!m)return d({error:"Auth required"},401);if(g.value==null)return d({error:"Caller has no ownership identity"},403);let R=await T.selectFrom(a).select(["id",g.field]).execute(),_=new Set(R.filter((b)=>K(b[g.field],g.value)).map((b)=>String(b.id))),N=f.filter((b)=>!_.has(String(b)));if(N.length>0)return d({error:`Cannot delete ${e} you don't own`,ids:N},403)}let P=new Date().toISOString();for(let R of f)if(S)await T.updateTable(a).set({deleted_at:P,updated_at:P}).where({id:R}).execute();else await T.deleteFrom(a).where({id:R}).execute();return d({message:`Successfully deleted ${f.length} ${s}`})}catch(i){if(i instanceof U){let u={error:i.message};if(i.details!==void 0)u.details=i.details;return d(u,i.status||400)}return d({error:`Failed to bulk delete ${s}`,detail:String(i)},500)}}),D)}var Dt=M;export{Dt as default};
2
+ var ke=import.meta.require;import ut from"process";import{route as F}from"@stacksjs/router";import{env as z}from"@stacksjs/env";import{projectPath as be,storagePath as ct}from"@stacksjs/path";import{createQueryBuilder as lt,defaultConfig as Me,setConfig as Fe}from"@stacksjs/query-builder";import{HttpError as U}from"@stacksjs/error-handling";import{log as X}from"@stacksjs/logging";function Xe(e){let t=e;return t?.code==="SQLITE_CONSTRAINT_UNIQUE"||t?.code==="SQLITE_CONSTRAINT"||t?.code==="23505"||t?.errno===1062||/unique|duplicate/i.test(t?.message??"")}function ce(e,t,n){let r=e;if(e instanceof Error&&typeof r.status==="number"&&Number.isInteger(r.status)&&r.status>=400&&r.status<600){let o={error:e.message};if(r.details!==void 0)o.details=r.details;return{status:r.status,body:o}}if(Xe(e))return{status:409,body:{error:`${t} already exists`}};return{status:500,body:{error:`Failed to ${n} ${t}`,detail:String(e)}}}function k(e){return e.replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/([A-Z])([A-Z][a-z])/g,"$1_$2").toLowerCase()}function le(e){let t={};for(let[n,r]of Object.entries(e))t[k(n)]=r;return t}function xe(e,t){let n=String(t||"").replace(/^\/+|\/+$/g,""),r=String(e).replace(/^\/+/,"");return`/api/${n?`${n}/`:""}${r}`}function Oe(e){if(!e)return null;let t=e.attributes??{};if(Object.prototype.hasOwnProperty.call(t,"teamId")||Object.prototype.hasOwnProperty.call(t,"team_id"))return"team_id";return e.belongsTo?.some((n)=>n==="Team")?"team_id":null}function Te(e,t,n){let r=Object.keys(e).find((s)=>k(s)===k(t));if(Array.isArray(n)){if(r===void 0)return{data:e,error:"Ownership value is required"};if(!n.some((s)=>String(s)===String(e[r])))return{data:e,error:"Ownership value is not available to this caller"};return{data:{...e,[t]:e[r]}}}if(n===null||n===void 0)return{data:e,error:"Caller has no ownership identity"};let o={...e};for(let s of Object.keys(o))if(k(s)===k(t))delete o[s];return o[t]=n,{data:o}}function Ae(e){if(!e)return[];let t=Object.entries(e.attributes??{}).filter(([,n])=>n?.fillable===!0).map(([n])=>n);for(let n of e.belongsTo??[]){if(typeof n!=="string"||!n.trim())continue;let r=k(n.trim()).split("_").filter(Boolean);if(r.length===0)continue;let o=`${r[0]}${r.slice(1).map((s)=>`${s[0]?.toUpperCase()}${s.slice(1)}`).join("")}Id`;t.push(o)}return[...new Set(t)]}function de(e,t){if(!e||t.length===0)return{};let n={};for(let r of t){if(r in e){n[r]=e[r];continue}let o=k(r);if(o!==r&&o in e)n[r]=e[o]}return n}function Ye(e,t){if(e?.name!=="date"||t instanceof Date||typeof t!=="string")return t;let n=/^(\d{4})-(\d{2})-(\d{2})$/.exec(t);if(!n)return t;let r=Number(n[1]),o=Number(n[2]),s=Number(n[3]),a=new Date(Date.UTC(r,o-1,s));if(a.getUTCFullYear()!==r||a.getUTCMonth()!==o-1||a.getUTCDate()!==s)return t;return a}function fe(e,t){if(!t.length)return e;let n={...e};for(let r of t)delete n[r],delete n[k(r)];return n}function V(e,t){if(!e||t.length===0)return e;let n={...e};for(let r of t)delete n[r],delete n[k(r)];return n}var Ze=["id","uuid","created_at","updated_at","deleted_at"];function De(e,t){let n=new Map;for(let r of[...Object.keys(e??{}),...Ze]){let o=k(r);if(!/^\w+$/.test(o))continue;n.set(r,o),n.set(o,o)}for(let r of t)n.delete(r),n.delete(k(r));return n}function Pe(e,t,n){if(!t)return e;let r=String(t).split(",").map((s)=>s.trim()).filter(Boolean),o=e;for(let s of r){let a=s.startsWith("-"),p=a?s.slice(1):s;if(!/^\w+$/.test(p))continue;let w=n.get(p);if(!w)continue;o=o.orderBy(w,a?"desc":"asc")}return o}var et={string:{get:(e)=>e!=null?String(e):null,set:(e)=>e!=null?String(e):null},number:{get:(e)=>e!=null?Number(e):null,set:(e)=>e!=null?Number(e):null},integer:{get:(e)=>e!=null?Math.trunc(Number(e)):null,set:(e)=>e!=null?Math.trunc(Number(e)):null},float:{get:(e)=>e!=null?Number.parseFloat(String(e)):null,set:(e)=>e!=null?Number.parseFloat(String(e)):null},boolean:{get:(e)=>e===1||e==="1"||e===!0||e==="true",set:(e)=>e===!0||e===1||e==="1"||e==="true"?1:0},json:{get:(e)=>e==null?null:typeof e==="string"?tt(e):e,set:(e)=>e==null?null:typeof e==="string"?e:JSON.stringify(e)},datetime:{get:(e)=>e?new Date(e):null,set:(e)=>e instanceof Date?e.toISOString():e},date:{get:(e)=>e?new Date(e):null,set:(e)=>e instanceof Date?e.toISOString().split("T")[0]:e},array:{get:(e)=>e==null?[]:Array.isArray(e)?e:typeof e==="string"?nt(e):[],set:(e)=>e==null?null:Array.isArray(e)?JSON.stringify(e):e}};function tt(e){try{return JSON.parse(e)}catch{return e}}function nt(e){try{return JSON.parse(e)}catch{return[]}}function ge(e,t,n){if(!e||typeof e!=="object"||!t||Object.keys(t).length===0)return e;let r={...e};for(let[o,s]of Object.entries(t)){let a=typeof s==="string"?et[s]:s;if(!a||typeof a[n]!=="function")continue;if(Object.prototype.hasOwnProperty.call(r,o))r[o]=a[n](r[o]);let p=k(o);if(p!==o&&Object.prototype.hasOwnProperty.call(r,p))r[p]=a[n](r[p])}return r}function pe(e,t,n){let r=t?.attributes??{},o={};for(let[s,a]of Object.entries(r)){let p=a?.validation?.rule;if(!p||typeof p.validate!=="function")continue;let w=Object.prototype.hasOwnProperty.call(e,s);if(!w&&n==="updating")continue;let c=a!==null&&typeof a==="object"&&Object.prototype.hasOwnProperty.call(a,"default"),I=w?e[s]:c?a.default:void 0,C=Ye(p,I),D=p.validate(C);if(!D?.valid&&Array.isArray(D?.errors)&&D.errors.length>0)o[s]=D.errors.map((B)=>a?.validation?.message?.[B?.code]??B?.message??"invalid")}return Object.keys(o).length===0?{valid:!0}:{valid:!1,errors:o}}function $e(e,t,n){let r=_e(n);return e.find((o)=>o.method===t&&_e(String(o.path??""))===r)}function _e(e){return e.replace(/\{[^}]*\}/g,"{}").replace(/:[^/]+/g,"{}")}function ue(e){if(Array.isArray(e))return e.filter((t)=>typeof t==="string"&&t.length>0);return typeof e==="string"&&e?[e]:[]}function Ne(e){let t=typeof e==="object"&&e!==null&&"middleware"in e,n=e?.middleware;if(!t)return{read:["auth"],write:["auth"],declared:!1};if(n&&typeof n==="object"&&!Array.isArray(n)){let o=n;return{read:"read"in o?ue(o.read):["auth"],write:"write"in o?ue(o.write):["auth"],declared:!0}}let r=ue(n);return{read:r,write:r,declared:!0}}var Se=15,rt=100;function Ie(e){let t=Number.parseInt(e.get("page")||String(1),10),n=Number.isFinite(t)?Math.max(1,t):1,r=Number.parseInt(e.get("per_page")||String(Se),10),o=Math.min(Number.isFinite(r)?Math.max(1,r):Se,rt);return{page:n,perPage:o,offset:(n-1)*o}}function oe(e,t){let n=new URL(e.toString());return n.searchParams.set("page",String(t)),`${n.pathname}${n.search}`}function se(e,t,n,r,o,s){let a=(t-1)*n,p=r===0,w={page:t,per_page:n,from:p?null:a+1,to:p?null:a+r,has_more_pages:o,prev_page_url:t>1?oe(e,t-1):null,next_page_url:o?oe(e,t+1):null};if(s!==void 0&&!Number.isNaN(s)){let c=Math.max(1,Math.ceil(s/n));w.total=s,w.last_page=c,w.first_page_url=oe(e,1),w.last_page_url=oe(e,c)}return w}function ye(e,t,n,r,o,s){let{page:a,...p}=se(e,t,n,r,o,s);return{current_page:a,...p}}function me(e,t){return(t??e??"").toString().trim().toLowerCase()==="deny"?"deny":"warn"}function Ce(e,t){if(e.length===0)return null;let n=[...e].sort().join(", ");if(t==="deny")return`[orm] security.api.rowScoping is 'deny': NOT registering store/update/destroy for ${e.length} model(s) `+`with no row-level scoping \u2014 ${n}. Give a model an \`ownership\` config or a \`team_id\` column to restore its writes.`;return`[orm] ${e.length} model(s) publish mutating routes with no row-level scoping, so an authenticated caller can write any row \u2014 `+`${n}. Scope one with an \`ownership\` config or a \`team_id\` column; intended for public catalog tables. Set \`security.api.rowScoping: 'deny'\` (config/security.ts) to stop generating these routes instead.`}import{readdirSync as ot}from"fs";import{basename as st,extname as ve,join as it}from"path";function at(e){let t=[],n=(r)=>{let o;try{o=ot(r,{withFileTypes:!0})}catch{return}for(let s of o){let a=it(r,s.name);if(s.isDirectory()){n(a);continue}if(![".ts",".js"].includes(ve(s.name)))continue;if(s.name.startsWith(".")||s.name.startsWith("index"))continue;t.push(a)}};return n(e),t.sort()}async function Ee(e,t,n){for(let r of at(e))try{let o=ve(r),s=await import(`${r}?t=${Date.now()}`),a=s.default??s,p=a.name??st(r,o);t[p]={...a,name:p}}catch(o){n?.(r,o)}}async function je(e){let t={};return await Ee(e.defaultsRoot,t,e.onImportError),await Ee(e.userRoot,t,e.onImportError),t}var dt=be("config/qb.ts");try{let e=(await import(dt)).default;Fe(e??Me)}catch{X.debug("[orm] No config/qb.ts override found - deriving config from DB_CONNECTION");let e=z.DB_CONNECTION||"sqlite";Fe({...Me,dialect:e,database:e==="sqlite"?{database:z.DB_DATABASE_PATH||"database/stacks.sqlite"}:{database:z.DB_DATABASE||"stacks",host:z.DB_HOST||"127.0.0.1",port:z.DB_PORT||(e==="postgres"?5432:3306),username:z.DB_USERNAME||(e==="postgres"?"postgres":"root"),password:z.DB_PASSWORD||""}})}var he=await je({defaultsRoot:ct("framework/defaults/app/Models"),userRoot:be("app/Models"),onImportError:(e,t)=>X.warn(`[orm] Could not load model ${e}: ${t.message}`)}),ft=lt(),A=ft;function H(e,t){let n=$e(F.routes,e,t);if(!n)return!1;let r=String(n.path??"");return X.info(`[orm] Skipping generated ${e} ${t} - already defined${r&&r!==t?` as ${r}`:""}.`),!0}function ze(e){if(!e.attributes)return[];return Object.entries(e.attributes).filter(([t,n])=>n.hidden===!0).map(([t])=>t)}function Ue(e){if(e.endsWith("y")&&!/[aeiou]y$/i.test(e))return`${e.slice(0,-1)}ies`;if(/(?:s|x|z|ch|sh)$/i.test(e))return`${e}es`;return`${e}s`}async function Be(e,t,n,r){if(!e.length)return e;let o=n.split(",").map((c)=>c.trim()).filter(Boolean);if(!o.length)return e;let s=Array.isArray(t.belongsTo)?t.belongsTo:[],a=Array.isArray(t.hasMany)?t.hasMany:[],p=Array.isArray(t.hasOne)?t.hasOne:[],w=new Map;for(let c of s)w.set(k(c),{kind:"belongsTo",modelName:c});for(let c of p)w.set(k(c),{kind:"hasOne",modelName:c});for(let c of a)w.set(Ue(k(c)),{kind:"hasMany",modelName:c});for(let c of o){let I=w.get(c);if(!I)continue;let C=r[I.modelName];if(!C)continue;let D=C.table||Ue(k(I.modelName)),B=ze(C),Y=(Q)=>V(ne(Q,C),B);if(I.kind==="belongsTo"||I.kind==="hasOne"){let Q=`${k(I.modelName)}_id`,E=[...new Set(e.map((S)=>S[Q]).filter((S)=>S!=null))];if(!E.length){for(let S of e)S[c]=null;continue}let J=await A.selectFrom(D).whereIn("id",E).get(),W=new Map;for(let S of J??[])W.set(String(S.id),Y(S));for(let S of e)S[c]=W.get(String(S[Q]))??null}else{let Q=String(t.name??""),E=`${k(Q)}_id`,J=[...new Set(e.map((x)=>x.id).filter((x)=>x!=null))];if(!J.length){for(let x of e)x[c]=[];continue}let W=await A.selectFrom(D).whereIn(E,J).get(),S=new Map;for(let x of W??[]){let Z=String(x[E]),f=S.get(Z)??[];f.push(Y(x)),S.set(Z,f)}for(let x of e)x[c]=S.get(String(x.id))??[]}}return e}async function Qe(e,t){let n=t?.set;if(!n||typeof n!=="object")return e;let r={...e};for(let[o,s]of Object.entries(n)){if(typeof s!=="function"||!(o in r))continue;try{r[o]=await s(r)}catch{}}return r}function We(e,t){return ge(e,t?.casts,"set")}function ne(e,t){return ge(e,t?.casts,"get")}function l(e,t=200){return new Response(JSON.stringify(e),{status:t,headers:{"Content-Type":"application/json"}})}var ie=1048576;async function we(e){if(Number(e.headers?.get?.("content-length")??0)>ie)throw new U(413,`Request body exceeds ${ie}-byte limit`);if(e.jsonBody&&typeof e.jsonBody==="object")return e.jsonBody;if(e.formBody&&typeof e.formBody==="object")return e.formBody;try{let n=await e.clone().text();if(n.length>ie)throw new U(413,`Request body exceeds ${ie}-byte limit`);if(!n)return{};let r=JSON.parse(n);return r&&typeof r==="object"&&!Array.isArray(r)?r:{}}catch(n){if(n instanceof U)throw n;throw new U(400,`Invalid JSON body: ${n.message}`)}}function ae(e){if(e==null)return null;if(typeof e==="number")return Number.isFinite(e)&&e>0?e:null;if(typeof e==="string"){let t=e.trim();if(!t)return null;if(/^\d+$/.test(t)){let n=Number(t);return Number.isFinite(n)&&n>0?n:null}return t}return null}function He(e){let t=e.bearerToken;if(typeof t==="function"){let r=t.call(e);if(r)return r}let n=e.headers?.get?.("authorization")||e.headers?.get?.("Authorization")||"";if(typeof n==="string"&&n.startsWith("Bearer "))return n.substring(7);return null}async function G(e){let t=e._authenticatedUser;if(t)return t;let n=He(e);if(!n)return null;try{let{Auth:r}=await import("@stacksjs/auth"),o=await r.getUserFromToken(n);if(o)e._authenticatedUser=o;return o||null}catch{return null}}function te(e,t){if(e==null||t==null)return!1;if(Array.isArray(t))return t.some((n)=>String(n)===String(e));return String(e)===String(t)}function gt(e){let t=He(e),n=e.headers?.get?.("cookie")||"";return{bearerToken:()=>t,cookies:{get:(r)=>{for(let o of n.split(";")){let s=o.indexOf("=");if(s===-1)continue;if(o.slice(0,s).trim()===r)return decodeURIComponent(o.slice(s+1).trim())}return null}}}}function Je(e){if(e?.ownership)return e.ownership;let t=Oe(e);if(!t)return null;return{field:t,resolve:async(n,r)=>{let{resolveAuthenticatedTeamId:o}=await import("@stacksjs/auth");return o(gt(r))}}}async function K(e,t,n){let r=Je(e);if(!r||!r.field||typeof r.resolve!=="function")return{enforced:!1,value:null,field:"",bypass:!1};let o=typeof r.bypass==="function"?!!r.bypass(t,n):!1,s=null;try{s=await r.resolve(t,n)}catch{s=null}return{enforced:!0,value:s,field:String(r.field),bypass:o}}async function Le(e,t,n,r){let o=e?.authedFill?.[t];if(!o)return{};if(typeof o==="function")try{let s=await o(n,r);return s&&typeof s==="object"?s:{}}catch{return{}}if(typeof o==="object"){let s={};for(let[a,p]of Object.entries(o))try{s[a]=typeof p==="function"?await p(n,r):p}catch{}return s}return{}}var qe=await(async()=>{let e=ut.env.STACKS_API_ROW_SCOPING;try{let t=(await import(be("config/security.ts"))).default;return me(t?.api?.rowScoping,e)}catch{return me(void 0,e)}})(),Ve=[];for(let[e,t]of Object.entries(he)){let n=t.traits?.useApi;if(!n)continue;let r=typeof n==="object"?n:{},o=r.uri||t.table||e.toLowerCase()+"s",s=r.routes||["index","show","store","update","destroy"],a=t.table||o,p=Ae(t),w=ze(t),c=xe(o,r.prefix),I=De(t.attributes,w),{read:C,write:D,declared:B}=Ne(n),Y=["store","update","destroy"].some((f)=>s.includes(f));if(Y&&B&&D.length===0)X.warn(`[orm] ${e}: registering UNAUTHENTICATED mutating routes at ${c} (explicit \`middleware: []\` opt-out)`);if(["index","show"].some((f)=>s.includes(f))&&B&&C.length===0)X.debug(`[orm] ${e}: registering public read routes at ${c} (declared \`middleware.read: []\`)`);let E=!!Je(t),J=E&&!C.includes("auth")?["auth",...C]:C,W=Y&&!E;if(W)Ve.push(e);let S=W&&qe==="deny",x=(f,i=J)=>{let u=f;for(let d of i)if(u&&typeof u.middleware==="function")u=u.middleware(d);return u};if(s.includes("index")&&!H("GET",c))x(F.get(c,async(f)=>{try{let i=new URL(f.url),{page:u,perPage:d,offset:h}=Ie(i.searchParams),m=i.searchParams.get("sort"),g=A.selectFrom(a);g=Pe(g,m,I);let N=new Set(["page","per_page","sort","fields","search","include","limit","offset","with_count","withTrashed","onlyTrashed"]);for(let[O,T]of i.searchParams.entries()){if(N.has(O)||!T)continue;if(!/^[a-z_][a-z0-9_]*$/i.test(O))continue;let L=I.get(O);if(L)g=g.where(L,"=",T)}let R=i.searchParams.get("search");if(R&&p.length>0){let O=p.slice(0,5);g=g.where((T)=>{for(let L of O)T=T.orWhere(k(L),"like",`%${R}%`);return T})}let _=i.searchParams.get("fields");if(_){let O=_.split(",").map((T)=>T.trim()).filter((T)=>/^[a-z_][a-z0-9_]*$/i.test(T)).map((T)=>k(T));if(O.length>0)g=g.select(O)}let P=!!t.traits?.useSoftDeletes,b=i.searchParams.get("withTrashed")==="true",v=i.searchParams.get("onlyTrashed")==="true";if(P&&!b)g=v?g.whereNotNull("deleted_at"):g.whereNull("deleted_at");let y=E?await K(t,await G(f),f):{enforced:!1,value:null,field:"",bypass:!1};if(y.enforced&&!y.bypass){if(y.value==null||Array.isArray(y.value)&&y.value.length===0){let O=ye(i,u,d,0,!1,void 0);return new Response(JSON.stringify({data:[],...O,meta:se(i,u,d,0,!1,void 0)}),{status:200,headers:{"Content-Type":"application/json","Cache-Control":"private, no-store",Vary:"Authorization"}})}g=Array.isArray(y.value)?g.where(y.field,"in",y.value):g.where(y.field,"=",y.value)}let j=await g.limit(d+1).offset(h).get()||[],M=j.length>d,ee=(M?j.slice(0,d):j).map((O)=>V(ne(O,t),w)),Re=i.searchParams.get("include");if(Re)ee=await Be(ee,t,Re,he);let Ge=i.searchParams.get("with_count")==="true",q;if(Ge)try{let O=A.selectFrom(a);if(y.enforced&&!y.bypass&&y.value!=null)O=Array.isArray(y.value)?O.where(y.field,"in",y.value):O.where(y.field,"=",y.value);let T=await O.count(),L=typeof T==="number"?T:Number(T?.count??T);if(Number.isFinite(L))q=L}catch{}let re={"Content-Type":"application/json"};if(q!==void 0&&!Number.isNaN(q))re["X-Total-Count"]=String(q);re["Cache-Control"]=y.enforced&&!y.bypass?"private, no-store":"public, max-age=15, must-revalidate",re.Vary="Authorization";let Ke=ye(i,u,d,ee.length,M,q);return new Response(JSON.stringify({data:ee,...Ke,meta:se(i,u,d,ee.length,M,q)}),{status:200,headers:re})}catch(i){if(i instanceof U){let u={error:i.message};if(i.details!==void 0)u.details=i.details;return l(u,i.status||400)}return l({error:`Failed to fetch ${o}`,detail:String(i)},500)}}));if(s.includes("show")&&!H("GET",`${c}/{id}`))x(F.get(`${c}/{id}`,async(f)=>{try{let i=ae(f.params?.id);if(i==null)return l({error:"Invalid ID parameter"},400);let u=await A.selectFrom(a).where({id:i}).executeTakeFirst();if(!u)return l({error:`${e} not found`},404);let d=new URL(f.url);if(t.traits?.useSoftDeletes&&u.deleted_at&&d.searchParams.get("withTrashed")!=="true")return l({error:`${e} not found`},404);let h=E?await K(t,await G(f),f):{enforced:!1,value:null,field:"",bypass:!1};if(h.enforced&&!h.bypass){if(h.value==null||!te(u[h.field],h.value))return l({error:`${e} not found`},404)}let m=V(ne(u,t),w),g=d.searchParams.get("include");if(g){let[b]=await Be([m],t,g,he);m=b}let N=m?.updated_at||m?.created_at,R=N?`W/"${m.id}-${String(N)}"`:void 0,_=f.headers?.get?.("if-none-match");if(R&&_&&_===R)return new Response(null,{status:304,headers:{ETag:R}});let P={"Content-Type":"application/json"};if(R)P.ETag=R;return P["Cache-Control"]=h.enforced&&!h.bypass?"private, no-store":"public, max-age=30, must-revalidate",P.Vary="Authorization",new Response(JSON.stringify({data:m}),{status:200,headers:P})}catch(i){if(i instanceof U){let u={error:i.message};if(i.details!==void 0)u.details=i.details;return l(u,i.status||400)}return l({error:`Failed to fetch ${e}`,detail:String(i)},500)}}));if(!S&&s.includes("store")&&!H("POST",c))x(F.post(c,async(f)=>{try{let i=await we(f),u=fe(i,w),d=de(u,p),h=await G(f);if(h){let b=await Le(t,"creating",h,f);for(let[v,y]of Object.entries(b))if(y!==void 0&&y!==null&&d[v]===void 0)d[v]=y}let m=await K(t,h,f);if(m.enforced&&!m.bypass){if(!h)return l({error:"Auth required"},401);let b=Te(d,m.field,m.value);if(b.error)return l({error:b.error},403);d=b.data}if(Object.keys(d).length===0)return l({error:"No fillable fields provided"},422);let g=pe(d,t,"creating");if(!g.valid)return l({success:!1,message:"Validation failed",errors:g.errors},422);if(t.traits?.useTimestamps!==!1){let b=new Date().toISOString();d.created_at=b,d.updated_at=b}let N=await Qe(d,t),R=le(We(N,t)),_=await A.insertInto(a).values(R).execute(),P=R;try{let b=_?.lastInsertRowid??_?.insertId??_;if(b){let v=await A.selectFrom(a).where({id:b}).executeTakeFirst();if(v)P=v}}catch{}return l({data:V(ne(P,t),w)},201)}catch(i){let{status:u,body:d}=ce(i,e,"create");return l(d,u)}}),D);if(!S&&s.includes("update")){let f=async(i)=>{try{let u=ae(i.params?.id);if(u==null)return l({error:"Invalid ID parameter"},400);let d=await we(i),h=fe(d,w),m=de(h,p),g=await G(i);if(g){let y=await Le(t,"updating",g,i);for(let[j,M]of Object.entries(y))if(M!==void 0&&M!==null&&m[j]===void 0)m[j]=M}if(Object.keys(m).length===0)return l({error:"No fillable fields provided"},422);let N=pe(m,t,"updating");if(!N.valid)return l({success:!1,message:"Validation failed",errors:N.errors},422);let R=await A.selectFrom(a).where({id:u}).executeTakeFirst();if(!R)return l({error:`${e} not found`},404);let _=await K(t,g,i);if(_.enforced&&!_.bypass){if(!g)return l({error:"Auth required"},401);let y=R[_.field];if(!te(y,_.value))return l({error:`Not your ${e}`},403);let j=Object.keys(m).find((M)=>k(M)===k(_.field));if(j!==void 0&&!te(m[j],_.value))return l({error:`Cannot reassign ${e} ownership`},403)}if(t.traits?.useTimestamps!==!1)m.updated_at=new Date().toISOString();let P=await Qe(m,t),b=le(We(P,t));await A.updateTable(a).set(b).where({id:u}).execute();let v={...R,...b};try{let y=await A.selectFrom(a).where({id:u}).executeTakeFirst();if(y)v=y}catch{}return l({data:V(ne(v,t),w)})}catch(u){let{status:d,body:h}=ce(u,e,"update");return l(h,d)}};if(!H("PUT",`${c}/{id}`))x(F.put(`${c}/{id}`,f),D);if(!H("PATCH",`${c}/{id}`))x(F.patch(`${c}/{id}`,f),D)}let Z=!!t.traits?.useSoftDeletes;if(!S&&s.includes("destroy")&&!H("DELETE",`${c}/{id}`))x(F.delete(`${c}/{id}`,async(f)=>{try{let i=ae(f.params?.id);if(i==null)return l({error:"Invalid ID parameter"},400);let u=await A.selectFrom(a).where({id:i}).executeTakeFirst();if(!u)return l({error:`${e} not found`},404);let d=await G(f),h=await K(t,d,f);if(h.enforced&&!h.bypass){if(!d)return l({error:"Auth required"},401);let m=u[h.field];if(!te(m,h.value))return l({error:`Not your ${e}`},403)}if(Z){let m=new Date().toISOString();await A.updateTable(a).set({deleted_at:m,updated_at:m}).where({id:i}).execute()}else await A.deleteFrom(a).where({id:i}).execute();return new Response(null,{status:204})}catch(i){if(i instanceof U){let u={error:i.message};if(i.details!==void 0)u.details=i.details;return l(u,i.status||400)}return l({error:`Failed to delete ${e}`,detail:String(i)},500)}}),D);if(!S&&s.includes("destroy")&&!H("POST",`${c}/bulk-delete`))x(F.post(`${c}/bulk-delete`,async(f)=>{try{let u=(await we(f))?.ids;if(!Array.isArray(u)||u.length===0)return l({error:"An array of IDs is required"},422);if(u.length>100)return l({error:"Cannot delete more than 100 records at once"},422);let d=[],h=[];for(let R of u){let _=ae(R);if(_!=null)d.push(_);else h.push(R)}if(h.length>0)return l({error:"Invalid IDs in batch",invalid:h},422);let m=await G(f),g=await K(t,m,f);if(g.enforced&&!g.bypass){if(!m)return l({error:"Auth required"},401);if(g.value==null)return l({error:"Caller has no ownership identity"},403);let R=await A.selectFrom(a).select(["id",g.field]).execute(),_=new Set(R.filter((b)=>te(b[g.field],g.value)).map((b)=>String(b.id))),P=d.filter((b)=>!_.has(String(b)));if(P.length>0)return l({error:`Cannot delete ${e} you don't own`,ids:P},403)}let N=new Date().toISOString();for(let R of d)if(Z)await A.updateTable(a).set({deleted_at:N,updated_at:N}).where({id:R}).execute();else await A.deleteFrom(a).where({id:R}).execute();return l({message:`Successfully deleted ${d.length} ${o}`})}catch(i){if(i instanceof U){let u={error:i.message};if(i.details!==void 0)u.details=i.details;return l(u,i.status||400)}return l({error:`Failed to bulk delete ${o}`,detail:String(i)},500)}}),D)}{let e=Ce(Ve,qe);if(e)X.warn(e)}var $t=F;export{$t as default};
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/orm",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.73.2",
5
+ "version": "0.74.0",
6
6
  "description": "The Stacks ORM integration",
7
7
  "author": "Chris Breuer",
8
8
  "contributors": [
@@ -63,13 +63,39 @@
63
63
  "prepublishOnly": "bun run build"
64
64
  },
65
65
  "dependencies": {
66
+ "@stacksjs/auth": "0.74.0",
67
+ "@stacksjs/cache": "0.74.0",
68
+ "@stacksjs/cli": "0.74.0",
69
+ "@stacksjs/config": "0.74.0",
70
+ "@stacksjs/database": "0.74.0",
71
+ "@stacksjs/env": "0.74.0",
72
+ "@stacksjs/error-handling": "0.74.0",
73
+ "@stacksjs/events": "0.74.0",
74
+ "@stacksjs/logging": "0.74.0",
75
+ "@stacksjs/path": "0.74.0",
76
+ "@stacksjs/payments": "0.74.0",
77
+ "@stacksjs/query-builder": "0.74.0",
78
+ "@stacksjs/queue": "0.74.0",
79
+ "@stacksjs/realtime": "0.74.0",
80
+ "@stacksjs/router": "0.74.0",
81
+ "@stacksjs/search-engine": "0.74.0",
82
+ "@stacksjs/storage": "0.74.0",
83
+ "@stacksjs/strings": "0.74.0",
66
84
  "@stacksjs/ts-validation": "^0.5.6",
85
+ "@stacksjs/validation": "0.74.0",
67
86
  "bun-query-builder": "^0.2.53"
68
87
  },
88
+ "peerDependencies": {
89
+ "stripe": "22.3.2"
90
+ },
91
+ "peerDependenciesMeta": {
92
+ "stripe": {
93
+ "optional": true
94
+ }
95
+ },
69
96
  "devDependencies": {
70
- "@stacksjs/config": "0.73.2",
97
+ "@stacksjs/types": "0.74.0",
71
98
  "better-dx": "^0.2.24",
72
- "@stacksjs/query-builder": "0.73.2",
73
- "@stacksjs/types": "0.73.2"
99
+ "stripe": "22.3.2"
74
100
  }
75
101
  }