@open-mercato/core 0.6.6-develop.6338.1.c32cd17821 → 0.6.6-develop.6343.1.8120f84f30

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 (25) hide show
  1. package/dist/modules/catalog/components/products/ProductComplianceSection.js +1 -1
  2. package/dist/modules/catalog/components/products/ProductComplianceSection.js.map +2 -2
  3. package/dist/modules/catalog/data/validators.js +1 -1
  4. package/dist/modules/catalog/data/validators.js.map +2 -2
  5. package/dist/modules/communication_channels/backend/communication_channels/channels/[id]/page.js +1 -1
  6. package/dist/modules/communication_channels/backend/communication_channels/channels/[id]/page.js.map +2 -2
  7. package/dist/modules/communication_channels/lib/route-mutation-guard.js +19 -29
  8. package/dist/modules/communication_channels/lib/route-mutation-guard.js.map +2 -2
  9. package/dist/modules/customers/backend/customers/deals/pipeline/page.js +4 -4
  10. package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
  11. package/dist/modules/customers/components/calendar/CalendarScreen.js +1 -1
  12. package/dist/modules/customers/components/calendar/CalendarScreen.js.map +2 -2
  13. package/dist/modules/notifications/lib/routeHelpers.js +18 -25
  14. package/dist/modules/notifications/lib/routeHelpers.js.map +2 -2
  15. package/dist/modules/payment_gateways/backend/payment-gateways/page.js +1 -1
  16. package/dist/modules/payment_gateways/backend/payment-gateways/page.js.map +2 -2
  17. package/package.json +7 -7
  18. package/src/modules/catalog/components/products/ProductComplianceSection.tsx +1 -1
  19. package/src/modules/catalog/data/validators.ts +1 -1
  20. package/src/modules/communication_channels/backend/communication_channels/channels/[id]/page.tsx +1 -1
  21. package/src/modules/communication_channels/lib/route-mutation-guard.ts +32 -32
  22. package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +4 -4
  23. package/src/modules/customers/components/calendar/CalendarScreen.tsx +1 -1
  24. package/src/modules/notifications/lib/routeHelpers.ts +18 -26
  25. package/src/modules/payment_gateways/backend/payment-gateways/page.tsx +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/core",
3
- "version": "0.6.6-develop.6338.1.c32cd17821",
3
+ "version": "0.6.6-develop.6343.1.8120f84f30",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -246,16 +246,16 @@
246
246
  "zod": "^4.4.3"
247
247
  },
248
248
  "peerDependencies": {
249
- "@open-mercato/ai-assistant": "0.6.6-develop.6338.1.c32cd17821",
250
- "@open-mercato/shared": "0.6.6-develop.6338.1.c32cd17821",
251
- "@open-mercato/ui": "0.6.6-develop.6338.1.c32cd17821",
249
+ "@open-mercato/ai-assistant": "0.6.6-develop.6343.1.8120f84f30",
250
+ "@open-mercato/shared": "0.6.6-develop.6343.1.8120f84f30",
251
+ "@open-mercato/ui": "0.6.6-develop.6343.1.8120f84f30",
252
252
  "react": "^19.0.0",
253
253
  "react-dom": "^19.0.0"
254
254
  },
255
255
  "devDependencies": {
256
- "@open-mercato/ai-assistant": "0.6.6-develop.6338.1.c32cd17821",
257
- "@open-mercato/shared": "0.6.6-develop.6338.1.c32cd17821",
258
- "@open-mercato/ui": "0.6.6-develop.6338.1.c32cd17821",
256
+ "@open-mercato/ai-assistant": "0.6.6-develop.6343.1.8120f84f30",
257
+ "@open-mercato/shared": "0.6.6-develop.6343.1.8120f84f30",
258
+ "@open-mercato/ui": "0.6.6-develop.6343.1.8120f84f30",
259
259
  "@testing-library/dom": "^10.4.1",
260
260
  "@testing-library/jest-dom": "^6.9.1",
261
261
  "@testing-library/react": "^16.3.1",
@@ -64,7 +64,7 @@ export function ProductComplianceSection({
64
64
  (code: string, checked: boolean) => {
65
65
  const current = Array.isArray(values.gtuCodes) ? values.gtuCodes : [];
66
66
  const next = checked
67
- ? Array.from(new Set([...current, code])).sort()
67
+ ? Array.from(new Set([...current, code])).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))
68
68
  : current.filter((entry) => entry !== code);
69
69
  setValue("gtuCodes", next);
70
70
  },
@@ -236,7 +236,7 @@ const productBaseSchema = scoped.extend({
236
236
  gtuCodes: z
237
237
  .array(z.enum(CATALOG_GTU_CODES))
238
238
  .max(13)
239
- .transform((codes) => Array.from(new Set(codes)).sort())
239
+ .transform((codes) => Array.from(new Set(codes)).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)))
240
240
  .nullable()
241
241
  .optional(),
242
242
  ageMin: z.coerce.number().int().min(0).max(120).nullable().optional(),
@@ -159,7 +159,7 @@ export default function ChannelDetailPage() {
159
159
  </p>
160
160
  ) : (
161
161
  <dl className="grid grid-cols-2 gap-x-6 gap-y-1 text-sm md:grid-cols-3">
162
- {capabilityKeys.sort().map((key) => (
162
+ {capabilityKeys.sort((a, b) => a.localeCompare(b)).map((key) => (
163
163
  <React.Fragment key={key}>
164
164
  <dt className="text-muted-foreground">{key}</dt>
165
165
  <dd className="md:col-span-2">{renderCapabilityValue(capabilities[key])}</dd>
@@ -1,9 +1,5 @@
1
1
  import type { AwilixContainer } from 'awilix'
2
- import {
3
- runCrudMutationGuardAfterSuccess,
4
- validateCrudMutationGuard,
5
- type CrudMutationGuardValidationResult,
6
- } from '@open-mercato/shared/lib/crud/mutation-guard'
2
+ import { runRouteMutationGuards } from '@open-mercato/shared/lib/crud/route-mutation-guard'
7
3
 
8
4
  type RouteAuth = {
9
5
  sub?: string | null
@@ -19,10 +15,21 @@ type RouteMutationGuardInput = {
19
15
  }
20
16
 
21
17
  export type RouteMutationGuardContext = {
22
- result: CrudMutationGuardValidationResult | null
18
+ /**
19
+ * Marker kept for source compatibility with callers; the registry result is
20
+ * fully handled inside the wrapper, so callers only need `afterSuccess`.
21
+ */
22
+ result: { ok: true } | null
23
23
  afterSuccess: () => Promise<void>
24
24
  }
25
25
 
26
+ /**
27
+ * Run a communication-channels custom write route through the full mutation
28
+ * guard registry (`runRouteMutationGuards`) instead of only the legacy DI
29
+ * service. Returns `{ response }` when a guard blocks the mutation, or
30
+ * `{ result, afterSuccess }` to run after a successful write — preserving the
31
+ * shape the dependent routes already consume.
32
+ */
26
33
  export async function validateRouteMutationGuard(params: {
27
34
  container: AwilixContainer
28
35
  req: Request
@@ -34,35 +41,28 @@ export async function validateRouteMutationGuard(params: {
34
41
  return { result: null, afterSuccess: async () => undefined }
35
42
  }
36
43
 
37
- const base = {
38
- tenantId: auth.tenantId,
39
- organizationId: auth.orgId ?? null,
40
- userId: auth.sub,
41
- resourceKind: input.resourceKind,
42
- resourceId: input.resourceId,
43
- operation: input.operation ?? 'custom',
44
- requestMethod: req.method,
45
- requestHeaders: req.headers,
46
- } as const
47
-
48
- const result = await validateCrudMutationGuard(container, {
49
- ...base,
50
- mutationPayload: input.mutationPayload ?? null,
44
+ const guarded = await runRouteMutationGuards({
45
+ container,
46
+ req,
47
+ auth: {
48
+ userId: auth.sub,
49
+ tenantId: auth.tenantId,
50
+ organizationId: auth.orgId ?? null,
51
+ },
52
+ input: {
53
+ resourceKind: input.resourceKind,
54
+ resourceId: input.resourceId,
55
+ operation: input.operation ?? 'custom',
56
+ mutationPayload: input.mutationPayload ?? null,
57
+ },
51
58
  })
52
- if (result && !result.ok) {
53
- return {
54
- response: Response.json(result.body, { status: result.status }),
55
- }
59
+
60
+ if (!guarded.ok) {
61
+ return { response: guarded.response }
56
62
  }
57
63
 
58
64
  return {
59
- result,
60
- afterSuccess: async () => {
61
- if (!result?.ok || !result.shouldRunAfterSuccess) return
62
- await runCrudMutationGuardAfterSuccess(container, {
63
- ...base,
64
- metadata: result.metadata ?? null,
65
- })
66
- },
65
+ result: { ok: true },
66
+ afterSuccess: guarded.runAfterSuccess,
67
67
  }
68
68
  }
@@ -606,10 +606,10 @@ export default function DealsKanbanPage(): React.ReactElement {
606
606
  () => ({
607
607
  pipelineId: selectedPipelineId,
608
608
  search: search.trim(),
609
- status: statusFilters.slice().sort().join(','),
610
- owners: ownerFilters.slice().sort().join(','),
611
- people: peopleFilters.slice().sort().join(','),
612
- companies: companyFilters.slice().sort().join(','),
609
+ status: statusFilters.slice().sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)).join(','),
610
+ owners: ownerFilters.slice().sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)).join(','),
611
+ people: peopleFilters.slice().sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)).join(','),
612
+ companies: companyFilters.slice().sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)).join(','),
613
613
  closeFrom: closeDateFilter.from ?? '',
614
614
  closeTo: closeDateFilter.to ?? '',
615
615
  currency: currencyFilter ?? '',
@@ -223,7 +223,7 @@ export function CalendarScreen() {
223
223
  const values = new Set<string>(Object.keys(typeLabels))
224
224
  for (const item of items) values.add(item.interactionType)
225
225
  return [...values]
226
- .sort()
226
+ .sort((a, b) => a.localeCompare(b))
227
227
  .map((value) => ({ value, label: typeLabels[value] ?? value }))
228
228
  }, [items, typeLabels])
229
229
 
@@ -2,10 +2,7 @@ import { z } from 'zod'
2
2
  import type { AwilixContainer } from 'awilix'
3
3
  import { resolveRequestContext } from '@open-mercato/shared/lib/api/context'
4
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'
5
+ import { runRouteMutationGuards } from '@open-mercato/shared/lib/crud/route-mutation-guard'
9
6
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
10
7
  import { resolveNotificationService, type NotificationService } from './notificationService'
11
8
 
@@ -106,33 +103,28 @@ export async function runGuardedNotificationWrite<T>(
106
103
  options: NotificationMutationGuardOptions,
107
104
  write: () => Promise<T>,
108
105
  ): 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,
106
+ const guarded = await runRouteMutationGuards({
107
+ container,
108
+ req,
109
+ auth: {
110
+ userId: scope.userId ?? '',
111
+ tenantId: scope.tenantId,
112
+ organizationId: scope.organizationId,
113
+ },
114
+ input: {
115
+ resourceKind: options.resourceKind,
116
+ resourceId: options.resourceId ?? null,
117
+ operation: options.operation,
118
+ mutationPayload: options.payload ?? null,
119
+ },
123
120
  })
124
- if (guardResult && !guardResult.ok) {
125
- return { ok: false, response: Response.json(guardResult.body, { status: guardResult.status }) }
121
+ if (!guarded.ok) {
122
+ return { ok: false, response: guarded.response }
126
123
  }
127
124
 
128
125
  const result = await write()
129
126
 
130
- if (guardResult?.ok && guardResult.shouldRunAfterSuccess) {
131
- await runCrudMutationGuardAfterSuccess(container, {
132
- ...guardScope,
133
- metadata: guardResult.metadata ?? null,
134
- })
135
- }
127
+ await guarded.runAfterSuccess()
136
128
 
137
129
  return { ok: true, result }
138
130
  }
@@ -354,7 +354,7 @@ export default function PaymentTransactionsPage() {
354
354
  }, [loadDetail, loadRows, runMutation, selectedId, t])
355
355
 
356
356
  const providerOptions = React.useMemo(() => {
357
- const values = Array.from(new Set(rows.map((row) => row.providerKey).filter(Boolean))).sort()
357
+ const values = Array.from(new Set(rows.map((row) => row.providerKey).filter(Boolean))).sort((a, b) => a.localeCompare(b))
358
358
  return values.map((value) => ({
359
359
  label: formatTypeLabel(value),
360
360
  value,