@open-mercato/core 0.6.6-develop.6184.1.b7e55f8d61 → 0.6.6-develop.6201.1.8ceb502c4b
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/.turbo/turbo-build.log +1 -1
- package/dist/modules/auth/frontend/login.js +5 -5
- package/dist/modules/auth/frontend/login.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.js +3 -2
- package/dist/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.js.map +2 -2
- package/dist/modules/catalog/widgets/injection/product-seo/widget.client.js +26 -14
- package/dist/modules/catalog/widgets/injection/product-seo/widget.client.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/route.js +169 -149
- package/dist/modules/customers/api/deals/[id]/route.js.map +3 -3
- package/dist/modules/customers/components/detail/InlineEditors.js +9 -4
- package/dist/modules/customers/components/detail/InlineEditors.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/[id]/page.js +13 -9
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +81 -37
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/detail-page-refresh.js +17 -0
- package/dist/modules/integrations/backend/integrations/detail-page-refresh.js.map +7 -0
- package/dist/modules/integrations/backend/integrations/page.js +45 -24
- package/dist/modules/integrations/backend/integrations/page.js.map +2 -2
- package/dist/modules/notifications/api/[id]/action/route.js +18 -3
- package/dist/modules/notifications/api/[id]/action/route.js.map +2 -2
- package/dist/modules/notifications/api/[id]/restore/route.js +19 -3
- package/dist/modules/notifications/api/[id]/restore/route.js.map +2 -2
- package/dist/modules/notifications/api/mark-all-read/route.js +18 -4
- package/dist/modules/notifications/api/mark-all-read/route.js.map +2 -2
- package/dist/modules/notifications/api/route.js +17 -4
- package/dist/modules/notifications/api/route.js.map +2 -2
- package/dist/modules/notifications/api/settings/route.js +26 -5
- package/dist/modules/notifications/api/settings/route.js.map +2 -2
- package/dist/modules/notifications/lib/routeHelpers.js +64 -5
- package/dist/modules/notifications/lib/routeHelpers.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentForm.js +299 -297
- package/dist/modules/sales/components/documents/SalesDocumentForm.js.map +2 -2
- package/dist/modules/workflows/components/EdgeEditDialog.js +120 -141
- package/dist/modules/workflows/components/EdgeEditDialog.js.map +2 -2
- package/dist/modules/workflows/components/NodeEditDialog.js +114 -118
- package/dist/modules/workflows/components/NodeEditDialog.js.map +2 -2
- package/dist/modules/workflows/frontend/checkout-demo/page.js +155 -260
- package/dist/modules/workflows/frontend/checkout-demo/page.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/auth/frontend/login.tsx +5 -5
- package/src/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.tsx +4 -3
- package/src/modules/catalog/widgets/injection/product-seo/widget.client.tsx +27 -17
- package/src/modules/customers/api/deals/[id]/route.ts +208 -174
- package/src/modules/customers/components/detail/InlineEditors.tsx +6 -10
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +13 -9
- package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +78 -35
- package/src/modules/integrations/backend/integrations/detail-page-refresh.ts +36 -0
- package/src/modules/integrations/backend/integrations/page.tsx +42 -21
- package/src/modules/notifications/api/[id]/action/route.ts +17 -2
- package/src/modules/notifications/api/[id]/restore/route.ts +19 -3
- package/src/modules/notifications/api/mark-all-read/route.ts +18 -4
- package/src/modules/notifications/api/route.ts +16 -3
- package/src/modules/notifications/api/settings/route.ts +26 -5
- package/src/modules/notifications/lib/routeHelpers.ts +101 -4
- package/src/modules/sales/components/documents/SalesDocumentForm.tsx +351 -327
- package/src/modules/workflows/components/EdgeEditDialog.tsx +132 -157
- package/src/modules/workflows/components/NodeEditDialog.tsx +116 -121
- package/src/modules/workflows/frontend/checkout-demo/page.tsx +172 -239
- package/src/modules/workflows/i18n/de.json +2 -0
- package/src/modules/workflows/i18n/en.json +2 -0
- package/src/modules/workflows/i18n/es.json +2 -0
- package/src/modules/workflows/i18n/pl.json +2 -0
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
import { z } from 'zod'
|
|
2
|
+
import type { AwilixContainer } from 'awilix'
|
|
2
3
|
import { resolveRequestContext } from '@open-mercato/shared/lib/api/context'
|
|
3
4
|
import { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
5
|
+
import {
|
|
6
|
+
runCrudMutationGuardAfterSuccess,
|
|
7
|
+
validateCrudMutationGuard,
|
|
8
|
+
} from '@open-mercato/shared/lib/crud/mutation-guard'
|
|
4
9
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
5
10
|
import { resolveNotificationService, type NotificationService } from './notificationService'
|
|
6
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Mutation-guard resource kind for notification rows.
|
|
14
|
+
*/
|
|
15
|
+
export const NOTIFICATION_RESOURCE_KIND = 'notifications.notification'
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Mutation-guard resource kind for notification delivery settings.
|
|
19
|
+
*/
|
|
20
|
+
export const NOTIFICATION_SETTINGS_RESOURCE_KIND = 'notifications.settings'
|
|
21
|
+
|
|
7
22
|
/**
|
|
8
23
|
* Notification scope context for service calls
|
|
9
24
|
*/
|
|
@@ -63,6 +78,65 @@ export async function resolveNotificationContext(req: Request): Promise<Notifica
|
|
|
63
78
|
}
|
|
64
79
|
}
|
|
65
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Mutation-guard options for a notification write.
|
|
83
|
+
*/
|
|
84
|
+
export interface NotificationMutationGuardOptions {
|
|
85
|
+
resourceKind: string
|
|
86
|
+
resourceId?: string | null
|
|
87
|
+
operation: 'create' | 'update' | 'delete' | 'custom'
|
|
88
|
+
payload?: Record<string, unknown> | null
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export type GuardedNotificationWriteResult<T> =
|
|
92
|
+
| { ok: true; result: T }
|
|
93
|
+
| { ok: false; response: Response }
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Run a notification write through the mutation guard lifecycle.
|
|
97
|
+
* Validates before the mutation, performs the write, then runs after-success
|
|
98
|
+
* hooks only when the write succeeded and the guard requested them. Returns the
|
|
99
|
+
* guard's own block response when validation fails so authorization behavior and
|
|
100
|
+
* conflict shapes are preserved.
|
|
101
|
+
*/
|
|
102
|
+
export async function runGuardedNotificationWrite<T>(
|
|
103
|
+
container: AwilixContainer,
|
|
104
|
+
scope: NotificationScope,
|
|
105
|
+
req: Request,
|
|
106
|
+
options: NotificationMutationGuardOptions,
|
|
107
|
+
write: () => Promise<T>,
|
|
108
|
+
): Promise<GuardedNotificationWriteResult<T>> {
|
|
109
|
+
const guardScope = {
|
|
110
|
+
tenantId: scope.tenantId,
|
|
111
|
+
organizationId: scope.organizationId,
|
|
112
|
+
userId: scope.userId ?? '',
|
|
113
|
+
resourceKind: options.resourceKind,
|
|
114
|
+
resourceId: options.resourceId ?? '',
|
|
115
|
+
operation: options.operation,
|
|
116
|
+
requestMethod: req.method,
|
|
117
|
+
requestHeaders: req.headers,
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const guardResult = await validateCrudMutationGuard(container, {
|
|
121
|
+
...guardScope,
|
|
122
|
+
mutationPayload: options.payload ?? null,
|
|
123
|
+
})
|
|
124
|
+
if (guardResult && !guardResult.ok) {
|
|
125
|
+
return { ok: false, response: Response.json(guardResult.body, { status: guardResult.status }) }
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const result = await write()
|
|
129
|
+
|
|
130
|
+
if (guardResult?.ok && guardResult.shouldRunAfterSuccess) {
|
|
131
|
+
await runCrudMutationGuardAfterSuccess(container, {
|
|
132
|
+
...guardScope,
|
|
133
|
+
metadata: guardResult.metadata ?? null,
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return { ok: true, result }
|
|
138
|
+
}
|
|
139
|
+
|
|
66
140
|
/**
|
|
67
141
|
* Create a POST handler for bulk notification creation routes.
|
|
68
142
|
* Used by batch, role, and feature notification endpoints.
|
|
@@ -72,7 +146,7 @@ export function createBulkNotificationRoute<TSchema extends z.ZodTypeAny>(
|
|
|
72
146
|
serviceMethod: 'createBatch' | 'createForRole' | 'createForFeature'
|
|
73
147
|
) {
|
|
74
148
|
return async function POST(req: Request) {
|
|
75
|
-
const { service, scope } = await resolveNotificationContext(req)
|
|
149
|
+
const { service, scope, ctx } = await resolveNotificationContext(req)
|
|
76
150
|
|
|
77
151
|
const body = await req.json().catch(() => ({}))
|
|
78
152
|
const parsed = schema.safeParse(body)
|
|
@@ -81,7 +155,19 @@ export function createBulkNotificationRoute<TSchema extends z.ZodTypeAny>(
|
|
|
81
155
|
}
|
|
82
156
|
|
|
83
157
|
try {
|
|
84
|
-
const
|
|
158
|
+
const guarded = await runGuardedNotificationWrite(
|
|
159
|
+
ctx.container,
|
|
160
|
+
scope,
|
|
161
|
+
req,
|
|
162
|
+
{
|
|
163
|
+
resourceKind: NOTIFICATION_RESOURCE_KIND,
|
|
164
|
+
operation: 'create',
|
|
165
|
+
payload: parsed.data as Record<string, unknown>,
|
|
166
|
+
},
|
|
167
|
+
() => service[serviceMethod](parsed.data as never, scope),
|
|
168
|
+
)
|
|
169
|
+
if (!guarded.ok) return guarded.response
|
|
170
|
+
const notifications = guarded.result
|
|
85
171
|
|
|
86
172
|
return Response.json({
|
|
87
173
|
ok: true,
|
|
@@ -144,10 +230,21 @@ export function createSingleNotificationActionRoute(
|
|
|
144
230
|
) {
|
|
145
231
|
return async function PUT(req: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
146
232
|
const { id } = await params
|
|
147
|
-
const { service, scope } = await resolveNotificationContext(req)
|
|
233
|
+
const { service, scope, ctx } = await resolveNotificationContext(req)
|
|
148
234
|
|
|
149
235
|
try {
|
|
150
|
-
await
|
|
236
|
+
const guarded = await runGuardedNotificationWrite(
|
|
237
|
+
ctx.container,
|
|
238
|
+
scope,
|
|
239
|
+
req,
|
|
240
|
+
{
|
|
241
|
+
resourceKind: NOTIFICATION_RESOURCE_KIND,
|
|
242
|
+
resourceId: id,
|
|
243
|
+
operation: 'update',
|
|
244
|
+
},
|
|
245
|
+
() => service[serviceMethod](id, scope),
|
|
246
|
+
)
|
|
247
|
+
if (!guarded.ok) return guarded.response
|
|
151
248
|
} catch (error) {
|
|
152
249
|
const errorResponse = notificationCrudErrorResponse(error)
|
|
153
250
|
if (errorResponse) return errorResponse
|