@open-mercato/core 0.6.7-develop.6795.1.8a3f27921c → 0.6.7-develop.6824.1.21fff90682

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 (228) 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/auth/lib/backendChrome.js +10 -9
  9. package/dist/modules/auth/lib/backendChrome.js.map +2 -2
  10. package/dist/modules/auth/lib/tenantAccess.js +7 -0
  11. package/dist/modules/auth/lib/tenantAccess.js.map +2 -2
  12. package/dist/modules/business_rules/api/openmercato-call-options/route.js +85 -0
  13. package/dist/modules/business_rules/api/openmercato-call-options/route.js.map +7 -0
  14. package/dist/modules/business_rules/api/rules/route.js +71 -4
  15. package/dist/modules/business_rules/api/rules/route.js.map +2 -2
  16. package/dist/modules/business_rules/components/ActionBuilder.js +47 -4
  17. package/dist/modules/business_rules/components/ActionBuilder.js.map +3 -3
  18. package/dist/modules/business_rules/components/ActionRow.js +106 -16
  19. package/dist/modules/business_rules/components/ActionRow.js.map +2 -2
  20. package/dist/modules/business_rules/components/utils/actionValidation.js +6 -0
  21. package/dist/modules/business_rules/components/utils/actionValidation.js.map +2 -2
  22. package/dist/modules/business_rules/lib/action-executor.js +148 -0
  23. package/dist/modules/business_rules/lib/action-executor.js.map +2 -2
  24. package/dist/modules/business_rules/lib/openmercato-call-options-types.js +5 -0
  25. package/dist/modules/business_rules/lib/openmercato-call-options-types.js.map +7 -0
  26. package/dist/modules/business_rules/lib/openmercato-call-options.js +231 -0
  27. package/dist/modules/business_rules/lib/openmercato-call-options.js.map +7 -0
  28. package/dist/modules/business_rules/lib/rule-engine.js +5 -1
  29. package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
  30. package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js +11 -1
  31. package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js.map +2 -2
  32. package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js +11 -6
  33. package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js.map +2 -2
  34. package/dist/modules/configs/lib/upgrade-actions.js +12 -0
  35. package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
  36. package/dist/modules/customer_accounts/api/admin/users/[id].js +10 -1
  37. package/dist/modules/customer_accounts/api/admin/users/[id].js.map +2 -2
  38. package/dist/modules/customer_accounts/api/admin/users-invite.js +61 -4
  39. package/dist/modules/customer_accounts/api/admin/users-invite.js.map +2 -2
  40. package/dist/modules/customer_accounts/api/portal/users-invite.js +20 -2
  41. package/dist/modules/customer_accounts/api/portal/users-invite.js.map +2 -2
  42. package/dist/modules/customer_accounts/data/entities.js +3 -0
  43. package/dist/modules/customer_accounts/data/entities.js.map +2 -2
  44. package/dist/modules/customer_accounts/data/validators.js +1 -0
  45. package/dist/modules/customer_accounts/data/validators.js.map +2 -2
  46. package/dist/modules/customer_accounts/emails/CustomerInvitationEmail.js +26 -0
  47. package/dist/modules/customer_accounts/emails/CustomerInvitationEmail.js.map +7 -0
  48. package/dist/modules/customer_accounts/lib/customerEntityOwnership.js +29 -3
  49. package/dist/modules/customer_accounts/lib/customerEntityOwnership.js.map +2 -2
  50. package/dist/modules/customer_accounts/lib/customerUrl.js +19 -10
  51. package/dist/modules/customer_accounts/lib/customerUrl.js.map +2 -2
  52. package/dist/modules/customer_accounts/lib/invitationEmail.js +35 -0
  53. package/dist/modules/customer_accounts/lib/invitationEmail.js.map +7 -0
  54. package/dist/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.js +13 -0
  55. package/dist/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.js.map +7 -0
  56. package/dist/modules/customer_accounts/services/customerInvitationService.js +32 -2
  57. package/dist/modules/customer_accounts/services/customerInvitationService.js.map +2 -2
  58. package/dist/modules/customer_accounts/subscribers/autoLinkCrm.js +47 -7
  59. package/dist/modules/customer_accounts/subscribers/autoLinkCrm.js.map +2 -2
  60. package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js +2 -2
  61. package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js.map +2 -2
  62. package/dist/modules/customer_accounts/widgets/injection-table.js +1 -1
  63. package/dist/modules/customer_accounts/widgets/injection-table.js.map +2 -2
  64. package/dist/modules/customers/api/deals/[id]/people/route.js +4 -2
  65. package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
  66. package/dist/modules/customers/api/deals/[id]/route.js +7 -3
  67. package/dist/modules/customers/api/deals/[id]/route.js.map +2 -2
  68. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +11 -1
  69. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  70. package/dist/modules/customers/backend/customers/deals/[id]/page.js +14 -8
  71. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  72. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +21 -6
  73. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  74. package/dist/modules/customers/commands/deals.js +48 -10
  75. package/dist/modules/customers/commands/deals.js.map +2 -2
  76. package/dist/modules/customers/commands/people.js +2 -0
  77. package/dist/modules/customers/commands/people.js.map +2 -2
  78. package/dist/modules/customers/components/detail/CompanyDetailTabs.js +26 -6
  79. package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +2 -2
  80. package/dist/modules/customers/components/detail/DealDetailTabs.js +30 -8
  81. package/dist/modules/customers/components/detail/DealDetailTabs.js.map +2 -2
  82. package/dist/modules/customers/components/detail/PersonDetailTabs.js +30 -8
  83. package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
  84. package/dist/modules/customers/data/entities.js +8 -0
  85. package/dist/modules/customers/data/entities.js.map +2 -2
  86. package/dist/modules/customers/data/validators.js +2 -1
  87. package/dist/modules/customers/data/validators.js.map +2 -2
  88. package/dist/modules/customers/migrations/Migration20260723210000_customers.js +15 -0
  89. package/dist/modules/customers/migrations/Migration20260723210000_customers.js.map +7 -0
  90. package/dist/modules/directory/api/tenants/route.js +8 -2
  91. package/dist/modules/directory/api/tenants/route.js.map +2 -2
  92. package/dist/modules/directory/commands/tenants.js +6 -0
  93. package/dist/modules/directory/commands/tenants.js.map +2 -2
  94. package/dist/modules/entities/api/entity-settings.js +59 -9
  95. package/dist/modules/entities/api/entity-settings.js.map +2 -2
  96. package/dist/modules/entities/backend/config/settings/page.js +10 -0
  97. package/dist/modules/entities/backend/config/settings/page.js.map +7 -0
  98. package/dist/modules/entities/backend/config/settings/page.meta.js +36 -0
  99. package/dist/modules/entities/backend/config/settings/page.meta.js.map +7 -0
  100. package/dist/modules/entities/backend/entities/user/create/page.js +16 -7
  101. package/dist/modules/entities/backend/entities/user/create/page.js.map +2 -2
  102. package/dist/modules/entities/components/EntitySettingsManager.js +136 -0
  103. package/dist/modules/entities/components/EntitySettingsManager.js.map +7 -0
  104. package/dist/modules/inbox_ops/api/webhook/inbound.js +14 -10
  105. package/dist/modules/inbox_ops/api/webhook/inbound.js.map +2 -2
  106. package/dist/modules/payment_gateways/api/sessions/route.js +1 -3
  107. package/dist/modules/payment_gateways/api/sessions/route.js.map +2 -2
  108. package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +11 -1
  109. package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +2 -2
  110. package/dist/modules/payment_gateways/data/entities.js +4 -0
  111. package/dist/modules/payment_gateways/data/entities.js.map +2 -2
  112. package/dist/modules/payment_gateways/lib/gateway-service.js +15 -6
  113. package/dist/modules/payment_gateways/lib/gateway-service.js.map +2 -2
  114. package/dist/modules/payment_gateways/lib/session-idempotency.js +33 -0
  115. package/dist/modules/payment_gateways/lib/session-idempotency.js.map +2 -2
  116. package/dist/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.js +18 -0
  117. package/dist/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.js.map +7 -0
  118. package/dist/modules/payment_gateways/setup.js +47 -0
  119. package/dist/modules/payment_gateways/setup.js.map +2 -2
  120. package/dist/modules/payment_gateways/workers/session-initialization-prune.js +50 -0
  121. package/dist/modules/payment_gateways/workers/session-initialization-prune.js.map +7 -0
  122. package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.js +134 -0
  123. package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.js.map +7 -0
  124. package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.js +11 -0
  125. package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.js.map +7 -0
  126. package/dist/modules/portal/lib/navigation.js +7 -0
  127. package/dist/modules/portal/lib/navigation.js.map +7 -0
  128. package/dist/modules/query_index/lib/engine.js +43 -0
  129. package/dist/modules/query_index/lib/engine.js.map +2 -2
  130. package/dist/modules/query_index/lib/search-tokens.js +15 -5
  131. package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
  132. package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js +11 -1
  133. package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js.map +2 -2
  134. package/generated/entities/customer_deal_person_link/index.ts +1 -0
  135. package/generated/entities/customer_user_invitation/index.ts +1 -0
  136. package/generated/entity-fields-registry.ts +2 -0
  137. package/package.json +7 -7
  138. package/src/modules/auth/lib/backendChrome.tsx +15 -9
  139. package/src/modules/auth/lib/tenantAccess.ts +8 -0
  140. package/src/modules/business_rules/api/openmercato-call-options/route.ts +94 -0
  141. package/src/modules/business_rules/api/rules/route.ts +92 -4
  142. package/src/modules/business_rules/components/ActionBuilder.tsx +54 -5
  143. package/src/modules/business_rules/components/ActionRow.tsx +156 -18
  144. package/src/modules/business_rules/components/utils/actionValidation.ts +6 -0
  145. package/src/modules/business_rules/i18n/de.json +12 -0
  146. package/src/modules/business_rules/i18n/en.json +12 -0
  147. package/src/modules/business_rules/i18n/es.json +12 -0
  148. package/src/modules/business_rules/i18n/pl.json +12 -0
  149. package/src/modules/business_rules/lib/action-executor.ts +198 -0
  150. package/src/modules/business_rules/lib/openmercato-call-options-types.ts +31 -0
  151. package/src/modules/business_rules/lib/openmercato-call-options.ts +297 -0
  152. package/src/modules/business_rules/lib/rule-engine.ts +4 -0
  153. package/src/modules/communication_channels/api/post/webhook/[provider]/route.ts +11 -1
  154. package/src/modules/communication_channels/api/post/webhooks/gmail/route.ts +17 -11
  155. package/src/modules/configs/lib/upgrade-actions.ts +14 -0
  156. package/src/modules/customer_accounts/api/admin/users/[id].ts +16 -1
  157. package/src/modules/customer_accounts/api/admin/users-invite.ts +78 -3
  158. package/src/modules/customer_accounts/api/portal/users-invite.ts +22 -1
  159. package/src/modules/customer_accounts/data/entities.ts +3 -0
  160. package/src/modules/customer_accounts/data/validators.ts +1 -0
  161. package/src/modules/customer_accounts/emails/CustomerInvitationEmail.tsx +45 -0
  162. package/src/modules/customer_accounts/i18n/de.json +6 -0
  163. package/src/modules/customer_accounts/i18n/en.json +6 -0
  164. package/src/modules/customer_accounts/i18n/es.json +6 -0
  165. package/src/modules/customer_accounts/i18n/pl.json +6 -0
  166. package/src/modules/customer_accounts/lib/customerEntityOwnership.ts +68 -2
  167. package/src/modules/customer_accounts/lib/customerUrl.ts +27 -11
  168. package/src/modules/customer_accounts/lib/invitationEmail.ts +42 -0
  169. package/src/modules/customer_accounts/migrations/.snapshot-open-mercato.json +16 -0
  170. package/src/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.ts +13 -0
  171. package/src/modules/customer_accounts/services/customerInvitationService.ts +56 -3
  172. package/src/modules/customer_accounts/subscribers/autoLinkCrm.ts +75 -8
  173. package/src/modules/customer_accounts/widgets/injection/account-status/widget.client.tsx +2 -2
  174. package/src/modules/customer_accounts/widgets/injection-table.ts +4 -1
  175. package/src/modules/customers/api/deals/[id]/people/route.ts +3 -0
  176. package/src/modules/customers/api/deals/[id]/route.ts +10 -2
  177. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +12 -1
  178. package/src/modules/customers/backend/customers/deals/[id]/hooks/types.ts +1 -0
  179. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +15 -9
  180. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +24 -6
  181. package/src/modules/customers/commands/deals.ts +50 -9
  182. package/src/modules/customers/commands/people.ts +3 -0
  183. package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +30 -7
  184. package/src/modules/customers/components/detail/DealDetailTabs.tsx +34 -9
  185. package/src/modules/customers/components/detail/PersonDetailTabs.tsx +34 -9
  186. package/src/modules/customers/data/entities.ts +9 -1
  187. package/src/modules/customers/data/validators.ts +1 -0
  188. package/src/modules/customers/i18n/de.json +1 -0
  189. package/src/modules/customers/i18n/en.json +1 -0
  190. package/src/modules/customers/i18n/es.json +1 -0
  191. package/src/modules/customers/i18n/pl.json +1 -0
  192. package/src/modules/customers/migrations/.snapshot-open-mercato.json +27 -1
  193. package/src/modules/customers/migrations/Migration20260723210000_customers.ts +15 -0
  194. package/src/modules/directory/api/tenants/route.ts +9 -1
  195. package/src/modules/directory/commands/tenants.ts +6 -0
  196. package/src/modules/entities/api/entity-settings.ts +66 -22
  197. package/src/modules/entities/backend/config/settings/page.meta.ts +34 -0
  198. package/src/modules/entities/backend/config/settings/page.tsx +12 -0
  199. package/src/modules/entities/backend/entities/user/create/page.tsx +16 -7
  200. package/src/modules/entities/components/EntitySettingsManager.tsx +160 -0
  201. package/src/modules/entities/i18n/de.json +9 -0
  202. package/src/modules/entities/i18n/en.json +9 -0
  203. package/src/modules/entities/i18n/es.json +9 -0
  204. package/src/modules/entities/i18n/pl.json +9 -0
  205. package/src/modules/inbox_ops/api/webhook/inbound.ts +14 -12
  206. package/src/modules/payment_gateways/api/sessions/route.ts +1 -3
  207. package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +13 -1
  208. package/src/modules/payment_gateways/data/entities.ts +5 -0
  209. package/src/modules/payment_gateways/i18n/de.json +5 -1
  210. package/src/modules/payment_gateways/i18n/en.json +5 -1
  211. package/src/modules/payment_gateways/i18n/es.json +5 -1
  212. package/src/modules/payment_gateways/i18n/pl.json +5 -1
  213. package/src/modules/payment_gateways/lib/gateway-service.ts +17 -8
  214. package/src/modules/payment_gateways/lib/session-idempotency.ts +36 -0
  215. package/src/modules/payment_gateways/migrations/.snapshot-open-mercato.json +10 -1
  216. package/src/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.ts +17 -0
  217. package/src/modules/payment_gateways/setup.ts +62 -0
  218. package/src/modules/payment_gateways/workers/session-initialization-prune.ts +63 -0
  219. package/src/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.ts +9 -0
  220. package/src/modules/portal/frontend/[orgSlug]/portal/invite/page.tsx +164 -0
  221. package/src/modules/portal/i18n/de.json +18 -0
  222. package/src/modules/portal/i18n/en.json +18 -0
  223. package/src/modules/portal/i18n/es.json +18 -0
  224. package/src/modules/portal/i18n/pl.json +18 -0
  225. package/src/modules/portal/lib/navigation.ts +3 -0
  226. package/src/modules/query_index/lib/engine.ts +52 -0
  227. package/src/modules/query_index/lib/search-tokens.ts +16 -4
  228. package/src/modules/shipping_carriers/api/webhook/[provider]/route.ts +11 -1
@@ -0,0 +1,134 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useCallback, useMemo, useState, useEffect } from "react";
4
+ import { useSearchParams } from "next/navigation";
5
+ import Link from "next/link";
6
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
7
+ import { PasswordInput } from "@open-mercato/ui/primitives/password-input";
8
+ import { Input } from "@open-mercato/ui/primitives/input";
9
+ import { Label } from "@open-mercato/ui/primitives/label";
10
+ import { Button } from "@open-mercato/ui/primitives/button";
11
+ import { Alert, AlertDescription } from "@open-mercato/ui/primitives/alert";
12
+ import { EmptyState } from "@open-mercato/ui/primitives/empty-state";
13
+ import { SearchX } from "lucide-react";
14
+ import { Spinner } from "@open-mercato/ui/primitives/spinner";
15
+ import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
16
+ import { usePortalContext } from "@open-mercato/ui/portal/PortalContext";
17
+ import { InjectionSpot } from "@open-mercato/ui/backend/injection/InjectionSpot";
18
+ import { PortalInjectionSpots } from "@open-mercato/ui/backend/injection/spotIds";
19
+ import { navigateWithPageReload } from "@open-mercato/core/modules/portal/lib/navigation";
20
+ function PortalInvitePage({ params }) {
21
+ const t = useT();
22
+ const orgSlug = params.orgSlug;
23
+ const { tenant } = usePortalContext();
24
+ const searchParams = useSearchParams();
25
+ const [displayName, setDisplayName] = useState("");
26
+ const [password, setPassword] = useState("");
27
+ const [confirmPassword, setConfirmPassword] = useState("");
28
+ const [error, setError] = useState(null);
29
+ const [submitting, setSubmitting] = useState(false);
30
+ const [token, setToken] = useState(null);
31
+ useEffect(() => {
32
+ const tokenParam = searchParams.get("token");
33
+ if (!tokenParam) {
34
+ setError(t("portal.invite.error.noToken", "Invalid or missing invitation token."));
35
+ } else {
36
+ setToken(tokenParam);
37
+ }
38
+ }, [searchParams, t]);
39
+ const handleSubmit = useCallback(
40
+ async (event) => {
41
+ event.preventDefault();
42
+ setError(null);
43
+ if (!token) {
44
+ setError(t("portal.invite.error.noToken", "Invalid or missing invitation token."));
45
+ return;
46
+ }
47
+ if (!displayName.trim()) {
48
+ setError(t("portal.invite.error.displayNameRequired", "Display name is required."));
49
+ return;
50
+ }
51
+ if (password !== confirmPassword) {
52
+ setError(t("portal.invite.error.passwordMismatch", "Passwords do not match."));
53
+ return;
54
+ }
55
+ if (password.length < 8) {
56
+ setError(t("portal.invite.error.passwordTooShort", "Password must be at least 8 characters long."));
57
+ return;
58
+ }
59
+ setSubmitting(true);
60
+ try {
61
+ const result = await apiCall("/api/customer_accounts/invitations/accept", {
62
+ method: "POST",
63
+ headers: { "Content-Type": "application/json" },
64
+ body: JSON.stringify({ token, password, displayName: displayName.trim() })
65
+ });
66
+ if (result.ok && result.result?.ok) {
67
+ navigateWithPageReload(`/${orgSlug}/portal/dashboard`);
68
+ return;
69
+ }
70
+ if (result.status === 400) {
71
+ setError(t("portal.invite.error.invalidToken", "Invalid or expired invitation."));
72
+ } else {
73
+ setError(result.result?.error || t("portal.invite.error.generic", "Invitation acceptance failed. Please try again."));
74
+ }
75
+ } catch {
76
+ setError(t("portal.invite.error.generic", "Invitation acceptance failed. Please try again."));
77
+ } finally {
78
+ setSubmitting(false);
79
+ }
80
+ },
81
+ [token, password, confirmPassword, displayName, orgSlug, t]
82
+ );
83
+ const injectionContext = useMemo(
84
+ () => ({ orgSlug }),
85
+ [orgSlug]
86
+ );
87
+ if (tenant.loading) {
88
+ return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ jsx(Spinner, {}) });
89
+ }
90
+ if (tenant.error) {
91
+ return /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-md py-12", children: /* @__PURE__ */ jsx(
92
+ EmptyState,
93
+ {
94
+ variant: "subtle",
95
+ size: "lg",
96
+ icon: /* @__PURE__ */ jsx(SearchX, { className: "h-6 w-6", "aria-hidden": true }),
97
+ title: t("portal.org.invalid", "Organization not found.")
98
+ }
99
+ ) });
100
+ }
101
+ return /* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-sm", children: [
102
+ /* @__PURE__ */ jsxs("div", { className: "mb-8 text-center", children: [
103
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold tracking-tight", children: t("portal.invite.title", "Accept Invitation") }),
104
+ /* @__PURE__ */ jsx("p", { className: "mt-1.5 text-sm text-muted-foreground", children: t("portal.invite.description", "Create your portal account to accept this invitation.") })
105
+ ] }),
106
+ /* @__PURE__ */ jsx(InjectionSpot, { spotId: PortalInjectionSpots.pageBefore("invite"), context: injectionContext }),
107
+ /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "flex flex-col gap-4", children: [
108
+ error ? /* @__PURE__ */ jsx(Alert, { variant: "destructive", children: /* @__PURE__ */ jsx(AlertDescription, { children: error }) }) : null,
109
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
110
+ /* @__PURE__ */ jsx(Label, { htmlFor: "invite-display-name", className: "text-overline font-semibold uppercase tracking-wider text-muted-foreground/70", children: t("portal.invite.displayName", "Display Name") }),
111
+ /* @__PURE__ */ jsx(Input, { id: "invite-display-name", autoComplete: "name", required: true, value: displayName, onChange: (e) => setDisplayName(e.target.value), disabled: submitting || !token, className: "rounded-lg" })
112
+ ] }),
113
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
114
+ /* @__PURE__ */ jsx(Label, { htmlFor: "invite-password", className: "text-overline font-semibold uppercase tracking-wider text-muted-foreground/70", children: t("portal.invite.password", "Password") }),
115
+ /* @__PURE__ */ jsx(PasswordInput, { id: "invite-password", autoComplete: "new-password", required: true, placeholder: t("portal.invite.password.placeholder", "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"), value: password, onChange: (e) => setPassword(e.target.value), disabled: submitting || !token, className: "rounded-lg" })
116
+ ] }),
117
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
118
+ /* @__PURE__ */ jsx(Label, { htmlFor: "invite-confirm-password", className: "text-overline font-semibold uppercase tracking-wider text-muted-foreground/70", children: t("portal.invite.confirmPassword", "Confirm Password") }),
119
+ /* @__PURE__ */ jsx(PasswordInput, { id: "invite-confirm-password", autoComplete: "new-password", required: true, placeholder: t("portal.invite.confirmPassword.placeholder", "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"), value: confirmPassword, onChange: (e) => setConfirmPassword(e.target.value), disabled: submitting || !token, className: "rounded-lg" })
120
+ ] }),
121
+ /* @__PURE__ */ jsx(Button, { type: "submit", disabled: submitting || !token, className: "mt-1 w-full rounded-lg", children: submitting ? t("portal.invite.submitting", "Accepting invitation...") : t("portal.invite.submit", "Accept Invitation") }),
122
+ /* @__PURE__ */ jsxs("p", { className: "text-center text-sm text-muted-foreground", children: [
123
+ t("portal.invite.backToLogin", "Already have an account?"),
124
+ " ",
125
+ /* @__PURE__ */ jsx(Link, { href: `/${orgSlug}/portal/login`, className: "font-medium text-foreground underline underline-offset-4 hover:opacity-80", children: t("portal.invite.loginLink", "Sign in") })
126
+ ] })
127
+ ] }),
128
+ /* @__PURE__ */ jsx(InjectionSpot, { spotId: PortalInjectionSpots.pageAfter("invite"), context: injectionContext })
129
+ ] });
130
+ }
131
+ export {
132
+ PortalInvitePage as default
133
+ };
134
+ //# sourceMappingURL=page.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../src/modules/portal/frontend/%5BorgSlug%5D/portal/invite/page.tsx"],
4
+ "sourcesContent": ["\"use client\"\nimport { useCallback, useMemo, useState, useEffect } from 'react'\nimport { useSearchParams } from 'next/navigation'\nimport Link from 'next/link'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { PasswordInput } from '@open-mercato/ui/primitives/password-input'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { EmptyState } from '@open-mercato/ui/primitives/empty-state'\nimport { SearchX } from 'lucide-react'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { usePortalContext } from '@open-mercato/ui/portal/PortalContext'\nimport { InjectionSpot } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { PortalInjectionSpots } from '@open-mercato/ui/backend/injection/spotIds'\nimport { navigateWithPageReload } from '@open-mercato/core/modules/portal/lib/navigation'\n\ntype Props = { params: { orgSlug: string } }\n\nexport default function PortalInvitePage({ params }: Props) {\n const t = useT()\n const orgSlug = params.orgSlug\n const { tenant } = usePortalContext()\n const searchParams = useSearchParams()\n\n const [displayName, setDisplayName] = useState('')\n const [password, setPassword] = useState('')\n const [confirmPassword, setConfirmPassword] = useState('')\n const [error, setError] = useState<string | null>(null)\n const [submitting, setSubmitting] = useState(false)\n const [token, setToken] = useState<string | null>(null)\n\n useEffect(() => {\n const tokenParam = searchParams.get('token')\n if (!tokenParam) {\n setError(t('portal.invite.error.noToken', 'Invalid or missing invitation token.'))\n } else {\n setToken(tokenParam)\n }\n }, [searchParams, t])\n\n const handleSubmit = useCallback(\n async (event: React.FormEvent) => {\n event.preventDefault()\n setError(null)\n\n if (!token) {\n setError(t('portal.invite.error.noToken', 'Invalid or missing invitation token.'))\n return\n }\n\n if (!displayName.trim()) {\n setError(t('portal.invite.error.displayNameRequired', 'Display name is required.'))\n return\n }\n\n if (password !== confirmPassword) {\n setError(t('portal.invite.error.passwordMismatch', 'Passwords do not match.'))\n return\n }\n\n if (password.length < 8) {\n setError(t('portal.invite.error.passwordTooShort', 'Password must be at least 8 characters long.'))\n return\n }\n\n setSubmitting(true)\n try {\n const result = await apiCall<{ ok: boolean; error?: string }>('/api/customer_accounts/invitations/accept', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token, password, displayName: displayName.trim() }),\n })\n\n if (result.ok && result.result?.ok) {\n navigateWithPageReload(`/${orgSlug}/portal/dashboard`)\n return\n }\n\n if (result.status === 400) {\n setError(t('portal.invite.error.invalidToken', 'Invalid or expired invitation.'))\n } else {\n setError(result.result?.error || t('portal.invite.error.generic', 'Invitation acceptance failed. Please try again.'))\n }\n } catch {\n setError(t('portal.invite.error.generic', 'Invitation acceptance failed. Please try again.'))\n } finally {\n setSubmitting(false)\n }\n },\n [token, password, confirmPassword, displayName, orgSlug, t],\n )\n\n const injectionContext = useMemo(\n () => ({ orgSlug }),\n [orgSlug],\n )\n\n if (tenant.loading) {\n return <div className=\"flex items-center justify-center py-20\"><Spinner /></div>\n }\n\n if (tenant.error) {\n return (\n <div className=\"mx-auto w-full max-w-md py-12\">\n <EmptyState\n variant=\"subtle\"\n size=\"lg\"\n icon={<SearchX className=\"h-6 w-6\" aria-hidden />}\n title={t('portal.org.invalid', 'Organization not found.')}\n />\n </div>\n )\n }\n\n return (\n <div className=\"mx-auto w-full max-w-sm\">\n <div className=\"mb-8 text-center\">\n <h1 className=\"text-2xl font-bold tracking-tight\">{t('portal.invite.title', 'Accept Invitation')}</h1>\n <p className=\"mt-1.5 text-sm text-muted-foreground\">{t('portal.invite.description', 'Create your portal account to accept this invitation.')}</p>\n </div>\n\n <InjectionSpot spotId={PortalInjectionSpots.pageBefore('invite')} context={injectionContext} />\n\n <form onSubmit={handleSubmit} className=\"flex flex-col gap-4\">\n {error ? (\n <Alert variant=\"destructive\">\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n ) : null}\n\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor=\"invite-display-name\" className=\"text-overline font-semibold uppercase tracking-wider text-muted-foreground/70\">{t('portal.invite.displayName', 'Display Name')}</Label>\n <Input id=\"invite-display-name\" autoComplete=\"name\" required value={displayName} onChange={(e) => setDisplayName(e.target.value)} disabled={submitting || !token} className=\"rounded-lg\" />\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor=\"invite-password\" className=\"text-overline font-semibold uppercase tracking-wider text-muted-foreground/70\">{t('portal.invite.password', 'Password')}</Label>\n <PasswordInput id=\"invite-password\" autoComplete=\"new-password\" required placeholder={t('portal.invite.password.placeholder', '\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022')} value={password} onChange={(e) => setPassword(e.target.value)} disabled={submitting || !token} className=\"rounded-lg\" />\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor=\"invite-confirm-password\" className=\"text-overline font-semibold uppercase tracking-wider text-muted-foreground/70\">{t('portal.invite.confirmPassword', 'Confirm Password')}</Label>\n <PasswordInput id=\"invite-confirm-password\" autoComplete=\"new-password\" required placeholder={t('portal.invite.confirmPassword.placeholder', '\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022')} value={confirmPassword} onChange={(e) => setConfirmPassword(e.target.value)} disabled={submitting || !token} className=\"rounded-lg\" />\n </div>\n\n <Button type=\"submit\" disabled={submitting || !token} className=\"mt-1 w-full rounded-lg\">\n {submitting ? t('portal.invite.submitting', 'Accepting invitation...') : t('portal.invite.submit', 'Accept Invitation')}\n </Button>\n\n <p className=\"text-center text-sm text-muted-foreground\">\n {t('portal.invite.backToLogin', 'Already have an account?')}{' '}\n <Link href={`/${orgSlug}/portal/login`} className=\"font-medium text-foreground underline underline-offset-4 hover:opacity-80\">\n {t('portal.invite.loginLink', 'Sign in')}\n </Link>\n </p>\n </form>\n\n <InjectionSpot spotId={PortalInjectionSpots.pageAfter('invite')} context={injectionContext} />\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,11 @@
1
+ const metadata = {
2
+ titleKey: "portal.nav.invite",
3
+ title: "Accept Invitation",
4
+ navHidden: true
5
+ };
6
+ var page_meta_default = metadata;
7
+ export {
8
+ page_meta_default as default,
9
+ metadata
10
+ };
11
+ //# sourceMappingURL=page.meta.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../src/modules/portal/frontend/%5BorgSlug%5D/portal/invite/page.meta.ts"],
4
+ "sourcesContent": ["import type { PageMetadata } from '@open-mercato/shared/modules/registry'\n\nexport const metadata: PageMetadata = {\n titleKey: 'portal.nav.invite',\n title: 'Accept Invitation',\n navHidden: true,\n}\n\nexport default metadata\n"],
5
+ "mappings": "AAEO,MAAM,WAAyB;AAAA,EACpC,UAAU;AAAA,EACV,OAAO;AAAA,EACP,WAAW;AACb;AAEA,IAAO,oBAAQ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,7 @@
1
+ function navigateWithPageReload(path) {
2
+ window.location.assign(path);
3
+ }
4
+ export {
5
+ navigateWithPageReload
6
+ };
7
+ //# sourceMappingURL=navigation.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/portal/lib/navigation.ts"],
4
+ "sourcesContent": ["export function navigateWithPageReload(path: string): void {\n window.location.assign(path)\n}\n"],
5
+ "mappings": "AAAO,SAAS,uBAAuB,MAAoB;AACzD,SAAO,SAAS,OAAO,IAAI;AAC7B;",
6
+ "names": []
7
+ }
@@ -24,8 +24,36 @@ import { warnOnCiphertextLikeFallback } from "@open-mercato/shared/lib/query/cip
24
24
  import { resolveEncryptedSortFields, resolveEncryptedSortMaxRows, sortRowsInMemory } from "@open-mercato/shared/lib/query/encrypted-sort";
25
25
  import { mapWithConcurrency } from "@open-mercato/shared/lib/query/bounded-decrypt";
26
26
  import { createLogger } from "@open-mercato/shared/lib/logger";
27
+ import { parseNumberWithDefault } from "@open-mercato/shared/lib/number";
27
28
  const logger = createLogger("query_index").child({ component: "engine" });
28
29
  const DECRYPT_CONCURRENCY = 8;
30
+ const AUTO_REINDEX_DEBOUNCE_DEFAULT_MS = 3e4;
31
+ const AUTO_REINDEX_DEBOUNCE_MAX_SCOPES = 1e4;
32
+ const AUTO_REINDEX_SCHEDULED_AT_KEY = /* @__PURE__ */ Symbol.for("@open-mercato/query-index/auto-reindex-scheduled-at");
33
+ function getAutoReindexScheduledAt() {
34
+ const globalScope = globalThis;
35
+ if (!globalScope[AUTO_REINDEX_SCHEDULED_AT_KEY]) {
36
+ globalScope[AUTO_REINDEX_SCHEDULED_AT_KEY] = /* @__PURE__ */ new Map();
37
+ }
38
+ return globalScope[AUTO_REINDEX_SCHEDULED_AT_KEY];
39
+ }
40
+ function markAutoReindexScheduled(key, debounceMs, now) {
41
+ const autoReindexScheduledAt = getAutoReindexScheduledAt();
42
+ const previous = autoReindexScheduledAt.get(key);
43
+ if (previous !== void 0 && now - previous < debounceMs) return false;
44
+ if (autoReindexScheduledAt.size >= AUTO_REINDEX_DEBOUNCE_MAX_SCOPES) {
45
+ for (const [scopeKey, scheduledAt] of autoReindexScheduledAt) {
46
+ if (now - scheduledAt >= debounceMs) autoReindexScheduledAt.delete(scopeKey);
47
+ }
48
+ if (autoReindexScheduledAt.size >= AUTO_REINDEX_DEBOUNCE_MAX_SCOPES) {
49
+ const oldestKey = autoReindexScheduledAt.keys().next().value;
50
+ if (oldestKey !== void 0) autoReindexScheduledAt.delete(oldestKey);
51
+ }
52
+ }
53
+ autoReindexScheduledAt.delete(key);
54
+ autoReindexScheduledAt.set(key, now);
55
+ return true;
56
+ }
29
57
  function buildFilterableCustomFieldJoins(sources) {
30
58
  if (!sources || sources.length === 0) return [];
31
59
  return sources.flatMap((source, index) => {
@@ -88,6 +116,7 @@ class HybridQueryEngine {
88
116
  this.sqlDebugEnabled = null;
89
117
  this.forcePartialIndexEnabled = null;
90
118
  this.autoReindexEnabled = null;
119
+ this.autoReindexDebounceMs = null;
91
120
  this.coverageOptimizationEnabled = null;
92
121
  this.pendingCoverageRefreshKeys = /* @__PURE__ */ new Set();
93
122
  this.searchAvailabilityInstance = null;
@@ -1642,6 +1671,11 @@ class HybridQueryEngine {
1642
1671
  organizationId: organizationIdOverride ?? opts.organizationId ?? null,
1643
1672
  force: false
1644
1673
  };
1674
+ const debounceMs = this.getAutoReindexDebounceMs();
1675
+ if (debounceMs > 0) {
1676
+ const key = [payload.entityType, payload.tenantId ?? "__tenant__", payload.organizationId ?? "__org__"].join("|");
1677
+ if (!markAutoReindexScheduled(key, debounceMs, Date.now())) return;
1678
+ }
1645
1679
  const context = stats ? { entity, tenantId: payload.tenantId, organizationId: payload.organizationId, baseCount: stats.baseCount, indexedCount: stats.indexedCount } : { entity, tenantId: payload.tenantId, organizationId: payload.organizationId };
1646
1680
  void Promise.resolve().then(async () => {
1647
1681
  try {
@@ -1710,6 +1744,15 @@ class HybridQueryEngine {
1710
1744
  this.autoReindexEnabled = parsed === null ? true : parsed;
1711
1745
  return this.autoReindexEnabled;
1712
1746
  }
1747
+ getAutoReindexDebounceMs() {
1748
+ if (this.autoReindexDebounceMs != null) return this.autoReindexDebounceMs;
1749
+ this.autoReindexDebounceMs = parseNumberWithDefault(
1750
+ process.env.OM_QUERY_INDEX_AUTO_REINDEX_DEBOUNCE_MS,
1751
+ AUTO_REINDEX_DEBOUNCE_DEFAULT_MS,
1752
+ { integer: true, min: 0 }
1753
+ );
1754
+ return this.autoReindexDebounceMs;
1755
+ }
1713
1756
  isCoverageOptimizationEnabled() {
1714
1757
  if (this.coverageOptimizationEnabled != null) return this.coverageOptimizationEnabled;
1715
1758
  const raw = (process.env.OPTIMIZE_INDEX_COVERAGE_STATS ?? "").trim().toLowerCase();