@open-mercato/core 0.6.6-develop.6171.1.17de2dc37a → 0.6.6-develop.6174.1.8a7040f00d

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.
@@ -6,7 +6,29 @@ import type { ActivitiesDataAdapter, ActivitySummary } from '@open-mercato/ui/ba
6
6
 
7
7
  type Translator = (key: string, fallback?: string, params?: Record<string, string | number>) => string
8
8
 
9
- export function createResourceActivitiesAdapter(translator: Translator): ActivitiesDataAdapter {
9
+ export type ResourceActivitiesGuardedMutation = <T>(
10
+ runner: () => Promise<T>,
11
+ payload?: Record<string, unknown>,
12
+ ) => Promise<T>
13
+
14
+ export type CreateResourceActivitiesAdapterOptions = {
15
+ runMutation?: ResourceActivitiesGuardedMutation
16
+ }
17
+
18
+ export function createResourceActivitiesAdapter(
19
+ translator: Translator,
20
+ options: CreateResourceActivitiesAdapterOptions = {},
21
+ ): ActivitiesDataAdapter {
22
+ const runWrite = async <T,>(
23
+ runner: () => Promise<T>,
24
+ payload: Record<string, unknown>,
25
+ ): Promise<T> => {
26
+ if (options.runMutation) {
27
+ return options.runMutation(runner, payload)
28
+ }
29
+ return runner()
30
+ }
31
+
10
32
  return {
11
33
  list: async ({ entityId }) => {
12
34
  const params = new URLSearchParams({
@@ -23,19 +45,23 @@ export function createResourceActivitiesAdapter(translator: Translator): Activit
23
45
  return Array.isArray(payload?.items) ? (payload.items as ActivitySummary[]) : []
24
46
  },
25
47
  create: async ({ entityId, activityType, subject, body, occurredAt, customFields }) => {
26
- await createCrud('resources/activities', {
48
+ const payload = {
27
49
  entityId,
28
50
  activityType,
29
51
  subject: subject ?? undefined,
30
52
  body: body ?? undefined,
31
53
  occurredAt: occurredAt ?? undefined,
32
54
  ...(customFields ? { customFields } : {}),
33
- }, {
34
- errorMessage: translator('resources.resources.detail.activities.error', 'Failed to save activity'),
35
- })
55
+ }
56
+ await runWrite(
57
+ () => createCrud('resources/activities', payload, {
58
+ errorMessage: translator('resources.resources.detail.activities.error', 'Failed to save activity'),
59
+ }),
60
+ { operation: 'createActivity', entityId, activityType },
61
+ )
36
62
  },
37
63
  update: async ({ id, patch }) => {
38
- await updateCrud('resources/activities', {
64
+ const payload = {
39
65
  id,
40
66
  entityId: patch.entityId,
41
67
  activityType: patch.activityType,
@@ -43,15 +69,22 @@ export function createResourceActivitiesAdapter(translator: Translator): Activit
43
69
  body: patch.body ?? undefined,
44
70
  occurredAt: patch.occurredAt ?? undefined,
45
71
  ...(patch.customFields ? { customFields: patch.customFields } : {}),
46
- }, {
47
- errorMessage: translator('resources.resources.detail.activities.error', 'Failed to save activity'),
48
- })
72
+ }
73
+ await runWrite(
74
+ () => updateCrud('resources/activities', payload, {
75
+ errorMessage: translator('resources.resources.detail.activities.error', 'Failed to save activity'),
76
+ }),
77
+ { operation: 'updateActivity', id },
78
+ )
49
79
  },
50
80
  delete: async ({ id }) => {
51
- await deleteCrud('resources/activities', {
52
- id,
53
- errorMessage: translator('resources.resources.detail.activities.deleteError', 'Failed to delete activity.'),
54
- })
81
+ await runWrite(
82
+ () => deleteCrud('resources/activities', {
83
+ id,
84
+ errorMessage: translator('resources.resources.detail.activities.deleteError', 'Failed to delete activity.'),
85
+ }),
86
+ { operation: 'deleteActivity', id },
87
+ )
55
88
  },
56
89
  }
57
90
  }
@@ -5,7 +5,29 @@ import { mapCommentSummary, type NotesDataAdapter } from '@open-mercato/ui/backe
5
5
 
6
6
  type Translator = (key: string, fallback?: string, params?: Record<string, string | number>) => string
7
7
 
8
- export function createResourceNotesAdapter(translator: Translator): NotesDataAdapter {
8
+ export type ResourceNotesGuardedMutation = <T>(
9
+ runner: () => Promise<T>,
10
+ payload?: Record<string, unknown>,
11
+ ) => Promise<T>
12
+
13
+ export type CreateResourceNotesAdapterOptions = {
14
+ runMutation?: ResourceNotesGuardedMutation
15
+ }
16
+
17
+ export function createResourceNotesAdapter(
18
+ translator: Translator,
19
+ options: CreateResourceNotesAdapterOptions = {},
20
+ ): NotesDataAdapter {
21
+ const runWrite = async <T,>(
22
+ runner: () => Promise<T>,
23
+ payload: Record<string, unknown>,
24
+ ): Promise<T> => {
25
+ if (options.runMutation) {
26
+ return options.runMutation(runner, payload)
27
+ }
28
+ return runner()
29
+ }
30
+
9
31
  return {
10
32
  list: async ({ entityId }) => {
11
33
  const params = new URLSearchParams()
@@ -19,19 +41,23 @@ export function createResourceNotesAdapter(translator: Translator): NotesDataAda
19
41
  return items.map(mapCommentSummary)
20
42
  },
21
43
  create: async ({ entityId, body, appearanceIcon, appearanceColor }) => {
22
- const response = await apiCallOrThrow<Record<string, unknown>>(
23
- '/api/resources/comments',
24
- {
25
- method: 'POST',
26
- headers: { 'content-type': 'application/json' },
27
- body: JSON.stringify({
28
- entityId,
29
- body,
30
- appearanceIcon: appearanceIcon ?? undefined,
31
- appearanceColor: appearanceColor ?? undefined,
32
- }),
33
- },
34
- { errorMessage: translator('resources.resources.detail.notes.error', 'Failed to save note.') },
44
+ const requestBody = {
45
+ entityId,
46
+ body,
47
+ appearanceIcon: appearanceIcon ?? undefined,
48
+ appearanceColor: appearanceColor ?? undefined,
49
+ }
50
+ const response = await runWrite(
51
+ () => apiCallOrThrow<Record<string, unknown>>(
52
+ '/api/resources/comments',
53
+ {
54
+ method: 'POST',
55
+ headers: { 'content-type': 'application/json' },
56
+ body: JSON.stringify(requestBody),
57
+ },
58
+ { errorMessage: translator('resources.resources.detail.notes.error', 'Failed to save note.') },
59
+ ),
60
+ { operation: 'createNote', entityId },
35
61
  )
36
62
  return response.result ?? {}
37
63
  },
@@ -40,24 +66,30 @@ export function createResourceNotesAdapter(translator: Translator): NotesDataAda
40
66
  if (patch.body !== undefined) payload.body = patch.body
41
67
  if (patch.appearanceIcon !== undefined) payload.appearanceIcon = patch.appearanceIcon
42
68
  if (patch.appearanceColor !== undefined) payload.appearanceColor = patch.appearanceColor
43
- await apiCallOrThrow(
44
- '/api/resources/comments',
45
- {
46
- method: 'PUT',
47
- headers: { 'content-type': 'application/json' },
48
- body: JSON.stringify(payload),
49
- },
50
- { errorMessage: translator('resources.resources.detail.notes.updateError', 'Failed to update note.') },
69
+ await runWrite(
70
+ () => apiCallOrThrow(
71
+ '/api/resources/comments',
72
+ {
73
+ method: 'PUT',
74
+ headers: { 'content-type': 'application/json' },
75
+ body: JSON.stringify(payload),
76
+ },
77
+ { errorMessage: translator('resources.resources.detail.notes.updateError', 'Failed to update note.') },
78
+ ),
79
+ { operation: 'updateNote', id },
51
80
  )
52
81
  },
53
82
  delete: async ({ id }) => {
54
- await apiCallOrThrow(
55
- `/api/resources/comments?id=${encodeURIComponent(id)}`,
56
- {
57
- method: 'DELETE',
58
- headers: { 'content-type': 'application/json' },
59
- },
60
- { errorMessage: translator('resources.resources.detail.notes.deleteError', 'Failed to delete note') },
83
+ await runWrite(
84
+ () => apiCallOrThrow(
85
+ `/api/resources/comments?id=${encodeURIComponent(id)}`,
86
+ {
87
+ method: 'DELETE',
88
+ headers: { 'content-type': 'application/json' },
89
+ },
90
+ { errorMessage: translator('resources.resources.detail.notes.deleteError', 'Failed to delete note') },
91
+ ),
92
+ { operation: 'deleteNote', id },
61
93
  )
62
94
  },
63
95
  }