@stacksjs/orm 0.72.16 → 0.72.18

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 (102) hide show
  1. package/dist/index.d.ts +97 -97
  2. package/dist/index.js +7 -7
  3. package/dist/models/Activity.ts +95 -0
  4. package/dist/models/AnalyticsEvent.ts +70 -0
  5. package/dist/models/Automation.ts +23 -0
  6. package/dist/models/AutomationRun.ts +26 -0
  7. package/dist/models/Board.ts +104 -0
  8. package/dist/models/BoardColumn.ts +88 -0
  9. package/dist/models/Campaign.ts +321 -0
  10. package/dist/models/CampaignSend.ts +191 -0
  11. package/dist/models/CampaignVariant.ts +25 -0
  12. package/dist/models/Card.ts +118 -0
  13. package/dist/models/CardComment.ts +68 -0
  14. package/dist/models/Comment.ts +109 -0
  15. package/dist/models/CommunicationSuppression.ts +22 -0
  16. package/dist/models/ConsentEvent.ts +30 -0
  17. package/dist/models/Content/Author.ts +109 -0
  18. package/dist/models/Content/Menu.ts +56 -0
  19. package/dist/models/Content/MenuItem.ts +91 -0
  20. package/dist/models/Content/Page.ts +205 -0
  21. package/dist/models/Content/PageRevision.ts +86 -0
  22. package/dist/models/Content/Post.ts +230 -0
  23. package/dist/models/Content/Redirect.ts +80 -0
  24. package/dist/models/Deployment.ts +117 -0
  25. package/dist/models/EmailIdempotency.ts +64 -0
  26. package/dist/models/EmailList.ts +134 -0
  27. package/dist/models/EmailListSubscriber.ts +91 -0
  28. package/dist/models/EmailSuppression.ts +52 -0
  29. package/dist/models/EmailWebhookEvent.ts +51 -0
  30. package/dist/models/Error.ts +77 -0
  31. package/dist/models/FailedJob.ts +84 -0
  32. package/dist/models/Forms/Form.ts +91 -0
  33. package/dist/models/Forms/FormField.ts +127 -0
  34. package/dist/models/Forms/FormSubmission.ts +114 -0
  35. package/dist/models/Job.ts +69 -0
  36. package/dist/models/Label.ts +67 -0
  37. package/dist/models/Log.ts +134 -0
  38. package/dist/models/MagicLinkToken.ts +97 -0
  39. package/dist/models/MailPreference.ts +213 -0
  40. package/dist/models/Notification.ts +68 -0
  41. package/dist/models/NotificationDelivery.ts +102 -0
  42. package/dist/models/PaymentMethod.ts +98 -0
  43. package/dist/models/PaymentProduct.ts +91 -0
  44. package/dist/models/PaymentTransaction.ts +78 -0
  45. package/dist/models/QueryLog.ts +182 -0
  46. package/dist/models/README.md +31 -0
  47. package/dist/models/Release.ts +90 -0
  48. package/dist/models/Request.ts +133 -0
  49. package/dist/models/SenderDomain.ts +22 -0
  50. package/dist/models/Site.ts +112 -0
  51. package/dist/models/SiteDomain.ts +74 -0
  52. package/dist/models/SmsOptOut.ts +65 -0
  53. package/dist/models/SocialAccount.ts +70 -0
  54. package/dist/models/SocialPost.ts +144 -0
  55. package/dist/models/Subscriber.ts +89 -0
  56. package/dist/models/SubscriberEmail.ts +55 -0
  57. package/dist/models/Subscription.ts +153 -0
  58. package/dist/models/Tag.ts +105 -0
  59. package/dist/models/Team.ts +75 -0
  60. package/dist/models/TeamInvitation.ts +159 -0
  61. package/dist/models/TeamMember.ts +88 -0
  62. package/dist/models/UsageEvent.ts +24 -0
  63. package/dist/models/User.ts +142 -0
  64. package/dist/models/commerce/Auction.ts +173 -0
  65. package/dist/models/commerce/AuctionItem.ts +204 -0
  66. package/dist/models/commerce/Bid.ts +129 -0
  67. package/dist/models/commerce/Cart.ts +140 -0
  68. package/dist/models/commerce/CartItem.ts +138 -0
  69. package/dist/models/commerce/Category.ts +125 -0
  70. package/dist/models/commerce/Coupon.ts +186 -0
  71. package/dist/models/commerce/Customer.ts +132 -0
  72. package/dist/models/commerce/DeliveryRoute.ts +127 -0
  73. package/dist/models/commerce/DeliveryStop.ts +166 -0
  74. package/dist/models/commerce/DigitalDelivery.ts +106 -0
  75. package/dist/models/commerce/Driver.ts +168 -0
  76. package/dist/models/commerce/DriverPing.ts +103 -0
  77. package/dist/models/commerce/GiftCard.ts +195 -0
  78. package/dist/models/commerce/LicenseKey.ts +89 -0
  79. package/dist/models/commerce/LoyaltyPoint.ts +108 -0
  80. package/dist/models/commerce/LoyaltyReward.ts +129 -0
  81. package/dist/models/commerce/Manufacturer.ts +90 -0
  82. package/dist/models/commerce/Order.ts +198 -0
  83. package/dist/models/commerce/OrderIdempotency.ts +34 -0
  84. package/dist/models/commerce/OrderItem.ts +51 -0
  85. package/dist/models/commerce/Payment.ts +182 -0
  86. package/dist/models/commerce/Pledge.ts +112 -0
  87. package/dist/models/commerce/PrintDevice.ts +120 -0
  88. package/dist/models/commerce/Product.ts +153 -0
  89. package/dist/models/commerce/ProductUnit.ts +113 -0
  90. package/dist/models/commerce/ProductVariant.ts +111 -0
  91. package/dist/models/commerce/Receipt.ts +144 -0
  92. package/dist/models/commerce/Review.ts +171 -0
  93. package/dist/models/commerce/ShippingMethod.ts +102 -0
  94. package/dist/models/commerce/ShippingRate.ts +79 -0
  95. package/dist/models/commerce/ShippingZone.ts +116 -0
  96. package/dist/models/commerce/TaxRate.ts +167 -0
  97. package/dist/models/commerce/Transaction.ts +127 -0
  98. package/dist/models/commerce/WaitlistProduct.ts +151 -0
  99. package/dist/models/commerce/WaitlistRestaurant.ts +189 -0
  100. package/dist/models/realtime/Websocket.ts +78 -0
  101. package/dist/password-policy.ts +46 -0
  102. package/package.json +4 -4
@@ -0,0 +1,133 @@
1
+ import { defineModel } from '@stacksjs/orm'
2
+ import { schema } from '@stacksjs/validation'
3
+
4
+ export default defineModel({
5
+ name: 'Request',
6
+ table: 'requests',
7
+ primaryKey: 'id',
8
+ autoIncrement: true,
9
+
10
+ indexes: [
11
+ {
12
+ name: 'requests_created_at_index',
13
+ columns: ['created_at'],
14
+ },
15
+ {
16
+ name: 'requests_duration_ms_index',
17
+ columns: ['duration_ms'],
18
+ },
19
+ {
20
+ name: 'requests_status_code_index',
21
+ columns: ['status_code'],
22
+ },
23
+ ],
24
+
25
+ traits: {
26
+ useTimestamps: true,
27
+ useSoftDeletes: true,
28
+ useSeeder: {
29
+ count: 50,
30
+ },
31
+ useApi: {
32
+ uri: 'requests',
33
+ routes: ['index', 'store', 'show', 'update', 'destroy'],
34
+ middleware: ['auth'],
35
+ },
36
+ },
37
+
38
+ attributes: {
39
+ method: {
40
+ fillable: true,
41
+ validation: {
42
+ rule: schema.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD']),
43
+ message: {
44
+ enum: 'method must be a valid HTTP method',
45
+ required: 'method is required',
46
+ },
47
+ },
48
+ factory: faker => faker.helpers.arrayElement(['GET', 'POST', 'PUT', 'DELETE']),
49
+ },
50
+
51
+ path: {
52
+ fillable: true,
53
+ validation: {
54
+ rule: schema.string(),
55
+ message: {
56
+ string: 'path must be a string',
57
+ required: 'path is required',
58
+ },
59
+ },
60
+ factory: faker => faker.internet.url(),
61
+ },
62
+
63
+ status_code: {
64
+ fillable: true,
65
+ validation: {
66
+ rule: schema.number(),
67
+ message: {
68
+ number: 'status_code must be a number',
69
+ required: 'status_code is required',
70
+ },
71
+ },
72
+ factory: faker => faker.helpers.arrayElement([200, 201, 400, 401, 403, 404, 500]),
73
+ },
74
+
75
+ duration_ms: {
76
+ fillable: true,
77
+ validation: {
78
+ rule: schema.number(),
79
+ message: {
80
+ number: 'duration_ms must be a number',
81
+ required: 'duration_ms is required',
82
+ },
83
+ },
84
+ factory: faker => faker.number.int({ min: 50, max: 1000 }),
85
+ },
86
+
87
+ ip_address: {
88
+ fillable: true,
89
+ validation: {
90
+ rule: schema.string(),
91
+ message: {
92
+ string: 'ip_address must be a string',
93
+ required: 'ip_address is required',
94
+ },
95
+ },
96
+ factory: faker => faker.internet.ip(),
97
+ },
98
+
99
+ memory_usage: {
100
+ fillable: true,
101
+ validation: {
102
+ rule: schema.number(),
103
+ message: {
104
+ number: 'memory_usage must be a number in MB',
105
+ required: 'memory_usage is required',
106
+ },
107
+ },
108
+ factory: faker => faker.number.int({ min: 50, max: 512 }),
109
+ },
110
+
111
+ user_agent: {
112
+ fillable: true,
113
+ validation: {
114
+ rule: schema.string(),
115
+ message: {
116
+ string: 'user_agent must be a string',
117
+ },
118
+ },
119
+ factory: faker => faker.internet.userAgent(),
120
+ },
121
+
122
+ error_message: {
123
+ fillable: true,
124
+ validation: {
125
+ rule: schema.string(),
126
+ message: {
127
+ string: 'error_message must be a string',
128
+ },
129
+ },
130
+ factory: faker => faker.helpers.maybe(() => faker.lorem.sentence(), { probability: 0.2 }),
131
+ },
132
+ },
133
+ } as const)
@@ -0,0 +1,22 @@
1
+ import { defineModel } from '@stacksjs/orm'
2
+ import { schema } from '@stacksjs/validation'
3
+
4
+ export default defineModel({
5
+ name: 'SenderDomain',
6
+ table: 'sender_domains',
7
+ belongsTo: ['Team'],
8
+ traits: {
9
+ useUuid: true,
10
+ useTimestamps: true,
11
+ useApi: { uri: 'sender-domains', routes: ['index', 'store', 'show', 'update', 'destroy'], middleware: ['auth', 'team'] },
12
+ },
13
+ indexes: [{ name: 'sender_domains_domain_unique', columns: ['domain'], unique: true }],
14
+ attributes: {
15
+ domain: { required: true, fillable: true, validation: { rule: schema.string().max(253) }, factory: faker => faker.internet.domainName() },
16
+ status: { required: true, fillable: true, default: 'pending', validation: { rule: schema.enum(['pending', 'verified', 'failed', 'disabled']) }, factory: () => 'pending' },
17
+ selector: { required: true, fillable: true, default: 'mail', validation: { rule: schema.string().max(63) }, factory: () => 'mail' },
18
+ dnsRecords: { required: false, fillable: true, validation: { rule: schema.json() }, factory: () => JSON.stringify([]) },
19
+ verifiedAt: { required: false, fillable: true, validation: { rule: schema.timestamp() }, factory: () => null },
20
+ lastCheckedAt: { required: false, fillable: true, validation: { rule: schema.timestamp() }, factory: () => null },
21
+ },
22
+ } as const)
@@ -0,0 +1,112 @@
1
+ import { defineModel } from '@stacksjs/orm'
2
+ import { schema } from '@stacksjs/validation'
3
+
4
+ /**
5
+ * A public web property served by this app: one host (subdomain of
6
+ * `config.sites.baseDomain`, plus any verified custom domains via
7
+ * SiteDomain), one content tree, one theme. A team may own several - a main
8
+ * site, a microsite, a campaign landing page - each with its own domain.
9
+ *
10
+ * The `useApi` surface is the ADMIN surface (auth'd, team-scoped). Public
11
+ * visitors never read sites through it; the serving layer resolves the site
12
+ * from the Host header (`@stacksjs/sites`).
13
+ */
14
+ export default defineModel({
15
+ name: 'Site',
16
+ table: 'sites',
17
+ primaryKey: 'id',
18
+ autoIncrement: true,
19
+
20
+ traits: {
21
+ useUuid: true,
22
+ useTimestamps: true,
23
+ observe: true, // site:updated clears the host-resolution cache
24
+
25
+ useSeeder: {
26
+ count: 2,
27
+ },
28
+
29
+ useApi: {
30
+ uri: 'sites',
31
+ routes: ['index', 'store', 'show', 'update', 'destroy'],
32
+ middleware: ['auth', 'team'],
33
+ },
34
+
35
+ useSearch: {
36
+ displayable: ['id', 'name', 'subdomain', 'status'],
37
+ searchable: ['name', 'subdomain'],
38
+ sortable: ['name', 'createdAt'],
39
+ filterable: ['status'],
40
+ },
41
+ },
42
+
43
+ belongsTo: ['Team'],
44
+ hasMany: ['SiteDomain'],
45
+
46
+ attributes: {
47
+ name: {
48
+ required: true,
49
+ order: 1,
50
+ fillable: true,
51
+ validation: {
52
+ rule: schema.string().min(2).max(255),
53
+ message: {
54
+ min: 'Site name must have a minimum of 2 characters',
55
+ max: 'Site name must have a maximum of 255 characters',
56
+ },
57
+ },
58
+ factory: faker => `${faker.company.name()} School`,
59
+ },
60
+
61
+ subdomain: {
62
+ required: true,
63
+ order: 2,
64
+ fillable: true,
65
+ unique: true,
66
+ validation: {
67
+ rule: schema.string().min(2).max(63).matches(/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/),
68
+ message: {
69
+ matches: 'Subdomain may only contain lowercase letters, numbers and hyphens',
70
+ },
71
+ },
72
+ factory: faker => faker.internet.domainWord(),
73
+ },
74
+
75
+ status: {
76
+ required: true,
77
+ order: 3,
78
+ fillable: true,
79
+ default: 'active',
80
+ validation: {
81
+ rule: schema.enum(['active', 'suspended', 'archived'] as const),
82
+ },
83
+ factory: () => 'active',
84
+ },
85
+
86
+ /** Theme tokens, locale, analytics id - render-time knobs, JSON. */
87
+ settings: {
88
+ required: false,
89
+ order: 4,
90
+ fillable: true,
91
+ validation: {
92
+ rule: schema.json(),
93
+ },
94
+ factory: () => JSON.stringify({}),
95
+ },
96
+
97
+ timezone: {
98
+ required: false,
99
+ order: 5,
100
+ fillable: true,
101
+ default: 'America/New_York',
102
+ validation: {
103
+ rule: schema.string().max(64),
104
+ },
105
+ factory: () => 'America/New_York',
106
+ },
107
+ },
108
+
109
+ dashboard: {
110
+ highlight: true,
111
+ },
112
+ })
@@ -0,0 +1,74 @@
1
+ import { defineModel } from '@stacksjs/orm'
2
+ import { schema } from '@stacksjs/validation'
3
+
4
+ /**
5
+ * A custom domain routed to a Site. Only rows with `verifiedAt` set resolve
6
+ * traffic - verification proves the school controls the DNS before we serve
7
+ * their content on it. `isPrimary` names the canonical host: sessions are
8
+ * host-scoped cookies, so every other host 301s there and portal logins
9
+ * always land on one origin.
10
+ */
11
+ export default defineModel({
12
+ name: 'SiteDomain',
13
+ table: 'site_domains',
14
+ primaryKey: 'id',
15
+ autoIncrement: true,
16
+
17
+ traits: {
18
+ useTimestamps: true,
19
+ observe: true, // domain changes clear the host-resolution cache
20
+
21
+ useApi: {
22
+ uri: 'site-domains',
23
+ routes: ['index', 'store', 'show', 'update', 'destroy'],
24
+ middleware: ['auth'],
25
+ },
26
+ },
27
+
28
+ belongsTo: ['Site'],
29
+
30
+ attributes: {
31
+ domain: {
32
+ required: true,
33
+ order: 1,
34
+ fillable: true,
35
+ unique: true,
36
+ validation: {
37
+ rule: schema.string().min(4).max(253),
38
+ },
39
+ factory: faker => faker.internet.domainName(),
40
+ },
41
+
42
+ isPrimary: {
43
+ required: false,
44
+ order: 2,
45
+ fillable: true,
46
+ default: false,
47
+ validation: {
48
+ rule: schema.boolean(),
49
+ },
50
+ factory: () => false,
51
+ },
52
+
53
+ verifiedAt: {
54
+ required: false,
55
+ order: 3,
56
+ fillable: true,
57
+ validation: {
58
+ rule: schema.timestamp(),
59
+ },
60
+ factory: () => null,
61
+ },
62
+
63
+ sslStatus: {
64
+ required: false,
65
+ order: 4,
66
+ fillable: true,
67
+ default: 'pending',
68
+ validation: {
69
+ rule: schema.enum(['pending', 'issued', 'failed'] as const),
70
+ },
71
+ factory: () => 'pending',
72
+ },
73
+ },
74
+ })
@@ -0,0 +1,65 @@
1
+ import { defineModel } from '@stacksjs/orm'
2
+ import { schema } from '@stacksjs/validation'
3
+
4
+ /**
5
+ * A phone number that texted STOP. Keyed by NUMBER, not user - the reply
6
+ * comes from a handset, and whoever holds it has spoken for it. Checked by
7
+ * `notify()`'s sms channel on every non-emergency send; written and cleared
8
+ * by `handleInboundSms()` (`@stacksjs/sms`).
9
+ */
10
+ export default defineModel({
11
+ name: 'SmsOptOut',
12
+ table: 'sms_opt_outs',
13
+ primaryKey: 'id',
14
+ autoIncrement: true,
15
+
16
+ indexes: [
17
+ {
18
+ name: 'sms_opt_outs_phone_unique',
19
+ columns: ['phone'],
20
+ unique: true,
21
+ },
22
+ ],
23
+
24
+ traits: {
25
+ useTimestamps: true,
26
+ },
27
+
28
+ attributes: {
29
+ /** E.164 where derivable (`+13105550199`). */
30
+ phone: {
31
+ required: true,
32
+ order: 1,
33
+ fillable: true,
34
+ unique: true,
35
+ validation: {
36
+ rule: schema.string().min(7).max(20),
37
+ },
38
+ factory: faker => faker.phone.number(),
39
+ },
40
+
41
+ reason: {
42
+ required: false,
43
+ order: 2,
44
+ fillable: true,
45
+ default: 'stop-keyword',
46
+ validation: {
47
+ rule: schema.string().max(64),
48
+ },
49
+ factory: () => 'stop-keyword',
50
+ },
51
+
52
+ optedOutAt: {
53
+ required: true,
54
+ order: 3,
55
+ fillable: true,
56
+ validation: {
57
+ rule: schema.timestamp(),
58
+ },
59
+ factory: (faker) => {
60
+ const date = faker.date.recent()
61
+ return date.toISOString().slice(0, 19).replace('T', ' ')
62
+ },
63
+ },
64
+ },
65
+ } as const)
@@ -0,0 +1,70 @@
1
+ import { defineModel } from '@stacksjs/orm'
2
+ import { schema } from '@stacksjs/validation'
3
+
4
+ /**
5
+ * A social provider identity linked to a local user (stacksjs/stacks#2276).
6
+ *
7
+ * One row per (provider, provider account): a link table rather than columns
8
+ * on `users`, so one user can attach several providers and a provider-side
9
+ * email change cannot orphan the link. The unique index on
10
+ * `(provider, provider_user_id)` is what makes "sign in with the same GitHub
11
+ * account" resolve to the same local user forever.
12
+ *
13
+ * Rows are only ever written by the framework's social sign-in policy
14
+ * (`resolveSocialSignIn` in @stacksjs/auth) — the takeover guard lives there,
15
+ * not here.
16
+ */
17
+ export default defineModel({
18
+ name: 'SocialAccount',
19
+ table: 'social_accounts',
20
+ primaryKey: 'id',
21
+ autoIncrement: true,
22
+
23
+ indexes: [
24
+ {
25
+ name: 'social_accounts_provider_provider_user_id_unique',
26
+ columns: ['provider', 'provider_user_id'],
27
+ unique: true,
28
+ },
29
+ {
30
+ name: 'social_accounts_user_id_index',
31
+ columns: ['user_id'],
32
+ },
33
+ ],
34
+
35
+ traits: {
36
+ useTimestamps: true,
37
+ },
38
+
39
+ belongsTo: ['User'],
40
+
41
+ attributes: {
42
+ provider: {
43
+ required: true,
44
+ fillable: true,
45
+ validation: {
46
+ rule: schema.string().max(50),
47
+ message: { max: 'Provider must not exceed 50 characters' },
48
+ },
49
+ },
50
+
51
+ providerUserId: {
52
+ required: true,
53
+ fillable: true,
54
+ validation: {
55
+ rule: schema.string().max(255),
56
+ message: { max: 'Provider user id must not exceed 255 characters' },
57
+ },
58
+ },
59
+
60
+ // The address the provider reported at link time. Informational — sign-in
61
+ // resolves through (provider, provider_user_id), never through this.
62
+ providerEmail: {
63
+ fillable: true,
64
+ validation: {
65
+ rule: schema.string().max(255),
66
+ message: { max: 'Provider email must not exceed 255 characters' },
67
+ },
68
+ },
69
+ },
70
+ } as const)
@@ -0,0 +1,144 @@
1
+ import { defineModel } from '@stacksjs/orm'
2
+ import { schema } from '@stacksjs/validation'
3
+
4
+ export default defineModel({
5
+ name: 'SocialPost',
6
+ table: 'social_posts',
7
+ primaryKey: 'id',
8
+ autoIncrement: true,
9
+
10
+ traits: {
11
+ useUuid: true,
12
+ useTimestamps: true,
13
+ useSeeder: {
14
+ count: 20,
15
+ },
16
+ useApi: {
17
+ uri: 'social-posts',
18
+ routes: ['index', 'store', 'show', 'update', 'destroy'],
19
+ middleware: ['auth'],
20
+ },
21
+ useSearch: {
22
+ displayable: ['id', 'content', 'platform', 'status', 'scheduledAt', 'publishedAt', 'reach'],
23
+ searchable: ['content', 'externalId'],
24
+ sortable: ['platform', 'status', 'scheduledAt', 'publishedAt', 'reach', 'createdAt', 'updatedAt'],
25
+ filterable: ['platform', 'status', 'userId'],
26
+ },
27
+ observe: true,
28
+ },
29
+
30
+ belongsTo: ['User'],
31
+
32
+ attributes: {
33
+ content: {
34
+ required: true,
35
+ fillable: true,
36
+ validation: {
37
+ rule: schema.string().min(1).max(2000),
38
+ },
39
+ factory: faker => faker.lorem.paragraph(),
40
+ },
41
+
42
+ platform: {
43
+ required: true,
44
+ fillable: true,
45
+ validation: {
46
+ rule: schema.enum(['twitter', 'facebook', 'instagram', 'linkedin', 'tiktok', 'youtube']),
47
+ },
48
+ factory: faker => faker.helpers.arrayElement(['twitter', 'facebook', 'instagram', 'linkedin', 'tiktok']),
49
+ },
50
+
51
+ status: {
52
+ required: true,
53
+ fillable: true,
54
+ default: 'draft',
55
+ validation: {
56
+ rule: schema.enum(['draft', 'scheduled', 'published', 'failed']),
57
+ },
58
+ factory: faker => faker.helpers.arrayElement(['draft', 'scheduled', 'published', 'published', 'published']),
59
+ },
60
+
61
+ scheduledAt: {
62
+ required: false,
63
+ fillable: true,
64
+ validation: {
65
+ rule: schema.timestamp(),
66
+ },
67
+ factory: (faker) => {
68
+ return faker.date.soon({ days: 7 }).toISOString().slice(0, 19).replace('T', ' ')
69
+ },
70
+ },
71
+
72
+ publishedAt: {
73
+ required: false,
74
+ fillable: true,
75
+ validation: {
76
+ rule: schema.timestamp(),
77
+ },
78
+ factory: (faker) => {
79
+ if (faker.datatype.boolean()) {
80
+ return faker.date.recent({ days: 14 }).toISOString().slice(0, 19).replace('T', ' ')
81
+ }
82
+ return null
83
+ },
84
+ },
85
+
86
+ likes: {
87
+ required: false,
88
+ fillable: true,
89
+ default: 0,
90
+ validation: {
91
+ rule: schema.number().min(0),
92
+ },
93
+ factory: faker => faker.number.int({ min: 0, max: 5000 }),
94
+ },
95
+
96
+ shares: {
97
+ required: false,
98
+ fillable: true,
99
+ default: 0,
100
+ validation: {
101
+ rule: schema.number().min(0),
102
+ },
103
+ factory: faker => faker.number.int({ min: 0, max: 500 }),
104
+ },
105
+
106
+ comments: {
107
+ required: false,
108
+ fillable: true,
109
+ default: 0,
110
+ validation: {
111
+ rule: schema.number().min(0),
112
+ },
113
+ factory: faker => faker.number.int({ min: 0, max: 200 }),
114
+ },
115
+
116
+ reach: {
117
+ required: false,
118
+ fillable: true,
119
+ default: 0,
120
+ validation: {
121
+ rule: schema.number().min(0),
122
+ },
123
+ factory: faker => faker.number.int({ min: 0, max: 50000 }),
124
+ },
125
+
126
+ imageUrl: {
127
+ required: false,
128
+ fillable: true,
129
+ validation: {
130
+ rule: schema.string().url(),
131
+ },
132
+ factory: faker => faker.image.url(),
133
+ },
134
+
135
+ externalId: {
136
+ required: false,
137
+ fillable: true,
138
+ validation: {
139
+ rule: schema.string().max(255),
140
+ },
141
+ factory: faker => faker.string.alphanumeric(20),
142
+ },
143
+ },
144
+ } as const)