@stacksjs/orm 0.75.41 → 0.75.43

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 (57) hide show
  1. package/dist/define-model.d.ts +8 -0
  2. package/dist/gdpr/engine.d.ts +82 -0
  3. package/dist/gdpr/index.d.ts +20 -0
  4. package/dist/gdpr/models.d.ts +9 -0
  5. package/dist/gdpr/plan.d.ts +12 -0
  6. package/dist/gdpr/register.d.ts +30 -0
  7. package/dist/gdpr/types.d.ts +88 -0
  8. package/dist/index.d.ts +5 -0
  9. package/dist/index.js +16 -11
  10. package/dist/model-registry.js +1 -1
  11. package/dist/models/Activity.ts +2 -0
  12. package/dist/models/CampaignSend.ts +2 -0
  13. package/dist/models/Card.ts +1 -0
  14. package/dist/models/CardComment.ts +1 -0
  15. package/dist/models/Comment.ts +5 -0
  16. package/dist/models/CommunicationSuppression.ts +2 -1
  17. package/dist/models/ConsentEvent.ts +4 -3
  18. package/dist/models/Content/Author.ts +5 -0
  19. package/dist/models/EmailListSubscriber.ts +1 -0
  20. package/dist/models/EmailSuppression.ts +2 -0
  21. package/dist/models/Forms/FormSubmission.ts +5 -0
  22. package/dist/models/GdprRequest.ts +77 -0
  23. package/dist/models/MagicLinkToken.ts +2 -0
  24. package/dist/models/Notification.ts +2 -0
  25. package/dist/models/NotificationDelivery.ts +4 -0
  26. package/dist/models/PaymentMethod.ts +5 -0
  27. package/dist/models/PaymentTransaction.ts +1 -0
  28. package/dist/models/PersonalAccessToken.ts +3 -0
  29. package/dist/models/Referral.ts +4 -1
  30. package/dist/models/ReferralCode.ts +4 -1
  31. package/dist/models/Request.ts +3 -0
  32. package/dist/models/SmsOptOut.ts +2 -0
  33. package/dist/models/SocialAccount.ts +3 -0
  34. package/dist/models/SocialPost.ts +2 -0
  35. package/dist/models/StorageItemTask.ts +14 -8
  36. package/dist/models/Subscriber.ts +2 -0
  37. package/dist/models/SubscriberEmail.ts +2 -0
  38. package/dist/models/Subscription.ts +1 -0
  39. package/dist/models/TeamInvitation.ts +2 -0
  40. package/dist/models/TeamMember.ts +1 -0
  41. package/dist/models/User.ts +5 -0
  42. package/dist/models/commerce/Bid.ts +3 -0
  43. package/dist/models/commerce/Cart.ts +2 -0
  44. package/dist/models/commerce/Courier.ts +7 -0
  45. package/dist/models/commerce/CourierPing.ts +3 -0
  46. package/dist/models/commerce/Customer.ts +5 -0
  47. package/dist/models/commerce/DeliveryStop.ts +7 -0
  48. package/dist/models/commerce/GiftCard.ts +4 -0
  49. package/dist/models/commerce/Order.ts +5 -0
  50. package/dist/models/commerce/OrderItem.ts +2 -0
  51. package/dist/models/commerce/Payment.ts +5 -0
  52. package/dist/models/commerce/Pledge.ts +3 -0
  53. package/dist/models/commerce/Transaction.ts +2 -0
  54. package/dist/models/commerce/WaitlistProduct.ts +5 -0
  55. package/dist/models/commerce/WaitlistRestaurant.ts +4 -0
  56. package/dist/routes.js +1 -1
  57. package/package.json +24 -24
@@ -34,6 +34,7 @@ export default defineModel({
34
34
  belongsTo: ['Team'],
35
35
 
36
36
  traits: {
37
+ gdpr: { subject: { email: 'email' }, erasure: 'delete', basis: 'contract', purpose: 'Team invitations' },
37
38
  useUuid: true,
38
39
  useTimestamps: true,
39
40
  useSeeder: { count: 0 },
@@ -60,6 +61,7 @@ export default defineModel({
60
61
  },
61
62
 
62
63
  email: {
64
+ personal: true,
63
65
  required: true,
64
66
  fillable: true,
65
67
  validation: {
@@ -30,6 +30,7 @@ export default defineModel({
30
30
  belongsTo: ['Team', 'User'],
31
31
 
32
32
  traits: {
33
+ gdpr: { erasure: 'delete', basis: 'contract', purpose: 'Team membership' },
33
34
  useUuid: true,
34
35
  useTimestamps: true,
35
36
  useSeeder: { count: 0 },
@@ -25,6 +25,7 @@ export default defineModel({
25
25
  ownership: selfOwnership(),
26
26
 
27
27
  traits: {
28
+ gdpr: { erasure: 'anonymize', basis: 'contract', purpose: 'User account and sign-in' },
28
29
  useAuth: {
29
30
  usePasskey: true,
30
31
  },
@@ -72,6 +73,7 @@ export default defineModel({
72
73
 
73
74
  attributes: {
74
75
  name: {
76
+ personal: true,
75
77
  order: 2,
76
78
  fillable: true,
77
79
  validation: {
@@ -86,6 +88,7 @@ export default defineModel({
86
88
  },
87
89
 
88
90
  email: {
91
+ personal: true,
89
92
  unique: true,
90
93
  order: 1,
91
94
  fillable: true,
@@ -100,6 +103,7 @@ export default defineModel({
100
103
  factory: faker => faker.internet.email(),
101
104
  },
102
105
  password: {
106
+ personal: { export: false },
103
107
  order: 3,
104
108
  hidden: true,
105
109
  fillable: true,
@@ -118,6 +122,7 @@ export default defineModel({
118
122
  },
119
123
 
120
124
  avatar: {
125
+ personal: true,
121
126
  order: 4,
122
127
  fillable: true,
123
128
  validation: {
@@ -21,6 +21,7 @@ export default defineModel({
21
21
  autoIncrement: true,
22
22
 
23
23
  traits: {
24
+ gdpr: { subject: { email: 'bidder_email' }, erasure: 'anonymize', basis: 'contract', purpose: 'Auction bids' },
24
25
  useUuid: true,
25
26
  useTimestamps: true,
26
27
 
@@ -54,6 +55,7 @@ export default defineModel({
54
55
 
55
56
  attributes: {
56
57
  bidderName: {
58
+ personal: true,
57
59
  order: 1,
58
60
  fillable: true,
59
61
  validation: {
@@ -66,6 +68,7 @@ export default defineModel({
66
68
  },
67
69
 
68
70
  bidderEmail: {
71
+ personal: true,
69
72
  order: 2,
70
73
  fillable: true,
71
74
  validation: {
@@ -13,6 +13,7 @@ export default defineModel({
13
13
  ownership: customerOwnership(),
14
14
 
15
15
  traits: {
16
+ gdpr: { subject: { via: 'Customer' }, erasure: 'anonymize', basis: 'contract', purpose: 'Shopping cart' },
16
17
  useUuid: true,
17
18
  useTimestamps: true,
18
19
  useSearch: {
@@ -122,6 +123,7 @@ export default defineModel({
122
123
  },
123
124
 
124
125
  notes: {
126
+ personal: true,
125
127
  order: 9,
126
128
  fillable: true,
127
129
  validation: {
@@ -11,6 +11,7 @@ export default defineModel({
11
11
  hasMany: ['DeliveryRoute', 'CourierPing'],
12
12
 
13
13
  traits: {
14
+ gdpr: { erasure: 'anonymize', basis: 'contract', purpose: 'Courier profile and live position for deliveries' },
14
15
  useUuid: true,
15
16
  useTimestamps: true,
16
17
  useSearch: {
@@ -34,6 +35,7 @@ export default defineModel({
34
35
 
35
36
  attributes: {
36
37
  name: {
38
+ personal: true,
37
39
  order: 1,
38
40
  fillable: true,
39
41
  validation: {
@@ -46,6 +48,7 @@ export default defineModel({
46
48
  },
47
49
 
48
50
  phone: {
51
+ personal: true,
49
52
  order: 2,
50
53
  fillable: true,
51
54
  validation: {
@@ -58,6 +61,7 @@ export default defineModel({
58
61
  },
59
62
 
60
63
  vehicleNumber: {
64
+ personal: true,
61
65
  order: 3,
62
66
  fillable: true,
63
67
  validation: {
@@ -70,6 +74,7 @@ export default defineModel({
70
74
  },
71
75
 
72
76
  license: {
77
+ personal: true,
73
78
  order: 4,
74
79
  fillable: true,
75
80
  validation: {
@@ -101,6 +106,7 @@ export default defineModel({
101
106
  * the history; these three columns are the present.
102
107
  */
103
108
  latitude: {
109
+ personal: true,
104
110
  order: 6,
105
111
  fillable: true,
106
112
  validation: {
@@ -114,6 +120,7 @@ export default defineModel({
114
120
  },
115
121
 
116
122
  longitude: {
123
+ personal: true,
117
124
  order: 7,
118
125
  fillable: true,
119
126
  validation: {
@@ -22,6 +22,7 @@ export default defineModel({
22
22
  autoIncrement: true,
23
23
 
24
24
  traits: {
25
+ gdpr: { subject: { via: 'Courier' }, erasure: 'delete', basis: 'contract', purpose: 'Courier location history' },
25
26
  useUuid: true,
26
27
  useTimestamps: true,
27
28
  useSeeder: { count: 0 },
@@ -31,6 +32,7 @@ export default defineModel({
31
32
 
32
33
  attributes: {
33
34
  latitude: {
35
+ personal: true,
34
36
  order: 1,
35
37
  required: true,
36
38
  fillable: true,
@@ -45,6 +47,7 @@ export default defineModel({
45
47
  },
46
48
 
47
49
  longitude: {
50
+ personal: true,
48
51
  order: 2,
49
52
  required: true,
50
53
  fillable: true,
@@ -9,6 +9,7 @@ export default defineModel({
9
9
  autoIncrement: true,
10
10
 
11
11
  traits: {
12
+ gdpr: { erasure: 'anonymize', basis: 'contract', purpose: 'Customer record behind orders and payments' },
12
13
  useUuid: true,
13
14
  useTimestamps: true,
14
15
  useSearch: {
@@ -35,6 +36,7 @@ export default defineModel({
35
36
 
36
37
  attributes: {
37
38
  name: {
39
+ personal: true,
38
40
  order: 1,
39
41
  fillable: true,
40
42
  validation: {
@@ -48,6 +50,7 @@ export default defineModel({
48
50
  },
49
51
 
50
52
  email: {
53
+ personal: true,
51
54
  unique: true,
52
55
  order: 2,
53
56
  fillable: true,
@@ -61,6 +64,7 @@ export default defineModel({
61
64
  },
62
65
 
63
66
  phone: {
67
+ personal: true,
64
68
  order: 3,
65
69
  fillable: true,
66
70
  validation: {
@@ -109,6 +113,7 @@ export default defineModel({
109
113
  },
110
114
 
111
115
  avatar: {
116
+ personal: true,
112
117
  order: 8,
113
118
  fillable: true,
114
119
  validation: {
@@ -24,6 +24,7 @@ export default defineModel({
24
24
  ownership: parentOwnership('Order', 'order_id'),
25
25
 
26
26
  traits: {
27
+ gdpr: { subject: { via: 'Order' }, erasure: 'anonymize', basis: 'contract', purpose: 'Delivering an order' },
27
28
  useUuid: true,
28
29
  useTimestamps: true,
29
30
 
@@ -78,6 +79,7 @@ export default defineModel({
78
79
  },
79
80
 
80
81
  address: {
82
+ personal: true,
81
83
  order: 3,
82
84
  required: true,
83
85
  fillable: true,
@@ -91,6 +93,7 @@ export default defineModel({
91
93
  * complete; it just cannot be drawn.
92
94
  */
93
95
  latitude: {
96
+ personal: true,
94
97
  order: 4,
95
98
  fillable: true,
96
99
  validation: { rule: schema.number().min(-90).max(90) },
@@ -98,6 +101,7 @@ export default defineModel({
98
101
  },
99
102
 
100
103
  longitude: {
104
+ personal: true,
101
105
  order: 5,
102
106
  fillable: true,
103
107
  validation: { rule: schema.number().min(-180).max(180) },
@@ -105,6 +109,7 @@ export default defineModel({
105
109
  },
106
110
 
107
111
  recipientName: {
112
+ personal: true,
108
113
  order: 6,
109
114
  fillable: true,
110
115
  validation: { rule: schema.string().max(255) },
@@ -112,6 +117,7 @@ export default defineModel({
112
117
  },
113
118
 
114
119
  recipientPhone: {
120
+ personal: true,
115
121
  order: 7,
116
122
  fillable: true,
117
123
  validation: { rule: schema.string().max(40) },
@@ -158,6 +164,7 @@ export default defineModel({
158
164
 
159
165
  /** Why a stop failed, or anything the courier needs to record. */
160
166
  notes: {
167
+ personal: true,
161
168
  order: 12,
162
169
  fillable: true,
163
170
  validation: { rule: schema.string().max(1000) },
@@ -13,6 +13,7 @@ export default defineModel({
13
13
  ownership: customerOwnership(),
14
14
 
15
15
  traits: {
16
+ gdpr: { subject: { via: 'Customer' }, erasure: 'anonymize', basis: 'contract', purpose: 'Gift cards bought by the customer' },
16
17
  useUuid: true,
17
18
  useTimestamps: true,
18
19
  useSearch: {
@@ -101,6 +102,7 @@ export default defineModel({
101
102
  },
102
103
 
103
104
  recipient_email: {
105
+ personal: true,
104
106
  order: 7,
105
107
  fillable: true,
106
108
  validation: {
@@ -110,6 +112,7 @@ export default defineModel({
110
112
  },
111
113
 
112
114
  recipientName: {
115
+ personal: true,
113
116
  order: 8,
114
117
  fillable: true,
115
118
  validation: {
@@ -119,6 +122,7 @@ export default defineModel({
119
122
  },
120
123
 
121
124
  personalMessage: {
125
+ personal: true,
122
126
  order: 9,
123
127
  fillable: true,
124
128
  validation: {
@@ -13,6 +13,7 @@ export default defineModel({
13
13
  ownership: customerOwnership(),
14
14
 
15
15
  traits: {
16
+ gdpr: { subject: { via: 'Customer' }, erasure: 'anonymize', basis: 'legal_obligation', purpose: 'Order fulfilment, kept for tax and accounting' },
16
17
  useUuid: true,
17
18
  useTimestamps: true,
18
19
  useSearch: {
@@ -128,6 +129,7 @@ export default defineModel({
128
129
  },
129
130
 
130
131
  deliveryAddress: {
132
+ personal: true,
131
133
  order: 10,
132
134
  fillable: true,
133
135
  validation: {
@@ -137,6 +139,7 @@ export default defineModel({
137
139
  },
138
140
 
139
141
  specialInstructions: {
142
+ personal: true,
140
143
  order: 11,
141
144
  fillable: true,
142
145
  validation: {
@@ -175,6 +178,7 @@ export default defineModel({
175
178
 
176
179
  /** Geocoded delivery destination, so the map has somewhere to point. */
177
180
  deliveryLatitude: {
181
+ personal: true,
178
182
  order: 14,
179
183
  fillable: true,
180
184
  validation: { rule: schema.number().min(-90).max(90) },
@@ -182,6 +186,7 @@ export default defineModel({
182
186
  },
183
187
 
184
188
  deliveryLongitude: {
189
+ personal: true,
185
190
  order: 15,
186
191
  fillable: true,
187
192
  validation: { rule: schema.number().min(-180).max(180) },
@@ -8,6 +8,7 @@ export default defineModel({
8
8
  autoIncrement: true,
9
9
 
10
10
  traits: {
11
+ gdpr: { subject: { via: 'Order' }, erasure: 'anonymize', basis: 'legal_obligation', purpose: 'Order lines, kept for tax and accounting' },
11
12
  useTimestamps: true,
12
13
  },
13
14
 
@@ -41,6 +42,7 @@ export default defineModel({
41
42
  },
42
43
 
43
44
  special_instructions: {
45
+ personal: true,
44
46
  order: 5,
45
47
  fillable: true,
46
48
  validation: {
@@ -13,6 +13,7 @@ export default defineModel({
13
13
  ownership: customerOwnership(),
14
14
 
15
15
  traits: {
16
+ gdpr: { subject: { via: 'Customer' }, erasure: 'anonymize', basis: 'legal_obligation', purpose: 'Payment records, kept for tax and accounting' },
16
17
  useUuid: true,
17
18
  useTimestamps: true,
18
19
  useSearch: {
@@ -116,6 +117,7 @@ export default defineModel({
116
117
  },
117
118
 
118
119
  cardLastFour: {
120
+ personal: true,
119
121
  order: 9,
120
122
  fillable: true,
121
123
  validation: {
@@ -125,6 +127,7 @@ export default defineModel({
125
127
  },
126
128
 
127
129
  cardBrand: {
130
+ personal: true,
128
131
  order: 10,
129
132
  fillable: true,
130
133
  validation: {
@@ -134,6 +137,7 @@ export default defineModel({
134
137
  },
135
138
 
136
139
  billingEmail: {
140
+ personal: true,
137
141
  order: 11,
138
142
  fillable: true,
139
143
  validation: {
@@ -172,6 +176,7 @@ export default defineModel({
172
176
  },
173
177
 
174
178
  notes: {
179
+ personal: true,
175
180
  order: 15,
176
181
  fillable: true,
177
182
  validation: {
@@ -16,6 +16,7 @@ export default defineModel({
16
16
  autoIncrement: true,
17
17
 
18
18
  traits: {
19
+ gdpr: { subject: { via: 'Customer' }, erasure: 'anonymize', basis: 'legal_obligation', purpose: 'Donation pledges, kept for receipts' },
19
20
  useUuid: true,
20
21
  useTimestamps: true,
21
22
 
@@ -50,6 +51,7 @@ export default defineModel({
50
51
 
51
52
  attributes: {
52
53
  donorName: {
54
+ personal: true,
53
55
  order: 1,
54
56
  fillable: true,
55
57
  validation: {
@@ -62,6 +64,7 @@ export default defineModel({
62
64
  },
63
65
 
64
66
  donorEmail: {
67
+ personal: true,
65
68
  order: 2,
66
69
  fillable: true,
67
70
  validation: {
@@ -13,6 +13,7 @@ export default defineModel({
13
13
  ownership: parentOwnership('Order', 'order_id'),
14
14
 
15
15
  traits: {
16
+ gdpr: { subject: { via: 'Order' }, erasure: 'anonymize', basis: 'legal_obligation', purpose: 'Payment transactions, kept for tax and accounting' },
16
17
  useUuid: true,
17
18
  useTimestamps: true,
18
19
  useSearch: {
@@ -66,6 +67,7 @@ export default defineModel({
66
67
  },
67
68
 
68
69
  paymentDetails: {
70
+ personal: true,
69
71
  order: 5,
70
72
  fillable: true,
71
73
  hidden: true,
@@ -13,6 +13,7 @@ export default defineModel({
13
13
  ownership: customerOwnership(),
14
14
 
15
15
  traits: {
16
+ gdpr: { subject: { via: 'Customer' }, erasure: 'delete', basis: 'consent', purpose: 'Back-in-stock waitlist' },
16
17
  useUuid: true,
17
18
  useTimestamps: true,
18
19
  useSearch: {
@@ -37,6 +38,7 @@ export default defineModel({
37
38
 
38
39
  attributes: {
39
40
  name: {
41
+ personal: true,
40
42
  order: 1,
41
43
  fillable: true,
42
44
  validation: {
@@ -49,6 +51,7 @@ export default defineModel({
49
51
  },
50
52
 
51
53
  email: {
54
+ personal: true,
52
55
  order: 2,
53
56
  fillable: true,
54
57
  validation: {
@@ -61,6 +64,7 @@ export default defineModel({
61
64
  },
62
65
 
63
66
  phone: {
67
+ personal: true,
64
68
  order: 3,
65
69
  fillable: true,
66
70
  validation: {
@@ -106,6 +110,7 @@ export default defineModel({
106
110
  },
107
111
 
108
112
  notes: {
113
+ personal: true,
109
114
  order: 7,
110
115
  fillable: true,
111
116
  validation: {
@@ -13,6 +13,7 @@ export default defineModel({
13
13
  ownership: customerOwnership(),
14
14
 
15
15
  traits: {
16
+ gdpr: { subject: { via: 'Customer' }, erasure: 'delete', basis: 'contract', purpose: 'Restaurant waitlist' },
16
17
  useUuid: true,
17
18
  useTimestamps: true,
18
19
  useSearch: {
@@ -37,6 +38,7 @@ export default defineModel({
37
38
 
38
39
  attributes: {
39
40
  name: {
41
+ personal: true,
40
42
  order: 1,
41
43
  fillable: true,
42
44
  validation: {
@@ -49,6 +51,7 @@ export default defineModel({
49
51
  },
50
52
 
51
53
  email: {
54
+ personal: true,
52
55
  order: 2,
53
56
  fillable: true,
54
57
  validation: {
@@ -61,6 +64,7 @@ export default defineModel({
61
64
  },
62
65
 
63
66
  phone: {
67
+ personal: true,
64
68
  order: 3,
65
69
  fillable: true,
66
70
  validation: {
package/dist/routes.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import Rt from"process";import{route as U}from"@stacksjs/router";import{env as z}from"@stacksjs/env";import{projectPath as Se,storagePath as kt}from"@stacksjs/path";import{createQueryBuilder as _t,defaultConfig as ze,setConfig as He}from"@stacksjs/query-builder";import{HttpError as W}from"@stacksjs/error-handling";import{log as J}from"@stacksjs/logging/runtime";function ot(e){let t=e;return t?.code==="SQLITE_CONSTRAINT_UNIQUE"||t?.code==="SQLITE_CONSTRAINT"||t?.code==="23505"||t?.errno===1062||/unique|duplicate/i.test(t?.message??"")}function ce(e,t,n){let r=e;if(e instanceof Error&&typeof r.status==="number"&&Number.isInteger(r.status)&&r.status>=400&&r.status<600){let o={error:e.message};if(r.details!==void 0)o.details=r.details;return{status:r.status,body:o}}if(ot(e))return{status:409,body:{error:`${t} already exists`}};return{status:500,body:{error:`Failed to ${n} ${t}`,detail:String(e)}}}function _(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 s=r>0?e.charCodeAt(r-1):0,i=r+1<e.length?e.charCodeAt(r+1):0,c=s>=97&&s<=122||s>=48&&s<=57,f=s>=65&&s<=90&&i>=97&&i<=122;if(r>0&&(c||f))n+="_";n+=String.fromCharCode(o+32)}return n}function de(e){let t={};for(let[n,r]of Object.entries(e))t[_(n)]=r;return t}function Ce(e,t){let n=String(t||"").replace(/^\/+|\/+$/g,""),r=String(e).replace(/^\/+/,"");return`/api/${n?`${n}/`:""}${r}`}function Pe(e){if(!e)return null;let t=e.attributes??{};if(Object.prototype.hasOwnProperty.call(t,"teamId")||Object.prototype.hasOwnProperty.call(t,"team_id"))return"team_id";return e.belongsTo?.some((n)=>n==="Team")?"team_id":null}function $e(e){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 Ie(e){return e?.ownership===!1}function Ne(e,t,n){let r=Object.keys(e).find((s)=>_(s)===_(t));if(Array.isArray(n)){if(r===void 0)return{data:e,error:"Ownership value is required"};if(!n.some((s)=>String(s)===String(e[r])))return{data:e,error:"Ownership value is not available to this caller"};return{data:{...e,[t]:e[r]}}}if(n===null||n===void 0)return{data:e,error:"Caller has no ownership identity"};let o={...e};for(let s of Object.keys(o))if(_(s)===_(t))delete o[s];return o[t]=n,{data:o}}function Me(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=_(n.trim()).split("_").filter(Boolean);if(r.length===0)continue;let o=`${r[0]}${r.slice(1).map((s)=>`${s[0]?.toUpperCase()}${s.slice(1)}`).join("")}Id`;t.push(o)}return[...new Set(t)]}function fe(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??=it(t);let s=r.get(o);if(s!==o&&s in e)n[o]=e[s]}return n}function st(e,t){if(e?.name!=="date"||t instanceof Date||typeof t!=="string")return t;let n=/^(\d{4})-(\d{2})-(\d{2})$/.exec(t);if(!n)return t;let r=Number(n[1]),o=Number(n[2]),s=Number(n[3]),i=new Date(Date.UTC(r,o-1,s));if(i.getUTCFullYear()!==r||i.getUTCMonth()!==o-1||i.getUTCDate()!==s)return t;return i}var ve=new WeakMap,Oe=new WeakMap;function ge(e){let t=ve.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:_(r)}));return ve.set(e,n),n}function it(e){let t=ge(e),n=Oe.get(t);if(n)return n;let r=new Map(t.map(({field:o,snake:s})=>[o,s]));return Oe.set(t,r),r}function pe(e,t){if(!t.length)return e;let n={...e};for(let{field:r,snake:o}of ge(t))if(delete n[r],o!==r)delete n[o];return n}function G(e,t){if(!e||t.length===0)return e;let n={...e};for(let{field:r,snake:o}of ge(t))if(delete n[r],o!==r)delete n[o];return n}var at=["id","uuid","created_at","updated_at","deleted_at"];function je(e,t){let n=new Map;for(let r of[...Object.keys(e??{}),...at]){let o=_(r);if(!/^\w+$/.test(o))continue;n.set(r,o),n.set(o,o)}for(let r of t)n.delete(r),n.delete(_(r));return n}function Ee(e,t,n){if(!t)return e;let r=e;for(let o of String(t).split(",")){let s=o.trim();if(!s)continue;let i=s.startsWith("-"),c=i?s.slice(1):s;if(!/^\w+$/.test(c))continue;let f=n.get(c);if(!f)continue;r=r.orderBy(f,i?"desc":"asc")}return r}var ut={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"?ct(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"?dt(e):[],set:(e)=>e==null?null:Array.isArray(e)?JSON.stringify(e):e}},Ae=new WeakMap;function lt(e,t){let n=Ae.get(e);if(n&&n.length===t.length){let o=!0;for(let s=0;s<t.length;s++){let i=t[s];if(n[s]?.attr!==i||n[s]?.definition!==e[i]){o=!1;break}}if(o)return n}let r=[];for(let o of t){let s=e[o],i=typeof s==="string"?ut[s]:s;r.push({attr:o,snake:_(o),definition:s,caster:i})}return Ae.set(e,r),r}function ct(e){try{return JSON.parse(e)}catch{return e}}function dt(e){try{return JSON.parse(e)}catch{return[]}}function ye(e,t,n){if(!e||typeof e!=="object"||!t)return e;let r=Object.keys(t);if(r.length===0)return e;let o=lt(t,r);if(o.length===0)return e;let s={...e};for(let{attr:i,caster:c,snake:f}of o){if(!c)continue;let u=c[n];if(typeof u!=="function")continue;if(Object.prototype.hasOwnProperty.call(s,i))s[i]=u.call(c,s[i]);if(f!==i&&Object.prototype.hasOwnProperty.call(s,f))s[f]=u.call(c,s[f])}return s}var Te=new WeakMap;function ft(e){let t=Te.get(e);if(t)return t;let n=[];for(let[r,o]of Object.entries(e)){let s=o?.validation?.rule;if(!s||typeof s.validate!=="function")continue;n.push({definition:o,field:r,hasDefault:o!==null&&typeof o==="object"&&Object.prototype.hasOwnProperty.call(o,"default"),rule:s})}return Te.set(e,n),n}function At(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 me(e,t,n){let r=t?.attributes;if(!r||typeof r!=="object")return{valid:!0};let o=ft(r);if(o.length===0)return{valid:!0};let s={},i=!1;for(let c of o){let{definition:f,field:u,hasDefault:T,rule:P}=c,I=Object.prototype.hasOwnProperty.call(e,u);if(!I&&n==="updating")continue;let q=I?e[u]:T?f.default:void 0,B=st(P,q),N=P.validate(B);if(!N?.valid&&Array.isArray(N?.errors)&&N.errors.length>0)i=!0,s[u]=N.errors.map((C)=>f.validation?.message?.[C?.code]??C?.message??"invalid")}return i?{valid:!1,errors:s}:{valid:!0}}function he(e,t){return`${e}\x00${gt(t)}`}function Fe(e){let t=new Map;for(let n of e){let r=he(String(n.method??""),String(n.path??""));if(!t.has(r))t.set(r,n)}return t}function gt(e){return e.replace(/\{[^}]*\}/g,"{}").replace(/:[^/]+/g,"{}")}function le(e){if(Array.isArray(e))return e.filter((t)=>typeof t==="string"&&t.length>0);return typeof e==="string"&&e?[e]:[]}function Ue(e){let t=typeof e==="object"&&e!==null&&"middleware"in e,n=e?.middleware;if(!t)return{read:["auth"],write:["auth"],declared:!1};if(n&&typeof n==="object"&&!Array.isArray(n)){let o=n;return{read:"read"in o?le(o.read):["auth"],write:"write"in o?le(o.write):["auth"],declared:!0}}let r=le(n);return{read:r,write:r,declared:!0}}var De=15,pt=100;function Be(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(De),10),o=Math.min(Number.isFinite(r)?Math.max(1,r):De,pt);return{page:n,perPage:o,offset:(n-1)*o}}function se(e,t){let n=new URL(e.toString());return n.searchParams.set("page",String(t)),`${n.pathname}${n.search}`}function yt(e,t,n,r,o,s){let i=(t-1)*n,c=r===0,f={page:t,per_page:n,from:c?null:i+1,to:c?null:i+r,has_more_pages:o,prev_page_url:t>1?se(e,t-1):null,next_page_url:o?se(e,t+1):null};if(s!==void 0&&!Number.isNaN(s)){let u=Math.max(1,Math.ceil(s/n));f.total=s,f.last_page=u,f.first_page_url=se(e,1),f.last_page_url=se(e,u)}return f}function we(e,t,n,r,o,s){let{page:i,...c}=yt(e,t,n,r,o,s);return{current_page:i,...c}}function be(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.`}import{readdirSync as mt}from"fs";import{basename as ht,extname as Le,join as wt}from"path";function bt(e){let t=[],n=(r)=>{let o;try{o=mt(r,{withFileTypes:!0})}catch{return}for(let s of o){let i=wt(r,s.name);if(s.isDirectory()){n(i);continue}if(![".ts",".js"].includes(Le(s.name)))continue;if(s.name.startsWith(".")||s.name.startsWith("index"))continue;t.push(i)}};return n(e),t.sort()}async function We(e,t,n){for(let r of bt(e))try{let o=Le(r),s=await import(`${r}?t=${Date.now()}`),i=s.default??s,c=i.name??ht(r,o);t[c]={...i,name:c}}catch(o){n?.(r,o)}}async function Ve(e){let t={};return await We(e.defaultsRoot,t,e.onImportError),await We(e.userRoot,t,e.onImportError),t}function ie(e){if(e?.ownership===!1)return null;if(e?.ownership)return e.ownership;let t=Pe(e);if(t)return{field:t,resolve:async(r,o)=>{let{resolveAuthenticatedTeamId:s}=await import("@stacksjs/auth");return s(Re(o))}};let n=$e(e);if(n)return{field:n,resolve:async(r)=>r?.id??null};return null}function Re(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 s of r.split(";")){let i=s.indexOf("=");if(i===-1)continue;if(s.slice(0,i).trim()===o)return decodeURIComponent(s.slice(i+1).trim())}return null}}}}function It(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 Nt(e="id"){return{field:e,resolve:async(t)=>t?.id??null}}function Mt(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")]),s=await r(Re(n));if(s==null)return[];return(await o.where("team_id",s).get()??[]).map((c)=>c.id).filter((c)=>c!=null)}catch{return[]}}}}function jt(e="id"){return{field:e,resolve:async(t,n)=>{try{let{resolveAuthenticatedTeamId:r}=await import("@stacksjs/auth");return await r(Re(n))}catch{return null}}}}function Et(e,t){return{field:t,resolve:async(n,r)=>{try{let o=await import("@stacksjs/orm"),s=o.models?.[e]??o[e]?.definition??null,i=ie(s);if(!i?.field||typeof i.resolve!=="function")return[];let c=await i.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(i.field,c).get():await f.where(i.field,c).get())??[]).map((T)=>T.id).filter((T)=>T!=null)}catch{return[]}}}}var St=Se("config/qb.ts");try{let e=(await import(St)).default;He(e??ze)}catch{J.debug("[orm] No config/qb.ts override found - deriving config from DB_CONNECTION");let e=z.DB_CONNECTION||"sqlite";He({...ze,dialect:e,database:e==="sqlite"?{database:z.DB_DATABASE_PATH||"database/stacks.sqlite"}:{database:z.DB_DATABASE||"stacks",host:z.DB_HOST||"127.0.0.1",port:z.DB_PORT||(e==="postgres"?5432:3306),username:z.DB_USERNAME||(e==="postgres"?"postgres":"root"),password:z.DB_PASSWORD||""}})}var ke=await Ve({defaultsRoot:kt("framework/defaults/app/Models"),userRoot:Se("app/Models"),onImportError:(e,t)=>J.warn(`[orm] Could not load model ${e}: ${t.message}`)}),xt=_t(),A=xt,Je=Fe(U.routes);function H(e,t){let n=he(e,t),r=Je.get(n);if(!r)return Je.set(n,{method:e,path:t}),!1;let o=String(r.path??"");return J.debug(`[orm] Skipping generated ${e} ${t} - already defined${o&&o!==t?` as ${o}`:""}.`),!0}function Ze(e){if(!e.attributes)return[];return Object.entries(e.attributes).filter(([t,n])=>n.hidden===!0).map(([t])=>t)}function qe(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 Ke(e,t,n,r){if(!e.length)return e;let o=n.split(",").map((u)=>u.trim()).filter(Boolean);if(!o.length)return e;let s=Array.isArray(t.belongsTo)?t.belongsTo:[],i=Array.isArray(t.hasMany)?t.hasMany:[],c=Array.isArray(t.hasOne)?t.hasOne:[],f=new Map;for(let u of s)f.set(_(u),{kind:"belongsTo",modelName:u});for(let u of c)f.set(_(u),{kind:"hasOne",modelName:u});for(let u of i)f.set(qe(_(u)),{kind:"hasMany",modelName:u});for(let u of o){let T=f.get(u);if(!T)continue;let P=r[T.modelName];if(!P)continue;let I=P.table||qe(_(T.modelName)),q=Ze(P),B=(N)=>G(ne(N,P),q);if(T.kind==="belongsTo"||T.kind==="hasOne"){let N=`${_(T.modelName)}_id`,C=[...new Set(e.map((S)=>S[N]).filter((S)=>S!=null))];if(!C.length){for(let S of e)S[u]=null;continue}let K=await A.selectFrom(I).whereIn("id",C).get(),L=new Map;for(let S of K??[])L.set(String(S.id),B(S));for(let S of e)S[u]=L.get(String(S[N]))??null}else{let N=String(t.name??""),C=`${_(N)}_id`,K=[...new Set(e.map((O)=>O.id).filter((O)=>O!=null))];if(!K.length){for(let O of e)O[u]=[];continue}let L=await A.selectFrom(I).whereIn(C,K).get(),S=new Map;for(let O of L??[]){let j=String(O[C]),Z=S.get(j)??[];Z.push(B(O)),S.set(j,Z)}for(let O of e)O[u]=S.get(String(O.id))??[]}}return e}async function Ge(e,t){let n=t?.set;if(!n||typeof n!=="object")return e;let r={...e};for(let[o,s]of Object.entries(n)){if(typeof s!=="function"||!(o in r))continue;try{r[o]=await s(r)}catch{}}return r}function Xe(e,t){return ye(e,t?.casts,"set")}function ne(e,t){return ye(e,t?.casts,"get")}function d(e,t=200){return new Response(JSON.stringify(e),{status:t,headers:{"Content-Type":"application/json"}})}var ae=1048576;async function _e(e){if(Number(e.headers?.get?.("content-length")??0)>ae)throw new W(413,`Request body exceeds ${ae}-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>ae)throw new W(413,`Request body exceeds ${ae}-byte limit`);if(!n)return{};let r=JSON.parse(n);return r&&typeof r==="object"&&!Array.isArray(r)?r:{}}catch(n){if(n instanceof W)throw n;throw new W(400,`Invalid JSON body: ${n.message}`)}}function ue(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 vt(e){let t=e.bearerToken;if(typeof t==="function"){let r=t.call(e);if(r)return r}let n=e.headers?.get?.("authorization")||e.headers?.get?.("Authorization")||"";if(typeof n==="string"&&n.startsWith("Bearer "))return n.substring(7);return null}async function X(e){let t=e._authenticatedUser;if(t)return t;let n=vt(e);if(!n)return null;try{let{Auth:r}=await import("@stacksjs/auth"),o=await r.getUserFromToken(n);if(o)e._authenticatedUser=o;return o||null}catch{return null}}function te(e,t){if(e==null||t==null)return!1;if(Array.isArray(t))return t.some((n)=>String(n)===String(e));return String(e)===String(t)}async function Y(e,t,n){let r=ie(e);if(!r||!r.field||typeof r.resolve!=="function")return{enforced:!1,value:null,field:"",bypass:!1};let o=typeof r.bypass==="function"?!!r.bypass(t,n):!1,s=null;try{s=await r.resolve(t,n)}catch{s=null}return{enforced:!0,value:s,field:String(r.field),bypass:o}}async function Ye(e,t,n,r){let o=e?.authedFill?.[t];if(!o)return{};if(typeof o==="function")try{let s=await o(n,r);return s&&typeof s==="object"?s:{}}catch{return{}}if(typeof o==="object"){let s={};for(let[i,c]of Object.entries(o))try{s[i]=typeof c==="function"?await c(n,r):c}catch{}return s}return{}}var et=await(async()=>{let e=Rt.env.STACKS_API_ROW_SCOPING;try{let t=(await import(Se("config/security.ts"))).default;return be(t?.api?.rowScoping,e)}catch{return be(void 0,e)}})(),tt=[];for(let[e,t]of Object.entries(ke)){let n=t.traits?.useApi;if(!n)continue;let r=typeof n==="object"?n:{},o=r.uri||t.table||e.toLowerCase()+"s",s=r.routes||["index","show","store","update","destroy"],i=t.table||o,c=Me(t),f=Ze(t),u=Ce(o,r.prefix),T=je(t.attributes,f),{read:P,write:I,declared:q}=Ue(n),B=["store","update","destroy"].some((y)=>s.includes(y));if(B&&q&&I.length===0)J.warn(`[orm] ${e}: registering UNAUTHENTICATED mutating routes at ${u} (explicit \`middleware: []\` opt-out)`);if(["index","show"].some((y)=>s.includes(y))&&q&&P.length===0)J.debug(`[orm] ${e}: registering public read routes at ${u} (declared \`middleware.read: []\`)`);let C=!!ie(t),K=C&&!P.includes("auth")?["auth",...P]:P,L=Ie(t),S=B&&!C&&!L;if(S)tt.push(e);if(B&&L)J.debug(`[orm] ${e}: registering unscoped mutating routes at ${u} (declared \`ownership: false\`)`);let O=S&&et==="deny",j=(y,a=K)=>{let l=y;for(let g of a)if(l&&typeof l.middleware==="function")l=l.middleware(g);return l};if(s.includes("index")&&!H("GET",u))j(U.get(u,async(y)=>{try{let a=new URL(y.url),{page:l,perPage:g,offset:w}=Be(a.searchParams),h=a.searchParams.get("sort"),p=A.selectFrom(i);p=Ee(p,h,T);let M=new Set(["page","per_page","sort","fields","search","include","limit","offset","with_count","withTrashed","onlyTrashed"]);for(let[x,v]of a.searchParams.entries()){if(M.has(x)||!v)continue;if(!/^[a-z_][a-z0-9_]*$/i.test(x))continue;let V=T.get(x);if(V)p=p.where(V,"=",v)}let R=a.searchParams.get("search");if(R&&c.length>0){let x=c.slice(0,5);p=p.where((v)=>{for(let V of x)v=v.orWhere(_(V),"like",`%${R}%`);return v})}let k=a.searchParams.get("fields");if(k){let x=k.split(",").map((v)=>v.trim()).filter((v)=>/^[a-z_][a-z0-9_]*$/i.test(v)).map((v)=>_(v));if(x.length>0)p=p.select(x)}let D=!!t.traits?.useSoftDeletes,b=a.searchParams.get("withTrashed")==="true",E=a.searchParams.get("onlyTrashed")==="true";if(D&&!b)p=E?p.whereNotNull("deleted_at"):p.whereNull("deleted_at");let m=C?await Y(t,await X(y),y):{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 x=we(a,l,g,0,!1,void 0);return new Response(JSON.stringify({data:[],...x}),{status:200,headers:{"Content-Type":"application/json","Cache-Control":"private, no-store",Vary:"Authorization"}})}p=Array.isArray(m.value)?p.where(m.field,"in",m.value):p.where(m.field,"=",m.value)}let F=await p.limit(g+1).offset(w).get()||[],Q=F.length>g,re=(Q?F.slice(0,g):F).map((x)=>G(ne(x,t),f)),xe=a.searchParams.get("include");if(xe)re=await Ke(re,t,xe,ke);let nt=a.searchParams.get("with_count")==="true",ee;if(nt)try{let x=A.selectFrom(i);if(m.enforced&&!m.bypass&&m.value!=null)x=Array.isArray(m.value)?x.where(m.field,"in",m.value):x.where(m.field,"=",m.value);let v=await x.count(),V=typeof v==="number"?v:Number(v?.count??v);if(Number.isFinite(V))ee=V}catch{}let oe={"Content-Type":"application/json"};if(ee!==void 0&&!Number.isNaN(ee))oe["X-Total-Count"]=String(ee);oe["Cache-Control"]=m.enforced&&!m.bypass?"private, no-store":"public, max-age=15, must-revalidate",oe.Vary="Authorization";let rt=we(a,l,g,re.length,Q,ee);return new Response(JSON.stringify({data:re,...rt}),{status:200,headers:oe})}catch(a){if(a instanceof W){let l={error:a.message};if(a.details!==void 0)l.details=a.details;return d(l,a.status||400)}return d({error:`Failed to fetch ${o}`,detail:String(a)},500)}}));if(s.includes("show")&&!H("GET",`${u}/{id}`))j(U.get(`${u}/{id}`,async(y)=>{try{let a=ue(y.params?.id);if(a==null)return d({error:"Invalid ID parameter"},400);let l=await A.selectFrom(i).where({id:a}).executeTakeFirst();if(!l)return d({error:`${e} not found`},404);let g=new URL(y.url);if(t.traits?.useSoftDeletes&&l.deleted_at&&g.searchParams.get("withTrashed")!=="true")return d({error:`${e} not found`},404);let w=C?await Y(t,await X(y),y):{enforced:!1,value:null,field:"",bypass:!1};if(w.enforced&&!w.bypass){if(w.value==null||!te(l[w.field],w.value))return d({error:`${e} not found`},404)}let h=G(ne(l,t),f),p=g.searchParams.get("include");if(p){let[b]=await Ke([h],t,p,ke);h=b}let M=h?.updated_at||h?.created_at,R=M?`W/"${h.id}-${String(M)}"`:void 0,k=y.headers?.get?.("if-none-match");if(R&&k&&k===R)return new Response(null,{status:304,headers:{ETag:R}});let D={"Content-Type":"application/json"};if(R)D.ETag=R;return D["Cache-Control"]=w.enforced&&!w.bypass?"private, no-store":"public, max-age=30, must-revalidate",D.Vary="Authorization",new Response(JSON.stringify({data:h}),{status:200,headers:D})}catch(a){if(a instanceof W){let l={error:a.message};if(a.details!==void 0)l.details=a.details;return d(l,a.status||400)}return d({error:`Failed to fetch ${e}`,detail:String(a)},500)}}));if(!O&&s.includes("store")&&!H("POST",u))j(U.post(u,async(y)=>{try{let a=await _e(y),l=pe(a,f),g=fe(l,c),w=await X(y);if(w){let b=await Ye(t,"creating",w,y);for(let[E,m]of Object.entries(b))if(m!==void 0&&m!==null&&g[E]===void 0)g[E]=m}let h=await Y(t,w,y);if(h.enforced&&!h.bypass){if(!w)return d({error:"Auth required"},401);let b=Ne(g,h.field,h.value);if(b.error)return d({error:b.error},403);g=b.data}if(Object.keys(g).length===0)return d({error:"No fillable fields provided"},422);let p=me(g,t,"creating");if(!p.valid)return d({success:!1,message:"Validation failed",errors:p.errors},422);if(t.traits?.useTimestamps!==!1){let b=new Date().toISOString();g.created_at=b,g.updated_at=b}let M=await Ge(g,t),R=de(Xe(M,t)),k=await A.insertInto(i).values(R).execute(),D=R;try{let b=k?.lastInsertRowid??k?.insertId??k;if(b){let E=await A.selectFrom(i).where({id:b}).executeTakeFirst();if(E)D=E}}catch{}return d({data:G(ne(D,t),f)},201)}catch(a){let{status:l,body:g}=ce(a,e,"create");return d(g,l)}}),I);if(!O&&s.includes("update")){let y=async(a)=>{try{let l=ue(a.params?.id);if(l==null)return d({error:"Invalid ID parameter"},400);let g=await _e(a),w=pe(g,f),h=fe(w,c),p=await X(a);if(p){let m=await Ye(t,"updating",p,a);for(let[F,Q]of Object.entries(m))if(Q!==void 0&&Q!==null&&h[F]===void 0)h[F]=Q}if(Object.keys(h).length===0)return d({error:"No fillable fields provided"},422);let M=me(h,t,"updating");if(!M.valid)return d({success:!1,message:"Validation failed",errors:M.errors},422);let R=await A.selectFrom(i).where({id:l}).executeTakeFirst();if(!R)return d({error:`${e} not found`},404);let k=await Y(t,p,a);if(k.enforced&&!k.bypass){if(!p)return d({error:"Auth required"},401);let m=R[k.field];if(!te(m,k.value))return d({error:`Not your ${e}`},403);let F=Object.keys(h).find((Q)=>_(Q)===_(k.field));if(F!==void 0&&!te(h[F],k.value))return d({error:`Cannot reassign ${e} ownership`},403)}if(t.traits?.useTimestamps!==!1)h.updated_at=new Date().toISOString();let D=await Ge(h,t),b=de(Xe(D,t));await A.updateTable(i).set(b).where({id:l}).execute();let E={...R,...b};try{let m=await A.selectFrom(i).where({id:l}).executeTakeFirst();if(m)E=m}catch{}return d({data:G(ne(E,t),f)})}catch(l){let{status:g,body:w}=ce(l,e,"update");return d(w,g)}};if(!H("PUT",`${u}/{id}`))j(U.put(`${u}/{id}`,y),I);if(!H("PATCH",`${u}/{id}`))j(U.patch(`${u}/{id}`,y),I)}let Z=!!t.traits?.useSoftDeletes;if(!O&&s.includes("destroy")&&!H("DELETE",`${u}/{id}`))j(U.delete(`${u}/{id}`,async(y)=>{try{let a=ue(y.params?.id);if(a==null)return d({error:"Invalid ID parameter"},400);let l=await A.selectFrom(i).where({id:a}).executeTakeFirst();if(!l)return d({error:`${e} not found`},404);let g=await X(y),w=await Y(t,g,y);if(w.enforced&&!w.bypass){if(!g)return d({error:"Auth required"},401);let h=l[w.field];if(!te(h,w.value))return d({error:`Not your ${e}`},403)}if(Z){let h=new Date().toISOString();await A.updateTable(i).set({deleted_at:h,updated_at:h}).where({id:a}).execute()}else await A.deleteFrom(i).where({id:a}).execute();return new Response(null,{status:204})}catch(a){if(a instanceof W){let l={error:a.message};if(a.details!==void 0)l.details=a.details;return d(l,a.status||400)}return d({error:`Failed to delete ${e}`,detail:String(a)},500)}}),I);if(!O&&s.includes("destroy")&&!H("POST",`${u}/bulk-delete`))j(U.post(`${u}/bulk-delete`,async(y)=>{try{let l=(await _e(y))?.ids;if(!Array.isArray(l)||l.length===0)return d({error:"An array of IDs is required"},422);if(l.length>100)return d({error:"Cannot delete more than 100 records at once"},422);let g=[],w=[];for(let R of l){let k=ue(R);if(k!=null)g.push(k);else w.push(R)}if(w.length>0)return d({error:"Invalid IDs in batch",invalid:w},422);let h=await X(y),p=await Y(t,h,y);if(p.enforced&&!p.bypass){if(!h)return d({error:"Auth required"},401);if(p.value==null)return d({error:"Caller has no ownership identity"},403);let R=await A.selectFrom(i).select(["id",p.field]).execute(),k=new Set(R.filter((b)=>te(b[p.field],p.value)).map((b)=>String(b.id))),D=g.filter((b)=>!k.has(String(b)));if(D.length>0)return d({error:`Cannot delete ${e} you don't own`,ids:D},403)}let M=new Date().toISOString();for(let R of g)if(Z)await A.updateTable(i).set({deleted_at:M,updated_at:M}).where({id:R}).execute();else await A.deleteFrom(i).where({id:R}).execute();return d({message:`Successfully deleted ${g.length} ${o}`})}catch(a){if(a instanceof W){let l={error:a.message};if(a.details!==void 0)l.details=a.details;return d(l,a.status||400)}return d({error:`Failed to bulk delete ${o}`,detail:String(a)},500)}}),I)}{let e=Qe(tt,et);if(e)J.warn(e)}var Gt=U;export{Gt as default};
2
+ var st=(e,t,n)=>()=>{if(e)try{t=e(e=0)}catch(r){n=[r]}if(n)throw n[0];return t};var Dt=import.meta.require;import{readdirSync as wt}from"fs";import{basename as bt,extname as Le,join as Rt}from"path";function kt(e){let t=[],n=(r)=>{let o;try{o=wt(r,{withFileTypes:!0})}catch{return}for(let s of o){let i=Rt(r,s.name);if(s.isDirectory()){n(i);continue}if(![".ts",".js"].includes(Le(s.name)))continue;if(s.name.startsWith(".")||s.name.startsWith("index"))continue;t.push(i)}};return n(e),t.sort()}async function We(e,t,n){for(let r of kt(e))try{let o=Le(r),s=await import(`${r}?t=${Date.now()}`),i=s.default??s,c=i.name??bt(r,o);t[c]={...i,name:c}}catch(o){n?.(r,o)}}async function Ve(e){let t={};return await We(e.defaultsRoot,t,e.onImportError),await We(e.userRoot,t,e.onImportError),t}var qe=()=>{};import _t from"process";import{route as B}from"@stacksjs/router";import{env as F}from"@stacksjs/env";import{projectPath as Se,storagePath as St}from"@stacksjs/path";import{createQueryBuilder as xt,defaultConfig as ze,setConfig as He}from"@stacksjs/query-builder";import{HttpError as L}from"@stacksjs/error-handling";import{log as H}from"@stacksjs/logging/runtime";function it(e){let t=e;return t?.code==="SQLITE_CONSTRAINT_UNIQUE"||t?.code==="SQLITE_CONSTRAINT"||t?.code==="23505"||t?.errno===1062||/unique|duplicate/i.test(t?.message??"")}function ce(e,t,n){let r=e;if(e instanceof Error&&typeof r.status==="number"&&Number.isInteger(r.status)&&r.status>=400&&r.status<600){let o={error:e.message};if(r.details!==void 0)o.details=r.details;return{status:r.status,body:o}}if(it(e))return{status:409,body:{error:`${t} already exists`}};return{status:500,body:{error:`Failed to ${n} ${t}`,detail:String(e)}}}function _(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 s=r>0?e.charCodeAt(r-1):0,i=r+1<e.length?e.charCodeAt(r+1):0,c=s>=97&&s<=122||s>=48&&s<=57,f=s>=65&&s<=90&&i>=97&&i<=122;if(r>0&&(c||f))n+="_";n+=String.fromCharCode(o+32)}return n}function de(e){let t={};for(let[n,r]of Object.entries(e))t[_(n)]=r;return t}function Ce(e,t){let n=String(t||"").replace(/^\/+|\/+$/g,""),r=String(e).replace(/^\/+/,"");return`/api/${n?`${n}/`:""}${r}`}function Pe(e){if(!e)return null;let t=e.attributes??{};if(Object.prototype.hasOwnProperty.call(t,"teamId")||Object.prototype.hasOwnProperty.call(t,"team_id"))return"team_id";return e.belongsTo?.some((n)=>n==="Team")?"team_id":null}function $e(e){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 Ie(e){return e?.ownership===!1}function Ne(e,t,n){let r=Object.keys(e).find((s)=>_(s)===_(t));if(Array.isArray(n)){if(r===void 0)return{data:e,error:"Ownership value is required"};if(!n.some((s)=>String(s)===String(e[r])))return{data:e,error:"Ownership value is not available to this caller"};return{data:{...e,[t]:e[r]}}}if(n===null||n===void 0)return{data:e,error:"Caller has no ownership identity"};let o={...e};for(let s of Object.keys(o))if(_(s)===_(t))delete o[s];return o[t]=n,{data:o}}function Me(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=_(n.trim()).split("_").filter(Boolean);if(r.length===0)continue;let o=`${r[0]}${r.slice(1).map((s)=>`${s[0]?.toUpperCase()}${s.slice(1)}`).join("")}Id`;t.push(o)}return[...new Set(t)]}function fe(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??=ut(t);let s=r.get(o);if(s!==o&&s in e)n[o]=e[s]}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]),s=Number(n[3]),i=new Date(Date.UTC(r,o-1,s));if(i.getUTCFullYear()!==r||i.getUTCMonth()!==o-1||i.getUTCDate()!==s)return t;return i}var Oe=new WeakMap,ve=new WeakMap;function ge(e){let t=Oe.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:_(r)}));return Oe.set(e,n),n}function ut(e){let t=ge(e),n=ve.get(t);if(n)return n;let r=new Map(t.map(({field:o,snake:s})=>[o,s]));return ve.set(t,r),r}function pe(e,t){if(!t.length)return e;let n={...e};for(let{field:r,snake:o}of ge(t))if(delete n[r],o!==r)delete n[o];return n}function G(e,t){if(!e||t.length===0)return e;let n={...e};for(let{field:r,snake:o}of ge(t))if(delete n[r],o!==r)delete n[o];return n}var lt=["id","uuid","created_at","updated_at","deleted_at"];function Ee(e,t){let n=new Map;for(let r of[...Object.keys(e??{}),...lt]){let o=_(r);if(!/^\w+$/.test(o))continue;n.set(r,o),n.set(o,o)}for(let r of t)n.delete(r),n.delete(_(r));return n}function je(e,t,n){if(!t)return e;let r=e;for(let o of String(t).split(",")){let s=o.trim();if(!s)continue;let i=s.startsWith("-"),c=i?s.slice(1):s;if(!/^\w+$/.test(c))continue;let f=n.get(c);if(!f)continue;r=r.orderBy(f,i?"desc":"asc")}return r}var ct={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"?ft(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"?gt(e):[],set:(e)=>e==null?null:Array.isArray(e)?JSON.stringify(e):e}},Ae=new WeakMap;function dt(e,t){let n=Ae.get(e);if(n&&n.length===t.length){let o=!0;for(let s=0;s<t.length;s++){let i=t[s];if(n[s]?.attr!==i||n[s]?.definition!==e[i]){o=!1;break}}if(o)return n}let r=[];for(let o of t){let s=e[o],i=typeof s==="string"?ct[s]:s;r.push({attr:o,snake:_(o),definition:s,caster:i})}return Ae.set(e,r),r}function ft(e){try{return JSON.parse(e)}catch{return e}}function gt(e){try{return JSON.parse(e)}catch{return[]}}function ye(e,t,n){if(!e||typeof e!=="object"||!t)return e;let r=Object.keys(t);if(r.length===0)return e;let o=dt(t,r);if(o.length===0)return e;let s={...e};for(let{attr:i,caster:c,snake:f}of o){if(!c)continue;let u=c[n];if(typeof u!=="function")continue;if(Object.prototype.hasOwnProperty.call(s,i))s[i]=u.call(c,s[i]);if(f!==i&&Object.prototype.hasOwnProperty.call(s,f))s[f]=u.call(c,s[f])}return s}var Te=new WeakMap;function pt(e){let t=Te.get(e);if(t)return t;let n=[];for(let[r,o]of Object.entries(e)){let s=o?.validation?.rule;if(!s||typeof s.validate!=="function")continue;n.push({definition:o,field:r,hasDefault:o!==null&&typeof o==="object"&&Object.prototype.hasOwnProperty.call(o,"default"),rule:s})}return Te.set(e,n),n}function Pt(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 me(e,t,n){let r=t?.attributes;if(!r||typeof r!=="object")return{valid:!0};let o=pt(r);if(o.length===0)return{valid:!0};let s={},i=!1;for(let c of o){let{definition:f,field:u,hasDefault:T,rule:P}=c,I=Object.prototype.hasOwnProperty.call(e,u);if(!I&&n==="updating")continue;let J=I?e[u]:T?f.default:void 0,Q=at(P,J),N=P.validate(Q);if(!N?.valid&&Array.isArray(N?.errors)&&N.errors.length>0)i=!0,s[u]=N.errors.map((C)=>f.validation?.message?.[C?.code]??C?.message??"invalid")}return i?{valid:!1,errors:s}:{valid:!0}}function he(e,t){return`${e}\x00${yt(t)}`}function Fe(e){let t=new Map;for(let n of e){let r=he(String(n.method??""),String(n.path??""));if(!t.has(r))t.set(r,n)}return t}function yt(e){return e.replace(/\{[^}]*\}/g,"{}").replace(/:[^/]+/g,"{}")}function le(e){if(Array.isArray(e))return e.filter((t)=>typeof t==="string"&&t.length>0);return typeof e==="string"&&e?[e]:[]}function Ue(e){let t=typeof e==="object"&&e!==null&&"middleware"in e,n=e?.middleware;if(!t)return{read:["auth"],write:["auth"],declared:!1};if(n&&typeof n==="object"&&!Array.isArray(n)){let o=n;return{read:"read"in o?le(o.read):["auth"],write:"write"in o?le(o.write):["auth"],declared:!0}}let r=le(n);return{read:r,write:r,declared:!0}}var De=15,mt=100;function Be(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(De),10),o=Math.min(Number.isFinite(r)?Math.max(1,r):De,mt);return{page:n,perPage:o,offset:(n-1)*o}}function se(e,t){let n=new URL(e.toString());return n.searchParams.set("page",String(t)),`${n.pathname}${n.search}`}function ht(e,t,n,r,o,s){let i=(t-1)*n,c=r===0,f={page:t,per_page:n,from:c?null:i+1,to:c?null:i+r,has_more_pages:o,prev_page_url:t>1?se(e,t-1):null,next_page_url:o?se(e,t+1):null};if(s!==void 0&&!Number.isNaN(s)){let u=Math.max(1,Math.ceil(s/n));f.total=s,f.last_page=u,f.first_page_url=se(e,1),f.last_page_url=se(e,u)}return f}function we(e,t,n,r,o,s){let{page:i,...c}=ht(e,t,n,r,o,s);return{current_page:i,...c}}function be(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.`}qe();function ie(e){if(e?.ownership===!1)return null;if(e?.ownership)return e.ownership;let t=Pe(e);if(t)return{field:t,resolve:async(r,o)=>{let{resolveAuthenticatedTeamId:s}=await import("@stacksjs/auth");return s(Re(o))}};let n=$e(e);if(n)return{field:n,resolve:async(r)=>r?.id??null};return null}function Re(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 s of r.split(";")){let i=s.indexOf("=");if(i===-1)continue;if(s.slice(0,i).trim()===o)return decodeURIComponent(s.slice(i+1).trim())}return null}}}}function jt(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 Ft(e="id"){return{field:e,resolve:async(t)=>t?.id??null}}function Ut(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")]),s=await r(Re(n));if(s==null)return[];return(await o.where("team_id",s).get()??[]).map((c)=>c.id).filter((c)=>c!=null)}catch{return[]}}}}function Bt(e="id"){return{field:e,resolve:async(t,n)=>{try{let{resolveAuthenticatedTeamId:r}=await import("@stacksjs/auth");return await r(Re(n))}catch{return null}}}}function Qt(e,t){return{field:t,resolve:async(n,r)=>{try{let o=await import("@stacksjs/orm"),s=o.models?.[e]??o[e]?.definition??null,i=ie(s);if(!i?.field||typeof i.resolve!=="function")return[];let c=await i.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(i.field,c).get():await f.where(i.field,c).get())??[]).map((T)=>T.id).filter((T)=>T!=null)}catch{return[]}}}}var Ot=Se("config/qb.ts");try{let e=(await import(Ot)).default;He(e??ze)}catch{H.debug("[orm] No config/qb.ts override found - deriving config from DB_CONNECTION");let e=F.DB_CONNECTION||"sqlite",t=e==="turso"||e==="libsql",n=t?"sqlite":e;He({...ze,dialect:n,database:t?{database:F.TURSO_DATABASE_URL||"",url:F.TURSO_DATABASE_URL||"",authToken:F.TURSO_AUTH_TOKEN||void 0}:n==="sqlite"?{database:F.DB_DATABASE_PATH||"database/stacks.sqlite"}:{database:F.DB_DATABASE||"stacks",host:F.DB_HOST||"127.0.0.1",port:F.DB_PORT||(n==="postgres"?5432:3306),username:F.DB_USERNAME||(n==="postgres"?"postgres":"root"),password:F.DB_PASSWORD||""}})}var ke=await Ve({defaultsRoot:St("framework/defaults/app/Models"),userRoot:Se("app/Models"),onImportError:(e,t)=>H.warn(`[orm] Could not load model ${e}: ${t.message}`)}),vt=xt(),A=vt,Je=Fe(B.routes);function z(e,t){let n=he(e,t),r=Je.get(n);if(!r)return Je.set(n,{method:e,path:t}),!1;let o=String(r.path??"");return H.debug(`[orm] Skipping generated ${e} ${t} - already defined${o&&o!==t?` as ${o}`:""}.`),!0}function et(e){if(!e.attributes)return[];return Object.entries(e.attributes).filter(([t,n])=>n.hidden===!0).map(([t])=>t)}function Ke(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 Ge(e,t,n,r){if(!e.length)return e;let o=n.split(",").map((u)=>u.trim()).filter(Boolean);if(!o.length)return e;let s=Array.isArray(t.belongsTo)?t.belongsTo:[],i=Array.isArray(t.hasMany)?t.hasMany:[],c=Array.isArray(t.hasOne)?t.hasOne:[],f=new Map;for(let u of s)f.set(_(u),{kind:"belongsTo",modelName:u});for(let u of c)f.set(_(u),{kind:"hasOne",modelName:u});for(let u of i)f.set(Ke(_(u)),{kind:"hasMany",modelName:u});for(let u of o){let T=f.get(u);if(!T)continue;let P=r[T.modelName];if(!P)continue;let I=P.table||Ke(_(T.modelName)),J=et(P),Q=(N)=>G(ne(N,P),J);if(T.kind==="belongsTo"||T.kind==="hasOne"){let N=`${_(T.modelName)}_id`,C=[...new Set(e.map((S)=>S[N]).filter((S)=>S!=null))];if(!C.length){for(let S of e)S[u]=null;continue}let K=await A.selectFrom(I).whereIn("id",C).get(),V=new Map;for(let S of K??[])V.set(String(S.id),Q(S));for(let S of e)S[u]=V.get(String(S[N]))??null}else{let N=String(t.name??""),C=`${_(N)}_id`,K=[...new Set(e.map((v)=>v.id).filter((v)=>v!=null))];if(!K.length){for(let v of e)v[u]=[];continue}let V=await A.selectFrom(I).whereIn(C,K).get(),S=new Map;for(let v of V??[]){let E=String(v[C]),Z=S.get(E)??[];Z.push(Q(v)),S.set(E,Z)}for(let v of e)v[u]=S.get(String(v.id))??[]}}return e}async function Xe(e,t){let n=t?.set;if(!n||typeof n!=="object")return e;let r={...e};for(let[o,s]of Object.entries(n)){if(typeof s!=="function"||!(o in r))continue;try{r[o]=await s(r)}catch{}}return r}function Ye(e,t){return ye(e,t?.casts,"set")}function ne(e,t){return ye(e,t?.casts,"get")}function d(e,t=200){return new Response(JSON.stringify(e),{status:t,headers:{"Content-Type":"application/json"}})}var ae=1048576;async function _e(e){if(Number(e.headers?.get?.("content-length")??0)>ae)throw new L(413,`Request body exceeds ${ae}-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>ae)throw new L(413,`Request body exceeds ${ae}-byte limit`);if(!n)return{};let r=JSON.parse(n);return r&&typeof r==="object"&&!Array.isArray(r)?r:{}}catch(n){if(n instanceof L)throw n;throw new L(400,`Invalid JSON body: ${n.message}`)}}function ue(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 At(e){let t=e.bearerToken;if(typeof t==="function"){let r=t.call(e);if(r)return r}let n=e.headers?.get?.("authorization")||e.headers?.get?.("Authorization")||"";if(typeof n==="string"&&n.startsWith("Bearer "))return n.substring(7);return null}async function X(e){let t=e._authenticatedUser;if(t)return t;let n=At(e);if(!n)return null;try{let{Auth:r}=await import("@stacksjs/auth"),o=await r.getUserFromToken(n);if(o)e._authenticatedUser=o;return o||null}catch{return null}}function te(e,t){if(e==null||t==null)return!1;if(Array.isArray(t))return t.some((n)=>String(n)===String(e));return String(e)===String(t)}async function Y(e,t,n){let r=ie(e);if(!r||!r.field||typeof r.resolve!=="function")return{enforced:!1,value:null,field:"",bypass:!1};let o=typeof r.bypass==="function"?!!r.bypass(t,n):!1,s=null;try{s=await r.resolve(t,n)}catch{s=null}return{enforced:!0,value:s,field:String(r.field),bypass:o}}async function Ze(e,t,n,r){let o=e?.authedFill?.[t];if(!o)return{};if(typeof o==="function")try{let s=await o(n,r);return s&&typeof s==="object"?s:{}}catch{return{}}if(typeof o==="object"){let s={};for(let[i,c]of Object.entries(o))try{s[i]=typeof c==="function"?await c(n,r):c}catch{}return s}return{}}var tt=await(async()=>{let e=_t.env.STACKS_API_ROW_SCOPING;try{let t=(await import(Se("config/security.ts"))).default;return be(t?.api?.rowScoping,e)}catch{return be(void 0,e)}})(),nt=[];for(let[e,t]of Object.entries(ke)){let n=t.traits?.useApi;if(!n)continue;let r=typeof n==="object"?n:{},o=r.uri||t.table||e.toLowerCase()+"s",s=r.routes||["index","show","store","update","destroy"],i=t.table||o,c=Me(t),f=et(t),u=Ce(o,r.prefix),T=Ee(t.attributes,f),{read:P,write:I,declared:J}=Ue(n),Q=["store","update","destroy"].some((y)=>s.includes(y));if(Q&&J&&I.length===0)H.warn(`[orm] ${e}: registering UNAUTHENTICATED mutating routes at ${u} (explicit \`middleware: []\` opt-out)`);if(["index","show"].some((y)=>s.includes(y))&&J&&P.length===0)H.debug(`[orm] ${e}: registering public read routes at ${u} (declared \`middleware.read: []\`)`);let C=!!ie(t),K=C&&!P.includes("auth")?["auth",...P]:P,V=Ie(t),S=Q&&!C&&!V;if(S)nt.push(e);if(Q&&V)H.debug(`[orm] ${e}: registering unscoped mutating routes at ${u} (declared \`ownership: false\`)`);let v=S&&tt==="deny",E=(y,a=K)=>{let l=y;for(let g of a)if(l&&typeof l.middleware==="function")l=l.middleware(g);return l};if(s.includes("index")&&!z("GET",u))E(B.get(u,async(y)=>{try{let a=new URL(y.url),{page:l,perPage:g,offset:w}=Be(a.searchParams),h=a.searchParams.get("sort"),p=A.selectFrom(i);p=je(p,h,T);let M=new Set(["page","per_page","sort","fields","search","include","limit","offset","with_count","withTrashed","onlyTrashed"]);for(let[x,O]of a.searchParams.entries()){if(M.has(x)||!O)continue;if(!/^[a-z_][a-z0-9_]*$/i.test(x))continue;let q=T.get(x);if(q)p=p.where(q,"=",O)}let R=a.searchParams.get("search");if(R&&c.length>0){let x=c.slice(0,5);p=p.where((O)=>{for(let q of x)O=O.orWhere(_(q),"like",`%${R}%`);return O})}let k=a.searchParams.get("fields");if(k){let x=k.split(",").map((O)=>O.trim()).filter((O)=>/^[a-z_][a-z0-9_]*$/i.test(O)).map((O)=>_(O));if(x.length>0)p=p.select(x)}let D=!!t.traits?.useSoftDeletes,b=a.searchParams.get("withTrashed")==="true",j=a.searchParams.get("onlyTrashed")==="true";if(D&&!b)p=j?p.whereNotNull("deleted_at"):p.whereNull("deleted_at");let m=C?await Y(t,await X(y),y):{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 x=we(a,l,g,0,!1,void 0);return new Response(JSON.stringify({data:[],...x}),{status:200,headers:{"Content-Type":"application/json","Cache-Control":"private, no-store",Vary:"Authorization"}})}p=Array.isArray(m.value)?p.where(m.field,"in",m.value):p.where(m.field,"=",m.value)}let U=await p.limit(g+1).offset(w).get()||[],W=U.length>g,re=(W?U.slice(0,g):U).map((x)=>G(ne(x,t),f)),xe=a.searchParams.get("include");if(xe)re=await Ge(re,t,xe,ke);let rt=a.searchParams.get("with_count")==="true",ee;if(rt)try{let x=A.selectFrom(i);if(m.enforced&&!m.bypass&&m.value!=null)x=Array.isArray(m.value)?x.where(m.field,"in",m.value):x.where(m.field,"=",m.value);let O=await x.count(),q=typeof O==="number"?O:Number(O?.count??O);if(Number.isFinite(q))ee=q}catch{}let oe={"Content-Type":"application/json"};if(ee!==void 0&&!Number.isNaN(ee))oe["X-Total-Count"]=String(ee);oe["Cache-Control"]=m.enforced&&!m.bypass?"private, no-store":"public, max-age=15, must-revalidate",oe.Vary="Authorization";let ot=we(a,l,g,re.length,W,ee);return new Response(JSON.stringify({data:re,...ot}),{status:200,headers:oe})}catch(a){if(a instanceof L){let l={error:a.message};if(a.details!==void 0)l.details=a.details;return d(l,a.status||400)}return d({error:`Failed to fetch ${o}`,detail:String(a)},500)}}));if(s.includes("show")&&!z("GET",`${u}/{id}`))E(B.get(`${u}/{id}`,async(y)=>{try{let a=ue(y.params?.id);if(a==null)return d({error:"Invalid ID parameter"},400);let l=await A.selectFrom(i).where({id:a}).executeTakeFirst();if(!l)return d({error:`${e} not found`},404);let g=new URL(y.url);if(t.traits?.useSoftDeletes&&l.deleted_at&&g.searchParams.get("withTrashed")!=="true")return d({error:`${e} not found`},404);let w=C?await Y(t,await X(y),y):{enforced:!1,value:null,field:"",bypass:!1};if(w.enforced&&!w.bypass){if(w.value==null||!te(l[w.field],w.value))return d({error:`${e} not found`},404)}let h=G(ne(l,t),f),p=g.searchParams.get("include");if(p){let[b]=await Ge([h],t,p,ke);h=b}let M=h?.updated_at||h?.created_at,R=M?`W/"${h.id}-${String(M)}"`:void 0,k=y.headers?.get?.("if-none-match");if(R&&k&&k===R)return new Response(null,{status:304,headers:{ETag:R}});let D={"Content-Type":"application/json"};if(R)D.ETag=R;return D["Cache-Control"]=w.enforced&&!w.bypass?"private, no-store":"public, max-age=30, must-revalidate",D.Vary="Authorization",new Response(JSON.stringify({data:h}),{status:200,headers:D})}catch(a){if(a instanceof L){let l={error:a.message};if(a.details!==void 0)l.details=a.details;return d(l,a.status||400)}return d({error:`Failed to fetch ${e}`,detail:String(a)},500)}}));if(!v&&s.includes("store")&&!z("POST",u))E(B.post(u,async(y)=>{try{let a=await _e(y),l=pe(a,f),g=fe(l,c),w=await X(y);if(w){let b=await Ze(t,"creating",w,y);for(let[j,m]of Object.entries(b))if(m!==void 0&&m!==null&&g[j]===void 0)g[j]=m}let h=await Y(t,w,y);if(h.enforced&&!h.bypass){if(!w)return d({error:"Auth required"},401);let b=Ne(g,h.field,h.value);if(b.error)return d({error:b.error},403);g=b.data}if(Object.keys(g).length===0)return d({error:"No fillable fields provided"},422);let p=me(g,t,"creating");if(!p.valid)return d({success:!1,message:"Validation failed",errors:p.errors},422);if(t.traits?.useTimestamps!==!1){let b=new Date().toISOString();g.created_at=b,g.updated_at=b}let M=await Xe(g,t),R=de(Ye(M,t)),k=await A.insertInto(i).values(R).execute(),D=R;try{let b=k?.lastInsertRowid??k?.insertId??k;if(b){let j=await A.selectFrom(i).where({id:b}).executeTakeFirst();if(j)D=j}}catch{}return d({data:G(ne(D,t),f)},201)}catch(a){let{status:l,body:g}=ce(a,e,"create");return d(g,l)}}),I);if(!v&&s.includes("update")){let y=async(a)=>{try{let l=ue(a.params?.id);if(l==null)return d({error:"Invalid ID parameter"},400);let g=await _e(a),w=pe(g,f),h=fe(w,c),p=await X(a);if(p){let m=await Ze(t,"updating",p,a);for(let[U,W]of Object.entries(m))if(W!==void 0&&W!==null&&h[U]===void 0)h[U]=W}if(Object.keys(h).length===0)return d({error:"No fillable fields provided"},422);let M=me(h,t,"updating");if(!M.valid)return d({success:!1,message:"Validation failed",errors:M.errors},422);let R=await A.selectFrom(i).where({id:l}).executeTakeFirst();if(!R)return d({error:`${e} not found`},404);let k=await Y(t,p,a);if(k.enforced&&!k.bypass){if(!p)return d({error:"Auth required"},401);let m=R[k.field];if(!te(m,k.value))return d({error:`Not your ${e}`},403);let U=Object.keys(h).find((W)=>_(W)===_(k.field));if(U!==void 0&&!te(h[U],k.value))return d({error:`Cannot reassign ${e} ownership`},403)}if(t.traits?.useTimestamps!==!1)h.updated_at=new Date().toISOString();let D=await Xe(h,t),b=de(Ye(D,t));await A.updateTable(i).set(b).where({id:l}).execute();let j={...R,...b};try{let m=await A.selectFrom(i).where({id:l}).executeTakeFirst();if(m)j=m}catch{}return d({data:G(ne(j,t),f)})}catch(l){let{status:g,body:w}=ce(l,e,"update");return d(w,g)}};if(!z("PUT",`${u}/{id}`))E(B.put(`${u}/{id}`,y),I);if(!z("PATCH",`${u}/{id}`))E(B.patch(`${u}/{id}`,y),I)}let Z=!!t.traits?.useSoftDeletes;if(!v&&s.includes("destroy")&&!z("DELETE",`${u}/{id}`))E(B.delete(`${u}/{id}`,async(y)=>{try{let a=ue(y.params?.id);if(a==null)return d({error:"Invalid ID parameter"},400);let l=await A.selectFrom(i).where({id:a}).executeTakeFirst();if(!l)return d({error:`${e} not found`},404);let g=await X(y),w=await Y(t,g,y);if(w.enforced&&!w.bypass){if(!g)return d({error:"Auth required"},401);let h=l[w.field];if(!te(h,w.value))return d({error:`Not your ${e}`},403)}if(Z){let h=new Date().toISOString();await A.updateTable(i).set({deleted_at:h,updated_at:h}).where({id:a}).execute()}else await A.deleteFrom(i).where({id:a}).execute();return new Response(null,{status:204})}catch(a){if(a instanceof L){let l={error:a.message};if(a.details!==void 0)l.details=a.details;return d(l,a.status||400)}return d({error:`Failed to delete ${e}`,detail:String(a)},500)}}),I);if(!v&&s.includes("destroy")&&!z("POST",`${u}/bulk-delete`))E(B.post(`${u}/bulk-delete`,async(y)=>{try{let l=(await _e(y))?.ids;if(!Array.isArray(l)||l.length===0)return d({error:"An array of IDs is required"},422);if(l.length>100)return d({error:"Cannot delete more than 100 records at once"},422);let g=[],w=[];for(let R of l){let k=ue(R);if(k!=null)g.push(k);else w.push(R)}if(w.length>0)return d({error:"Invalid IDs in batch",invalid:w},422);let h=await X(y),p=await Y(t,h,y);if(p.enforced&&!p.bypass){if(!h)return d({error:"Auth required"},401);if(p.value==null)return d({error:"Caller has no ownership identity"},403);let R=await A.selectFrom(i).select(["id",p.field]).execute(),k=new Set(R.filter((b)=>te(b[p.field],p.value)).map((b)=>String(b.id))),D=g.filter((b)=>!k.has(String(b)));if(D.length>0)return d({error:`Cannot delete ${e} you don't own`,ids:D},403)}let M=new Date().toISOString();for(let R of g)if(Z)await A.updateTable(i).set({deleted_at:M,updated_at:M}).where({id:R}).execute();else await A.deleteFrom(i).where({id:R}).execute();return d({message:`Successfully deleted ${g.length} ${o}`})}catch(a){if(a instanceof L){let l={error:a.message};if(a.details!==void 0)l.details=a.details;return d(l,a.status||400)}return d({error:`Failed to bulk delete ${o}`,detail:String(a)},500)}}),I)}{let e=Qe(nt,tt);if(e)H.warn(e)}var en=B;export{en as default};