@stacksjs/orm 0.75.41 → 0.75.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/define-model.d.ts +8 -0
- package/dist/gdpr/engine.d.ts +82 -0
- package/dist/gdpr/index.d.ts +20 -0
- package/dist/gdpr/models.d.ts +9 -0
- package/dist/gdpr/plan.d.ts +12 -0
- package/dist/gdpr/register.d.ts +30 -0
- package/dist/gdpr/types.d.ts +88 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +16 -11
- package/dist/model-registry.js +1 -1
- package/dist/models/Activity.ts +2 -0
- package/dist/models/CampaignSend.ts +2 -0
- package/dist/models/Card.ts +1 -0
- package/dist/models/CardComment.ts +1 -0
- package/dist/models/Comment.ts +5 -0
- package/dist/models/CommunicationSuppression.ts +2 -1
- package/dist/models/ConsentEvent.ts +4 -3
- package/dist/models/Content/Author.ts +5 -0
- package/dist/models/EmailListSubscriber.ts +1 -0
- package/dist/models/EmailSuppression.ts +2 -0
- package/dist/models/Forms/FormSubmission.ts +5 -0
- package/dist/models/GdprRequest.ts +77 -0
- package/dist/models/MagicLinkToken.ts +2 -0
- package/dist/models/Notification.ts +2 -0
- package/dist/models/NotificationDelivery.ts +4 -0
- package/dist/models/PaymentMethod.ts +5 -0
- package/dist/models/PaymentTransaction.ts +1 -0
- package/dist/models/PersonalAccessToken.ts +3 -0
- package/dist/models/Referral.ts +4 -1
- package/dist/models/ReferralCode.ts +4 -1
- package/dist/models/Request.ts +3 -0
- package/dist/models/SmsOptOut.ts +2 -0
- package/dist/models/SocialAccount.ts +3 -0
- package/dist/models/SocialPost.ts +2 -0
- package/dist/models/StorageItemTask.ts +14 -8
- package/dist/models/Subscriber.ts +2 -0
- package/dist/models/SubscriberEmail.ts +2 -0
- package/dist/models/Subscription.ts +1 -0
- package/dist/models/TeamInvitation.ts +2 -0
- package/dist/models/TeamMember.ts +1 -0
- package/dist/models/User.ts +5 -0
- package/dist/models/commerce/Bid.ts +3 -0
- package/dist/models/commerce/Cart.ts +2 -0
- package/dist/models/commerce/Courier.ts +7 -0
- package/dist/models/commerce/CourierPing.ts +3 -0
- package/dist/models/commerce/Customer.ts +5 -0
- package/dist/models/commerce/DeliveryStop.ts +7 -0
- package/dist/models/commerce/GiftCard.ts +4 -0
- package/dist/models/commerce/Order.ts +5 -0
- package/dist/models/commerce/OrderItem.ts +2 -0
- package/dist/models/commerce/Payment.ts +5 -0
- package/dist/models/commerce/Pledge.ts +3 -0
- package/dist/models/commerce/Transaction.ts +2 -0
- package/dist/models/commerce/WaitlistProduct.ts +5 -0
- package/dist/models/commerce/WaitlistRestaurant.ts +4 -0
- package/dist/routes.js +1 -1
- 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: {
|
package/dist/models/User.ts
CHANGED
|
@@ -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};
|