@open-mercato/core 0.6.7-develop.6788.1.c2a1520a30 → 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.
- package/.turbo/turbo-build.log +1 -1
- package/dist/generated/entities/customer_deal_person_link/index.js +2 -0
- package/dist/generated/entities/customer_deal_person_link/index.js.map +2 -2
- package/dist/generated/entities/customer_user_invitation/index.js +2 -0
- package/dist/generated/entities/customer_user_invitation/index.js.map +2 -2
- package/dist/generated/entities.ids.generated.js +1 -0
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +2 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/business_rules/api/openmercato-call-options/route.js +85 -0
- package/dist/modules/business_rules/api/openmercato-call-options/route.js.map +7 -0
- package/dist/modules/business_rules/api/rules/route.js +71 -4
- package/dist/modules/business_rules/api/rules/route.js.map +2 -2
- package/dist/modules/business_rules/components/ActionBuilder.js +47 -4
- package/dist/modules/business_rules/components/ActionBuilder.js.map +3 -3
- package/dist/modules/business_rules/components/ActionRow.js +106 -16
- package/dist/modules/business_rules/components/ActionRow.js.map +2 -2
- package/dist/modules/business_rules/components/utils/actionValidation.js +6 -0
- package/dist/modules/business_rules/components/utils/actionValidation.js.map +2 -2
- package/dist/modules/business_rules/lib/action-executor.js +148 -0
- package/dist/modules/business_rules/lib/action-executor.js.map +2 -2
- package/dist/modules/business_rules/lib/openmercato-call-options-types.js +5 -0
- package/dist/modules/business_rules/lib/openmercato-call-options-types.js.map +7 -0
- package/dist/modules/business_rules/lib/openmercato-call-options.js +231 -0
- package/dist/modules/business_rules/lib/openmercato-call-options.js.map +7 -0
- package/dist/modules/business_rules/lib/rule-engine.js +5 -1
- package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
- package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js +11 -1
- package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js +11 -6
- package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js.map +2 -2
- package/dist/modules/configs/lib/upgrade-actions.js +12 -0
- package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/users/[id].js +10 -1
- package/dist/modules/customer_accounts/api/admin/users/[id].js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/users-invite.js +61 -4
- package/dist/modules/customer_accounts/api/admin/users-invite.js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/users-invite.js +20 -2
- package/dist/modules/customer_accounts/api/portal/users-invite.js.map +2 -2
- package/dist/modules/customer_accounts/data/entities.js +3 -0
- package/dist/modules/customer_accounts/data/entities.js.map +2 -2
- package/dist/modules/customer_accounts/data/validators.js +1 -0
- package/dist/modules/customer_accounts/data/validators.js.map +2 -2
- package/dist/modules/customer_accounts/emails/CustomerInvitationEmail.js +26 -0
- package/dist/modules/customer_accounts/emails/CustomerInvitationEmail.js.map +7 -0
- package/dist/modules/customer_accounts/lib/customerEntityOwnership.js +29 -3
- package/dist/modules/customer_accounts/lib/customerEntityOwnership.js.map +2 -2
- package/dist/modules/customer_accounts/lib/customerUrl.js +19 -10
- package/dist/modules/customer_accounts/lib/customerUrl.js.map +2 -2
- package/dist/modules/customer_accounts/lib/invitationEmail.js +35 -0
- package/dist/modules/customer_accounts/lib/invitationEmail.js.map +7 -0
- package/dist/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.js +13 -0
- package/dist/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.js.map +7 -0
- package/dist/modules/customer_accounts/services/customerInvitationService.js +32 -2
- package/dist/modules/customer_accounts/services/customerInvitationService.js.map +2 -2
- package/dist/modules/customer_accounts/subscribers/autoLinkCrm.js +47 -7
- package/dist/modules/customer_accounts/subscribers/autoLinkCrm.js.map +2 -2
- package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js +2 -2
- package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js.map +2 -2
- package/dist/modules/customer_accounts/widgets/injection-table.js +1 -1
- package/dist/modules/customer_accounts/widgets/injection-table.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/people/route.js +4 -2
- package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/route.js +7 -3
- package/dist/modules/customers/api/deals/[id]/route.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +11 -1
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/page.js +14 -8
- package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +21 -6
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/cli.js +17 -7
- package/dist/modules/customers/cli.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +48 -10
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/commands/people.js +2 -0
- package/dist/modules/customers/commands/people.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js +26 -6
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/DealDetailTabs.js +30 -8
- package/dist/modules/customers/components/detail/DealDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonDetailTabs.js +30 -8
- package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
- package/dist/modules/customers/data/entities.js +8 -0
- package/dist/modules/customers/data/entities.js.map +2 -2
- package/dist/modules/customers/data/validators.js +2 -1
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/customers/migrations/Migration20260723210000_customers.js +15 -0
- package/dist/modules/customers/migrations/Migration20260723210000_customers.js.map +7 -0
- package/dist/modules/customers/search.js +50 -29
- package/dist/modules/customers/search.js.map +2 -2
- package/dist/modules/data_sync/api/mappings/[id]/route.js +22 -9
- package/dist/modules/data_sync/api/mappings/[id]/route.js.map +2 -2
- package/dist/modules/data_sync/api/mappings/route.js +13 -4
- package/dist/modules/data_sync/api/mappings/route.js.map +2 -2
- package/dist/modules/data_sync/api/options.js +7 -2
- package/dist/modules/data_sync/api/options.js.map +2 -2
- package/dist/modules/data_sync/api/run.js +7 -2
- package/dist/modules/data_sync/api/run.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/cancel.js +8 -3
- package/dist/modules/data_sync/api/runs/[id]/cancel.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/retry.js +7 -2
- package/dist/modules/data_sync/api/runs/[id]/retry.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/route.js +8 -3
- package/dist/modules/data_sync/api/runs/[id]/route.js.map +2 -2
- package/dist/modules/data_sync/api/runs.js +7 -2
- package/dist/modules/data_sync/api/runs.js.map +2 -2
- package/dist/modules/data_sync/api/schedules/[id]/route.js +19 -6
- package/dist/modules/data_sync/api/schedules/[id]/route.js.map +2 -2
- package/dist/modules/data_sync/api/schedules/route.js +13 -4
- package/dist/modules/data_sync/api/schedules/route.js.map +2 -2
- package/dist/modules/data_sync/api/validate.js +9 -4
- package/dist/modules/data_sync/api/validate.js.map +2 -2
- package/dist/modules/design_system/acl.js +9 -0
- package/dist/modules/design_system/acl.js.map +7 -0
- package/dist/modules/design_system/backend/design-system/page.js +11 -0
- package/dist/modules/design_system/backend/design-system/page.js.map +7 -0
- package/dist/modules/design_system/backend/design-system/page.meta.js +15 -0
- package/dist/modules/design_system/backend/design-system/page.meta.js.map +7 -0
- package/dist/modules/design_system/gallery/components/CodeSnippet.js +52 -0
- package/dist/modules/design_system/gallery/components/CodeSnippet.js.map +7 -0
- package/dist/modules/design_system/gallery/components/EntryCard.js +63 -0
- package/dist/modules/design_system/gallery/components/EntryCard.js.map +7 -0
- package/dist/modules/design_system/gallery/components/GalleryShell.js +163 -0
- package/dist/modules/design_system/gallery/components/GalleryShell.js.map +7 -0
- package/dist/modules/design_system/gallery/components/VariantPreview.js +9 -0
- package/dist/modules/design_system/gallery/components/VariantPreview.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/banners.js +186 -0
- package/dist/modules/design_system/gallery/entries/banners.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/buttons.js +361 -0
- package/dist/modules/design_system/gallery/entries/buttons.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/charts.js +457 -0
- package/dist/modules/design_system/gallery/entries/charts.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/dates.js +306 -0
- package/dist/modules/design_system/gallery/entries/dates.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/detail.js +358 -0
- package/dist/modules/design_system/gallery/entries/detail.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/display.js +785 -0
- package/dist/modules/design_system/gallery/entries/display.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/feedback.js +658 -0
- package/dist/modules/design_system/gallery/entries/feedback.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/filters.js +505 -0
- package/dist/modules/design_system/gallery/entries/filters.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/foundations.js +453 -0
- package/dist/modules/design_system/gallery/entries/foundations.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/icons.js +140 -0
- package/dist/modules/design_system/gallery/entries/icons.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/inputs.js +1217 -0
- package/dist/modules/design_system/gallery/entries/inputs.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/messages.js +334 -0
- package/dist/modules/design_system/gallery/entries/messages.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/navigation.js +475 -0
- package/dist/modules/design_system/gallery/entries/navigation.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/notifications.js +257 -0
- package/dist/modules/design_system/gallery/entries/notifications.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/overlays.js +576 -0
- package/dist/modules/design_system/gallery/entries/overlays.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/scaffolding.js +378 -0
- package/dist/modules/design_system/gallery/entries/scaffolding.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/schedule.js +297 -0
- package/dist/modules/design_system/gallery/entries/schedule.js.map +7 -0
- package/dist/modules/design_system/gallery/registry.js +139 -0
- package/dist/modules/design_system/gallery/registry.js.map +7 -0
- package/dist/modules/design_system/gallery/types.js +1 -0
- package/dist/modules/design_system/gallery/types.js.map +7 -0
- package/dist/modules/design_system/index.js +9 -0
- package/dist/modules/design_system/index.js.map +7 -0
- package/dist/modules/design_system/setup.js +14 -0
- package/dist/modules/design_system/setup.js.map +7 -0
- package/dist/modules/entities/api/entity-settings.js +59 -9
- package/dist/modules/entities/api/entity-settings.js.map +2 -2
- package/dist/modules/entities/backend/config/settings/page.js +10 -0
- package/dist/modules/entities/backend/config/settings/page.js.map +7 -0
- package/dist/modules/entities/backend/config/settings/page.meta.js +36 -0
- package/dist/modules/entities/backend/config/settings/page.meta.js.map +7 -0
- package/dist/modules/entities/backend/entities/user/create/page.js +16 -7
- package/dist/modules/entities/backend/entities/user/create/page.js.map +2 -2
- package/dist/modules/entities/components/EntitySettingsManager.js +136 -0
- package/dist/modules/entities/components/EntitySettingsManager.js.map +7 -0
- package/dist/modules/inbox_ops/api/webhook/inbound.js +14 -10
- package/dist/modules/inbox_ops/api/webhook/inbound.js.map +2 -2
- package/dist/modules/inbox_ops/search.js +15 -4
- package/dist/modules/inbox_ops/search.js.map +2 -2
- package/dist/modules/integrations/api/[id]/credentials/route.js +11 -5
- package/dist/modules/integrations/api/[id]/credentials/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/health/route.js +6 -3
- package/dist/modules/integrations/api/[id]/health/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/route.js +6 -3
- package/dist/modules/integrations/api/[id]/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/state/route.js +6 -3
- package/dist/modules/integrations/api/[id]/state/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/version/route.js +6 -3
- package/dist/modules/integrations/api/[id]/version/route.js.map +2 -2
- package/dist/modules/integrations/api/logs/route.js +6 -3
- package/dist/modules/integrations/api/logs/route.js.map +2 -2
- package/dist/modules/integrations/api/route.js +6 -3
- package/dist/modules/integrations/api/route.js.map +2 -2
- package/dist/modules/integrations/api/umes-read.js +2 -2
- package/dist/modules/integrations/api/umes-read.js.map +2 -2
- package/dist/modules/integrations/lib/organization-scope.js +2 -9
- package/dist/modules/integrations/lib/organization-scope.js.map +2 -2
- package/dist/modules/messages/search.js +10 -5
- package/dist/modules/messages/search.js.map +2 -2
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +11 -1
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +2 -2
- package/dist/modules/payment_gateways/data/entities.js +4 -0
- package/dist/modules/payment_gateways/data/entities.js.map +2 -2
- package/dist/modules/payment_gateways/lib/gateway-service.js +12 -2
- package/dist/modules/payment_gateways/lib/gateway-service.js.map +2 -2
- package/dist/modules/payment_gateways/lib/session-idempotency.js +33 -0
- package/dist/modules/payment_gateways/lib/session-idempotency.js.map +2 -2
- package/dist/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.js +18 -0
- package/dist/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.js.map +7 -0
- package/dist/modules/payment_gateways/setup.js +47 -0
- package/dist/modules/payment_gateways/setup.js.map +2 -2
- package/dist/modules/payment_gateways/workers/session-initialization-prune.js +50 -0
- package/dist/modules/payment_gateways/workers/session-initialization-prune.js.map +7 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.js +134 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.js.map +7 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.js +11 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.js.map +7 -0
- package/dist/modules/portal/lib/navigation.js +7 -0
- package/dist/modules/portal/lib/navigation.js.map +7 -0
- package/dist/modules/query_index/data/entities.js +2 -1
- package/dist/modules/query_index/data/entities.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +75 -50
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/query_index/lib/search-tokens.js +15 -5
- package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
- package/dist/modules/query_index/migrations/Migration20260731105052_query_index.js +17 -0
- package/dist/modules/query_index/migrations/Migration20260731105052_query_index.js.map +7 -0
- package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js +11 -1
- package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js.map +2 -2
- package/generated/entities/customer_deal_person_link/index.ts +1 -0
- package/generated/entities/customer_user_invitation/index.ts +1 -0
- package/generated/entities.ids.generated.ts +1 -0
- package/generated/entity-fields-registry.ts +2 -0
- package/package.json +16 -16
- package/src/modules/business_rules/api/openmercato-call-options/route.ts +94 -0
- package/src/modules/business_rules/api/rules/route.ts +92 -4
- package/src/modules/business_rules/components/ActionBuilder.tsx +54 -5
- package/src/modules/business_rules/components/ActionRow.tsx +156 -18
- package/src/modules/business_rules/components/utils/actionValidation.ts +6 -0
- package/src/modules/business_rules/i18n/de.json +12 -0
- package/src/modules/business_rules/i18n/en.json +12 -0
- package/src/modules/business_rules/i18n/es.json +12 -0
- package/src/modules/business_rules/i18n/pl.json +12 -0
- package/src/modules/business_rules/lib/action-executor.ts +198 -0
- package/src/modules/business_rules/lib/openmercato-call-options-types.ts +31 -0
- package/src/modules/business_rules/lib/openmercato-call-options.ts +297 -0
- package/src/modules/business_rules/lib/rule-engine.ts +4 -0
- package/src/modules/communication_channels/api/post/webhook/[provider]/route.ts +11 -1
- package/src/modules/communication_channels/api/post/webhooks/gmail/route.ts +17 -11
- package/src/modules/configs/lib/upgrade-actions.ts +14 -0
- package/src/modules/customer_accounts/api/admin/users/[id].ts +16 -1
- package/src/modules/customer_accounts/api/admin/users-invite.ts +78 -3
- package/src/modules/customer_accounts/api/portal/users-invite.ts +22 -1
- package/src/modules/customer_accounts/data/entities.ts +3 -0
- package/src/modules/customer_accounts/data/validators.ts +1 -0
- package/src/modules/customer_accounts/emails/CustomerInvitationEmail.tsx +45 -0
- package/src/modules/customer_accounts/i18n/de.json +6 -0
- package/src/modules/customer_accounts/i18n/en.json +6 -0
- package/src/modules/customer_accounts/i18n/es.json +6 -0
- package/src/modules/customer_accounts/i18n/pl.json +6 -0
- package/src/modules/customer_accounts/lib/customerEntityOwnership.ts +68 -2
- package/src/modules/customer_accounts/lib/customerUrl.ts +27 -11
- package/src/modules/customer_accounts/lib/invitationEmail.ts +42 -0
- package/src/modules/customer_accounts/migrations/.snapshot-open-mercato.json +16 -0
- package/src/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.ts +13 -0
- package/src/modules/customer_accounts/services/customerInvitationService.ts +56 -3
- package/src/modules/customer_accounts/subscribers/autoLinkCrm.ts +75 -8
- package/src/modules/customer_accounts/widgets/injection/account-status/widget.client.tsx +2 -2
- package/src/modules/customer_accounts/widgets/injection-table.ts +4 -1
- package/src/modules/customers/api/deals/[id]/people/route.ts +3 -0
- package/src/modules/customers/api/deals/[id]/route.ts +10 -2
- package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +12 -1
- package/src/modules/customers/backend/customers/deals/[id]/hooks/types.ts +1 -0
- package/src/modules/customers/backend/customers/deals/[id]/page.tsx +15 -9
- package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +24 -6
- package/src/modules/customers/cli.ts +17 -7
- package/src/modules/customers/commands/deals.ts +50 -9
- package/src/modules/customers/commands/people.ts +3 -0
- package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +30 -7
- package/src/modules/customers/components/detail/DealDetailTabs.tsx +34 -9
- package/src/modules/customers/components/detail/PersonDetailTabs.tsx +34 -9
- package/src/modules/customers/data/entities.ts +9 -1
- package/src/modules/customers/data/validators.ts +1 -0
- package/src/modules/customers/i18n/de.json +18 -0
- package/src/modules/customers/i18n/en.json +18 -0
- package/src/modules/customers/i18n/es.json +18 -0
- package/src/modules/customers/i18n/pl.json +18 -0
- package/src/modules/customers/migrations/.snapshot-open-mercato.json +27 -1
- package/src/modules/customers/migrations/Migration20260723210000_customers.ts +15 -0
- package/src/modules/customers/search.ts +59 -27
- package/src/modules/data_sync/AGENTS.md +1 -0
- package/src/modules/data_sync/api/mappings/[id]/route.ts +22 -9
- package/src/modules/data_sync/api/mappings/route.ts +13 -4
- package/src/modules/data_sync/api/options.ts +7 -2
- package/src/modules/data_sync/api/run.ts +7 -2
- package/src/modules/data_sync/api/runs/[id]/cancel.ts +8 -3
- package/src/modules/data_sync/api/runs/[id]/retry.ts +7 -2
- package/src/modules/data_sync/api/runs/[id]/route.ts +8 -3
- package/src/modules/data_sync/api/runs.ts +7 -2
- package/src/modules/data_sync/api/schedules/[id]/route.ts +19 -6
- package/src/modules/data_sync/api/schedules/route.ts +13 -4
- package/src/modules/data_sync/api/validate.ts +9 -4
- package/src/modules/design_system/AGENTS.md +34 -0
- package/src/modules/design_system/acl.ts +5 -0
- package/src/modules/design_system/backend/design-system/page.meta.ts +11 -0
- package/src/modules/design_system/backend/design-system/page.tsx +14 -0
- package/src/modules/design_system/gallery/components/CodeSnippet.tsx +55 -0
- package/src/modules/design_system/gallery/components/EntryCard.tsx +95 -0
- package/src/modules/design_system/gallery/components/GalleryShell.tsx +206 -0
- package/src/modules/design_system/gallery/components/VariantPreview.tsx +15 -0
- package/src/modules/design_system/gallery/entries/banners.tsx +226 -0
- package/src/modules/design_system/gallery/entries/buttons.tsx +422 -0
- package/src/modules/design_system/gallery/entries/charts.tsx +518 -0
- package/src/modules/design_system/gallery/entries/dates.tsx +325 -0
- package/src/modules/design_system/gallery/entries/detail.tsx +403 -0
- package/src/modules/design_system/gallery/entries/display.tsx +893 -0
- package/src/modules/design_system/gallery/entries/feedback.tsx +746 -0
- package/src/modules/design_system/gallery/entries/filters.tsx +570 -0
- package/src/modules/design_system/gallery/entries/foundations.tsx +529 -0
- package/src/modules/design_system/gallery/entries/icons.tsx +168 -0
- package/src/modules/design_system/gallery/entries/inputs.tsx +1516 -0
- package/src/modules/design_system/gallery/entries/messages.tsx +339 -0
- package/src/modules/design_system/gallery/entries/navigation.tsx +573 -0
- package/src/modules/design_system/gallery/entries/notifications.tsx +285 -0
- package/src/modules/design_system/gallery/entries/overlays.tsx +677 -0
- package/src/modules/design_system/gallery/entries/scaffolding.tsx +430 -0
- package/src/modules/design_system/gallery/entries/schedule.tsx +307 -0
- package/src/modules/design_system/gallery/registry.ts +152 -0
- package/src/modules/design_system/gallery/types.ts +32 -0
- package/src/modules/design_system/i18n/.hardcoded-allowlist.json +71 -0
- package/src/modules/design_system/i18n/de.json +46 -0
- package/src/modules/design_system/i18n/en.json +46 -0
- package/src/modules/design_system/i18n/es.json +46 -0
- package/src/modules/design_system/i18n/pl.json +46 -0
- package/src/modules/design_system/index.ts +7 -0
- package/src/modules/design_system/setup.ts +12 -0
- package/src/modules/entities/api/entity-settings.ts +66 -22
- package/src/modules/entities/backend/config/settings/page.meta.ts +34 -0
- package/src/modules/entities/backend/config/settings/page.tsx +12 -0
- package/src/modules/entities/backend/entities/user/create/page.tsx +16 -7
- package/src/modules/entities/components/EntitySettingsManager.tsx +160 -0
- package/src/modules/entities/i18n/de.json +9 -0
- package/src/modules/entities/i18n/en.json +9 -0
- package/src/modules/entities/i18n/es.json +9 -0
- package/src/modules/entities/i18n/pl.json +9 -0
- package/src/modules/inbox_ops/api/webhook/inbound.ts +14 -12
- package/src/modules/inbox_ops/i18n/de.json +3 -0
- package/src/modules/inbox_ops/i18n/en.json +3 -0
- package/src/modules/inbox_ops/i18n/es.json +3 -0
- package/src/modules/inbox_ops/i18n/pl.json +3 -0
- package/src/modules/inbox_ops/search.ts +20 -4
- package/src/modules/integrations/api/[id]/credentials/route.ts +11 -5
- package/src/modules/integrations/api/[id]/health/route.ts +6 -3
- package/src/modules/integrations/api/[id]/route.ts +6 -3
- package/src/modules/integrations/api/[id]/state/route.ts +6 -3
- package/src/modules/integrations/api/[id]/version/route.ts +6 -3
- package/src/modules/integrations/api/logs/route.ts +6 -3
- package/src/modules/integrations/api/route.ts +6 -3
- package/src/modules/integrations/api/umes-read.ts +2 -2
- package/src/modules/integrations/lib/organization-scope.ts +5 -25
- package/src/modules/messages/i18n/de.json +2 -0
- package/src/modules/messages/i18n/en.json +2 -0
- package/src/modules/messages/i18n/es.json +2 -0
- package/src/modules/messages/i18n/pl.json +2 -0
- package/src/modules/messages/search.ts +11 -5
- package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +13 -1
- package/src/modules/payment_gateways/data/entities.ts +5 -0
- package/src/modules/payment_gateways/i18n/de.json +5 -1
- package/src/modules/payment_gateways/i18n/en.json +5 -1
- package/src/modules/payment_gateways/i18n/es.json +5 -1
- package/src/modules/payment_gateways/i18n/pl.json +5 -1
- package/src/modules/payment_gateways/lib/gateway-service.ts +12 -2
- package/src/modules/payment_gateways/lib/session-idempotency.ts +36 -0
- package/src/modules/payment_gateways/migrations/.snapshot-open-mercato.json +10 -1
- package/src/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.ts +17 -0
- package/src/modules/payment_gateways/setup.ts +62 -0
- package/src/modules/payment_gateways/workers/session-initialization-prune.ts +63 -0
- package/src/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.ts +9 -0
- package/src/modules/portal/frontend/[orgSlug]/portal/invite/page.tsx +164 -0
- package/src/modules/portal/i18n/de.json +18 -0
- package/src/modules/portal/i18n/en.json +18 -0
- package/src/modules/portal/i18n/es.json +18 -0
- package/src/modules/portal/i18n/pl.json +18 -0
- package/src/modules/portal/lib/navigation.ts +3 -0
- package/src/modules/query_index/data/entities.ts +7 -0
- package/src/modules/query_index/lib/engine.ts +92 -63
- package/src/modules/query_index/lib/search-tokens.ts +16 -4
- package/src/modules/query_index/migrations/.snapshot-open-mercato.json +12 -0
- package/src/modules/query_index/migrations/Migration20260731105052_query_index.ts +35 -0
- package/src/modules/shipping_carriers/api/webhook/[provider]/route.ts +11 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/integrations/api/route.ts"],
|
|
4
|
-
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { CredentialsEncryptionUnavailableError, type CredentialsService } from '../lib/credentials-service'\nimport type { IntegrationStateService } from '../lib/state-service'\nimport type { IntegrationLogService } from '../lib/log-service'\nimport { deriveIntegrationHealthStatus, getEffectiveHealthCheckConfig } from '../lib/health-service'\nimport type { IntegrationHealthDisplayStatus } from '../lib/health-service'\nimport { getAllBundles, getAllIntegrations } from '@open-mercato/shared/modules/integrations/types'\nimport { listIntegrationsQuerySchema } from '../data/validators'\nimport { buildIntegrationsCrudOpenApi, integrationsListResponseSchema } from './openapi'\nimport {\n finalizeIntegrationsReadResponse,\n integrationApiRoutePaths,\n runIntegrationsReadBeforeInterceptors,\n} from './umes-read'\nimport { resolveIntegrationsOrganizationId } from '../lib/organization-scope'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['integrations.view'] },\n}\n\nexport const openApi = buildIntegrationsCrudOpenApi({\n resourceName: 'Integration',\n pluralName: 'Integrations',\n listResponseSchema: integrationsListResponseSchema,\n querySchema: listIntegrationsQuerySchema,\n})\n\nconst HEALTH_SORT_RANK: Record<IntegrationHealthDisplayStatus, number> = {\n healthy: 0,\n degraded: 1,\n unhealthy: 2,\n unconfigured: 3,\n}\n\nfunction matchesSearchQuery(\n integration: { title: string; description?: string; tags?: string[] },\n queryNormalized: string,\n): boolean {\n if (!queryNormalized) return true\n if (integration.title.toLowerCase().includes(queryNormalized)) return true\n if (integration.description?.toLowerCase().includes(queryNormalized)) return true\n const tags = integration.tags ?? []\n return tags.some((tag) => tag.toLowerCase().includes(queryNormalized))\n}\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n const organizationId = resolveIntegrationsOrganizationId(auth)\n if (!auth?.tenantId || !organizationId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const url = new URL(req.url)\n const parsedQuery = listIntegrationsQuerySchema.safeParse(Object.fromEntries(url.searchParams.entries()))\n if (!parsedQuery.success) {\n return NextResponse.json({ error: 'Invalid query', details: parsedQuery.error.flatten() }, { status: 400 })\n }\n const query = parsedQuery.data\n\n const container = await createRequestContainer()\n const beforeInterceptors = await runIntegrationsReadBeforeInterceptors({\n routePath: integrationApiRoutePaths.list,\n request: req,\n auth,\n container,\n })\n if (!beforeInterceptors.ok) {\n return NextResponse.json(beforeInterceptors.body, { status: beforeInterceptors.statusCode })\n }\n const credentialsService = container.resolve('integrationCredentialsService') as CredentialsService\n const stateService = container.resolve('integrationStateService') as IntegrationStateService\n const logService = container.resolve('integrationLogService') as IntegrationLogService\n\n const scope = { organizationId: organizationId, tenantId: auth.tenantId as string }\n const searchNeedle = query.q?.trim().toLowerCase() ?? ''\n\n type ListRow = {\n id: string\n title: string\n description: string | null\n category: string | null\n tags: string[]\n hub: string | null\n providerKey: string | null\n bundleId: string | null\n author: string | null\n company: string | null\n version: string | null\n hasCredentials: boolean\n isEnabled: boolean\n apiVersion: string | null\n healthStatus: IntegrationHealthDisplayStatus\n lastHealthCheckedAt: string | null\n lastHealthLatencyMs: number | null\n enabledAt: string | null\n stateUpdatedAt: string | null\n sortEnabledAtMs: number\n sortTitle: string\n sortCategory: string\n }\n\n const baseRows: ListRow[] = await Promise.all(\n getAllIntegrations().map(async (integration) => {\n const [resolvedCredentials, state] = await Promise.all([\n credentialsService.resolve(integration.id, scope).catch((err) => {\n if (err instanceof CredentialsEncryptionUnavailableError) return null\n throw err\n }),\n stateService.resolveState(integration.id, scope),\n ])\n\n const hasCredentials =\n resolvedCredentials != null && Object.keys(resolvedCredentials).length > 0\n const healthConfig = getEffectiveHealthCheckConfig(integration.id)\n const hasHealthCheck = Boolean(healthConfig?.service)\n const healthStatus = deriveIntegrationHealthStatus({\n hasHealthCheck,\n hasCredentials,\n lastHealthStatus: state.lastHealthStatus,\n lastHealthCheckedAt: state.lastHealthCheckedAt,\n })\n\n const enabledAtMs = state.enabledAt?.getTime() ?? 0\n\n return {\n id: integration.id,\n title: integration.title,\n description: integration.description ?? null,\n category: integration.category ?? null,\n tags: integration.tags ?? [],\n hub: integration.hub ?? null,\n providerKey: integration.providerKey ?? null,\n bundleId: integration.bundleId ?? null,\n author: integration.author ?? null,\n company: integration.company ?? null,\n version: integration.version ?? null,\n hasCredentials,\n isEnabled: state.isEnabled,\n apiVersion: state.apiVersion,\n healthStatus,\n lastHealthCheckedAt: state.lastHealthCheckedAt?.toISOString() ?? null,\n lastHealthLatencyMs: state.lastHealthLatencyMs,\n enabledAt: state.enabledAt?.toISOString() ?? null,\n stateUpdatedAt: state.updatedAt?.toISOString() ?? null,\n sortEnabledAtMs: enabledAtMs,\n sortTitle: integration.title.toLowerCase(),\n sortCategory: (integration.category ?? '').toLowerCase(),\n }\n }),\n )\n\n let filtered = baseRows.filter((row) => matchesSearchQuery(\n { title: row.title, description: row.description ?? undefined, tags: row.tags },\n searchNeedle,\n ))\n\n if (query.category) {\n filtered = filtered.filter((row) => row.category === query.category)\n }\n if (query.bundleId) {\n filtered = filtered.filter((row) => row.bundleId === query.bundleId)\n }\n if (query.isEnabled !== undefined) {\n filtered = filtered.filter((row) => row.isEnabled === query.isEnabled)\n }\n if (query.healthStatus) {\n filtered = filtered.filter((row) => row.healthStatus === query.healthStatus)\n }\n\n const sortKey = query.sort ?? 'title'\n const orderSign = query.order === 'desc' ? -1 : 1\n\n const sorted = [...filtered].sort((rowA, rowB) => {\n let cmp = 0\n if (sortKey === 'title') {\n cmp = rowA.sortTitle.localeCompare(rowB.sortTitle)\n } else if (sortKey === 'category') {\n cmp = rowA.sortCategory.localeCompare(rowB.sortCategory)\n if (cmp === 0) cmp = rowA.sortTitle.localeCompare(rowB.sortTitle)\n } else if (sortKey === 'enabledAt') {\n cmp = rowA.sortEnabledAtMs - rowB.sortEnabledAtMs\n if (cmp === 0) cmp = rowA.sortTitle.localeCompare(rowB.sortTitle)\n } else if (sortKey === 'healthStatus') {\n cmp = HEALTH_SORT_RANK[rowA.healthStatus] - HEALTH_SORT_RANK[rowB.healthStatus]\n if (cmp === 0) cmp = rowA.sortTitle.localeCompare(rowB.sortTitle)\n }\n return cmp * orderSign\n })\n\n const total = sorted.length\n const pageSize = query.pageSize\n const page = query.page\n const totalPages = Math.max(1, Math.ceil(total / pageSize) || 1)\n const safePage = Math.min(page, totalPages)\n const offset = (safePage - 1) * pageSize\n const pageSlice = sorted.slice(offset, offset + pageSize)\n\n const analyticsMap = await logService.aggregateAnalytics(\n pageSlice.map((row) => row.id),\n scope,\n 30,\n )\n\n const items = pageSlice.map((row) => {\n const analytics = analyticsMap.get(row.id)\n return {\n id: row.id,\n title: row.title,\n description: row.description,\n category: row.category,\n tags: row.tags,\n hub: row.hub,\n providerKey: row.providerKey,\n bundleId: row.bundleId,\n author: row.author,\n company: row.company,\n version: row.version,\n hasCredentials: row.hasCredentials,\n isEnabled: row.isEnabled,\n apiVersion: row.apiVersion,\n healthStatus: row.healthStatus,\n lastHealthCheckedAt: row.lastHealthCheckedAt,\n lastHealthLatencyMs: row.lastHealthLatencyMs,\n enabledAt: row.enabledAt,\n stateUpdatedAt: row.stateUpdatedAt,\n analytics: analytics ?? {\n lastActivityAt: null,\n totalCount: 0,\n errorCount: 0,\n errorRate: 0,\n dailyCounts: Array.from({ length: 30 }, () => 0),\n },\n }\n })\n\n const bundles = getAllBundles().map((bundle) => {\n const bundleIntegrations = filtered.filter((row) => row.bundleId === bundle.id)\n const enabledCount = bundleIntegrations.reduce((count, integration) => count + (integration.isEnabled ? 1 : 0), 0)\n\n return {\n id: bundle.id,\n title: bundle.title,\n description: bundle.description,\n icon: bundle.icon ?? null,\n integrationCount: bundleIntegrations.length,\n enabledCount,\n }\n })\n\n return finalizeIntegrationsReadResponse({\n routePath: integrationApiRoutePaths.list,\n request: req,\n auth,\n container,\n interceptorRequest: beforeInterceptors.request,\n beforeMetadata: beforeInterceptors.metadataByInterceptor,\n enrich: {\n targetEntity: 'integrations.integration',\n listKeys: ['items'],\n },\n body: {\n items,\n bundles,\n total,\n page: safePage,\n pageSize,\n totalPages,\n },\n })\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AACnC,SAAS,8BAA8B;AACvC,SAAS,6CAAsE;AAG/E,SAAS,+BAA+B,qCAAqC;AAE7E,SAAS,eAAe,0BAA0B;AAClD,SAAS,mCAAmC;AAC5C,SAAS,8BAA8B,sCAAsC;AAC7E;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { CredentialsEncryptionUnavailableError, type CredentialsService } from '../lib/credentials-service'\nimport type { IntegrationStateService } from '../lib/state-service'\nimport type { IntegrationLogService } from '../lib/log-service'\nimport { deriveIntegrationHealthStatus, getEffectiveHealthCheckConfig } from '../lib/health-service'\nimport type { IntegrationHealthDisplayStatus } from '../lib/health-service'\nimport { getAllBundles, getAllIntegrations } from '@open-mercato/shared/modules/integrations/types'\nimport { listIntegrationsQuerySchema } from '../data/validators'\nimport { buildIntegrationsCrudOpenApi, integrationsListResponseSchema } from './openapi'\nimport {\n finalizeIntegrationsReadResponse,\n integrationApiRoutePaths,\n runIntegrationsReadBeforeInterceptors,\n} from './umes-read'\nimport { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['integrations.view'] },\n}\n\nexport const openApi = buildIntegrationsCrudOpenApi({\n resourceName: 'Integration',\n pluralName: 'Integrations',\n listResponseSchema: integrationsListResponseSchema,\n querySchema: listIntegrationsQuerySchema,\n})\n\nconst HEALTH_SORT_RANK: Record<IntegrationHealthDisplayStatus, number> = {\n healthy: 0,\n degraded: 1,\n unhealthy: 2,\n unconfigured: 3,\n}\n\nfunction matchesSearchQuery(\n integration: { title: string; description?: string; tags?: string[] },\n queryNormalized: string,\n): boolean {\n if (!queryNormalized) return true\n if (integration.title.toLowerCase().includes(queryNormalized)) return true\n if (integration.description?.toLowerCase().includes(queryNormalized)) return true\n const tags = integration.tags ?? []\n return tags.some((tag) => tag.toLowerCase().includes(queryNormalized))\n}\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n const organizationId = resolveActiveOrganizationId(auth)\n if (!organizationId) {\n return organizationScopeRequiredResponse()\n }\n\n const url = new URL(req.url)\n const parsedQuery = listIntegrationsQuerySchema.safeParse(Object.fromEntries(url.searchParams.entries()))\n if (!parsedQuery.success) {\n return NextResponse.json({ error: 'Invalid query', details: parsedQuery.error.flatten() }, { status: 400 })\n }\n const query = parsedQuery.data\n\n const container = await createRequestContainer()\n const beforeInterceptors = await runIntegrationsReadBeforeInterceptors({\n routePath: integrationApiRoutePaths.list,\n request: req,\n auth,\n container,\n })\n if (!beforeInterceptors.ok) {\n return NextResponse.json(beforeInterceptors.body, { status: beforeInterceptors.statusCode })\n }\n const credentialsService = container.resolve('integrationCredentialsService') as CredentialsService\n const stateService = container.resolve('integrationStateService') as IntegrationStateService\n const logService = container.resolve('integrationLogService') as IntegrationLogService\n\n const scope = { organizationId: organizationId, tenantId: auth.tenantId as string }\n const searchNeedle = query.q?.trim().toLowerCase() ?? ''\n\n type ListRow = {\n id: string\n title: string\n description: string | null\n category: string | null\n tags: string[]\n hub: string | null\n providerKey: string | null\n bundleId: string | null\n author: string | null\n company: string | null\n version: string | null\n hasCredentials: boolean\n isEnabled: boolean\n apiVersion: string | null\n healthStatus: IntegrationHealthDisplayStatus\n lastHealthCheckedAt: string | null\n lastHealthLatencyMs: number | null\n enabledAt: string | null\n stateUpdatedAt: string | null\n sortEnabledAtMs: number\n sortTitle: string\n sortCategory: string\n }\n\n const baseRows: ListRow[] = await Promise.all(\n getAllIntegrations().map(async (integration) => {\n const [resolvedCredentials, state] = await Promise.all([\n credentialsService.resolve(integration.id, scope).catch((err) => {\n if (err instanceof CredentialsEncryptionUnavailableError) return null\n throw err\n }),\n stateService.resolveState(integration.id, scope),\n ])\n\n const hasCredentials =\n resolvedCredentials != null && Object.keys(resolvedCredentials).length > 0\n const healthConfig = getEffectiveHealthCheckConfig(integration.id)\n const hasHealthCheck = Boolean(healthConfig?.service)\n const healthStatus = deriveIntegrationHealthStatus({\n hasHealthCheck,\n hasCredentials,\n lastHealthStatus: state.lastHealthStatus,\n lastHealthCheckedAt: state.lastHealthCheckedAt,\n })\n\n const enabledAtMs = state.enabledAt?.getTime() ?? 0\n\n return {\n id: integration.id,\n title: integration.title,\n description: integration.description ?? null,\n category: integration.category ?? null,\n tags: integration.tags ?? [],\n hub: integration.hub ?? null,\n providerKey: integration.providerKey ?? null,\n bundleId: integration.bundleId ?? null,\n author: integration.author ?? null,\n company: integration.company ?? null,\n version: integration.version ?? null,\n hasCredentials,\n isEnabled: state.isEnabled,\n apiVersion: state.apiVersion,\n healthStatus,\n lastHealthCheckedAt: state.lastHealthCheckedAt?.toISOString() ?? null,\n lastHealthLatencyMs: state.lastHealthLatencyMs,\n enabledAt: state.enabledAt?.toISOString() ?? null,\n stateUpdatedAt: state.updatedAt?.toISOString() ?? null,\n sortEnabledAtMs: enabledAtMs,\n sortTitle: integration.title.toLowerCase(),\n sortCategory: (integration.category ?? '').toLowerCase(),\n }\n }),\n )\n\n let filtered = baseRows.filter((row) => matchesSearchQuery(\n { title: row.title, description: row.description ?? undefined, tags: row.tags },\n searchNeedle,\n ))\n\n if (query.category) {\n filtered = filtered.filter((row) => row.category === query.category)\n }\n if (query.bundleId) {\n filtered = filtered.filter((row) => row.bundleId === query.bundleId)\n }\n if (query.isEnabled !== undefined) {\n filtered = filtered.filter((row) => row.isEnabled === query.isEnabled)\n }\n if (query.healthStatus) {\n filtered = filtered.filter((row) => row.healthStatus === query.healthStatus)\n }\n\n const sortKey = query.sort ?? 'title'\n const orderSign = query.order === 'desc' ? -1 : 1\n\n const sorted = [...filtered].sort((rowA, rowB) => {\n let cmp = 0\n if (sortKey === 'title') {\n cmp = rowA.sortTitle.localeCompare(rowB.sortTitle)\n } else if (sortKey === 'category') {\n cmp = rowA.sortCategory.localeCompare(rowB.sortCategory)\n if (cmp === 0) cmp = rowA.sortTitle.localeCompare(rowB.sortTitle)\n } else if (sortKey === 'enabledAt') {\n cmp = rowA.sortEnabledAtMs - rowB.sortEnabledAtMs\n if (cmp === 0) cmp = rowA.sortTitle.localeCompare(rowB.sortTitle)\n } else if (sortKey === 'healthStatus') {\n cmp = HEALTH_SORT_RANK[rowA.healthStatus] - HEALTH_SORT_RANK[rowB.healthStatus]\n if (cmp === 0) cmp = rowA.sortTitle.localeCompare(rowB.sortTitle)\n }\n return cmp * orderSign\n })\n\n const total = sorted.length\n const pageSize = query.pageSize\n const page = query.page\n const totalPages = Math.max(1, Math.ceil(total / pageSize) || 1)\n const safePage = Math.min(page, totalPages)\n const offset = (safePage - 1) * pageSize\n const pageSlice = sorted.slice(offset, offset + pageSize)\n\n const analyticsMap = await logService.aggregateAnalytics(\n pageSlice.map((row) => row.id),\n scope,\n 30,\n )\n\n const items = pageSlice.map((row) => {\n const analytics = analyticsMap.get(row.id)\n return {\n id: row.id,\n title: row.title,\n description: row.description,\n category: row.category,\n tags: row.tags,\n hub: row.hub,\n providerKey: row.providerKey,\n bundleId: row.bundleId,\n author: row.author,\n company: row.company,\n version: row.version,\n hasCredentials: row.hasCredentials,\n isEnabled: row.isEnabled,\n apiVersion: row.apiVersion,\n healthStatus: row.healthStatus,\n lastHealthCheckedAt: row.lastHealthCheckedAt,\n lastHealthLatencyMs: row.lastHealthLatencyMs,\n enabledAt: row.enabledAt,\n stateUpdatedAt: row.stateUpdatedAt,\n analytics: analytics ?? {\n lastActivityAt: null,\n totalCount: 0,\n errorCount: 0,\n errorRate: 0,\n dailyCounts: Array.from({ length: 30 }, () => 0),\n },\n }\n })\n\n const bundles = getAllBundles().map((bundle) => {\n const bundleIntegrations = filtered.filter((row) => row.bundleId === bundle.id)\n const enabledCount = bundleIntegrations.reduce((count, integration) => count + (integration.isEnabled ? 1 : 0), 0)\n\n return {\n id: bundle.id,\n title: bundle.title,\n description: bundle.description,\n icon: bundle.icon ?? null,\n integrationCount: bundleIntegrations.length,\n enabledCount,\n }\n })\n\n return finalizeIntegrationsReadResponse({\n routePath: integrationApiRoutePaths.list,\n request: req,\n auth,\n container,\n interceptorRequest: beforeInterceptors.request,\n beforeMetadata: beforeInterceptors.metadataByInterceptor,\n enrich: {\n targetEntity: 'integrations.integration',\n listKeys: ['items'],\n },\n body: {\n items,\n bundles,\n total,\n page: safePage,\n pageSize,\n totalPages,\n },\n })\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NextResponse } from "next/server";
|
|
2
2
|
import { runApiInterceptorsAfter, runApiInterceptorsBefore } from "@open-mercato/shared/lib/crud/interceptor-runner";
|
|
3
3
|
import { applyResponseEnrichers, applyResponseEnricherToRecord } from "@open-mercato/shared/lib/crud/enricher-runner";
|
|
4
|
-
import {
|
|
4
|
+
import { resolveActiveOrganizationId } from "@open-mercato/shared/lib/auth/organizationScope";
|
|
5
5
|
const integrationApiRoutePaths = {
|
|
6
6
|
list: "integrations",
|
|
7
7
|
detail: "integrations/detail",
|
|
@@ -35,7 +35,7 @@ function mergeAdditiveBody(baseBody, candidateBody) {
|
|
|
35
35
|
}
|
|
36
36
|
function getEnricherContext(input) {
|
|
37
37
|
return {
|
|
38
|
-
organizationId:
|
|
38
|
+
organizationId: resolveActiveOrganizationId(input.auth),
|
|
39
39
|
tenantId: input.auth.tenantId,
|
|
40
40
|
userId: input.auth.sub ?? "",
|
|
41
41
|
em: input.container.resolve("em"),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/integrations/api/umes-read.ts"],
|
|
4
|
-
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { NextResponse } from 'next/server'\nimport type { AwilixContainer } from 'awilix'\nimport { runApiInterceptorsAfter, runApiInterceptorsBefore, type RunInterceptorsBeforeResult } from '@open-mercato/shared/lib/crud/interceptor-runner'\nimport { applyResponseEnrichers, applyResponseEnricherToRecord } from '@open-mercato/shared/lib/crud/enricher-runner'\nimport type { ApiInterceptorMethod, InterceptorRequest } from '@open-mercato/shared/lib/crud/api-interceptor'\nimport {
|
|
5
|
-
"mappings": "AACA,SAAS,oBAAoB;AAE7B,SAAS,yBAAyB,gCAAkE;AACpG,SAAS,wBAAwB,qCAAqC;AAEtE,SAAS,
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { NextResponse } from 'next/server'\nimport type { AwilixContainer } from 'awilix'\nimport { runApiInterceptorsAfter, runApiInterceptorsBefore, type RunInterceptorsBeforeResult } from '@open-mercato/shared/lib/crud/interceptor-runner'\nimport { applyResponseEnrichers, applyResponseEnricherToRecord } from '@open-mercato/shared/lib/crud/enricher-runner'\nimport type { ApiInterceptorMethod, InterceptorRequest } from '@open-mercato/shared/lib/crud/api-interceptor'\nimport { resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'\n\nexport const integrationApiRoutePaths = {\n list: 'integrations',\n detail: 'integrations/detail',\n logs: 'integrations/logs',\n} as const\n\ntype ReadRouteFieldConfig = {\n targetEntity: string\n recordKeys?: string[]\n listKeys?: string[]\n}\n\ntype ReadRouteContext = {\n routePath: string\n request: Request\n auth: {\n tenantId: string | null\n orgId: string | null\n sub?: string | null\n features?: unknown\n }\n container: AwilixContainer\n}\n\nfunction headersToObject(headers: Headers): Record<string, string> {\n return Object.fromEntries(headers.entries())\n}\n\nfunction searchParamsToObject(url: URL): Record<string, string> {\n const entries: Record<string, string> = {}\n url.searchParams.forEach((value, key) => {\n entries[key] = value\n })\n return entries\n}\n\nfunction toUserFeatures(features: unknown): string[] {\n if (!Array.isArray(features)) return []\n return features.filter((value): value is string => typeof value === 'string')\n}\n\nfunction mergeAdditiveRecord<T extends Record<string, unknown>>(base: T, candidate: T): T {\n const additions = Object.fromEntries(\n Object.entries(candidate).filter(([key]) => !(key in base)),\n ) as Partial<T>\n\n return {\n ...base,\n ...additions,\n }\n}\n\nfunction mergeAdditiveBody(\n baseBody: Record<string, unknown>,\n candidateBody: Record<string, unknown>,\n): Record<string, unknown> {\n return mergeAdditiveRecord(baseBody, candidateBody)\n}\n\nfunction getEnricherContext(input: ReadRouteContext) {\n return {\n organizationId: resolveActiveOrganizationId(input.auth) as string,\n tenantId: input.auth.tenantId as string,\n userId: input.auth.sub ?? '',\n em: input.container.resolve('em') as EntityManager,\n container: input.container,\n userFeatures: toUserFeatures(input.auth.features),\n }\n}\n\nexport async function runIntegrationsReadBeforeInterceptors(\n input: ReadRouteContext,\n): Promise<RunInterceptorsBeforeResult> {\n const url = new URL(input.request.url)\n\n return runApiInterceptorsBefore({\n routePath: input.routePath,\n method: 'GET',\n request: {\n method: 'GET',\n url: input.request.url,\n headers: headersToObject(input.request.headers),\n query: searchParamsToObject(url),\n },\n context: getEnricherContext(input),\n })\n}\n\nasync function applySafeRecordEnrichment(\n record: Record<string, unknown>,\n targetEntity: string,\n context: ReturnType<typeof getEnricherContext>,\n): Promise<Record<string, unknown>> {\n const enriched = await applyResponseEnricherToRecord(record, targetEntity, context)\n return mergeAdditiveRecord(record, enriched.record)\n}\n\nasync function applySafeListEnrichment(\n items: Record<string, unknown>[],\n targetEntity: string,\n context: ReturnType<typeof getEnricherContext>,\n): Promise<Record<string, unknown>[]> {\n const enriched = await applyResponseEnrichers(items, targetEntity, context)\n return items.map((item, index) => {\n const enrichedItem = enriched.items[index]\n if (!enrichedItem) return item\n return mergeAdditiveRecord(item, enrichedItem)\n })\n}\n\nexport async function finalizeIntegrationsReadResponse(\n input: ReadRouteContext & {\n interceptorRequest: InterceptorRequest\n body: Record<string, unknown>\n enrich?: ReadRouteFieldConfig\n method?: ApiInterceptorMethod\n beforeMetadata?: Record<string, Record<string, unknown> | undefined>\n },\n): Promise<NextResponse> {\n const method = input.method ?? 'GET'\n const baseBody = input.body\n const context = getEnricherContext(input)\n\n const intercepted = await runApiInterceptorsAfter({\n routePath: input.routePath,\n method,\n request: input.interceptorRequest,\n response: {\n statusCode: 200,\n body: baseBody,\n headers: {},\n },\n context,\n metadataByInterceptor: input.beforeMetadata,\n })\n\n if (!intercepted.ok) {\n return NextResponse.json(intercepted.body, { status: intercepted.statusCode, headers: intercepted.headers })\n }\n\n let responseBody = mergeAdditiveBody(baseBody, intercepted.body)\n\n if (input.enrich) {\n const { targetEntity, recordKeys = [], listKeys = [] } = input.enrich\n\n for (const key of recordKeys) {\n const current = responseBody[key]\n if (!current || typeof current !== 'object' || Array.isArray(current)) continue\n responseBody = {\n ...responseBody,\n [key]: await applySafeRecordEnrichment(current as Record<string, unknown>, targetEntity, context),\n }\n }\n\n for (const key of listKeys) {\n const current = responseBody[key]\n if (!Array.isArray(current)) continue\n const records = current.filter(\n (item): item is Record<string, unknown> => typeof item === 'object' && item !== null && !Array.isArray(item),\n )\n if (records.length !== current.length) continue\n responseBody = {\n ...responseBody,\n [key]: await applySafeListEnrichment(records, targetEntity, context),\n }\n }\n }\n\n return NextResponse.json(responseBody, { headers: intercepted.headers })\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
if (!auth) return null;
|
|
3
|
-
const selected = auth.orgId;
|
|
4
|
-
if (typeof selected === "string" && selected.trim().length > 0) return selected;
|
|
5
|
-
const actorOrgId = auth.actorOrgId;
|
|
6
|
-
if (typeof actorOrgId === "string" && actorOrgId.trim().length > 0) return actorOrgId;
|
|
7
|
-
return null;
|
|
8
|
-
}
|
|
1
|
+
import { resolveActiveOrganizationId } from "@open-mercato/shared/lib/auth/organizationScope";
|
|
9
2
|
export {
|
|
10
|
-
resolveIntegrationsOrganizationId
|
|
3
|
+
resolveActiveOrganizationId as resolveIntegrationsOrganizationId
|
|
11
4
|
};
|
|
12
5
|
//# sourceMappingURL=organization-scope.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/integrations/lib/organization-scope.ts"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["/**\n * @deprecated Moved to `@open-mercato/shared/lib/auth/organizationScope` as\n * `resolveActiveOrganizationId`, because `data_sync` needs the same resolution and\n * `integrations` is not the right owner for it. This alias stays for third-party\n * modules that already import from here.\n */\nexport { resolveActiveOrganizationId as resolveIntegrationsOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'\n"],
|
|
5
|
+
"mappings": "AAMA,SAAwC,mCAAyC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
|
|
1
2
|
function appendLine(lines, label, value) {
|
|
2
3
|
if (value === null || value === void 0) return;
|
|
3
4
|
const text = Array.isArray(value) ? value.map((item) => item === null || item === void 0 ? "" : String(item)).filter(Boolean).join(", ") : typeof value === "object" ? JSON.stringify(value) : String(value);
|
|
@@ -19,8 +20,8 @@ function snippet(value, max = 140) {
|
|
|
19
20
|
if (trimmed.length <= max) return trimmed;
|
|
20
21
|
return `${trimmed.slice(0, max - 3)}...`;
|
|
21
22
|
}
|
|
22
|
-
function buildMessagePresenter(record) {
|
|
23
|
-
const title = pickString(record.subject) ?? "Message";
|
|
23
|
+
function buildMessagePresenter(translate, record) {
|
|
24
|
+
const title = pickString(record.subject) ?? translate("messages.search.fallback.title", "Message");
|
|
24
25
|
const body = snippet(record.body);
|
|
25
26
|
const externalName = pickString(record.external_name, record.externalName);
|
|
26
27
|
const subtitle = [externalName, body].filter(Boolean).join(" \xB7 ") || void 0;
|
|
@@ -28,7 +29,7 @@ function buildMessagePresenter(record) {
|
|
|
28
29
|
title: String(title),
|
|
29
30
|
subtitle,
|
|
30
31
|
icon: "mail",
|
|
31
|
-
badge: "Message"
|
|
32
|
+
badge: translate("messages.search.badge.message", "Message")
|
|
32
33
|
};
|
|
33
34
|
}
|
|
34
35
|
const searchConfig = {
|
|
@@ -38,6 +39,7 @@ const searchConfig = {
|
|
|
38
39
|
enabled: true,
|
|
39
40
|
priority: 5,
|
|
40
41
|
buildSource: async (ctx) => {
|
|
42
|
+
const { t } = await resolveTranslations();
|
|
41
43
|
const record = ctx.record;
|
|
42
44
|
const lines = [];
|
|
43
45
|
appendLine(lines, "Subject", record.subject);
|
|
@@ -46,7 +48,7 @@ const searchConfig = {
|
|
|
46
48
|
if (!lines.length) return null;
|
|
47
49
|
return {
|
|
48
50
|
text: lines,
|
|
49
|
-
presenter: buildMessagePresenter(record),
|
|
51
|
+
presenter: buildMessagePresenter(t, record),
|
|
50
52
|
checksumSource: {
|
|
51
53
|
record: {
|
|
52
54
|
subject: record.subject,
|
|
@@ -57,7 +59,10 @@ const searchConfig = {
|
|
|
57
59
|
}
|
|
58
60
|
};
|
|
59
61
|
},
|
|
60
|
-
formatResult: async (ctx) =>
|
|
62
|
+
formatResult: async (ctx) => {
|
|
63
|
+
const { t } = await resolveTranslations();
|
|
64
|
+
return buildMessagePresenter(t, ctx.record);
|
|
65
|
+
},
|
|
61
66
|
resolveUrl: async (ctx) => {
|
|
62
67
|
const id = pickString(ctx.record.id);
|
|
63
68
|
return id ? `/backend/messages/${encodeURIComponent(id)}` : null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/modules/messages/search.ts"],
|
|
4
|
-
"sourcesContent": ["import type {\n SearchModuleConfig,\n SearchBuildContext,\n SearchIndexSource,\n SearchResultPresenter,\n} from '@open-mercato/shared/modules/search'\n\nfunction appendLine(lines: string[], label: string, value: unknown) {\n if (value === null || value === undefined) return\n const text = Array.isArray(value)\n ? value.map((item) => (item === null || item === undefined ? '' : String(item))).filter(Boolean).join(', ')\n : (typeof value === 'object' ? JSON.stringify(value) : String(value))\n if (!text.trim()) return\n lines.push(`${label}: ${text}`)\n}\n\nfunction pickString(...candidates: Array<unknown>): string | null {\n for (const candidate of candidates) {\n if (typeof candidate !== 'string') continue\n const trimmed = candidate.trim()\n if (trimmed.length > 0) return trimmed\n }\n return null\n}\n\nfunction snippet(value: unknown, max = 140): string | undefined {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n if (!trimmed.length) return undefined\n if (trimmed.length <= max) return trimmed\n return `${trimmed.slice(0, max - 3)}...`\n}\n\nfunction buildMessagePresenter(record: Record<string, unknown>): SearchResultPresenter {\n const title = pickString(record.subject) ?? 'Message'\n const body = snippet(record.body)\n const externalName = pickString(record.external_name, record.externalName)\n const subtitle = [externalName, body].filter(Boolean).join(' \u00B7 ') || undefined\n return {\n title: String(title),\n subtitle,\n icon: 'mail',\n badge: 'Message',\n }\n}\n\nexport const searchConfig: SearchModuleConfig = {\n entities: [\n {\n entityId: 'messages:message',\n enabled: true,\n priority: 5,\n buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Subject', record.subject)\n appendLine(lines, 'Body', record.body)\n appendLine(lines, 'From name', record.external_name ?? record.externalName)\n if (!lines.length) return null\n return {\n text: lines,\n presenter: buildMessagePresenter(record),\n checksumSource: {\n record: {\n subject: record.subject,\n body: record.body,\n external_name: record.external_name ?? record.externalName,\n external_email_hash: record.external_email_hash ?? record.externalEmailHash,\n },\n },\n }\n },\n formatResult: async (ctx) => buildMessagePresenter(ctx.record),\n resolveUrl: async (ctx) => {\n const id = pickString(ctx.record.id)\n return id ? `/backend/messages/${encodeURIComponent(id)}` : null\n },\n fieldPolicy: {\n searchable: ['subject', 'body', 'external_name'],\n hashOnly: ['external_email'],\n excluded: ['action_data', 'action_result'],\n },\n },\n ],\n}\n\nexport default searchConfig\nexport const config = searchConfig\n"],
|
|
5
|
-
"mappings": "AAOA,SAAS,WAAW,OAAiB,OAAe,OAAgB;AAClE,MAAI,UAAU,QAAQ,UAAU,OAAW;AAC3C,QAAM,OAAO,MAAM,QAAQ,KAAK,IAC5B,MAAM,IAAI,CAAC,SAAU,SAAS,QAAQ,SAAS,SAAY,KAAK,OAAO,IAAI,CAAE,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,IACvG,OAAO,UAAU,WAAW,KAAK,UAAU,KAAK,IAAI,OAAO,KAAK;AACrE,MAAI,CAAC,KAAK,KAAK,EAAG;AAClB,QAAM,KAAK,GAAG,KAAK,KAAK,IAAI,EAAE;AAChC;AAEA,SAAS,cAAc,YAA2C;AAChE,aAAW,aAAa,YAAY;AAClC,QAAI,OAAO,cAAc,SAAU;AACnC,UAAM,UAAU,UAAU,KAAK;AAC/B,QAAI,QAAQ,SAAS,EAAG,QAAO;AAAA,EACjC;AACA,SAAO;AACT;AAEA,SAAS,QAAQ,OAAgB,MAAM,KAAyB;AAC9D,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,MAAI,QAAQ,UAAU,IAAK,QAAO;AAClC,SAAO,GAAG,QAAQ,MAAM,GAAG,MAAM,CAAC,CAAC;AACrC;AAEA,SAAS,sBAAsB,QAAwD;
|
|
4
|
+
"sourcesContent": ["import type {\n SearchModuleConfig,\n SearchBuildContext,\n SearchIndexSource,\n SearchResultPresenter,\n} from '@open-mercato/shared/modules/search'\nimport type { TranslateFn } from '@open-mercato/shared/lib/i18n/context'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\n\nfunction appendLine(lines: string[], label: string, value: unknown) {\n if (value === null || value === undefined) return\n const text = Array.isArray(value)\n ? value.map((item) => (item === null || item === undefined ? '' : String(item))).filter(Boolean).join(', ')\n : (typeof value === 'object' ? JSON.stringify(value) : String(value))\n if (!text.trim()) return\n lines.push(`${label}: ${text}`)\n}\n\nfunction pickString(...candidates: Array<unknown>): string | null {\n for (const candidate of candidates) {\n if (typeof candidate !== 'string') continue\n const trimmed = candidate.trim()\n if (trimmed.length > 0) return trimmed\n }\n return null\n}\n\nfunction snippet(value: unknown, max = 140): string | undefined {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n if (!trimmed.length) return undefined\n if (trimmed.length <= max) return trimmed\n return `${trimmed.slice(0, max - 3)}...`\n}\n\nfunction buildMessagePresenter(translate: TranslateFn, record: Record<string, unknown>): SearchResultPresenter {\n const title = pickString(record.subject) ?? translate('messages.search.fallback.title', 'Message')\n const body = snippet(record.body)\n const externalName = pickString(record.external_name, record.externalName)\n const subtitle = [externalName, body].filter(Boolean).join(' \u00B7 ') || undefined\n return {\n title: String(title),\n subtitle,\n icon: 'mail',\n badge: translate('messages.search.badge.message', 'Message'),\n }\n}\n\nexport const searchConfig: SearchModuleConfig = {\n entities: [\n {\n entityId: 'messages:message',\n enabled: true,\n priority: 5,\n buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {\n const { t } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Subject', record.subject)\n appendLine(lines, 'Body', record.body)\n appendLine(lines, 'From name', record.external_name ?? record.externalName)\n if (!lines.length) return null\n return {\n text: lines,\n presenter: buildMessagePresenter(t, record),\n checksumSource: {\n record: {\n subject: record.subject,\n body: record.body,\n external_name: record.external_name ?? record.externalName,\n external_email_hash: record.external_email_hash ?? record.externalEmailHash,\n },\n },\n }\n },\n formatResult: async (ctx) => {\n const { t } = await resolveTranslations()\n return buildMessagePresenter(t, ctx.record)\n },\n resolveUrl: async (ctx) => {\n const id = pickString(ctx.record.id)\n return id ? `/backend/messages/${encodeURIComponent(id)}` : null\n },\n fieldPolicy: {\n searchable: ['subject', 'body', 'external_name'],\n hashOnly: ['external_email'],\n excluded: ['action_data', 'action_result'],\n },\n },\n ],\n}\n\nexport default searchConfig\nexport const config = searchConfig\n"],
|
|
5
|
+
"mappings": "AAOA,SAAS,2BAA2B;AAEpC,SAAS,WAAW,OAAiB,OAAe,OAAgB;AAClE,MAAI,UAAU,QAAQ,UAAU,OAAW;AAC3C,QAAM,OAAO,MAAM,QAAQ,KAAK,IAC5B,MAAM,IAAI,CAAC,SAAU,SAAS,QAAQ,SAAS,SAAY,KAAK,OAAO,IAAI,CAAE,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,IACvG,OAAO,UAAU,WAAW,KAAK,UAAU,KAAK,IAAI,OAAO,KAAK;AACrE,MAAI,CAAC,KAAK,KAAK,EAAG;AAClB,QAAM,KAAK,GAAG,KAAK,KAAK,IAAI,EAAE;AAChC;AAEA,SAAS,cAAc,YAA2C;AAChE,aAAW,aAAa,YAAY;AAClC,QAAI,OAAO,cAAc,SAAU;AACnC,UAAM,UAAU,UAAU,KAAK;AAC/B,QAAI,QAAQ,SAAS,EAAG,QAAO;AAAA,EACjC;AACA,SAAO;AACT;AAEA,SAAS,QAAQ,OAAgB,MAAM,KAAyB;AAC9D,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,MAAI,QAAQ,UAAU,IAAK,QAAO;AAClC,SAAO,GAAG,QAAQ,MAAM,GAAG,MAAM,CAAC,CAAC;AACrC;AAEA,SAAS,sBAAsB,WAAwB,QAAwD;AAC7G,QAAM,QAAQ,WAAW,OAAO,OAAO,KAAK,UAAU,kCAAkC,SAAS;AACjG,QAAM,OAAO,QAAQ,OAAO,IAAI;AAChC,QAAM,eAAe,WAAW,OAAO,eAAe,OAAO,YAAY;AACzE,QAAM,WAAW,CAAC,cAAc,IAAI,EAAE,OAAO,OAAO,EAAE,KAAK,QAAK,KAAK;AACrE,SAAO;AAAA,IACL,OAAO,OAAO,KAAK;AAAA,IACnB;AAAA,IACA,MAAM;AAAA,IACN,OAAO,UAAU,iCAAiC,SAAS;AAAA,EAC7D;AACF;AAEO,MAAM,eAAmC;AAAA,EAC9C,UAAU;AAAA,IACR;AAAA,MACE,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU;AAAA,MACV,aAAa,OAAO,QAA+D;AACjF,cAAM,EAAE,EAAE,IAAI,MAAM,oBAAoB;AACxC,cAAM,SAAS,IAAI;AACnB,cAAM,QAAkB,CAAC;AACzB,mBAAW,OAAO,WAAW,OAAO,OAAO;AAC3C,mBAAW,OAAO,QAAQ,OAAO,IAAI;AACrC,mBAAW,OAAO,aAAa,OAAO,iBAAiB,OAAO,YAAY;AAC1E,YAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,eAAO;AAAA,UACL,MAAM;AAAA,UACN,WAAW,sBAAsB,GAAG,MAAM;AAAA,UAC1C,gBAAgB;AAAA,YACd,QAAQ;AAAA,cACN,SAAS,OAAO;AAAA,cAChB,MAAM,OAAO;AAAA,cACb,eAAe,OAAO,iBAAiB,OAAO;AAAA,cAC9C,qBAAqB,OAAO,uBAAuB,OAAO;AAAA,YAC5D;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,MACA,cAAc,OAAO,QAAQ;AAC3B,cAAM,EAAE,EAAE,IAAI,MAAM,oBAAoB;AACxC,eAAO,sBAAsB,GAAG,IAAI,MAAM;AAAA,MAC5C;AAAA,MACA,YAAY,OAAO,QAAQ;AACzB,cAAM,KAAK,WAAW,IAAI,OAAO,EAAE;AACnC,eAAO,KAAK,qBAAqB,mBAAmB,EAAE,CAAC,KAAK;AAAA,MAC9D;AAAA,MACA,aAAa;AAAA,QACX,YAAY,CAAC,WAAW,QAAQ,eAAe;AAAA,QAC/C,UAAU,CAAC,gBAAgB;AAAA,QAC3B,UAAU,CAAC,eAAe,eAAe;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,iBAAQ;AACR,MAAM,SAAS;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -9,6 +9,7 @@ import { getPaymentGatewayQueue } from "../../../lib/queue.js";
|
|
|
9
9
|
import { processPaymentGatewayWebhookJob } from "../../../lib/webhook-processor.js";
|
|
10
10
|
import { paymentGatewaysTag } from "../../openapi.js";
|
|
11
11
|
import { createLogger } from "@open-mercato/shared/lib/logger";
|
|
12
|
+
import { readBoundedRequestBody, WebhookBodyTooLargeError } from "@open-mercato/shared/lib/webhooks";
|
|
12
13
|
const logger = createLogger("payment_gateways").child({ component: "webhook" });
|
|
13
14
|
const metadata = {
|
|
14
15
|
path: "/payment_gateways/webhook/[provider]",
|
|
@@ -30,7 +31,15 @@ async function POST(req, { params }) {
|
|
|
30
31
|
}
|
|
31
32
|
const rateLimitResponse = await checkProviderWebhookRateLimit(container, req, providerKey);
|
|
32
33
|
if (rateLimitResponse) return rateLimitResponse;
|
|
33
|
-
|
|
34
|
+
let rawBody;
|
|
35
|
+
try {
|
|
36
|
+
rawBody = registration.maxBodyBytes === void 0 ? await req.text() : await readBoundedRequestBody(req, { maxBytes: registration.maxBodyBytes });
|
|
37
|
+
} catch (error) {
|
|
38
|
+
if (error instanceof WebhookBodyTooLargeError) {
|
|
39
|
+
return NextResponse.json({ error: "Webhook payload too large" }, { status: 413 });
|
|
40
|
+
}
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
34
43
|
const headers = {};
|
|
35
44
|
req.headers.forEach((value, key) => {
|
|
36
45
|
headers[key] = value;
|
|
@@ -126,6 +135,7 @@ const openApi = {
|
|
|
126
135
|
responses: [
|
|
127
136
|
{ status: 202, description: "Webhook accepted for async processing" },
|
|
128
137
|
{ status: 401, description: "Signature verification failed" },
|
|
138
|
+
{ status: 413, description: "Webhook payload too large" },
|
|
129
139
|
{ status: 404, description: "Unknown provider" }
|
|
130
140
|
]
|
|
131
141
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/payment_gateways/api/webhook/%5Bprovider%5D/route.ts"],
|
|
4
|
-
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { checkRateLimit, getClientIp, RATE_LIMIT_ERROR_FALLBACK } from '@open-mercato/shared/lib/ratelimit/helpers'\nimport type { RateLimiterService } from '@open-mercato/shared/lib/ratelimit/service'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { getWebhookHandler } from '@open-mercato/shared/modules/payment_gateways/types'\nimport type { IntegrationLogService } from '../../../../integrations/lib/log-service'\nimport type { PaymentGatewayService } from '../../../lib/gateway-service'\nimport type { CredentialsService } from '../../../../integrations/lib/credentials-service'\nimport { GatewayTransaction } from '../../../data/entities'\nimport { getPaymentGatewayQueue } from '../../../lib/queue'\nimport { processPaymentGatewayWebhookJob } from '../../../lib/webhook-processor'\nimport { paymentGatewaysTag } from '../../openapi'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('payment_gateways').child({ component: 'webhook' })\n\nexport const metadata = {\n path: '/payment_gateways/webhook/[provider]',\n POST: { requireAuth: false },\n}\n\nconst WEBHOOK_VERIFICATION_FAILED = 'Webhook verification failed'\n\nconst paymentGatewayWebhookRateLimitConfig = {\n points: 60,\n duration: 60,\n keyPrefix: 'payment_gateways:webhook',\n}\n\nexport async function POST(req: Request, { params }: { params: Promise<{ provider: string }> | { provider: string } }) {\n const resolvedParams = await params\n const providerKey = resolvedParams.provider\n const container = await createRequestContainer()\n const registration = getWebhookHandler(providerKey)\n if (!registration) {\n return NextResponse.json({ error: `No webhook handler for provider: ${providerKey}` }, { status: 404 })\n }\n\n const rateLimitResponse = await checkProviderWebhookRateLimit(container, req, providerKey)\n if (rateLimitResponse) return rateLimitResponse\n\n
|
|
5
|
-
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,8BAA8B;AACvC,SAAS,0BAA0B;AACnC,SAAS,oBAAoB;AAC7B,SAAS,gBAAgB,aAAa,iCAAiC;AAGvE,SAAS,yBAAyB;AAIlC,SAAS,0BAA0B;AACnC,SAAS,8BAA8B;AACvC,SAAS,uCAAuC;AAChD,SAAS,0BAA0B;AACnC,SAAS,oBAAoB;
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { checkRateLimit, getClientIp, RATE_LIMIT_ERROR_FALLBACK } from '@open-mercato/shared/lib/ratelimit/helpers'\nimport type { RateLimiterService } from '@open-mercato/shared/lib/ratelimit/service'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { getWebhookHandler } from '@open-mercato/shared/modules/payment_gateways/types'\nimport type { IntegrationLogService } from '../../../../integrations/lib/log-service'\nimport type { PaymentGatewayService } from '../../../lib/gateway-service'\nimport type { CredentialsService } from '../../../../integrations/lib/credentials-service'\nimport { GatewayTransaction } from '../../../data/entities'\nimport { getPaymentGatewayQueue } from '../../../lib/queue'\nimport { processPaymentGatewayWebhookJob } from '../../../lib/webhook-processor'\nimport { paymentGatewaysTag } from '../../openapi'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { readBoundedRequestBody, WebhookBodyTooLargeError } from '@open-mercato/shared/lib/webhooks'\n\nconst logger = createLogger('payment_gateways').child({ component: 'webhook' })\n\nexport const metadata = {\n path: '/payment_gateways/webhook/[provider]',\n POST: { requireAuth: false },\n}\n\nconst WEBHOOK_VERIFICATION_FAILED = 'Webhook verification failed'\n\nconst paymentGatewayWebhookRateLimitConfig = {\n points: 60,\n duration: 60,\n keyPrefix: 'payment_gateways:webhook',\n}\n\nexport async function POST(req: Request, { params }: { params: Promise<{ provider: string }> | { provider: string } }) {\n const resolvedParams = await params\n const providerKey = resolvedParams.provider\n const container = await createRequestContainer()\n const registration = getWebhookHandler(providerKey)\n if (!registration) {\n return NextResponse.json({ error: `No webhook handler for provider: ${providerKey}` }, { status: 404 })\n }\n\n const rateLimitResponse = await checkProviderWebhookRateLimit(container, req, providerKey)\n if (rateLimitResponse) return rateLimitResponse\n\n let rawBody: string\n try {\n rawBody = registration.maxBodyBytes === undefined\n ? await req.text()\n : await readBoundedRequestBody(req, { maxBytes: registration.maxBodyBytes })\n } catch (error) {\n if (error instanceof WebhookBodyTooLargeError) {\n return NextResponse.json({ error: 'Webhook payload too large' }, { status: 413 })\n }\n throw error\n }\n const headers: Record<string, string> = {}\n req.headers.forEach((value, key) => {\n headers[key] = value\n })\n\n const service = container.resolve('paymentGatewayService') as PaymentGatewayService\n const em = container.resolve('em') as EntityManager\n const integrationCredentialsService = container.resolve('integrationCredentialsService') as CredentialsService\n const queue = getPaymentGatewayQueue(registration.queue ?? 'payment-gateways-webhook')\n const payload = await readJsonSafe<Record<string, unknown>>(rawBody)\n const sessionIdHint = registration.readSessionIdHint?.(payload) ?? null\n\n try {\n // The webhook endpoint is unauthenticated. Tenant/organization scope MUST come from a\n // GatewayTransaction whose per-tenant credentials successfully verify the inbound\n // signature \u2014 NEVER from attacker-controlled payload metadata. If no candidate\n // transaction can be located by the provider-reported session id, or no candidate's\n // credentials can verify the signature, we fail closed with 401. This prevents\n // forged webhooks (e.g. mock gateway PoC) from mutating another tenant's payment\n // state via `event.data.metadata.{organizationId,tenantId}`.\n const candidates = sessionIdHint\n ? await findWithDecryption(\n em,\n GatewayTransaction,\n {\n providerKey,\n providerSessionId: sessionIdHint,\n deletedAt: null,\n },\n { limit: 10, orderBy: { createdAt: 'desc' } },\n )\n : []\n\n let transaction: GatewayTransaction | null = null\n let matchedScope: { organizationId: string; tenantId: string } | null = null\n let event: Awaited<ReturnType<typeof registration.handler>> | null = null\n let lastVerificationError: unknown = null\n\n for (const candidate of candidates) {\n const candidateScope = { organizationId: candidate.organizationId, tenantId: candidate.tenantId }\n const credentials = await integrationCredentialsService.resolve(`gateway_${providerKey}`, candidateScope) ?? {}\n try {\n event = await registration.handler({ rawBody, headers, credentials })\n transaction = candidate\n matchedScope = candidateScope\n break\n } catch (error: unknown) {\n lastVerificationError = error\n }\n }\n\n if (!event || !transaction || !matchedScope) {\n throw lastVerificationError ?? new Error('Webhook verification failed: no matching transaction')\n }\n\n const scope = matchedScope\n\n const jobPayload = {\n providerKey,\n event,\n transactionId: transaction.id,\n scope,\n }\n\n if (process.env.QUEUE_STRATEGY === 'async') {\n await queue.enqueue({\n name: 'payment-gateway-webhook',\n payload: jobPayload,\n })\n } else {\n await processPaymentGatewayWebhookJob(\n {\n em: container.resolve('em') as EntityManager,\n paymentGatewayService: service,\n integrationLogService: container.resolve('integrationLogService') as IntegrationLogService,\n },\n jobPayload,\n )\n }\n\n return NextResponse.json({ received: true, queued: true }, { status: 202 })\n } catch (err: unknown) {\n logger.warn('Webhook verification failed', { providerKey, err })\n return NextResponse.json({ error: WEBHOOK_VERIFICATION_FAILED }, { status: 401 })\n }\n}\n\nasync function checkProviderWebhookRateLimit(\n container: { resolve: (name: string) => unknown },\n req: Request,\n providerKey: string,\n): Promise<NextResponse | null> {\n const rateLimiterService = tryResolve<RateLimiterService>(container, 'rateLimiterService')\n if (!rateLimiterService) return null\n\n return checkRateLimit(\n rateLimiterService,\n paymentGatewayWebhookRateLimitConfig,\n `${providerKey}:${getClientIp(req, rateLimiterService.trustProxyDepth) ?? 'unknown'}`,\n RATE_LIMIT_ERROR_FALLBACK,\n )\n}\n\nfunction tryResolve<T>(container: { resolve: (name: string) => unknown }, name: string): T | null {\n try {\n return container.resolve(name) as T\n } catch {\n return null\n }\n}\n\nexport const openApi = {\n tags: [paymentGatewaysTag],\n summary: 'Receive payment gateway webhook',\n methods: {\n POST: {\n summary: 'Process inbound webhook from payment provider',\n tags: [paymentGatewaysTag],\n responses: [\n { status: 202, description: 'Webhook accepted for async processing' },\n { status: 401, description: 'Signature verification failed' },\n { status: 413, description: 'Webhook payload too large' },\n { status: 404, description: 'Unknown provider' },\n ],\n },\n },\n}\n\nexport default POST\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -205,6 +205,10 @@ GatewaySessionInitialization = __decorateClass([
|
|
|
205
205
|
Unique({
|
|
206
206
|
name: "gateway_session_initializations_scope_operation_unique",
|
|
207
207
|
properties: ["operationKey", "providerKey", "organizationId", "tenantId"]
|
|
208
|
+
}),
|
|
209
|
+
Index({
|
|
210
|
+
name: "gateway_session_initializations_prune_idx",
|
|
211
|
+
expression: 'create index "gateway_session_initializations_prune_idx" on "gateway_session_initializations" ("tenant_id", "organization_id", "updated_at") where "gateway_transaction_id" is not null'
|
|
208
212
|
})
|
|
209
213
|
], GatewaySessionInitialization);
|
|
210
214
|
OptionalProps;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/payment_gateways/data/entities.ts"],
|
|
4
|
-
"sourcesContent": ["import { OptionalProps } from '@mikro-orm/core'\nimport { Entity, Index, PrimaryKey, Property, Unique } from '@mikro-orm/decorators/legacy'\n\n@Entity({ tableName: 'gateway_transactions' })\n@Index({ properties: ['paymentId', 'organizationId', 'tenantId'] })\n@Index({ properties: ['providerKey', 'providerSessionId', 'organizationId'] })\n@Index({ properties: ['organizationId', 'tenantId', 'unifiedStatus'] })\nexport class GatewayTransaction {\n [OptionalProps]?: 'unifiedStatus' | 'gatewayStatus' | 'providerSessionId' | 'gatewayPaymentId' | 'gatewayRefundId' | 'redirectUrl' | 'clientSecret' | 'capturedAmount' | 'gatewayMetadata' | 'webhookLog' | 'lastWebhookAt' | 'lastPolledAt' | 'expiresAt' | 'createdAt' | 'updatedAt' | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'payment_id', type: 'uuid' })\n paymentId!: string\n\n @Property({ name: 'provider_key', type: 'text' })\n providerKey!: string\n\n @Property({ name: 'provider_session_id', type: 'text', nullable: true })\n providerSessionId?: string | null\n\n @Property({ name: 'gateway_payment_id', type: 'text', nullable: true })\n gatewayPaymentId?: string | null\n\n @Property({ name: 'gateway_refund_id', type: 'text', nullable: true })\n gatewayRefundId?: string | null\n\n @Property({ name: 'unified_status', type: 'text' })\n unifiedStatus: string = 'pending'\n\n @Property({ name: 'gateway_status', type: 'text', nullable: true })\n gatewayStatus?: string | null\n\n @Property({ name: 'redirect_url', type: 'text', nullable: true })\n redirectUrl?: string | null\n\n @Property({ name: 'client_secret', type: 'text', nullable: true })\n clientSecret?: string | null\n\n @Property({ name: 'amount', type: 'numeric', precision: 18, scale: 4 })\n amount!: string\n\n @Property({ name: 'captured_amount', type: 'numeric', precision: 18, scale: 4, default: '0' })\n capturedAmount: string = '0'\n\n @Property({ name: 'currency_code', type: 'text' })\n currencyCode!: string\n\n @Property({ name: 'gateway_metadata', type: 'jsonb', nullable: true })\n gatewayMetadata?: Record<string, unknown> | null\n\n @Property({ name: 'webhook_log', type: 'jsonb', nullable: true })\n webhookLog?: Array<{ eventType: string; receivedAt: string; idempotencyKey: string; unifiedStatus: string; processed: boolean }> | null\n\n @Property({ name: 'last_webhook_at', type: Date, nullable: true })\n lastWebhookAt?: Date | null\n\n @Property({ name: 'last_polled_at', type: Date, nullable: true })\n lastPolledAt?: Date | null\n\n @Property({ name: 'expires_at', type: Date, nullable: true })\n expiresAt?: Date | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'gateway_payment_operations' })\n@Unique({\n name: 'gateway_payment_operations_scope_operation_unique',\n properties: ['operationId', 'organizationId', 'tenantId'],\n})\n@Index({ properties: ['transactionId', 'operationType', 'organizationId', 'tenantId'] })\n@Index({ properties: ['status', 'leaseExpiresAt'] })\nexport class GatewayPaymentOperation {\n [OptionalProps]?: 'status' | 'attemptCount' | 'result' | 'reservedAmount' | 'leaseExpiresAt' | 'createdAt' | 'updatedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'operation_id', type: 'text' })\n operationId!: string\n\n @Property({ name: 'transaction_id', type: 'uuid' })\n transactionId!: string\n\n @Property({ name: 'operation_type', type: 'text' })\n operationType!: string\n\n @Property({ name: 'provider_key', type: 'text' })\n providerKey!: string\n\n @Property({ name: 'request_hash', type: 'text' })\n requestHash!: string\n\n @Property({ name: 'provider_idempotency_key', type: 'text' })\n providerIdempotencyKey!: string\n\n @Property({ name: 'status', type: 'text' })\n status: string = 'in_progress'\n\n @Property({ name: 'attempt_token', type: 'text' })\n attemptToken!: string\n\n @Property({ name: 'attempt_count', type: 'integer' })\n attemptCount: number = 1\n\n @Property({ name: 'result', type: 'jsonb', nullable: true })\n result?: Record<string, unknown> | null\n\n @Property({ name: 'reserved_amount', type: 'numeric', precision: 18, scale: 4, nullable: true })\n reservedAmount?: string | null\n\n @Property({ name: 'lease_expires_at', type: Date, nullable: true })\n leaseExpiresAt?: Date | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onCreate: () => new Date(), onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n@Entity({ tableName: 'gateway_session_initializations' })\n@Unique({\n name: 'gateway_session_initializations_scope_operation_unique',\n properties: ['operationKey', 'providerKey', 'organizationId', 'tenantId'],\n})\nexport class GatewaySessionInitialization {\n [OptionalProps]?: 'claimToken' | 'claimedAt' | 'gatewayTransactionId' | 'createdAt' | 'updatedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'operation_key', type: 'text' })\n operationKey!: string\n\n @Property({ name: 'provider_key', type: 'text' })\n providerKey!: string\n\n @Property({ name: 'claim_token', type: 'uuid', nullable: true })\n claimToken?: string | null\n\n @Property({ name: 'claimed_at', type: Date, nullable: true })\n claimedAt?: Date | null\n\n @Property({ name: 'gateway_transaction_id', type: 'uuid', nullable: true })\n gatewayTransactionId?: string | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onCreate: () => new Date(), onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n@Entity({ tableName: 'gateway_webhook_events' })\n@Unique({\n name: 'gateway_webhook_events_idempotency_unique',\n properties: ['idempotencyKey', 'providerKey', 'organizationId', 'tenantId'],\n})\nexport class WebhookProcessedEvent {\n [OptionalProps]?: 'processedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'provider_key', type: 'text' })\n providerKey!: string\n\n @Property({ name: 'idempotency_key', type: 'text' })\n idempotencyKey!: string\n\n @Property({ name: 'event_type', type: 'text' })\n eventType!: string\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'processed_at', type: Date, onCreate: () => new Date() })\n processedAt: Date = new Date()\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import { OptionalProps } from '@mikro-orm/core'\nimport { Entity, Index, PrimaryKey, Property, Unique } from '@mikro-orm/decorators/legacy'\n\n@Entity({ tableName: 'gateway_transactions' })\n@Index({ properties: ['paymentId', 'organizationId', 'tenantId'] })\n@Index({ properties: ['providerKey', 'providerSessionId', 'organizationId'] })\n@Index({ properties: ['organizationId', 'tenantId', 'unifiedStatus'] })\nexport class GatewayTransaction {\n [OptionalProps]?: 'unifiedStatus' | 'gatewayStatus' | 'providerSessionId' | 'gatewayPaymentId' | 'gatewayRefundId' | 'redirectUrl' | 'clientSecret' | 'capturedAmount' | 'gatewayMetadata' | 'webhookLog' | 'lastWebhookAt' | 'lastPolledAt' | 'expiresAt' | 'createdAt' | 'updatedAt' | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'payment_id', type: 'uuid' })\n paymentId!: string\n\n @Property({ name: 'provider_key', type: 'text' })\n providerKey!: string\n\n @Property({ name: 'provider_session_id', type: 'text', nullable: true })\n providerSessionId?: string | null\n\n @Property({ name: 'gateway_payment_id', type: 'text', nullable: true })\n gatewayPaymentId?: string | null\n\n @Property({ name: 'gateway_refund_id', type: 'text', nullable: true })\n gatewayRefundId?: string | null\n\n @Property({ name: 'unified_status', type: 'text' })\n unifiedStatus: string = 'pending'\n\n @Property({ name: 'gateway_status', type: 'text', nullable: true })\n gatewayStatus?: string | null\n\n @Property({ name: 'redirect_url', type: 'text', nullable: true })\n redirectUrl?: string | null\n\n @Property({ name: 'client_secret', type: 'text', nullable: true })\n clientSecret?: string | null\n\n @Property({ name: 'amount', type: 'numeric', precision: 18, scale: 4 })\n amount!: string\n\n @Property({ name: 'captured_amount', type: 'numeric', precision: 18, scale: 4, default: '0' })\n capturedAmount: string = '0'\n\n @Property({ name: 'currency_code', type: 'text' })\n currencyCode!: string\n\n @Property({ name: 'gateway_metadata', type: 'jsonb', nullable: true })\n gatewayMetadata?: Record<string, unknown> | null\n\n @Property({ name: 'webhook_log', type: 'jsonb', nullable: true })\n webhookLog?: Array<{ eventType: string; receivedAt: string; idempotencyKey: string; unifiedStatus: string; processed: boolean }> | null\n\n @Property({ name: 'last_webhook_at', type: Date, nullable: true })\n lastWebhookAt?: Date | null\n\n @Property({ name: 'last_polled_at', type: Date, nullable: true })\n lastPolledAt?: Date | null\n\n @Property({ name: 'expires_at', type: Date, nullable: true })\n expiresAt?: Date | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'gateway_payment_operations' })\n@Unique({\n name: 'gateway_payment_operations_scope_operation_unique',\n properties: ['operationId', 'organizationId', 'tenantId'],\n})\n@Index({ properties: ['transactionId', 'operationType', 'organizationId', 'tenantId'] })\n@Index({ properties: ['status', 'leaseExpiresAt'] })\nexport class GatewayPaymentOperation {\n [OptionalProps]?: 'status' | 'attemptCount' | 'result' | 'reservedAmount' | 'leaseExpiresAt' | 'createdAt' | 'updatedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'operation_id', type: 'text' })\n operationId!: string\n\n @Property({ name: 'transaction_id', type: 'uuid' })\n transactionId!: string\n\n @Property({ name: 'operation_type', type: 'text' })\n operationType!: string\n\n @Property({ name: 'provider_key', type: 'text' })\n providerKey!: string\n\n @Property({ name: 'request_hash', type: 'text' })\n requestHash!: string\n\n @Property({ name: 'provider_idempotency_key', type: 'text' })\n providerIdempotencyKey!: string\n\n @Property({ name: 'status', type: 'text' })\n status: string = 'in_progress'\n\n @Property({ name: 'attempt_token', type: 'text' })\n attemptToken!: string\n\n @Property({ name: 'attempt_count', type: 'integer' })\n attemptCount: number = 1\n\n @Property({ name: 'result', type: 'jsonb', nullable: true })\n result?: Record<string, unknown> | null\n\n @Property({ name: 'reserved_amount', type: 'numeric', precision: 18, scale: 4, nullable: true })\n reservedAmount?: string | null\n\n @Property({ name: 'lease_expires_at', type: Date, nullable: true })\n leaseExpiresAt?: Date | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onCreate: () => new Date(), onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n@Entity({ tableName: 'gateway_session_initializations' })\n@Unique({\n name: 'gateway_session_initializations_scope_operation_unique',\n properties: ['operationKey', 'providerKey', 'organizationId', 'tenantId'],\n})\n@Index({\n name: 'gateway_session_initializations_prune_idx',\n expression:\n 'create index \"gateway_session_initializations_prune_idx\" on \"gateway_session_initializations\" (\"tenant_id\", \"organization_id\", \"updated_at\") where \"gateway_transaction_id\" is not null',\n})\nexport class GatewaySessionInitialization {\n [OptionalProps]?: 'claimToken' | 'claimedAt' | 'gatewayTransactionId' | 'createdAt' | 'updatedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'operation_key', type: 'text' })\n operationKey!: string\n\n @Property({ name: 'provider_key', type: 'text' })\n providerKey!: string\n\n @Property({ name: 'claim_token', type: 'uuid', nullable: true })\n claimToken?: string | null\n\n @Property({ name: 'claimed_at', type: Date, nullable: true })\n claimedAt?: Date | null\n\n @Property({ name: 'gateway_transaction_id', type: 'uuid', nullable: true })\n gatewayTransactionId?: string | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onCreate: () => new Date(), onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n@Entity({ tableName: 'gateway_webhook_events' })\n@Unique({\n name: 'gateway_webhook_events_idempotency_unique',\n properties: ['idempotencyKey', 'providerKey', 'organizationId', 'tenantId'],\n})\nexport class WebhookProcessedEvent {\n [OptionalProps]?: 'processedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'provider_key', type: 'text' })\n providerKey!: string\n\n @Property({ name: 'idempotency_key', type: 'text' })\n idempotencyKey!: string\n\n @Property({ name: 'event_type', type: 'text' })\n eventType!: string\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'processed_at', type: Date, onCreate: () => new Date() })\n processedAt: Date = new Date()\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;AAAA,SAAS,qBAAqB;AAC9B,SAAS,QAAQ,OAAO,YAAY,UAAU,cAAc;AAOzD;AADI,IAAM,qBAAN,MAAyB;AAAA,EAAzB;AAsBL,yBAAwB;AAexB,0BAAyB;AA2BzB,qBAAkB,oBAAI,KAAK;AAG3B,qBAAkB,oBAAI,KAAK;AAAA;AAI7B;AAnEE;AAAA,EADC,WAAW,EAAE,MAAM,QAAQ,YAAY,oBAAoB,CAAC;AAAA,GAHlD,mBAIX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,OAAO,CAAC;AAAA,GANnC,mBAOX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,gBAAgB,MAAM,OAAO,CAAC;AAAA,GATrC,mBAUX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,uBAAuB,MAAM,QAAQ,UAAU,KAAK,CAAC;AAAA,GAZ5D,mBAaX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,sBAAsB,MAAM,QAAQ,UAAU,KAAK,CAAC;AAAA,GAf3D,mBAgBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,qBAAqB,MAAM,QAAQ,UAAU,KAAK,CAAC;AAAA,GAlB1D,mBAmBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,kBAAkB,MAAM,OAAO,CAAC;AAAA,GArBvC,mBAsBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,kBAAkB,MAAM,QAAQ,UAAU,KAAK,CAAC;AAAA,GAxBvD,mBAyBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,gBAAgB,MAAM,QAAQ,UAAU,KAAK,CAAC;AAAA,GA3BrD,mBA4BX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,iBAAiB,MAAM,QAAQ,UAAU,KAAK,CAAC;AAAA,GA9BtD,mBA+BX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,UAAU,MAAM,WAAW,WAAW,IAAI,OAAO,EAAE,CAAC;AAAA,GAjC3D,mBAkCX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,mBAAmB,MAAM,WAAW,WAAW,IAAI,OAAO,GAAG,SAAS,IAAI,CAAC;AAAA,GApClF,mBAqCX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,iBAAiB,MAAM,OAAO,CAAC;AAAA,GAvCtC,mBAwCX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,oBAAoB,MAAM,SAAS,UAAU,KAAK,CAAC;AAAA,GA1C1D,mBA2CX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,eAAe,MAAM,SAAS,UAAU,KAAK,CAAC;AAAA,GA7CrD,mBA8CX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,mBAAmB,MAAM,MAAM,UAAU,KAAK,CAAC;AAAA,GAhDtD,mBAiDX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,kBAAkB,MAAM,MAAM,UAAU,KAAK,CAAC;AAAA,GAnDrD,mBAoDX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,KAAK,CAAC;AAAA,GAtDjD,mBAuDX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,mBAAmB,MAAM,OAAO,CAAC;AAAA,GAzDxC,mBA0DX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,aAAa,MAAM,OAAO,CAAC;AAAA,GA5DlC,mBA6DX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,MAAM,oBAAI,KAAK,EAAE,CAAC;AAAA,GA/D7D,mBAgEX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,MAAM,oBAAI,KAAK,EAAE,CAAC;AAAA,GAlE7D,mBAmEX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,KAAK,CAAC;AAAA,GArEjD,mBAsEX;AAtEW,qBAAN;AAAA,EAJN,OAAO,EAAE,WAAW,uBAAuB,CAAC;AAAA,EAC5C,MAAM,EAAE,YAAY,CAAC,aAAa,kBAAkB,UAAU,EAAE,CAAC;AAAA,EACjE,MAAM,EAAE,YAAY,CAAC,eAAe,qBAAqB,gBAAgB,EAAE,CAAC;AAAA,EAC5E,MAAM,EAAE,YAAY,CAAC,kBAAkB,YAAY,eAAe,EAAE,CAAC;AAAA,GACzD;AAiFV;AADI,IAAM,0BAAN,MAA8B;AAAA,EAA9B;AAyBL,kBAAiB;AAMjB,wBAAuB;AAkBvB,qBAAkB,oBAAI,KAAK;AAG3B,qBAAkB,oBAAI,KAAK;AAAA;AAC7B;AAjDE;AAAA,EADC,WAAW,EAAE,MAAM,QAAQ,YAAY,oBAAoB,CAAC;AAAA,GAHlD,wBAIX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,gBAAgB,MAAM,OAAO,CAAC;AAAA,GANrC,wBAOX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,kBAAkB,MAAM,OAAO,CAAC;AAAA,GATvC,wBAUX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,kBAAkB,MAAM,OAAO,CAAC;AAAA,GAZvC,wBAaX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,gBAAgB,MAAM,OAAO,CAAC;AAAA,GAfrC,wBAgBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,gBAAgB,MAAM,OAAO,CAAC;AAAA,GAlBrC,wBAmBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,4BAA4B,MAAM,OAAO,CAAC;AAAA,GArBjD,wBAsBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,UAAU,MAAM,OAAO,CAAC;AAAA,GAxB/B,wBAyBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,iBAAiB,MAAM,OAAO,CAAC;AAAA,GA3BtC,wBA4BX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,iBAAiB,MAAM,UAAU,CAAC;AAAA,GA9BzC,wBA+BX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,UAAU,MAAM,SAAS,UAAU,KAAK,CAAC;AAAA,GAjChD,wBAkCX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,mBAAmB,MAAM,WAAW,WAAW,IAAI,OAAO,GAAG,UAAU,KAAK,CAAC;AAAA,GApCpF,wBAqCX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,oBAAoB,MAAM,MAAM,UAAU,KAAK,CAAC;AAAA,GAvCvD,wBAwCX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,mBAAmB,MAAM,OAAO,CAAC;AAAA,GA1CxC,wBA2CX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,aAAa,MAAM,OAAO,CAAC;AAAA,GA7ClC,wBA8CX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,MAAM,oBAAI,KAAK,EAAE,CAAC;AAAA,GAhD7D,wBAiDX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,MAAM,oBAAI,KAAK,GAAG,UAAU,MAAM,oBAAI,KAAK,EAAE,CAAC;AAAA,GAnDzF,wBAoDX;AApDW,0BAAN;AAAA,EAPN,OAAO,EAAE,WAAW,6BAA6B,CAAC;AAAA,EAClD,OAAO;AAAA,IACN,MAAM;AAAA,IACN,YAAY,CAAC,eAAe,kBAAkB,UAAU;AAAA,EAC1D,CAAC;AAAA,EACA,MAAM,EAAE,YAAY,CAAC,iBAAiB,iBAAiB,kBAAkB,UAAU,EAAE,CAAC;AAAA,EACtF,MAAM,EAAE,YAAY,CAAC,UAAU,gBAAgB,EAAE,CAAC;AAAA,GACtC;AAkEV;AADI,IAAM,+BAAN,MAAmC;AAAA,EAAnC;AA4BL,qBAAkB,oBAAI,KAAK;AAG3B,qBAAkB,oBAAI,KAAK;AAAA;AAC7B;AA5BE;AAAA,EADC,WAAW,EAAE,MAAM,QAAQ,YAAY,oBAAoB,CAAC;AAAA,GAHlD,6BAIX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,iBAAiB,MAAM,OAAO,CAAC;AAAA,GANtC,6BAOX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,gBAAgB,MAAM,OAAO,CAAC;AAAA,GATrC,6BAUX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,eAAe,MAAM,QAAQ,UAAU,KAAK,CAAC;AAAA,GAZpD,6BAaX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,KAAK,CAAC;AAAA,GAfjD,6BAgBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,0BAA0B,MAAM,QAAQ,UAAU,KAAK,CAAC;AAAA,GAlB/D,6BAmBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,mBAAmB,MAAM,OAAO,CAAC;AAAA,GArBxC,6BAsBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,aAAa,MAAM,OAAO,CAAC;AAAA,GAxBlC,6BAyBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,MAAM,oBAAI,KAAK,EAAE,CAAC;AAAA,GA3B7D,6BA4BX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,MAAM,oBAAI,KAAK,GAAG,UAAU,MAAM,oBAAI,KAAK,EAAE,CAAC;AAAA,GA9BzF,6BA+BX;AA/BW,+BAAN;AAAA,EAVN,OAAO,EAAE,WAAW,kCAAkC,CAAC;AAAA,EACvD,OAAO;AAAA,IACN,MAAM;AAAA,IACN,YAAY,CAAC,gBAAgB,eAAe,kBAAkB,UAAU;AAAA,EAC1E,CAAC;AAAA,EACA,MAAM;AAAA,IACL,MAAM;AAAA,IACN,YACE;AAAA,EACJ,CAAC;AAAA,GACY;AAwCV;AADI,IAAM,wBAAN,MAA4B;AAAA,EAA5B;AAsBL,uBAAoB,oBAAI,KAAK;AAAA;AAC/B;AAnBE;AAAA,EADC,WAAW,EAAE,MAAM,QAAQ,YAAY,oBAAoB,CAAC;AAAA,GAHlD,sBAIX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,gBAAgB,MAAM,OAAO,CAAC;AAAA,GANrC,sBAOX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,mBAAmB,MAAM,OAAO,CAAC;AAAA,GATxC,sBAUX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,OAAO,CAAC;AAAA,GAZnC,sBAaX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,mBAAmB,MAAM,OAAO,CAAC;AAAA,GAfxC,sBAgBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,aAAa,MAAM,OAAO,CAAC;AAAA,GAlBlC,sBAmBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,gBAAgB,MAAM,MAAM,UAAU,MAAM,oBAAI,KAAK,EAAE,CAAC;AAAA,GArB/D,sBAsBX;AAtBW,wBAAN;AAAA,EALN,OAAO,EAAE,WAAW,yBAAyB,CAAC;AAAA,EAC9C,OAAO;AAAA,IACN,MAAM;AAAA,IACN,YAAY,CAAC,kBAAkB,eAAe,kBAAkB,UAAU;AAAA,EAC5E,CAAC;AAAA,GACY;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { findOneWithDecryption, findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
3
|
+
import { createLogger } from "@open-mercato/shared/lib/logger";
|
|
3
4
|
import {
|
|
4
5
|
getGatewayAdapter
|
|
5
6
|
} from "@open-mercato/shared/modules/payment_gateways/types";
|
|
@@ -33,6 +34,7 @@ import {
|
|
|
33
34
|
} from "./session-idempotency.js";
|
|
34
35
|
const PAYMENT_SESSION_CLAIM_STALE_MS = 3e4;
|
|
35
36
|
const PAYMENT_SESSION_WAIT_INTERVAL_MS = 25;
|
|
37
|
+
const logger = createLogger("payment_gateways").child({ component: "gateway-service" });
|
|
36
38
|
function assertManualActionAllowed(action, transaction) {
|
|
37
39
|
const current = transaction.unifiedStatus;
|
|
38
40
|
if (!canApplyManualAction(action, current)) {
|
|
@@ -330,7 +332,7 @@ function createPaymentGatewayService(deps) {
|
|
|
330
332
|
scope
|
|
331
333
|
);
|
|
332
334
|
if (!transaction2) {
|
|
333
|
-
throw new Error("Completed payment session is missing its gateway transaction");
|
|
335
|
+
throw new Error("[internal] Completed payment session is missing its gateway transaction");
|
|
334
336
|
}
|
|
335
337
|
return { transaction: transaction2, session: restoreSession(transaction2) };
|
|
336
338
|
}
|
|
@@ -346,7 +348,15 @@ function createPaymentGatewayService(deps) {
|
|
|
346
348
|
try {
|
|
347
349
|
session = await adapter.createSession({ ...sessionInput, idempotencyKey: operationKey });
|
|
348
350
|
} catch (error) {
|
|
349
|
-
|
|
351
|
+
try {
|
|
352
|
+
await releasePaymentSessionInitialization(em, ownership, scope);
|
|
353
|
+
} catch (releaseError) {
|
|
354
|
+
logger.warn("Failed to release payment session initialization claim", {
|
|
355
|
+
claimId: ownership.id,
|
|
356
|
+
providerKey: input.providerKey,
|
|
357
|
+
err: releaseError
|
|
358
|
+
});
|
|
359
|
+
}
|
|
350
360
|
throw error;
|
|
351
361
|
} finally {
|
|
352
362
|
await stopHeartbeat();
|