@stacksjs/orm 0.75.109 → 0.75.111

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.
Files changed (48) hide show
  1. package/dist/api-routes.js +0 -0
  2. package/dist/auto-crud.js +1 -0
  3. package/dist/batch-loader.js +1 -0
  4. package/dist/builder.d.ts +68 -0
  5. package/dist/builder.js +0 -0
  6. package/dist/db.js +1 -0
  7. package/dist/define-model.js +1 -0
  8. package/dist/extend-model.js +1 -0
  9. package/dist/gdpr/engine.js +1 -0
  10. package/dist/gdpr/index.js +1 -0
  11. package/dist/gdpr/models.js +1 -0
  12. package/dist/gdpr/plan.js +3 -0
  13. package/dist/gdpr/register.js +4 -0
  14. package/dist/gdpr/types.js +0 -0
  15. package/dist/generate-database-schema.js +21 -0
  16. package/dist/generated/index.d.ts +1 -0
  17. package/dist/generated/index.js +1 -0
  18. package/dist/generated/table-traits.d.ts +8 -0
  19. package/dist/generated/table-traits.js +135 -0
  20. package/dist/generated/types.d.ts +1 -0
  21. package/dist/generated/types.js +0 -0
  22. package/dist/index.js +1 -27
  23. package/dist/migration-tables.js +1 -0
  24. package/dist/model-registry.js +1 -2
  25. package/dist/model-types.js +0 -0
  26. package/dist/ownership.js +1 -0
  27. package/dist/paginator-request.js +1 -0
  28. package/dist/paginator.js +1 -0
  29. package/dist/routes.js +1 -2
  30. package/dist/subquery.js +1 -0
  31. package/dist/traits/activity-log.js +1 -0
  32. package/dist/traits/actor.js +1 -0
  33. package/dist/traits/audit.js +1 -0
  34. package/dist/traits/billable.js +1 -0
  35. package/dist/traits/categorizable.js +1 -0
  36. package/dist/traits/commentable.js +1 -0
  37. package/dist/traits/index.d.ts +11 -0
  38. package/dist/traits/index.js +1 -0
  39. package/dist/traits/likeable.js +1 -0
  40. package/dist/traits/soft-deletes.js +1 -0
  41. package/dist/traits/taggable.js +1 -0
  42. package/dist/traits/two-factor.js +1 -0
  43. package/dist/transaction.js +1 -0
  44. package/dist/types.js +0 -0
  45. package/dist/utils/compiled-binary.js +1 -0
  46. package/dist/utils/encrypted.js +1 -0
  47. package/dist/utils/prunable.js +1 -0
  48. package/package.json +24 -24
package/dist/index.js CHANGED
@@ -1,27 +1 @@
1
- // @bun
2
- var mt=(e,n,t)=>()=>{if(e)try{n=e(e=0)}catch(r){t=[r]}if(t)throw t[0];return n};var Xn=import.meta.require;import{readdirSync as io}from"fs";import{basename as ao,extname as Vt,join as so}from"path";function uo(e){let n=[],t=(r)=>{let o;try{o=io(r,{withFileTypes:!0})}catch{return}for(let i of o){let a=so(r,i.name);if(i.isDirectory()){t(a);continue}if(![".ts",".js"].includes(Vt(i.name)))continue;if(i.name.startsWith(".")||i.name.startsWith("index"))continue;n.push(a)}};return t(e),n.sort()}async function Wt(e,n,t,r){for(let o of uo(e))try{let i=Vt(o),a=await import(`${o}?t=${Date.now()}`),s=a.default??a,u=s.name??ao(o,i);t.models[u]={...s,name:u},t.origins[u]=n}catch(i){r?.(o,i)}}async function co(e){let n={models:{},origins:{}};return await Wt(e.defaultsRoot,"default",n,e.onImportError),await Wt(e.userRoot,"app",n,e.onImportError),n}async function Qt(e){return(await co(e)).models}function ec(e,n){let t,r="default";if(n!==void 0&&n!==null)t=n.split(","),r="env";else if(typeof e==="string")t=[e],r="config";else if(Array.isArray(e)&&e.every((i)=>typeof i==="string"))t=e,r="config";if(t===void 0)return{all:!0,own:!1,names:new Set,source:r};let o=t.map((i)=>i.trim().toLowerCase()).filter(Boolean);if(o.length===0||o.includes("none"))return{all:!1,own:!1,names:new Set,source:r};if(o.includes("all"))return{all:!0,own:!1,names:new Set,source:r};return{all:!1,own:o.includes("own"),names:new Set(o.filter((i)=>i!=="own")),source:r}}function tc(e,n){let t={},r=new Set;for(let[o,i]of Object.entries(e.models)){if(!i?.traits?.useApi)continue;let a=o.toLowerCase(),s=n.names.has(a);if(s)r.add(a);if(n.all||s||n.own&&e.origins[o]==="app")t[o]=i}return{models:t,unmatched:[...n.names].filter((o)=>!r.has(o)).sort()}}var zt=()=>{};import{path as Ht}from"@stacksjs/path";async function Ve(){return Qt({defaultsRoot:Ht.frameworkPath("defaults/app/Models"),userRoot:Ht.userModelsPath()})}var Qe=mt(()=>{zt()});import"@stacksjs/validation/runtime";var Zn=/(?:^|[/\\])(?:\$bunfs|~BUN)(?:[/\\]|$)/;function gt(e=Bun.main){if(!e)return!1;return Zn.test(e)}import{log as ve}from"@stacksjs/cli";import{db as yt,mutationCount as wt}from"@stacksjs/database/runtime";async function er(e,n={}){let{olderThanDays:t=30,column:r="created_at",query:o}=n;try{if(o){let u=yt.deleteFrom(e);u=o(u);let c=wt(await u.execute());return ve.info(`Pruned ${c} records from ${e}`),c}let i=new Date;i.setDate(i.getDate()-t);let a=await yt.deleteFrom(e).where(r,"<",i.toISOString()).execute(),s=wt(a);return ve.info(`Pruned ${s} records from ${e} older than ${t} days`),s}catch(i){throw ve.error(`Failed to prune ${e}:`,i),i}}async function Xs(e,n={}){return er(e,n)}function Zs(e){if(!e?.prunable)return null;if(typeof e.prunable==="boolean")return{olderThanDays:30,column:"created_at"};return e.prunable}import{createCipheriv as tr,createDecipheriv as nr,createHash as rr,randomBytes as or}from"crypto";import{log as se}from"@stacksjs/logging";var bt="enc:",ht="aes-256-gcm",ir=12,ae=null;async function kt(){if(ae)return ae;let e=process.env.APP_KEY;if(!e)try{e=(await import("@stacksjs/config").catch(()=>null))?.config?.app?.key}catch{}if(!e)return null;return ae=rr("sha256").update(e).digest(),ae}function Q(e){return typeof e==="string"&&e.startsWith(bt)}async function Me(e){if(e==null)return e;if(Q(e))return e;if(typeof e!=="string")return e;let n=await kt();if(!n)return se.warn("[orm] encrypted attribute: APP_KEY not set - storing value in plaintext"),e;let t=or(ir),r=tr(ht,n,t),o=Buffer.concat([r.update(e,"utf8"),r.final()]),i=r.getAuthTag();return`${bt}${t.toString("base64")}:${i.toString("base64")}:${o.toString("base64")}`}async function Oe(e){if(e==null)return e;if(typeof e!=="string")return e;if(!Q(e))return e;try{let n=await kt();if(!n)return se.warn("[orm] encrypted attribute: APP_KEY not set - cannot decrypt"),null;let[,t,r,o]=e.split(":");if(!t||!r||!o)return se.warn("[orm] encrypted attribute: malformed envelope, returning null"),null;let i=Buffer.from(t,"base64"),a=Buffer.from(r,"base64"),s=Buffer.from(o,"base64"),u=nr(ht,n,i);return u.setAuthTag(a),Buffer.concat([u.update(s),u.final()]).toString("utf8")}catch(n){return se.warn("[orm] encrypted attribute: decrypt failed (key rotation? corrupted ciphertext?)",{error:n}),null}}function De(e){let n=e.attributes;if(!n||typeof n!=="object")return[];let t=[];for(let[r,o]of Object.entries(n))if(o&&typeof o==="object"&&o.encrypted===!0)t.push(r);return t}import{sqlDateTime as ar}from"@stacksjs/database/runtime";import{log as q}from"@stacksjs/logging";var sr=[/^password$/i,/^password_hash$/i,/^api_key$/i,/_token$/i,/_secret$/i,/^remember_token$/i],Rt="model_audits",Ee=null;function ur(e){Ee=e}async function ue(){if(Ee!=null)return Ee;try{let e=await import("@stacksjs/router").catch(()=>null);if(!e)return null;let n=e.getCurrentRequest;if(typeof n!=="function")return null;let t=n();if(!t)return null;return(t.user??t._user)?.id??null}catch{return null}}function z(e){if(!e||typeof e!=="object")return null;let n={};for(let[t,r]of Object.entries(e)){if(sr.some((o)=>o.test(t)))continue;n[t]=r}return n}function L(e){if(!e||typeof e!=="object")return null;let n=e;if(n._attributes&&typeof n._attributes==="object")return{...n._attributes};return{...e}}function cr(e,n){if(!e||!n)return{old:e,next:n};let t={},r={},o=new Set([...Object.keys(e),...Object.keys(n)]);for(let i of o)if(e[i]!==n[i])t[i]=e[i],r[i]=n[i];return{old:t,next:r}}async function ce(e,n=!1){try{let{db:t}=await import("@stacksjs/database/runtime");await t.insertInto(Rt).values({auditable_type:e.auditable_type,auditable_id:e.auditable_id,event:e.event,old_values:e.old_values?JSON.stringify(e.old_values):null,new_values:e.new_values?JSON.stringify(e.new_values):null,user_id:e.user_id,created_at:ar()}).executeTakeFirst()}catch(t){if(q.warn(`[orm] audit row write failed for ${e.auditable_type}#${String(e.auditable_id)} (${e.event})`,{error:t}),n)throw t}}function St(e){return{async audits(n){try{let{db:t}=await import("@stacksjs/database/runtime");return(await t.selectFrom(Rt).selectAll().where("auditable_type","=",e).where("auditable_id","=",n).orderBy("created_at","desc").execute()??[]).map((o)=>({...o,old_values:typeof o.old_values==="string"?Tt(o.old_values):o.old_values,new_values:typeof o.new_values==="string"?Tt(o.new_values):o.new_values}))}catch(t){return q.warn(`[orm] audits() lookup failed for ${e}#${String(n)}`,{error:t}),[]}}}}function Tt(e){try{return JSON.parse(e)}catch{return e}}function _t(e){if(e&&typeof e==="object"&&"transactional"in e)return{transactional:e.transactional===!0};return{transactional:!1}}function At(e,n,t="id",r={}){let o=r.transactional===!0,i=e;if(typeof e.audits!=="function")e.audits=St(n).audits;let a=async(f)=>{if(!o)return await f();let{db:d}=await import("@stacksjs/database/runtime");return await d.transaction(async()=>f())},s=e.create;if(typeof s==="function")e.create=async function(...f){return await a(async()=>{let d=await s.apply(this,f);try{let p=L(d),m=p?.[t];if(m!=null){let g=await ue();await ce({auditable_type:n,auditable_id:m,event:"created",old_values:null,new_values:z(p),user_id:g},o)}}catch(p){if(q.warn(`[orm] audit(create) failed for ${n}`,{error:p}),o)throw p}return d})};let u=e.createMany;if(typeof u==="function")e.createMany=async function(...f){return await a(async()=>{let d=await u.apply(this,f);try{let p=Array.isArray(d)&&d.length?await ue():null;for(let m of Array.isArray(d)?d:[]){let g=L(m),w=g?.[t];if(w==null)continue;await ce({auditable_type:n,auditable_id:w,event:"created",old_values:null,new_values:z(g),user_id:p},o)}}catch(p){if(q.warn(`[orm] audit(createMany) failed for ${n}`,{error:p}),o)throw p}return d})};let c=e.update;if(typeof c==="function")e.update=async function(f,d){return await a(async()=>{let p=i.find,m=typeof p==="function"?L(await p.call(i,f)):null,g=await c.call(this,f,d);try{let w=L(g)??(typeof p==="function"?L(await p.call(i,f)):null),{old:h,next:b}=cr(m,w);if(b&&Object.keys(b).length>0){let k=await ue();await ce({auditable_type:n,auditable_id:f,event:"updated",old_values:z(h),new_values:z(b),user_id:k},o)}}catch(w){if(q.warn(`[orm] audit(update) failed for ${n}#${String(f)}`,{error:w}),o)throw w}return g})};let l=(f)=>{let d=e[f];if(typeof d!=="function")return;e[f]=async function(p){return await a(async()=>{let m=i.find,g=typeof m==="function"?L(await m.call(i,p)):null,w=await d.call(this,p);try{if(w!==!1&&g){let h=await ue();await ce({auditable_type:n,auditable_id:p,event:"deleted",old_values:z(g),new_values:null,user_id:h},o)}}catch(h){if(q.warn(`[orm] audit(${f}) failed for ${n}#${String(p)}`,{error:h}),o)throw h}return w})}};l("delete"),l("softDelete")}import{db as lr,sql as dr,sqlDateTime as je}from"@stacksjs/database/runtime";function v(e,n){if(typeof e!=="number"||!Number.isFinite(e)||e<=0)throw Error(`[orm/commentable] ${n} requires a positive numeric id (received ${String(e)})`)}var H="commentable_upvotes",J="commentables";function fr(e){let n=e;return n.code==="SQLITE_CONSTRAINT_UNIQUE"||n.code==="SQLITE_CONSTRAINT"||n.code==="23505"||n.errno===1062||/unique|duplicate/i.test(n.message??"")}var Pt=["pending","approved"];function Fe(e){let n=lr;return{async comments(t){return v(t,"comments"),await n.selectFrom("commentables").where("commentables_id","=",t).where("commentables_type","=",e).selectAll().orderBy("id","asc").execute()},async commentCount(t){let r=await n.selectFrom("commentables").select(dr`count(*) as count`).where("commentables_id","=",t).where("commentables_type","=",e).executeTakeFirst();return Number(r?.count)||0},async addComment(t,r,o={}){if(v(t,"addComment"),!r||typeof r.body!=="string"||r.body.trim().length===0)throw Error("[orm/commentable] addComment requires a non-empty comment.body");if(r.title!=null&&typeof r.title!=="string")throw Error("[orm/commentable] addComment requires comment.title to be a string when given");let i=o.status??"pending";if(!Pt.includes(i))throw Error(`[orm/commentable] addComment status must be one of ${Pt.join(", ")} (received ${String(i)})`);let a={title:r.title?.trim()??"",body:r.body,commentables_id:t,commentables_type:e,status:i,approved_at:i==="approved"?Date.now():null,created_at:je(),updated_at:je()};for(let c of["author_name","author_email","user_id"])if(r[c]!=null)a[c]=r[c];let s=await n.insertInto("commentables").values(a).returningAll().executeTakeFirst();if(s&&typeof s==="object"&&"id"in s)return s;let u=s?.lastInsertRowid;if(u==null)return s;return await n.selectFrom("commentables").where("id","=",Number(u)).selectAll().executeTakeFirst()},async approvedComments(t){return await n.selectFrom("commentables").where("commentables_id","=",t).where("commentables_type","=",e).where("status","=","approved").selectAll().orderBy("id","asc").execute()},async pendingComments(t){return await n.selectFrom("commentables").where("commentables_id","=",t).where("commentables_type","=",e).where("status","=","pending").selectAll().orderBy("id","asc").execute()},async rejectedComments(t){return await n.selectFrom("commentables").where("commentables_id","=",t).where("commentables_type","=",e).where("status","=","rejected").selectAll().orderBy("id","asc").execute()},async upvoteComment(t,r){v(t,"upvoteComment"),v(r,"upvoteComment");let o=()=>n.selectFrom(H).where("upvoteable_id","=",t).where("upvoteable_type","=",J).where("user_id","=",r).selectAll().executeTakeFirst(),i=await o();if(i)return i;try{await n.insertInto(H).values({upvoteable_id:t,upvoteable_type:J,user_id:r,created_at:je()}).execute()}catch(a){if(!fr(a))throw a}return await o()},async removeCommentUpvote(t,r){v(t,"removeCommentUpvote"),v(r,"removeCommentUpvote"),await n.deleteFrom(H).where("upvoteable_id","=",t).where("upvoteable_type","=",J).where("user_id","=",r).execute()},async commentUpvoteCount(t){v(t,"commentUpvoteCount");let r=await n.selectFrom(H).select("count(*) as count").where("upvoteable_id","=",t).where("upvoteable_type","=",J).executeTakeFirst();return Number(r?.count)||0},async hasUpvotedComment(t,r){return v(t,"hasUpvotedComment"),v(r,"hasUpvotedComment"),!!await n.selectFrom(H).where("upvoteable_id","=",t).where("upvoteable_type","=",J).where("user_id","=",r).selectAll().executeTakeFirst()}}}import{db as pr,sql as mr,sqlDateTime as xt}from"@stacksjs/database/runtime";function $e(e,n){if(typeof e!=="number"||!Number.isFinite(e)||e<=0)throw Error(`[orm/taggable] ${n} requires a positive numeric id (received ${String(e)})`)}function Ie(e){let n=pr;return{async tags(t){return $e(t,"tags"),await n.selectFrom("taggables").where("taggable_id","=",t).where("taggable_type","=",e).selectAll().execute()},async tagCount(t){$e(t,"tagCount");let r=await n.selectFrom("taggables").select(mr`count(*) as count`).where("taggable_id","=",t).where("taggable_type","=",e).executeTakeFirst();return Number(r?.count)||0},async addTag(t,r){if($e(t,"addTag"),!r||typeof r.name!=="string"||r.name.trim().length===0)throw Error("[orm/taggable] addTag requires a non-empty tag.name");return await n.insertInto("taggables").values({...r,taggable_id:t,taggable_type:e,slug:r.name.toLowerCase().replace(/[^a-z0-9]+/g,"-"),is_active:!0,created_at:xt(),updated_at:xt()}).execute(),await n.selectFrom("taggables").where("taggable_id","=",t).where("taggable_type","=",e).where("name","=",r.name).selectAll().executeTakeFirst()},async activeTags(t){return await n.selectFrom("taggables").where("taggable_id","=",t).where("taggable_type","=",e).where("is_active","=",!0).selectAll().execute()},async inactiveTags(t){return await n.selectFrom("taggables").where("taggable_id","=",t).where("taggable_type","=",e).where("is_active","=",!1).selectAll().execute()},async removeTag(t,r){await n.deleteFrom("taggables").where("taggable_id","=",t).where("taggable_type","=",e).where("id","=",r).execute()}}}import{db as gr,sqlDateTime as le}from"@stacksjs/database/runtime";function Be(e){let n=gr;async function t(r){return(await n.selectFrom("categorizable_models").where("categorizable_id","=",r).where("categorizable_type","=",e).selectAll().execute()).map((i)=>i.category_id)}return{async categories(r){let o=await t(r);if(o.length===0)return[];return await n.selectFrom("categorizables").where("id","in",o).selectAll().execute()},async categoryCount(r){return(await t(r)).length},async addCategory(r,o){let i=()=>n.selectFrom("categorizables").where("name","=",o.name).where("categorizable_type","=",e).selectAll().executeTakeFirst(),a=await i();if(!a)await n.insertInto("categorizables").values({name:o.name,description:o.description,slug:o.name.toLowerCase().replace(/[^a-z0-9]+/g,"-"),categorizable_type:e,is_active:!0,created_at:le(),updated_at:le()}).execute(),a=await i();return await n.insertInto("categorizable_models").values({categorizable_id:r,categorizable_type:e,category_id:a?.id,created_at:le(),updated_at:le()}).execute(),a},async activeCategories(r){let o=await t(r);if(o.length===0)return[];return await n.selectFrom("categorizables").where("id","in",o).where("is_active","=",!0).selectAll().execute()},async inactiveCategories(r){let o=await t(r);if(o.length===0)return[];return await n.selectFrom("categorizables").where("id","in",o).where("is_active","=",!1).selectAll().execute()},async removeCategory(r,o){await n.deleteFrom("categorizable_models").where("categorizable_id","=",r).where("categorizable_type","=",e).where("category_id","=",o).execute()}}}import{db as yr,sqlDateTime as wr}from"@stacksjs/database/runtime";function Ne(e,n){let t=yr,r=n?.table||`${e}_likes`,o=n?.foreignKey||`${e.replace(/s$/,"")}_id`;return{async likes(i){return await t.selectFrom(r).where(o,"=",i).selectAll().execute()},async likeCount(i){let a=await t.selectFrom(r).select("count(*) as count").where(o,"=",i).executeTakeFirst();return Number(a?.count)||0},async like(i,a){if(typeof i!=="number"||!Number.isFinite(i)||i<=0)throw Error(`[orm/likeable] like requires a positive numeric id (received ${String(i)})`);if(typeof a!=="number"||!Number.isFinite(a)||a<=0)throw Error(`[orm/likeable] like requires a positive numeric userId (received ${String(a)})`);let s=wr();try{return await t.insertInto(r).values({[o]:i,user_id:a,created_at:s,updated_at:s}).returningAll().executeTakeFirst()}catch(u){let c=u;if(!(c.code==="SQLITE_CONSTRAINT_UNIQUE"||c.code==="SQLITE_CONSTRAINT"||c.code==="23505"||c.errno===1062||/unique|duplicate/i.test(c.message??"")))throw u;let f=await t.selectFrom(r).where(o,"=",i).where("user_id","=",a).selectAll().executeTakeFirst();if(f)return f;throw u}},async unlike(i,a){await t.deleteFrom(r).where(o,"=",i).where("user_id","=",a).execute()},async isLiked(i,a){return!!await t.selectFrom(r).where(o,"=",i).where("user_id","=",a).selectAll().executeTakeFirst()},async likedBy(i){return(await t.selectFrom(r).select([o]).where("user_id","=",i).execute()).map((s)=>Number(s[o])).filter(Boolean)}}}import{createRequire as br}from"module";import{db as hr}from"@stacksjs/database/runtime";var kr=br(import.meta.url);class Le extends Error{constructor(e){super(`No subscription ${e} belongs to this user`);this.name="SubscriptionNotOwnedError"}}async function M(){let{paymentDriver:e}=await import("@stacksjs/payments");return e()}async function S(e){let{assertStripeDriver:n}=await import("@stacksjs/payments");n(e)}function Ct(e){let n=hr;return{async paymentCustomer(t){return(await M()).customer(t)},async charge(t,r,o,i={}){return(await M()).charge(t,r,o,i)},async createPayment(t,r,o={}){return(await M()).createPayment(t,r,o)},async checkout(t,r){return(await M()).checkout(t,r)},async paymentMethods(t){return(await M()).paymentMethods(t)},async removePaymentMethod(t,r){return(await M()).removePaymentMethod(t,r)},async newSubscription(t,r,o){return(await M()).subscribe(t,o,{type:r})},async cancelSubscription(t,r,o={}){if(!await n.selectFrom("subscriptions").where("provider_id","=",r).where("user_id","=",t.id).select(["id"]).executeTakeFirst())throw new Le(r);return(await M()).cancelSubscription(r,o)},async activeSubscription(t){let r=await n.selectFrom("subscriptions").where("user_id","=",t.id).where("provider_status","=","active").selectAll().executeTakeFirst();if(!r)return;let o=(await(await M()).subscriptions(t)).find((i)=>i.id===r.provider_id);return o?{subscription:r,providerSubscription:o}:void 0},async syncStripeCustomerDetails(t,r){await S("syncStripeCustomerDetails");let{manageCustomer:o}=await import("@stacksjs/payments");return await o.syncStripeCustomerDetails(t,r)},async createStripeUser(t,r){await S("createStripeUser");let{manageCustomer:o}=await import("@stacksjs/payments");return await o.createStripeCustomer(t,r)},async updateStripeUser(t,r){await S("updateStripeUser");let{manageCustomer:o}=await import("@stacksjs/payments");return await o.updateStripeCustomer(t,r)},async deleteStripeUser(t){await S("deleteStripeUser");let{manageCustomer:r}=await import("@stacksjs/payments");return await r.deleteStripeUser(t)},async createOrGetStripeUser(t,r){await S("createOrGetStripeUser");let{manageCustomer:o}=await import("@stacksjs/payments");return await o.createOrGetStripeUser(t,r)},async retrieveStripeUser(t){await S("retrieveStripeUser");let{manageCustomer:r}=await import("@stacksjs/payments");return await r.retrieveStripeUser(t)},async defaultPaymentMethod(t){let{managePaymentMethod:r}=await import("@stacksjs/payments");return await r.retrieveDefaultPaymentMethod(t)},async setDefaultPaymentMethod(t,r){await S("setDefaultPaymentMethod");let{managePaymentMethod:o}=await import("@stacksjs/payments");if(typeof r==="string")await o.setUserDefaultPayment(t,r);else await o.setDefaultPaymentMethod(t,r)},async addPaymentMethod(t,r){await S("addPaymentMethod");let{managePaymentMethod:o,toStoredPaymentMethod:i}=await import("@stacksjs/payments");return i(await o.addPaymentMethod(t,r))},async updateSubscription(t,r,o){await S("updateSubscription");let{manageSubscription:i,summarizeSubscription:a}=await import("@stacksjs/payments");return a(await i.update(t,r,o,{}))},async createSetupIntent(t,r={}){await S("createSetupIntent");let{manageSetupIntent:o}=await import("@stacksjs/payments"),i=await o.create(t,r);if(!i.client_secret)throw Error("Stripe returned a SetupIntent without a client secret.");return{id:i.id,clientConfirmation:{provider:"stripe",clientSecret:i.client_secret}}},async storeTransaction(t,r,o){let{manageTransaction:i}=await import("@stacksjs/payments");return await i.store(t,r,o)},async subscriptionHistory(t){await S("subscriptionHistory");let{manageInvoice:r}=await import("@stacksjs/payments");return await r.list(t)},async transactionHistory(t){let{manageTransaction:r}=await import("@stacksjs/payments");return await r.list(t)},async connectAccount(t,r={}){await S("Stripe Connect (connectAccount)");let o=r.accountColumn||"stripe_account_id",i=(t._attributes??t)[o];if(!i)return null;let a=await Y();try{return await a.accounts.retrieve(i)}catch{return null}},async createConnectAccount(t,r={}){await S("Stripe Connect (createConnectAccount)");let o=r.accountColumn||"stripe_account_id",i=t._attributes??t,a=i[o],s=await Y();if(!a){let{stacksIdempotencyKey:u}=await import("@stacksjs/payments"),c=r.modelTable||e,l=await s.accounts.create({type:r.type??"express",email:r.email??i.email,country:r.country??"US",capabilities:r.capabilities??{card_payments:{requested:!0},transfers:{requested:!0}}},{idempotencyKey:u("connect.account.create",c,i.id)});return a=l.id,await n.updateTable(c).set({[o]:a}).where("id","=",Number(i.id)).execute(),l}return await s.accounts.retrieve(a)},async connectOnboardLink(t,r){await S("Stripe Connect (connectOnboardLink)");let o=r.accountColumn||"stripe_account_id",a=(t._attributes??t)[o];if(!a)throw Error("connectOnboardLink: model has no Stripe Connect account; call createConnectAccount first");return{url:(await(await Y()).accountLinks.create({account:a,refresh_url:r.refreshUrl,return_url:r.returnUrl,type:r.type??"account_onboarding"})).url,accountId:a}},async syncConnectStatus(t,r={}){await S("Stripe Connect (syncConnectStatus)");let o=r.accountColumn||"stripe_account_id",i=r.chargesColumn||"charges_enabled",a=r.payoutsColumn||"payouts_enabled",s=t._attributes??t,u=s[o];if(!u)return{chargesEnabled:!1,payoutsEnabled:!1};let l=await(await Y()).accounts.retrieve(u),f=!!l.charges_enabled,d=!!l.payouts_enabled,p=r.modelTable||e;return await n.updateTable(p).set({[i]:f,[a]:d}).where("id","=",Number(s.id)).execute(),{chargesEnabled:f,payoutsEnabled:d}},async chargeWithSplit(t,r){await S("Stripe Connect (chargeWithSplit)");let o=await Y(),i=r.accountColumn||"stripe_account_id",a=t._attributes??t,s=r.connectAccountId||a[i],u={amount:r.amountCents,currency:r.currency||"usd",automatic_payment_methods:{enabled:!0},metadata:r.metadata};if(s){if(u.transfer_data={destination:s},r.platformFeeCents)u.application_fee_amount=r.platformFeeCents}let{freshIdempotencyKey:c}=await import("@stacksjs/payments");return await o.paymentIntents.create(u,{idempotencyKey:c("payment_intent.create",a.id,r.amountCents)})}}}var Tr={syncStripeCustomerDetails:!0,createStripeUser:!0,updateStripeUser:!0,deleteStripeUser:!0,createOrGetStripeUser:!0,retrieveStripeUser:!0,defaultPaymentMethod:!0,setDefaultPaymentMethod:!0,removePaymentMethod:!0,addPaymentMethod:!0,paymentMethods:!0,paymentCustomer:!0,charge:!0,newSubscription:!0,updateSubscription:!0,cancelSubscription:!0,activeSubscription:!0,checkout:!0,createSetupIntent:!0,createPayment:!0,storeTransaction:!0,subscriptionHistory:!0,transactionHistory:!0,connectAccount:!0,createConnectAccount:!0,connectOnboardLink:!0,syncConnectStatus:!0,chargeWithSplit:!0},de=Object.freeze(Object.keys(Tr));function Rr(e){return de.every((n)=>typeof Reflect.get(e,n)==="function")}function Y(){let e=globalThis.process?.env?.STRIPE_SECRET_KEY;if(!e)throw Error("Stripe Connect: STRIPE_SECRET_KEY not configured");let n;try{n=kr("stripe")}catch{throw Error("Stripe Connect is being used but the `stripe` package is not installed. It is an opt-in dependency - run `bun add stripe` to enable Stripe Connect.")}return new n(e,{apiVersion:n.API_VERSION})}import{isUniqueViolation as Ur}from"@stacksjs/error-handling";import{isUniqueViolation as Sr}from"@stacksjs/error-handling";function _r(e,n,t){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(Sr(e))return{status:409,body:{error:`${n} already exists`}};return{status:500,body:{error:`Failed to ${t} ${n}`,detail:String(e)}}}function x(e){let n=!1;for(let r=0;r<e.length;r++){let o=e.charCodeAt(r);if(o>127)return e.replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/([A-Z])([A-Z][a-z])/g,"$1_$2").toLowerCase();if(o>=65&&o<=90)n=!0}if(!n)return e;let t="";for(let r=0;r<e.length;r++){let o=e.charCodeAt(r);if(o<65||o>90){t+=e[r];continue}let i=r>0?e.charCodeAt(r-1):0,a=r+1<e.length?e.charCodeAt(r+1):0,s=i>=97&&i<=122||i>=48&&i<=57,u=i>=65&&i<=90&&a>=97&&a<=122;if(r>0&&(s||u))t+="_";t+=String.fromCharCode(o+32)}return t}function Ar(e){let n={};for(let[t,r]of Object.entries(e))n[x(t)]=r;return n}function hu(e,n){let t=String(n||"").replace(/^\/+|\/+$/g,""),r=String(e).replace(/^\/+/,"");return`/api/${t?`${t}/`:""}${r}`}function jt(e){if(!e)return null;let n=e.attributes??{};if(Object.prototype.hasOwnProperty.call(n,"teamId")||Object.prototype.hasOwnProperty.call(n,"team_id"))return"team_id";return e.belongsTo?.some((t)=>t==="Team")?"team_id":null}function Ft(e){if(!e)return null;let n=e.attributes??{};if(Object.prototype.hasOwnProperty.call(n,"userId")||Object.prototype.hasOwnProperty.call(n,"user_id"))return"user_id";return e.belongsTo?.some((t)=>t==="User")?"user_id":null}function ku(e){return e?.ownership===!1}function Tu(e,n,t){let r=Object.keys(e).find((i)=>x(i)===x(n));if(Array.isArray(t)){if(r===void 0)return{data:e,error:"Ownership value is required"};if(!t.some((i)=>String(i)===String(e[r])))return{data:e,error:"Ownership value is not available to this caller"};return{data:{...e,[n]:e[r]}}}if(t===null||t===void 0)return{data:e,error:"Caller has no ownership identity"};let o={...e};for(let i of Object.keys(o))if(x(i)===x(n))delete o[i];return o[n]=t,{data:o}}function Pr(e){if(!e)return[];let n=Object.entries(e.attributes??{}).filter(([,t])=>t?.fillable===!0).map(([t])=>t);for(let t of e.belongsTo??[]){if(typeof t!=="string"||!t.trim())continue;let r=x(t.trim()).split("_").filter(Boolean);if(r.length===0)continue;let o=`${r[0]}${r.slice(1).map((i)=>`${i[0]?.toUpperCase()}${i.slice(1)}`).join("")}Id`;n.push(o)}return[...new Set(n)]}function xr(e,n){if(!e||n.length===0)return{};let t={},r;for(let o of n){if(o in e){t[o]=e[o];continue}r??=vr(n);let i=r.get(o);if(i!==o&&i in e)t[o]=e[i]}return t}function Cr(e,n){if(e?.name!=="date"||n instanceof Date||typeof n!=="string")return n;let t=/^(\d{4})-(\d{2})-(\d{2})$/.exec(n);if(!t)return n;let r=Number(t[1]),o=Number(t[2]),i=Number(t[3]),a=new Date(Date.UTC(r,o-1,i));if(a.getUTCFullYear()!==r||a.getUTCMonth()!==o-1||a.getUTCDate()!==i)return n;return a}var vt=new WeakMap,Mt=new WeakMap;function qe(e){let n=vt.get(e);if(n&&n.length===e.length){let r=!0;for(let o=0;o<e.length;o++)if(n[o]?.field!==e[o]){r=!1;break}if(r)return n}let t=e.map((r)=>({field:r,snake:x(r)}));return vt.set(e,t),t}function vr(e){let n=qe(e),t=Mt.get(n);if(t)return t;let r=new Map(n.map(({field:o,snake:i})=>[o,i]));return Mt.set(n,r),r}function Ru(e,n){if(!n.length)return e;let t={...e};for(let{field:r,snake:o}of qe(n))if(delete t[r],o!==r)delete t[o];return t}function Su(e,n){if(!e||n.length===0)return e;let t={...e};for(let{field:r,snake:o}of qe(n))if(delete t[r],o!==r)delete t[o];return t}var Mr=["id","uuid","created_at","updated_at","deleted_at"];function _u(e,n){let t=new Map;for(let r of[...Object.keys(e??{}),...Mr]){let o=x(r);if(!/^\w+$/.test(o))continue;t.set(r,o),t.set(o,o)}for(let r of n)t.delete(r),t.delete(x(r));return t}function Au(e,n,t){if(!n)return e;let r=e;for(let o of String(n).split(",")){let i=o.trim();if(!i)continue;let a=i.startsWith("-"),s=a?i.slice(1):i;if(!/^\w+$/.test(s))continue;let u=t.get(s);if(!u)continue;r=r.orderBy(u,a?"desc":"asc")}return r}var Or={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"?Er(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"?jr(e):[],set:(e)=>e==null?null:Array.isArray(e)?JSON.stringify(e):e}},Ot=new WeakMap;function Dr(e,n){let t=Ot.get(e);if(t&&t.length===n.length){let o=!0;for(let i=0;i<n.length;i++){let a=n[i];if(t[i]?.attr!==a||t[i]?.definition!==e[a]){o=!1;break}}if(o)return t}let r=[];for(let o of n){let i=e[o],a=typeof i==="string"?Or[i]:i;r.push({attr:o,snake:x(o),definition:i,caster:a})}return Ot.set(e,r),r}function Er(e){try{return JSON.parse(e)}catch{return e}}function jr(e){try{return JSON.parse(e)}catch{return[]}}function Pu(e,n,t){if(!e||typeof e!=="object"||!n)return e;let r=Object.keys(n);if(r.length===0)return e;let o=Dr(n,r);if(o.length===0)return e;let i={...e};for(let{attr:a,caster:s,snake:u}of o){if(!s)continue;let c=s[t];if(typeof c!=="function")continue;if(Object.prototype.hasOwnProperty.call(i,a))i[a]=c.call(s,i[a]);if(u!==a&&Object.prototype.hasOwnProperty.call(i,u))i[u]=c.call(s,i[u])}return i}var Dt=new WeakMap;function Fr(e){let n=Dt.get(e);if(n)return n;let t=[];for(let[r,o]of Object.entries(e)){let i=o?.validation?.rule;if(!i||typeof i.validate!=="function")continue;t.push({definition:o,field:r,hasDefault:o!==null&&typeof o==="object"&&Object.prototype.hasOwnProperty.call(o,"default"),rule:i})}return Dt.set(e,t),t}function $t(e){let n=e?.attributes;if(!n||typeof n!=="object")return!1;for(let t of Object.values(n)){let r=t?.validation?.rule;if(r&&typeof r.validate==="function")return!0}return!1}function It(e,n,t){let r=n?.attributes;if(!r||typeof r!=="object")return{valid:!0};let o=Fr(r);if(o.length===0)return{valid:!0};let i={},a=!1;for(let s of o){let{definition:u,field:c,hasDefault:l,rule:f}=s,d=Object.prototype.hasOwnProperty.call(e,c);if(!d&&t==="updating")continue;let p=d?e[c]:l?u.default:void 0,m=Cr(f,p),g=f.validate(m);if(!g?.valid&&Array.isArray(g?.errors)&&g.errors.length>0)a=!0,i[c]=g.errors.map((w)=>u.validation?.message?.[w?.code]??w?.message??"invalid")}return a?{valid:!1,errors:i}:{valid:!0}}function $r(e,n){return`${e}\x00${Ir(n)}`}function xu(e){let n=new Map;for(let t of e){let r=$r(String(t.method??""),String(t.path??""));if(!n.has(r))n.set(r,t)}return n}function Ir(e){return e.replace(/\{[^}]*\}/g,"{}").replace(/:[^/]+/g,"{}")}function pe(e){if(Array.isArray(e))return e.filter((n)=>typeof n==="string"&&n.length>0);return typeof e==="string"&&e?[e]:[]}function Br(e,n){let t=typeof e==="object"&&e!==null&&"middleware"in e,r=e?.middleware,o=Bt(n);if(!t)return{read:F(["auth"],o),write:F(["auth"],o),declared:!1};if(r&&typeof r==="object"&&!Array.isArray(r)){let a=r;return{read:F("read"in a?pe(a.read):["auth"],o),write:F("write"in a?pe(a.write):["auth"],o),declared:!0}}let i=pe(r);return{read:F(i,o),write:F(i,o),declared:!0}}function Bt(e){if(!e||typeof e!=="object")return null;let n=e;if(n.enforce===!1)return null;if(!Array.isArray(n.roles))return null;let t=n.roles.filter((r)=>typeof r==="string").map((r)=>r.trim()).filter((r)=>r.length>0);return t.length>0?`role:${t.join(",")}`:null}var Nr=["index","show","store","update","destroy"],Lr={index:"read",show:"read",store:"write",update:"write",destroy:"write"};function Cu(e,n){let{read:t,write:r,declared:o}=Br(e,n),i=Bt(n),a=e?.middleware,s=a&&typeof a==="object"&&!Array.isArray(a)?a:void 0,u={};for(let c of Nr)u[c]=s&&c in s?F(pe(s[c]),i):Lr[c]==="read"?t:r;return{abilities:u,read:t,write:r,declared:o}}function F(e,n){if(!n||e.length===0)return e;if(e.some((t)=>t==="role"||t.startsWith("role:")))return e;return[...e,n]}function vu(e){if(e.length===0)return null;let n=[...e].sort((t,r)=>t.model.localeCompare(r.model)).map((t)=>`${t.model} (${[...t.abilities].join(", ")})`).join(", ");return`[orm] ${e.length} model(s) role-gate their sidebar row and publish part of the matching API to everyone, because \`useApi.middleware\` declares those abilities empty - ${n}. Drop the empty list to let \`dashboard.roles\` gate them, or set \`dashboard.enforce: false\` to keep the row hidden and the API public.`}async function Mu(e,n,t,r){let o;try{o=await t.gate()}catch{return null}if(!o||!o.hasPolicy(e))return null;try{let i=await t.user(),a=r===void 0?await o.inspectFor(e,n,i):await o.inspectFor(e,n,i,r);if(a&&!a.isAllowed)return{status:403,message:a.message||"This action is unauthorized."};return null}catch{return{status:403,message:"This action is unauthorized."}}}var Et=15,qr=100;function Ou(e){let n=Number.parseInt(e.get("page")||String(1),10),t=Number.isFinite(n)?Math.max(1,n):1,r=Number.parseInt(e.get("per_page")||String(Et),10),o=Math.min(Number.isFinite(r)?Math.max(1,r):Et,qr);return{page:t,perPage:o,offset:(t-1)*o}}function fe(e,n){let t=new URL(e.toString());return t.searchParams.set("page",String(n)),`${t.pathname}${t.search}`}function Gr(e,n,t,r,o,i){let a=(n-1)*t,s=r===0,u={page:n,per_page:t,from:s?null:a+1,to:s?null:a+r,has_more_pages:o,prev_page_url:n>1?fe(e,n-1):null,next_page_url:o?fe(e,n+1):null};if(i!==void 0&&!Number.isNaN(i)){let c=Math.max(1,Math.ceil(i/t));u.total=i,u.last_page=c,u.first_page_url=fe(e,1),u.last_page_url=fe(e,c)}return u}function Du(e,n,t,r,o,i){let{page:a,...s}=Gr(e,n,t,r,o,i);return{current_page:a,...s}}function Eu(e,n){return(n??e??"").toString().trim().toLowerCase()==="warn"?"warn":"deny"}function ju(e,n){if(e.length===0)return null;let t=[...e].sort().join(", ");if(n==="deny")return`[orm] security.api.rowScoping is 'deny': NOT registering store/update/destroy for ${e.length} model(s) `+`with no row-level scoping \u2014 ${t}. 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 `+`${t}. 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.`}function Kr(e){if(e?.ownership===!1)return null;if(e?.ownership)return e.ownership;let n=jt(e);if(n)return{field:n,resolve:async(r,o)=>{let{resolveAuthenticatedTeamId:i}=await import("@stacksjs/auth");return i(Ge(o))}};let t=Ft(e);if(t)return{field:t,resolve:async(r)=>r?.id??null};return null}function Ge(e){let n=e?.headers?.get?.("authorization"),t=n&&/^Bearer\s+/i.test(n)?n.replace(/^Bearer\s+/i,"").trim():null,r=e?.headers?.get?.("cookie")||"";return{bearerToken:()=>t,cookies:{get:(o)=>{for(let i of r.split(";")){let a=i.indexOf("=");if(a===-1)continue;if(i.slice(0,a).trim()===o)return decodeURIComponent(i.slice(a+1).trim())}return null}}}}function Wr(e="customer_id"){return{field:e,resolve:async(n)=>{let t=n?.id;if(t==null)return null;try{let{Customer:r}=await import("@stacksjs/orm");return(await r.where("user_id",t).first())?.id??null}catch{return null}}}}function Vr(e="id"){return{field:e,resolve:async(n)=>n?.id??null}}function Qr(e="site_id"){return{field:e,resolve:async(n,t)=>{try{let[{resolveAuthenticatedTeamId:r},{Site:o}]=await Promise.all([import("@stacksjs/auth"),import("@stacksjs/orm")]),i=await r(Ge(t));if(i==null)return[];return(await o.where("team_id",i).get()??[]).map((s)=>s.id).filter((s)=>s!=null)}catch{return[]}}}}function zr(e="id"){return{field:e,resolve:async(n,t)=>{try{let{resolveAuthenticatedTeamId:r}=await import("@stacksjs/auth");return await r(Ge(t))}catch{return null}}}}function Hr(e,n){return{field:n,resolve:async(t,r)=>{try{let o=await import("@stacksjs/orm"),i=o.models?.[e]??o[e]?.definition??null,a=Kr(i);if(!a?.field||typeof a.resolve!=="function")return[];let s=await a.resolve(t,r);if(s==null||Array.isArray(s)&&s.length===0)return[];let u=o[e];if(!u)return[];return((Array.isArray(s)?await u.whereIn(a.field,s).get():await u.where(a.field,s).get())??[]).map((l)=>l.id).filter((l)=>l!=null)}catch{return[]}}}}import{getCurrentRequest as Jr}from"@stacksjs/router";var Nt=new WeakMap;function Lt(e){let n=new Map;for(let t of e){let r=t?.id;if(r!==void 0)n.set(r,t)}return n}async function Yr(e,n){if(typeof e.find==="function")return e.find(n);let t=await e.findMany?.([n]);return Lt(t??[]).get(n)}async function Xr(e,n,t){n.pending=void 0;try{let r=typeof e.findMany==="function"?await e.findMany(t.keys):await Promise.all(t.keys.map((i)=>e.find?.(i))),o=Lt(r??[]);for(let i of t.resolvers)i.resolve(o.get(i.key))}catch(r){for(let o of t.resolvers)o.reject(r)}}function Lu(e,n){let t=Jr();if(!t)return Yr(e,n);let r=Nt.get(t);if(!r)r=new WeakMap,Nt.set(t,r);let o=r.get(e);if(!o)o={cache:new Map},r.set(e,o);let i=o.cache.get(n);if(i)return i.then();let a=o.pending;if(!a){a={keys:[],resolvers:[]},o.pending=a;let c=a,l=o;queueMicrotask(()=>{Xr(e,l,c)})}let s=new Promise((c,l)=>{a.keys.push(n),a.resolvers.push({key:n,resolve:c,reject:l})});o.cache.set(n,s);let u=o.cache;return s.catch(()=>u.delete(n)),s.then()}import{db as Ku}from"@stacksjs/database/runtime";class Zr{conditions=[];where(e,...n){let[t,r]=n,o=r===void 0?"=":t,i=r===void 0?t:r;this.addCondition("and","where",e,o,i)}orWhere(e,...n){let[t,r]=n,o=r===void 0?"=":t,i=r===void 0?t:r;this.addCondition("or","where",e,o,i)}whereIn(e,n){this.conditions.push({type:"and",method:"whereIn",column:e,values:n})}whereNotIn(e,n){this.conditions.push({type:"and",method:"whereIn",column:e,values:n,operator:"not in"})}whereNull(e){this.conditions.push({type:"and",method:"whereNull",column:e})}whereNotNull(e){this.conditions.push({type:"and",method:"whereNotNull",column:e})}whereBetween(e,n){this.conditions.push({type:"and",method:"whereBetween",column:e,range:n})}whereExists(e){this.conditions.push({type:"and",method:"whereExists",column:"",callback:e})}addCondition(e,n,t,r,o){this.conditions.push({type:e,method:n,column:t,operator:r,value:o})}getConditions(){return this.conditions}}import{db as Ue}from"@stacksjs/database/runtime";async function Ke(e,n){return await Ue.transaction(e,n)}async function Qu(e){return await Ue.savepoint(e)}function zu(e,n){return Ue.transactional(e,n)}import{randomUUID as lo}from"crypto";import{db as C,getDatabaseDialect as fo,parseSqlDateTime as po,sqlDateTime as Xt}from"@stacksjs/database/runtime";import{plural as eo,snakeCase as X}from"@stacksjs/strings";var qt=new Set(["anonymize","delete","keep"]),Gt=new Set(["anonymize","delete"]),Ut=new Set(["consent","contract","legal_obligation","vital_interests","public_task","legitimate_interests"]),D="User";class We extends Error{problems;constructor(e){super(`GDPR declarations cannot be honoured:
3
- ${e.map((n)=>` - ${n.model}: ${n.message}`).join(`
4
- `)}`);this.name="GdprDeclarationError",this.problems=e}}function to(e){return(Array.isArray(e)?e.map((t)=>[t.name??"",t]):Object.entries(e)).map(([t,r])=>({name:String(r?.name??t),definition:r})).filter((t)=>t.name&&t.definition&&typeof t.definition==="object").sort((t,r)=>t.name.localeCompare(r.name))}function Kt(e,n){return n.table??X(eo(e))}function no(e){let n=e.belongsTo,t=Array.isArray(n)?n:n&&typeof n==="object"?Object.values(n):[],r=[];for(let o of t){if(typeof o==="string"){r.push({model:o,foreignKey:`${X(o)}_id`});continue}if(o&&typeof o==="object"&&typeof o.model==="string"){let i=o;r.push({model:i.model,foreignKey:i.foreignKey??`${X(i.model)}_id`})}}return r}function ro(e){if(e===!0)return{};if(e&&typeof e==="object")return e;return null}function oo(e,n){if(n.anonymize!==void 0)return{perRow:!1,value:n.anonymize};if(!(e.required===!0&&e.nullable!==!0))return{perRow:!1,value:null};let r=e.validation?.rule?.name??e.type??"string";if(r==="string"||r==="text")return e.unique?{perRow:!0,value:null}:{perRow:!1,value:"[erased]"};if(e.unique)return{problem:`is a NOT NULL unique ${r} column; declare personal: { anonymize: <value> } or make it nullable`};if(r==="number"||r==="integer"||r==="float"||r==="decimal")return{perRow:!1,value:0};if(r==="boolean")return{perRow:!1,value:!1};if(r==="json")return{perRow:!1,value:"{}"};return{problem:`is a NOT NULL ${r} column with no safe placeholder; declare personal: { anonymize: <value> }`}}function me(e){let n=new Map,t=new Map,r=[],o=[],i=(s,u)=>{o.push({model:s,message:u})};for(let{name:s,definition:u}of to(e)){let c=u.attributes??{},l=u.traits?.gdpr,f=no(u),d=f.find((T)=>T.model===D),p=Object.entries(c).map(([T,P])=>({attribute:T,shape:P,options:ro(P?.personal)})).filter((T)=>T.options!==null);if(!l&&p.length===0){if(d&&s!==D)r.push(s);continue}if(l!==void 0&&(l===null||typeof l!=="object")){i(s,"`traits.gdpr` must be an object");continue}let m=Kt(s,u),g=u.primaryKey??"id",w=null,h,b=l?.subject;if(b===void 0){if(s===D)w={kind:"column",columns:[g],where:{}};else if(d)w={kind:"column",columns:[d.foreignKey],where:{}}}else if(typeof b==="string")w={kind:"column",columns:[b],where:{}};else if(Array.isArray(b))w={kind:"column",columns:[...b].map(String),where:{}};else if(b&&typeof b==="object"&&"column"in b)w={kind:"column",columns:Array.isArray(b.column)?[...b.column].map(String):[String(b.column)],where:{...b.where??{}}};else if(b&&typeof b==="object"&&"via"in b){let T=f.find((P)=>P.model===b.via);if(!T)i(s,`subject { via: '${b.via}' } names a model this one does not declare in belongsTo`);else h=T.model,w={kind:"via",model:T.model,foreignKey:T.foreignKey}}else if(b&&typeof b==="object"&&"email"in b)w={kind:"email",column:String(b.email)};else i(s,"subject must be a column name, a list of columns, { column, where }, { via } or { email }");if(w?.kind==="column"&&w.columns.length===0)i(s,"subject names no column");let k=l?.erasure??"anonymize";if(!qt.has(k))i(s,`erasure must be one of ${[...qt].join(", ")}, got '${String(k)}'`);let R=null;if(l?.retention!==void 0){let T=l.retention,P=T?.action??"delete";if(!T||typeof T!=="object"||!Number.isInteger(T.days)||T.days<=0)i(s,"retention.days must be a positive whole number of days");else if(!Gt.has(P))i(s,`retention.action must be one of ${[...Gt].join(", ")}, got '${String(P)}'`);else R={days:T.days,column:T.column??"created_at",action:P}}if(l?.basis!==void 0&&!Ut.has(l.basis))i(s,`basis must be one of ${[...Ut].join(", ")}, got '${String(l.basis)}'`);let oe=k==="anonymize"&&w!==null||R?.action==="anonymize",V=[];for(let{attribute:T,shape:P,options:Ce}of p){let ie=oo(P,Ce);if("problem"in ie){if(oe)i(s,`personal attribute '${T}' ${ie.problem}`);V.push({attribute:T,column:X(T),export:Ce.export!==!1,perRow:!1,anonymizeTo:null});continue}V.push({attribute:T,column:X(T),export:Ce.export!==!1,perRow:ie.perRow,anonymizeTo:ie.value})}if(w!==null&&k==="anonymize"&&V.length===0)i(s,"declares a subject but no personal attributes, so 'anonymize' would change nothing; mark the personal attributes, or declare erasure 'keep' or 'delete'");if(R?.action==="anonymize"&&V.length===0)i(s,"retention anonymizes, but no attribute is marked personal");if(n.set(s,{model:s,table:m,primaryKey:g,subject:w,personal:V,erasure:k,retention:R,purpose:l?.purpose??null,basis:l?.basis??null,depth:0,exportColumns:[...new Set([g,"uuid","created_at","updated_at"])]}),h)t.set(s,h)}let a=(s,u)=>{let c=t.get(s);if(!c)return 0;if(u.has(s))return null;if(!n.get(c)?.subject)return null;u.add(s);let f=a(c,u);return f===null?null:f+1};for(let s of n.values()){let u=t.get(s.model);if(!u)continue;if(!n.get(u)?.subject){i(s.model,`subject { via: '${u}' } points at a model that declares no subject of its own`);continue}let l=a(s.model,new Set);if(l===null)i(s.model,`subject { via: '${u}' } is part of a cycle`);else s.depth=l}return{models:[...n.values()],unclassified:r.sort(),problems:o}}function ge(e){if(e.problems.length)throw new We(e.problems);return e}var ye="gdpr_requests",ze=500;class we extends Error{constructor(e){super(`No user matches '${String(e)}'.`);this.name="GdprSubjectNotFoundError"}}async function be(e){if(e)return ge(me(e));await Promise.resolve().then(() => Qe());return ge(me(await Ve()))}async function Zt(e=C){let n=String(fo()),t=n==="sqlite"?"SELECT name FROM sqlite_master WHERE type = 'table'":n==="mysql"?"SELECT TABLE_NAME AS name FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE()":n==="postgres"?"SELECT table_name AS name FROM information_schema.tables WHERE table_schema = current_schema()":null;if(!t)return null;let r=await e.unsafe(t).execute();return new Set(r.map((o)=>String(o.name??o.NAME??"").toLowerCase()).filter(Boolean))}var mo=/no such table|does not exist|doesn't exist|unknown table|undefined table|ER_NO_SUCH_TABLE/i;async function he(e,n=C){let t=await Zt(n);if(t)return t.has(e.toLowerCase());try{return await n.selectFrom(e).selectAll().limit(1).execute(),!0}catch(r){if(mo.test(r instanceof Error?r.message:String(r)))return!1;throw r}}function go(e){let n=e.models.find((t)=>t.model===D);return{table:n?.table??"users",primaryKey:n?.primaryKey??"id"}}function yo(e){if(typeof e==="number")return{kind:"id",value:e};let n=String(e).trim();if(/^\d+$/.test(n))return{kind:"id",value:Number(n)};if(n.includes("@"))return{kind:"email",value:n};return{kind:"uuid",value:n}}async function wo(e,n={},t=C){let r=await be(n.models);return Je(r,e,t)}async function Je(e,n,t){let{table:r,primaryKey:o}=go(e),i=yo(n),a;if(i.kind==="id")a=(await t.selectFrom(r).selectAll().where(o,"=",i.value).limit(1).execute())[0];else if(i.kind==="email"){for(let s of new Set([i.value,i.value.toLowerCase()]))if(a=(await t.selectFrom(r).selectAll().where("email","=",s).limit(1).execute())[0],a)break}else a=(await t.selectFrom(r).selectAll().where("uuid","=",i.value).limit(1).execute())[0];if(!a)return null;return{id:a[o],email:typeof a.email==="string"?a.email:null}}function Ye(e,n=ze){let t=[];for(let r=0;r<e.length;r+=n)t.push(e.slice(r,r+n));return t}function bo(e,n){let t=new Map;for(let r of e)t.set(String(r[n]),r);return[...t.values()].sort((r,o)=>String(r[n]).localeCompare(String(o[n]),void 0,{numeric:!0}))}async function Xe(e,n,t,r,o){let i=o.get(t.model);if(i)return i;let a=t.subject,s=[];if(a?.kind==="column")for(let u of a.columns){let c=e.selectFrom(t.table).selectAll().where(u,"=",r.id);for(let[l,f]of Object.entries(a.where))c=c.where(l,"=",f);s.push(...await c.execute())}else if(a?.kind==="email"){if(r.email)for(let u of new Set([r.email,r.email.toLowerCase()]))s.push(...await e.selectFrom(t.table).selectAll().where(a.column,"=",u).execute())}else if(a?.kind==="via"){let u=n.get(a.model),l=(await Xe(e,n,u,r,o)).map((f)=>f[u.primaryKey]).filter((f)=>f!==null&&f!==void 0);for(let f of Ye(l))s.push(...await e.selectFrom(t.table).selectAll().where(a.foreignKey,"in",f).execute())}return s=bo(s,t.primaryKey),o.set(t.model,s),s}function Jt(e){if(typeof e==="bigint")return Number.isSafeInteger(Number(e))?Number(e):e.toString();if(e instanceof Date)return e.toISOString();return e}function ho(e,n){let t={};for(let r of e.exportColumns)if(r in n)t[r]=Jt(n[r]);for(let r of e.personal)if(r.export&&r.column in n)t[r.column]=Jt(n[r.column]);return t}function He(e,n){let t={};for(let r of e.personal)t[r.column]=r.perRow?`erased-${String(n[e.primaryKey])}`:r.anonymizeTo;return t}function ko(e,n){if(e===n)return!0;if(e===null||e===void 0||n===null||n===void 0)return(e===null||e===void 0)&&(n===null||n===void 0);if(typeof n==="boolean")return Number(e)===Number(n);return String(e)===String(n)}function en(e,n){let t=He(e,n);return Object.entries(t).some(([r,o])=>!ko(n[r],o))}async function tn(e,n,t){if(!t.length)return;if(n.personal.some((o)=>o.perRow)){for(let o of t)await e.updateTable(n.table).set(He(n,o)).where(n.primaryKey,"=",o[n.primaryKey]).execute();return}let r=He(n,t[0]);for(let o of Ye(t.map((i)=>i[n.primaryKey])))await e.updateTable(n.table).set(r).where(n.primaryKey,"in",o).execute()}async function nn(e,n,t){for(let r of Ye(t.map((o)=>o[n.primaryKey])))await e.deleteFrom(n.table).where(n.primaryKey,"in",r).execute()}async function Ze(e,n,t,r,o){let i=Xt(new Date);await e.insertInto(ye).values({uuid:lo(),type:n,subject_id:t!==null&&Number.isSafeInteger(Number(t))?Number(t):null,actor:r,status:"completed",summary:JSON.stringify(t!==null&&!Number.isSafeInteger(Number(t))?{subject:String(t),...o}:o),occurred_at:i,created_at:i}).execute()}async function et(){if(!await he(ye))throw Error(`The '${ye}' table does not exist, so this request cannot be recorded. Run \`buddy migrate\` first.`)}async function tt(e){let n=[],t=[],r=await Zt(),o=new Map;for(let i of e){if(!o.has(i.table))o.set(i.table,r?r.has(i.table.toLowerCase()):await he(i.table));if(o.get(i.table))n.push(i);else t.push(i.table)}return{present:n,skipped:[...new Set(t)].sort()}}async function To(e,n={}){let t=await be(n.models),r=await Je(t,e,C);if(!r)throw new we(e);await et();let o=t.models.filter((l)=>l.subject),{present:i}=await tt(o),a=new Map(i.map((l)=>[l.model,l]));for(let l of i)if(l.subject?.kind==="via"&&!a.has(l.subject.model))a.delete(l.model);let s=new Map,u={},c={};for(let l of[...a.values()].sort((f,d)=>f.model.localeCompare(d.model))){let f=await Xe(C,a,l,r,s);if(!f.length)continue;u[l.model]=f.map((d)=>ho(l,d)),c[l.model]={purpose:l.purpose,basis:l.basis,retentionDays:l.retention?.days??null}}return await Ze(C,"access",r.id,n.actor??"system",{models:Object.fromEntries(Object.entries(u).map(([l,f])=>[l,f.length]))}),{subject:{id:r.id},generatedAt:new Date().toISOString(),data:u,processing:c}}function Ro(e){return[...e].sort((n,t)=>{let r=n.model===D?1:0,o=t.model===D?1:0;if(r!==o)return r-o;if(n.depth!==t.depth)return t.depth-n.depth;return n.model.localeCompare(t.model)})}async function So(e,n={}){let t=n.dryRun===!0,r=await be(n.models),o=await Je(r,e,C);if(!o)throw new we(e);if(!t)await et();let i=r.models.filter((d)=>d.subject),{present:a,skipped:s}=await tt(i),u=new Map(a.map((d)=>[d.model,d]));for(let d of a)if(d.subject?.kind==="via"&&!u.has(d.subject.model))u.delete(d.model);let c=async(d)=>{let p=new Map;for(let g of u.values())await Xe(d,u,g,o,p);let m=[];for(let g of Ro([...u.values()])){let w=p.get(g.model)??[];if(g.erasure==="delete"){if(!t)await nn(d,g,w);m.push({model:g.model,table:g.table,action:"delete",matched:w.length,changed:w.length,fields:[]})}else if(g.erasure==="anonymize"){let h=w.filter((b)=>en(g,b));if(!t)await tn(d,g,h);m.push({model:g.model,table:g.table,action:"anonymize",matched:w.length,changed:h.length,fields:g.personal.map((b)=>b.column)})}else m.push({model:g.model,table:g.table,action:"keep",matched:w.length,changed:0,fields:[]})}if(!t)await Ze(d,"erasure",o.id,n.actor??"system",{changes:m.map(({model:g,action:w,matched:h,changed:b})=>({model:g,action:w,matched:h,changed:b})),skipped:s});return m},l=t?await c(C):await Ke(c),f=!1;if(!t&&n.revokeCredentials!==!1)f=await _o(o.id);return{subject:{id:o.id},dryRun:t,changes:l.sort((d,p)=>d.model.localeCompare(p.model)),skipped:s,credentialsRevoked:f}}async function _o(e){let n;try{n=await import("@stacksjs/auth")}catch{return!1}let t=Number(e);if(!Number.isSafeInteger(t))return!1;if(n.revokeAllTokens&&await he("oauth_access_tokens"))await n.revokeAllTokens(t);if(n.sessionDestroyAll)await n.sessionDestroyAll(t);return!0}var Yt=86400000;async function Ao(e={}){let n=e.dryRun===!0,t=e.now??new Date,o=(await be(e.models)).models.filter((c)=>c.retention);if(!o.length)return{dryRun:n,cutoffs:{},changes:[],skipped:[]};if(!n)await et();let{present:i,skipped:a}=await tt(o),s=[],u={};for(let c of i){let l=c.retention,f=new Date(t.getTime()-l.days*Yt),d=Xt(new Date(f.getTime()+Yt));u[c.model]=f.toISOString();let p=[],m;for(;;){let h=C.selectFrom(c.table).selectAll().where(l.column,"<",d);if(m!==void 0)h=h.where(c.primaryKey,">",m);let b=await h.orderBy(c.primaryKey,"asc").limit(ze).execute();if(!b.length)break;for(let k of b){let R=po(k[l.column]);if(R&&R.getTime()<f.getTime())p.push(k)}if(m=b[b.length-1][c.primaryKey],b.length<ze)break}let g=l.action==="delete"?p:p.filter((w)=>en(c,w));if(!n&&g.length)await Ke(async(w)=>{if(l.action==="delete")await nn(w,c,g);else await tn(w,c,g)});s.push({model:c.model,table:c.table,action:l.action,matched:p.length,changed:g.length,fields:l.action==="anonymize"?c.personal.map((w)=>w.column):[]})}if(!n&&s.some((c)=>c.changed>0))await Ze(C,"retention",null,e.actor??"scheduler",{changes:s.map(({model:c,action:l,matched:f,changed:d})=>({model:c,action:l,matched:f,changed:d})),cutoffs:u});return{dryRun:n,cutoffs:u,changes:s.sort((c,l)=>c.model.localeCompare(l.model)),skipped:a}}Qe();function Po(e){let n=e.subject;if(!n)return"none (not reachable by access or erasure)";if(n.kind==="via")return`via ${n.model} (\`${n.foreignKey}\`)`;if(n.kind==="email")return`email address in \`${n.column}\``;let t=n.columns.map((o)=>`\`${o}\``).join(" or "),r=Object.entries(n.where).map(([o,i])=>`${o} = ${String(i)}`).join(", ");return r?`${t} where ${r}`:t}function xo(e){return{entries:e.models.map((t)=>({model:t.model,table:t.table,subject:Po(t),personal:t.personal.map((r)=>r.column),notExported:t.personal.filter((r)=>!r.export).map((r)=>r.column),erasure:t.subject?t.erasure:null,retention:t.retention?`${t.retention.action} after ${t.retention.days} days (\`${t.retention.column}\`)`:null,basis:t.basis,purpose:t.purpose})).sort((t,r)=>t.model.localeCompare(r.model)),unclassified:[...e.unclassified].sort()}}function Z(e){return(e??"-").replaceAll("|","\\|").replaceAll(`
5
- `," ")}function Co(e,n="markdown"){if(n==="json")return`${JSON.stringify(e,null,2)}
6
- `;let t=["# Processing register","","<!-- Generated by `buddy gdpr:register` from the model declarations. Do not edit by hand. -->","","Every model that declares personal data or a `gdpr` trait, what erasure does to its rows, and how long they are kept. Change the model, then regenerate this file.","","| Model | Table | Subject | Personal data | Erasure | Retention | Basis | Purpose |","| --- | --- | --- | --- | --- | --- | --- | --- |"];for(let r of e.entries){let o=r.personal.length?r.personal.map((i)=>r.notExported.includes(i)?`\`${i}\` (not exported)`:`\`${i}\``).join(", "):"-";t.push(`| ${[r.model,`\`${r.table}\``,Z(r.subject),o,Z(r.erasure),Z(r.retention),Z(r.basis),Z(r.purpose)].join(" | ")} |`)}if(t.push(""),t.push("## Unclassified"),t.push(""),e.unclassified.length){t.push("These models belong to a user but declare neither personal attributes nor a `gdpr` trait, so access and erasure do not reach them. Classify each one, even if only as `erasure: 'keep'`."),t.push("");for(let r of e.unclassified)t.push(`- ${r}`)}else t.push("None. Every model that belongs to a user is classified.");return t.push(""),t.join(`
7
- `)}export*from"@stacksjs/model-meta";import{createModel as qo,registerModel as Go}from"@stacksjs/query-builder";import{log as _}from"@stacksjs/logging/runtime";import{snakeCase as ne}from"@stacksjs/strings";import{AsyncLocalStorage as vn}from"async_hooks";import{toCursorPaginator as Uo,toPaginator as Ko,toSimplePaginator as Wo}from"@stacksjs/pagination";function rt(e,n){let t=at(),r=t?nt(t,"per_page"):void 0,o=t?nt(t,"page"):void 0,i=e!==void 0?Math.max(1,Math.floor(e)):Math.min(100,Math.max(1,r??15)),a=Math.max(1,Math.floor(n??o??1));return{perPage:i,page:a}}function ot(e,n){let t=at(),r=t?on(t,"cursor"):void 0,o=t?nt(t,"per_page"):void 0,i=e!==void 0?Math.max(1,Math.floor(e)):Math.min(100,Math.max(1,o??15)),s=rn(n!==void 0?n:r??null);return{perPage:i,cursor:s}}function rn(e){if(e===null||e===void 0)return null;if(Array.isArray(e))return e;if(typeof e==="string"&&e.startsWith("["))try{let n=JSON.parse(e);if(Array.isArray(n))return n}catch{}return e}function it(e){let n=at();if(!n)return e;let t=(()=>{try{return new URL(n.url)}catch{return null}})();if(!t)return e;let r=t.pathname;if(e.path=r,"next_cursor"in e)return e.next_page_url=e.next_cursor!==null?I(t,{cursor:e.next_cursor}):null,e.prev_page_url=e.prev_cursor!==null?I(t,{cursor:e.prev_cursor}):null,e;let o=e.current_page;if(e.prev_page_url=o>1?I(t,{page:o-1}):null,"total"in e){let i=e.last_page;e.next_page_url=o<i?I(t,{page:o+1}):null,e.first_page_url=I(t,{page:1}),e.last_page_url=I(t,{page:i})}else e.next_page_url=e.has_more_pages?I(t,{page:o+1}):null;return e}function I(e,n){let t=new URL(e.toString());for(let[r,o]of Object.entries(n))t.searchParams.set(r,String(o));return`${t.pathname}${t.search}`}var G;function at(){if(G===null)return;if(G===void 0)try{let n=Xn("@stacksjs/router");if(typeof n.getCurrentRequest==="function")G=n.getCurrentRequest;else{G=null;return}}catch{G=null;return}return G()}function nt(e,n){let t=on(e,n);if(t===void 0)return;let r=Number(t);return Number.isFinite(r)?r:void 0}function on(e,n){let t=e.query?.[n];if(t===void 0)return;return Array.isArray(t)?t[0]:t}function an(){return{async generateTwoFactorForModel(e){let{generateTwoFactorSecret:n}=await import("@stacksjs/auth"),t=n();await e.update({two_factor_secret:t})},async verifyTwoFactorCode(e,n){let t=e.get("two_factor_secret");if(typeof t!=="string")return!1;let{verifyTwoFactorCode:r,RateLimiter:o}=await import("@stacksjs/auth"),i=String(e.id??e.get?.("id")??e.get?.("email")??t),a=`2fa:${i}`;if(await o.isRateLimited(a)){let{HttpError:u}=await import("@stacksjs/error-handling");throw new u(429,"Too many verification attempts. Please try again later.")}if(!await r(n,t))return await o.recordFailedAttempt(a),!1;try{let{cache:u}=await import("@stacksjs/cache"),c=`2fa:used:${i}:${n}`;if(await u.has(c))return await o.recordFailedAttempt(a),!1;await u.set(c,"1",90)}catch{}return await o.resetAttempts(a),!0}}}import{mutationCount as vo,sqlDateTime as Mo}from"@stacksjs/database/runtime";import{log as U}from"@stacksjs/logging";var ke="deleted_at";function sn(e,n="id"){return{async softDelete(t){let r=Mo(),o=e.where(n,t);if(typeof o?.update==="function")return await o.update({[ke]:r}),!0;return!1},async restore(t){let r=e.where(n,t).withTrashed();if(typeof r?.update==="function")return await r.update({[ke]:null}),!0;return!1},async forceDelete(t){let r=e.where(n,t),o=typeof r?.withTrashed==="function"?r.withTrashed():r;if(typeof o?.forceDelete==="function")return vo(await o.forceDelete())>0;return!1},withTrashed(){return typeof e.query==="function"?e.query():e},onlyTrashed(){let t=typeof e.query==="function"?e.query():e;if(typeof t?.whereNotNull==="function")return t.whereNotNull(ke);return t?.where?.(ke,"!=",null)??t}}}function un(e){if(e===!0||e==null)return{};if(typeof e==="object"&&!Array.isArray(e)){let n=e;if(Array.isArray(n.cascade)){let t=n.cascade.filter((r)=>typeof r==="string");return t.length?{cascade:t}:{}}return{}}return{}}function Oo(e,n){let t=e.hasMany??[],r=e.hasOne??[],o=t.some((l)=>st(l,n,!0)),i=r.some((l)=>st(l,n,!1));if(!o&&!i)return U.warn(`[orm] soft-delete cascade: '${n}' is not a declared hasMany/hasOne relation - skipping`),null;let s=(o?t:r).find((l)=>st(l,n,o))??null;if(!s)return null;let c=globalThis[s];if(!c)return U.warn(`[orm] soft-delete cascade: model '${s}' is not yet on globalThis - skipping cascade for '${n}'`),null;return{className:s,model:c}}function st(e,n,t){let r=e.toLowerCase();if(n===r)return!0;if(t&&n===`${r}s`)return!0;if(t&&r.endsWith("y")&&n===`${r.slice(0,-1)}ies`)return!0;return!1}async function Do(e,n,t,r,o){try{let i=t.where;if(typeof i!=="function"){U.warn(`[orm] cascade ${o}: child model has no .where()`);return}if(o==="softDelete"){let a=t.softDelete;if(typeof a==="function"){let u=i.call(t,r,n),c=typeof u?.get==="function"?await u.get():Array.isArray(u)?u:[],l=t.primaryKey||"id";for(let f of c){let d=f?.[l];if(d!=null)await a.call(t,d)}return}let s=i.call(t,r,n);if(typeof s?.delete==="function"){U.debug(`[orm] cascade soft-delete: child has no softDeletes trait, hard-deleting from ${String(t.table??"?")}`),await s.delete();return}}else{let a=t.restore;if(typeof a!=="function"){U.debug("[orm] cascade restore: child has no restore() - nothing to do");return}let s=t.withTrashed,c=(typeof s==="function"?s.call(t):t).where?.(r,n),l=typeof c?.get==="function"?await c.get():[],f=t.primaryKey||"id";for(let d of l){let p=d?.[f];if(p!=null)await a.call(t,p)}}}catch(i){if(U.warn(`[orm] soft-delete cascade ${o} on ${e}#${String(n)} failed`,{error:i}),process.env.STACKS_ORM_CASCADE_SWALLOW!=="true")throw i}}async function ee(e,n,t,r){let o=n.cascade;if(!o||o.length===0)return;let i=`${e.name.toLowerCase()}_id`;for(let a of o){let s=Oo(e,a);if(!s)continue;await Do(s.className,t,s.model,i,r)}}import{sqlDateTime as Fo}from"@stacksjs/database/runtime";import{log as Eo}from"@stacksjs/logging";var jo=[/^password$/i,/^password_hash$/i,/^api_key$/i,/_token$/i,/_secret$/i,/^remember_token$/i],cn=null;async function ln(){if(cn!=null)return cn;try{let e=await import("@stacksjs/router").catch(()=>null);if(!e)return null;let n=e.getCurrentRequest;if(typeof n!=="function")return null;let t=n();return t?.user?.id??t?._user?.id??null}catch{return null}}async function dn(){try{let n=(await import("@stacksjs/router").catch(()=>null))?.getCurrentRequest;if(typeof n!=="function")return null;let t=n();return typeof t?.ip==="function"?t.ip()??null:null}catch{return null}}function fn(e){if(!e||typeof e!=="object")return null;let n={};for(let[t,r]of Object.entries(e)){if(jo.some((o)=>o.test(t)))continue;n[t]=r}return n}function pn(e,n,t){Eo.warn(`[orm] ${e} row write failed for ${n}: ${t?.message??String(t)}`)}var $o="activities";function mn(e){if(!e)return null;if(e===!0)return{};if(typeof e!=="object")return null;let n=e;return{logOnly:Array.isArray(n.logOnly)?n.logOnly:void 0,include:Array.isArray(n.include)?n.include:void 0,exclude:Array.isArray(n.exclude)?n.exclude:void 0}}function Io(e,n,t=[]){let r=fn(e);if(!r)return null;let o=new Set(t),i=n.logOnly??n.include,a=new Set(n.exclude??[]),s={};for(let[u,c]of Object.entries(r)){if(o.has(u)||a.has(u))continue;if(i&&!i.includes(u))continue;s[u]=c}return s}function Bo(e,n,t){return t==null?`${e} was ${n}`:`${e} ${String(t)} was ${n}`}async function No(e){try{let{db:n}=await import("@stacksjs/database/runtime");await n.insertInto($o).values({type:e.type,description:e.description,subject_type:e.subject_type,subject_id:e.subject_id,causer:e.causer,properties:e.properties?JSON.stringify(e.properties):null,ip_address:e.ip_address,user_id:e.user_id,created_at:Fo()}).executeTakeFirst()}catch(n){pn("activity",`${e.subject_type}#${String(e.subject_id)}`,n)}}async function Lo(e){let{attributes:n,event:t,modelName:r,options:o,primaryKey:i}=e,a=n?.[i]??null,s=await ln();await No({type:`${r.toLowerCase()}.${t}`,description:Bo(r,t,a),subject_type:r,subject_id:a,properties:Io(n,o,e.hidden),causer:s==null?null:`User:${String(s)}`,user_id:s,ip_address:await dn()})}function Te(e){if(!e||typeof e!=="object")return null;let n=e;if(n.attributes&&typeof n.attributes==="object")return{...n.attributes};if(n._attributes&&typeof n._attributes==="object")return{...n._attributes};return{...e}}function gn(e,n,t,r,o=[]){if(n==="Activity")return;let i=e,a=async(d)=>typeof i.find==="function"?Te(await i.find(d)):null,s=async(d,p)=>{await Lo({modelName:n,event:d,attributes:p,primaryKey:t,options:r,hidden:o})},u=e.create;if(typeof u==="function")e.create=async function(...d){let p=await u.apply(this,d);return await s("created",Te(p)),p};let c=e.createMany;if(typeof c==="function")e.createMany=async function(...d){let p=await c.apply(this,d);for(let m of Array.isArray(p)?p:[])await s("created",Te(m));return p};let l=e.update;if(typeof l==="function")e.update=async function(d,p){let m=await l.call(this,d,p);return await s("updated",Te(m)??await a(d)),m};let f=e.delete;if(typeof f==="function")e.delete=async function(d){let p=await a(d),m=await f.call(this,d);return await s("deleted",p??{[t]:d}),m}}var _e,Mn=new vn;function N(){return Mn.getStore()?.suppressed===!0}function B(e){return Promise.resolve(Mn.run({suppressed:!0},e))}var On=new vn;function Vo(){return On.getStore()?.suppressed===!0}function Qo(e){return Promise.resolve(On.run({suppressed:!0},e))}var pt=Symbol.for("stacks.orm.modelDefinition");class Dn extends Error{status=422;errors;constructor(e,n){let t=Object.keys(n).join(", ");super(`${e} validation failed: ${t}`);this.name="ModelValidationError",this.errors=n}}var yn=new Set,zo=4096,wn=Object.create(null),bn=0;function te(e){let n=wn[e];if(n!==void 0)return n;let t=ne(e);if(bn<zo)wn[e]=t,bn++;return t}function Ho(e,n){let t=typeof e==="string"?e.slice(0,80):String(e),r=`${typeof e}:${t}`;if(yn.has(r))return;yn.add(r);let o=n instanceof Error?n.message:String(n);console.error(`[orm] JSON cast failed to parse value (returning null): ${o} - value preview: ${JSON.stringify(t)}`)}var Jo={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)=>{if(e==null)return null;if(typeof e==="string")try{return JSON.parse(e)}catch(n){return Ho(e,n),null}return e},set:(e)=>{if(e==null)return null;return 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)=>{if(e==null)return[];if(Array.isArray(e))return e;if(typeof e==="string")try{return JSON.parse(e)}catch{return[]}return[]},set:(e)=>{if(e==null)return null;return Array.isArray(e)?JSON.stringify(e):e}}};function Yo(e){return typeof e==="string"?Jo[e]:e}var hn=new WeakMap;function En(e){let n=Object.keys(e),t=hn.get(e);if(t&&t.length===n.length){let o=!0;for(let i=0;i<n.length;i++){let a=n[i];if(t[i]?.attr!==a||t[i]?.definition!==e[a]){o=!1;break}}if(o)return t}let r=n.map((o)=>{let i=e[o];return{attr:o,definition:i,caster:Yo(i)}});return hn.set(e,r),r}function ut(e,n,t){if(!e||typeof e!=="object")return e;let r={...e};for(let{attr:o,caster:i}of En(n))if(o in r)r[o]=i[t].call(i,r[o]);return r}function Re(e){return e==="_attributes"||e==="_original"||e==="_definition"||e==="_hasSaved"||e==="_relations"}var lt=Symbol.for("stacks.modelInstanceProxy"),kn,Tn=new WeakMap,Xo={tags:{bag:"_taggable",mode:"id"},tagCount:{bag:"_taggable",mode:"id"},addTag:{bag:"_taggable",mode:"id"},activeTags:{bag:"_taggable",mode:"id"},inactiveTags:{bag:"_taggable",mode:"id"},removeTag:{bag:"_taggable",mode:"id"},categories:{bag:"_categorizable",mode:"id"},categoryCount:{bag:"_categorizable",mode:"id"},addCategory:{bag:"_categorizable",mode:"id"},activeCategories:{bag:"_categorizable",mode:"id"},inactiveCategories:{bag:"_categorizable",mode:"id"},removeCategory:{bag:"_categorizable",mode:"id"},comments:{bag:"_commentable",mode:"id"},commentCount:{bag:"_commentable",mode:"id"},addComment:{bag:"_commentable",mode:"id"},approvedComments:{bag:"_commentable",mode:"id"},pendingComments:{bag:"_commentable",mode:"id"},rejectedComments:{bag:"_commentable",mode:"id"},likes:{bag:"_likeable",mode:"id"},likeCount:{bag:"_likeable",mode:"id"},like:{bag:"_likeable",mode:"id"},unlike:{bag:"_likeable",mode:"id"},isLiked:{bag:"_likeable",mode:"id"},...Object.fromEntries(de.map((e)=>[e,{bag:"_billable",mode:"model"}])),generateTwoFactorForModel:{bag:"_twoFactor",mode:"model"},verifyTwoFactorCode:{bag:"_twoFactor",mode:"model"}};function Zo(e,n){if(!e||!n)return null;let t=n.split("."),r=e;for(let o of t){if(r==null||typeof r!=="object")return null;let i=r;if("_attributes"in i&&i._attributes&&typeof i._attributes==="object"){let a=i._attributes;if(o in a){r=a[o];continue}}if(o in i){r=i[o];continue}return null}return r??null}function Se(e,n,t){if(e&&typeof e.then==="function")return e.then((r)=>r===n?t:r);return e===n?t:e}function O(e,n){if(!e||typeof e!=="object")return e;let t=e;if(t[lt])return e;let r=t._attributes;if(!r||typeof r!=="object")return e;if(n){for(let{attr:i,caster:a}of En(n))if(Object.hasOwn(r,i))r[i]=a.get.call(a,r[i])}let o=n?Tn.get(n):kn;if(!o)if(o={get(i,a,s){let u=i;if(a===lt)return!0;if(a==="saveAsync")return async function(){let l=u._definition,f=l?.set;if(f&&typeof u.isDirty==="function"){for(let[p,m]of Object.entries(f)){if(typeof m!=="function")continue;if(!u.isDirty(p))continue;let g=m(u._attributes),w=g&&typeof g.then==="function"?await g:g;u._attributes[p]=w}let d=l.set;l.set={};try{return Se(u.save(),i,s)}finally{l.set=d}}return Se(u.save(),i,s)};if(a==="save")return function(){let l=u._definition,f=l?.set;if(f&&Object.keys(f).length>0&&typeof u.isDirty==="function"){for(let[p,m]of Object.entries(f)){if(typeof m!=="function")continue;if(!u.isDirty(p))continue;let g=m(u._attributes);if(g&&typeof g.then==="function")throw Error(`Setter for "${p}" returned a Promise - use \`saveAsync()\` instead of \`save()\` when a model has async setters.`);u._attributes[p]=g}let d=l.set;l.set={};try{return Se(u.save(),i,s)}finally{l.set=d}}return Se(u.save(),i,s)};if(a==="updateAsync")return async function(l){if(l&&typeof l==="object"&&!Array.isArray(l))for(let[f,d]of Object.entries(l))s[f]=d;return s.saveAsync()};if(a==="saveQuietly")return function(){return B(()=>u.save())};if(a==="saveAsyncQuietly")return function(){return B(()=>s.saveAsync())};if(a==="updateQuietly")return function(l){return B(()=>u.update(l))};if(a==="updateAsyncQuietly")return function(l){return B(()=>s.updateAsync(l))};if(a==="deleteQuietly")return function(){return B(()=>u.delete())};if(a==="toSearchableObject")return function(){let d=u._definition?.traits?.useSearch;if(!d)return null;let p=u._attributes;if(!p)return null;if(d===!0){let b={...p};if(p.id!=null)b.id=String(p.id);return b}let m={},g=d.displayable?.length?d.displayable:[...d.searchable??[],...d.filterable??[],...d.sortable??[],"id"],w=d.denormalize??{},h=u._relations;for(let b of g){let k=ne(b),R=p[k]??p[b];if(R!==void 0){m[k]=R;continue}let oe=w[b]??w[k];if(oe){m[k]=Zo(h,oe);continue}m[k]=void 0}if(p.id!=null)m.id=String(p.id);return m};if(typeof a==="string"&&!Re(a)){let l=u._attributes;if(l&&Object.hasOwn(l,a))return l[a];let f=u._relations;if(f&&Object.hasOwn(f,a)){let p=f[a];if(Array.isArray(p))return p.map((m)=>O(m,n));return p&&typeof p==="object"?O(p,n):p}let d=Xo[a];if(d){let g=u._definition?.__traitMethods?.[d.bag]?.[a];if(typeof g==="function")return d.mode==="model"?(...w)=>g(s,...w):(...w)=>g(u.id,...w)}if(l){let p=te(a);if(p!==a&&Object.hasOwn(l,p))return l[p]}}let c=Reflect.get(u,a,u);return typeof c==="function"?c.bind(u):c},set(i,a,s,u){let c=i;if(typeof a==="string"&&!Re(a)){let{_attributes:l,set:f}=c;if(l&&Object.hasOwn(l,a)){if(typeof f==="function")f.call(c,a,s);else l[a]=s;return!0}if(l){let d=te(a);if(d!==a&&Object.hasOwn(l,d)){if(typeof f==="function")f.call(c,d,s);else l[d]=s;return!0}}if(l&&!(a in c)){if(typeof f==="function")f.call(c,a,s);else l[a]=s;return!0}}return Reflect.set(c,a,s,u)},has(i,a){let s=i;if(typeof a==="string"&&!Re(a)){let u=s._attributes;if(u&&Object.hasOwn(u,a))return!0;let c=s._relations;if(c&&Object.hasOwn(c,a))return!0;if(u){let l=te(a);if(l!==a&&Object.hasOwn(u,l))return!0}}return Reflect.has(s,a)},deleteProperty(i,a){let s=i;if(typeof a==="string"&&!Re(a)){let u=s._attributes;if(u&&Object.hasOwn(u,a))return delete u[a],!0}return Reflect.deleteProperty(s,a)},ownKeys(i){let s=i._attributes;return s?Object.keys(s):[]},getOwnPropertyDescriptor(i,a){let s=i;if(typeof a==="string"){let u=s._attributes;if(u&&Object.hasOwn(u,a))return{configurable:!0,enumerable:!0,value:u[a],writable:!0}}return Object.getOwnPropertyDescriptor(s,a)}},n)Tn.set(n,o);else kn=o;return new Proxy(e,o)}var jn=Object.assign(Object.create(null),{get:!0,first:!0,last:!0,firstOrFail:!0,find:!0,findOrFail:!0,all:!0,paginate:!0,simplePaginate:!0,cursorPaginate:!0}),ei={paginate:Ko,simplePaginate:Wo,cursorPaginate:Uo},Rn=Symbol.for("stacks.queryBuilderProxy");function Sn(e,n,t){if(jn[n]){if(Array.isArray(e))return e.map((o)=>O(o,t));let r=ei[n];if(r&&e&&Array.isArray(e.data)){let o=e.data.map((a)=>O(a,t)),i=r({...e,data:o});return it(i)}if(e&&Array.isArray(e.data))return{...e,data:e.data.map((o)=>O(o,t))};return O(e,t)}if(e&&typeof e==="object"&&typeof e.get==="function")return Fn(e,t);return e}function Fn(e,n){if(!e||typeof e!=="object")return e;if(e[Rn])return e;return new Proxy(e,{get(t,r,o){if(r===Rn)return!0;let i=Reflect.get(t,r,o);if(typeof i!=="function")return i;let a=String(r);return function(...s){let u=s;if(a==="paginate"||a==="simplePaginate"){let{perPage:l,page:f}=rt(s[0],s[1]);u=[l,f]}else if(a==="cursorPaginate"){let{perPage:l,cursor:f}=ot(s[0],s[1]);u=[l,f,s[2],s[3]]}let c=i.apply(t,u);if(!jn[a]&&c===t)return o;if(c&&typeof c.then==="function")return c.then((l)=>Sn(l,a,n));return Sn(c,a,n)}}})}function ti(e,n){let t=(a)=>Array.isArray(a)?a.map((s)=>O(s,n)):O(a,n),r=["find","first","last","all","firstOrFail","findOrFail","findMany"];for(let a of r){let s=e[a];if(typeof s!=="function")continue;e[a]=function(...u){let c=s.apply(this,u);if(c&&typeof c.then==="function")return c.then(t);return t(c)}}let o=["create","createMany","firstOrCreate","updateOrCreate","make"];for(let a of o){let s=e[a];if(typeof s!=="function")continue;e[a]=function(...u){let c=s.apply(this,u);if(c&&typeof c.then==="function")return c.then(t);return t(c)}}let i=["query","where","orWhere","whereIn","whereNotIn","whereNull","whereNotNull","whereLike","whereBetween","whereNotBetween","orderBy","orderByDesc","select","with","limit","take","skip","latest","oldest"];for(let a of i){let s=e[a];if(typeof s!=="function")continue;e[a]=function(...u){let c=s.apply(this,u);return Fn(c,n)}}}class $n extends Error{model;id;constructor(e,n){super(n!=null?`[ORM] ${e} not found for id=${String(n)}`:`[ORM] No matching ${e} row`);this.name="ModelNotFoundError",this.model=e,this.id=n}}class dt extends Error{model;attribute;reason;constructor(e,n,t){let r=t==="guarded"?`'${n}' is marked guarded`:`'${n}' is not in the fillable allowlist`;super(`[ORM] Mass assignment to ${e} forbidden: ${r}. Use ${e}.forceCreate(...) / .forceUpdate(...) to bypass.`);this.name="MassAssignmentException",this.model=e,this.attribute=n,this.reason=t}}var ni=new Set(["id","created_at","updated_at","deleted_at","uuid"]),_n=new WeakMap;function ri(e){let n=_n.get(e);if(n)return n;let t=new Set,r=new Set,o=new Set;for(let[a,s]of Object.entries(e)){let u=te(a);if(t.add(u),s?.fillable===!0)r.add(u);if(s?.guarded===!0)o.add(u)}let i={allowed:r.size>0?r:t,guarded:o};return _n.set(e,i),i}function K(e,n,t={}){if(t.force)return n;if(!n||typeof n!=="object"||Array.isArray(n))return n;let r=e.attributes;if(!r)return n;let{allowed:o,guarded:i}=ri(r);for(let a in n){if(!Object.hasOwn(n,a))continue;let s=te(a);if(ni.has(s))continue;if(i.has(s))throw new dt(e.name,a,"guarded");if(s.endsWith("_id"))continue;if(!o.has(s))throw new dt(e.name,a,"not-fillable")}return n}async function Ae(e,n){let t=e.set;if(!t||typeof t!=="object")return n;let r={...n};for(let[o,i]of Object.entries(t)){if(typeof i!=="function"||!(o in r))continue;try{r[o]=await i(r)}catch(a){_.error(`[orm] ${e.name}.set.${o} threw - skipping setter`,a)}}return r}function oi(e,n){let t=n.primaryKey||"id",r=e.create;function o(c){let l=e.where;if(typeof l!=="function")throw Error(`[ORM] ${n.name}.${c} needs a working where(): the underlying query builder did not expose one`);return l}function i(c){let l=e.find;if(typeof l!=="function")throw Error(`[ORM] ${n.name}.${c} needs a working find(): the underlying query builder did not expose one`);return l}function a(c){let l=e.create;if(typeof l!=="function")throw Error(`[ORM] ${n.name}.${c} cannot create: the underlying query builder did not expose create()`);return l}if(e.update=async function(c,l){if(c==null)throw Error(`[ORM] ${n.name}.update requires an id as the first argument`);if(!l||typeof l!=="object"||Array.isArray(l))throw Error(`[ORM] ${n.name}.update requires a data object as the second argument`);if(Object.keys(l).length===0){_.debug(`[orm] ${n.name}.update called with empty data - short-circuiting and returning current row`);let p=e.find;return typeof p==="function"?await p.call(e,c):null}K(n,l);let f=await Ae(n,l);await o("update").call(e,t,c).update(f);let d=e.find;return typeof d==="function"?await d.call(e,c):null},typeof e.forceUpdate!=="function")e.forceUpdate=async function(c,l){if(c==null)throw Error(`[ORM] ${n.name}.forceUpdate requires an id as the first argument`);if(!l||typeof l!=="object"||Array.isArray(l))throw Error(`[ORM] ${n.name}.forceUpdate requires a data object as the second argument`);let f=await Ae(n,l);await o("forceUpdate").call(e,t,c).update(f);let d=e.find;return typeof d==="function"?await d.call(e,c):null};if(typeof e.forceCreate!=="function")e.forceCreate=async function(c){if(!c||typeof c!=="object"||Array.isArray(c))throw Error(`[ORM] ${n.name}.forceCreate requires a data object`);let l=e.make;if(typeof l==="function"){let f=await l.call(e);if(f&&typeof f.forceFill==="function"&&typeof f.save==="function"){f.forceFill(c);let d=await f.save();return d&&typeof d==="object"&&d!==f&&!d[lt]?f:d??f}}if(typeof r!=="function")throw Error(`[ORM] ${n.name}.forceCreate cannot create: the underlying query builder did not expose create()`);return await r.call(e,c)};if(e.delete=async function(c){if(c==null)throw Error(`[ORM] ${n.name}.delete requires an id as the first argument`);if(!await i("delete").call(e,c))return!1;return await o("delete").call(e,t,c).delete(),!0},typeof e.findOrFail!=="function")e.findOrFail=async function(c){let l=await i("findOrFail").call(e,c);if(l==null)throw new $n(n.name,c);return l};if(typeof e.exists!=="function")e.exists=async function(c){if(c==null)return!1;let l=o("exists").call(e,t,c);if(typeof l.count==="function"){let d=await l.count();return Number(d)>0}let f=e.find;return typeof f==="function"?await f.call(e,c)!=null:!1};if(typeof e.firstOrCreate!=="function")e.firstOrCreate=async function(c,l={}){if(!c||typeof c!=="object"||Array.isArray(c))throw Error(`[ORM] ${n.name}.firstOrCreate requires a where-attrs object`);let f=o("firstOrCreate").call(e,c),d=typeof f.first==="function"?await f.first():await f;if(d)return d;let p={...c,...l};return K(n,p),await a("firstOrCreate").call(e,p)};if(typeof e.updateOrCreate!=="function")e.updateOrCreate=async function(c,l){if(!c||typeof c!=="object"||Array.isArray(c))throw Error(`[ORM] ${n.name}.updateOrCreate requires a where-attrs object`);if(!l||typeof l!=="object"||Array.isArray(l))throw Error(`[ORM] ${n.name}.updateOrCreate requires a values object`);let f=o("updateOrCreate").call(e,c),d=typeof f.first==="function"?await f.first():await f;if(d){K(n,l);let m=d[t];await o("updateOrCreate").call(e,t,m).update(l);let g=e.find;return typeof g==="function"?await g.call(e,m):{...d,...l}}let p={...c,...l};return K(n,p),await a("updateOrCreate").call(e,p)};if(typeof e.count!=="function")e.count=async function(){let c=e;if(typeof c.query==="function"){let d=c.query();if(typeof d?.count==="function"){let p=await d.count();return Number(p)||0}}let{all:l,get:f}=e;if(typeof l==="function")return(await l.call(e)||[]).length;if(typeof f==="function")return(await f.call(e)||[]).length;return 0};if(typeof e.pluck!=="function")e.pluck=async function(c){if(!c||typeof c!=="string")throw Error(`[ORM] ${n.name}.pluck requires a column name`);let l=e.all;return((typeof l==="function"?await l.call(e):[])||[]).map((d)=>d?.[c])};if(typeof e.whereIn!=="function")e.whereIn=async function(c,l){if(!c||typeof c!=="string")throw Error(`[ORM] ${n.name}.whereIn requires a column name`);if(!Array.isArray(l))throw Error(`[ORM] ${n.name}.whereIn requires an array of values`);if(l.length===0)return[];let f=e.where;if(typeof f!=="function")return[];let d=f.call(e,c,"in",l);if(d&&typeof d.get==="function")return await d.get();return await d};let s=[["latest","desc"],["oldest","asc"]];for(let[c,l]of s)if(typeof e[c]!=="function")e[c]=async function(f="created_at"){let d=e,p=typeof d.query==="function"?d.query():d;if(typeof p?.orderBy==="function"){let h=p.orderBy(f,l);if(typeof h.first==="function")return await h.first();if(typeof h.get==="function")return(await h.get())?.[0]??null}let m=e.all;if(typeof m!=="function")return null;return[...await m.call(e)||[]].sort((h,b)=>{let k=h?.[f],R=b?.[f];if(k===R)return 0;return(k>R?1:-1)*(l==="desc"?-1:1)})[0]??null};let u=Ln(n.traits?.useSearch,n);if(u){let c=u.index??n.table??ne(`${n.name}s`);if(typeof e.search!=="function")e.search=function(l,f){return si(e,c,l,f,u.searchable)};if(typeof e.makeAllSearchable!=="function")e.makeAllSearchable=async function(l=500){let f=e.all;if(typeof f!=="function")throw Error(`[ORM] ${n.name}.makeAllSearchable cannot run: the underlying query builder did not expose all()`);let{useSearchEngine:d}=await import("@stacksjs/search-engine"),p=d(),m=0,g=e.query;if(typeof g==="function")try{let b=g.call(e);if(b&&typeof b.chunk==="function")return await b.chunk(l,async(k)=>{let R=await ft(k,u);if(R.length>0)await p.addDocuments(c,R);m+=R.length}),m}catch{}let w=await f.call(e)||[],h=await ft(w,u);if(h.length>0)await p.addDocuments(c,h);return h.length};if(typeof e.removeAllFromSearch!=="function")e.removeAllFromSearch=async function(){let{searchEngineReady:l}=await import("@stacksjs/search-engine");await(await l()).deleteAllDocuments(c)}}}async function ft(e,n){if(e.length===0)return[];if(typeof n.shapeMany==="function"){let r=await n.shapeMany(e);if(!Array.isArray(r)||r.length!==e.length)throw TypeError(`[orm/search] shapeMany returned ${Array.isArray(r)?r.length:typeof r} documents for ${e.length} rows. It must return one document per row, in order, or documents are indexed under the wrong ids.`);return r.filter(Boolean)}return(await Promise.all(e.map((r)=>ai(r,n)))).filter(Boolean)}function In(e){let n=new Set,t=e.attributes??{};for(let[r,o]of Object.entries(t))if(o?.hidden)n.add(r);return n}function ii(e,n){if(!e||n.size===0)return e;let t={};for(let[r,o]of Object.entries(e))if(!n.has(r))t[r]=o;return t}async function ai(e,n){if(typeof n.shape==="function")try{return await n.shape(e)}catch{return}let t=e?.toSearchableObject?.();if(t!==void 0)return t;return ii(e?._attributes??(typeof e?.toJSON==="function"?e.toJSON():null),n.hidden??new Set)}function si(e,n,t,r,o){let i=o&&o.length>0?{query_by:[...o].join(",")}:{},a={q:t,...i,...r??{}},s={with(u){return a={...a,...u},s},where(u){return a={...a,filter:u},s},async get(){let{useSearchEngine:u}=await import("@stacksjs/search-engine");return(await u().search(n,a))?.hits??[]},async paginate(u,c=1){if(!Number.isInteger(u)||u<1)throw TypeError(`[orm/search] paginate() needs a positive integer page size, got ${u}`);if(!Number.isInteger(c)||c<1)throw TypeError(`[orm/search] paginate() pages are 1-based, got ${c}`);let{useSearchEngine:l}=await import("@stacksjs/search-engine"),d=await l().search(n,{...a,limit:u,offset:(c-1)*u});return{hits:d.hits??[],total:Number(d.estimatedTotalHits??d.nbHits??d.total??0),page:c,perPage:u}},async raw(){let{useSearchEngine:u}=await import("@stacksjs/search-engine");return await u().search(n,a)}};return s}function Bn(e){let n=ne(e);return n===e?[e]:[e,n]}async function ct(e,n){if(!e||typeof e!=="object")return;let t=e._attributes??e;for(let r of n)for(let o of Bn(r)){if(!(o in t))continue;let i=t[o];if(!Q(i))continue;t[o]=await Oe(i)}}function ui(e,n){if(n.length===0)return;let t=async(s)=>{if(Array.isArray(s)){for(let u of s)await ct(u,n);return s}if(s&&typeof s==="object"&&Array.isArray(s.data)){for(let u of s.data)await ct(u,n);return s}if(s)await ct(s,n);return s},r=["find","first","last","all","firstOrFail","findOrFail","findMany"];for(let s of r){let u=e[s];if(typeof u!=="function")continue;e[s]=async function(...c){let l=await u.apply(this,c);return await t(l)}}let o=["create","createMany","firstOrCreate","updateOrCreate","make"];for(let s of o){let u=e[s];if(typeof u!=="function")continue;e[s]=async function(...c){let l=await u.apply(this,c);return await t(l)}}for(let s of["update","forceUpdate"]){let u=e[s];if(typeof u!=="function")continue;e[s]=async function(c,l){let f=await u.call(this,c,l);return await t(f)}}let i=["first","firstOrFail","get","all","find","findOrFail","last","paginate","simplePaginate"],a=(s)=>{if(!s||typeof s!=="object")return s;let u=s;if(u.__stacksEncryptedReads)return s;for(let c of i){let l=u[c];if(typeof l!=="function")continue;u[c]=async function(...f){return await t(await l.apply(this,f))}}for(let c of["where","whereIn","whereNull","whereNotNull","orWhere","orderBy","orderByDesc","limit","offset","with"]){let l=u[c];if(typeof l!=="function")continue;u[c]=function(...f){return a(l.apply(this,f))}}return Object.defineProperty(u,"__stacksEncryptedReads",{value:!0,enumerable:!1}),s};for(let s of["where","whereIn","whereNull","whereNotNull","orderBy","orderByDesc","limit","query"]){let u=e[s];if(typeof u!=="function")continue;e[s]=function(...c){return a(u.apply(this,c))}}}function ci(e,n){if(n.length===0)return;let t=async(i)=>{if(!i||typeof i!=="object"||Array.isArray(i))return i;let a={...i};for(let s of n)for(let u of Bn(s))if(u in a)a[u]=await Me(a[u]);return a},r=["create","firstOrCreate","updateOrCreate","forceCreate"],o=e.createMany;if(typeof o==="function")e.createMany=async function(i,...a){let s=Array.isArray(i)?await Promise.all(i.map(t)):i;return await o.call(this,s,...a)};for(let i of r){let a=e[i];if(typeof a!=="function")continue;e[i]=async function(...s){if(s[0]=await t(s[0]),s[1])s[1]=await t(s[1]);return await a.apply(this,s)}}for(let i of["update","forceUpdate"]){let a=e[i];if(typeof a!=="function")continue;e[i]=async function(s,u){let c=await t(u);return await a.call(this,s,c)}}}function li(e,n){let t=e.create;if(typeof t==="function")e.create=async function(o,...i){K(n,o);let a=await Ae(n,o);return await t.call(this,a,...i)};let r=e.createMany;if(typeof r==="function")e.createMany=async function(o,...i){let a=[];for(let s of o)K(n,s),a.push(await Ae(n,s));return await r.call(this,a,...i)};for(let o of["firstOrCreate","updateOrCreate"]){let i=e[o];if(typeof i!=="function")continue}}function di(e,n){if(!$t(n))return;let t=String(n?.name??e.name??"Model"),r=(s,u)=>{if(Vo())return;if(!s||typeof s!=="object"||Array.isArray(s))return;let c=It(s,n,u);if(!c.valid)throw new Dn(t,c.errors)},o=e.create;if(typeof o==="function")e.create=async function(s,...u){return r(s,"creating"),await o.call(this,s,...u)};let i=e.createMany;if(typeof i==="function")e.createMany=async function(s,...u){if(Array.isArray(s))for(let c of s)r(c,"creating");return await i.call(this,s,...u)};let a=e.update;if(typeof a==="function")e.update=async function(s,u,...c){return r(u,"updating"),await a.call(this,s,u,...c)}}function fi(e,n){let t=["create","firstOrCreate","updateOrCreate"],r=e.createMany;if(typeof r==="function")e.createMany=async function(i,...a){let s=Array.isArray(i)?i.map((u)=>u&&typeof u==="object"&&!Array.isArray(u)?ut(u,n,"set"):u):i;return await r.call(this,s,...a)};for(let i of t){let a=e[i];if(typeof a==="function")e[i]=async function(...s){if(_.debug(`[orm] ${i.charAt(0).toUpperCase()+i.slice(1)} ${String(e.name||"unknown")}`,s[0]),s[0]&&typeof s[0]==="object"&&!Array.isArray(s[0]))s[0]=ut(s[0],n,"set");return await a.apply(this,s)}}let o=e.update;if(typeof o==="function")e.update=async function(i,a){let s=a&&typeof a==="object"&&!Array.isArray(a)?ut(a,n,"set"):a;return await o.call(this,i,s)}}var An=new Set(["useUuid","useTimestamps","timestampable","useSoftDeletes","softDeletable","useApi","useAuth","authenticatable","useSearch","searchable","useSeeder","seedable","useSocials","billable","observe","useAudit","useActivityLog","prunable","sharding","likeable","taggable","categorizable","commentable","commentables","broadcastOn","broadcastWith","gdpr"]);function Nn(e){_.debug(`[orm] Defining model: ${e.name} (table: ${e.table})`);for(let g of Object.keys(e.traits??{}))if(!An.has(g))_.warn(`[orm] Model '${e.name}' declares an unknown trait '${g}'. It does nothing. Known traits: ${[...An].sort().join(", ")}.`);let n=pi(e),t=gi(e),r=mi(n,t),o=yi(e);e.__traitMethods=o;let i=e.traits;if((i?.useAuth||i?.authenticatable)&&e.name!=="PersonalAccessToken"){let g=e.morphMany;if(!g||!("tokenable"in g))e.morphMany={...g??{},tokenable:"PersonalAccessToken"}}let a=r?{...e,hooks:{...e.hooks,...r}}:e,u=qo(a);if(ti(u,e.casts),oi(u,a),li(u,a),e.casts&&Object.keys(e.casts).length>0)fi(u,e.casts);let c=De(e);if(c.length>0)ci(u,c),ui(u,c);let l=e.traits?.useSoftDeletes;if(l)wi(u,a,l);let f=e.traits?.useAudit;if(f){let g=_t(f);At(u,e.name,e.primaryKey||"id",g)}let d=mn(e.traits?.useActivityLog);if(d)gn(u,e.name,e.primaryKey||"id",d,[...In(e)]);di(u,a);let p=u;p.withoutValidation=function(g){return Qo(g)},p.withoutEvents=function(g){return B(g)};for(let g of["create","createMany","update","firstOrCreate","updateOrCreate","forceCreate","forceUpdate","delete","forceDelete","softDelete","restore"]){let w=u[g];if(typeof w!=="function")continue;let h=`${g}Quietly`;if(typeof u[h]==="function")continue;u[h]=function(...b){return B(()=>w.apply(u,b))}}let m=Object.assign(u,o,{...e,getDefinition:()=>e,_isStacksModel:!0});return Go(e.name,m),Object.defineProperty(m,pt,{value:e,enumerable:!1,configurable:!0}),m}function pi(e){let n=e.traits?.observe;if(!n)return;let t=e.name.toLowerCase(),r=(d)=>{let p=d?.attributes;if(!p||typeof p!=="object")return d;let m=e.primaryKey||"id",g={...p};if(g[m]===void 0&&d[m]!==void 0)g[m]=d[m];return g},o=async(d,p)=>{if(N())return;try{let{dispatch:m}=_e??=await import("@stacksjs/events");await m(d,p)}catch(m){if(m&&typeof m==="object"&&"code"in m&&m.code==="MODULE_NOT_FOUND")return;if(console.error(`[ORM] Event '${d}' handler error:`,m),process.env.STACKS_ORM_EVENT_ERRORS!=="swallow")throw m}},i=e.traits?.broadcastOn,a=e.traits?.broadcastWith,s=typeof i==="function"&&typeof a==="function",u=async(d,p)=>{if(!s)return;if(N())return;try{let m=i(p),g=Array.isArray(m)?m:[m],w=a(p),b=(await import("@stacksjs/realtime").catch(()=>null))?.broadcast;if(typeof b!=="function")return;for(let k of g){if(typeof k!=="string"||k.length===0)continue;await b(k,d,w)}}catch(m){if(m&&typeof m==="object"&&"code"in m&&m.code==="MODULE_NOT_FOUND")return;if(console.error(`[ORM] Broadcast '${d}' handler error:`,m),process.env.STACKS_ORM_BROADCAST_ERRORS==="throw")throw m}},c=async(d,p)=>{if(N())return!0;let m;try{m=_e??=await import("@stacksjs/events");let{dispatchAndCollect:g}=m,w=await g(d,p);if(w.some((b)=>b.ok&&b.value===!1))return!1;let h=w.find((b)=>!b.ok);if(h&&!h.ok)throw h.error}catch(g){if(!m&&g&&typeof g==="object"&&"code"in g&&g.code==="MODULE_NOT_FOUND")return!0;if(console.error(`[ORM] Before-event '${d}' handler error:`,g),process.env.STACKS_ORM_EVENT_ERRORS!=="swallow")throw g}return!0},l=n===!0?["create","update","delete"]:Array.isArray(n)?n:[],f={};if(l.includes("create"))f.beforeCreate=async(d)=>{if(_.debug(`[orm] Create ${t}`,d),!await c(`${t}:saving`,d))throw Error(`[ORM] ${t}:saving event cancelled the operation`);if(!await c(`${t}:creating`,d))throw Error(`[ORM] ${t}:creating event cancelled the operation`)},f.afterCreate=async(d)=>{let p=r(d);await o(`${t}:created`,p),await o(`${t}:saved`,p),await u(`${t}:created`,d)};if(l.includes("update"))f.beforeUpdate=async(d)=>{if(_.debug(`[orm] Update ${t}#${d?.id??"unknown"}`,d),!await c(`${t}:saving`,d))throw Error(`[ORM] ${t}:saving event cancelled the operation`);if(!await c(`${t}:updating`,d))throw Error(`[ORM] ${t}:updating event cancelled the operation`)},f.afterUpdate=async(d)=>{let p=r(d);await o(`${t}:updated`,p),await o(`${t}:saved`,p),await u(`${t}:updated`,d)};if(l.includes("delete"))f.beforeDelete=async(d)=>{if(_.debug(`[orm] Delete ${t}#${d?.id??"unknown"}`),!await c(`${t}:deleting`,d))throw Error(`[ORM] ${t}:deleting event cancelled the operation`)},f.afterDelete=async(d)=>{await o(`${t}:deleted`,r(d)),await u(`${t}:deleted`,d)};return f}function mi(...e){let n={},t=new Set;for(let r of e){if(!r)continue;for(let o of Object.keys(r))t.add(o)}for(let r of t){let o=e.map((i)=>i?.[r]).filter((i)=>typeof i==="function");if(!o.length)continue;n[r]=async(...i)=>{for(let a of o)await a(...i)}}return Object.keys(n).length?n:void 0}function Ln(e,n){if(!e)return null;let t=e===!0?{}:typeof e==="object"?{...e}:null;if(!t)return null;if(n)t.hidden=In(n);return t}function gi(e){let n=Ln(e.traits?.useSearch,e);if(!n)return;let t=n,r=t.index??e.table??ne(`${e.name}s`);async function o(s){if(typeof t.shapeMany==="function")try{let[l]=await ft([s],t);return l}catch(l){_.warn(`[orm/search] shapeMany() threw for ${e.name}: ${l.message}`);return}if(typeof t.shape==="function")try{return await t.shape(s)}catch(l){_.warn(`[orm/search] shape() threw for ${e.name}: ${l.message}`);return}let c=O(s).toSearchableObject?.();if(c!==void 0)return c;return s?._attributes??(typeof s?.toJSON==="function"?s.toJSON():null)}let i=async(s)=>{if(N())return;let u=await o(s);if(!u)return;if(n.queueable){try{let{Jobs:c}=await import("@stacksjs/queue");await c.dispatch("SyncSearchIndexJob",{index:r,op:"upsert",doc:u})}catch(c){_.warn(`[orm/search] queue dispatch failed for ${e.name}; falling back to inline: ${c.message}`),await xn(r,u,e.name)}return}await xn(r,u,e.name)};return{afterCreate:i,afterUpdate:i,afterDelete:async(s)=>{if(N())return;let u=s?.id??s?._attributes?.id;if(u==null)return;if(n.queueable){try{let{Jobs:c}=await import("@stacksjs/queue");await c.dispatch("SyncSearchIndexJob",{index:r,op:"delete",id:Number(u)})}catch(c){_.warn(`[orm/search] queue dispatch failed for ${e.name}#${u}; falling back to inline: ${c.message}`),await Cn(r,Number(u),e.name)}return}await Cn(r,Number(u),e.name)}}}var Pn=new Map;function qn(e,n){let t=Pn.get(e)??0;if(Pn.set(e,t+1),t===0)_.warn(`[orm/search] ${n}`);else if(t===9)_.warn(`[orm/search] ${e} is still failing; further identical warnings suppressed for this process.`)}async function xn(e,n,t){try{let{useSearchEngine:r}=await import("@stacksjs/search-engine");await r().addDocument(e,n)}catch(r){qn(`index:${t}`,`Failed to index ${t}: ${r.message}`)}}async function Cn(e,n,t){try{let{useSearchEngine:r}=await import("@stacksjs/search-engine");await r().deleteDocument(e,n)}catch(r){qn(`remove:${t}`,`Failed to remove ${t}#${n}: ${r.message}`)}}function yi(e){let n={},{table:t,traits:r}=e;if(!r)return n;if(r.taggable)n._taggable=Ie(t);if(r.categorizable)n._categorizable=Be(t);if(r.commentable)n._commentable=Fe(t);if(r.billable)n._billable=Ct(t);if(r.likeable){let i=typeof r.likeable==="object"?r.likeable:void 0;n._likeable=Ne(t,i)}let o=r.useAuth||r.authenticatable;if(typeof o==="object"&&o&&"useTwoFactor"in o&&o.useTwoFactor)n._twoFactor=an();return n}function wi(e,n,t){let r=sn(e,n.primaryKey||"id"),o=un(t),i=n,a=n.name.toLowerCase(),s=n.traits?.observe!=null&&n.traits?.observe!==!1,u=async(p)=>{if(!s||N())return!0;try{let{dispatchAsync:m}=_e??=await import("@stacksjs/events"),g=await m(`${a}:restoring`,{id:p});if(Array.isArray(g)&&g.some((w)=>w===!1))return!1}catch(m){if(m?.code!=="MODULE_NOT_FOUND")console.error(`[ORM] Before-event '${a}:restoring' handler error:`,m)}return!0},c=async(p)=>{if(!s||N())return;try{let{dispatch:m}=_e??=await import("@stacksjs/events");await m(`${a}:restored`,{id:p})}catch(m){if(m?.code!=="MODULE_NOT_FOUND")console.error(`[ORM] Event '${a}:restored' handler error:`,m)}},l=process.env.STACKS_ORM_CASCADE_SWALLOW!=="true",f=async(p)=>{if(!o.cascade?.length||!l){let g=await r.softDelete(p);if(g&&o.cascade?.length)await ee(i,o,p,"softDelete");return g}let{db:m}=await import("@stacksjs/database/runtime");return await m.transaction(async()=>{let g=await r.softDelete(p);if(g)await ee(i,o,p,"softDelete");return g})},d=async(p)=>{if(!await u(p))return!1;if(!o.cascade?.length||!l){let h=await r.restore(p);if(h){if(o.cascade?.length)await ee(i,o,p,"restore");await c(p)}return h}let{db:g}=await import("@stacksjs/database/runtime"),w=await g.transaction(async()=>{let h=await r.restore(p);if(h)await ee(i,o,p,"restore");return h});if(w)await c(p);return w};e.softDelete=f,e.restore=d,e.forceDelete=r.forceDelete,e.withTrashed=r.withTrashed,e.onlyTrashed=r.onlyTrashed,e.delete=f}function bi(e){if(e==null)return e;if(Array.isArray(e))return e.map((t)=>bi(t));if(typeof e!=="object")return e;let n=e;if(typeof n.toJSON==="function")return n.toJSON();if(n._attributes&&typeof n._attributes==="object")return n._attributes;return e}var hi=["belongsTo","hasOne","hasMany","belongsToMany","morphMany","morphOne"],ki=["traits","dashboard"];function Ti(e){let n=e?.[pt];if(n&&typeof n==="object")return n;if(e&&typeof e==="object"&&"name"in e&&"attributes"in e)return e;throw TypeError("extendModel() expects a model created by defineModel(), or a model definition. Import the framework model itself rather than its table name.")}function Ri(e,n){let t=Array.isArray(e)?e:[],r=Array.isArray(n)?n:[];if(!t.length&&!r.length)return;return[...new Set([...t,...r])]}function Si(e){if(!e)return 0;return Object.values(e).reduce((n,t)=>{let r=Number(t?.order);return Number.isFinite(r)&&r>n?r:n},0)}function _i(e,n){let t={...e,...n},r=e.attributes??{},o=n.attributes??{};if(n.attributes){let i=Si(r),a=Object.fromEntries(Object.entries(o).map(([s,u])=>{let c=!(s in r),l=Number.isFinite(Number(u?.order));if(c&&!l)return[s,{...u,order:++i}];return[s,u]}));t.attributes={...r,...a}}for(let i of hi){let a=Ri(e[i],n[i]);if(a)t[i]=a}for(let i of ki){let a=e[i],s=n[i];if(a&&s&&typeof a==="object"&&typeof s==="object")t[i]={...a,...s}}return t}function Vc(e,n){return Nn(_i(Ti(e),n))}import Un from"process";import{log as Di}from"@stacksjs/logging";import{path as A}from"@stacksjs/path";import{fs as re}from"@stacksjs/storage";import{Database as Ai}from"bun:sqlite";import{existsSync as Pi,readdirSync as xi,readFileSync as Ci}from"fs";function vi(e){return e.startsWith("sqlite_")||e.startsWith("_qb_tmp_")}function Mi(e,n){let t=e.toUpperCase();if(t.includes("BOOL"))return n==="postgres"?"boolean":"number";if(t.includes("DATE")||t.includes("TIME"))return"string";if(t.includes("INT"))return"number";if(t.includes("CHAR")||t.includes("CLOB")||t.includes("TEXT"))return"string";if(t.includes("REAL")||t.includes("FLOA")||t.includes("DOUB")||t.includes("NUMERIC")||t.includes("DEC"))return"number";if(t.includes("BLOB"))return"Uint8Array";return"unknown"}function Oi(e,n){try{return e.exec(n),{ok:!0}}catch(t){if(/CREATE\s+TRIGGER/i.test(n))return{ok:!1,error:t.message};let r=0;for(let o of n.split(/;\s*$/m)){if(!o.trim())continue;try{e.exec(o),r++}catch(i){if(/duplicate column name/i.test(i.message))r++}}return r>0?{ok:!0}:{ok:!1,error:t.message}}}function Gn(e,n="sqlite"){let t=[];if(!Pi(e))return{tables:[],errors:t};let r;try{r=xi(e).filter((i)=>i.endsWith(".sql")).sort()}catch(i){return{tables:[],errors:[{file:e,error:i.message}]}}let o=new Ai(":memory:");try{for(let s of r){let u=`${e}/${s}`,c;try{c=Ci(u,"utf-8")}catch(f){t.push({file:u,error:f.message});continue}let l=Oi(o,c);if(!l.ok)t.push({file:u,error:l.error??"could not be applied"})}let i=o.query("SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name").all().map((s)=>s.name).filter((s)=>!vi(s)),a=[];for(let s of i){let u=o.query(`PRAGMA table_info("${s.replace(/"/g,'""')}")`).all();if(u.length===0)continue;let c={};for(let l of u){let f=Mi(l.type??"",n),d=l.notnull===0&&l.pk===0;c[l.name]=d&&f!=="unknown"?`${f} | null`:f}a.push({table:s,columns:c})}return{tables:a,errors:t}}finally{o.close()}}function Ei(e){if(e)return e;if(Un.env.STACKS_CANONICAL_FEATURES==="1")return"sqlite";let n=String(Un.env.DB_CONNECTION??"").toLowerCase();return n==="postgres"||n==="mysql"?n:"sqlite"}function Pe(e){return e==="postgres"?"boolean":"number"}function E(e){return e.replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").toLowerCase()}function ji(e,n){let t=e.default;if(typeof t==="boolean")return Pe(n);if(typeof t==="number")return"number";if(typeof t==="string")return"string";return"unknown"}function Fi(e){let n=e.validation;if(!n||typeof n!=="object")return null;let t=n.rule;return t&&typeof t==="object"?t:null}function $i(e){if(!e||String(e.name??"")!=="enum")return null;let t=(Array.isArray(e.allowedValues)?e.allowedValues:[]).filter((r)=>typeof r==="string"||typeof r==="number").map((r)=>typeof r==="number"?String(r):JSON.stringify(r));return t.length>0?t.join(" | "):null}function Ii(e,n){let t=Fi(e),r=$i(t);if(r!==null)return e.nullable===!0?`${r} | null`:r;let o=typeof e.type==="string"?e.type.toLowerCase():String(t?.name??"").toLowerCase(),i=(()=>{switch(o){case"string":case"text":case"longtext":case"mediumtext":case"tinytext":case"char":case"varchar":case"enum":case"uuid":case"date":case"datetime":case"timestamp":case"timestamptz":case"password":case"time":case"year":return"string";case"number":case"integer":case"int":case"tinyint":case"smallint":case"mediumint":case"float":case"double":case"decimal":case"numeric":return"number";case"bigint":return"number | bigint";case"boolean":case"bool":return Pe(n);case"json":case"jsonb":return"unknown";case"binary":case"blob":case"bytea":return"Uint8Array";case"unix":return"number";case"array":return"unknown[]";case"object":return"Record<string, unknown>";default:return ji(e,n)}})();return e.nullable===!0?`${i} | null`:i}function Bi(e){let n={},t=e.belongsTo;if(!t)return n;let r=Array.isArray(t)?t:Object.values(t);for(let o of r){if(typeof o==="string"){n[`${E(o)}_id`]="number";continue}if(o&&typeof o==="object"){let i=o;if(typeof i.foreignKey==="string"){n[i.foreignKey]="number";continue}if(typeof i.model==="string")n[`${E(i.model)}_id`]="number"}}return n}function Ni(e,n){let[t,r]=[E(e),E(n)].sort();return`${t}_${r}`}function Li(e,n){let t=e.default,r=typeof t==="string"?"string":typeof t==="number"?"number":typeof t==="boolean"?Pe(n):t instanceof Date?"string":"unknown";return e.nullable?`${r} | null`:r}function qi(e,n,t){let r=n.belongsToMany;if(!r)return[];let o=[],i=Array.isArray(r)?r:Object.values(r);for(let a of i){let s,u,c,l,f={},d=!0;if(typeof a==="string")s=a;else if(a&&typeof a==="object"&&"model"in a){let h=a;if(s=h.model,"pivotTable"in h||"firstForeignKey"in h||"secondForeignKey"in h)u=h.pivotTable,c=h.firstForeignKey,l=h.secondForeignKey;else{let b=a;u=b.table,c=b.foreignKey,l=b.relatedKey,f=b.pivot?.columns??{},d=Boolean(b.pivot?.timestamps)}}else continue;let p=u??Ni(e,s),m=c??`${E(e)}_id`,g=l??`${E(s)}_id`,w={id:"number",[m]:"number",[g]:"number"};for(let[h,b]of Object.entries(f))w[h]=Li(b,t);if(d)w.created_at="string",w.updated_at="string | null";o.push({table:p,columns:w})}return o}function Gi(e){return{email_verified_at:"string | null",password_changed_at:"string | null",two_factor_secret:"string | null",two_factor_enabled:`${Pe(e)} | null`,two_factor_last_used_step:"number | null",stripe_id:"string | null"}}function Ui(e,n){let t={id:"number"},r=e.traits??{};if(r.useUuid)t.uuid="string";if((r.useTimestamps??r.timestampable)!==!1)t.created_at="string",t.updated_at="string | null";if(r.useSoftDeletes??r.softDeletable)t.deleted_at="string | null";if((e.table??"")==="users"||e.name==="User")Object.assign(t,Gi(n));return t}function Ki(e,n){let t={},r=e.attributes??{};for(let[o,i]of Object.entries(r))t[E(o)]=Ii(i,n);return t}function Kn(e,n,t=2){let r=" ".repeat(t),o=" ".repeat(t+1),i=Object.entries(n).map(([s,u])=>`${o}${s}: ${u}`).join(`
8
- `),a=/^[A-Z_a-z]\w*$/.test(e)?e:`'${e}'`;return`${r}${a}: {
9
- ${o}// columns
10
- ${i}
11
- ${r}}`}var Wi=`/* eslint-disable */
12
- // AUTO-GENERATED by \`buddy generate:db-types\` \u2014 do not edit.
13
- // Regenerate after adding/removing a model or changing its attributes.
14
- // See stacksjs/stacks#1923.
15
-
16
- declare module '@stacksjs/database' {
17
- interface DatabaseSchema {
18
- `,Vi=` }
19
- }
20
-
21
- export {}
22
- `,Qi="/* eslint-disable */\n// AUTO-GENERATED by `buddy generate:db-types --framework` \u2014 do not edit.\n//\n// The shapes of the tables the framework itself ships, so framework code gets\n// real rows from `db.selectFrom(...)` without asserting them. An application's\n// own tables (and its overrides of these) live in `DatabaseSchema`, which takes\n// precedence - see `RowOf` in `./utils`.\n\nexport interface FrameworkSchema {\n",zi=`}
23
- `;function Wn(e){return e==="framework"?Qi:Wi}function Vn(e){return e==="framework"?zi:Vi}async function Qn(e,n,t=[]){let r=[];if(!re.existsSync(e))return r;let o=re.readdirSync(e,{withFileTypes:!0});for(let i of o){let a=A.join(e,i.name);if(i.isDirectory()){if(n){let s=await Qn(a,!0,t);r.push(...s)}continue}if(!i.name.endsWith(".ts"))continue;if(i.name.startsWith("_")||i.name.startsWith("index"))continue;try{let s=await(A.isAbsolute(a)?import(a):import(A.resolve(a))),u=s.default||s;if(u?.name&&(u.attributes||u.table))r.push({filePath:a,model:u})}catch(s){t.push({file:a,error:s.message})}}return r}async function Hi(e={}){let n=Ei(e.dialect),t=e.modelsDir??A.userModelsPath(),r=e.defaultsDir??A.frameworkPath("defaults/app/Models"),o=e.outFile??A.projectPath("database/types.d.ts"),i=[],a=[];for(let[m,g]of[[t,!1],[r,!0]])try{let w=await Qn(m,g,i);a.push(...w)}catch(w){i.push({file:m,error:w.message})}let s=new Map;for(let m of a)s.set(m.model.name??A.basename(m.filePath).replace(/\.ts$/,""),m);for(let m of a)if(m.filePath.startsWith(t))s.set(m.model.name??A.basename(m.filePath).replace(/\.ts$/,""),m);let u=[];for(let[m,{model:g}]of s){let w=g.table??`${E(m)}s`,h={...Ui(g,n),...Ki(g,n),...Bi(g)};u.push({table:w,model:m,columns:h})}let c=new Map;for(let[m,{model:g}]of s)for(let w of qi(m,g,n)){if(c.has(w.table))continue;c.set(w.table,{table:w.table,model:`(${w.table} pivot)`,columns:w.columns})}if(u.push(...c.values()),e.migrationsDir!==!1){let m=e.migrationsDir??A.resolve(A.dirname(o),"migrations"),g=new Set(u.map((h)=>h.table)),w=Gn(m,n);for(let h of w.tables){if(g.has(h.table))continue;g.add(h.table),u.push({table:h.table,model:`(${h.table} migration)`,columns:h.columns})}i.push(...w.errors)}u.sort((m,g)=>m.table.localeCompare(g.table));let l=e.target??"app",f=l==="framework"?1:2,d=u.map((m)=>Kn(m.table,m.columns,f)).join(`
24
- `),p=`${Wn(l)}${d}
25
- ${Vn(l)}`;if(!e.dryRun){let m=A.dirname(o);if(!re.existsSync(m))re.mkdirSync(m,{recursive:!0});re.writeFileSync(o,p,"utf-8"),Di.success(`[generate:db-types] wrote ${u.length} table(s) to ${o}`)}return{outFile:o,tables:u,errors:i,content:p}}function Ji(e,n="app"){let t=[...e].sort((r,o)=>r.table.localeCompare(o.table)).map((r)=>Kn(r.table,r.columns,n==="framework"?1:2)).join(`
26
- `);return`${Wn(n)}${t}
27
- ${Vn(n)}`}import{isCursorPaginator as Bl,isPaginator as Nl,isSimplePaginator as Ll,toCursorPaginator as ql,toPaginator as Gl,toSimplePaginator as Ul}from"@stacksjs/pagination";import{configureOrm as Yi}from"@stacksjs/query-builder";function Xi(){try{let e=process.env.DB_DATABASE_PATH||"database/stacks.sqlite";if((process.env.DB_CONNECTION||"sqlite")==="sqlite")Yi({database:e})}catch{}}Xi();async function zn(e){for(let n=0;;n++){let t=await import(e);try{return t.default}catch(r){if(n<5&&r instanceof ReferenceError&&/before initialization/.test(r.message)){await new Promise((o)=>setTimeout(o,0));continue}throw r}}}var Hn=!1;async function xe(e,n=[""]){if(gt()){if(!Hn)Hn=!0,console.debug("[orm] running from a compiled binary, so framework default models are not probed on disk; models this app uses are bundled.");return null}let{path:t}=await import("@stacksjs/path"),r=t.userModelsPath(`${e}.ts`);try{if(await Bun.file(r).exists())return await zn(r)}catch(o){console.error(`[orm] Failed to import userland model ${e} from ${r} - falling back to framework default. Reason:`,o)}for(let o of n){let i=o?`${o}/`:"",a=t.frameworkPath(`defaults/app/Models/${i}${e}.ts`);try{if(await Bun.file(a).exists())return await zn(a)}catch(s){console.error(`[orm] Failed to import framework default model ${e} from ${a} - trying next subdir. Reason:`,s)}}return null}var j={},Jn=()=>{},al=new Promise((e)=>{Jn=e});function y(e){return new Proxy(function(){},{get(n,t){if(t==="then")return;let r=j[e];if(r==null)return;let o=r[t];return typeof o==="function"?o.bind(r):o},set(n,t,r){let o=j[e];if(o==null)return!1;return o[t]=r,!0},has(n,t){let r=j[e];return r==null?!1:(t in r)},apply(n,t,r){let o=j[e];if(o==null||typeof o!=="function")return;return o.apply(t,r)}})}var Zi=y("User"),ea=y("Job"),ta=y("FailedJob"),na=[["Referral",[""],"auth"],["ReferralCode",[""],"auth"],["Team",[""],"auth"],["TeamInvitation",[""],"auth"],["TeamMember",[""],"auth"],["SocialAccount",[""],"auth"],["Subscriber",[""],"auth"],["SubscriberEmail",[""],"auth"],["Subscription",[""],"auth"],["Categorizable",["Content"],"cms"],["Post",["Content"],"cms"],["Page",["Content"],"cms"],["PageRevision",["Content"],"cms"],["Redirect",["Content"],"cms"],["Menu",["Content"],"cms"],["MenuItem",["Content"],"cms"],["Author",["Content"],"cms"],["Comment",[""],"cms"],["Tag",[""],"cms"],["Site",[""],"auth"],["SiteDomain",[""],"auth"],["MagicLinkToken",[""],"auth"],["SmsOptOut",[""],"auth"],["GdprRequest",[""],"auth"],["Form",["Forms"],"forms"],["FormField",["Forms"],"forms"],["FormSubmission",["Forms"],"forms"],["Activity",[""],"dashboard"],["Board",[""],"dashboard"],["BoardColumn",[""],"dashboard"],["Card",[""],"dashboard"],["CardAttachment",[""],"dashboard"],["CardComment",[""],"dashboard"],["Deployment",[""],"dashboard"],["FeedbackToken",[""],"dashboard"],["Label",[""],"dashboard"],["Release",[""],"dashboard"],["Notification",[""],"dashboard"],["NotificationDelivery",[""],"dashboard"],["PersonalAccessToken",[""],"dashboard"],["MailPreference",[""],"dashboard"],["Log",[""],"dashboard"],["Request",[""],"dashboard"],["AnalyticsEvent",[""],"dashboard"],["QueryLog",[""],"dashboard"],["StorageItem",[""],"dashboard"],["StorageItemTask",[""],"dashboard"],["Error",[""],"monitoring"],["Websocket",["realtime"],"realtime"],["Campaign",[""],"marketing"],["CampaignSend",[""],"marketing"],["EmailList",[""],"marketing"],["EmailListSubscriber",[""],"marketing"],["EmailIdempotency",[""],"marketing"],["EmailSuppression",[""],"marketing"],["EmailWebhookEvent",[""],"marketing"],["SocialPost",[""],"marketing"],["Automation",[""],"marketing"],["AutomationRun",[""],"marketing"],["CampaignVariant",[""],"marketing"],["CommunicationSuppression",[""],"marketing"],["ConsentEvent",[""],"marketing"],["SenderDomain",[""],"marketing"],["UsageEvent",[""],"marketing"],["PaymentMethod",[""],"commerce"],["PaymentProduct",[""],"commerce"],["PaymentTransaction",[""],"commerce"],["Order",["commerce"],"commerce"],["OrderIdempotency",["commerce"],"commerce"],["OrderItem",["commerce"],"commerce"],["Cart",["commerce"],"commerce"],["CartItem",["commerce"],"commerce"],["Customer",["commerce"],"commerce"],["Product",["commerce"],"commerce"],["ProductVariant",["commerce"],"commerce"],["ProductUnit",["commerce"],"commerce"],["Manufacturer",["commerce"],"commerce"],["Category",["commerce"],"commerce"],["Coupon",["commerce"],"commerce"],["GiftCard",["commerce"],"commerce"],["LicenseKey",["commerce"],"commerce"],["Review",["commerce"],"commerce"],["Receipt",["commerce"],"commerce"],["PrintDevice",["commerce"],"commerce"],["ShippingMethod",["commerce"],"commerce"],["ShippingRate",["commerce"],"commerce"],["ShippingZone",["commerce"],"commerce"],["DeliveryRoute",["commerce"],"commerce"],["DeliveryStop",["commerce"],"commerce"],["DigitalDelivery",["commerce"],"commerce"],["Courier",["commerce"],"commerce"],["CourierPing",["commerce"],"commerce"],["TaxRate",["commerce"],"commerce"],["WaitlistProduct",["commerce"],"commerce"],["WaitlistRestaurant",["commerce"],"commerce"],["Auction",["commerce"],"commerce"],["AuctionItem",["commerce"],"commerce"],["Bid",["commerce"],"commerce"],["Pledge",["commerce"],"commerce"],["LoyaltyPoint",["commerce"],"commerce"],["LoyaltyReward",["commerce"],"commerce"],["Payment",["commerce"],"commerce"],["PaymentWebhookEvent",["commerce"],"commerce"],["Transaction",["commerce"],"commerce"]];queueMicrotask(async()=>{try{let{feature:e}=await import("@stacksjs/config"),n=await xe("User");if(n)j.User=n;if(e("queue")){let t=await xe("Job");if(t)j.Job=t;let r=await xe("FailedJob");if(r)j.FailedJob=r}for(let[t,r,o]of na){if(!e(o))continue;let i=await xe(t,r);if(i)j[t]=i}}catch(e){console.error("[orm] deferred model load failed:",e)}finally{Jn()}});var ra=y("Activity"),oa=y("AnalyticsEvent"),ia=y("Automation"),aa=y("AutomationRun"),sa=y("Auction"),ua=y("CampaignVariant"),ca=y("CommunicationSuppression"),la=y("ConsentEvent"),da=y("SenderDomain"),fa=y("UsageEvent"),pa=y("AuctionItem"),ma=y("Author"),ga=y("Bid"),ya=y("Board"),wa=y("BoardColumn"),ba=y("Campaign"),ha=y("Card"),sl=y("CardAttachment"),ka=y("CardComment"),Ta=y("Cart"),Ra=y("CartItem"),Sa=y("Category"),_a=y("Comment"),Aa=y("Coupon"),Pa=y("Customer"),xa=y("DeliveryRoute"),Ca=y("DeliveryStop"),va=y("Deployment"),ul=y("FeedbackToken"),Ma=y("DigitalDelivery"),Oa=y("Courier"),Da=y("CourierPing"),Ea=y("CampaignSend"),ja=y("EmailList"),Fa=y("EmailListSubscriber"),$a=y("Form"),Ia=y("FormField"),Ba=y("FormSubmission"),Na=y("MagicLinkToken"),La=y("Menu"),qa=y("MenuItem"),Ga=y("PageRevision"),Ua=y("Pledge"),Ka=y("Redirect"),Wa=y("Site"),Va=y("SiteDomain"),Qa=y("SmsOptOut"),za=y("GdprRequest"),cl=y("StorageItem"),ll=y("StorageItemTask"),Ha=y("EmailIdempotency"),Ja=y("EmailSuppression"),Ya=y("EmailWebhookEvent"),Xa=y("Error"),Za=y("GiftCard"),es=y("Label"),ts=y("LicenseKey"),ns=y("Log"),rs=y("LoyaltyPoint"),os=y("LoyaltyReward"),is=y("MailPreference"),as=y("Manufacturer"),ss=y("Notification"),us=y("NotificationDelivery"),cs=y("Order"),ls=y("OrderIdempotency"),dl=y("PersonalAccessToken"),ds=y("OrderItem"),fs=y("Page"),ps=y("Payment"),ms=y("PaymentWebhookEvent"),gs=y("PaymentMethod"),ys=y("PaymentProduct"),ws=y("PaymentTransaction"),bs=y("Post"),hs=y("Categorizable"),ks=y("PrintDevice"),Ts=y("Product"),Rs=y("ProductUnit"),Ss=y("ProductVariant"),_s=y("QueryLog"),As=y("Receipt"),fl=y("Referral"),pl=y("ReferralCode"),Ps=y("Release"),xs=y("Request"),Cs=y("Review"),vs=y("ShippingMethod"),Ms=y("ShippingRate"),Os=y("ShippingZone"),Ds=y("SocialPost"),Es=y("SocialAccount"),js=y("Subscriber"),Fs=y("SubscriberEmail"),$s=y("Subscription"),Is=y("Tag"),Bs=y("TaxRate"),Ns=y("Team"),Ls=y("TeamInvitation"),qs=y("TeamMember"),Gs=y("Transaction"),Us=y("WaitlistProduct"),Ks=y("WaitlistRestaurant"),Ws=y("Websocket"),Yn={User:Zi,Job:ea,FailedJob:ta,Activity:ra,AnalyticsEvent:oa,Automation:ia,AutomationRun:aa,Auction:sa,AuctionItem:pa,Author:ma,Bid:ga,Board:ya,BoardColumn:wa,Campaign:ba,CampaignSend:Ea,CampaignVariant:ua,Card:ha,CardComment:ka,Cart:Ta,CartItem:Ra,Categorizable:hs,Category:Sa,Comment:_a,Coupon:Aa,Customer:Pa,CommunicationSuppression:ca,ConsentEvent:la,DeliveryRoute:xa,DeliveryStop:Ca,Deployment:va,DigitalDelivery:Ma,Courier:Oa,CourierPing:Da,EmailList:ja,EmailListSubscriber:Fa,EmailIdempotency:Ha,EmailSuppression:Ja,EmailWebhookEvent:Ya,ErrorModel:Xa,Form:$a,FormField:Ia,FormSubmission:Ba,GdprRequest:za,GiftCard:Za,Label:es,LicenseKey:ts,Log:ns,LoyaltyPoint:rs,LoyaltyReward:os,MailPreference:is,Manufacturer:as,Notification:ss,MagicLinkToken:Na,Menu:La,MenuItem:qa,NotificationDelivery:us,Order:cs,OrderIdempotency:ls,OrderItem:ds,Page:fs,PageRevision:Ga,Payment:ps,PaymentMethod:gs,PaymentProduct:ys,PaymentTransaction:ws,PaymentWebhookEvent:ms,Pledge:Ua,Post:bs,PrintDevice:ks,Product:Ts,ProductUnit:Rs,ProductVariant:Ss,QueryLog:_s,Receipt:As,Release:Ps,Request:xs,Review:Cs,ShippingMethod:vs,Redirect:Ka,SenderDomain:da,ShippingRate:Ms,ShippingZone:Os,Site:Wa,SiteDomain:Va,SmsOptOut:Qa,SocialAccount:Es,SocialPost:Ds,Subscriber:js,SubscriberEmail:Fs,Subscription:$s,Tag:Is,TaxRate:Bs,Team:Ns,TeamInvitation:Ls,TeamMember:qs,Transaction:Gs,UsageEvent:fa,WaitlistProduct:Us,WaitlistRestaurant:Ks,Websocket:Ws},W=globalThis;for(let[e,n]of Object.entries(Yn))if(n&&W[e]===void 0)W[e]=n;var ml=Object.keys(Yn);async function Vs(e){if(!e)return[];try{if(typeof e.all==="function"){let n=await e.all();return Array.isArray(n)?n:[]}if(typeof e.get==="function"){let n=await e.get();return Array.isArray(n)?n:[]}}catch{}return[]}function Qs(e,n,t=""){if(!e)return t;try{if(typeof e.get==="function"){let o=e.get(n);if(o!==void 0&&o!==null)return o}}catch{}let r=e?.[n];return r!==void 0&&r!==null?r:t}if(W.safeAll===void 0)W.safeAll=Vs;if(W.safeGet===void 0)W.safeGet=Qs;export{ra as Activity,oa as AnalyticsEvent,sa as Auction,pa as AuctionItem,ma as Author,ia as Automation,aa as AutomationRun,de as BILLABLE_INSTANCE_METHODS,ga as Bid,ya as Board,wa as BoardColumn,ba as Campaign,Ea as CampaignSend,ua as CampaignVariant,ha as Card,sl as CardAttachment,ka as CardComment,Ta as Cart,Ra as CartItem,hs as Categorizable,Sa as Category,_a as Comment,ca as CommunicationSuppression,la as ConsentEvent,Aa as Coupon,Oa as Courier,Da as CourierPing,Pa as Customer,xa as DeliveryRoute,Ca as DeliveryStop,va as Deployment,Ma as DigitalDelivery,Ha as EmailIdempotency,ja as EmailList,Fa as EmailListSubscriber,Ja as EmailSuppression,Ya as EmailWebhookEvent,Xa as ErrorModel,ta as FailedJob,ul as FeedbackToken,$a as Form,Ia as FormField,Ba as FormSubmission,ye as GDPR_AUDIT_TABLE,D as GDPR_SUBJECT_MODEL,We as GdprDeclarationError,za as GdprRequest,we as GdprSubjectNotFoundError,Za as GiftCard,ea as Job,es as Label,ts as LicenseKey,ns as Log,rs as LoyaltyPoint,os as LoyaltyReward,pt as MODEL_DEFINITION,Na as MagicLinkToken,is as MailPreference,as as Manufacturer,dt as MassAssignmentException,La as Menu,qa as MenuItem,$n as ModelNotFoundError,Dn as ModelValidationError,ss as Notification,us as NotificationDelivery,cs as Order,ls as OrderIdempotency,ds as OrderItem,fs as Page,Ga as PageRevision,ps as Payment,gs as PaymentMethod,ys as PaymentProduct,ws as PaymentTransaction,ms as PaymentWebhookEvent,dl as PersonalAccessToken,Ua as Pledge,bs as Post,ks as PrintDevice,Ts as Product,Rs as ProductUnit,Ss as ProductVariant,_s as QueryLog,As as Receipt,Ka as Redirect,fl as Referral,pl as ReferralCode,Ps as Release,xs as Request,Cs as Review,da as SenderDomain,vs as ShippingMethod,Ms as ShippingRate,Os as ShippingZone,Wa as Site,Va as SiteDomain,Qa as SmsOptOut,Es as SocialAccount,Ds as SocialPost,cl as StorageItem,ll as StorageItemTask,Zr as SubqueryBuilder,js as Subscriber,Fs as SubscriberEmail,$s as Subscription,Le as SubscriptionNotOwnedError,Is as Tag,Bs as TaxRate,Ns as Team,Ls as TeamInvitation,qs as TeamMember,Gs as Transaction,fa as UsageEvent,Zi as User,Us as WaitlistProduct,Ks as WaitlistRestaurant,Ws as Websocket,ge as assertGdprPlan,Lu as batchLoad,Hi as buildDatabaseSchema,xo as buildProcessingRegister,De as collectEncryptedAttributes,St as createAuditMethods,Be as createCategorizableMethods,Fe as createCommentableMethods,Ne as createLikeableMethods,Ie as createTaggableMethods,Wr as customerOwnership,Ku as db,Oe as decryptValue,Nn as defineModel,Me as encryptValue,it as enrichPaginatorUrls,So as eraseSubject,To as exportSubjectData,Vc as extendModel,xr as filterFillable,he as gdprTableExists,Kt as gdprTableName,Zs as getPrunableConfig,Pr as getWritableFields,Rr as isBillable,Bl as isCursorPaginator,Q as isEncrypted,Nl as isPaginator,Ll as isSimplePaginator,Ur as isUniqueViolation,Ve as loadGdprModels,_r as mapWriteError,Xs as massPrunable,_i as mergeModelDefinition,ml as modelGlobalNames,al as ormReady,Hr as parentOwnership,rn as parseCursor,ft as projectDocumentsFromTrait,er as prunable,Ao as pruneRetainedData,Ji as renderDatabaseTypeFile,Co as renderProcessingRegister,ot as resolveCursorArgs,me as resolveGdprPlan,wo as resolveGdprSubject,rt as resolvePageArgs,Qu as savepoint,Vr as selfOwnership,ur as setAuditUser,Qr as siteOwnership,zr as teamMembershipOwnership,bi as toAttrs,ql as toCursorPaginator,Gl as toPaginator,Ul as toSimplePaginator,Ar as toSnakeCaseKeys,Ke as transaction,zu as transactional,B as withoutEvents,Qo as withoutValidation};
1
+ import"@stacksjs/validation/runtime";import{isCompiledBinary}from"./utils/compiled-binary";export*from"./utils/prunable";export{collectEncryptedAttributes,decryptValue,encryptValue,isEncrypted}from"./utils/encrypted";export{setAuditUser,createAuditMethods}from"./traits/audit";export{createCommentableMethods}from"./traits/commentable";export{createTaggableMethods}from"./traits/taggable";export{createCategorizableMethods}from"./traits/categorizable";export{createLikeableMethods}from"./traits/likeable";export{BILLABLE_INSTANCE_METHODS,isBillable,SubscriptionNotOwnedError}from"./traits/billable";export{filterFillable,getWritableFields,isUniqueViolation,mapWriteError,toSnakeCaseKeys}from"./auto-crud";export{customerOwnership,parentOwnership,selfOwnership,siteOwnership,teamMembershipOwnership}from"./ownership";export*from"./batch-loader";export*from"./db";export*from"./subquery";export*from"./transaction";export*from"./gdpr";export*from"./model-types";export*from"./types";export*from"@stacksjs/model-meta";export*from"./define-model";export*from"./extend-model";export{buildDatabaseSchema,renderDatabaseTypeFile}from"./generate-database-schema";export{isCursorPaginator,isPaginator,isSimplePaginator,toCursorPaginator,toPaginator,toSimplePaginator}from"@stacksjs/pagination";export{enrichPaginatorUrls,parseCursor,resolveCursorArgs,resolvePageArgs}from"./paginator-request";import{configureOrm}from"@stacksjs/query-builder";function autoConfigureOrm(){try{const dbPath=process.env.DB_DATABASE_PATH||"database/stacks.sqlite";if((process.env.DB_CONNECTION||"sqlite")==="sqlite")configureOrm({database:dbPath})}catch{}}autoConfigureOrm();async function importDefault(modulePath){for(let attempt=0;;attempt++){const mod=await import(modulePath);try{return mod.default}catch(err){if(attempt<5&&err instanceof ReferenceError&&/before initialization/.test(err.message)){await new Promise((resolve)=>setTimeout(resolve,0));continue}throw err}}}let announcedCompiledSkip=!1;async function loadUserlandModel(modelName,subdirs=[""]){if(isCompiledBinary()){if(!announcedCompiledSkip){announcedCompiledSkip=!0;console.debug("[orm] running from a compiled binary, so framework default models are not probed on disk; models this app uses are bundled.")}return null}const{path}=await import("@stacksjs/path"),userPath=path.userModelsPath(`${modelName}.ts`);try{if(await Bun.file(userPath).exists())return await importDefault(userPath)}catch(err){console.error(`[orm] Failed to import userland model ${modelName} from ${userPath} - falling back to framework default. Reason:`,err)}for(const sub of subdirs){const prefix=sub?`${sub}/`:"",defaultPath=path.frameworkPath(`defaults/app/Models/${prefix}${modelName}.ts`);try{if(await Bun.file(defaultPath).exists())return await importDefault(defaultPath)}catch(err){console.error(`[orm] Failed to import framework default model ${modelName} from ${defaultPath} - trying next subdir. Reason:`,err)}}return null}const _loaded={};let _readyResolve=()=>{};export const ormReady=new Promise((resolve)=>{_readyResolve=resolve});function lazyModel(name){return new Proxy(function _modelStub(){},{get(_target,prop){if(prop==="then")return;const m=_loaded[name];if(m==null)return;const value=m[prop];return typeof value==="function"?value.bind(m):value},set(_target,prop,value){const m=_loaded[name];if(m==null)return!1;m[prop]=value;return!0},has(_target,prop){const m=_loaded[name];return m==null?!1:(prop in m)},apply(_target,thisArg,args){const m=_loaded[name];if(m==null||typeof m!=="function")return;return m.apply(thisArg,args)}})}export const User=lazyModel("User"),Job=lazyModel("Job"),FailedJob=lazyModel("FailedJob");const FRAMEWORK_MODEL_MANIFEST=[["Referral",[""],"auth"],["ReferralCode",[""],"auth"],["Team",[""],"auth"],["TeamInvitation",[""],"auth"],["TeamMember",[""],"auth"],["SocialAccount",[""],"auth"],["Subscriber",[""],"auth"],["SubscriberEmail",[""],"auth"],["Subscription",[""],"auth"],["Categorizable",["Content"],"cms"],["Post",["Content"],"cms"],["Page",["Content"],"cms"],["PageRevision",["Content"],"cms"],["Redirect",["Content"],"cms"],["Menu",["Content"],"cms"],["MenuItem",["Content"],"cms"],["Author",["Content"],"cms"],["Comment",[""],"cms"],["Tag",[""],"cms"],["Site",[""],"auth"],["SiteDomain",[""],"auth"],["MagicLinkToken",[""],"auth"],["SmsOptOut",[""],"auth"],["GdprRequest",[""],"auth"],["Form",["Forms"],"forms"],["FormField",["Forms"],"forms"],["FormSubmission",["Forms"],"forms"],["Activity",[""],"dashboard"],["Board",[""],"dashboard"],["BoardColumn",[""],"dashboard"],["Card",[""],"dashboard"],["CardAttachment",[""],"dashboard"],["CardComment",[""],"dashboard"],["Deployment",[""],"dashboard"],["FeedbackToken",[""],"dashboard"],["Label",[""],"dashboard"],["Release",[""],"dashboard"],["Notification",[""],"dashboard"],["NotificationDelivery",[""],"dashboard"],["PersonalAccessToken",[""],"dashboard"],["MailPreference",[""],"dashboard"],["Log",[""],"dashboard"],["Request",[""],"dashboard"],["AnalyticsEvent",[""],"dashboard"],["QueryLog",[""],"dashboard"],["StorageItem",[""],"dashboard"],["StorageItemTask",[""],"dashboard"],["Error",[""],"monitoring"],["Websocket",["realtime"],"realtime"],["Campaign",[""],"marketing"],["CampaignSend",[""],"marketing"],["EmailList",[""],"marketing"],["EmailListSubscriber",[""],"marketing"],["EmailIdempotency",[""],"marketing"],["EmailSuppression",[""],"marketing"],["EmailWebhookEvent",[""],"marketing"],["SocialPost",[""],"marketing"],["Automation",[""],"marketing"],["AutomationRun",[""],"marketing"],["CampaignVariant",[""],"marketing"],["CommunicationSuppression",[""],"marketing"],["ConsentEvent",[""],"marketing"],["SenderDomain",[""],"marketing"],["UsageEvent",[""],"marketing"],["PaymentMethod",[""],"commerce"],["PaymentProduct",[""],"commerce"],["PaymentTransaction",[""],"commerce"],["Order",["commerce"],"commerce"],["OrderIdempotency",["commerce"],"commerce"],["OrderItem",["commerce"],"commerce"],["Cart",["commerce"],"commerce"],["CartItem",["commerce"],"commerce"],["Customer",["commerce"],"commerce"],["Product",["commerce"],"commerce"],["ProductVariant",["commerce"],"commerce"],["ProductUnit",["commerce"],"commerce"],["Manufacturer",["commerce"],"commerce"],["Category",["commerce"],"commerce"],["Coupon",["commerce"],"commerce"],["GiftCard",["commerce"],"commerce"],["LicenseKey",["commerce"],"commerce"],["Review",["commerce"],"commerce"],["Receipt",["commerce"],"commerce"],["PrintDevice",["commerce"],"commerce"],["ShippingMethod",["commerce"],"commerce"],["ShippingRate",["commerce"],"commerce"],["ShippingZone",["commerce"],"commerce"],["DeliveryRoute",["commerce"],"commerce"],["DeliveryStop",["commerce"],"commerce"],["DigitalDelivery",["commerce"],"commerce"],["Courier",["commerce"],"commerce"],["CourierPing",["commerce"],"commerce"],["TaxRate",["commerce"],"commerce"],["WaitlistProduct",["commerce"],"commerce"],["WaitlistRestaurant",["commerce"],"commerce"],["Auction",["commerce"],"commerce"],["AuctionItem",["commerce"],"commerce"],["Bid",["commerce"],"commerce"],["Pledge",["commerce"],"commerce"],["LoyaltyPoint",["commerce"],"commerce"],["LoyaltyReward",["commerce"],"commerce"],["Payment",["commerce"],"commerce"],["PaymentWebhookEvent",["commerce"],"commerce"],["Transaction",["commerce"],"commerce"]];queueMicrotask(async()=>{try{const{feature}=await import("@stacksjs/config"),userModel=await loadUserlandModel("User");if(userModel)_loaded.User=userModel;if(feature("queue")){const job=await loadUserlandModel("Job");if(job)_loaded.Job=job;const failedJob=await loadUserlandModel("FailedJob");if(failedJob)_loaded.FailedJob=failedJob}for(const[name,subdirs,featureFlag]of FRAMEWORK_MODEL_MANIFEST){if(!feature(featureFlag))continue;const M=await loadUserlandModel(name,subdirs);if(M)_loaded[name]=M}}catch(err){console.error("[orm] deferred model load failed:",err)}finally{_readyResolve()}});export const Activity=lazyModel("Activity"),AnalyticsEvent=lazyModel("AnalyticsEvent"),Automation=lazyModel("Automation"),AutomationRun=lazyModel("AutomationRun"),Auction=lazyModel("Auction"),CampaignVariant=lazyModel("CampaignVariant"),CommunicationSuppression=lazyModel("CommunicationSuppression"),ConsentEvent=lazyModel("ConsentEvent"),SenderDomain=lazyModel("SenderDomain"),UsageEvent=lazyModel("UsageEvent"),AuctionItem=lazyModel("AuctionItem"),Author=lazyModel("Author"),Bid=lazyModel("Bid"),Board=lazyModel("Board"),BoardColumn=lazyModel("BoardColumn"),Campaign=lazyModel("Campaign"),Card=lazyModel("Card"),CardAttachment=lazyModel("CardAttachment"),CardComment=lazyModel("CardComment"),Cart=lazyModel("Cart"),CartItem=lazyModel("CartItem"),Category=lazyModel("Category"),Comment=lazyModel("Comment"),Coupon=lazyModel("Coupon"),Customer=lazyModel("Customer"),DeliveryRoute=lazyModel("DeliveryRoute"),DeliveryStop=lazyModel("DeliveryStop"),Deployment=lazyModel("Deployment"),FeedbackToken=lazyModel("FeedbackToken"),DigitalDelivery=lazyModel("DigitalDelivery"),Courier=lazyModel("Courier"),CourierPing=lazyModel("CourierPing"),CampaignSend=lazyModel("CampaignSend"),EmailList=lazyModel("EmailList"),EmailListSubscriber=lazyModel("EmailListSubscriber"),Form=lazyModel("Form"),FormField=lazyModel("FormField"),FormSubmission=lazyModel("FormSubmission"),MagicLinkToken=lazyModel("MagicLinkToken"),Menu=lazyModel("Menu"),MenuItem=lazyModel("MenuItem"),PageRevision=lazyModel("PageRevision"),Pledge=lazyModel("Pledge"),Redirect=lazyModel("Redirect"),Site=lazyModel("Site"),SiteDomain=lazyModel("SiteDomain"),SmsOptOut=lazyModel("SmsOptOut"),GdprRequest=lazyModel("GdprRequest"),StorageItem=lazyModel("StorageItem"),StorageItemTask=lazyModel("StorageItemTask"),EmailIdempotency=lazyModel("EmailIdempotency"),EmailSuppression=lazyModel("EmailSuppression"),EmailWebhookEvent=lazyModel("EmailWebhookEvent"),ErrorModel=lazyModel("Error"),GiftCard=lazyModel("GiftCard"),Label=lazyModel("Label"),LicenseKey=lazyModel("LicenseKey"),Log=lazyModel("Log"),LoyaltyPoint=lazyModel("LoyaltyPoint"),LoyaltyReward=lazyModel("LoyaltyReward"),MailPreference=lazyModel("MailPreference"),Manufacturer=lazyModel("Manufacturer"),Notification=lazyModel("Notification"),NotificationDelivery=lazyModel("NotificationDelivery"),Order=lazyModel("Order"),OrderIdempotency=lazyModel("OrderIdempotency"),PersonalAccessToken=lazyModel("PersonalAccessToken"),OrderItem=lazyModel("OrderItem"),Page=lazyModel("Page"),Payment=lazyModel("Payment"),PaymentWebhookEvent=lazyModel("PaymentWebhookEvent"),PaymentMethod=lazyModel("PaymentMethod"),PaymentProduct=lazyModel("PaymentProduct"),PaymentTransaction=lazyModel("PaymentTransaction"),Post=lazyModel("Post"),Categorizable=lazyModel("Categorizable"),PrintDevice=lazyModel("PrintDevice"),Product=lazyModel("Product"),ProductUnit=lazyModel("ProductUnit"),ProductVariant=lazyModel("ProductVariant"),QueryLog=lazyModel("QueryLog"),Receipt=lazyModel("Receipt"),Referral=lazyModel("Referral"),ReferralCode=lazyModel("ReferralCode"),Release=lazyModel("Release"),Request=lazyModel("Request"),Review=lazyModel("Review"),ShippingMethod=lazyModel("ShippingMethod"),ShippingRate=lazyModel("ShippingRate"),ShippingZone=lazyModel("ShippingZone"),SocialPost=lazyModel("SocialPost"),SocialAccount=lazyModel("SocialAccount"),Subscriber=lazyModel("Subscriber"),SubscriberEmail=lazyModel("SubscriberEmail"),Subscription=lazyModel("Subscription"),Tag=lazyModel("Tag"),TaxRate=lazyModel("TaxRate"),Team=lazyModel("Team"),TeamInvitation=lazyModel("TeamInvitation"),TeamMember=lazyModel("TeamMember"),Transaction=lazyModel("Transaction"),WaitlistProduct=lazyModel("WaitlistProduct"),WaitlistRestaurant=lazyModel("WaitlistRestaurant"),Websocket=lazyModel("Websocket");const _allExports={User,Job,FailedJob,Activity,AnalyticsEvent,Automation,AutomationRun,Auction,AuctionItem,Author,Bid,Board,BoardColumn,Campaign,CampaignSend,CampaignVariant,Card,CardComment,Cart,CartItem,Categorizable,Category,Comment,Coupon,Customer,CommunicationSuppression,ConsentEvent,DeliveryRoute,DeliveryStop,Deployment,DigitalDelivery,Courier,CourierPing,EmailList,EmailListSubscriber,EmailIdempotency,EmailSuppression,EmailWebhookEvent,ErrorModel,Form,FormField,FormSubmission,GdprRequest,GiftCard,Label,LicenseKey,Log,LoyaltyPoint,LoyaltyReward,MailPreference,Manufacturer,Notification,MagicLinkToken,Menu,MenuItem,NotificationDelivery,Order,OrderIdempotency,OrderItem,Page,PageRevision,Payment,PaymentMethod,PaymentProduct,PaymentTransaction,PaymentWebhookEvent,Pledge,Post,PrintDevice,Product,ProductUnit,ProductVariant,QueryLog,Receipt,Release,Request,Review,ShippingMethod,Redirect,SenderDomain,ShippingRate,ShippingZone,Site,SiteDomain,SmsOptOut,SocialAccount,SocialPost,Subscriber,SubscriberEmail,Subscription,Tag,TaxRate,Team,TeamInvitation,TeamMember,Transaction,UsageEvent,WaitlistProduct,WaitlistRestaurant,Websocket},g=globalThis;for(const[name,M]of Object.entries(_allExports))if(M&&g[name]===void 0)g[name]=M;export const modelGlobalNames=Object.keys(_allExports);async function _safeAll(M){if(!M)return[];try{if(typeof M.all==="function"){const rows=await M.all();return Array.isArray(rows)?rows:[]}if(typeof M.get==="function"){const rows=await M.get();return Array.isArray(rows)?rows:[]}}catch{}return[]}function _safeGet(row,key,fallback=""){if(!row)return fallback;try{if(typeof row.get==="function"){const v=row.get(key);if(v!==void 0&&v!==null)return v}}catch{}const direct=row?.[key];return direct!==void 0&&direct!==null?direct:fallback}if(g.safeAll===void 0)g.safeAll=_safeAll;if(g.safeGet===void 0)g.safeGet=_safeGet;
@@ -0,0 +1 @@
1
+ import{Database}from"bun:sqlite";import{existsSync,readdirSync,readFileSync}from"node:fs";function isInternalTable(name){return name.startsWith("sqlite_")||name.startsWith("_qb_tmp_")}function sqliteTypeToTs(declared,dialect){const type=declared.toUpperCase();if(type.includes("BOOL"))return dialect==="postgres"?"boolean":"number";if(type.includes("DATE")||type.includes("TIME"))return"string";if(type.includes("INT"))return"number";if(type.includes("CHAR")||type.includes("CLOB")||type.includes("TEXT"))return"string";if(type.includes("REAL")||type.includes("FLOA")||type.includes("DOUB")||type.includes("NUMERIC")||type.includes("DEC"))return"number";if(type.includes("BLOB"))return"Uint8Array";return"unknown"}function applyMigration(db,sql){try{db.exec(sql);return{ok:!0}}catch(err){if(/CREATE\s+TRIGGER/i.test(sql))return{ok:!1,error:err.message};let applied=0;for(const statement of sql.split(/;\s*$/m)){if(!statement.trim())continue;try{db.exec(statement);applied++}catch(statementError){if(/duplicate column name/i.test(statementError.message))applied++}}return applied>0?{ok:!0}:{ok:!1,error:err.message}}}export function deriveMigrationTables(migrationsDir,dialect="sqlite"){const errors=[];if(!existsSync(migrationsDir))return{tables:[],errors};let files;try{files=readdirSync(migrationsDir).filter((name)=>name.endsWith(".sql")).sort()}catch(err){return{tables:[],errors:[{file:migrationsDir,error:err.message}]}}const db=new Database(":memory:");try{for(const file of files){const full=`${migrationsDir}/${file}`;let sql;try{sql=readFileSync(full,"utf-8")}catch(err){errors.push({file:full,error:err.message});continue}const result=applyMigration(db,sql);if(!result.ok)errors.push({file:full,error:result.error??"could not be applied"})}const names=db.query("SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name").all().map((row)=>row.name).filter((name)=>!isInternalTable(name)),tables=[];for(const name of names){const info=db.query(`PRAGMA table_info("${name.replace(/"/g,'""')}")`).all();if(info.length===0)continue;const columns={};for(const column of info){const base=sqliteTypeToTs(column.type??"",dialect),nullable=column.notnull===0&&column.pk===0;columns[column.name]=nullable&&base!=="unknown"?`${base} | null`:base}tables.push({table:name,columns})}return{tables,errors}}finally{db.close()}}
@@ -1,2 +1 @@
1
- // @bun
2
- var f=(e,o,n)=>()=>{if(e)try{o=e(e=0)}catch(i){n=[i]}if(n)throw n[0];return o};var R=import.meta.require;import{readdirSync as m}from"fs";import{basename as p,extname as c,join as u}from"path";function g(e){let o=[],n=(i)=>{let t;try{t=m(i,{withFileTypes:!0})}catch{return}for(let r of t){let s=u(i,r.name);if(r.isDirectory()){n(s);continue}if(![".ts",".js"].includes(c(r.name)))continue;if(r.name.startsWith(".")||r.name.startsWith("index"))continue;o.push(s)}};return n(e),o.sort()}async function d(e,o,n,i){for(let t of g(e))try{let r=c(t),s=await import(`${t}?t=${Date.now()}`),l=s.default??s,a=l.name??p(t,r);n.models[a]={...l,name:a},n.origins[a]=o}catch(r){i?.(t,r)}}async function y(e){let o={models:{},origins:{}};return await d(e.defaultsRoot,"default",o,e.onImportError),await d(e.userRoot,"app",o,e.onImportError),o}async function x(e){return(await y(e)).models}function A(e,o){let n,i="default";if(o!==void 0&&o!==null)n=o.split(","),i="env";else if(typeof e==="string")n=[e],i="config";else if(Array.isArray(e)&&e.every((r)=>typeof r==="string"))n=e,i="config";if(n===void 0)return{all:!0,own:!1,names:new Set,source:i};let t=n.map((r)=>r.trim().toLowerCase()).filter(Boolean);if(t.length===0||t.includes("none"))return{all:!1,own:!1,names:new Set,source:i};if(t.includes("all"))return{all:!0,own:!1,names:new Set,source:i};return{all:!1,own:t.includes("own"),names:new Set(t.filter((r)=>r!=="own")),source:i}}function v(e,o){let n={},i=new Set;for(let[t,r]of Object.entries(e.models)){if(!r?.traits?.useApi)continue;let s=t.toLowerCase(),l=o.names.has(s);if(l)i.add(s);if(o.all||l||o.own&&e.origins[t]==="app")n[t]=r}return{models:n,unmatched:[...o.names].filter((t)=>!i.has(t)).sort()}}var w=()=>{};w();export{x as loadModelRegistry,y as loadModelRegistryWithOrigins,g as modelFiles,A as resolveModelApiSelection,v as selectApiModels};
1
+ import{readdirSync}from"node:fs";import{basename,extname,join}from"node:path";export function modelFiles(root){const files=[],walk=(directory)=>{let entries;try{entries=readdirSync(directory,{withFileTypes:!0})}catch{return}for(const entry of entries){const file=join(directory,entry.name);if(entry.isDirectory()){walk(file);continue}if(![".ts",".js"].includes(extname(entry.name)))continue;if(entry.name.startsWith(".")||entry.name.startsWith("index"))continue;files.push(file)}};walk(root);return files.sort()}async function loadRoot(root,origin,registry,onImportError){for(const file of modelFiles(root))try{const extension=extname(file),module=await import(`${file}?t=${Date.now()}`),definition=module.default??module,name=definition.name??basename(file,extension);registry.models[name]={...definition,name};registry.origins[name]=origin}catch(error){onImportError?.(file,error)}}export async function loadModelRegistryWithOrigins(options){const registry={models:{},origins:{}};await loadRoot(options.defaultsRoot,"default",registry,options.onImportError);await loadRoot(options.userRoot,"app",registry,options.onImportError);return registry}export async function loadModelRegistry(options){return(await loadModelRegistryWithOrigins(options)).models}export function resolveModelApiSelection(configured,envOverride){let raw,source="default";if(envOverride!==void 0&&envOverride!==null){raw=envOverride.split(",");source="env"}else if(typeof configured==="string"){raw=[configured];source="config"}else if(Array.isArray(configured)&&configured.every((entry)=>typeof entry==="string")){raw=configured;source="config"}if(raw===void 0)return{all:!0,own:!1,names:new Set,source};const names=raw.map((name)=>name.trim().toLowerCase()).filter(Boolean);if(names.length===0||names.includes("none"))return{all:!1,own:!1,names:new Set,source};if(names.includes("all"))return{all:!0,own:!1,names:new Set,source};return{all:!1,own:names.includes("own"),names:new Set(names.filter((name)=>name!=="own")),source}}export function selectApiModels(registry,selection){const selected={},matched=new Set;for(const[name,model]of Object.entries(registry.models)){if(!model?.traits?.useApi)continue;const key=name.toLowerCase(),named=selection.names.has(key);if(named)matched.add(key);if(selection.all||named||selection.own&&registry.origins[name]==="app")selected[name]=model}return{models:selected,unmatched:[...selection.names].filter((name)=>!matched.has(name)).sort()}}
File without changes
@@ -0,0 +1 @@
1
+ import{teamOwnershipField,userOwnershipField}from"./auto-crud";export function effectiveOwnershipConfig(model){if(model?.ownership===!1)return null;if(model?.ownership)return model.ownership;const teamCol=teamOwnershipField(model);if(teamCol)return{field:teamCol,resolve:async(_user,req)=>{const{resolveAuthenticatedTeamId}=await import("@stacksjs/auth");return resolveAuthenticatedTeamId(teamAuthRequest(req))}};const userCol=userOwnershipField(model);if(userCol)return{field:userCol,resolve:async(user)=>user?.id??null};return null}export function teamAuthRequest(req){const header=req?.headers?.get?.("authorization"),token=header&&/^Bearer\s+/i.test(header)?header.replace(/^Bearer\s+/i,"").trim():null,cookieHeader=req?.headers?.get?.("cookie")||"";return{bearerToken:()=>token,cookies:{get:(name)=>{for(const part of cookieHeader.split(";")){const eq=part.indexOf("=");if(eq===-1)continue;if(part.slice(0,eq).trim()===name)return decodeURIComponent(part.slice(eq+1).trim())}return null}}}}export function customerOwnership(field="customer_id"){return{field,resolve:async(user)=>{const userId=user?.id;if(userId==null)return null;try{const{Customer}=await import("@stacksjs/orm");return(await Customer.where("user_id",userId).first())?.id??null}catch{return null}}}}export function selfOwnership(field="id"){return{field,resolve:async(user)=>user?.id??null}}export function siteOwnership(field="site_id"){return{field,resolve:async(_user,req)=>{try{const[{resolveAuthenticatedTeamId},{Site}]=await Promise.all([import("@stacksjs/auth"),import("@stacksjs/orm")]),teamId=await resolveAuthenticatedTeamId(teamAuthRequest(req));if(teamId==null)return[];return(await Site.where("team_id",teamId).get()??[]).map((site)=>site.id).filter((id)=>id!=null)}catch{return[]}}}}export function teamMembershipOwnership(field="id"){return{field,resolve:async(_user,req)=>{try{const{resolveAuthenticatedTeamId}=await import("@stacksjs/auth");return await resolveAuthenticatedTeamId(teamAuthRequest(req))}catch{return null}}}}export function parentOwnership(parentModel,field){return{field,resolve:async(user,req)=>{try{const orm=await import("@stacksjs/orm"),parent=orm.models?.[parentModel]??orm[parentModel]?.definition??null,parentConfig=effectiveOwnershipConfig(parent);if(!parentConfig?.field||typeof parentConfig.resolve!=="function")return[];const ownerValue=await parentConfig.resolve(user,req);if(ownerValue==null||Array.isArray(ownerValue)&&ownerValue.length===0)return[];const Parent=orm[parentModel];if(!Parent)return[];return((Array.isArray(ownerValue)?await Parent.whereIn(parentConfig.field,ownerValue).get():await Parent.where(parentConfig.field,ownerValue).get())??[]).map((row)=>row.id).filter((id)=>id!=null)}catch{return[]}}}}
@@ -0,0 +1 @@
1
+ var {require}=import.meta;const DEFAULT_MAX_PER_PAGE=100,DEFAULT_PER_PAGE=15;export function resolvePageArgs(perPageArg,pageArg){const request=lazyGetCurrentRequest(),queryPerPage=request?readNumericQuery(request,"per_page"):void 0,queryPage=request?readNumericQuery(request,"page"):void 0,perPage=perPageArg!==void 0?Math.max(1,Math.floor(perPageArg)):Math.min(DEFAULT_MAX_PER_PAGE,Math.max(1,queryPerPage??DEFAULT_PER_PAGE)),page=Math.max(1,Math.floor(pageArg??queryPage??1));return{perPage,page}}export function resolveCursorArgs(perPageArg,cursorArg){const request=lazyGetCurrentRequest(),queryCursor=request?readStringQuery(request,"cursor"):void 0,queryPerPage=request?readNumericQuery(request,"per_page"):void 0,perPage=perPageArg!==void 0?Math.max(1,Math.floor(perPageArg)):Math.min(DEFAULT_MAX_PER_PAGE,Math.max(1,queryPerPage??DEFAULT_PER_PAGE)),cursor=parseCursor(cursorArg!==void 0?cursorArg:queryCursor??null);return{perPage,cursor}}export function parseCursor(value){if(value===null||value===void 0)return null;if(Array.isArray(value))return value;if(typeof value==="string"&&value.startsWith("["))try{const parsed=JSON.parse(value);if(Array.isArray(parsed))return parsed}catch{}return value}export function enrichPaginatorUrls(paginator){const request=lazyGetCurrentRequest();if(!request)return paginator;const url=(()=>{try{return new URL(request.url)}catch{return null}})();if(!url)return paginator;const path=url.pathname;paginator.path=path;if("next_cursor"in paginator){paginator.next_page_url=paginator.next_cursor!==null?buildUrl(url,{cursor:paginator.next_cursor}):null;paginator.prev_page_url=paginator.prev_cursor!==null?buildUrl(url,{cursor:paginator.prev_cursor}):null;return paginator}const currentPage=paginator.current_page;paginator.prev_page_url=currentPage>1?buildUrl(url,{page:currentPage-1}):null;if("total"in paginator){const lastPage=paginator.last_page;paginator.next_page_url=currentPage<lastPage?buildUrl(url,{page:currentPage+1}):null;paginator.first_page_url=buildUrl(url,{page:1});paginator.last_page_url=buildUrl(url,{page:lastPage})}else paginator.next_page_url=paginator.has_more_pages?buildUrl(url,{page:currentPage+1}):null;return paginator}function buildUrl(base,overrides){const out=new URL(base.toString());for(const[key,value]of Object.entries(overrides))out.searchParams.set(key,String(value));return`${out.pathname}${out.search}`}let _getCurrentRequestCache;function lazyGetCurrentRequest(){if(_getCurrentRequestCache===null)return;if(_getCurrentRequestCache===void 0)try{const mod=require("@stacksjs/router");if(typeof mod.getCurrentRequest==="function")_getCurrentRequestCache=mod.getCurrentRequest;else{_getCurrentRequestCache=null;return}}catch{_getCurrentRequestCache=null;return}return _getCurrentRequestCache()}function readNumericQuery(request,key){const raw=readStringQuery(request,key);if(raw===void 0)return;const n=Number(raw);return Number.isFinite(n)?n:void 0}function readStringQuery(request,key){const value=request.query?.[key];if(value===void 0)return;return Array.isArray(value)?value[0]:value}export function __resetRequestContextCache(){_getCurrentRequestCache=void 0}
@@ -0,0 +1 @@
1
+ export*from"@stacksjs/pagination";
package/dist/routes.js CHANGED
@@ -1,2 +1 @@
1
- // @bun
2
- var kt=(e,t,n)=>()=>{if(e)try{t=e(e=0)}catch(r){n=[r]}if(n)throw n[0];return t};var qt=import.meta.require;import{readdirSync as jt}from"fs";import{basename as Et,extname as Xe,join as Ft}from"path";function Ut(e){let t=[],n=(r)=>{let o;try{o=jt(r,{withFileTypes:!0})}catch{return}for(let i of o){let s=Ft(r,i.name);if(i.isDirectory()){n(s);continue}if(![".ts",".js"].includes(Xe(i.name)))continue;if(i.name.startsWith(".")||i.name.startsWith("index"))continue;t.push(s)}};return n(e),t.sort()}async function Ye(e,t,n,r){for(let o of Ut(e))try{let i=Xe(o),s=await import(`${o}?t=${Date.now()}`),c=s.default??s,f=c.name??Et(o,i);n.models[f]={...c,name:f},n.origins[f]=t}catch(i){r?.(o,i)}}async function xe(e){let t={models:{},origins:{}};return await Ye(e.defaultsRoot,"default",t,e.onImportError),await Ye(e.userRoot,"app",t,e.onImportError),t}async function sn(e){return(await xe(e)).models}function Ze(e,t){let n,r="default";if(t!==void 0&&t!==null)n=t.split(","),r="env";else if(typeof e==="string")n=[e],r="config";else if(Array.isArray(e)&&e.every((i)=>typeof i==="string"))n=e,r="config";if(n===void 0)return{all:!0,own:!1,names:new Set,source:r};let o=n.map((i)=>i.trim().toLowerCase()).filter(Boolean);if(o.length===0||o.includes("none"))return{all:!1,own:!1,names:new Set,source:r};if(o.includes("all"))return{all:!0,own:!1,names:new Set,source:r};return{all:!1,own:o.includes("own"),names:new Set(o.filter((i)=>i!=="own")),source:r}}function et(e,t){let n={},r=new Set;for(let[o,i]of Object.entries(e.models)){if(!i?.traits?.useApi)continue;let s=o.toLowerCase(),c=t.names.has(s);if(c)r.add(s);if(t.all||c||t.own&&e.origins[o]==="app")n[o]=i}return{models:n,unmatched:[...t.names].filter((o)=>!r.has(o)).sort()}}var tt=()=>{};import dt from"process";import{parseBearerToken as Bt,route as U}from"@stacksjs/router";import{env as E}from"@stacksjs/env";import{projectPath as Oe,storagePath as Lt}from"@stacksjs/path";import{createQueryBuilder as Wt,defaultConfig as nt,setConfig as rt}from"@stacksjs/query-builder";import{HttpError as Q}from"@stacksjs/error-handling";import{log as B}from"@stacksjs/logging/runtime";import{isUniqueViolation as nn}from"@stacksjs/error-handling";import{isUniqueViolation as St}from"@stacksjs/error-handling";function me(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(St(e))return{status:409,body:{error:`${t} already exists`}};return{status:500,body:{error:`Failed to ${n} ${t}`,detail:String(e)}}}function A(e){let t=!1;for(let r=0;r<e.length;r++){let o=e.charCodeAt(r);if(o>127)return e.replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/([A-Z])([A-Z][a-z])/g,"$1_$2").toLowerCase();if(o>=65&&o<=90)t=!0}if(!t)return e;let n="";for(let r=0;r<e.length;r++){let o=e.charCodeAt(r);if(o<65||o>90){n+=e[r];continue}let i=r>0?e.charCodeAt(r-1):0,s=r+1<e.length?e.charCodeAt(r+1):0,c=i>=97&&i<=122||i>=48&&i<=57,f=i>=65&&i<=90&&s>=97&&s<=122;if(r>0&&(c||f))n+="_";n+=String.fromCharCode(o+32)}return n}function we(e){let t={};for(let[n,r]of Object.entries(e))t[A(n)]=r;return t}function je(e,t){let n=String(t||"").replace(/^\/+|\/+$/g,""),r=String(e).replace(/^\/+/,"");return`/api/${n?`${n}/`:""}${r}`}function Ee(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 Fe(e){if(!e)return null;let t=e.attributes??{};if(Object.prototype.hasOwnProperty.call(t,"userId")||Object.prototype.hasOwnProperty.call(t,"user_id"))return"user_id";return e.belongsTo?.some((n)=>n==="User")?"user_id":null}function Ue(e){return e?.ownership===!1}function Be(e,t,n){let r=Object.keys(e).find((i)=>A(i)===A(t));if(Array.isArray(n)){if(r===void 0)return{data:e,error:"Ownership value is required"};if(!n.some((i)=>String(i)===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 i of Object.keys(o))if(A(i)===A(t))delete o[i];return o[t]=n,{data:o}}function Le(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=A(n.trim()).split("_").filter(Boolean);if(r.length===0)continue;let o=`${r[0]}${r.slice(1).map((i)=>`${i[0]?.toUpperCase()}${i.slice(1)}`).join("")}Id`;t.push(o)}return[...new Set(t)]}function he(e,t){if(!e||t.length===0)return{};let n={},r;for(let o of t){if(o in e){n[o]=e[o];continue}r??=_t(t);let i=r.get(o);if(i!==o&&i in e)n[o]=e[i]}return n}function At(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]),i=Number(n[3]),s=new Date(Date.UTC(r,o-1,i));if(s.getUTCFullYear()!==r||s.getUTCMonth()!==o-1||s.getUTCDate()!==i)return t;return s}var Ie=new WeakMap,Ce=new WeakMap;function be(e){let t=Ie.get(e);if(t&&t.length===e.length){let r=!0;for(let o=0;o<e.length;o++)if(t[o]?.field!==e[o]){r=!1;break}if(r)return t}let n=e.map((r)=>({field:r,snake:A(r)}));return Ie.set(e,n),n}function _t(e){let t=be(e),n=Ce.get(t);if(n)return n;let r=new Map(t.map(({field:o,snake:i})=>[o,i]));return Ce.set(t,r),r}function Re(e,t){if(!t.length)return e;let n={...e};for(let{field:r,snake:o}of be(t))if(delete n[r],o!==r)delete n[o];return n}function ee(e,t){if(!e||t.length===0)return e;let n={...e};for(let{field:r,snake:o}of be(t))if(delete n[r],o!==r)delete n[o];return n}var xt=["id","uuid","created_at","updated_at","deleted_at"];function We(e,t){let n=new Map;for(let r of[...Object.keys(e??{}),...xt]){let o=A(r);if(!/^\w+$/.test(o))continue;n.set(r,o),n.set(o,o)}for(let r of t)n.delete(r),n.delete(A(r));return n}function Qe(e,t,n){if(!t)return e;let r=e;for(let o of String(t).split(",")){let i=o.trim();if(!i)continue;let s=i.startsWith("-"),c=s?i.slice(1):i;if(!/^\w+$/.test(c))continue;let f=n.get(c);if(!f)continue;r=r.orderBy(f,s?"desc":"asc")}return r}var vt={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"?Ot(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"?Tt(e):[],set:(e)=>e==null?null:Array.isArray(e)?JSON.stringify(e):e}},$e=new WeakMap;function Pt(e,t){let n=$e.get(e);if(n&&n.length===t.length){let o=!0;for(let i=0;i<t.length;i++){let s=t[i];if(n[i]?.attr!==s||n[i]?.definition!==e[s]){o=!1;break}}if(o)return n}let r=[];for(let o of t){let i=e[o],s=typeof i==="string"?vt[i]:i;r.push({attr:o,snake:A(o),definition:i,caster:s})}return $e.set(e,r),r}function Ot(e){try{return JSON.parse(e)}catch{return e}}function Tt(e){try{return JSON.parse(e)}catch{return[]}}function ke(e,t,n){if(!e||typeof e!=="object"||!t)return e;let r=Object.keys(t);if(r.length===0)return e;let o=Pt(t,r);if(o.length===0)return e;let i={...e};for(let{attr:s,caster:c,snake:f}of o){if(!c)continue;let l=c[n];if(typeof l!=="function")continue;if(Object.prototype.hasOwnProperty.call(i,s))i[s]=l.call(c,i[s]);if(f!==s&&Object.prototype.hasOwnProperty.call(i,f))i[f]=l.call(c,i[f])}return i}var Me=new WeakMap;function Dt(e){let t=Me.get(e);if(t)return t;let n=[];for(let[r,o]of Object.entries(e)){let i=o?.validation?.rule;if(!i||typeof i.validate!=="function")continue;n.push({definition:o,field:r,hasDefault:o!==null&&typeof o==="object"&&Object.prototype.hasOwnProperty.call(o,"default"),rule:i})}return Me.set(e,n),n}function Zt(e){let t=e?.attributes;if(!t||typeof t!=="object")return!1;for(let n of Object.values(t)){let r=n?.validation?.rule;if(r&&typeof r.validate==="function")return!0}return!1}function Se(e,t,n){let r=t?.attributes;if(!r||typeof r!=="object")return{valid:!0};let o=Dt(r);if(o.length===0)return{valid:!0};let i={},s=!1;for(let c of o){let{definition:f,field:l,hasDefault:I,rule:_}=c,L=Object.prototype.hasOwnProperty.call(e,l);if(!L&&n==="updating")continue;let X=L?e[l]:I?f.default:void 0,V=At(_,X),C=_.validate(V);if(!C?.valid&&Array.isArray(C?.errors)&&C.errors.length>0)s=!0,i[l]=C.errors.map((N)=>f.validation?.message?.[N?.code]??N?.message??"invalid")}return s?{valid:!1,errors:i}:{valid:!0}}function Ae(e,t){return`${e}\x00${It(t)}`}function Ve(e){let t=new Map;for(let n of e){let r=Ae(String(n.method??""),String(n.path??""));if(!t.has(r))t.set(r,n)}return t}function It(e){return e.replace(/\{[^}]*\}/g,"{}").replace(/:[^/]+/g,"{}")}function de(e){if(Array.isArray(e))return e.filter((t)=>typeof t==="string"&&t.length>0);return typeof e==="string"&&e?[e]:[]}function Ct(e,t){let n=typeof e==="object"&&e!==null&&"middleware"in e,r=e?.middleware,o=fe(t);if(!n)return{read:K(["auth"],o),write:K(["auth"],o),declared:!1};if(r&&typeof r==="object"&&!Array.isArray(r)){let s=r;return{read:K("read"in s?de(s.read):["auth"],o),write:K("write"in s?de(s.write):["auth"],o),declared:!0}}let i=de(r);return{read:K(i,o),write:K(i,o),declared:!0}}function fe(e){if(!e||typeof e!=="object")return null;let t=e;if(t.enforce===!1)return null;if(!Array.isArray(t.roles))return null;let n=t.roles.filter((r)=>typeof r==="string").map((r)=>r.trim()).filter((r)=>r.length>0);return n.length>0?`role:${n.join(",")}`:null}var ie=["index","show","store","update","destroy"],$t={index:"read",show:"read",store:"write",update:"write",destroy:"write"};function Ge(e,t){let{read:n,write:r,declared:o}=Ct(e,t),i=fe(t),s=e?.middleware,c=s&&typeof s==="object"&&!Array.isArray(s)?s:void 0,f={};for(let l of ie)f[l]=c&&l in c?K(de(c[l]),i):$t[l]==="read"?n:r;return{abilities:f,read:n,write:r,declared:o}}function K(e,t){if(!t||e.length===0)return e;if(e.some((n)=>n==="role"||n.startsWith("role:")))return e;return[...e,t]}function ze(e){if(e.length===0)return null;let t=[...e].sort((n,r)=>n.model.localeCompare(r.model)).map((n)=>`${n.model} (${[...n.abilities].join(", ")})`).join(", ");return`[orm] ${e.length} model(s) role-gate their sidebar row and publish part of the matching API to everyone, because \`useApi.middleware\` declares those abilities empty - ${t}. Drop the empty list to let \`dashboard.roles\` gate them, or set \`dashboard.enforce: false\` to keep the row hidden and the API public.`}async function He(e,t,n,r){let o;try{o=await n.gate()}catch{return null}if(!o||!o.hasPolicy(e))return null;try{let i=await n.user(),s=r===void 0?await o.inspectFor(e,t,i):await o.inspectFor(e,t,i,r);if(s&&!s.isAllowed)return{status:403,message:s.message||"This action is unauthorized."};return null}catch{return{status:403,message:"This action is unauthorized."}}}var Ne=15,Mt=100;function Je(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(Ne),10),o=Math.min(Number.isFinite(r)?Math.max(1,r):Ne,Mt);return{page:n,perPage:o,offset:(n-1)*o}}function ce(e,t){let n=new URL(e.toString());return n.searchParams.set("page",String(t)),`${n.pathname}${n.search}`}function Nt(e,t,n,r,o,i){let s=(t-1)*n,c=r===0,f={page:t,per_page:n,from:c?null:s+1,to:c?null:s+r,has_more_pages:o,prev_page_url:t>1?ce(e,t-1):null,next_page_url:o?ce(e,t+1):null};if(i!==void 0&&!Number.isNaN(i)){let l=Math.max(1,Math.ceil(i/n));f.total=i,f.last_page=l,f.first_page_url=ce(e,1),f.last_page_url=ce(e,l)}return f}function _e(e,t,n,r,o,i){let{page:s,...c}=Nt(e,t,n,r,o,i);return{current_page:s,...c}}function Ke(e,t){return(t??e??"").toString().trim().toLowerCase()==="warn"?"warn":"deny"}function qe(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.`}tt();function ge(e){if(e?.ownership===!1)return null;if(e?.ownership)return e.ownership;let t=Ee(e);if(t)return{field:t,resolve:async(r,o)=>{let{resolveAuthenticatedTeamId:i}=await import("@stacksjs/auth");return i(ve(o))}};let n=Fe(e);if(n)return{field:n,resolve:async(r)=>r?.id??null};return null}function ve(e){let t=e?.headers?.get?.("authorization"),n=t&&/^Bearer\s+/i.test(t)?t.replace(/^Bearer\s+/i,"").trim():null,r=e?.headers?.get?.("cookie")||"";return{bearerToken:()=>n,cookies:{get:(o)=>{for(let i of r.split(";")){let s=i.indexOf("=");if(s===-1)continue;if(i.slice(0,s).trim()===o)return decodeURIComponent(i.slice(s+1).trim())}return null}}}}function un(e="customer_id"){return{field:e,resolve:async(t)=>{let n=t?.id;if(n==null)return null;try{let{Customer:r}=await import("@stacksjs/orm");return(await r.where("user_id",n).first())?.id??null}catch{return null}}}}function cn(e="id"){return{field:e,resolve:async(t)=>t?.id??null}}function dn(e="site_id"){return{field:e,resolve:async(t,n)=>{try{let[{resolveAuthenticatedTeamId:r},{Site:o}]=await Promise.all([import("@stacksjs/auth"),import("@stacksjs/orm")]),i=await r(ve(n));if(i==null)return[];return(await o.where("team_id",i).get()??[]).map((c)=>c.id).filter((c)=>c!=null)}catch{return[]}}}}function fn(e="id"){return{field:e,resolve:async(t,n)=>{try{let{resolveAuthenticatedTeamId:r}=await import("@stacksjs/auth");return await r(ve(n))}catch{return null}}}}function gn(e,t){return{field:t,resolve:async(n,r)=>{try{let o=await import("@stacksjs/orm"),i=o.models?.[e]??o[e]?.definition??null,s=ge(i);if(!s?.field||typeof s.resolve!=="function")return[];let c=await s.resolve(n,r);if(c==null||Array.isArray(c)&&c.length===0)return[];let f=o[e];if(!f)return[];return((Array.isArray(c)?await f.whereIn(s.field,c).get():await f.where(s.field,c).get())??[]).map((I)=>I.id).filter((I)=>I!=null)}catch{return[]}}}}var Qt=Oe("config/qb.ts");try{let e=(await import(Qt)).default;rt(e??nt)}catch{B.debug("[orm] No config/qb.ts override found - deriving config from DB_CONNECTION");let e=E.DB_CONNECTION||"sqlite",t=e==="turso"||e==="libsql",n=t?"sqlite":e;rt({...nt,dialect:n,database:t?{database:E.TURSO_DATABASE_URL||"",url:E.TURSO_DATABASE_URL||"",authToken:E.TURSO_AUTH_TOKEN||void 0}:n==="sqlite"?{database:E.DB_DATABASE_PATH||"database/stacks.sqlite"}:{database:E.DB_DATABASE||"stacks",host:E.DB_HOST||"127.0.0.1",port:E.DB_PORT||(n==="postgres"?5432:3306),username:E.DB_USERNAME||(n==="postgres"?"postgres":"root"),password:E.DB_PASSWORD||""}})}var ft=await xe({defaultsRoot:Lt("framework/defaults/app/Models"),userRoot:Oe("app/Models"),onImportError:(e,t)=>B.warn(`[orm] Could not load model ${e}: ${t.message}`)}),ot=ft.models,Vt=Wt(),D=Vt,it=Ve(U.routes);function q(e,t){let n=Ae(e,t),r=it.get(n);if(!r)return it.set(n,{method:e,path:t}),!1;let o=String(r.path??"");return B.debug(`[orm] Skipping generated ${e} ${t} - already defined${o&&o!==t?` as ${o}`:""}.`),!0}function gt(e){if(!e.attributes)return[];return Object.entries(e.attributes).filter(([t,n])=>n.hidden===!0).map(([t])=>t)}function st(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 at(e,t,n,r){if(!e.length)return e;let o=n.split(",").map((l)=>l.trim()).filter(Boolean);if(!o.length)return e;let i=Array.isArray(t.belongsTo)?t.belongsTo:[],s=Array.isArray(t.hasMany)?t.hasMany:[],c=Array.isArray(t.hasOne)?t.hasOne:[],f=new Map;for(let l of i)f.set(A(l),{kind:"belongsTo",modelName:l});for(let l of c)f.set(A(l),{kind:"hasOne",modelName:l});for(let l of s)f.set(st(A(l)),{kind:"hasMany",modelName:l});for(let l of o){let I=f.get(l);if(!I)continue;let _=r[I.modelName];if(!_)continue;let L=_.table||st(A(I.modelName)),X=gt(_),V=(C)=>ee(ae(C,_),X);if(I.kind==="belongsTo"||I.kind==="hasOne"){let C=`${A(I.modelName)}_id`,N=[...new Set(e.map((v)=>v[C]).filter((v)=>v!=null))];if(!N.length){for(let v of e)v[l]=null;continue}let G=await D.selectFrom(L).whereIn("id",N).get(),Z=new Map;for(let v of G??[])Z.set(String(v.id),V(v));for(let v of e)v[l]=Z.get(String(v[C]))??null}else{let C=String(t.name??""),N=`${A(C)}_id`,G=[...new Set(e.map((M)=>M.id).filter((M)=>M!=null))];if(!G.length){for(let M of e)M[l]=[];continue}let Z=await D.selectFrom(L).whereIn(N,G).get(),v=new Map;for(let M of Z??[]){let re=String(M[N]),z=v.get(re)??[];z.push(V(M)),v.set(re,z)}for(let M of e)M[l]=v.get(String(M.id))??[]}}return e}async function lt(e,t){let n=t?.set;if(!n||typeof n!=="object")return e;let r={...e};for(let[o,i]of Object.entries(n)){if(typeof i!=="function"||!(o in r))continue;try{r[o]=await i(r)}catch{}}return r}function ut(e,t){return ke(e,t?.casts,"set")}function ae(e,t){return ke(e,t?.casts,"get")}function g(e,t=200){return new Response(JSON.stringify(e),{status:t,headers:{"Content-Type":"application/json"}})}var pe=1048576;async function Pe(e){if(Number(e.headers?.get?.("content-length")??0)>pe)throw new Q(413,`Request body exceeds ${pe}-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>pe)throw new Q(413,`Request body exceeds ${pe}-byte limit`);if(!n)return{};let r=JSON.parse(n);return r&&typeof r==="object"&&!Array.isArray(r)?r:{}}catch(n){if(n instanceof Q)throw n;throw new Q(400,`Invalid JSON body: ${n.message}`)}}function ye(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 Gt(e){let t=e.bearerToken;if(typeof t==="function"){let n=t.call(e);if(n)return n}return Bt(e.headers?.get?.("authorization")??null)}async function Y(e){let t=e._authenticatedUser;if(t)return t;let n=Gt(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}}var zt;async function pt(){try{let{Gate:e}=zt??=await import("@stacksjs/auth");return e}catch{return null}}async function Ht(e){let t=await pt();return!!t&&t.hasPolicy(e)}async function te(e,t,n,r){let o=await He(e,t,{gate:pt,user:()=>Y(n)},r);return o?g({error:o.message},o.status):null}function se(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)}async function ne(e,t,n){let r=ge(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,i=null;try{i=await r.resolve(t,n)}catch{i=null}return{enforced:!0,value:i,field:String(r.field),bypass:o}}async function ct(e,t,n,r){let o=e?.authedFill?.[t];if(!o)return{};if(typeof o==="function")try{let i=await o(n,r);return i&&typeof i==="object"?i:{}}catch{return{}}if(typeof o==="object"){let i={};for(let[s,c]of Object.entries(o))try{i[s]=typeof c==="function"?await c(n,r):c}catch{}return i}return{}}var yt=await(async()=>{try{return(await import(Oe("config/security.ts"))).default?.api}catch{return}})(),mt=Ke(yt?.rowScoping,dt.env.STACKS_API_ROW_SCOPING),Jt=(()=>{let e=Ze(yt?.models,dt.env.STACKS_MODEL_APIS),{models:t,unmatched:n}=et(ft,e);if(n.length>0){let r=e.source==="env"?"STACKS_MODEL_APIS":"security.api.models";B.warn(`[orm] ${r} names ${n.length===1?"a model":"models"} with no \`useApi\` trait, so no API was generated for ${n.join(", ")}.`)}return t})(),wt=[],ht=[];for(let[e,t]of Object.entries(Jt)){let n=t.traits?.useApi;if(!n)continue;let r=typeof n==="object"?n:{},o=r.uri||t.table||e.toLowerCase()+"s",i=r.routes||["index","show","store","update","destroy"],s=t.table||o,c=Le(t),f=gt(t),l=je(o,r.prefix),I=We(t.attributes,f),{abilities:_,declared:L}=Ge(n,t.dashboard);if(fe(t.dashboard)){let u=ie.filter((a)=>i.includes(a)&&_[a].length===0);if(u.length>0)ht.push({model:e,abilities:u})}let X=["store","update","destroy"].some((u)=>i.includes(u)),V=ie.filter((u)=>u!=="index"&&u!=="show"&&i.includes(u)&&_[u].length===0);if(L&&V.length>0)B.warn(`[orm] ${e}: registering UNAUTHENTICATED ${V.join(", ")} at ${l} (explicit empty \`middleware\` opt-out)`);let C=ie.filter((u)=>(u==="index"||u==="show")&&i.includes(u)&&_[u].length===0);if(L&&C.length>0)B.debug(`[orm] ${e}: registering public ${C.join(", ")} at ${l} (declared an empty read \`middleware\`)`);let N=!!ge(t),G=(u)=>N&&!u.includes("auth")?["auth",...u]:u,Z=G(_.index),v=G(_.show),M=Ue(t),re=X&&!N&&!M;if(re)wt.push(e);if(X&&M)B.debug(`[orm] ${e}: registering unscoped mutating routes at ${l} (declared \`ownership: false\`)`);let z=re&&mt==="deny",H=(u,a)=>{let d=u;for(let p of a)if(d&&typeof d.middleware==="function")d=d.middleware(p);return d};if(i.includes("index")&&!q("GET",l))H(U.get(l,async(u)=>{try{let a=new URL(u.url),{page:d,perPage:p,offset:w}=Je(a.searchParams),R=a.searchParams.get("sort"),y=await te(e,"viewAny",u);if(y)return y;let h=D.selectFrom(s);h=Qe(h,R,I);let b=new Set(["page","per_page","sort","fields","search","include","limit","offset","with_count","withTrashed","onlyTrashed"]);for(let[O,T]of a.searchParams.entries()){if(b.has(O)||!T)continue;if(!/^[a-z_][a-z0-9_]*$/i.test(O))continue;let J=I.get(O);if(J)h=h.where(J,"=",T)}let k=a.searchParams.get("search");if(k&&c.length>0){let O=c.slice(0,5);h=h.where((T)=>{for(let J of O)T=T.orWhere(A(J),"like",`%${k}%`);return T})}let S=a.searchParams.get("fields");if(S){let O=S.split(",").map((T)=>T.trim()).filter((T)=>/^[a-z_][a-z0-9_]*$/i.test(T)).map((T)=>A(T));if(O.length>0)h=h.select(O)}let P=!!t.traits?.useSoftDeletes,x=a.searchParams.get("withTrashed")==="true",j=a.searchParams.get("onlyTrashed")==="true";if(P&&!x)h=j?h.whereNotNull("deleted_at"):h.whereNull("deleted_at");let m=N?await ne(t,await Y(u),u):{enforced:!1,value:null,field:"",bypass:!1};if(m.enforced&&!m.bypass){if(m.value==null||Array.isArray(m.value)&&m.value.length===0){let O=_e(a,d,p,0,!1,void 0);return new Response(JSON.stringify({data:[],...O}),{status:200,headers:{"Content-Type":"application/json","Cache-Control":"private, no-store",Vary:"Authorization"}})}h=Array.isArray(m.value)?h.where(m.field,"in",m.value):h.where(m.field,"=",m.value)}let F=await h.limit(p+1).offset(w).get()||[],W=F.length>p,le=(W?F.slice(0,p):F).map((O)=>ee(ae(O,t),f)),De=a.searchParams.get("include");if(De)le=await at(le,t,De,ot);let bt=a.searchParams.get("with_count")==="true",oe;if(bt)try{let O=D.selectFrom(s);if(m.enforced&&!m.bypass&&m.value!=null)O=Array.isArray(m.value)?O.where(m.field,"in",m.value):O.where(m.field,"=",m.value);let T=await O.count(),J=typeof T==="number"?T:Number(T?.count??T);if(Number.isFinite(J))oe=J}catch{}let ue={"Content-Type":"application/json"};if(oe!==void 0&&!Number.isNaN(oe))ue["X-Total-Count"]=String(oe);ue["Cache-Control"]=m.enforced&&!m.bypass?"private, no-store":"public, max-age=15, must-revalidate",ue.Vary="Authorization";let Rt=_e(a,d,p,le.length,W,oe);return new Response(JSON.stringify({data:le,...Rt}),{status:200,headers:ue})}catch(a){if(a instanceof Q){let d={error:a.message};if(a.details!==void 0)d.details=a.details;return g(d,a.status||400)}return g({error:`Failed to fetch ${o}`,detail:String(a)},500)}}),Z);if(i.includes("show")&&!q("GET",`${l}/{id}`))H(U.get(`${l}/{id}`,async(u)=>{try{let a=ye(u.params?.id);if(a==null)return g({error:"Invalid ID parameter"},400);let d=await D.selectFrom(s).where({id:a}).executeTakeFirst();if(!d)return g({error:`${e} not found`},404);let p=new URL(u.url);if(t.traits?.useSoftDeletes&&d.deleted_at&&p.searchParams.get("withTrashed")!=="true")return g({error:`${e} not found`},404);let w=N?await ne(t,await Y(u),u):{enforced:!1,value:null,field:"",bypass:!1};if(w.enforced&&!w.bypass){if(w.value==null||!se(d[w.field],w.value))return g({error:`${e} not found`},404)}let R=await te(e,"view",u,d);if(R)return R;let y=ee(ae(d,t),f),h=p.searchParams.get("include");if(h){let[x]=await at([y],t,h,ot);y=x}let b=y?.updated_at||y?.created_at,k=b?`W/"${y.id}-${String(b)}"`:void 0,S=u.headers?.get?.("if-none-match");if(k&&S&&S===k)return new Response(null,{status:304,headers:{ETag:k}});let P={"Content-Type":"application/json"};if(k)P.ETag=k;return P["Cache-Control"]=w.enforced&&!w.bypass?"private, no-store":"public, max-age=30, must-revalidate",P.Vary="Authorization",new Response(JSON.stringify({data:y}),{status:200,headers:P})}catch(a){if(a instanceof Q){let d={error:a.message};if(a.details!==void 0)d.details=a.details;return g(d,a.status||400)}return g({error:`Failed to fetch ${e}`,detail:String(a)},500)}}),v);if(!z&&i.includes("store")&&!q("POST",l))H(U.post(l,async(u)=>{try{let a=await Pe(u),d=Re(a,f),p=he(d,c),w=await Y(u);if(w){let x=await ct(t,"creating",w,u);for(let[j,m]of Object.entries(x))if(m!==void 0&&m!==null&&p[j]===void 0)p[j]=m}let R=await te(e,"create",u);if(R)return R;let y=await ne(t,w,u);if(y.enforced&&!y.bypass){if(!w)return g({error:"Auth required"},401);let x=Be(p,y.field,y.value);if(x.error)return g({error:x.error},403);p=x.data}if(Object.keys(p).length===0)return g({error:"No fillable fields provided"},422);let h=Se(p,t,"creating");if(!h.valid)return g({success:!1,message:"Validation failed",errors:h.errors},422);if(t.traits?.useTimestamps!==!1){let x=new Date().toISOString();p.created_at=x,p.updated_at=x}let b=await lt(p,t),k=we(ut(b,t)),S=await D.insertInto(s).values(k).execute(),P=k;try{let x=S?.lastInsertRowid??S?.insertId??S;if(x){let j=await D.selectFrom(s).where({id:x}).executeTakeFirst();if(j)P=j}}catch{}return g({data:ee(ae(P,t),f)},201)}catch(a){let{status:d,body:p}=me(a,e,"create");return g(p,d)}}),_.store);if(!z&&i.includes("update")){let u=async(a)=>{try{let d=ye(a.params?.id);if(d==null)return g({error:"Invalid ID parameter"},400);let p=await Pe(a),w=Re(p,f),R=he(w,c),y=await Y(a);if(y){let m=await ct(t,"updating",y,a);for(let[F,W]of Object.entries(m))if(W!==void 0&&W!==null&&R[F]===void 0)R[F]=W}if(Object.keys(R).length===0)return g({error:"No fillable fields provided"},422);let h=Se(R,t,"updating");if(!h.valid)return g({success:!1,message:"Validation failed",errors:h.errors},422);let b=await D.selectFrom(s).where({id:d}).executeTakeFirst();if(!b)return g({error:`${e} not found`},404);let k=await te(e,"update",a,b);if(k)return k;let S=await ne(t,y,a);if(S.enforced&&!S.bypass){if(!y)return g({error:"Auth required"},401);let m=b[S.field];if(!se(m,S.value))return g({error:`Not your ${e}`},403);let F=Object.keys(R).find((W)=>A(W)===A(S.field));if(F!==void 0&&!se(R[F],S.value))return g({error:`Cannot reassign ${e} ownership`},403)}if(t.traits?.useTimestamps!==!1)R.updated_at=new Date().toISOString();let P=await lt(R,t),x=we(ut(P,t));await D.updateTable(s).set(x).where({id:d}).execute();let j={...b,...x};try{let m=await D.selectFrom(s).where({id:d}).executeTakeFirst();if(m)j=m}catch{}return g({data:ee(ae(j,t),f)})}catch(d){let{status:p,body:w}=me(d,e,"update");return g(w,p)}};if(!q("PUT",`${l}/{id}`))H(U.put(`${l}/{id}`,u),_.update);if(!q("PATCH",`${l}/{id}`))H(U.patch(`${l}/{id}`,u),_.update)}let Te=!!t.traits?.useSoftDeletes;if(!z&&i.includes("destroy")&&!q("DELETE",`${l}/{id}`))H(U.delete(`${l}/{id}`,async(u)=>{try{let a=ye(u.params?.id);if(a==null)return g({error:"Invalid ID parameter"},400);let d=await D.selectFrom(s).where({id:a}).executeTakeFirst();if(!d)return g({error:`${e} not found`},404);let p=await Y(u),w=await ne(t,p,u);if(w.enforced&&!w.bypass){if(!p)return g({error:"Auth required"},401);let y=d[w.field];if(!se(y,w.value))return g({error:`Not your ${e}`},403)}let R=await te(e,"delete",u,d);if(R)return R;if(Te){let y=new Date().toISOString();await D.updateTable(s).set({deleted_at:y,updated_at:y}).where({id:a}).execute()}else await D.deleteFrom(s).where({id:a}).execute();return new Response(null,{status:204})}catch(a){if(a instanceof Q){let d={error:a.message};if(a.details!==void 0)d.details=a.details;return g(d,a.status||400)}return g({error:`Failed to delete ${e}`,detail:String(a)},500)}}),_.destroy);if(!z&&i.includes("destroy")&&!q("POST",`${l}/bulk-delete`))H(U.post(`${l}/bulk-delete`,async(u)=>{try{let d=(await Pe(u))?.ids;if(!Array.isArray(d)||d.length===0)return g({error:"An array of IDs is required"},422);if(d.length>100)return g({error:"Cannot delete more than 100 records at once"},422);let p=[],w=[];for(let b of d){let k=ye(b);if(k!=null)p.push(k);else w.push(b)}if(w.length>0)return g({error:"Invalid IDs in batch",invalid:w},422);let R=await Y(u),y=await ne(t,R,u);if(y.enforced&&!y.bypass){if(!R)return g({error:"Auth required"},401);if(y.value==null)return g({error:"Caller has no ownership identity"},403);let b=await D.selectFrom(s).select(["id",y.field]).execute(),k=new Set(b.filter((P)=>se(P[y.field],y.value)).map((P)=>String(P.id))),S=p.filter((P)=>!k.has(String(P)));if(S.length>0)return g({error:`Cannot delete ${e} you don't own`,ids:S},403)}if(await Ht(e)){let b=[];for(let k of p){let S=await D.selectFrom(s).where({id:k}).executeTakeFirst();if(!S)continue;if(await te(e,"delete",u,S))b.push(k)}if(b.length>0)return g({error:`Cannot delete ${e} this policy refuses`,ids:b},403)}let h=new Date().toISOString();for(let b of p)if(Te)await D.updateTable(s).set({deleted_at:h,updated_at:h}).where({id:b}).execute();else await D.deleteFrom(s).where({id:b}).execute();return g({message:`Successfully deleted ${p.length} ${o}`})}catch(a){if(a instanceof Q){let d={error:a.message};if(a.details!==void 0)d.details=a.details;return g(d,a.status||400)}return g({error:`Failed to bulk delete ${o}`,detail:String(a)},500)}}),_.destroy)}{let e=qe(wt,mt);if(e)B.warn(e);let t=ze(ht);if(t)B.warn(t)}var vn=U;export{vn as default};
1
+ import process from"node:process";import{parseBearerToken,route}from"@stacksjs/router";import{env}from"@stacksjs/env";import{projectPath,storagePath}from"@stacksjs/path";import{createQueryBuilder,defaultConfig,setConfig}from"@stacksjs/query-builder";import{HttpError}from"@stacksjs/error-handling";import{log}from"@stacksjs/logging/runtime";import{API_ABILITIES,apiBasePath,applyCasts,applySorting,buildIndexPaginator,buildReadColumnMap,dashboardRoleMiddleware,describeContradictoryRoleGates,describeUnscopedMutatingModels,dropHiddenInputs,filterFillable,getWritableFields,indexRouteShapes,mapWriteError,ownershipDeclaredUnscoped,policyDecision,resolveAbilityMiddleware,resolveIndexPageArgs,resolveRowScopingPolicy,routeShapeKey,stampOwnership,stripHidden,toSnakeCase,toSnakeCaseKeys,validateWriteBody}from"./auto-crud";import{loadModelRegistryWithOrigins,resolveModelApiSelection,selectApiModels}from"./model-registry";import{effectiveOwnershipConfig}from"./ownership";const qbConfigPath=projectPath("config/qb.ts");try{const projectQbConfig=(await import(qbConfigPath)).default;setConfig(projectQbConfig??defaultConfig)}catch{log.debug("[orm] No config/qb.ts override found - deriving config from DB_CONNECTION");const connection=env.DB_CONNECTION||"sqlite",libsql=connection==="turso"||connection==="libsql",dialect=libsql?"sqlite":connection;setConfig({...defaultConfig,dialect,database:libsql?{database:env.TURSO_DATABASE_URL||"",url:env.TURSO_DATABASE_URL||"",authToken:env.TURSO_AUTH_TOKEN||void 0}:dialect==="sqlite"?{database:env.DB_DATABASE_PATH||"database/stacks.sqlite"}:{database:env.DB_DATABASE||"stacks",host:env.DB_HOST||"127.0.0.1",port:env.DB_PORT||(dialect==="postgres"?5432:3306),username:env.DB_USERNAME||(dialect==="postgres"?"postgres":"root"),password:env.DB_PASSWORD||""}})}const registry=await loadModelRegistryWithOrigins({defaultsRoot:storagePath("framework/defaults/app/Models"),userRoot:projectPath("app/Models"),onImportError:(file,error)=>log.warn(`[orm] Could not load model ${file}: ${error.message}`)}),models=registry.models,db=createQueryBuilder(),dyn=db,routeShapeIndex=indexRouteShapes(route.routes);function routeClaimed(method,path){const key=routeShapeKey(method,path),existing=routeShapeIndex.get(key);if(!existing){routeShapeIndex.set(key,{method,path});return!1}const existingPath=String(existing.path??"");log.debug(`[orm] Skipping generated ${method} ${path} - already defined${existingPath&&existingPath!==path?` as ${existingPath}`:""}.`);return!0}function getHiddenFields(model){if(!model.attributes)return[];return Object.entries(model.attributes).filter(([_,attr])=>attr.hidden===!0).map(([name])=>name)}function pluralize(s){if(s.endsWith("y")&&!/[aeiou]y$/i.test(s))return`${s.slice(0,-1)}ies`;if(/(?:s|x|z|ch|sh)$/i.test(s))return`${s}es`;return`${s}s`}async function applyIncludes(rows,model,includeParam,modelsRegistry){if(!rows.length)return rows;const requested=includeParam.split(",").map((s)=>s.trim()).filter(Boolean);if(!requested.length)return rows;const belongsTo=Array.isArray(model.belongsTo)?model.belongsTo:[],hasMany=Array.isArray(model.hasMany)?model.hasMany:[],hasOne=Array.isArray(model.hasOne)?model.hasOne:[],allowed=new Map;for(const m of belongsTo)allowed.set(toSnakeCase(m),{kind:"belongsTo",modelName:m});for(const m of hasOne)allowed.set(toSnakeCase(m),{kind:"hasOne",modelName:m});for(const m of hasMany)allowed.set(pluralize(toSnakeCase(m)),{kind:"hasMany",modelName:m});for(const include of requested){const meta=allowed.get(include);if(!meta)continue;const related=modelsRegistry[meta.modelName];if(!related)continue;const relatedTable=related.table||pluralize(toSnakeCase(meta.modelName)),relatedHidden=getHiddenFields(related),relatedAttrs=(id)=>stripHidden(applyReadCasts(id,related),relatedHidden);if(meta.kind==="belongsTo"||meta.kind==="hasOne"){const fkOnParent=`${toSnakeCase(meta.modelName)}_id`,ids=[...new Set(rows.map((r)=>r[fkOnParent]).filter((v)=>v!=null))];if(!ids.length){for(const r of rows)r[include]=null;continue}const childRows=await dyn.selectFrom(relatedTable).whereIn("id",ids).get(),byId=new Map;for(const cr of childRows??[])byId.set(String(cr.id),relatedAttrs(cr));for(const r of rows)r[include]=byId.get(String(r[fkOnParent]))??null}else{const parentName=String(model.name??""),fkOnChild=`${toSnakeCase(parentName)}_id`,parentIds=[...new Set(rows.map((r)=>r.id).filter((v)=>v!=null))];if(!parentIds.length){for(const r of rows)r[include]=[];continue}const childRows=await dyn.selectFrom(relatedTable).whereIn(fkOnChild,parentIds).get(),grouped=new Map;for(const cr of childRows??[]){const key=String(cr[fkOnChild]),arr=grouped.get(key)??[];arr.push(relatedAttrs(cr));grouped.set(key,arr)}for(const r of rows)r[include]=grouped.get(String(r.id))??[]}}return rows}async function applyDefinedSetters(data,model){const setters=model?.set;if(!setters||typeof setters!=="object")return data;const out={...data};for(const[key,fn]of Object.entries(setters)){if(typeof fn!=="function"||!(key in out))continue;try{out[key]=await fn(out)}catch{}}return out}function applySetCasts(data,model){return applyCasts(data,model?.casts,"set")}function applyReadCasts(row,model){return applyCasts(row,model?.casts,"get")}function jsonResponse(data,status=200){return new Response(JSON.stringify(data),{status,headers:{"Content-Type":"application/json"}})}function errorResponse(req,body,status=400){const reqId=req?._requestId,enriched=reqId?{...body,request_id:reqId}:body;return new Response(JSON.stringify(enriched),{status,headers:{"Content-Type":"application/json"}})}const MAX_BODY_BYTES=1048576;async function getRequestBody(req){if(Number(req.headers?.get?.("content-length")??0)>MAX_BODY_BYTES)throw new HttpError(413,`Request body exceeds ${MAX_BODY_BYTES}-byte limit`);if(req.jsonBody&&typeof req.jsonBody==="object")return req.jsonBody;if(req.formBody&&typeof req.formBody==="object")return req.formBody;try{const text=await req.clone().text();if(text.length>MAX_BODY_BYTES)throw new HttpError(413,`Request body exceeds ${MAX_BODY_BYTES}-byte limit`);if(!text)return{};const parsed=JSON.parse(text);return parsed&&typeof parsed==="object"&&!Array.isArray(parsed)?parsed:{}}catch(err){if(err instanceof HttpError)throw err;throw new HttpError(400,`Invalid JSON body: ${err.message}`)}}function coerceId(raw){if(raw==null)return null;if(typeof raw==="number")return Number.isFinite(raw)&&raw>0?raw:null;if(typeof raw==="string"){const trimmed=raw.trim();if(!trimmed)return null;if(/^\d+$/.test(trimmed)){const n=Number(trimmed);return Number.isFinite(n)&&n>0?n:null}return trimmed}return null}function bearerOf(req){const fn=req.bearerToken;if(typeof fn==="function"){const t=fn.call(req);if(t)return t}return parseBearerToken(req.headers?.get?.("authorization")??null)}async function authedUserFromRequest(req){const stored=req._authenticatedUser;if(stored)return stored;const token=bearerOf(req);if(!token)return null;try{const{Auth}=await import("@stacksjs/auth"),user=await Auth.getUserFromToken(token);if(user)req._authenticatedUser=user;return user||null}catch{return null}}let authGateModule;async function authGate(){try{const{Gate}=authGateModule??=await import("@stacksjs/auth");return Gate}catch{return null}}async function hasPolicyFor(modelName){const gate=await authGate();return!!gate&&gate.hasPolicy(modelName)}async function policyRefusal(modelName,ability,req,subject){const refusal=await policyDecision(modelName,ability,{gate:authGate,user:()=>authedUserFromRequest(req)},subject);return refusal?jsonResponse({error:refusal.message},refusal.status):null}function ownsRow(rowField,ownerValue){if(rowField==null||ownerValue==null)return!1;if(Array.isArray(ownerValue))return ownerValue.some((v)=>String(v)===String(rowField));return String(rowField)===String(ownerValue)}async function resolveOwnership(model,user,req){const cfg=effectiveOwnershipConfig(model);if(!cfg||!cfg.field||typeof cfg.resolve!=="function")return{enforced:!1,value:null,field:"",bypass:!1};const bypass=typeof cfg.bypass==="function"?!!cfg.bypass(user,req):!1;let value=null;try{value=await cfg.resolve(user,req)}catch{value=null}return{enforced:!0,value,field:String(cfg.field),bypass}}async function resolveAuthedFill(model,hook,user,req){const cfg=model?.authedFill?.[hook];if(!cfg)return{};if(typeof cfg==="function")try{const result=await cfg(user,req);return result&&typeof result==="object"?result:{}}catch{return{}}if(typeof cfg==="object"){const out={};for(const[field,getter]of Object.entries(cfg))try{out[field]=typeof getter==="function"?await getter(user,req):getter}catch{}return out}return{}}const securityApiConfig=await(async()=>{try{return(await import(projectPath("config/security.ts"))).default?.api}catch{return}})(),rowScopingPolicy=resolveRowScopingPolicy(securityApiConfig?.rowScoping,process.env.STACKS_API_ROW_SCOPING),apiModels=(()=>{const selection=resolveModelApiSelection(securityApiConfig?.models,process.env.STACKS_MODEL_APIS),{models:selected,unmatched}=selectApiModels(registry,selection);if(unmatched.length>0){const setting=selection.source==="env"?"STACKS_MODEL_APIS":"security.api.models";log.warn(`[orm] ${setting} names ${unmatched.length===1?"a model":"models"} with no \`useApi\` trait, so no API was generated for ${unmatched.join(", ")}.`)}return selected})(),unscopedMutatingModels=[],contradictoryRoleGates=[];for(const[modelName,model]of Object.entries(apiModels)){const useApi=model.traits?.useApi;if(!useApi)continue;const apiConfig=typeof useApi==="object"?useApi:{},uri=apiConfig.uri||model.table||modelName.toLowerCase()+"s",enabledRoutes=apiConfig.routes||["index","show","store","update","destroy"],table=model.table||uri,fillableFields=getWritableFields(model),hiddenFields=getHiddenFields(model),basePath=apiBasePath(uri,apiConfig.prefix),readColumns=buildReadColumnMap(model.attributes,hiddenFields),{abilities,declared}=resolveAbilityMiddleware(useApi,model.dashboard);if(dashboardRoleMiddleware(model.dashboard)){const open=API_ABILITIES.filter((ability)=>enabledRoutes.includes(ability)&&abilities[ability].length===0);if(open.length>0)contradictoryRoleGates.push({model:modelName,abilities:open})}const hasMutating=["store","update","destroy"].some((r)=>enabledRoutes.includes(r)),openWrites=API_ABILITIES.filter((ability)=>ability!=="index"&&ability!=="show"&&enabledRoutes.includes(ability)&&abilities[ability].length===0);if(declared&&openWrites.length>0)log.warn(`[orm] ${modelName}: registering UNAUTHENTICATED ${openWrites.join(", ")} at ${basePath} (explicit empty \`middleware\` opt-out)`);const openReads=API_ABILITIES.filter((ability)=>(ability==="index"||ability==="show")&&enabledRoutes.includes(ability)&&abilities[ability].length===0);if(declared&&openReads.length>0)log.debug(`[orm] ${modelName}: registering public ${openReads.join(", ")} at ${basePath} (declared an empty read \`middleware\`)`);const rowScoped=!!effectiveOwnershipConfig(model),forceAuth=(names)=>rowScoped&&!names.includes("auth")?["auth",...names]:names,indexMiddleware=forceAuth(abilities.index),showMiddleware=forceAuth(abilities.show),declaredUnscoped=ownershipDeclaredUnscoped(model),writesAreUnscoped=hasMutating&&!rowScoped&&!declaredUnscoped;if(writesAreUnscoped)unscopedMutatingModels.push(modelName);if(hasMutating&&declaredUnscoped)log.debug(`[orm] ${modelName}: registering unscoped mutating routes at ${basePath} (declared \`ownership: false\`)`);const skipMutatingRoutes=writesAreUnscoped&&rowScopingPolicy==="deny",applyMiddleware=(chain,names)=>{let r=chain;for(const name of names)if(r&&typeof r.middleware==="function")r=r.middleware(name);return r};if(enabledRoutes.includes("index")&&!routeClaimed("GET",basePath))applyMiddleware(route.get(basePath,async(req)=>{try{const url=new URL(req.url),{page,perPage,offset}=resolveIndexPageArgs(url.searchParams),sort=url.searchParams.get("sort"),refusedList=await policyRefusal(modelName,"viewAny",req);if(refusedList)return refusedList;let query=dyn.selectFrom(table);query=applySorting(query,sort,readColumns);const RESERVED=new Set(["page","per_page","sort","fields","search","include","limit","offset","with_count","withTrashed","onlyTrashed"]);for(const[key,value]of url.searchParams.entries()){if(RESERVED.has(key)||!value)continue;if(!/^[a-z_][a-z0-9_]*$/i.test(key))continue;const col=readColumns.get(key);if(col)query=query.where(col,"=",value)}const searchTerm=url.searchParams.get("search");if(searchTerm&&fillableFields.length>0){const textFields=fillableFields.slice(0,5);query=query.where((qb)=>{for(const field of textFields)qb=qb.orWhere(toSnakeCase(field),"like",`%${searchTerm}%`);return qb})}const fieldsParam=url.searchParams.get("fields");if(fieldsParam){const selectedFields=fieldsParam.split(",").map((f)=>f.trim()).filter((f)=>/^[a-z_][a-z0-9_]*$/i.test(f)).map((f)=>toSnakeCase(f));if(selectedFields.length>0)query=query.select(selectedFields)}const usesSoftDeletes=!!model.traits?.useSoftDeletes,withTrashed=url.searchParams.get("withTrashed")==="true",onlyTrashed=url.searchParams.get("onlyTrashed")==="true";if(usesSoftDeletes&&!withTrashed)query=onlyTrashed?query.whereNotNull("deleted_at"):query.whereNull("deleted_at");const own=rowScoped?await resolveOwnership(model,await authedUserFromRequest(req),req):{enforced:!1,value:null,field:"",bypass:!1};if(own.enforced&&!own.bypass){if(own.value==null||Array.isArray(own.value)&&own.value.length===0){const emptyPaginator=buildIndexPaginator(url,page,perPage,0,!1,void 0);return new Response(JSON.stringify({data:[],...emptyPaginator}),{status:200,headers:{"Content-Type":"application/json","Cache-Control":"private, no-store",Vary:"Authorization"}})}query=Array.isArray(own.value)?query.where(own.field,"in",own.value):query.where(own.field,"=",own.value)}const rawResults=await query.limit(perPage+1).offset(offset).get()||[],hasMore=rawResults.length>perPage;let records=(hasMore?rawResults.slice(0,perPage):rawResults).map((r)=>stripHidden(applyReadCasts(r,model),hiddenFields));const includeParam=url.searchParams.get("include");if(includeParam)records=await applyIncludes(records,model,includeParam,models);const wantCount=url.searchParams.get("with_count")==="true";let total;if(wantCount)try{let countQuery=dyn.selectFrom(table);if(own.enforced&&!own.bypass&&own.value!=null)countQuery=Array.isArray(own.value)?countQuery.where(own.field,"in",own.value):countQuery.where(own.field,"=",own.value);const raw=await countQuery.count(),n=typeof raw==="number"?raw:Number(raw?.count??raw);if(Number.isFinite(n))total=n}catch{}const respHeaders={"Content-Type":"application/json"};if(total!==void 0&&!Number.isNaN(total))respHeaders["X-Total-Count"]=String(total);respHeaders["Cache-Control"]=own.enforced&&!own.bypass?"private, no-store":"public, max-age=15, must-revalidate";respHeaders.Vary="Authorization";const paginator=buildIndexPaginator(url,page,perPage,records.length,hasMore,total);return new Response(JSON.stringify({data:records,...paginator}),{status:200,headers:respHeaders})}catch(err){if(err instanceof HttpError){const body={error:err.message};if(err.details!==void 0)body.details=err.details;return jsonResponse(body,err.status||400)}return jsonResponse({error:`Failed to fetch ${uri}`,detail:String(err)},500)}}),indexMiddleware);if(enabledRoutes.includes("show")&&!routeClaimed("GET",`${basePath}/{id}`))applyMiddleware(route.get(`${basePath}/{id}`,async(req)=>{try{const id=coerceId(req.params?.id);if(id==null)return jsonResponse({error:"Invalid ID parameter"},400);const result=await dyn.selectFrom(table).where({id}).executeTakeFirst();if(!result)return jsonResponse({error:`${modelName} not found`},404);const url=new URL(req.url);if(model.traits?.useSoftDeletes&&result.deleted_at&&url.searchParams.get("withTrashed")!=="true")return jsonResponse({error:`${modelName} not found`},404);const own=rowScoped?await resolveOwnership(model,await authedUserFromRequest(req),req):{enforced:!1,value:null,field:"",bypass:!1};if(own.enforced&&!own.bypass){if(own.value==null||!ownsRow(result[own.field],own.value))return jsonResponse({error:`${modelName} not found`},404)}const refusedView=await policyRefusal(modelName,"view",req,result);if(refusedView)return refusedView;let payload=stripHidden(applyReadCasts(result,model),hiddenFields);const includeParam=url.searchParams.get("include");if(includeParam){const[withRel]=await applyIncludes([payload],model,includeParam,models);payload=withRel}const lastWrite=payload?.updated_at||payload?.created_at,etag=lastWrite?`W/"${payload.id}-${String(lastWrite)}"`:void 0,ifNoneMatch=req.headers?.get?.("if-none-match");if(etag&&ifNoneMatch&&ifNoneMatch===etag)return new Response(null,{status:304,headers:{ETag:etag}});const headers={"Content-Type":"application/json"};if(etag)headers.ETag=etag;headers["Cache-Control"]=own.enforced&&!own.bypass?"private, no-store":"public, max-age=30, must-revalidate";headers.Vary="Authorization";return new Response(JSON.stringify({data:payload}),{status:200,headers})}catch(err){if(err instanceof HttpError){const body={error:err.message};if(err.details!==void 0)body.details=err.details;return jsonResponse(body,err.status||400)}return jsonResponse({error:`Failed to fetch ${modelName}`,detail:String(err)},500)}}),showMiddleware);if(!skipMutatingRoutes&&enabledRoutes.includes("store")&&!routeClaimed("POST",basePath))applyMiddleware(route.post(basePath,async(req)=>{try{const body=await getRequestBody(req),safeBody=dropHiddenInputs(body,hiddenFields);let data=filterFillable(safeBody,fillableFields);const authedUser=await authedUserFromRequest(req);if(authedUser){const stamped=await resolveAuthedFill(model,"creating",authedUser,req);for(const[k,v]of Object.entries(stamped))if(v!==void 0&&v!==null&&data[k]===void 0)data[k]=v}const refusedCreate=await policyRefusal(modelName,"create",req);if(refusedCreate)return refusedCreate;const own=await resolveOwnership(model,authedUser,req);if(own.enforced&&!own.bypass){if(!authedUser)return jsonResponse({error:"Auth required"},401);const stamped=stampOwnership(data,own.field,own.value);if(stamped.error)return jsonResponse({error:stamped.error},403);data=stamped.data}if(Object.keys(data).length===0)return jsonResponse({error:"No fillable fields provided"},422);const v=validateWriteBody(data,model,"creating");if(!v.valid)return jsonResponse({success:!1,message:"Validation failed",errors:v.errors},422);if(model.traits?.useTimestamps!==!1){const now=new Date().toISOString();data.created_at=now;data.updated_at=now}const hookedData=await applyDefinedSetters(data,model),writeData=toSnakeCaseKeys(applySetCasts(hookedData,model)),result=await dyn.insertInto(table).values(writeData).execute();let created=writeData;try{const lastId=result?.lastInsertRowid??result?.insertId??result;if(lastId){const fetched=await dyn.selectFrom(table).where({id:lastId}).executeTakeFirst();if(fetched)created=fetched}}catch{}return jsonResponse({data:stripHidden(applyReadCasts(created,model),hiddenFields)},201)}catch(err){const{status,body}=mapWriteError(err,modelName,"create");return jsonResponse(body,status)}}),abilities.store);if(!skipMutatingRoutes&&enabledRoutes.includes("update")){const updateHandler=async(req)=>{try{const id=coerceId(req.params?.id);if(id==null)return jsonResponse({error:"Invalid ID parameter"},400);const body=await getRequestBody(req),safeBody=dropHiddenInputs(body,hiddenFields),data=filterFillable(safeBody,fillableFields),authedUser=await authedUserFromRequest(req);if(authedUser){const stamped=await resolveAuthedFill(model,"updating",authedUser,req);for(const[k,v]of Object.entries(stamped))if(v!==void 0&&v!==null&&data[k]===void 0)data[k]=v}if(Object.keys(data).length===0)return jsonResponse({error:"No fillable fields provided"},422);const v=validateWriteBody(data,model,"updating");if(!v.valid)return jsonResponse({success:!1,message:"Validation failed",errors:v.errors},422);const existing=await dyn.selectFrom(table).where({id}).executeTakeFirst();if(!existing)return jsonResponse({error:`${modelName} not found`},404);const refusedUpdate=await policyRefusal(modelName,"update",req,existing);if(refusedUpdate)return refusedUpdate;const own=await resolveOwnership(model,authedUser,req);if(own.enforced&&!own.bypass){if(!authedUser)return jsonResponse({error:"Auth required"},401);const rowOwner=existing[own.field];if(!ownsRow(rowOwner,own.value))return jsonResponse({error:`Not your ${modelName}`},403);const submittedOwnerKey=Object.keys(data).find((k)=>toSnakeCase(k)===toSnakeCase(own.field));if(submittedOwnerKey!==void 0&&!ownsRow(data[submittedOwnerKey],own.value))return jsonResponse({error:`Cannot reassign ${modelName} ownership`},403)}if(model.traits?.useTimestamps!==!1)data.updated_at=new Date().toISOString();const hookedData=await applyDefinedSetters(data,model),writeData=toSnakeCaseKeys(applySetCasts(hookedData,model));await dyn.updateTable(table).set(writeData).where({id}).execute();let updated={...existing,...writeData};try{const fetched=await dyn.selectFrom(table).where({id}).executeTakeFirst();if(fetched)updated=fetched}catch{}return jsonResponse({data:stripHidden(applyReadCasts(updated,model),hiddenFields)})}catch(err){const{status,body}=mapWriteError(err,modelName,"update");return jsonResponse(body,status)}};if(!routeClaimed("PUT",`${basePath}/{id}`))applyMiddleware(route.put(`${basePath}/{id}`,updateHandler),abilities.update);if(!routeClaimed("PATCH",`${basePath}/{id}`))applyMiddleware(route.patch(`${basePath}/{id}`,updateHandler),abilities.update)}const usesSoftDeletes=!!model.traits?.useSoftDeletes;if(!skipMutatingRoutes&&enabledRoutes.includes("destroy")&&!routeClaimed("DELETE",`${basePath}/{id}`))applyMiddleware(route.delete(`${basePath}/{id}`,async(req)=>{try{const id=coerceId(req.params?.id);if(id==null)return jsonResponse({error:"Invalid ID parameter"},400);const existing=await dyn.selectFrom(table).where({id}).executeTakeFirst();if(!existing)return jsonResponse({error:`${modelName} not found`},404);const authedUser=await authedUserFromRequest(req),own=await resolveOwnership(model,authedUser,req);if(own.enforced&&!own.bypass){if(!authedUser)return jsonResponse({error:"Auth required"},401);const rowOwner=existing[own.field];if(!ownsRow(rowOwner,own.value))return jsonResponse({error:`Not your ${modelName}`},403)}const refusedDelete=await policyRefusal(modelName,"delete",req,existing);if(refusedDelete)return refusedDelete;if(usesSoftDeletes){const now=new Date().toISOString();await dyn.updateTable(table).set({deleted_at:now,updated_at:now}).where({id}).execute()}else await dyn.deleteFrom(table).where({id}).execute();return new Response(null,{status:204})}catch(err){if(err instanceof HttpError){const body={error:err.message};if(err.details!==void 0)body.details=err.details;return jsonResponse(body,err.status||400)}return jsonResponse({error:`Failed to delete ${modelName}`,detail:String(err)},500)}}),abilities.destroy);if(!skipMutatingRoutes&&enabledRoutes.includes("destroy")&&!routeClaimed("POST",`${basePath}/bulk-delete`))applyMiddleware(route.post(`${basePath}/bulk-delete`,async(req)=>{try{const ids=(await getRequestBody(req))?.ids;if(!Array.isArray(ids)||ids.length===0)return jsonResponse({error:"An array of IDs is required"},422);if(ids.length>100)return jsonResponse({error:"Cannot delete more than 100 records at once"},422);const validIds=[],invalidIds=[];for(const raw of ids){const coerced=coerceId(raw);if(coerced!=null)validIds.push(coerced);else invalidIds.push(raw)}if(invalidIds.length>0)return jsonResponse({error:"Invalid IDs in batch",invalid:invalidIds},422);const authedUser=await authedUserFromRequest(req),own=await resolveOwnership(model,authedUser,req);if(own.enforced&&!own.bypass){if(!authedUser)return jsonResponse({error:"Auth required"},401);if(own.value==null)return jsonResponse({error:"Caller has no ownership identity"},403);const rows=await dyn.selectFrom(table).select(["id",own.field]).execute(),ownedIds=new Set(rows.filter((r)=>ownsRow(r[own.field],own.value)).map((r)=>String(r.id))),notOwned=validIds.filter((id)=>!ownedIds.has(String(id)));if(notOwned.length>0)return jsonResponse({error:`Cannot delete ${modelName} you don't own`,ids:notOwned},403)}if(await hasPolicyFor(modelName)){const refusedRows=[];for(const id of validIds){const row=await dyn.selectFrom(table).where({id}).executeTakeFirst();if(!row)continue;if(await policyRefusal(modelName,"delete",req,row))refusedRows.push(id)}if(refusedRows.length>0)return jsonResponse({error:`Cannot delete ${modelName} this policy refuses`,ids:refusedRows},403)}const now=new Date().toISOString();for(const id of validIds)if(usesSoftDeletes)await dyn.updateTable(table).set({deleted_at:now,updated_at:now}).where({id}).execute();else await dyn.deleteFrom(table).where({id}).execute();return jsonResponse({message:`Successfully deleted ${validIds.length} ${uri}`})}catch(err){if(err instanceof HttpError){const body={error:err.message};if(err.details!==void 0)body.details=err.details;return jsonResponse(body,err.status||400)}return jsonResponse({error:`Failed to bulk delete ${uri}`,detail:String(err)},500)}}),abilities.destroy)}{const report=describeUnscopedMutatingModels(unscopedMutatingModels,rowScopingPolicy);if(report)log.warn(report);const contradictions=describeContradictoryRoleGates(contradictoryRoleGates);if(contradictions)log.warn(contradictions)}export default route;