@stacksjs/orm 0.75.318 → 0.75.321

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 (54) hide show
  1. package/dist/auto-crud.d.ts +13 -0
  2. package/dist/auto-crud.js +1 -1
  3. package/dist/define-model.js +1 -1
  4. package/dist/models/Activity.ts +1 -0
  5. package/dist/models/AnalyticsEvent.ts +1 -0
  6. package/dist/models/AutomationRun.ts +1 -1
  7. package/dist/models/BoardColumn.ts +0 -1
  8. package/dist/models/Campaign.ts +1 -1
  9. package/dist/models/CampaignSend.ts +3 -3
  10. package/dist/models/Card.ts +0 -1
  11. package/dist/models/CardComment.ts +0 -2
  12. package/dist/models/Content/Author.ts +2 -0
  13. package/dist/models/Content/Categorizable.ts +1 -0
  14. package/dist/models/Content/Menu.ts +2 -0
  15. package/dist/models/Content/MenuItem.ts +2 -0
  16. package/dist/models/Content/PageRevision.ts +2 -0
  17. package/dist/models/Content/Post.ts +2 -0
  18. package/dist/models/Content/Redirect.ts +2 -0
  19. package/dist/models/EmailListSubscriber.ts +2 -2
  20. package/dist/models/Error.ts +5 -0
  21. package/dist/models/Forms/Form.ts +2 -0
  22. package/dist/models/Forms/FormField.ts +2 -0
  23. package/dist/models/Forms/FormSubmission.ts +2 -0
  24. package/dist/models/Label.ts +0 -1
  25. package/dist/models/Log.ts +3 -1
  26. package/dist/models/MagicLinkToken.ts +0 -7
  27. package/dist/models/PaymentProduct.ts +1 -0
  28. package/dist/models/PaymentTransaction.ts +1 -0
  29. package/dist/models/Release.ts +3 -0
  30. package/dist/models/Request.ts +1 -0
  31. package/dist/models/SenderDomain.ts +2 -0
  32. package/dist/models/SmsOptOut.ts +0 -7
  33. package/dist/models/Subscription.ts +2 -0
  34. package/dist/models/commerce/Auction.ts +1 -0
  35. package/dist/models/commerce/AuctionItem.ts +1 -0
  36. package/dist/models/commerce/Cart.ts +83 -2
  37. package/dist/models/commerce/Category.ts +5 -1
  38. package/dist/models/commerce/Coupon.ts +4 -1
  39. package/dist/models/commerce/DigitalDelivery.ts +1 -0
  40. package/dist/models/commerce/GiftCard.ts +1 -0
  41. package/dist/models/commerce/LoyaltyPoint.ts +1 -0
  42. package/dist/models/commerce/LoyaltyReward.ts +3 -1
  43. package/dist/models/commerce/Order.ts +4 -1
  44. package/dist/models/commerce/OrderItem.ts +1 -0
  45. package/dist/models/commerce/Payment.ts +1 -0
  46. package/dist/models/commerce/Product.ts +15 -0
  47. package/dist/models/commerce/ProductVariant.ts +2 -0
  48. package/dist/models/commerce/Receipt.ts +1 -0
  49. package/dist/models/commerce/Review.ts +3 -1
  50. package/dist/models/commerce/Transaction.ts +1 -0
  51. package/dist/models/realtime/Websocket.ts +4 -1
  52. package/dist/native.d.ts +29 -0
  53. package/dist/native.js +1 -0
  54. package/package.json +24 -24
@@ -15,6 +15,8 @@ export default defineModel({
15
15
  ],
16
16
 
17
17
  traits: {
18
+ // So a fresh seed fills its dashboard page (stacksjs/stacks#3000).
19
+ useSeeder: { count: 10 },
18
20
  useTimestamps: true,
19
21
  },
20
22
 
@@ -32,6 +34,7 @@ export default defineModel({
32
34
 
33
35
  message: {
34
36
  fillable: true,
37
+ type: 'text',
35
38
  validation: {
36
39
  rule: schema.string().required(),
37
40
  message: {
@@ -43,6 +46,7 @@ export default defineModel({
43
46
 
44
47
  stack: {
45
48
  fillable: true,
49
+ type: 'text',
46
50
  validation: {
47
51
  rule: schema.string(),
48
52
  message: {
@@ -86,6 +90,7 @@ export default defineModel({
86
90
 
87
91
  additional_info: {
88
92
  fillable: true,
93
+ type: 'text',
89
94
  validation: {
90
95
  rule: schema.string(),
91
96
  message: {
@@ -28,6 +28,8 @@ export default defineModel({
28
28
  ownership: siteOwnership(),
29
29
 
30
30
  traits: {
31
+ // So a fresh seed fills its dashboard page (stacksjs/stacks#3000).
32
+ useSeeder: { count: 3 },
31
33
  useUuid: true,
32
34
  useTimestamps: true,
33
35
  useApi: {
@@ -27,6 +27,8 @@ export default defineModel({
27
27
  ownership: parentOwnership('Form', 'form_id'),
28
28
 
29
29
  traits: {
30
+ // So a fresh seed fills its dashboard page (stacksjs/stacks#3000).
31
+ useSeeder: { count: 10 },
30
32
  useTimestamps: true,
31
33
  useApi: {
32
34
  middleware: ['auth'],
@@ -18,6 +18,8 @@ export default defineModel({
18
18
  autoIncrement: true,
19
19
 
20
20
  traits: {
21
+ // So a fresh seed fills its dashboard page (stacksjs/stacks#3000).
22
+ useSeeder: { count: 10 },
21
23
  gdpr: { subject: { email: 'email' }, erasure: 'anonymize', basis: 'consent', purpose: 'Form submissions' },
22
24
  useUuid: true,
23
25
  useTimestamps: true,
@@ -47,7 +47,6 @@ export default defineModel({
47
47
  order: 1,
48
48
  fillable: true,
49
49
  validation: { rule: schema.number().required() },
50
- factory: () => 1,
51
50
  },
52
51
 
53
52
  name: {
@@ -49,7 +49,9 @@ export default defineModel({
49
49
  order: 1,
50
50
  fillable: true,
51
51
  validation: {
52
- rule: schema.number().required(),
52
+ // Milliseconds since the epoch, so a bigint column, as on Websocket.time
53
+ // (stacksjs/stacks#2996).
54
+ rule: schema.unix().required(),
53
55
  message: {
54
56
  date: 'Timestamp must be a valid date',
55
57
  },
@@ -15,13 +15,6 @@ export default defineModel({
15
15
  primaryKey: 'id',
16
16
  autoIncrement: true,
17
17
 
18
- indexes: [
19
- {
20
- name: 'magic_link_tokens_token_unique',
21
- columns: ['token'],
22
- unique: true,
23
- },
24
- ],
25
18
 
26
19
  traits: {
27
20
  gdpr: { erasure: 'delete', basis: 'contract', purpose: 'Passwordless sign-in links' },
@@ -28,6 +28,7 @@ export default defineModel({
28
28
 
29
29
  description: {
30
30
  fillable: true,
31
+ type: 'text',
31
32
  validation: {
32
33
  rule: schema.string(),
33
34
  message: {
@@ -32,6 +32,7 @@ export default defineModel({
32
32
 
33
33
  description: {
34
34
  fillable: true,
35
+ type: 'text',
35
36
  validation: {
36
37
  rule: schema.string(),
37
38
  message: {
@@ -8,6 +8,8 @@ export default defineModel({
8
8
  autoIncrement: true,
9
9
 
10
10
  traits: {
11
+ // So a fresh seed fills its dashboard page (stacksjs/stacks#3000).
12
+ useSeeder: { count: 5 },
11
13
  useUuid: true,
12
14
  useTimestamps: true,
13
15
  useSearch: {
@@ -59,6 +61,7 @@ export default defineModel({
59
61
  notes: {
60
62
  order: 4,
61
63
  fillable: true,
64
+ type: 'text',
62
65
  validation: {
63
66
  rule: schema.string(),
64
67
  },
@@ -132,6 +132,7 @@ export default defineModel({
132
132
 
133
133
  error_message: {
134
134
  fillable: true,
135
+ type: 'text',
135
136
  validation: {
136
137
  rule: schema.string(),
137
138
  message: {
@@ -6,6 +6,8 @@ export default defineModel({
6
6
  table: 'sender_domains',
7
7
  belongsTo: ['Team'],
8
8
  traits: {
9
+ // So a fresh seed fills its dashboard page (stacksjs/stacks#3000).
10
+ useSeeder: { count: 3 },
9
11
  useUuid: true,
10
12
  useTimestamps: true,
11
13
  useApi: { uri: 'sender-domains', routes: ['index', 'store', 'show', 'update', 'destroy'], middleware: ['auth', 'team'] },
@@ -13,13 +13,6 @@ export default defineModel({
13
13
  primaryKey: 'id',
14
14
  autoIncrement: true,
15
15
 
16
- indexes: [
17
- {
18
- name: 'sms_opt_outs_phone_unique',
19
- columns: ['phone'],
20
- unique: true,
21
- },
22
- ],
23
16
 
24
17
  traits: {
25
18
  gdpr: { erasure: 'keep', basis: 'legal_obligation', purpose: 'Honouring SMS STOP replies, keyed by phone number' },
@@ -8,6 +8,8 @@ export default defineModel({
8
8
  autoIncrement: true, // defaults to true
9
9
  belongsTo: ['User'],
10
10
  traits: {
11
+ // So a fresh seed fills its dashboard page (stacksjs/stacks#3000).
12
+ useSeeder: { count: 10 },
11
13
  gdpr: { erasure: 'keep', basis: 'legal_obligation', purpose: 'Billing records' },
12
14
  useUuid: true,
13
15
  },
@@ -75,6 +75,7 @@ export default defineModel({
75
75
  description: {
76
76
  order: 3,
77
77
  fillable: true,
78
+ type: 'text',
78
79
  validation: {
79
80
  rule: schema.string(),
80
81
  },
@@ -74,6 +74,7 @@ export default defineModel({
74
74
  description: {
75
75
  order: 3,
76
76
  fillable: true,
77
+ type: 'text',
77
78
  validation: {
78
79
  rule: schema.string(),
79
80
  },
@@ -136,9 +136,90 @@ export default defineModel({
136
136
  order: 10,
137
137
  fillable: true,
138
138
  validation: {
139
- rule: schema.string().required(),
139
+ // Optional: a cart without a coupon is the common case.
140
+ rule: schema.string(),
141
+ },
142
+ // Stored and shown, never resolved: nothing redeems or joins on it yet,
143
+ // so what it holds is left to the feature that does. No factory, so a
144
+ // seed does not invent one (stacksjs/stacks#3002).
145
+ },
146
+
147
+ // The storefront's anonymous cart: the shopper's signed stacks_cart cookie
148
+ // carries this token, checkout records its progress and the address, and
149
+ // the order is placed from them (stacksjs/stacks#3017). A cart made any
150
+ // other way has none of them.
151
+
152
+ /** Bearer for an anonymous cart, so never returned by the API. No factory: a seeded cart is no shopper's. */
153
+ sessionToken: {
154
+ order: 11,
155
+ unique: true,
156
+ hidden: true,
157
+ validation: {
158
+ rule: schema.string().max(255),
159
+ },
160
+ },
161
+
162
+ checkoutStep: {
163
+ default: 'cart',
164
+ order: 12,
165
+ fillable: true,
166
+ validation: {
167
+ rule: schema.enum(['cart', 'shipping', 'payment', 'placed']),
168
+ },
169
+ },
170
+
171
+ email: {
172
+ personal: true,
173
+ order: 13,
174
+ fillable: true,
175
+ validation: {
176
+ rule: schema.string().email().max(255),
177
+ },
178
+ },
179
+
180
+ shippingName: {
181
+ personal: true,
182
+ order: 14,
183
+ fillable: true,
184
+ validation: {
185
+ rule: schema.string().max(255),
186
+ },
187
+ },
188
+
189
+ shippingAddress: {
190
+ personal: true,
191
+ order: 15,
192
+ fillable: true,
193
+ validation: {
194
+ rule: schema.string().max(255),
195
+ },
196
+ },
197
+
198
+ shippingCity: {
199
+ personal: true,
200
+ order: 16,
201
+ fillable: true,
202
+ validation: {
203
+ rule: schema.string().max(255),
204
+ },
205
+ },
206
+
207
+ shippingState: {
208
+ personal: true,
209
+ order: 17,
210
+ fillable: true,
211
+ validation: {
212
+ rule: schema.string().max(100),
213
+ },
214
+ },
215
+
216
+ shippingZip: {
217
+ personal: true,
218
+ order: 18,
219
+ fillable: true,
220
+ validation: {
221
+ rule: schema.string().max(20),
140
222
  },
141
- factory: () => 'test-coupon-id',
142
223
  },
143
224
  },
144
225
 
@@ -64,6 +64,7 @@ export default defineModel({
64
64
  description: {
65
65
  order: 2,
66
66
  fillable: true,
67
+ type: 'text',
67
68
  validation: {
68
69
  rule: schema.string(),
69
70
  },
@@ -101,7 +102,10 @@ export default defineModel({
101
102
  order: 5,
102
103
  fillable: true,
103
104
  validation: {
104
- rule: schema.string(),
105
+ // Another category's id, so a number like the id it points at. As a
106
+ // string it was a text column, and joining it to categories.id failed
107
+ // on PostgreSQL with "text = bigint" (stacksjs/stacks#3002).
108
+ rule: schema.number(),
105
109
  },
106
110
  factory: () => null, // Most categories won't have a parent
107
111
  },
@@ -55,6 +55,7 @@ export default defineModel({
55
55
  description: {
56
56
  order: 2,
57
57
  fillable: true,
58
+ type: 'text',
58
59
  validation: {
59
60
  rule: schema.string(),
60
61
  },
@@ -145,7 +146,9 @@ export default defineModel({
145
146
  validation: {
146
147
  rule: schema.string(),
147
148
  },
148
- factory: faker => faker.string.uuid(),
149
+ // Stored and shown, never resolved: nothing redeems or joins on it yet,
150
+ // so what it holds is left to the feature that does. No factory, so a
151
+ // seed does not invent one (stacksjs/stacks#3002).
149
152
  },
150
153
 
151
154
  usageLimit: {
@@ -56,6 +56,7 @@ export default defineModel({
56
56
  description: {
57
57
  order: 3,
58
58
  fillable: true,
59
+ type: 'text',
59
60
  validation: {
60
61
  rule: schema.string().required(),
61
62
  },
@@ -125,6 +125,7 @@ export default defineModel({
125
125
  personal: true,
126
126
  order: 9,
127
127
  fillable: true,
128
+ type: 'text',
128
129
  validation: {
129
130
  rule: schema.string(),
130
131
  },
@@ -81,6 +81,7 @@ export default defineModel({
81
81
  description: {
82
82
  order: 5,
83
83
  fillable: true,
84
+ type: 'text',
84
85
  validation: {
85
86
  rule: schema.string(),
86
87
  },
@@ -98,7 +98,9 @@ export default defineModel({
98
98
  validation: {
99
99
  rule: schema.string(),
100
100
  },
101
- factory: faker => faker.helpers.maybe(() => faker.string.uuid(), { probability: 0.4 }),
101
+ // Stored and shown, never resolved: nothing redeems or joins on it yet,
102
+ // so what it holds is left to the feature that does. No factory, so a
103
+ // seed does not invent one (stacksjs/stacks#3002).
102
104
  },
103
105
 
104
106
  isActive: {
@@ -142,6 +142,7 @@ export default defineModel({
142
142
  personal: true,
143
143
  order: 11,
144
144
  fillable: true,
145
+ type: 'text',
145
146
  validation: {
146
147
  rule: schema.string(),
147
148
  },
@@ -199,7 +200,9 @@ export default defineModel({
199
200
  validation: {
200
201
  rule: schema.string(),
201
202
  },
202
- factory: faker => faker.helpers.maybe(() => faker.string.uuid(), { probability: 0.2 }),
203
+ // Stored and shown, never resolved: nothing redeems or joins on it yet,
204
+ // so what it holds is left to the feature that does. No factory, so a
205
+ // seed does not invent one (stacksjs/stacks#3002).
203
206
  },
204
207
  },
205
208
 
@@ -45,6 +45,7 @@ export default defineModel({
45
45
  personal: true,
46
46
  order: 5,
47
47
  fillable: true,
48
+ type: 'text',
48
49
  validation: {
49
50
  rule: schema.string(),
50
51
  },
@@ -179,6 +179,7 @@ export default defineModel({
179
179
  personal: true,
180
180
  order: 15,
181
181
  fillable: true,
182
+ type: 'text',
182
183
  validation: {
183
184
  rule: schema.string(),
184
185
  },
@@ -1,4 +1,5 @@
1
1
  import { defineModel } from '@stacksjs/orm'
2
+ import { slug } from '@stacksjs/strings'
2
3
  import { schema } from '@stacksjs/validation/runtime'
3
4
 
4
5
  export default defineModel({
@@ -56,9 +57,22 @@ export default defineModel({
56
57
  factory: faker => faker.commerce.productName(),
57
58
  },
58
59
 
60
+ // The storefront's address for a product: /products/{slug}, and what a
61
+ // cart line keeps in product_sku (stacksjs/stacks#3005).
62
+ slug: {
63
+ order: 1,
64
+ unique: true,
65
+ fillable: true,
66
+ validation: {
67
+ rule: schema.string().required().max(255),
68
+ },
69
+ factory: (_faker, attributes) => slug(String(attributes.name)),
70
+ },
71
+
59
72
  description: {
60
73
  order: 2,
61
74
  fillable: true,
75
+ type: 'text',
62
76
  validation: {
63
77
  rule: schema.string(),
64
78
  },
@@ -139,6 +153,7 @@ export default defineModel({
139
153
  nutritionalInfo: {
140
154
  order: 10,
141
155
  fillable: true,
156
+ type: 'text',
142
157
  validation: {
143
158
  rule: schema.string(),
144
159
  },
@@ -77,6 +77,7 @@ export default defineModel({
77
77
  description: {
78
78
  order: 5,
79
79
  fillable: true,
80
+ type: 'text',
80
81
  validation: {
81
82
  rule: schema.string(),
82
83
  },
@@ -86,6 +87,7 @@ export default defineModel({
86
87
  options: {
87
88
  order: 6,
88
89
  fillable: true,
90
+ type: 'text',
89
91
  validation: {
90
92
  rule: schema.string(),
91
93
  },
@@ -136,6 +136,7 @@ export default defineModel({
136
136
  order: 8,
137
137
  fillable: true,
138
138
  default: '{}',
139
+ type: 'text',
139
140
  validation: {
140
141
  rule: schema.string(),
141
142
  },
@@ -34,7 +34,9 @@ export default defineModel({
34
34
  observe: true,
35
35
  },
36
36
 
37
- belongsTo: ['Product', 'Customer'],
37
+ // The order a storefront review was left for: one review per product per
38
+ // order, and the proof the reviewer bought it (stacksjs/stacks#3017).
39
+ belongsTo: ['Product', 'Customer', 'Order'],
38
40
 
39
41
  attributes: {
40
42
  /**
@@ -71,6 +71,7 @@ export default defineModel({
71
71
  order: 5,
72
72
  fillable: true,
73
73
  hidden: true,
74
+ type: 'text',
74
75
  validation: {
75
76
  rule: schema.string(),
76
77
  },
@@ -72,7 +72,10 @@ export default defineModel({
72
72
  order: 4,
73
73
  fillable: true,
74
74
  validation: {
75
- rule: schema.number(),
75
+ // A Unix timestamp in milliseconds, so a bigint column: `number()`
76
+ // generated a 32-bit integer that Date.now() overflows on PostgreSQL
77
+ // and MySQL (stacksjs/stacks#2996).
78
+ rule: schema.unix(),
76
79
  message: {
77
80
  date: 'Time must be a valid timestamp',
78
81
  },
@@ -0,0 +1,29 @@
1
+ import { Database } from 'bun:sqlite';
2
+ import { MODEL_DEFINITION } from './define-model';
3
+ import type { StacksModelDefinition } from './define-model';
4
+ /**
5
+ * Own one SQLite database in a native backend process. Schema comes from the
6
+ * same migration planner as Buddy; additive upgrades and the snapshot commit
7
+ * atomically. Destructive upgrades require an explicit application migration.
8
+ */
9
+ export declare function openNativeDatabase(options: { path: string, models: Record<string, NativeModel> }): Database;
10
+ /**
11
+ * Model-declared CRUD for an authenticated native transport. Authorization is
12
+ * mandatory and evaluated before queries; web middleware is never bypassed.
13
+ * Use only behind stx's authenticated native backend, or supply an equivalent
14
+ * per-request authorization implementation. Native models explicitly declare
15
+ * middleware: [] because their session is enforced by this transport.
16
+ */
17
+ export declare function createNativeModelApi(options: {
18
+ models: Record<string, NativeModel>
19
+ authorize: (request: Request, model: string, ability: string) => boolean | Promise<boolean>
20
+ }): (request: Request) => Promise<Response | null>;
21
+ /** Explicit model registry: the compiled app never discovers source files at runtime. */
22
+ export declare interface NativeModel {
23
+ [MODEL_DEFINITION]: StacksModelDefinition
24
+ find: (id: number) => Promise<unknown>
25
+ create: (data: Record<string, unknown>) => Promise<unknown>
26
+ update: (id: number, data: Record<string, unknown>) => Promise<unknown>
27
+ destroy: (id: number) => Promise<unknown>
28
+ limit: (count: number) => { offset: (offset: number) => { get: () => Promise<unknown> } }
29
+ }
package/dist/native.js ADDED
@@ -0,0 +1 @@
1
+ import{Database}from"bun:sqlite";import{chmodSync,mkdirSync}from"node:fs";import{dirname,isAbsolute}from"node:path";import{buildMigrationPlan,configureOrm,generateDiffOperations}from"@stacksjs/query-builder";import{apiBasePath,filterFillable,getWritableFields,mapWriteError,resolveIndexPageArgs}from"./auto-crud";import{MODEL_DEFINITION,toAttrs}from"./define-model";export function openNativeDatabase(options){if(options.path!==":memory:"&&!isAbsolute(options.path))throw Error("A native database requires an absolute Application Support path");if(options.path!==":memory:")mkdirSync(dirname(options.path),{recursive:!0,mode:448});const db=new Database(options.path,{create:!0});try{if(options.path!==":memory:")chmodSync(options.path,384);db.exec("PRAGMA foreign_keys = ON; PRAGMA busy_timeout = 5000;");const models=Object.fromEntries(Object.entries(options.models).map(([name,model])=>[name,model[MODEL_DEFINITION]])),next=buildMigrationPlan(models,{dialect:"sqlite"});db.transaction(()=>{db.exec("CREATE TABLE IF NOT EXISTS _stacks_native_schema (id INTEGER PRIMARY KEY CHECK (id = 1), snapshot TEXT NOT NULL)");const saved=db.query("SELECT snapshot FROM _stacks_native_schema WHERE id = 1").get(),previous=saved?JSON.parse(saved.snapshot):void 0,diff=generateDiffOperations(previous,next);if(diff.operations.some((operation)=>operation.destructive))throw Error("Native model upgrade contains destructive changes; provide an explicit data migration");for(const statement of diff.statements)if(statement.replace(/--[^\n]*/g,"").trim())db.exec(statement);db.query("INSERT INTO _stacks_native_schema (id, snapshot) VALUES (1, ?) ON CONFLICT (id) DO UPDATE SET snapshot = excluded.snapshot").run(JSON.stringify(next))}).immediate();configureOrm({database:db});return db}catch(error){db.close();throw error}}export function createNativeModelApi(options){const models=Object.entries(options.models).flatMap(([name,model])=>{const definition=model[MODEL_DEFINITION],api=definition.traits?.useApi;if(!api||typeof api!=="object")return[];if(!Array.isArray(api.middleware)||api.middleware.length)throw Error(`${name}: native CRUD requires explicit middleware: [] and transport authorization`);if(!api.uri)throw Error(`${name}: native CRUD requires a useApi uri`);return[{name,model,definition,api,base:apiBasePath(api.uri,api.prefix)}]}),json=(data,status=200)=>Response.json(data,{status,headers:{"cache-control":"private, no-store"}});return async(request)=>{const url=new URL(request.url);for(const entry of models){const{name,model,definition,api,base}=entry,suffix=url.pathname.slice(base.length);if(!url.pathname.startsWith(base)||suffix&&!/^\/\d+$/.test(suffix))continue;const id=suffix?Number(suffix.slice(1)):void 0,ability=request.method==="GET"?id===void 0?"index":"show":request.method==="POST"&&id===void 0?"store":["PATCH","PUT"].includes(request.method)&&id!==void 0?"update":request.method==="DELETE"&&id!==void 0?"destroy":void 0;if(!ability||!api.routes?.includes(ability))return json({error:"Method not allowed"},405);if(!await options.authorize(request,name,ability))return json({error:"Forbidden"},403);try{if(ability==="index"){const{perPage,offset}=resolveIndexPageArgs(url.searchParams);return json({data:toAttrs(await model.limit(perPage).offset(offset).get())})}if(id!==void 0&&!await model.find(id))return json({error:"Not found"},404);if(ability==="show")return json({data:toAttrs(await model.find(id))});if(ability==="destroy"){await model.destroy(id);return new Response(null,{status:204})}let body;try{body=await request.json()}catch{return json({error:"Invalid JSON"},400)}if(!body||typeof body!=="object"||Array.isArray(body))return json({error:"Expected an object"},422);const fields=getWritableFields({attributes:definition.attributes,belongsTo:Object.values(definition.belongsTo??{})}),data=filterFillable(body,fields),row=ability==="store"?await model.create(data):await model.update(id,data);return json({data:toAttrs(row)},ability==="store"?201:200)}catch(error){const result=mapWriteError(error,name,ability==="store"?"create":"update"),body={...result.body};delete body.detail;return json(body,result.status)}}return null}}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/orm",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.75.318",
5
+ "version": "0.75.321",
6
6
  "description": "The Stacks ORM integration",
7
7
  "author": "Chris Breuer",
8
8
  "contributors": [
@@ -63,31 +63,31 @@
63
63
  "prepublishOnly": "bun run build"
64
64
  },
65
65
  "dependencies": {
66
- "@stacksjs/cache": "0.75.318",
67
- "@stacksjs/cli": "0.75.318",
68
- "@stacksjs/config": "0.75.318",
69
- "@stacksjs/database": "0.75.318",
70
- "@stacksjs/env": "0.75.318",
71
- "@stacksjs/error-handling": "0.75.318",
72
- "@stacksjs/events": "0.75.318",
73
- "@stacksjs/logging": "0.75.318",
74
- "@stacksjs/model-meta": "0.75.318",
75
- "@stacksjs/pagination": "0.75.318",
76
- "@stacksjs/path": "0.75.318",
77
- "@stacksjs/query-builder": "0.75.318",
78
- "@stacksjs/realtime": "0.75.318",
79
- "@stacksjs/router": "0.75.318",
80
- "@stacksjs/storage": "0.75.318",
81
- "@stacksjs/strings": "0.75.318",
66
+ "@stacksjs/cache": "0.75.321",
67
+ "@stacksjs/cli": "0.75.321",
68
+ "@stacksjs/config": "0.75.321",
69
+ "@stacksjs/database": "0.75.321",
70
+ "@stacksjs/env": "0.75.321",
71
+ "@stacksjs/error-handling": "0.75.321",
72
+ "@stacksjs/events": "0.75.321",
73
+ "@stacksjs/logging": "0.75.321",
74
+ "@stacksjs/model-meta": "0.75.321",
75
+ "@stacksjs/pagination": "0.75.321",
76
+ "@stacksjs/path": "0.75.321",
77
+ "@stacksjs/query-builder": "0.75.321",
78
+ "@stacksjs/realtime": "0.75.321",
79
+ "@stacksjs/router": "0.75.321",
80
+ "@stacksjs/storage": "0.75.321",
81
+ "@stacksjs/strings": "0.75.321",
82
82
  "@stacksjs/ts-validation": "^0.5.6",
83
- "@stacksjs/validation": "0.75.318",
84
- "bun-query-builder": "^0.3.8"
83
+ "@stacksjs/validation": "0.75.321",
84
+ "bun-query-builder": "^0.3.22"
85
85
  },
86
86
  "peerDependencies": {
87
- "@stacksjs/auth": "0.75.318",
88
- "@stacksjs/payments": "0.75.318",
89
- "@stacksjs/queue": "0.75.318",
90
- "@stacksjs/search-engine": "0.75.318",
87
+ "@stacksjs/auth": "0.75.321",
88
+ "@stacksjs/payments": "0.75.321",
89
+ "@stacksjs/queue": "0.75.321",
90
+ "@stacksjs/search-engine": "0.75.321",
91
91
  "stripe": "23.0.0"
92
92
  },
93
93
  "peerDependenciesMeta": {
@@ -108,7 +108,7 @@
108
108
  }
109
109
  },
110
110
  "devDependencies": {
111
- "@stacksjs/types": "0.75.318",
111
+ "@stacksjs/types": "0.75.321",
112
112
  "better-dx": "^0.2.24",
113
113
  "stripe": "23.0.0"
114
114
  }