also looking at this
Promote: give the subscribe action a model it can call
#18
2 files
+144
-0
| @@ -0,0 +1,55 @@ | ||
| 1 | import { defineModel } from '@stacksjs/orm' | |
| 2 | import { schema } from '@stacksjs/validation' | |
| 3 | ||
| 4 | export default defineModel({ | |
| 5 | name: 'SubscriberEmail', | |
| 6 | table: 'subscriber_emails', | |
| 7 | primaryKey: 'id', | |
| 8 | autoIncrement: true, | |
| 9 | belongsTo: ['Subscriber'], | |
| 10 | ||
| 11 | traits: { | |
| 12 | useUuid: true, | |
| 13 | useTimestamps: true, | |
| 14 | useApi: { | |
| 15 | uri: 'subscriber-emails', | |
| 16 | routes: ['index', 'show'], | |
| 17 | // SubscriberEmail rows are PII (email + signup source). Without | |
| 18 | // this gate, anyone can scrape the list at GET /api/subscriber-emails. | |
| 19 | // Apps that genuinely want a public list (e.g. a transparency | |
| 20 | // page) can override the model in `app/Models/`. | |
| 21 | middleware: ['auth'], | |
| 22 | }, | |
| 23 | }, | |
| 24 | ||
| 25 | attributes: { | |
| 26 | email: { | |
| 27 | required: true, | |
| 28 | fillable: true, | |
| 29 | validation: { | |
| 30 | rule: schema.string().email().max(255), | |
| 31 | message: { | |
| 32 | string: 'email must be a string', | |
| 33 | required: 'email is required', | |
| 34 | email: 'email must be a valid email address', | |
| 35 | max: 'email must have a maximum of 255 characters', | |
| 36 | }, | |
| 37 | }, | |
| 38 | factory: faker => faker.internet.email(), | |
| 39 | }, | |
| 40 | ||
| 41 | source: { | |
| 42 | required: false, | |
| 43 | fillable: true, | |
| 44 | default: 'homepage', | |
| 45 | validation: { | |
| 46 | rule: schema.string().max(100), | |
| 47 | message: { | |
| 48 | string: 'source must be a string', | |
| 49 | max: 'source must have a maximum of 100 characters', | |
| 50 | }, | |
| 51 | }, | |
| 52 | factory: faker => faker.helpers.arrayElement(['homepage', 'blog', 'landing-page', 'api', 'import']), | |
| 53 | }, | |
| 54 | }, | |
| 55 | } as const) | |