@open-mercato/core 0.6.7-develop.6795.1.8a3f27921c → 0.6.7-develop.6814.1.0627c7e9f1

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 (213) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/generated/entities/customer_deal_person_link/index.js +2 -0
  3. package/dist/generated/entities/customer_deal_person_link/index.js.map +2 -2
  4. package/dist/generated/entities/customer_user_invitation/index.js +2 -0
  5. package/dist/generated/entities/customer_user_invitation/index.js.map +2 -2
  6. package/dist/generated/entity-fields-registry.js +2 -0
  7. package/dist/generated/entity-fields-registry.js.map +2 -2
  8. package/dist/modules/business_rules/api/openmercato-call-options/route.js +85 -0
  9. package/dist/modules/business_rules/api/openmercato-call-options/route.js.map +7 -0
  10. package/dist/modules/business_rules/api/rules/route.js +71 -4
  11. package/dist/modules/business_rules/api/rules/route.js.map +2 -2
  12. package/dist/modules/business_rules/components/ActionBuilder.js +47 -4
  13. package/dist/modules/business_rules/components/ActionBuilder.js.map +3 -3
  14. package/dist/modules/business_rules/components/ActionRow.js +106 -16
  15. package/dist/modules/business_rules/components/ActionRow.js.map +2 -2
  16. package/dist/modules/business_rules/components/utils/actionValidation.js +6 -0
  17. package/dist/modules/business_rules/components/utils/actionValidation.js.map +2 -2
  18. package/dist/modules/business_rules/lib/action-executor.js +148 -0
  19. package/dist/modules/business_rules/lib/action-executor.js.map +2 -2
  20. package/dist/modules/business_rules/lib/openmercato-call-options-types.js +5 -0
  21. package/dist/modules/business_rules/lib/openmercato-call-options-types.js.map +7 -0
  22. package/dist/modules/business_rules/lib/openmercato-call-options.js +231 -0
  23. package/dist/modules/business_rules/lib/openmercato-call-options.js.map +7 -0
  24. package/dist/modules/business_rules/lib/rule-engine.js +5 -1
  25. package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
  26. package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js +11 -1
  27. package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js.map +2 -2
  28. package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js +11 -6
  29. package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js.map +2 -2
  30. package/dist/modules/configs/lib/upgrade-actions.js +12 -0
  31. package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
  32. package/dist/modules/customer_accounts/api/admin/users/[id].js +10 -1
  33. package/dist/modules/customer_accounts/api/admin/users/[id].js.map +2 -2
  34. package/dist/modules/customer_accounts/api/admin/users-invite.js +61 -4
  35. package/dist/modules/customer_accounts/api/admin/users-invite.js.map +2 -2
  36. package/dist/modules/customer_accounts/api/portal/users-invite.js +20 -2
  37. package/dist/modules/customer_accounts/api/portal/users-invite.js.map +2 -2
  38. package/dist/modules/customer_accounts/data/entities.js +3 -0
  39. package/dist/modules/customer_accounts/data/entities.js.map +2 -2
  40. package/dist/modules/customer_accounts/data/validators.js +1 -0
  41. package/dist/modules/customer_accounts/data/validators.js.map +2 -2
  42. package/dist/modules/customer_accounts/emails/CustomerInvitationEmail.js +26 -0
  43. package/dist/modules/customer_accounts/emails/CustomerInvitationEmail.js.map +7 -0
  44. package/dist/modules/customer_accounts/lib/customerEntityOwnership.js +29 -3
  45. package/dist/modules/customer_accounts/lib/customerEntityOwnership.js.map +2 -2
  46. package/dist/modules/customer_accounts/lib/customerUrl.js +19 -10
  47. package/dist/modules/customer_accounts/lib/customerUrl.js.map +2 -2
  48. package/dist/modules/customer_accounts/lib/invitationEmail.js +35 -0
  49. package/dist/modules/customer_accounts/lib/invitationEmail.js.map +7 -0
  50. package/dist/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.js +13 -0
  51. package/dist/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.js.map +7 -0
  52. package/dist/modules/customer_accounts/services/customerInvitationService.js +32 -2
  53. package/dist/modules/customer_accounts/services/customerInvitationService.js.map +2 -2
  54. package/dist/modules/customer_accounts/subscribers/autoLinkCrm.js +47 -7
  55. package/dist/modules/customer_accounts/subscribers/autoLinkCrm.js.map +2 -2
  56. package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js +2 -2
  57. package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js.map +2 -2
  58. package/dist/modules/customer_accounts/widgets/injection-table.js +1 -1
  59. package/dist/modules/customer_accounts/widgets/injection-table.js.map +2 -2
  60. package/dist/modules/customers/api/deals/[id]/people/route.js +4 -2
  61. package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
  62. package/dist/modules/customers/api/deals/[id]/route.js +7 -3
  63. package/dist/modules/customers/api/deals/[id]/route.js.map +2 -2
  64. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +11 -1
  65. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  66. package/dist/modules/customers/backend/customers/deals/[id]/page.js +14 -8
  67. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  68. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +21 -6
  69. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  70. package/dist/modules/customers/commands/deals.js +48 -10
  71. package/dist/modules/customers/commands/deals.js.map +2 -2
  72. package/dist/modules/customers/commands/people.js +2 -0
  73. package/dist/modules/customers/commands/people.js.map +2 -2
  74. package/dist/modules/customers/components/detail/CompanyDetailTabs.js +26 -6
  75. package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +2 -2
  76. package/dist/modules/customers/components/detail/DealDetailTabs.js +30 -8
  77. package/dist/modules/customers/components/detail/DealDetailTabs.js.map +2 -2
  78. package/dist/modules/customers/components/detail/PersonDetailTabs.js +30 -8
  79. package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
  80. package/dist/modules/customers/data/entities.js +8 -0
  81. package/dist/modules/customers/data/entities.js.map +2 -2
  82. package/dist/modules/customers/data/validators.js +2 -1
  83. package/dist/modules/customers/data/validators.js.map +2 -2
  84. package/dist/modules/customers/migrations/Migration20260723210000_customers.js +15 -0
  85. package/dist/modules/customers/migrations/Migration20260723210000_customers.js.map +7 -0
  86. package/dist/modules/entities/api/entity-settings.js +59 -9
  87. package/dist/modules/entities/api/entity-settings.js.map +2 -2
  88. package/dist/modules/entities/backend/config/settings/page.js +10 -0
  89. package/dist/modules/entities/backend/config/settings/page.js.map +7 -0
  90. package/dist/modules/entities/backend/config/settings/page.meta.js +36 -0
  91. package/dist/modules/entities/backend/config/settings/page.meta.js.map +7 -0
  92. package/dist/modules/entities/backend/entities/user/create/page.js +16 -7
  93. package/dist/modules/entities/backend/entities/user/create/page.js.map +2 -2
  94. package/dist/modules/entities/components/EntitySettingsManager.js +136 -0
  95. package/dist/modules/entities/components/EntitySettingsManager.js.map +7 -0
  96. package/dist/modules/inbox_ops/api/webhook/inbound.js +14 -10
  97. package/dist/modules/inbox_ops/api/webhook/inbound.js.map +2 -2
  98. package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +11 -1
  99. package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +2 -2
  100. package/dist/modules/payment_gateways/data/entities.js +4 -0
  101. package/dist/modules/payment_gateways/data/entities.js.map +2 -2
  102. package/dist/modules/payment_gateways/lib/gateway-service.js +12 -2
  103. package/dist/modules/payment_gateways/lib/gateway-service.js.map +2 -2
  104. package/dist/modules/payment_gateways/lib/session-idempotency.js +33 -0
  105. package/dist/modules/payment_gateways/lib/session-idempotency.js.map +2 -2
  106. package/dist/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.js +18 -0
  107. package/dist/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.js.map +7 -0
  108. package/dist/modules/payment_gateways/setup.js +47 -0
  109. package/dist/modules/payment_gateways/setup.js.map +2 -2
  110. package/dist/modules/payment_gateways/workers/session-initialization-prune.js +50 -0
  111. package/dist/modules/payment_gateways/workers/session-initialization-prune.js.map +7 -0
  112. package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.js +134 -0
  113. package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.js.map +7 -0
  114. package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.js +11 -0
  115. package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.js.map +7 -0
  116. package/dist/modules/portal/lib/navigation.js +7 -0
  117. package/dist/modules/portal/lib/navigation.js.map +7 -0
  118. package/dist/modules/query_index/lib/engine.js +43 -0
  119. package/dist/modules/query_index/lib/engine.js.map +2 -2
  120. package/dist/modules/query_index/lib/search-tokens.js +15 -5
  121. package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
  122. package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js +11 -1
  123. package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js.map +2 -2
  124. package/generated/entities/customer_deal_person_link/index.ts +1 -0
  125. package/generated/entities/customer_user_invitation/index.ts +1 -0
  126. package/generated/entity-fields-registry.ts +2 -0
  127. package/package.json +7 -7
  128. package/src/modules/business_rules/api/openmercato-call-options/route.ts +94 -0
  129. package/src/modules/business_rules/api/rules/route.ts +92 -4
  130. package/src/modules/business_rules/components/ActionBuilder.tsx +54 -5
  131. package/src/modules/business_rules/components/ActionRow.tsx +156 -18
  132. package/src/modules/business_rules/components/utils/actionValidation.ts +6 -0
  133. package/src/modules/business_rules/i18n/de.json +12 -0
  134. package/src/modules/business_rules/i18n/en.json +12 -0
  135. package/src/modules/business_rules/i18n/es.json +12 -0
  136. package/src/modules/business_rules/i18n/pl.json +12 -0
  137. package/src/modules/business_rules/lib/action-executor.ts +198 -0
  138. package/src/modules/business_rules/lib/openmercato-call-options-types.ts +31 -0
  139. package/src/modules/business_rules/lib/openmercato-call-options.ts +297 -0
  140. package/src/modules/business_rules/lib/rule-engine.ts +4 -0
  141. package/src/modules/communication_channels/api/post/webhook/[provider]/route.ts +11 -1
  142. package/src/modules/communication_channels/api/post/webhooks/gmail/route.ts +17 -11
  143. package/src/modules/configs/lib/upgrade-actions.ts +14 -0
  144. package/src/modules/customer_accounts/api/admin/users/[id].ts +16 -1
  145. package/src/modules/customer_accounts/api/admin/users-invite.ts +78 -3
  146. package/src/modules/customer_accounts/api/portal/users-invite.ts +22 -1
  147. package/src/modules/customer_accounts/data/entities.ts +3 -0
  148. package/src/modules/customer_accounts/data/validators.ts +1 -0
  149. package/src/modules/customer_accounts/emails/CustomerInvitationEmail.tsx +45 -0
  150. package/src/modules/customer_accounts/i18n/de.json +6 -0
  151. package/src/modules/customer_accounts/i18n/en.json +6 -0
  152. package/src/modules/customer_accounts/i18n/es.json +6 -0
  153. package/src/modules/customer_accounts/i18n/pl.json +6 -0
  154. package/src/modules/customer_accounts/lib/customerEntityOwnership.ts +68 -2
  155. package/src/modules/customer_accounts/lib/customerUrl.ts +27 -11
  156. package/src/modules/customer_accounts/lib/invitationEmail.ts +42 -0
  157. package/src/modules/customer_accounts/migrations/.snapshot-open-mercato.json +16 -0
  158. package/src/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.ts +13 -0
  159. package/src/modules/customer_accounts/services/customerInvitationService.ts +56 -3
  160. package/src/modules/customer_accounts/subscribers/autoLinkCrm.ts +75 -8
  161. package/src/modules/customer_accounts/widgets/injection/account-status/widget.client.tsx +2 -2
  162. package/src/modules/customer_accounts/widgets/injection-table.ts +4 -1
  163. package/src/modules/customers/api/deals/[id]/people/route.ts +3 -0
  164. package/src/modules/customers/api/deals/[id]/route.ts +10 -2
  165. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +12 -1
  166. package/src/modules/customers/backend/customers/deals/[id]/hooks/types.ts +1 -0
  167. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +15 -9
  168. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +24 -6
  169. package/src/modules/customers/commands/deals.ts +50 -9
  170. package/src/modules/customers/commands/people.ts +3 -0
  171. package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +30 -7
  172. package/src/modules/customers/components/detail/DealDetailTabs.tsx +34 -9
  173. package/src/modules/customers/components/detail/PersonDetailTabs.tsx +34 -9
  174. package/src/modules/customers/data/entities.ts +9 -1
  175. package/src/modules/customers/data/validators.ts +1 -0
  176. package/src/modules/customers/i18n/de.json +1 -0
  177. package/src/modules/customers/i18n/en.json +1 -0
  178. package/src/modules/customers/i18n/es.json +1 -0
  179. package/src/modules/customers/i18n/pl.json +1 -0
  180. package/src/modules/customers/migrations/.snapshot-open-mercato.json +27 -1
  181. package/src/modules/customers/migrations/Migration20260723210000_customers.ts +15 -0
  182. package/src/modules/entities/api/entity-settings.ts +66 -22
  183. package/src/modules/entities/backend/config/settings/page.meta.ts +34 -0
  184. package/src/modules/entities/backend/config/settings/page.tsx +12 -0
  185. package/src/modules/entities/backend/entities/user/create/page.tsx +16 -7
  186. package/src/modules/entities/components/EntitySettingsManager.tsx +160 -0
  187. package/src/modules/entities/i18n/de.json +9 -0
  188. package/src/modules/entities/i18n/en.json +9 -0
  189. package/src/modules/entities/i18n/es.json +9 -0
  190. package/src/modules/entities/i18n/pl.json +9 -0
  191. package/src/modules/inbox_ops/api/webhook/inbound.ts +14 -12
  192. package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +13 -1
  193. package/src/modules/payment_gateways/data/entities.ts +5 -0
  194. package/src/modules/payment_gateways/i18n/de.json +5 -1
  195. package/src/modules/payment_gateways/i18n/en.json +5 -1
  196. package/src/modules/payment_gateways/i18n/es.json +5 -1
  197. package/src/modules/payment_gateways/i18n/pl.json +5 -1
  198. package/src/modules/payment_gateways/lib/gateway-service.ts +12 -2
  199. package/src/modules/payment_gateways/lib/session-idempotency.ts +36 -0
  200. package/src/modules/payment_gateways/migrations/.snapshot-open-mercato.json +10 -1
  201. package/src/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.ts +17 -0
  202. package/src/modules/payment_gateways/setup.ts +62 -0
  203. package/src/modules/payment_gateways/workers/session-initialization-prune.ts +63 -0
  204. package/src/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.ts +9 -0
  205. package/src/modules/portal/frontend/[orgSlug]/portal/invite/page.tsx +164 -0
  206. package/src/modules/portal/i18n/de.json +18 -0
  207. package/src/modules/portal/i18n/en.json +18 -0
  208. package/src/modules/portal/i18n/es.json +18 -0
  209. package/src/modules/portal/i18n/pl.json +18 -0
  210. package/src/modules/portal/lib/navigation.ts +3 -0
  211. package/src/modules/query_index/lib/engine.ts +52 -0
  212. package/src/modules/query_index/lib/search-tokens.ts +16 -4
  213. package/src/modules/shipping_carriers/api/webhook/[provider]/route.ts +11 -1
@@ -2,6 +2,9 @@
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import { X, ChevronUp, ChevronDown } from "lucide-react";
4
4
  import { Input } from "@open-mercato/ui/primitives/input";
5
+ import { Textarea } from "@open-mercato/ui/primitives/textarea";
6
+ import { IconButton } from "@open-mercato/ui/primitives/icon-button";
7
+ import { ComboboxInput } from "@open-mercato/ui/backend/inputs";
5
8
  import {
6
9
  Select,
7
10
  SelectContent,
@@ -20,7 +23,8 @@ function ActionRow({
20
23
  onMoveDown,
21
24
  canMoveUp,
22
25
  canMoveDown,
23
- error
26
+ error,
27
+ openMercatoOptions
24
28
  }) {
25
29
  const t = useT();
26
30
  const actionTypes = getActionTypeOptions(t);
@@ -43,6 +47,85 @@ function ActionRow({
43
47
  }
44
48
  });
45
49
  };
50
+ const renderOpenMercatoConfig = () => {
51
+ const options = openMercatoOptions ?? { endpoints: [], apiKeys: [], loading: false, error: null };
52
+ const endpointValue = action.config?.endpoint && action.config?.method ? `${String(action.config.method).toUpperCase()} ${action.config.endpoint}` : void 0;
53
+ const apiKeyValue = action.config?.apiKeyId || void 0;
54
+ const endpointOptions = options.endpoints.map((option) => ({
55
+ value: option.id,
56
+ label: option.label,
57
+ description: option.summary || option.operationId || null
58
+ }));
59
+ const bodyValue = action.config?.body == null ? "" : typeof action.config.body === "string" ? action.config.body : JSON.stringify(action.config.body, null, 2);
60
+ const handleEndpointChange = (value) => {
61
+ const option = options.endpoints.find((candidate) => candidate.id === value);
62
+ if (!option) return;
63
+ onChange(index, {
64
+ ...action,
65
+ config: {
66
+ ...action.config || {},
67
+ endpoint: option.path,
68
+ method: option.method
69
+ }
70
+ });
71
+ };
72
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
73
+ options.loading && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground col-start-2", children: t("business_rules.components.actionRow.openMercato.options.loading") }),
74
+ options.error && /* @__PURE__ */ jsx("p", { className: "text-xs text-status-error-text col-start-2", children: t("business_rules.components.actionRow.openMercato.options.error", { error: options.error }) }),
75
+ !options.loading && !options.error && options.endpoints.length === 0 && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground col-start-2", children: t("business_rules.components.actionRow.openMercato.options.noEndpoints") }),
76
+ !options.loading && !options.error && options.apiKeys.length === 0 && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground col-start-2", children: t("business_rules.components.actionRow.openMercato.options.noApiKeys") }),
77
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-4 gap-2 items-center", children: [
78
+ /* @__PURE__ */ jsxs("label", { className: "text-xs font-medium text-foreground col-span-1", children: [
79
+ t("business_rules.components.actionRow.config.endpoint"),
80
+ " ",
81
+ /* @__PURE__ */ jsx("span", { className: "text-status-error-text", children: t("business_rules.components.actionRow.actionType.required") })
82
+ ] }),
83
+ /* @__PURE__ */ jsx("div", { className: "col-span-3", children: /* @__PURE__ */ jsx(
84
+ ComboboxInput,
85
+ {
86
+ value: endpointValue ?? "",
87
+ onChange: handleEndpointChange,
88
+ suggestions: endpointOptions,
89
+ placeholder: t("business_rules.components.actionRow.config.endpoint.placeholder"),
90
+ disabled: options.loading || !!options.error || options.endpoints.length === 0,
91
+ allowCustomValues: false
92
+ }
93
+ ) })
94
+ ] }),
95
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-4 gap-2 items-center", children: [
96
+ /* @__PURE__ */ jsxs("label", { className: "text-xs font-medium text-foreground col-span-1", children: [
97
+ t("business_rules.components.actionRow.config.apiKey"),
98
+ " ",
99
+ /* @__PURE__ */ jsx("span", { className: "text-status-error-text", children: t("business_rules.components.actionRow.actionType.required") })
100
+ ] }),
101
+ /* @__PURE__ */ jsxs(
102
+ Select,
103
+ {
104
+ value: apiKeyValue,
105
+ onValueChange: (next) => handleConfigChange("apiKeyId", next),
106
+ disabled: options.loading || !!options.error || options.apiKeys.length === 0,
107
+ children: [
108
+ /* @__PURE__ */ jsx(SelectTrigger, { size: "sm", className: "col-span-3", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: t("business_rules.components.actionRow.config.apiKey.placeholder") }) }),
109
+ /* @__PURE__ */ jsx(SelectContent, { children: options.apiKeys.map((apiKey) => /* @__PURE__ */ jsx(SelectItem, { value: apiKey.id, children: apiKey.organizationName ? `${apiKey.name} (${apiKey.keyPrefix}, ${apiKey.organizationName})` : `${apiKey.name} (${apiKey.keyPrefix})` }, apiKey.id)) })
110
+ ]
111
+ }
112
+ )
113
+ ] }),
114
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-4 gap-2 items-start", children: [
115
+ /* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-foreground col-span-1", children: t("business_rules.components.actionRow.config.body") }),
116
+ /* @__PURE__ */ jsx(
117
+ Textarea,
118
+ {
119
+ value: bodyValue,
120
+ onChange: (e) => handleConfigChange("body", e.target.value),
121
+ placeholder: t("business_rules.components.actionRow.config.body.placeholder"),
122
+ rows: 3,
123
+ className: "col-span-3"
124
+ }
125
+ )
126
+ ] })
127
+ ] });
128
+ };
46
129
  const renderConfigField = (field, required) => {
47
130
  const value = action.config?.[field] || "";
48
131
  if (field === "recipients" && action.type === "NOTIFY") {
@@ -50,7 +133,7 @@ function ActionRow({
50
133
  /* @__PURE__ */ jsxs("label", { className: "text-xs font-medium text-foreground col-span-1", children: [
51
134
  t("business_rules.components.actionRow.config.recipients"),
52
135
  " ",
53
- required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: t("business_rules.components.actionRow.actionType.required") })
136
+ required && /* @__PURE__ */ jsx("span", { className: "text-status-error-text", children: t("business_rules.components.actionRow.actionType.required") })
54
137
  ] }),
55
138
  /* @__PURE__ */ jsx(
56
139
  Input,
@@ -113,16 +196,16 @@ function ActionRow({
113
196
  /* @__PURE__ */ jsxs("label", { className: "text-xs font-medium text-foreground col-span-1", children: [
114
197
  t("business_rules.components.actionRow.config.message"),
115
198
  " ",
116
- required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: t("business_rules.components.actionRow.actionType.required") })
199
+ required && /* @__PURE__ */ jsx("span", { className: "text-status-error-text", children: t("business_rules.components.actionRow.actionType.required") })
117
200
  ] }),
118
201
  /* @__PURE__ */ jsx(
119
- "textarea",
202
+ Textarea,
120
203
  {
121
204
  value,
122
205
  onChange: (e) => handleConfigChange(field, e.target.value),
123
206
  placeholder: t("business_rules.components.actionRow.config.message.placeholder"),
124
207
  rows: 2,
125
- className: "col-span-3 px-2 py-1.5 text-sm border border-border rounded bg-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
208
+ className: "col-span-3"
126
209
  }
127
210
  ),
128
211
  /* @__PURE__ */ jsx("div", { className: "col-span-4 col-start-2", children: /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("business_rules.components.actionRow.config.message.help") }) })
@@ -132,7 +215,7 @@ function ActionRow({
132
215
  /* @__PURE__ */ jsxs("label", { className: "text-xs font-medium text-foreground col-span-1", children: [
133
216
  field,
134
217
  " ",
135
- required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: t("business_rules.components.actionRow.actionType.required") })
218
+ required && /* @__PURE__ */ jsx("span", { className: "text-status-error-text", children: t("business_rules.components.actionRow.actionType.required") })
136
219
  ] }),
137
220
  /* @__PURE__ */ jsx(
138
221
  Input,
@@ -152,7 +235,7 @@ function ActionRow({
152
235
  /* @__PURE__ */ jsxs("label", { className: "text-xs font-medium text-foreground col-span-1", children: [
153
236
  t("business_rules.components.actionRow.actionType"),
154
237
  " ",
155
- /* @__PURE__ */ jsx("span", { className: "text-red-500", children: t("business_rules.components.actionRow.actionType.required") })
238
+ /* @__PURE__ */ jsx("span", { className: "text-status-error-text", children: t("business_rules.components.actionRow.actionType.required") })
156
239
  ] }),
157
240
  /* @__PURE__ */ jsxs(
158
241
  Select,
@@ -166,42 +249,49 @@ function ActionRow({
166
249
  }
167
250
  )
168
251
  ] }),
169
- action.type && /* @__PURE__ */ jsxs(Fragment, { children: [
252
+ action.type && /* @__PURE__ */ jsx(Fragment, { children: action.type === "CALL_OPEN_MERCATO" ? renderOpenMercatoConfig() : /* @__PURE__ */ jsxs(Fragment, { children: [
170
253
  requiredFields.map((field) => renderConfigField(field, true)),
171
254
  optionalFields.map((field) => renderConfigField(field, false))
172
- ] }),
173
- error && /* @__PURE__ */ jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsx("p", { className: "text-xs text-red-600", children: error }) })
255
+ ] }) }),
256
+ error && /* @__PURE__ */ jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsx("p", { className: "text-xs text-status-error-text", children: error }) })
174
257
  ] }),
175
258
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
176
259
  onMoveUp && /* @__PURE__ */ jsx(
177
- "button",
260
+ IconButton,
178
261
  {
179
262
  type: "button",
180
263
  onClick: () => onMoveUp(index),
181
264
  disabled: !canMoveUp,
182
- className: "p-1 text-muted-foreground hover:text-foreground hover:bg-muted rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
265
+ variant: "ghost",
266
+ size: "xs",
183
267
  title: t("business_rules.components.actionRow.moveUp"),
268
+ "aria-label": t("business_rules.components.actionRow.moveUp"),
184
269
  children: /* @__PURE__ */ jsx(ChevronUp, { className: "w-4 h-4" })
185
270
  }
186
271
  ),
187
272
  onMoveDown && /* @__PURE__ */ jsx(
188
- "button",
273
+ IconButton,
189
274
  {
190
275
  type: "button",
191
276
  onClick: () => onMoveDown(index),
192
277
  disabled: !canMoveDown,
193
- className: "p-1 text-muted-foreground hover:text-foreground hover:bg-muted rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
278
+ variant: "ghost",
279
+ size: "xs",
194
280
  title: t("business_rules.components.actionRow.moveDown"),
281
+ "aria-label": t("business_rules.components.actionRow.moveDown"),
195
282
  children: /* @__PURE__ */ jsx(ChevronDown, { className: "w-4 h-4" })
196
283
  }
197
284
  ),
198
285
  /* @__PURE__ */ jsx(
199
- "button",
286
+ IconButton,
200
287
  {
201
288
  type: "button",
202
289
  onClick: () => onDelete(index),
203
- className: "p-1 text-muted-foreground hover:text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 rounded transition-colors",
290
+ variant: "ghost",
291
+ size: "xs",
292
+ className: "hover:text-status-error-text",
204
293
  title: t("business_rules.components.actionRow.delete"),
294
+ "aria-label": t("business_rules.components.actionRow.delete"),
205
295
  children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4" })
206
296
  }
207
297
  )
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/business_rules/components/ActionRow.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { X, ChevronUp, ChevronDown } from 'lucide-react'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport type { Action } from './utils/actionValidation'\nimport { getActionTypeOptions, getRequiredConfigFields, getOptionalConfigFields } from './utils/actionValidation'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\nexport type ActionRowProps = {\n action: Action\n index: number\n onChange: (index: number, action: Action) => void\n onDelete: (index: number) => void\n onMoveUp?: (index: number) => void\n onMoveDown?: (index: number) => void\n canMoveUp?: boolean\n canMoveDown?: boolean\n error?: string\n}\n\nexport function ActionRow({\n action,\n index,\n onChange,\n onDelete,\n onMoveUp,\n onMoveDown,\n canMoveUp,\n canMoveDown,\n error,\n}: ActionRowProps) {\n const t = useT()\n const actionTypes = getActionTypeOptions(t)\n const requiredFields = getRequiredConfigFields(action.type)\n const optionalFields = getOptionalConfigFields(action.type)\n\n const handleTypeChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n onChange(index, {\n ...action,\n type: e.target.value,\n config: {}, // Reset config when type changes\n })\n }\n\n const handleConfigChange = (field: string, value: any) => {\n onChange(index, {\n ...action,\n config: {\n ...(action.config || {}),\n [field]: value,\n },\n })\n }\n\n const renderConfigField = (field: string, required: boolean) => {\n const value = action.config?.[field] || ''\n\n // Special handling for different field types\n if (field === 'recipients' && action.type === 'NOTIFY') {\n return (\n <div key={field} className=\"grid grid-cols-4 gap-2 items-start\">\n <label className=\"text-xs font-medium text-foreground col-span-1\">\n {t('business_rules.components.actionRow.config.recipients')} {required && <span className=\"text-red-500\">{t('business_rules.components.actionRow.actionType.required')}</span>}\n </label>\n <Input\n type=\"text\"\n value={value}\n onChange={(e) => handleConfigChange(field, e.target.value.split(',').map((s) => s.trim()))}\n placeholder={t('business_rules.components.actionRow.config.recipients.placeholder')}\n className=\"col-span-3\"\n />\n <div className=\"col-span-4 col-start-2\">\n <p className=\"text-xs text-muted-foreground\">{t('business_rules.components.actionRow.config.recipients.help')}</p>\n </div>\n </div>\n )\n }\n\n if (field === 'level' && action.type === 'LOG') {\n return (\n <div key={field} className=\"grid grid-cols-4 gap-2 items-center\">\n <label className=\"text-xs font-medium text-foreground col-span-1\">{t('business_rules.components.actionRow.config.level')}</label>\n <Select\n value={value || 'info'}\n onValueChange={(next) => handleConfigChange(field, next)}\n >\n <SelectTrigger size=\"sm\" className=\"col-span-3\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"info\">{t('business_rules.components.actionRow.config.level.info')}</SelectItem>\n <SelectItem value=\"warn\">{t('business_rules.components.actionRow.config.level.warn')}</SelectItem>\n <SelectItem value=\"error\">{t('business_rules.components.actionRow.config.level.error')}</SelectItem>\n <SelectItem value=\"debug\">{t('business_rules.components.actionRow.config.level.debug')}</SelectItem>\n </SelectContent>\n </Select>\n </div>\n )\n }\n\n if (field === 'method' && action.type === 'CALL_WEBHOOK') {\n return (\n <div key={field} className=\"grid grid-cols-4 gap-2 items-center\">\n <label className=\"text-xs font-medium text-foreground col-span-1\">{t('business_rules.components.actionRow.config.method')}</label>\n <Select\n value={value || 'POST'}\n onValueChange={(next) => handleConfigChange(field, next)}\n >\n <SelectTrigger size=\"sm\" className=\"col-span-3\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"GET\">GET</SelectItem>\n <SelectItem value=\"POST\">POST</SelectItem>\n <SelectItem value=\"PUT\">PUT</SelectItem>\n <SelectItem value=\"PATCH\">PATCH</SelectItem>\n <SelectItem value=\"DELETE\">DELETE</SelectItem>\n </SelectContent>\n </Select>\n </div>\n )\n }\n\n if (field === 'message') {\n return (\n <div key={field} className=\"grid grid-cols-4 gap-2 items-start\">\n <label className=\"text-xs font-medium text-foreground col-span-1\">\n {t('business_rules.components.actionRow.config.message')} {required && <span className=\"text-red-500\">{t('business_rules.components.actionRow.actionType.required')}</span>}\n </label>\n <textarea\n value={value}\n onChange={(e) => handleConfigChange(field, e.target.value)}\n placeholder={t('business_rules.components.actionRow.config.message.placeholder')}\n rows={2}\n className=\"col-span-3 px-2 py-1.5 text-sm border border-border rounded bg-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n />\n <div className=\"col-span-4 col-start-2\">\n <p className=\"text-xs text-muted-foreground\">{t('business_rules.components.actionRow.config.message.help')}</p>\n </div>\n </div>\n )\n }\n\n // Default text input\n return (\n <div key={field} className=\"grid grid-cols-4 gap-2 items-center\">\n <label className=\"text-xs font-medium text-foreground col-span-1\">\n {field} {required && <span className=\"text-red-500\">{t('business_rules.components.actionRow.actionType.required')}</span>}\n </label>\n <Input\n type=\"text\"\n value={value}\n onChange={(e) => handleConfigChange(field, e.target.value)}\n placeholder={t('business_rules.components.actionRow.config.field.placeholder', { field })}\n className=\"col-span-3\"\n />\n </div>\n )\n }\n\n return (\n <div className=\"flex items-start gap-2 p-3 bg-muted rounded border border-border\">\n <div className=\"flex-1 space-y-2\">\n {/* Action Type */}\n <div className=\"grid grid-cols-4 gap-2 items-center\">\n <label className=\"text-xs font-medium text-foreground col-span-1\">\n {t('business_rules.components.actionRow.actionType')} <span className=\"text-red-500\">{t('business_rules.components.actionRow.actionType.required')}</span>\n </label>\n <Select\n value={action.type || undefined}\n onValueChange={(value) => handleTypeChange({ target: { value } } as React.ChangeEvent<HTMLSelectElement>)}\n >\n <SelectTrigger size=\"sm\" className=\"col-span-3 font-medium\">\n <SelectValue placeholder={t('business_rules.components.actionRow.actionType.placeholder')} />\n </SelectTrigger>\n <SelectContent>\n {actionTypes.map((type) => (\n <SelectItem key={type.value} value={type.value}>\n {type.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {/* Config Fields */}\n {action.type && (\n <>\n {requiredFields.map((field) => renderConfigField(field, true))}\n {optionalFields.map((field) => renderConfigField(field, false))}\n </>\n )}\n\n {/* Error Display */}\n {error && (\n <div className=\"mt-2\">\n <p className=\"text-xs text-red-600\">{error}</p>\n </div>\n )}\n </div>\n\n {/* Control Buttons */}\n <div className=\"flex flex-col gap-1\">\n {onMoveUp && (\n <button\n type=\"button\"\n onClick={() => onMoveUp(index)}\n disabled={!canMoveUp}\n className=\"p-1 text-muted-foreground hover:text-foreground hover:bg-muted rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n title={t('business_rules.components.actionRow.moveUp')}\n >\n <ChevronUp className=\"w-4 h-4\" />\n </button>\n )}\n {onMoveDown && (\n <button\n type=\"button\"\n onClick={() => onMoveDown(index)}\n disabled={!canMoveDown}\n className=\"p-1 text-muted-foreground hover:text-foreground hover:bg-muted rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n title={t('business_rules.components.actionRow.moveDown')}\n >\n <ChevronDown className=\"w-4 h-4\" />\n </button>\n )}\n <button\n type=\"button\"\n onClick={() => onDelete(index)}\n className=\"p-1 text-muted-foreground hover:text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 rounded transition-colors\"\n title={t('business_rules.components.actionRow.delete')}\n >\n <X className=\"w-4 h-4\" />\n </button>\n </div>\n </div>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { X, ChevronUp, ChevronDown } from 'lucide-react'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Textarea } from '@open-mercato/ui/primitives/textarea'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { ComboboxInput, type ComboboxOption } from '@open-mercato/ui/backend/inputs'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport type { Action } from './utils/actionValidation'\nimport { getActionTypeOptions, getRequiredConfigFields, getOptionalConfigFields } from './utils/actionValidation'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type {\n OpenMercatoApiKeyOption,\n OpenMercatoEndpointOption,\n} from '../lib/openmercato-call-options-types'\n\nexport type OpenMercatoCallOptionsState = {\n endpoints: OpenMercatoEndpointOption[]\n apiKeys: OpenMercatoApiKeyOption[]\n loading: boolean\n error: string | null\n}\n\nexport type ActionRowProps = {\n action: Action\n index: number\n onChange: (index: number, action: Action) => void\n onDelete: (index: number) => void\n onMoveUp?: (index: number) => void\n onMoveDown?: (index: number) => void\n canMoveUp?: boolean\n canMoveDown?: boolean\n error?: string\n openMercatoOptions?: OpenMercatoCallOptionsState\n}\n\nexport function ActionRow({\n action,\n index,\n onChange,\n onDelete,\n onMoveUp,\n onMoveDown,\n canMoveUp,\n canMoveDown,\n error,\n openMercatoOptions,\n}: ActionRowProps) {\n const t = useT()\n const actionTypes = getActionTypeOptions(t)\n const requiredFields = getRequiredConfigFields(action.type)\n const optionalFields = getOptionalConfigFields(action.type)\n\n const handleTypeChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n onChange(index, {\n ...action,\n type: e.target.value,\n config: {}, // Reset config when type changes\n })\n }\n\n const handleConfigChange = (field: string, value: any) => {\n onChange(index, {\n ...action,\n config: {\n ...(action.config || {}),\n [field]: value,\n },\n })\n }\n\n const renderOpenMercatoConfig = () => {\n const options = openMercatoOptions ?? { endpoints: [], apiKeys: [], loading: false, error: null }\n const endpointValue = action.config?.endpoint && action.config?.method\n ? `${String(action.config.method).toUpperCase()} ${action.config.endpoint}`\n : undefined\n const apiKeyValue = action.config?.apiKeyId || undefined\n const endpointOptions = options.endpoints.map<ComboboxOption>((option) => ({\n value: option.id,\n label: option.label,\n description: option.summary || option.operationId || null,\n }))\n const bodyValue = action.config?.body == null\n ? ''\n : typeof action.config.body === 'string'\n ? action.config.body\n : JSON.stringify(action.config.body, null, 2)\n\n const handleEndpointChange = (value: string) => {\n const option = options.endpoints.find((candidate) => candidate.id === value)\n if (!option) return\n onChange(index, {\n ...action,\n config: {\n ...(action.config || {}),\n endpoint: option.path,\n method: option.method,\n },\n })\n }\n\n return (\n <div className=\"space-y-2\">\n {options.loading && (\n <p className=\"text-xs text-muted-foreground col-start-2\">\n {t('business_rules.components.actionRow.openMercato.options.loading')}\n </p>\n )}\n {options.error && (\n <p className=\"text-xs text-status-error-text col-start-2\">\n {t('business_rules.components.actionRow.openMercato.options.error', { error: options.error })}\n </p>\n )}\n {!options.loading && !options.error && options.endpoints.length === 0 && (\n <p className=\"text-xs text-muted-foreground col-start-2\">\n {t('business_rules.components.actionRow.openMercato.options.noEndpoints')}\n </p>\n )}\n {!options.loading && !options.error && options.apiKeys.length === 0 && (\n <p className=\"text-xs text-muted-foreground col-start-2\">\n {t('business_rules.components.actionRow.openMercato.options.noApiKeys')}\n </p>\n )}\n\n <div className=\"grid grid-cols-4 gap-2 items-center\">\n <label className=\"text-xs font-medium text-foreground col-span-1\">\n {t('business_rules.components.actionRow.config.endpoint')} <span className=\"text-status-error-text\">{t('business_rules.components.actionRow.actionType.required')}</span>\n </label>\n <div className=\"col-span-3\">\n <ComboboxInput\n value={endpointValue ?? ''}\n onChange={handleEndpointChange}\n suggestions={endpointOptions}\n placeholder={t('business_rules.components.actionRow.config.endpoint.placeholder')}\n disabled={options.loading || !!options.error || options.endpoints.length === 0}\n allowCustomValues={false}\n />\n </div>\n </div>\n\n <div className=\"grid grid-cols-4 gap-2 items-center\">\n <label className=\"text-xs font-medium text-foreground col-span-1\">\n {t('business_rules.components.actionRow.config.apiKey')} <span className=\"text-status-error-text\">{t('business_rules.components.actionRow.actionType.required')}</span>\n </label>\n <Select\n value={apiKeyValue}\n onValueChange={(next) => handleConfigChange('apiKeyId', next)}\n disabled={options.loading || !!options.error || options.apiKeys.length === 0}\n >\n <SelectTrigger size=\"sm\" className=\"col-span-3\">\n <SelectValue placeholder={t('business_rules.components.actionRow.config.apiKey.placeholder')} />\n </SelectTrigger>\n <SelectContent>\n {options.apiKeys.map((apiKey) => (\n <SelectItem key={apiKey.id} value={apiKey.id}>\n {apiKey.organizationName\n ? `${apiKey.name} (${apiKey.keyPrefix}, ${apiKey.organizationName})`\n : `${apiKey.name} (${apiKey.keyPrefix})`}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"grid grid-cols-4 gap-2 items-start\">\n <label className=\"text-xs font-medium text-foreground col-span-1\">\n {t('business_rules.components.actionRow.config.body')}\n </label>\n <Textarea\n value={bodyValue}\n onChange={(e) => handleConfigChange('body', e.target.value)}\n placeholder={t('business_rules.components.actionRow.config.body.placeholder')}\n rows={3}\n className=\"col-span-3\"\n />\n </div>\n </div>\n )\n }\n\n const renderConfigField = (field: string, required: boolean) => {\n const value = action.config?.[field] || ''\n\n // Special handling for different field types\n if (field === 'recipients' && action.type === 'NOTIFY') {\n return (\n <div key={field} className=\"grid grid-cols-4 gap-2 items-start\">\n <label className=\"text-xs font-medium text-foreground col-span-1\">\n {t('business_rules.components.actionRow.config.recipients')} {required && <span className=\"text-status-error-text\">{t('business_rules.components.actionRow.actionType.required')}</span>}\n </label>\n <Input\n type=\"text\"\n value={value}\n onChange={(e) => handleConfigChange(field, e.target.value.split(',').map((s) => s.trim()))}\n placeholder={t('business_rules.components.actionRow.config.recipients.placeholder')}\n className=\"col-span-3\"\n />\n <div className=\"col-span-4 col-start-2\">\n <p className=\"text-xs text-muted-foreground\">{t('business_rules.components.actionRow.config.recipients.help')}</p>\n </div>\n </div>\n )\n }\n\n if (field === 'level' && action.type === 'LOG') {\n return (\n <div key={field} className=\"grid grid-cols-4 gap-2 items-center\">\n <label className=\"text-xs font-medium text-foreground col-span-1\">{t('business_rules.components.actionRow.config.level')}</label>\n <Select\n value={value || 'info'}\n onValueChange={(next) => handleConfigChange(field, next)}\n >\n <SelectTrigger size=\"sm\" className=\"col-span-3\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"info\">{t('business_rules.components.actionRow.config.level.info')}</SelectItem>\n <SelectItem value=\"warn\">{t('business_rules.components.actionRow.config.level.warn')}</SelectItem>\n <SelectItem value=\"error\">{t('business_rules.components.actionRow.config.level.error')}</SelectItem>\n <SelectItem value=\"debug\">{t('business_rules.components.actionRow.config.level.debug')}</SelectItem>\n </SelectContent>\n </Select>\n </div>\n )\n }\n\n if (field === 'method' && action.type === 'CALL_WEBHOOK') {\n return (\n <div key={field} className=\"grid grid-cols-4 gap-2 items-center\">\n <label className=\"text-xs font-medium text-foreground col-span-1\">{t('business_rules.components.actionRow.config.method')}</label>\n <Select\n value={value || 'POST'}\n onValueChange={(next) => handleConfigChange(field, next)}\n >\n <SelectTrigger size=\"sm\" className=\"col-span-3\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"GET\">GET</SelectItem>\n <SelectItem value=\"POST\">POST</SelectItem>\n <SelectItem value=\"PUT\">PUT</SelectItem>\n <SelectItem value=\"PATCH\">PATCH</SelectItem>\n <SelectItem value=\"DELETE\">DELETE</SelectItem>\n </SelectContent>\n </Select>\n </div>\n )\n }\n\n if (field === 'message') {\n return (\n <div key={field} className=\"grid grid-cols-4 gap-2 items-start\">\n <label className=\"text-xs font-medium text-foreground col-span-1\">\n {t('business_rules.components.actionRow.config.message')} {required && <span className=\"text-status-error-text\">{t('business_rules.components.actionRow.actionType.required')}</span>}\n </label>\n <Textarea\n value={value}\n onChange={(e) => handleConfigChange(field, e.target.value)}\n placeholder={t('business_rules.components.actionRow.config.message.placeholder')}\n rows={2}\n className=\"col-span-3\"\n />\n <div className=\"col-span-4 col-start-2\">\n <p className=\"text-xs text-muted-foreground\">{t('business_rules.components.actionRow.config.message.help')}</p>\n </div>\n </div>\n )\n }\n\n // Default text input\n return (\n <div key={field} className=\"grid grid-cols-4 gap-2 items-center\">\n <label className=\"text-xs font-medium text-foreground col-span-1\">\n {field} {required && <span className=\"text-status-error-text\">{t('business_rules.components.actionRow.actionType.required')}</span>}\n </label>\n <Input\n type=\"text\"\n value={value}\n onChange={(e) => handleConfigChange(field, e.target.value)}\n placeholder={t('business_rules.components.actionRow.config.field.placeholder', { field })}\n className=\"col-span-3\"\n />\n </div>\n )\n }\n\n return (\n <div className=\"flex items-start gap-2 p-3 bg-muted rounded border border-border\">\n <div className=\"flex-1 space-y-2\">\n {/* Action Type */}\n <div className=\"grid grid-cols-4 gap-2 items-center\">\n <label className=\"text-xs font-medium text-foreground col-span-1\">\n {t('business_rules.components.actionRow.actionType')} <span className=\"text-status-error-text\">{t('business_rules.components.actionRow.actionType.required')}</span>\n </label>\n <Select\n value={action.type || undefined}\n onValueChange={(value) => handleTypeChange({ target: { value } } as React.ChangeEvent<HTMLSelectElement>)}\n >\n <SelectTrigger size=\"sm\" className=\"col-span-3 font-medium\">\n <SelectValue placeholder={t('business_rules.components.actionRow.actionType.placeholder')} />\n </SelectTrigger>\n <SelectContent>\n {actionTypes.map((type) => (\n <SelectItem key={type.value} value={type.value}>\n {type.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {/* Config Fields */}\n {action.type && (\n <>\n {action.type === 'CALL_OPEN_MERCATO'\n ? renderOpenMercatoConfig()\n : (\n <>\n {requiredFields.map((field) => renderConfigField(field, true))}\n {optionalFields.map((field) => renderConfigField(field, false))}\n </>\n )}\n </>\n )}\n\n {/* Error Display */}\n {error && (\n <div className=\"mt-2\">\n <p className=\"text-xs text-status-error-text\">{error}</p>\n </div>\n )}\n </div>\n\n {/* Control Buttons */}\n <div className=\"flex flex-col gap-1\">\n {onMoveUp && (\n <IconButton\n type=\"button\"\n onClick={() => onMoveUp(index)}\n disabled={!canMoveUp}\n variant=\"ghost\"\n size=\"xs\"\n title={t('business_rules.components.actionRow.moveUp')}\n aria-label={t('business_rules.components.actionRow.moveUp')}\n >\n <ChevronUp className=\"w-4 h-4\" />\n </IconButton>\n )}\n {onMoveDown && (\n <IconButton\n type=\"button\"\n onClick={() => onMoveDown(index)}\n disabled={!canMoveDown}\n variant=\"ghost\"\n size=\"xs\"\n title={t('business_rules.components.actionRow.moveDown')}\n aria-label={t('business_rules.components.actionRow.moveDown')}\n >\n <ChevronDown className=\"w-4 h-4\" />\n </IconButton>\n )}\n <IconButton\n type=\"button\"\n onClick={() => onDelete(index)}\n variant=\"ghost\"\n size=\"xs\"\n className=\"hover:text-status-error-text\"\n title={t('business_rules.components.actionRow.delete')}\n aria-label={t('business_rules.components.actionRow.delete')}\n >\n <X className=\"w-4 h-4\" />\n </IconButton>\n </div>\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -8,6 +8,7 @@ const ACTION_TYPES = [
8
8
  "NOTIFY",
9
9
  "SET_FIELD",
10
10
  "CALL_WEBHOOK",
11
+ "CALL_OPEN_MERCATO",
11
12
  "EMIT_EVENT"
12
13
  ];
13
14
  function getActionTypeOptions(t) {
@@ -21,6 +22,7 @@ function getActionTypeOptions(t) {
21
22
  { value: "NOTIFY", label: t("business_rules.validation.actionTypes.NOTIFY") },
22
23
  { value: "SET_FIELD", label: t("business_rules.validation.actionTypes.SET_FIELD") },
23
24
  { value: "CALL_WEBHOOK", label: t("business_rules.validation.actionTypes.CALL_WEBHOOK") },
25
+ { value: "CALL_OPEN_MERCATO", label: t("business_rules.validation.actionTypes.CALL_OPEN_MERCATO") },
24
26
  { value: "EMIT_EVENT", label: t("business_rules.validation.actionTypes.EMIT_EVENT") }
25
27
  ];
26
28
  }
@@ -37,6 +39,8 @@ function getRequiredConfigFields(actionType) {
37
39
  return ["field", "value"];
38
40
  case "CALL_WEBHOOK":
39
41
  return ["url"];
42
+ case "CALL_OPEN_MERCATO":
43
+ return ["endpoint", "method", "apiKeyId"];
40
44
  case "EMIT_EVENT":
41
45
  return ["eventName"];
42
46
  case "ALLOW_TRANSITION":
@@ -53,6 +57,8 @@ function getOptionalConfigFields(actionType) {
53
57
  return ["template"];
54
58
  case "CALL_WEBHOOK":
55
59
  return ["method", "headers", "body"];
60
+ case "CALL_OPEN_MERCATO":
61
+ return ["body"];
56
62
  case "EMIT_EVENT":
57
63
  return ["payload"];
58
64
  default:
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/business_rules/components/utils/actionValidation.ts"],
4
- "sourcesContent": ["export type TranslatorFn = (key: string, params?: Record<string, any>) => string\n\nexport type Action = {\n type: string\n config?: Record<string, any>\n}\n\nexport type ValidationResult = {\n valid: boolean\n errors: string[]\n}\n\n/**\n * Available action types\n */\nexport const ACTION_TYPES = [\n 'ALLOW_TRANSITION',\n 'BLOCK_TRANSITION',\n 'LOG',\n 'SHOW_ERROR',\n 'SHOW_WARNING',\n 'SHOW_INFO',\n 'NOTIFY',\n 'SET_FIELD',\n 'CALL_WEBHOOK',\n 'EMIT_EVENT',\n] as const\n\nexport type ActionType = (typeof ACTION_TYPES)[number]\n\n/**\n * Get action type options for dropdown\n */\nexport function getActionTypeOptions(t: TranslatorFn): { value: string; label: string }[] {\n return [\n { value: 'ALLOW_TRANSITION', label: t('business_rules.validation.actionTypes.ALLOW_TRANSITION') },\n { value: 'BLOCK_TRANSITION', label: t('business_rules.validation.actionTypes.BLOCK_TRANSITION') },\n { value: 'LOG', label: t('business_rules.validation.actionTypes.LOG') },\n { value: 'SHOW_ERROR', label: t('business_rules.validation.actionTypes.SHOW_ERROR') },\n { value: 'SHOW_WARNING', label: t('business_rules.validation.actionTypes.SHOW_WARNING') },\n { value: 'SHOW_INFO', label: t('business_rules.validation.actionTypes.SHOW_INFO') },\n { value: 'NOTIFY', label: t('business_rules.validation.actionTypes.NOTIFY') },\n { value: 'SET_FIELD', label: t('business_rules.validation.actionTypes.SET_FIELD') },\n { value: 'CALL_WEBHOOK', label: t('business_rules.validation.actionTypes.CALL_WEBHOOK') },\n { value: 'EMIT_EVENT', label: t('business_rules.validation.actionTypes.EMIT_EVENT') },\n ]\n}\n\n/**\n * Get required config fields for an action type\n */\nexport function getRequiredConfigFields(actionType: string): string[] {\n switch (actionType) {\n case 'LOG':\n case 'SHOW_ERROR':\n case 'SHOW_WARNING':\n case 'SHOW_INFO':\n return ['message']\n case 'NOTIFY':\n return ['message', 'recipients']\n case 'SET_FIELD':\n return ['field', 'value']\n case 'CALL_WEBHOOK':\n return ['url']\n case 'EMIT_EVENT':\n return ['eventName']\n case 'ALLOW_TRANSITION':\n case 'BLOCK_TRANSITION':\n default:\n return []\n }\n}\n\n/**\n * Get optional config fields for an action type\n */\nexport function getOptionalConfigFields(actionType: string): string[] {\n switch (actionType) {\n case 'LOG':\n return ['level']\n case 'NOTIFY':\n return ['template']\n case 'CALL_WEBHOOK':\n return ['method', 'headers', 'body']\n case 'EMIT_EVENT':\n return ['payload']\n default:\n return []\n }\n}\n\n/**\n * Validate a single action\n */\nexport function validateAction(action: Action, t?: TranslatorFn): ValidationResult {\n const errors: string[] = []\n const translate = t || ((key: string) => key)\n\n if (!action) {\n errors.push(translate('business_rules.validation.action.required'))\n return { valid: false, errors }\n }\n\n if (!action.type || typeof action.type !== 'string') {\n errors.push(translate('business_rules.validation.action.typeRequired'))\n } else if (!ACTION_TYPES.includes(action.type as ActionType)) {\n errors.push(translate('business_rules.validation.action.unknownType', { type: action.type, validTypes: ACTION_TYPES.join(', ') }))\n }\n\n const requiredFields = getRequiredConfigFields(action.type)\n if (requiredFields.length > 0) {\n if (!action.config) {\n errors.push(translate('business_rules.validation.action.configRequired', { type: action.type, fields: requiredFields.join(', ') }))\n } else {\n requiredFields.forEach((field) => {\n if (!action.config![field]) {\n errors.push(translate('business_rules.validation.action.fieldMissing', { field }))\n }\n })\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n }\n}\n\n/**\n * Validate action config for a specific type\n */\nexport function validateActionConfig(actionType: string, config: Record<string, any> | undefined, t?: TranslatorFn): ValidationResult {\n const errors: string[] = []\n const translate = t || ((key: string) => key)\n\n const requiredFields = getRequiredConfigFields(actionType)\n if (requiredFields.length > 0 && !config) {\n errors.push(translate('business_rules.validation.action.configRequiredForType', { type: actionType }))\n return { valid: false, errors }\n }\n\n if (config) {\n requiredFields.forEach((field) => {\n if (!config[field]) {\n errors.push(translate('business_rules.validation.action.fieldMissingShort', { field }))\n }\n })\n }\n\n return {\n valid: errors.length === 0,\n errors,\n }\n}\n\n/**\n * Validate array of actions\n */\nexport function validateActions(actions: Action[] | null | undefined, t?: TranslatorFn): ValidationResult {\n if (!actions || actions.length === 0) {\n return { valid: true, errors: [] } // Empty is valid\n }\n\n const errors: string[] = []\n const translate = t || ((key: string) => key)\n\n actions.forEach((action, index) => {\n const result = validateAction(action, t)\n if (!result.valid) {\n errors.push(translate('business_rules.validation.action.indexError', { index: index + 1, errors: result.errors.join(', ') }))\n }\n })\n\n return {\n valid: errors.length === 0,\n errors,\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["export type TranslatorFn = (key: string, params?: Record<string, any>) => string\n\nexport type Action = {\n type: string\n config?: Record<string, any>\n}\n\nexport type ValidationResult = {\n valid: boolean\n errors: string[]\n}\n\n/**\n * Available action types\n */\nexport const ACTION_TYPES = [\n 'ALLOW_TRANSITION',\n 'BLOCK_TRANSITION',\n 'LOG',\n 'SHOW_ERROR',\n 'SHOW_WARNING',\n 'SHOW_INFO',\n 'NOTIFY',\n 'SET_FIELD',\n 'CALL_WEBHOOK',\n 'CALL_OPEN_MERCATO',\n 'EMIT_EVENT',\n] as const\n\nexport type ActionType = (typeof ACTION_TYPES)[number]\n\n/**\n * Get action type options for dropdown\n */\nexport function getActionTypeOptions(t: TranslatorFn): { value: string; label: string }[] {\n return [\n { value: 'ALLOW_TRANSITION', label: t('business_rules.validation.actionTypes.ALLOW_TRANSITION') },\n { value: 'BLOCK_TRANSITION', label: t('business_rules.validation.actionTypes.BLOCK_TRANSITION') },\n { value: 'LOG', label: t('business_rules.validation.actionTypes.LOG') },\n { value: 'SHOW_ERROR', label: t('business_rules.validation.actionTypes.SHOW_ERROR') },\n { value: 'SHOW_WARNING', label: t('business_rules.validation.actionTypes.SHOW_WARNING') },\n { value: 'SHOW_INFO', label: t('business_rules.validation.actionTypes.SHOW_INFO') },\n { value: 'NOTIFY', label: t('business_rules.validation.actionTypes.NOTIFY') },\n { value: 'SET_FIELD', label: t('business_rules.validation.actionTypes.SET_FIELD') },\n { value: 'CALL_WEBHOOK', label: t('business_rules.validation.actionTypes.CALL_WEBHOOK') },\n { value: 'CALL_OPEN_MERCATO', label: t('business_rules.validation.actionTypes.CALL_OPEN_MERCATO') },\n { value: 'EMIT_EVENT', label: t('business_rules.validation.actionTypes.EMIT_EVENT') },\n ]\n}\n\n/**\n * Get required config fields for an action type\n */\nexport function getRequiredConfigFields(actionType: string): string[] {\n switch (actionType) {\n case 'LOG':\n case 'SHOW_ERROR':\n case 'SHOW_WARNING':\n case 'SHOW_INFO':\n return ['message']\n case 'NOTIFY':\n return ['message', 'recipients']\n case 'SET_FIELD':\n return ['field', 'value']\n case 'CALL_WEBHOOK':\n return ['url']\n case 'CALL_OPEN_MERCATO':\n return ['endpoint', 'method', 'apiKeyId']\n case 'EMIT_EVENT':\n return ['eventName']\n case 'ALLOW_TRANSITION':\n case 'BLOCK_TRANSITION':\n default:\n return []\n }\n}\n\n/**\n * Get optional config fields for an action type\n */\nexport function getOptionalConfigFields(actionType: string): string[] {\n switch (actionType) {\n case 'LOG':\n return ['level']\n case 'NOTIFY':\n return ['template']\n case 'CALL_WEBHOOK':\n return ['method', 'headers', 'body']\n case 'CALL_OPEN_MERCATO':\n return ['body']\n case 'EMIT_EVENT':\n return ['payload']\n default:\n return []\n }\n}\n\n/**\n * Validate a single action\n */\nexport function validateAction(action: Action, t?: TranslatorFn): ValidationResult {\n const errors: string[] = []\n const translate = t || ((key: string) => key)\n\n if (!action) {\n errors.push(translate('business_rules.validation.action.required'))\n return { valid: false, errors }\n }\n\n if (!action.type || typeof action.type !== 'string') {\n errors.push(translate('business_rules.validation.action.typeRequired'))\n } else if (!ACTION_TYPES.includes(action.type as ActionType)) {\n errors.push(translate('business_rules.validation.action.unknownType', { type: action.type, validTypes: ACTION_TYPES.join(', ') }))\n }\n\n const requiredFields = getRequiredConfigFields(action.type)\n if (requiredFields.length > 0) {\n if (!action.config) {\n errors.push(translate('business_rules.validation.action.configRequired', { type: action.type, fields: requiredFields.join(', ') }))\n } else {\n requiredFields.forEach((field) => {\n if (!action.config![field]) {\n errors.push(translate('business_rules.validation.action.fieldMissing', { field }))\n }\n })\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n }\n}\n\n/**\n * Validate action config for a specific type\n */\nexport function validateActionConfig(actionType: string, config: Record<string, any> | undefined, t?: TranslatorFn): ValidationResult {\n const errors: string[] = []\n const translate = t || ((key: string) => key)\n\n const requiredFields = getRequiredConfigFields(actionType)\n if (requiredFields.length > 0 && !config) {\n errors.push(translate('business_rules.validation.action.configRequiredForType', { type: actionType }))\n return { valid: false, errors }\n }\n\n if (config) {\n requiredFields.forEach((field) => {\n if (!config[field]) {\n errors.push(translate('business_rules.validation.action.fieldMissingShort', { field }))\n }\n })\n }\n\n return {\n valid: errors.length === 0,\n errors,\n }\n}\n\n/**\n * Validate array of actions\n */\nexport function validateActions(actions: Action[] | null | undefined, t?: TranslatorFn): ValidationResult {\n if (!actions || actions.length === 0) {\n return { valid: true, errors: [] } // Empty is valid\n }\n\n const errors: string[] = []\n const translate = t || ((key: string) => key)\n\n actions.forEach((action, index) => {\n const result = validateAction(action, t)\n if (!result.valid) {\n errors.push(translate('business_rules.validation.action.indexError', { index: index + 1, errors: result.errors.join(', ') }))\n }\n })\n\n return {\n valid: errors.length === 0,\n errors,\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,4 +1,9 @@
1
1
  import { resolveSpecialValue } from "./value-resolver.js";
2
+ import {
3
+ findOpenMercatoEndpointOption,
4
+ getCurrentOpenMercatoEndpointOptions,
5
+ resolveOpenMercatoApiKeyProfile
6
+ } from "./openmercato-call-options.js";
2
7
  async function executeActions(actions, context) {
3
8
  const startTime = Date.now();
4
9
  const results = [];
@@ -63,6 +68,7 @@ function getActionHandler(actionType) {
63
68
  NOTIFY: handleNotify,
64
69
  SET_FIELD: handleSetField,
65
70
  CALL_WEBHOOK: handleCallWebhook,
71
+ CALL_OPEN_MERCATO: handleCallOpenMercato,
66
72
  EMIT_EVENT: handleEmitEvent
67
73
  };
68
74
  const handler = handlers[actionType];
@@ -176,6 +182,97 @@ async function handleCallWebhook(action, context) {
176
182
  status: "pending"
177
183
  };
178
184
  }
185
+ async function handleCallOpenMercato(action, context) {
186
+ const endpoint = String(action.config?.endpoint ?? "").trim();
187
+ const method = String(action.config?.method ?? "").trim().toUpperCase();
188
+ const apiKeyId = String(action.config?.apiKeyId ?? "").trim();
189
+ if (!endpoint) {
190
+ throw new Error("CALL_OPEN_MERCATO action requires an endpoint");
191
+ }
192
+ if (!method) {
193
+ throw new Error("CALL_OPEN_MERCATO action requires an HTTP method");
194
+ }
195
+ if (!apiKeyId) {
196
+ throw new Error("CALL_OPEN_MERCATO action requires an API key profile");
197
+ }
198
+ const endpointOptions = context.openMercatoEndpointOptions ?? await getCurrentOpenMercatoEndpointOptions();
199
+ const endpointOption = findOpenMercatoEndpointOption(
200
+ endpoint,
201
+ method,
202
+ endpointOptions
203
+ );
204
+ if (!endpointOption) {
205
+ throw new Error("CALL_OPEN_MERCATO action requires a currently available /api/* endpoint");
206
+ }
207
+ const em = context.em;
208
+ if (!em) {
209
+ throw new Error("CALL_OPEN_MERCATO action requires an EntityManager in action context");
210
+ }
211
+ const tenantId = context.tenantId ?? context.tenant?.id;
212
+ const organizationId = context.organizationId ?? context.organization?.id;
213
+ if (!tenantId || !organizationId) {
214
+ throw new Error("CALL_OPEN_MERCATO action requires tenant and organization context");
215
+ }
216
+ const apiKeyProfile = await resolveOpenMercatoApiKeyProfile(em, apiKeyId, {
217
+ tenantId,
218
+ organizationId
219
+ });
220
+ if (!apiKeyProfile) {
221
+ throw new Error("CALL_OPEN_MERCATO action requires an active API key profile in scope");
222
+ }
223
+ const roleIds = Array.isArray(apiKeyProfile.rolesJson) ? apiKeyProfile.rolesJson.filter((roleId) => typeof roleId === "string" && roleId.length > 0) : [];
224
+ if (roleIds.length === 0) {
225
+ throw new Error("CALL_OPEN_MERCATO action requires an API key profile with at least one role");
226
+ }
227
+ const { withOnetimeApiKey } = await import("../../api_keys/services/apiKeyService.js");
228
+ const fullUrl = buildOpenMercatoApiUrl(endpointOption.path);
229
+ const requestBody = method === "GET" ? void 0 : normalizeOpenMercatoRequestBody(action.config?.body, context);
230
+ return await withOnetimeApiKey(
231
+ em,
232
+ {
233
+ name: `__business_rule_${context.ruleId || "unknown"}__`,
234
+ description: `One-time key for business rule ${context.ruleId || "unknown"}`,
235
+ tenantId,
236
+ organizationId,
237
+ roles: roleIds,
238
+ createdBy: null,
239
+ expiresAt: null
240
+ },
241
+ async (apiKeySecret) => {
242
+ const headers = {
243
+ "Content-Type": "application/json",
244
+ "Authorization": `apikey ${apiKeySecret}`,
245
+ "X-Tenant-Id": tenantId,
246
+ "X-Organization-Id": organizationId
247
+ };
248
+ if (context.ruleId) headers["X-Business-Rule-Id"] = context.ruleId;
249
+ if (context.ruleName) headers["X-Business-Rule-Name"] = context.ruleName;
250
+ if (context.entityType) headers["X-Business-Rule-Entity-Type"] = context.entityType;
251
+ if (context.entityId) headers["X-Business-Rule-Entity-Id"] = context.entityId;
252
+ const response = await fetch(fullUrl, {
253
+ method,
254
+ headers,
255
+ body: requestBody === void 0 ? void 0 : JSON.stringify(requestBody)
256
+ });
257
+ const responseBody = await parseOpenMercatoResponseBody(response);
258
+ if (!response.ok) {
259
+ throwOpenMercatoResponseError(response.status);
260
+ }
261
+ return {
262
+ type: "CALL_OPEN_MERCATO",
263
+ endpoint: endpointOption.path,
264
+ method,
265
+ apiKeyId,
266
+ status: response.status,
267
+ statusText: response.statusText,
268
+ body: responseBody,
269
+ authenticated: true,
270
+ tenantId,
271
+ organizationId
272
+ };
273
+ }
274
+ );
275
+ }
179
276
  async function handleEmitEvent(action, context) {
180
277
  const eventName = action.config?.event;
181
278
  const payload = action.config?.payload || {};
@@ -213,6 +310,57 @@ function resolveValue(value, context) {
213
310
  }
214
311
  return value;
215
312
  }
313
+ function buildOpenMercatoApiUrl(endpoint) {
314
+ if (!endpoint.startsWith("/api/")) {
315
+ throw new Error(`CALL_OPEN_MERCATO only supports /api/* paths, got: ${endpoint}`);
316
+ }
317
+ const appUrl = (process.env.APP_URL || "http://localhost:3000").replace(/\/$/, "");
318
+ return `${appUrl}${endpoint}`;
319
+ }
320
+ function normalizeOpenMercatoRequestBody(value, context) {
321
+ if (value === void 0 || value === null || value === "") return void 0;
322
+ const interpolated = interpolateActionValue(value, context);
323
+ if (typeof interpolated !== "string") return interpolated;
324
+ const trimmed = interpolated.trim();
325
+ if (!trimmed) return void 0;
326
+ try {
327
+ return JSON.parse(trimmed);
328
+ } catch {
329
+ return interpolated;
330
+ }
331
+ }
332
+ function interpolateActionValue(value, context) {
333
+ if (typeof value === "string") {
334
+ return interpolateMessage(value, context);
335
+ }
336
+ if (Array.isArray(value)) {
337
+ return value.map((item) => interpolateActionValue(item, context));
338
+ }
339
+ if (value && typeof value === "object") {
340
+ return Object.fromEntries(
341
+ Object.entries(value).map(([key, entry]) => [key, interpolateActionValue(entry, context)])
342
+ );
343
+ }
344
+ return value;
345
+ }
346
+ async function parseOpenMercatoResponseBody(response) {
347
+ const contentType = response.headers.get("content-type");
348
+ try {
349
+ if (contentType && contentType.includes("application/json")) {
350
+ return await response.json();
351
+ }
352
+ return await response.text();
353
+ } catch {
354
+ return null;
355
+ }
356
+ }
357
+ function throwOpenMercatoResponseError(status) {
358
+ const error = new Error(`CALL_OPEN_MERCATO request failed with status ${status}`);
359
+ if (status >= 500) {
360
+ error.retriable = true;
361
+ }
362
+ throw error;
363
+ }
216
364
  export {
217
365
  executeAction,
218
366
  executeActions,