@stacksjs/defaults 0.70.355 → 0.70.357
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/ai/skills/stacks-email/SKILL.md +38 -1
- package/ai/skills/stacks-orm/SKILL.md +6 -0
- package/app/Actions/ContactAction.ts +2 -2
- package/app/Actions/Dashboard/Analytics/EventAnalyticsAction.ts +2 -3
- package/app/Actions/Dashboard/Analytics/MarketingAnalyticsAction.ts +2 -3
- package/app/Actions/Dashboard/Analytics/SalesAnalyticsAction.ts +2 -3
- package/app/Actions/Dashboard/Analytics/WebAnalyticsAction.ts +9 -3
- package/app/Actions/Dashboard/Auth/MeAction.ts +4 -7
- package/app/Actions/Dashboard/Buddy/BuddyChatAction.ts +2 -3
- package/app/Actions/Dashboard/Cloud/CloudIndexAction.ts +8 -1
- package/app/Actions/Dashboard/Cloud/ServerlessIndexAction.ts +15 -8
- package/app/Actions/Dashboard/Commerce/CommerceCategoriesAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/CommerceCouponsAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/CommerceCustomersAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/CommerceDashboardAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/CommerceDeliveryAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/CommerceGiftCardsAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/CommerceOrdersAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/CommercePaymentsAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/CommercePosAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/CommercePosCheckoutAction.ts +75 -61
- package/app/Actions/Dashboard/Commerce/CommercePrintDevicesAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/CommercePrintLogsAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/CommerceProductDetailAction.ts +3 -4
- package/app/Actions/Dashboard/Commerce/CommerceProductsAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/CommerceTaxesAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/DeliveryRouteIndexAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/DigitalDeliveryIndexAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/DriverIndexAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/LicenseKeyIndexAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/LicenseKeyOptionsAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/ManufacturerIndexAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/ProductUnitIndexAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/ProductVariantIndexAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/ProductWaitlistIndexAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/RestaurantWaitlistIndexAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/ReviewIndexAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/ShippingMethodIndexAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/ShippingRateIndexAction.ts +2 -4
- package/app/Actions/Dashboard/Commerce/ShippingZoneIndexAction.ts +2 -4
- package/app/Actions/Dashboard/Content/AuthorDestroyAction.ts +23 -9
- package/app/Actions/Dashboard/Content/AuthorIndexAction.ts +32 -26
- package/app/Actions/Dashboard/Content/AuthorStoreAction.ts +44 -24
- package/app/Actions/Dashboard/Content/AuthorUpdateAction.ts +48 -26
- package/app/Actions/Dashboard/Content/CategoryDestroyAction.ts +27 -8
- package/app/Actions/Dashboard/Content/CategoryIndexAction.ts +21 -15
- package/app/Actions/Dashboard/Content/CategoryStoreAction.ts +47 -29
- package/app/Actions/Dashboard/Content/CommentDestroyAction.ts +17 -4
- package/app/Actions/Dashboard/Content/CommentIndexAction.ts +23 -17
- package/app/Actions/Dashboard/Content/CommentUpdateAction.ts +30 -12
- package/app/Actions/Dashboard/Content/ContentDashboardAction.ts +43 -37
- package/app/Actions/Dashboard/Content/PageDestroyAction.ts +17 -4
- package/app/Actions/Dashboard/Content/PageIndexAction.ts +23 -17
- package/app/Actions/Dashboard/Content/PageStoreAction.ts +33 -18
- package/app/Actions/Dashboard/Content/PageUpdateAction.ts +40 -22
- package/app/Actions/Dashboard/Content/PostDestroyAction.ts +24 -11
- package/app/Actions/Dashboard/Content/PostIndexAction.ts +55 -49
- package/app/Actions/Dashboard/Content/PostStoreAction.ts +43 -33
- package/app/Actions/Dashboard/Content/PostUpdateAction.ts +46 -34
- package/app/Actions/Dashboard/Content/TagDestroyAction.ts +27 -8
- package/app/Actions/Dashboard/Content/TagIndexAction.ts +31 -25
- package/app/Actions/Dashboard/Content/TagStoreAction.ts +44 -23
- package/app/Actions/Dashboard/Content/content-input.ts +4 -4
- package/app/Actions/Dashboard/Content/post-input.ts +60 -8
- package/app/Actions/Dashboard/DashboardActivityAction.ts +2 -5
- package/app/Actions/Dashboard/Data/ActivityIndexAction.ts +2 -5
- package/app/Actions/Dashboard/Data/SubscriberIndexAction.ts +2 -5
- package/app/Actions/Dashboard/Data/TeamIndexAction.ts +2 -5
- package/app/Actions/Dashboard/Data/UserIndexAction.ts +2 -5
- package/app/Actions/Dashboard/Deployments/CreateDeployment.ts +23 -19
- package/app/Actions/Dashboard/Deployments/GetAverageDeploymentTime.ts +8 -2
- package/app/Actions/Dashboard/Deployments/GetDeployScript.ts +3 -6
- package/app/Actions/Dashboard/Deployments/GetDeployment.ts +4 -5
- package/app/Actions/Dashboard/Deployments/GetDeploymentCount.ts +7 -1
- package/app/Actions/Dashboard/Deployments/GetDeploymentLiveTerminalOutput.ts +10 -9
- package/app/Actions/Dashboard/Deployments/GetDeployments.ts +2 -4
- package/app/Actions/Dashboard/Deployments/GetRecentDeployments.ts +8 -2
- package/app/Actions/Dashboard/Deployments/UpdateDeployScript.ts +18 -5
- package/app/Actions/Dashboard/Email/CapturedMailIndexAction.ts +2 -4
- package/app/Actions/Dashboard/Email/CapturedMailShowAction.ts +3 -4
- package/app/Actions/Dashboard/Infrastructure/InsightsAction.ts +15 -14
- package/app/Actions/Dashboard/Infrastructure/LogIndexAction.ts +2 -8
- package/app/Actions/Dashboard/Jobs/JobIndexAction.ts +2 -4
- package/app/Actions/Dashboard/Jobs/JobShowAction.ts +13 -8
- package/app/Actions/Dashboard/Jobs/JobStatsAction.ts +2 -4
- package/app/Actions/Dashboard/Kanban/BoardDestroyAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/BoardShowAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/BoardStoreAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/BoardUpdateAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/BoardsIndexAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/BoardsReorderAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/CardAssigneesSyncAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/CardCommentDestroyAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/CardCommentStoreAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/CardCommentUpdateAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/CardDestroyAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/CardLabelsSyncAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/CardShowAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/CardStoreAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/CardUpdateAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/CardsReorderAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/ColumnDestroyAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/ColumnStoreAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/ColumnUpdateAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/ColumnsReorderAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/LabelDestroyAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/LabelStoreAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/LabelUpdateAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/UsersListAction.ts +2 -3
- package/app/Actions/Dashboard/Kanban/kanban-response.ts +5 -0
- package/app/Actions/Dashboard/Library/CreateComponent.ts +15 -6
- package/app/Actions/Dashboard/Library/CreateFunction.ts +15 -6
- package/app/Actions/Dashboard/Library/DependencyIndexAction.ts +88 -77
- package/app/Actions/Dashboard/Library/GetAverageReleaseTime.ts +21 -15
- package/app/Actions/Dashboard/Library/GetComponents.ts +14 -7
- package/app/Actions/Dashboard/Library/GetDownloadCount.ts +14 -5
- package/app/Actions/Dashboard/Library/GetFunctions.ts +12 -5
- package/app/Actions/Dashboard/Library/GetReleaseCount.ts +14 -5
- package/app/Actions/Dashboard/Library/GetReleases.ts +17 -10
- package/app/Actions/Dashboard/Library/PackageIndexAction.ts +14 -7
- package/app/Actions/Dashboard/Models/ModelDestroyAction.ts +7 -5
- package/app/Actions/Dashboard/Models/ModelShowAction.ts +82 -174
- package/app/Actions/Dashboard/Models/ModelStoreAction.ts +6 -4
- package/app/Actions/Dashboard/Models/ModelUpdateAction.ts +9 -7
- package/app/Actions/Dashboard/Models/ModelsIndexAction.ts +47 -17
- package/app/Actions/Dashboard/Models/model-write.ts +20 -5
- package/app/Actions/Dashboard/Notifications/NotificationDeliveryHistoryAction.ts +46 -36
- package/app/Actions/Dashboard/Notifications/NotificationDeliveryIndexAction.ts +14 -6
- package/app/Actions/Dashboard/Notifications/NotificationDeliveryOverviewAction.ts +96 -84
- package/app/Actions/Dashboard/Notifications/NotificationDeliveryRetryAction.ts +34 -21
- package/app/Actions/Dashboard/Queries/QueryDashboardAction.ts +2 -4
- package/app/Actions/Dashboard/Queries/QueryShowAction.ts +2 -3
- package/app/Actions/Dashboard/Queue/QueueStatsAction.ts +2 -4
- package/app/Actions/Dashboard/Queue/QueueWorkersAction.ts +2 -4
- package/app/Actions/Dashboard/Rbac/PermissionDestroyAction.ts +2 -2
- package/app/Actions/Dashboard/Rbac/PermissionStoreAction.ts +2 -2
- package/app/Actions/Dashboard/Rbac/PermissionsIndexAction.ts +2 -3
- package/app/Actions/Dashboard/Rbac/RoleDestroyAction.ts +2 -2
- package/app/Actions/Dashboard/Rbac/RolePermissionsShowAction.ts +2 -2
- package/app/Actions/Dashboard/Rbac/RolePermissionsSyncAction.ts +2 -6
- package/app/Actions/Dashboard/Rbac/RoleStoreAction.ts +2 -2
- package/app/Actions/Dashboard/Rbac/RolesIndexAction.ts +4 -6
- package/app/Actions/Dashboard/Rbac/UserRolesShowAction.ts +2 -2
- package/app/Actions/Dashboard/Rbac/UserRolesSyncAction.ts +2 -9
- package/app/Actions/Dashboard/Rbac/UsersListAction.ts +2 -3
- package/app/Actions/Dashboard/Rbac/rbac-response.ts +10 -0
- package/app/Actions/Dashboard/Realtime/RealtimeStatsAction.ts +2 -4
- package/app/Actions/Dashboard/Search/GlobalSearchAction.ts +68 -55
- package/app/Actions/Dashboard/Teams/TeamInvitationDestroyAction.ts +34 -16
- package/app/Actions/Dashboard/Teams/TeamInvitationResendAction.ts +52 -29
- package/app/Actions/Dashboard/Teams/TeamInviteAction.ts +102 -71
- package/app/Actions/Dashboard/Teams/TeamMemberDestroyAction.ts +36 -17
- package/app/Actions/Dashboard/Teams/TeamMemberUpdateAction.ts +39 -26
- package/app/Actions/Dashboard/Teams/TeamPeopleIndexAction.ts +71 -58
- package/app/Actions/Dashboard/Teams/team-invitation-delivery.ts +29 -7
- package/app/Actions/Dashboard/Teams/team-member-count.ts +4 -2
- package/app/Actions/Dashboard/Teams/team-records.test.ts +2 -0
- package/app/Actions/Dashboard/Teams/team-records.ts +2 -0
- package/app/Actions/Dashboard/dashboard-response.ts +16 -0
- package/app/Actions/SendWelcomeEmail.ts +1 -1
- package/app/Actions/Teams/AcceptInvitationAction.ts +74 -51
- package/app/Actions/Teams/ShowInvitationAction.ts +21 -14
- package/app/Actions/Teams/team-response.ts +23 -0
- package/app/Mail/OrderConfirmation.ts +1 -1
- package/app/Mail/SubscriptionConfirmation.ts +1 -1
- package/app/Mail/TeamInvitation.ts +1 -1
- package/app/Models/EmailIdempotency.ts +64 -0
- package/app/Models/EmailSuppression.ts +52 -0
- package/app/Models/EmailWebhookEvent.ts +51 -0
- package/app/Models/TeamInvitation.ts +13 -0
- package/functions/data.ts +0 -1
- package/functions/jobs.ts +0 -1
- package/ide/vscode/package.json +1 -1
- package/package.json +1 -1
- package/resources/components/Dashboard/Data/DataRecords.stx +0 -4
- package/resources/components/Dashboard/Jobs/JobDetail.stx +3 -2
- package/resources/components/Dashboard/Models/ModelRecordsDashboard.stx +7 -13
- package/resources/components/Dashboard/Models/ModelsOverview.stx +1 -1
- package/views/dashboard/.discovered-models.json +30 -0
- package/views/dashboard/stores/auth.ts +15 -14
|
@@ -14,6 +14,7 @@ Multi-driver email system with template rendering, S3-based inbox management, an
|
|
|
14
14
|
- Core package: `storage/framework/core/email/src/`
|
|
15
15
|
- Configuration: `config/email.ts`
|
|
16
16
|
- Application mail: `app/Mail/`
|
|
17
|
+
- Persistence models: `storage/framework/defaults/app/Models/EmailSuppression.ts`, `EmailIdempotency.ts`, `EmailWebhookEvent.ts`
|
|
17
18
|
- Email layouts: `storage/framework/defaults/resources/emails/layouts/`
|
|
18
19
|
- Email resources: `storage/framework/defaults/resources/emails/`
|
|
19
20
|
|
|
@@ -54,11 +55,30 @@ await mail.send({
|
|
|
54
55
|
text: 'Hello!'
|
|
55
56
|
})
|
|
56
57
|
|
|
58
|
+
// Use this when later state depends on successful provider delivery.
|
|
59
|
+
await mail.sendOrFail({
|
|
60
|
+
to: 'user@example.com',
|
|
61
|
+
subject: 'Your invitation',
|
|
62
|
+
text: 'Open the invitation link.'
|
|
63
|
+
})
|
|
64
|
+
|
|
57
65
|
// Switch driver
|
|
58
66
|
const sendgridMail = mail.use('sendgrid')
|
|
59
67
|
await sendgridMail.send(message)
|
|
60
68
|
```
|
|
61
69
|
|
|
70
|
+
`mail.send()` always returns an `EmailResult`. Provider rejection is represented
|
|
71
|
+
as `{ success: false, message, provider }`, which is useful for campaign jobs
|
|
72
|
+
that aggregate individual outcomes. It may still throw for invalid framework
|
|
73
|
+
configuration. `mail.sendOrFail()` returns the same successful result and throws
|
|
74
|
+
`EmailDeliveryError` for a structured provider failure. Use `sendOrFail()` when
|
|
75
|
+
an action reports that mail was sent, when a caller relies on `.catch()`, or when
|
|
76
|
+
delivery status is persisted after the call.
|
|
77
|
+
|
|
78
|
+
Keep template rendering fallback separate from provider delivery. Resolve HTML
|
|
79
|
+
and text first, fall back to plain text only when rendering fails, then call
|
|
80
|
+
`sendOrFail()` once outside the template `try` block.
|
|
81
|
+
|
|
62
82
|
## Email Class
|
|
63
83
|
|
|
64
84
|
```typescript
|
|
@@ -230,7 +250,7 @@ export async function sendSubscriptionConfirmation({ to, subscriberUuid }: Optio
|
|
|
230
250
|
}
|
|
231
251
|
})
|
|
232
252
|
|
|
233
|
-
await mail.
|
|
253
|
+
await mail.sendOrFail({
|
|
234
254
|
from: { name: config.app.name, address: config.email.from.address },
|
|
235
255
|
to,
|
|
236
256
|
subject: 'Confirm your subscription',
|
|
@@ -240,6 +260,21 @@ export async function sendSubscriptionConfirmation({ to, subscriberUuid }: Optio
|
|
|
240
260
|
}
|
|
241
261
|
```
|
|
242
262
|
|
|
263
|
+
## Delivery persistence models
|
|
264
|
+
|
|
265
|
+
Stacks ships three internal models and their generated migrations:
|
|
266
|
+
|
|
267
|
+
- `EmailSuppression` uses `email_suppressions` and uniquely keys `email + type`.
|
|
268
|
+
- `EmailIdempotency` uses `email_idempotency` and uniquely keys `idempotency_key`.
|
|
269
|
+
- `EmailWebhookEvent` uses `email_webhook_events` and uniquely keys `provider + event_id`.
|
|
270
|
+
|
|
271
|
+
Each model declares authenticated `useApi` index, show, and destroy routes, but
|
|
272
|
+
sets `dashboard.enabled` to false so operational records do not clutter the
|
|
273
|
+
generic model catalog. Sensitive idempotency keys, recipients, subjects, and
|
|
274
|
+
provider event IDs are hidden from generated responses. Run `buddy migrate`
|
|
275
|
+
after upgrading so suppression, send deduplication, and webhook deduplication
|
|
276
|
+
are enforced rather than using their legacy warn-once compatibility path.
|
|
277
|
+
|
|
243
278
|
## Inbound MIME and attachment storage
|
|
244
279
|
|
|
245
280
|
`parseInboundEmail()` parses RFC messages with bounded header, nesting, total-size, and attachment-count limits. It returns normalized sender and recipient data, text and HTML bodies, and binary-safe attachments. Attachment filenames are sanitized before they become S3 keys.
|
|
@@ -274,6 +309,8 @@ Reprocessing refreshes existing messages instead of skipping them, preserves the
|
|
|
274
309
|
- The `mail` singleton auto-registers all 5 drivers on initialization
|
|
275
310
|
- SMTP driver handles TLS handshake manually (not via node:tls)
|
|
276
311
|
- SendGrid/Mailgun retry with exponential backoff on failure
|
|
312
|
+
- `mail.send()` returns structured failures; use `mail.sendOrFail()` when success is required
|
|
313
|
+
- Suppression, send idempotency, and webhook dedup are backed by built-in `useApi` models
|
|
277
314
|
- Mailtrap requires `inboxId` for sandbox mode
|
|
278
315
|
- EmailSDK reads inbox from S3 (bucket configured via env)
|
|
279
316
|
- EmailSDK attachment downloads use binary-safe S3 reads and opaque IDs
|
|
@@ -196,6 +196,12 @@ await createUser('Alice', 'alice@example.com') // auto-wrapped
|
|
|
196
196
|
|
|
197
197
|
Both `transaction()` and `savepoint()` delegate to `db.transaction()` and `db.savepoint()` from `@stacksjs/database`.
|
|
198
198
|
|
|
199
|
+
### Transaction executor boundary
|
|
200
|
+
|
|
201
|
+
Every query that must commit or roll back together must use the callback handle (`tx` or `sp`), including validation reads, pivot writes, and the final readback. Do not mix `Model.find()`, `Model.create()`, instance `update()` / `delete()`, or instance relation calls into a raw query-builder transaction. The model executor is a separate execution surface and is not rebound to the callback handle. On SQLite it may use a separate connection, so it cannot observe an uncommitted row written through `tx`.
|
|
202
|
+
|
|
203
|
+
`runInTransactionScope()` buffers supported side effects until commit, but it does not rebind model queries. For a transaction-backed custom action, use the model definition as the schema and relationship source of truth, then execute the complete persistence workflow through `tx`. Read the created or updated row through `tx` before returning so a readback failure also rolls back the mutation.
|
|
204
|
+
|
|
199
205
|
## Trait Methods (traits/)
|
|
200
206
|
|
|
201
207
|
### Taggable (when `traits.taggable: true`)
|
|
@@ -53,7 +53,7 @@ export default new Action({
|
|
|
53
53
|
].join('\n')
|
|
54
54
|
|
|
55
55
|
try {
|
|
56
|
-
await mail.
|
|
56
|
+
await mail.sendOrFail({
|
|
57
57
|
to: [toAddress],
|
|
58
58
|
from: { name: appName, address: fromAddress },
|
|
59
59
|
replyTo: email,
|
|
@@ -63,7 +63,7 @@ export default new Action({
|
|
|
63
63
|
}
|
|
64
64
|
catch (err) {
|
|
65
65
|
const errMessage = err instanceof Error ? err.message : String(err)
|
|
66
|
-
console.error('[ContactAction] mail.
|
|
66
|
+
console.error('[ContactAction] mail.sendOrFail failed:', errMessage)
|
|
67
67
|
return { success: false, message: 'We could not send your message. Try again in a moment.' }
|
|
68
68
|
}
|
|
69
69
|
|
|
@@ -2,6 +2,7 @@ import type { RequestInstance } from '@stacksjs/types'
|
|
|
2
2
|
import { Action } from '@stacksjs/actions'
|
|
3
3
|
import { AnalyticsEvent } from '@stacksjs/orm'
|
|
4
4
|
import { response } from '@stacksjs/router'
|
|
5
|
+
import { dashboardOperationalError } from '../dashboard-response'
|
|
5
6
|
import {
|
|
6
7
|
analyticsCurrency,
|
|
7
8
|
analyticsIdentifier,
|
|
@@ -50,9 +51,7 @@ export default new Action({
|
|
|
50
51
|
)
|
|
51
52
|
}
|
|
52
53
|
catch (error) {
|
|
53
|
-
return
|
|
54
|
-
message: error instanceof Error ? error.message : 'Event analytics records could not be read.',
|
|
55
|
-
}, 503)
|
|
54
|
+
return dashboardOperationalError(error, 'Event analytics records could not be read.', 'EventAnalyticsAction')
|
|
56
55
|
}
|
|
57
56
|
},
|
|
58
57
|
})
|
|
@@ -2,6 +2,7 @@ import type { RequestInstance } from '@stacksjs/types'
|
|
|
2
2
|
import { Action } from '@stacksjs/actions'
|
|
3
3
|
import { Campaign } from '@stacksjs/orm'
|
|
4
4
|
import { response } from '@stacksjs/router'
|
|
5
|
+
import { dashboardOperationalError } from '../dashboard-response'
|
|
5
6
|
import {
|
|
6
7
|
analyticsCurrency,
|
|
7
8
|
analyticsIdentifier,
|
|
@@ -55,9 +56,7 @@ export default new Action({
|
|
|
55
56
|
)
|
|
56
57
|
}
|
|
57
58
|
catch (error) {
|
|
58
|
-
return
|
|
59
|
-
message: error instanceof Error ? error.message : 'Campaign analytics records could not be read.',
|
|
60
|
-
}, 503)
|
|
59
|
+
return dashboardOperationalError(error, 'Campaign analytics records could not be read.', 'MarketingAnalyticsAction')
|
|
61
60
|
}
|
|
62
61
|
},
|
|
63
62
|
})
|
|
@@ -2,6 +2,7 @@ import type { RequestInstance } from '@stacksjs/types'
|
|
|
2
2
|
import { Action } from '@stacksjs/actions'
|
|
3
3
|
import { Category, Order, OrderItem, Payment, Product } from '@stacksjs/orm'
|
|
4
4
|
import { response } from '@stacksjs/router'
|
|
5
|
+
import { dashboardOperationalError } from '../dashboard-response'
|
|
5
6
|
import {
|
|
6
7
|
analyticsCurrency,
|
|
7
8
|
analyticsIdentifier,
|
|
@@ -93,9 +94,7 @@ export default new Action({
|
|
|
93
94
|
)
|
|
94
95
|
}
|
|
95
96
|
catch (error) {
|
|
96
|
-
return
|
|
97
|
-
message: error instanceof Error ? error.message : 'Sales analytics records could not be read.',
|
|
98
|
-
}, 503)
|
|
97
|
+
return dashboardOperationalError(error, 'Sales analytics records could not be read.', 'SalesAnalyticsAction')
|
|
99
98
|
}
|
|
100
99
|
},
|
|
101
100
|
})
|
|
@@ -2,6 +2,7 @@ import type { RequestInstance } from '@stacksjs/types'
|
|
|
2
2
|
import { Action } from '@stacksjs/actions'
|
|
3
3
|
import { Request } from '@stacksjs/orm'
|
|
4
4
|
import { response } from '@stacksjs/router'
|
|
5
|
+
import { dashboardOperationalError } from '../dashboard-response'
|
|
5
6
|
import {
|
|
6
7
|
buildWebAnalytics,
|
|
7
8
|
normalizeAnalyticsRange,
|
|
@@ -27,9 +28,14 @@ export default new Action({
|
|
|
27
28
|
message: error instanceof Error ? error.message : 'The analytics query is invalid.',
|
|
28
29
|
}, 422)
|
|
29
30
|
}
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
try {
|
|
32
|
+
const records = await Request.orderByDesc('id').limit(10_000).get()
|
|
33
|
+
const rows = records.map(requestAnalyticsRow)
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
return buildWebAnalytics(rows, range, new Date(), scope)
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
return dashboardOperationalError(error, 'Web analytics records could not be read.', 'WebAnalyticsAction')
|
|
39
|
+
}
|
|
34
40
|
},
|
|
35
41
|
})
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { RequestInstance } from '@stacksjs/types'
|
|
2
2
|
import { Action } from '@stacksjs/actions'
|
|
3
3
|
import { getUserRoles } from '@stacksjs/auth'
|
|
4
|
+
import { dashboardOperationalError } from '../dashboard-response'
|
|
4
5
|
|
|
5
6
|
interface MeResponse {
|
|
6
7
|
user: {
|
|
@@ -59,17 +60,13 @@ export default new Action({
|
|
|
59
60
|
|
|
60
61
|
const userId = Number(user.id)
|
|
61
62
|
|
|
62
|
-
let roles: string[]
|
|
63
|
+
let roles: string[]
|
|
63
64
|
try {
|
|
64
65
|
const records = await getUserRoles(userId)
|
|
65
66
|
roles = records.map(r => r.name)
|
|
66
67
|
}
|
|
67
|
-
catch (
|
|
68
|
-
|
|
69
|
-
// Empty roles → useRole will fall back to its dev default. We don't
|
|
70
|
-
// want to 500 the dashboard just because the role tables haven't
|
|
71
|
-
// been migrated yet on a fresh project.
|
|
72
|
-
console.warn('[dashboard/auth/me] getUserRoles failed:', err instanceof Error ? err.message : err)
|
|
68
|
+
catch (error) {
|
|
69
|
+
return dashboardOperationalError(error, 'Dashboard identity could not be loaded.', 'MeAction')
|
|
73
70
|
}
|
|
74
71
|
|
|
75
72
|
const res: MeResponse = {
|
|
@@ -4,6 +4,7 @@ import { Action } from '@stacksjs/actions'
|
|
|
4
4
|
import { buddyState, createAIClient } from '@stacksjs/ai'
|
|
5
5
|
import { config } from '@stacksjs/config'
|
|
6
6
|
import { response } from '@stacksjs/router'
|
|
7
|
+
import { dashboardOperationalError } from '../dashboard-response'
|
|
7
8
|
import { buddySystemPrompt, isBuddyProviderConfigured, publicBuddyHistory, resolveBuddyProvider } from './buddy-chat'
|
|
8
9
|
|
|
9
10
|
export default new Action({
|
|
@@ -49,9 +50,7 @@ export default new Action({
|
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
52
|
catch (error) {
|
|
52
|
-
return
|
|
53
|
-
message: error instanceof Error ? error.message : 'Buddy could not answer the question.',
|
|
54
|
-
}, 502)
|
|
53
|
+
return dashboardOperationalError(error, 'Buddy could not answer the question.', 'BuddyChatAction', 502)
|
|
55
54
|
}
|
|
56
55
|
},
|
|
57
56
|
})
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import { Action } from '@stacksjs/actions'
|
|
2
2
|
import { tsCloud } from '~/config/cloud'
|
|
3
|
+
import { dashboardOperationalError } from '../dashboard-response'
|
|
3
4
|
import { getDashboardCloudSnapshot } from './cloud-overview'
|
|
4
5
|
|
|
5
6
|
export default new Action({
|
|
6
7
|
name: 'CloudIndexAction',
|
|
7
8
|
description: 'Returns configured cloud infrastructure and persisted deployment state.',
|
|
8
9
|
method: 'GET',
|
|
10
|
+
apiResponse: true,
|
|
9
11
|
async handle() {
|
|
10
|
-
|
|
12
|
+
try {
|
|
13
|
+
return await getDashboardCloudSnapshot(tsCloud)
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
return dashboardOperationalError(error, 'Cloud infrastructure could not be loaded.', 'CloudIndexAction')
|
|
17
|
+
}
|
|
11
18
|
},
|
|
12
19
|
})
|
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
import { Action } from '@stacksjs/actions'
|
|
2
2
|
import { tsCloud } from '~/config/cloud'
|
|
3
|
+
import { dashboardOperationalError } from '../dashboard-response'
|
|
3
4
|
import { getDashboardCloudSnapshot } from './cloud-overview'
|
|
4
5
|
|
|
5
6
|
export default new Action({
|
|
6
7
|
name: 'ServerlessIndexAction',
|
|
7
8
|
description: 'Returns serverless services derived from environment application manifests.',
|
|
8
9
|
method: 'GET',
|
|
10
|
+
apiResponse: true,
|
|
9
11
|
async handle() {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
try {
|
|
13
|
+
const snapshot = await getDashboardCloudSnapshot(tsCloud)
|
|
14
|
+
return {
|
|
15
|
+
project: snapshot.project,
|
|
16
|
+
environments: snapshot.environments.filter(environment => environment.serverless),
|
|
17
|
+
services: snapshot.serverlessServices,
|
|
18
|
+
links: snapshot.serverlessLinks,
|
|
19
|
+
events: snapshot.events.filter(event => event.service.toLowerCase().includes('serverless')),
|
|
20
|
+
generatedAt: snapshot.generatedAt,
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
return dashboardOperationalError(error, 'Serverless infrastructure could not be loaded.', 'ServerlessIndexAction')
|
|
18
25
|
}
|
|
19
26
|
},
|
|
20
27
|
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Action } from '@stacksjs/actions'
|
|
2
2
|
import { Category } from '@stacksjs/orm'
|
|
3
|
-
import {
|
|
3
|
+
import { dashboardOperationalError } from '../dashboard-response'
|
|
4
4
|
import { normalizeCommerceCategoryRecord, summarizeCommerceCategories } from './commerce-category-records'
|
|
5
5
|
|
|
6
6
|
export default new Action({
|
|
@@ -24,9 +24,7 @@ export default new Action({
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
catch (error) {
|
|
27
|
-
return
|
|
28
|
-
message: error instanceof Error ? error.message : 'Category records could not be read.',
|
|
29
|
-
}, 503)
|
|
27
|
+
return dashboardOperationalError(error, 'Category records could not be read.', 'CommerceCategoriesAction')
|
|
30
28
|
}
|
|
31
29
|
},
|
|
32
30
|
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Action } from '@stacksjs/actions'
|
|
2
2
|
import { Coupon, Product } from '@stacksjs/orm'
|
|
3
|
-
import {
|
|
3
|
+
import { dashboardOperationalError } from '../dashboard-response'
|
|
4
4
|
import { normalizeCouponRecord, summarizeCoupons } from './coupon-records'
|
|
5
5
|
import { commerceIdentifier, commerceValue } from './commerce-record'
|
|
6
6
|
|
|
@@ -26,9 +26,7 @@ export default new Action({
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
catch (error) {
|
|
29
|
-
return
|
|
30
|
-
message: error instanceof Error ? error.message : 'Coupon records could not be read.',
|
|
31
|
-
}, 503)
|
|
29
|
+
return dashboardOperationalError(error, 'Coupon records could not be read.', 'CommerceCouponsAction')
|
|
32
30
|
}
|
|
33
31
|
},
|
|
34
32
|
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Action } from '@stacksjs/actions'
|
|
2
2
|
import { config } from '@stacksjs/config'
|
|
3
3
|
import { Customer } from '@stacksjs/orm'
|
|
4
|
-
import {
|
|
4
|
+
import { dashboardOperationalError } from '../dashboard-response'
|
|
5
5
|
import {
|
|
6
6
|
normalizeCommerceCustomerCurrency,
|
|
7
7
|
normalizeCommerceCustomerRecord,
|
|
@@ -25,9 +25,7 @@ export default new Action({
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
catch (error) {
|
|
28
|
-
return
|
|
29
|
-
message: error instanceof Error ? error.message : 'Customer records could not be read.',
|
|
30
|
-
}, 503)
|
|
28
|
+
return dashboardOperationalError(error, 'Customer records could not be read.', 'CommerceCustomersAction')
|
|
31
29
|
}
|
|
32
30
|
},
|
|
33
31
|
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { RequestInstance } from '@stacksjs/types'
|
|
2
2
|
import { Action } from '@stacksjs/actions'
|
|
3
3
|
import { Customer, Order, OrderItem, Product } from '@stacksjs/orm'
|
|
4
|
-
import {
|
|
4
|
+
import { dashboardOperationalError } from '../dashboard-response'
|
|
5
5
|
import {
|
|
6
6
|
buildCommerceDashboard,
|
|
7
7
|
commerceDashboardQueryStart,
|
|
@@ -56,9 +56,7 @@ export default new Action({
|
|
|
56
56
|
)
|
|
57
57
|
}
|
|
58
58
|
catch (error) {
|
|
59
|
-
return
|
|
60
|
-
message: error instanceof Error ? error.message : 'Commerce overview records could not be read.',
|
|
61
|
-
}, 503)
|
|
59
|
+
return dashboardOperationalError(error, 'Commerce overview records could not be read.', 'CommerceDashboardAction')
|
|
62
60
|
}
|
|
63
61
|
},
|
|
64
62
|
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Action } from '@stacksjs/actions'
|
|
2
2
|
import { config } from '@stacksjs/config'
|
|
3
3
|
import { DeliveryRoute, Driver, ShippingMethod, ShippingZone } from '@stacksjs/orm'
|
|
4
|
-
import {
|
|
4
|
+
import { dashboardOperationalError } from '../dashboard-response'
|
|
5
5
|
import { buildDeliveryOverview } from './commerce-delivery'
|
|
6
6
|
|
|
7
7
|
export default new Action({
|
|
@@ -28,9 +28,7 @@ export default new Action({
|
|
|
28
28
|
)
|
|
29
29
|
}
|
|
30
30
|
catch (error) {
|
|
31
|
-
return
|
|
32
|
-
message: error instanceof Error ? error.message : 'Delivery records could not be read.',
|
|
33
|
-
}, 503)
|
|
31
|
+
return dashboardOperationalError(error, 'Delivery records could not be read.', 'CommerceDeliveryAction')
|
|
34
32
|
}
|
|
35
33
|
},
|
|
36
34
|
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Action } from '@stacksjs/actions'
|
|
2
2
|
import { Customer, GiftCard } from '@stacksjs/orm'
|
|
3
|
-
import {
|
|
3
|
+
import { dashboardOperationalError } from '../dashboard-response'
|
|
4
4
|
import { normalizeGiftCardRecord, summarizeGiftCards } from './gift-card-records'
|
|
5
5
|
import { commerceIdentifier, commerceValue } from './commerce-record'
|
|
6
6
|
|
|
@@ -26,9 +26,7 @@ export default new Action({
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
catch (error) {
|
|
29
|
-
return
|
|
30
|
-
message: error instanceof Error ? error.message : 'Gift card records could not be read.',
|
|
31
|
-
}, 503)
|
|
29
|
+
return dashboardOperationalError(error, 'Gift card records could not be read.', 'CommerceGiftCardsAction')
|
|
32
30
|
}
|
|
33
31
|
},
|
|
34
32
|
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Action } from '@stacksjs/actions'
|
|
2
2
|
import { config } from '@stacksjs/config'
|
|
3
3
|
import { Coupon, Customer, Order, OrderItem } from '@stacksjs/orm'
|
|
4
|
-
import {
|
|
4
|
+
import { dashboardOperationalError } from '../dashboard-response'
|
|
5
5
|
import {
|
|
6
6
|
addOrderItemQuantity,
|
|
7
7
|
normalizeCommerceOrderRecord,
|
|
@@ -54,9 +54,7 @@ export default new Action({
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
catch (error) {
|
|
57
|
-
return
|
|
58
|
-
message: error instanceof Error ? error.message : 'Order records could not be read.',
|
|
59
|
-
}, 503)
|
|
57
|
+
return dashboardOperationalError(error, 'Order records could not be read.', 'CommerceOrdersAction')
|
|
60
58
|
}
|
|
61
59
|
},
|
|
62
60
|
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Action } from '@stacksjs/actions'
|
|
2
2
|
import { Customer, Order, Payment } from '@stacksjs/orm'
|
|
3
|
-
import {
|
|
3
|
+
import { dashboardOperationalError } from '../dashboard-response'
|
|
4
4
|
import { commerceIdentifier, commerceValue } from './commerce-record'
|
|
5
5
|
import { normalizePaymentRecord, summarizePayments } from './payment-records'
|
|
6
6
|
|
|
@@ -32,9 +32,7 @@ export default new Action({
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
catch (error) {
|
|
35
|
-
return
|
|
36
|
-
message: error instanceof Error ? error.message : 'Payment records could not be read.',
|
|
37
|
-
}, 503)
|
|
35
|
+
return dashboardOperationalError(error, 'Payment records could not be read.', 'CommercePaymentsAction')
|
|
38
36
|
}
|
|
39
37
|
},
|
|
40
38
|
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Action } from '@stacksjs/actions'
|
|
2
2
|
import { config } from '@stacksjs/config'
|
|
3
3
|
import { Category, Customer, Manufacturer, Product, TaxRate } from '@stacksjs/orm'
|
|
4
|
-
import {
|
|
4
|
+
import { dashboardOperationalError } from '../dashboard-response'
|
|
5
5
|
import {
|
|
6
6
|
isCommercePosCustomerActive,
|
|
7
7
|
normalizeCommercePosCustomer,
|
|
@@ -63,9 +63,7 @@ export default new Action({
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
catch (error) {
|
|
66
|
-
return
|
|
67
|
-
message: error instanceof Error ? error.message : 'Point of sale records could not be read.',
|
|
68
|
-
}, 503)
|
|
66
|
+
return dashboardOperationalError(error, 'Point of sale records could not be read.', 'CommercePosAction')
|
|
69
67
|
}
|
|
70
68
|
},
|
|
71
69
|
})
|