@stacksjs/orm 0.72.62 → 0.72.64
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/auto-crud.d.ts +26 -9
- package/dist/index.js +14 -14
- package/dist/routes.js +1 -1
- package/package.json +4 -4
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 lt=(e,t)=>{for(var n in t)He(e,n,{get:t[n],enumerable:!0,configurable:!0,set:qe.bind(t,n)})};var ct=(e,t)=>()=>(e&&(t=e(e=0)),t);var we=import.meta.require;import{route as F}from"@stacksjs/router";import{env as z}from"@stacksjs/env";import{projectPath as Fe,storagePath as st}from"@stacksjs/path";import{createQueryBuilder as at,defaultConfig as Pe,setConfig as Ee}from"@stacksjs/query-builder";import{HttpError as U}from"@stacksjs/error-handling";import{log as se}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 ie(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 Se(e,t,n){let r=Object.keys(e).find((a)=>k(a)===k(t));if(Array.isArray(n)){if(r===void 0)return{data:e,error:"Ownership value is required"};if(!n.some((a)=>String(a)===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 a of Object.keys(s))if(k(a)===k(t))delete s[a];return s[t]=n,{data:s}}function _e(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((a)=>`${a[0]?.toUpperCase()}${a.slice(1)}`).join("")}Id`;t.push(s)}return[...new Set(t)]}function le(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 Qe(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]),a=Number(n[3]),i=new Date(Date.UTC(r,s-1,a));if(i.getUTCFullYear()!==r||i.getUTCMonth()!==s-1||i.getUTCDate()!==a)return t;return i}function ce(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 Xe=["id","uuid","created_at","updated_at","deleted_at"];function Oe(e,t){let n=new Map;for(let r of[...Object.keys(e??{}),...Xe]){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 xe(e,t,n){if(!t)return e;let r=String(t).split(",").map((a)=>a.trim()).filter(Boolean),s=e;for(let a of r){let i=a.startsWith("-"),p=i?a.slice(1):a;if(!/^\w+$/.test(p))continue;let w=n.get(p);if(!w)continue;s=s.orderBy(w,i?"desc":"asc")}return s}var Ge={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"?Ke(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"?Ye(e):[],set:(e)=>e==null?null:Array.isArray(e)?JSON.stringify(e):e}};function Ke(e){try{return JSON.parse(e)}catch{return e}}function Ye(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,a]of Object.entries(t)){let i=typeof a==="string"?Ge[a]:a;if(!i||typeof i[n]!=="function")continue;if(Object.prototype.hasOwnProperty.call(r,s))r[s]=i[n](r[s]);let p=k(s);if(p!==s&&Object.prototype.hasOwnProperty.call(r,p))r[p]=i[n](r[p])}return r}function fe(e,t,n){let r=t?.attributes??{},s={};for(let[a,i]of Object.entries(r)){let p=i?.validation?.rule;if(!p||typeof p.validate!=="function")continue;let w=Object.prototype.hasOwnProperty.call(e,a);if(!w&&n==="updating")continue;let c=i!==null&&typeof i==="object"&&Object.prototype.hasOwnProperty.call(i,"default"),E=w?e[a]:c?i.default:void 0,C=Qe(p,E),A=p.validate(C);if(!A?.valid&&Array.isArray(A?.errors)&&A.errors.length>0)s[a]=A.errors.map((B)=>i?.validation?.message?.[B?.code]??B?.message??"invalid")}return Object.keys(s).length===0?{valid:!0}:{valid:!1,errors:s}}function ge(e){return e.replace(/\{[^}]*\}/g,"{}").replace(/:[^/]+/g,"{}")}function oe(e){if(Array.isArray(e))return e.filter((t)=>typeof t==="string"&&t.length>0);return typeof e==="string"&&e?[e]:[]}function Te(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?oe(s.read):["auth"],write:"write"in s?oe(s.write):["auth"],declared:!0}}let r=oe(n);return{read:r,write:r,declared:!0}}var be=15,Ze=100;function Ae(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,Ze);return{page:n,perPage:s,offset:(n-1)*s}}function ee(e,t){let n=new URL(e.toString());return n.searchParams.set("page",String(t)),`${n.pathname}${n.search}`}function te(e,t,n,r,s,a){let i=(t-1)*n,p=r===0,w={page:t,per_page:n,from:p?null:i+1,to:p?null:i+r,has_more_pages:s,prev_page_url:t>1?ee(e,t-1):null,next_page_url:s?ee(e,t+1):null};if(a!==void 0&&!Number.isNaN(a)){let c=Math.max(1,Math.ceil(a/n));w.total=a,w.last_page=c,w.first_page_url=ee(e,1),w.last_page_url=ee(e,c)}return w}function pe(e,t,n,r,s,a){let{page:i,...p}=te(e,t,n,r,s,a);return{current_page:i,...p}}import{readdirSync as et}from"fs";import{basename as tt,extname as $e,join as nt}from"path";function rt(e){let t=[],n=(r)=>{let s;try{s=et(r,{withFileTypes:!0})}catch{return}for(let a of s){let i=nt(r,a.name);if(a.isDirectory()){n(i);continue}if(![".ts",".js"].includes($e(a.name)))continue;if(a.name.startsWith(".")||a.name.startsWith("index"))continue;t.push(i)}};return n(e),t.sort()}async function Ne(e,t,n){for(let r of rt(e))try{let s=$e(r),a=await import(`${r}?t=${Date.now()}`),i=a.default??a,p=i.name??tt(r,s);t[p]={...i,name:p}}catch(s){n?.(r,s)}}async function Ie(e){let t={};return await Ne(e.defaultsRoot,t,e.onImportError),await Ne(e.userRoot,t,e.onImportError),t}var ot=Fe("config/qb.ts");try{let e=(await import(ot)).default;Ee(e??Pe)}catch{se.debug("[orm] No config/qb.ts override found - deriving config from DB_CONNECTION");let e=z.DB_CONNECTION||"sqlite";Ee({...Pe,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 ye=await Ie({defaultsRoot:st("framework/defaults/app/Models"),userRoot:Fe("app/Models"),onImportError:(e,t)=>se.warn(`[orm] Could not load model ${e}: ${t.message}`)}),T=at();function H(e,t){let n=ge(t);return F.routes.some((r)=>r.method===e&&ge(String(r.path??""))===n)}function Ue(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 De(e,t,n,r){if(!e.length)return e;let s=n.split(",").map((c)=>c.trim()).filter(Boolean);if(!s.length)return e;let a=Array.isArray(t.belongsTo)?t.belongsTo:[],i=Array.isArray(t.hasMany)?t.hasMany:[],p=Array.isArray(t.hasOne)?t.hasOne:[],w=new Map;for(let c of a)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 i)w.set(Ce(k(c)),{kind:"hasMany",modelName:c});for(let c of s){let E=w.get(c);if(!E)continue;let C=r[E.modelName];if(!C)continue;let A=C.table||Ce(k(E.modelName)),B=Ue(C),ae=(L)=>V(Y(L,C),B);if(E.kind==="belongsTo"||E.kind==="hasOne"){let L=`${k(E.modelName)}_id`,j=[...new Set(e.map((_)=>_[L]).filter((_)=>_!=null))];if(!j.length){for(let _ of e)_[c]=null;continue}let J=await T.selectFrom(A).whereIn("id",j).get(),I=new Map;for(let _ of J??[])I.set(String(_.id),ae(_));for(let _ of e)_[c]=I.get(String(_[L]))??null}else{let L=String(t.name??""),j=`${k(L)}_id`,J=[...new Set(e.map((l)=>l.id).filter((l)=>l!=null))];if(!J.length){for(let l of e)l[c]=[];continue}let I=await T.selectFrom(A).whereIn(j,J).get(),_=new Map;for(let l of I??[]){let o=String(l[j]),u=_.get(o)??[];u.push(ae(l)),_.set(o,u)}for(let l of e)l[c]=_.get(String(l.id))??[]}}return e}async function je(e,t){let n=t?.set;if(!n||typeof n!=="object")return e;let r={...e};for(let[s,a]of Object.entries(n)){if(typeof a!=="function"||!(s in r))continue;try{r[s]=await a(r)}catch{}}return r}function Me(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 ne=1048576;async function me(e){if(Number(e.headers?.get?.("content-length")??0)>ne)throw new U(413,`Request body exceeds ${ne}-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>ne)throw new U(413,`Request body exceeds ${ne}-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 re(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 Be(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 Q(e){let t=e._authenticatedUser;if(t)return t;let n=Be(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 it(e){let t=Be(e),n=e.headers?.get?.("cookie")||"";return{bearerToken:()=>t,cookies:{get:(r)=>{for(let s of n.split(";")){let a=s.indexOf("=");if(a===-1)continue;if(s.slice(0,a).trim()===r)return decodeURIComponent(s.slice(a+1).trim())}return null}}}}function Le(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(it(r))}}}async function X(e,t,n){let r=Le(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,a=null;try{a=await r.resolve(t,n)}catch{a=null}return{enforced:!0,value:a,field:String(r.field),bypass:s}}async function ve(e,t,n,r){let s=e?.authedFill?.[t];if(!s)return{};if(typeof s==="function")try{let a=await s(n,r);return a&&typeof a==="object"?a:{}}catch{return{}}if(typeof s==="object"){let a={};for(let[i,p]of Object.entries(s))try{a[i]=typeof p==="function"?await p(n,r):p}catch{}return a}return{}}for(let[e,t]of Object.entries(ye)){let n=t.traits?.useApi;if(!n)continue;let r=typeof n==="object"?n:{},s=r.uri||t.table||e.toLowerCase()+"s",a=r.routes||["index","show","store","update","destroy"],i=t.table||s,p=_e(t),w=Ue(t),c=Re(s,r.prefix),E=Oe(t.attributes,w),{read:C,write:A,declared:B}=Te(n);if(["store","update","destroy"].some((l)=>a.includes(l))&&B&&A.length===0)se.warn(`[orm] ${e}: registering UNAUTHENTICATED mutating routes at ${c} (explicit \`middleware: []\` opt-out)`);if(["index","show"].some((l)=>a.includes(l))&&B&&C.length===0)se.debug(`[orm] ${e}: registering public read routes at ${c} (declared \`middleware.read: []\`)`);let j=!!Le(t),J=j&&!C.includes("auth")?["auth",...C]:C,I=(l,o=J)=>{let u=l;for(let f of o)if(u&&typeof u.middleware==="function")u=u.middleware(f);return u};if(a.includes("index")&&!H("GET",c))I(F.get(c,async(l)=>{try{let o=new URL(l.url),{page:u,perPage:f,offset:h}=Ae(o.searchParams),m=o.searchParams.get("sort"),g=T.selectFrom(i);g=xe(g,m,E);let P=new Set(["page","per_page","sort","fields","search","include","limit","offset","with_count","withTrashed","onlyTrashed"]);for(let[O,x]of o.searchParams.entries()){if(P.has(O)||!x)continue;if(!/^[a-z_][a-z0-9_]*$/i.test(O))continue;let W=E.get(O);if(W)g=g.where(W,"=",x)}let R=o.searchParams.get("search");if(R&&p.length>0){let O=p.slice(0,5);g=g.where((x)=>{for(let W of O)x=x.orWhere(k(W),"like",`%${R}%`);return x})}let S=o.searchParams.get("fields");if(S){let O=S.split(",").map((x)=>x.trim()).filter((x)=>/^[a-z_][a-z0-9_]*$/i.test(x)).map((x)=>k(x));if(O.length>0)g=g.select(O)}let N=!!t.traits?.useSoftDeletes,b=o.searchParams.get("withTrashed")==="true",D=o.searchParams.get("onlyTrashed")==="true";if(N&&!b)g=D?g.whereNotNull("deleted_at"):g.whereNull("deleted_at");let y=j?await X(t,await Q(l),l):{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=pe(o,u,f,0,!1,void 0);return new Response(JSON.stringify({data:[],...O,meta:te(o,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 M=await g.limit(f+1).offset(h).get()||[],v=M.length>f,G=(v?M.slice(0,f):M).map((O)=>V(Y(O,t),w)),he=o.searchParams.get("include");if(he)G=await De(G,t,he,ye);let We=o.searchParams.get("with_count")==="true",q;if(We)try{let O=T.selectFrom(i);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 x=await O.count(),W=typeof x==="number"?x:Number(x?.count??x);if(Number.isFinite(W))q=W}catch{}let Z={"Content-Type":"application/json"};if(q!==void 0&&!Number.isNaN(q))Z["X-Total-Count"]=String(q);Z["Cache-Control"]=y.enforced&&!y.bypass?"private, no-store":"public, max-age=15, must-revalidate",Z.Vary="Authorization";let ze=pe(o,u,f,G.length,v,q);return new Response(JSON.stringify({data:G,...ze,meta:te(o,u,f,G.length,v,q)}),{status:200,headers:Z})}catch(o){if(o instanceof U){let u={error:o.message};if(o.details!==void 0)u.details=o.details;return d(u,o.status||400)}return d({error:`Failed to fetch ${s}`,detail:String(o)},500)}}));if(a.includes("show")&&!H("GET",`${c}/{id}`))I(F.get(`${c}/{id}`,async(l)=>{try{let o=re(l.params?.id);if(o==null)return d({error:"Invalid ID parameter"},400);let u=await T.selectFrom(i).where({id:o}).executeTakeFirst();if(!u)return d({error:`${e} not found`},404);let f=new URL(l.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 Q(l),l):{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=V(Y(u,t),w),g=f.searchParams.get("include");if(g){let[b]=await De([m],t,g,ye);m=b}let P=m?.updated_at||m?.created_at,R=P?`W/"${m.id}-${String(P)}"`:void 0,S=l.headers?.get?.("if-none-match");if(R&&S&&S===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(o){if(o instanceof U){let u={error:o.message};if(o.details!==void 0)u.details=o.details;return d(u,o.status||400)}return d({error:`Failed to fetch ${e}`,detail:String(o)},500)}}));if(a.includes("store")&&!H("POST",c))I(F.post(c,async(l)=>{try{let o=await me(l),u=ce(o,w),f=le(u,p),h=await Q(l);if(h){let b=await ve(t,"creating",h,l);for(let[D,y]of Object.entries(b))if(y!==void 0&&y!==null&&f[D]===void 0)f[D]=y}let m=await X(t,h,l);if(m.enforced&&!m.bypass){if(!h)return d({error:"Auth required"},401);let b=Se(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 je(f,t),R=ue(Me(P,t)),S=await T.insertInto(i).values(R).execute(),N=R;try{let b=S?.lastInsertRowid??S?.insertId??S;if(b){let D=await T.selectFrom(i).where({id:b}).executeTakeFirst();if(D)N=D}}catch{}return d({data:V(Y(N,t),w)},201)}catch(o){let{status:u,body:f}=ie(o,e,"create");return d(f,u)}}),A);if(a.includes("update")){let l=async(o)=>{try{let u=re(o.params?.id);if(u==null)return d({error:"Invalid ID parameter"},400);let f=await me(o),h=ce(f,w),m=le(h,p),g=await Q(o);if(g){let y=await ve(t,"updating",g,o);for(let[M,v]of Object.entries(y))if(v!==void 0&&v!==null&&m[M]===void 0)m[M]=v}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(i).where({id:u}).executeTakeFirst();if(!R)return d({error:`${e} not found`},404);let S=await X(t,g,o);if(S.enforced&&!S.bypass){if(!g)return d({error:"Auth required"},401);let y=R[S.field];if(!K(y,S.value))return d({error:`Not your ${e}`},403);let M=Object.keys(m).find((v)=>k(v)===k(S.field));if(M!==void 0&&!K(m[M],S.value))return d({error:`Cannot reassign ${e} ownership`},403)}if(t.traits?.useTimestamps!==!1)m.updated_at=new Date().toISOString();let N=await je(m,t),b=ue(Me(N,t));await T.updateTable(i).set(b).where({id:u}).execute();let D={...R,...b};try{let y=await T.selectFrom(i).where({id:u}).executeTakeFirst();if(y)D=y}catch{}return d({data:V(Y(D,t),w)})}catch(u){let{status:f,body:h}=ie(u,e,"update");return d(h,f)}};if(!H("PUT",`${c}/{id}`))I(F.put(`${c}/{id}`,l),A);if(!H("PATCH",`${c}/{id}`))I(F.patch(`${c}/{id}`,l),A)}let _=!!t.traits?.useSoftDeletes;if(a.includes("destroy")&&!H("DELETE",`${c}/{id}`))I(F.delete(`${c}/{id}`,async(l)=>{try{let o=re(l.params?.id);if(o==null)return d({error:"Invalid ID parameter"},400);let u=await T.selectFrom(i).where({id:o}).executeTakeFirst();if(!u)return d({error:`${e} not found`},404);let f=await Q(l),h=await X(t,f,l);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(_){let m=new Date().toISOString();await T.updateTable(i).set({deleted_at:m,updated_at:m}).where({id:o}).execute()}else await T.deleteFrom(i).where({id:o}).execute();return new Response(null,{status:204})}catch(o){if(o instanceof U){let u={error:o.message};if(o.details!==void 0)u.details=o.details;return d(u,o.status||400)}return d({error:`Failed to delete ${e}`,detail:String(o)},500)}}),A);if(a.includes("destroy")&&!H("POST",`${c}/bulk-delete`))I(F.post(`${c}/bulk-delete`,async(l)=>{try{let u=(await me(l))?.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 S=re(R);if(S!=null)f.push(S);else h.push(R)}if(h.length>0)return d({error:"Invalid IDs in batch",invalid:h},422);let m=await Q(l),g=await X(t,m,l);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(i).select(["id",g.field]).execute(),S=new Set(R.filter((b)=>K(b[g.field],g.value)).map((b)=>String(b.id))),N=f.filter((b)=>!S.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(_)await T.updateTable(i).set({deleted_at:P,updated_at:P}).where({id:R}).execute();else await T.deleteFrom(i).where({id:R}).execute();return d({message:`Successfully deleted ${f.length} ${s}`})}catch(o){if(o instanceof U){let u={error:o.message};if(o.details!==void 0)u.details=o.details;return d(u,o.status||400)}return d({error:`Failed to bulk delete ${s}`,detail:String(o)},500)}}),A)}var xt=F;export{xt as default};
|
|
2
|
+
var Je=Object.defineProperty;var qe=(e)=>e;function Ve(e,t){this[e]=qe.bind(null,t)}var ct=(e,t)=>{for(var n in t)Je(e,n,{get:t[n],enumerable:!0,configurable:!0,set:Ve.bind(t,n)})};var dt=(e,t)=>()=>(e&&(t=e(e=0)),t);var he=import.meta.require;import{route as F}from"@stacksjs/router";import{env as z}from"@stacksjs/env";import{projectPath as Ue,storagePath as at}from"@stacksjs/path";import{createQueryBuilder as ot,defaultConfig as Ee,setConfig as Ce}from"@stacksjs/query-builder";import{HttpError as U}from"@stacksjs/error-handling";import{log as Z}from"@stacksjs/logging";function Qe(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 ie(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(Qe(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 Se(e,t,n){let r=Object.keys(e).find((a)=>k(a)===k(t));if(Array.isArray(n)){if(r===void 0)return{data:e,error:"Ownership value is required"};if(!n.some((a)=>String(a)===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 a of Object.keys(s))if(k(a)===k(t))delete s[a];return s[t]=n,{data:s}}function _e(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((a)=>`${a[0]?.toUpperCase()}${a.slice(1)}`).join("")}Id`;t.push(s)}return[...new Set(t)]}function le(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]),a=Number(n[3]),i=new Date(Date.UTC(r,s-1,a));if(i.getUTCFullYear()!==r||i.getUTCMonth()!==s-1||i.getUTCDate()!==a)return t;return i}function ce(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 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((a)=>a.trim()).filter(Boolean),s=e;for(let a of r){let i=a.startsWith("-"),p=i?a.slice(1):a;if(!/^\w+$/.test(p))continue;let w=n.get(p);if(!w)continue;s=s.orderBy(w,i?"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,a]of Object.entries(t)){let i=typeof a==="string"?Ke[a]:a;if(!i||typeof i[n]!=="function")continue;if(Object.prototype.hasOwnProperty.call(r,s))r[s]=i[n](r[s]);let p=k(s);if(p!==s&&Object.prototype.hasOwnProperty.call(r,p))r[p]=i[n](r[p])}return r}function fe(e,t,n){let r=t?.attributes??{},s={};for(let[a,i]of Object.entries(r)){let p=i?.validation?.rule;if(!p||typeof p.validate!=="function")continue;let w=Object.prototype.hasOwnProperty.call(e,a);if(!w&&n==="updating")continue;let c=i!==null&&typeof i==="object"&&Object.prototype.hasOwnProperty.call(i,"default"),E=w?e[a]:c?i.default:void 0,C=Xe(p,E),A=p.validate(C);if(!A?.valid&&Array.isArray(A?.errors)&&A.errors.length>0)s[a]=A.errors.map((B)=>i?.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 oe(e){if(Array.isArray(e))return e.filter((t)=>typeof t==="string"&&t.length>0);return typeof e==="string"&&e?[e]:[]}function Ae(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?oe(s.read):["auth"],write:"write"in s?oe(s.write):["auth"],declared:!0}}let r=oe(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,a){let i=(t-1)*n,p=r===0,w={page:t,per_page:n,from:p?null:i+1,to:p?null:i+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(a!==void 0&&!Number.isNaN(a)){let c=Math.max(1,Math.ceil(a/n));w.total=a,w.last_page=c,w.first_page_url=te(e,1),w.last_page_url=te(e,c)}return w}function ge(e,t,n,r,s,a){let{page:i,...p}=ne(e,t,n,r,s,a);return{current_page:i,...p}}import{readdirSync as tt}from"fs";import{basename as nt,extname as Ie,join as rt}from"path";function st(e){let t=[],n=(r)=>{let s;try{s=tt(r,{withFileTypes:!0})}catch{return}for(let a of s){let i=rt(r,a.name);if(a.isDirectory()){n(i);continue}if(![".ts",".js"].includes(Ie(a.name)))continue;if(a.name.startsWith(".")||a.name.startsWith("index"))continue;t.push(i)}};return n(e),t.sort()}async function $e(e,t,n){for(let r of st(e))try{let s=Ie(r),a=await import(`${r}?t=${Date.now()}`),i=a.default??a,p=i.name??nt(r,s);t[p]={...i,name:p}}catch(s){n?.(r,s)}}async function Pe(e){let t={};return await $e(e.defaultsRoot,t,e.onImportError),await $e(e.userRoot,t,e.onImportError),t}var it=Ue("config/qb.ts");try{let e=(await import(it)).default;Ce(e??Ee)}catch{Z.debug("[orm] No config/qb.ts override found - deriving config from DB_CONNECTION");let e=z.DB_CONNECTION||"sqlite";Ce({...Ee,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 pe=await Pe({defaultsRoot:at("framework/defaults/app/Models"),userRoot:Ue("app/Models"),onImportError:(e,t)=>Z.warn(`[orm] Could not load model ${e}: ${t.message}`)}),T=ot();function H(e,t){let n=Te(F.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 De(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((c)=>c.trim()).filter(Boolean);if(!s.length)return e;let a=Array.isArray(t.belongsTo)?t.belongsTo:[],i=Array.isArray(t.hasMany)?t.hasMany:[],p=Array.isArray(t.hasOne)?t.hasOne:[],w=new Map;for(let c of a)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 i)w.set(De(k(c)),{kind:"hasMany",modelName:c});for(let c of s){let E=w.get(c);if(!E)continue;let C=r[E.modelName];if(!C)continue;let A=C.table||De(k(E.modelName)),B=Be(C),ae=(L)=>V(Y(L,C),B);if(E.kind==="belongsTo"||E.kind==="hasOne"){let L=`${k(E.modelName)}_id`,j=[...new Set(e.map((_)=>_[L]).filter((_)=>_!=null))];if(!j.length){for(let _ of e)_[c]=null;continue}let J=await T.selectFrom(A).whereIn("id",j).get(),I=new Map;for(let _ of J??[])I.set(String(_.id),ae(_));for(let _ of e)_[c]=I.get(String(_[L]))??null}else{let L=String(t.name??""),j=`${k(L)}_id`,J=[...new Set(e.map((l)=>l.id).filter((l)=>l!=null))];if(!J.length){for(let l of e)l[c]=[];continue}let I=await T.selectFrom(A).whereIn(j,J).get(),_=new Map;for(let l of I??[]){let o=String(l[j]),u=_.get(o)??[];u.push(ae(l)),_.set(o,u)}for(let l of e)l[c]=_.get(String(l.id))??[]}}return e}async function Me(e,t){let n=t?.set;if(!n||typeof n!=="object")return e;let r={...e};for(let[s,a]of Object.entries(n)){if(typeof a!=="function"||!(s in r))continue;try{r[s]=await a(r)}catch{}}return r}function ve(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 Le(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 Q(e){let t=e._authenticatedUser;if(t)return t;let n=Le(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 ut(e){let t=Le(e),n=e.headers?.get?.("cookie")||"";return{bearerToken:()=>t,cookies:{get:(r)=>{for(let s of n.split(";")){let a=s.indexOf("=");if(a===-1)continue;if(s.slice(0,a).trim()===r)return decodeURIComponent(s.slice(a+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(ut(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,a=null;try{a=await r.resolve(t,n)}catch{a=null}return{enforced:!0,value:a,field:String(r.field),bypass:s}}async function Fe(e,t,n,r){let s=e?.authedFill?.[t];if(!s)return{};if(typeof s==="function")try{let a=await s(n,r);return a&&typeof a==="object"?a:{}}catch{return{}}if(typeof s==="object"){let a={};for(let[i,p]of Object.entries(s))try{a[i]=typeof p==="function"?await p(n,r):p}catch{}return a}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",a=r.routes||["index","show","store","update","destroy"],i=t.table||s,p=_e(t),w=Be(t),c=Re(s,r.prefix),E=xe(t.attributes,w),{read:C,write:A,declared:B}=Ae(n);if(["store","update","destroy"].some((l)=>a.includes(l))&&B&&A.length===0)Z.warn(`[orm] ${e}: registering UNAUTHENTICATED mutating routes at ${c} (explicit \`middleware: []\` opt-out)`);if(["index","show"].some((l)=>a.includes(l))&&B&&C.length===0)Z.debug(`[orm] ${e}: registering public read routes at ${c} (declared \`middleware.read: []\`)`);let j=!!We(t),J=j&&!C.includes("auth")?["auth",...C]:C,I=(l,o=J)=>{let u=l;for(let f of o)if(u&&typeof u.middleware==="function")u=u.middleware(f);return u};if(a.includes("index")&&!H("GET",c))I(F.get(c,async(l)=>{try{let o=new URL(l.url),{page:u,perPage:f,offset:h}=Ne(o.searchParams),m=o.searchParams.get("sort"),g=T.selectFrom(i);g=Oe(g,m,E);let P=new Set(["page","per_page","sort","fields","search","include","limit","offset","with_count","withTrashed","onlyTrashed"]);for(let[x,O]of o.searchParams.entries()){if(P.has(x)||!O)continue;if(!/^[a-z_][a-z0-9_]*$/i.test(x))continue;let W=E.get(x);if(W)g=g.where(W,"=",O)}let R=o.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 S=o.searchParams.get("fields");if(S){let x=S.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=o.searchParams.get("withTrashed")==="true",D=o.searchParams.get("onlyTrashed")==="true";if(N&&!b)g=D?g.whereNotNull("deleted_at"):g.whereNull("deleted_at");let y=j?await X(t,await Q(l),l):{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(o,u,f,0,!1,void 0);return new Response(JSON.stringify({data:[],...x,meta:ne(o,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 M=await g.limit(f+1).offset(h).get()||[],v=M.length>f,G=(v?M.slice(0,f):M).map((x)=>V(Y(x,t),w)),me=o.searchParams.get("include");if(me)G=await je(G,t,me,pe);let ze=o.searchParams.get("with_count")==="true",q;if(ze)try{let x=T.selectFrom(i);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))q=W}catch{}let ee={"Content-Type":"application/json"};if(q!==void 0&&!Number.isNaN(q))ee["X-Total-Count"]=String(q);ee["Cache-Control"]=y.enforced&&!y.bypass?"private, no-store":"public, max-age=15, must-revalidate",ee.Vary="Authorization";let He=ge(o,u,f,G.length,v,q);return new Response(JSON.stringify({data:G,...He,meta:ne(o,u,f,G.length,v,q)}),{status:200,headers:ee})}catch(o){if(o instanceof U){let u={error:o.message};if(o.details!==void 0)u.details=o.details;return d(u,o.status||400)}return d({error:`Failed to fetch ${s}`,detail:String(o)},500)}}));if(a.includes("show")&&!H("GET",`${c}/{id}`))I(F.get(`${c}/{id}`,async(l)=>{try{let o=se(l.params?.id);if(o==null)return d({error:"Invalid ID parameter"},400);let u=await T.selectFrom(i).where({id:o}).executeTakeFirst();if(!u)return d({error:`${e} not found`},404);let f=new URL(l.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 Q(l),l):{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=V(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,S=l.headers?.get?.("if-none-match");if(R&&S&&S===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(o){if(o instanceof U){let u={error:o.message};if(o.details!==void 0)u.details=o.details;return d(u,o.status||400)}return d({error:`Failed to fetch ${e}`,detail:String(o)},500)}}));if(a.includes("store")&&!H("POST",c))I(F.post(c,async(l)=>{try{let o=await ye(l),u=ce(o,w),f=le(u,p),h=await Q(l);if(h){let b=await Fe(t,"creating",h,l);for(let[D,y]of Object.entries(b))if(y!==void 0&&y!==null&&f[D]===void 0)f[D]=y}let m=await X(t,h,l);if(m.enforced&&!m.bypass){if(!h)return d({error:"Auth required"},401);let b=Se(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 Me(f,t),R=ue(ve(P,t)),S=await T.insertInto(i).values(R).execute(),N=R;try{let b=S?.lastInsertRowid??S?.insertId??S;if(b){let D=await T.selectFrom(i).where({id:b}).executeTakeFirst();if(D)N=D}}catch{}return d({data:V(Y(N,t),w)},201)}catch(o){let{status:u,body:f}=ie(o,e,"create");return d(f,u)}}),A);if(a.includes("update")){let l=async(o)=>{try{let u=se(o.params?.id);if(u==null)return d({error:"Invalid ID parameter"},400);let f=await ye(o),h=ce(f,w),m=le(h,p),g=await Q(o);if(g){let y=await Fe(t,"updating",g,o);for(let[M,v]of Object.entries(y))if(v!==void 0&&v!==null&&m[M]===void 0)m[M]=v}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(i).where({id:u}).executeTakeFirst();if(!R)return d({error:`${e} not found`},404);let S=await X(t,g,o);if(S.enforced&&!S.bypass){if(!g)return d({error:"Auth required"},401);let y=R[S.field];if(!K(y,S.value))return d({error:`Not your ${e}`},403);let M=Object.keys(m).find((v)=>k(v)===k(S.field));if(M!==void 0&&!K(m[M],S.value))return d({error:`Cannot reassign ${e} ownership`},403)}if(t.traits?.useTimestamps!==!1)m.updated_at=new Date().toISOString();let N=await Me(m,t),b=ue(ve(N,t));await T.updateTable(i).set(b).where({id:u}).execute();let D={...R,...b};try{let y=await T.selectFrom(i).where({id:u}).executeTakeFirst();if(y)D=y}catch{}return d({data:V(Y(D,t),w)})}catch(u){let{status:f,body:h}=ie(u,e,"update");return d(h,f)}};if(!H("PUT",`${c}/{id}`))I(F.put(`${c}/{id}`,l),A);if(!H("PATCH",`${c}/{id}`))I(F.patch(`${c}/{id}`,l),A)}let _=!!t.traits?.useSoftDeletes;if(a.includes("destroy")&&!H("DELETE",`${c}/{id}`))I(F.delete(`${c}/{id}`,async(l)=>{try{let o=se(l.params?.id);if(o==null)return d({error:"Invalid ID parameter"},400);let u=await T.selectFrom(i).where({id:o}).executeTakeFirst();if(!u)return d({error:`${e} not found`},404);let f=await Q(l),h=await X(t,f,l);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(_){let m=new Date().toISOString();await T.updateTable(i).set({deleted_at:m,updated_at:m}).where({id:o}).execute()}else await T.deleteFrom(i).where({id:o}).execute();return new Response(null,{status:204})}catch(o){if(o instanceof U){let u={error:o.message};if(o.details!==void 0)u.details=o.details;return d(u,o.status||400)}return d({error:`Failed to delete ${e}`,detail:String(o)},500)}}),A);if(a.includes("destroy")&&!H("POST",`${c}/bulk-delete`))I(F.post(`${c}/bulk-delete`,async(l)=>{try{let u=(await ye(l))?.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 S=se(R);if(S!=null)f.push(S);else h.push(R)}if(h.length>0)return d({error:"Invalid IDs in batch",invalid:h},422);let m=await Q(l),g=await X(t,m,l);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(i).select(["id",g.field]).execute(),S=new Set(R.filter((b)=>K(b[g.field],g.value)).map((b)=>String(b.id))),N=f.filter((b)=>!S.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(_)await T.updateTable(i).set({deleted_at:P,updated_at:P}).where({id:R}).execute();else await T.deleteFrom(i).where({id:R}).execute();return d({message:`Successfully deleted ${f.length} ${s}`})}catch(o){if(o instanceof U){let u={error:o.message};if(o.details!==void 0)u.details=o.details;return d(u,o.status||400)}return d({error:`Failed to bulk delete ${s}`,detail:String(o)},500)}}),A)}var Tt=F;export{Tt 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.72.
|
|
5
|
+
"version": "0.72.64",
|
|
6
6
|
"description": "The Stacks ORM integration",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"contributors": [
|
|
@@ -67,9 +67,9 @@
|
|
|
67
67
|
"bun-query-builder": "^0.2.53"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
|
-
"@stacksjs/config": "0.72.
|
|
70
|
+
"@stacksjs/config": "0.72.64",
|
|
71
71
|
"better-dx": "^0.2.24",
|
|
72
|
-
"@stacksjs/query-builder": "0.72.
|
|
73
|
-
"@stacksjs/types": "0.72.
|
|
72
|
+
"@stacksjs/query-builder": "0.72.64",
|
|
73
|
+
"@stacksjs/types": "0.72.64"
|
|
74
74
|
}
|
|
75
75
|
}
|