@open-mercato/core 0.6.7 → 0.6.8-develop.6874.1.982d6097d8
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 +2 -2
- package/AGENTS.md +3 -3
- package/agentic/standalone-guide.md +13 -0
- package/dist/bootstrap.js +16 -1
- package/dist/bootstrap.js.map +2 -2
- package/dist/generated/entities/attachment_quota_reservation/index.js +33 -0
- package/dist/generated/entities/attachment_quota_reservation/index.js.map +7 -0
- 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/gateway_payment_operation/index.js +2 -0
- package/dist/generated/entities/gateway_payment_operation/index.js.map +2 -2
- package/dist/generated/entities/gateway_transaction/index.js +2 -0
- package/dist/generated/entities/gateway_transaction/index.js.map +2 -2
- package/dist/generated/entities/organization/index.js +2 -0
- package/dist/generated/entities/organization/index.js.map +2 -2
- package/dist/generated/entities/resources_resource/index.js +2 -0
- package/dist/generated/entities/resources_resource/index.js.map +2 -2
- package/dist/generated/entities.ids.generated.js +3 -1
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +23 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/helpers/integration/salesFixtures.js +31 -2
- package/dist/helpers/integration/salesFixtures.js.map +2 -2
- package/dist/helpers/integration/salesUi.js +5 -0
- package/dist/helpers/integration/salesUi.js.map +2 -2
- package/dist/modules/api_keys/backend/api-keys/page.js +2 -1
- package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
- package/dist/modules/api_keys/extension-points.js +16 -0
- package/dist/modules/api_keys/extension-points.js.map +7 -0
- package/dist/modules/attachments/api/route.js +120 -10
- package/dist/modules/attachments/api/route.js.map +2 -2
- package/dist/modules/attachments/backend/config/attachments/page.js +1 -1
- package/dist/modules/attachments/backend/config/attachments/page.js.map +2 -2
- package/dist/modules/attachments/data/entities.js +67 -1
- package/dist/modules/attachments/data/entities.js.map +2 -2
- package/dist/modules/attachments/di.js +7 -1
- package/dist/modules/attachments/di.js.map +2 -2
- package/dist/modules/attachments/fields/attachment.js +1 -1
- package/dist/modules/attachments/fields/attachment.js.map +2 -2
- package/dist/modules/attachments/lib/drivers/index.js.map +1 -1
- package/dist/modules/attachments/lib/drivers/localDriver.js +19 -6
- package/dist/modules/attachments/lib/drivers/localDriver.js.map +2 -2
- package/dist/modules/attachments/lib/quota-recovery-queue.js +9 -0
- package/dist/modules/attachments/lib/quota-recovery-queue.js.map +7 -0
- package/dist/modules/attachments/lib/quota-service.js +224 -0
- package/dist/modules/attachments/lib/quota-service.js.map +7 -0
- package/dist/modules/attachments/lib/upload-limits.js +33 -0
- package/dist/modules/attachments/lib/upload-limits.js.map +2 -2
- package/dist/modules/attachments/migrations/Migration20260709234741_attachments.js +13 -0
- package/dist/modules/attachments/migrations/Migration20260709234741_attachments.js.map +7 -0
- package/dist/modules/attachments/workers/quota-recovery.js +45 -0
- package/dist/modules/attachments/workers/quota-recovery.js.map +7 -0
- package/dist/modules/audit_logs/api/audit-logs/access/route.js +5 -1
- package/dist/modules/audit_logs/api/audit-logs/access/route.js.map +2 -2
- package/dist/modules/audit_logs/api/audit-logs/actions/export/route.js +5 -1
- package/dist/modules/audit_logs/api/audit-logs/actions/export/route.js.map +2 -2
- package/dist/modules/audit_logs/api/audit-logs/actions/route.js +5 -1
- package/dist/modules/audit_logs/api/audit-logs/actions/route.js.map +2 -2
- package/dist/modules/audit_logs/api/audit-logs/readScope.js +12 -0
- package/dist/modules/audit_logs/api/audit-logs/readScope.js.map +7 -0
- package/dist/modules/audit_logs/components/AccessLogsTable.js +2 -1
- package/dist/modules/audit_logs/components/AccessLogsTable.js.map +2 -2
- package/dist/modules/audit_logs/components/AuditLogsActions.js +3 -2
- package/dist/modules/audit_logs/components/AuditLogsActions.js.map +2 -2
- package/dist/modules/audit_logs/extension-points.js +14 -0
- package/dist/modules/audit_logs/extension-points.js.map +7 -0
- package/dist/modules/auth/api/admin/nav.js +17 -4
- package/dist/modules/auth/api/admin/nav.js.map +2 -2
- package/dist/modules/auth/api/profile/route.js +8 -2
- package/dist/modules/auth/api/profile/route.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +8 -19
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/backend/auth/profile/page.js.map +2 -2
- package/dist/modules/auth/backend/profile/change-password/page.js.map +2 -2
- package/dist/modules/auth/backend/roles/page.js +2 -1
- package/dist/modules/auth/backend/roles/page.js.map +2 -2
- package/dist/modules/auth/backend/settings/page.js +14 -9
- package/dist/modules/auth/backend/settings/page.js.map +2 -2
- package/dist/modules/auth/backend/users/page.js +2 -1
- package/dist/modules/auth/backend/users/page.js.map +2 -2
- package/dist/modules/auth/cli.js +1 -1
- package/dist/modules/auth/cli.js.map +2 -2
- package/dist/modules/auth/components/UserConsentsPanel.js +9 -9
- package/dist/modules/auth/components/UserConsentsPanel.js.map +2 -2
- package/dist/modules/auth/extension-points.js +21 -0
- package/dist/modules/auth/extension-points.js.map +7 -0
- package/dist/modules/auth/frontend/login.js +7 -3
- package/dist/modules/auth/frontend/login.js.map +2 -2
- package/dist/modules/auth/frontend/reset.js +2 -2
- package/dist/modules/auth/frontend/reset.js.map +2 -2
- package/dist/modules/auth/lib/backendChrome.js +45 -29
- package/dist/modules/auth/lib/backendChrome.js.map +2 -2
- package/dist/modules/auth/lib/setup-app.js +17 -2
- package/dist/modules/auth/lib/setup-app.js.map +2 -2
- package/dist/modules/auth/lib/tenantAccess.js +7 -0
- package/dist/modules/auth/lib/tenantAccess.js.map +2 -2
- package/dist/modules/auth/services/rbacService.js +29 -44
- package/dist/modules/auth/services/rbacService.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/backend/rules/page.js +2 -1
- package/dist/modules/business_rules/backend/rules/page.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/ConditionRow.js +8 -4
- package/dist/modules/business_rules/components/ConditionRow.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/events.js +13 -0
- package/dist/modules/business_rules/events.js.map +7 -0
- package/dist/modules/business_rules/extension-points.js +13 -0
- package/dist/modules/business_rules/extension-points.js.map +7 -0
- 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/catalog/backend/catalog/products/[id]/page.js +6 -5
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/create/page.js +7 -6
- package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
- package/dist/modules/catalog/components/PriceKindSettings.js +3 -3
- package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js +2 -1
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductCategorizeSection.js +3 -3
- package/dist/modules/catalog/components/products/ProductCategorizeSection.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductMediaManager.js +1 -1
- package/dist/modules/catalog/components/products/ProductMediaManager.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductsDataTable.js +3 -2
- package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
- package/dist/modules/catalog/components/products/VariantBuilder.js +5 -5
- package/dist/modules/catalog/components/products/VariantBuilder.js.map +2 -2
- package/dist/modules/catalog/events.js +1 -0
- package/dist/modules/catalog/events.js.map +2 -2
- package/dist/modules/catalog/extension-points.js +27 -0
- package/dist/modules/catalog/extension-points.js.map +7 -0
- package/dist/modules/catalog/widgets/injection/product-bulk-delete/widget.js +10 -5
- package/dist/modules/catalog/widgets/injection/product-bulk-delete/widget.js.map +2 -2
- package/dist/modules/catalog/widgets/injection/product-seo/widget.js +1 -1
- package/dist/modules/catalog/widgets/injection/product-seo/widget.js.map +2 -2
- package/dist/modules/communication_channels/api/post/test-seed/route.js +52 -2
- package/dist/modules/communication_channels/api/post/test-seed/route.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/communication_channels/backend/communication_channels/channels/page.js +2 -1
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.js.map +2 -2
- package/dist/modules/communication_channels/backend/profile/communication-channels/page.js +8 -7
- package/dist/modules/communication_channels/backend/profile/communication-channels/page.js.map +2 -2
- package/dist/modules/communication_channels/data/enrichers.js +4 -4
- package/dist/modules/communication_channels/data/enrichers.js.map +2 -2
- package/dist/modules/communication_channels/extension-points.js +20 -0
- package/dist/modules/communication_channels/extension-points.js.map +7 -0
- package/dist/modules/communication_channels/lib/access-control.js +2 -2
- package/dist/modules/communication_channels/lib/access-control.js.map +2 -2
- package/dist/modules/configs/backend/config/system-status/page.js +2 -1
- package/dist/modules/configs/backend/config/system-status/page.js.map +2 -2
- package/dist/modules/configs/extension-points.js +18 -0
- package/dist/modules/configs/extension-points.js.map +7 -0
- package/dist/modules/configs/lib/upgrade-actions.js +12 -0
- package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
- package/dist/modules/currencies/backend/currencies/page.js +2 -1
- package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
- package/dist/modules/currencies/backend/exchange-rates/page.js +2 -1
- package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
- package/dist/modules/currencies/di.js +4 -0
- package/dist/modules/currencies/di.js.map +2 -2
- package/dist/modules/currencies/extension-points.js +14 -0
- package/dist/modules/currencies/extension-points.js.map +7 -0
- package/dist/modules/currencies/services/baseCurrencyService.js +42 -0
- package/dist/modules/currencies/services/baseCurrencyService.js.map +7 -0
- 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 +63 -4
- package/dist/modules/customer_accounts/api/admin/users-invite.js.map +2 -2
- package/dist/modules/customer_accounts/api/invitations/accept.js +1 -2
- package/dist/modules/customer_accounts/api/invitations/accept.js.map +2 -2
- package/dist/modules/customer_accounts/api/login.js +4 -2
- package/dist/modules/customer_accounts/api/login.js.map +2 -2
- package/dist/modules/customer_accounts/api/magic-link/verify.js +4 -2
- package/dist/modules/customer_accounts/api/magic-link/verify.js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/feature-check.js +5 -4
- package/dist/modules/customer_accounts/api/portal/feature-check.js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/nav.js +6 -4
- package/dist/modules/customer_accounts/api/portal/nav.js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/profile.js +5 -1
- package/dist/modules/customer_accounts/api/portal/profile.js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/sessions-refresh.js +3 -3
- package/dist/modules/customer_accounts/api/portal/sessions-refresh.js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/users-invite.js +22 -2
- package/dist/modules/customer_accounts/api/portal/users-invite.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js +2 -1
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/components/Diagnostics.js +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/components/Diagnostics.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js +2 -1
- package/dist/modules/customer_accounts/backend/customer_accounts/users/page.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/extension-points.js +14 -0
- package/dist/modules/customer_accounts/extension-points.js.map +7 -0
- package/dist/modules/customer_accounts/lib/customerAuth.js +7 -2
- package/dist/modules/customer_accounts/lib/customerAuth.js.map +2 -2
- package/dist/modules/customer_accounts/lib/customerAuthServer.js +2 -1
- package/dist/modules/customer_accounts/lib/customerAuthServer.js.map +2 -2
- 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/services/customerRbacService.js +12 -3
- package/dist/modules/customer_accounts/services/customerRbacService.js.map +2 -2
- package/dist/modules/customer_accounts/setup.js +6 -0
- package/dist/modules/customer_accounts/setup.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/portal-ai-assistant-trigger/widget.client.js +1 -1
- package/dist/modules/customer_accounts/widgets/injection/portal-ai-assistant-trigger/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/analytics.js +4 -1
- package/dist/modules/customers/analytics.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/route.js +3 -4
- package/dist/modules/customers/api/companies/[id]/route.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/api/deals/aggregate/route.js +5 -4
- package/dist/modules/customers/api/deals/aggregate/route.js.map +2 -2
- package/dist/modules/customers/api/deals/summary/route.js +14 -119
- package/dist/modules/customers/api/deals/summary/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js +3 -2
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js.map +2 -2
- package/dist/modules/customers/api/utils.js +21 -24
- package/dist/modules/customers/api/utils.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/[id]/page.js +2 -1
- package/dist/modules/customers/backend/customers/companies/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/page.js +2 -1
- package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +16 -5
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/page.js +18 -11
- package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/page.js +2 -1
- package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.js +17 -3
- package/dist/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/page.js +8 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/[id]/page.js +2 -1
- package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/page.js +2 -1
- package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +26 -10
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/cli.js +28 -11
- 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/CustomerTodosTable.js +2 -1
- package/dist/modules/customers/components/CustomerTodosTable.js.map +2 -2
- package/dist/modules/customers/components/calendar/CalendarEventEditor.js +1 -1
- package/dist/modules/customers/components/calendar/CalendarEventEditor.js.map +2 -2
- package/dist/modules/customers/components/detail/ActiveDealCard.js +2 -1
- package/dist/modules/customers/components/detail/ActiveDealCard.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivitiesDayStrip.js +2 -3
- package/dist/modules/customers/components/detail/ActivitiesDayStrip.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/CompanyKpiBar.js +6 -5
- package/dist/modules/customers/components/detail/CompanyKpiBar.js.map +2 -2
- package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js +2 -2
- package/dist/modules/customers/components/detail/ConfirmDealLostDialog.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/DealForm.js +2 -1
- package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
- package/dist/modules/customers/components/detail/DealsSection.js +1 -1
- package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
- package/dist/modules/customers/components/detail/MiniWeekCalendar.js +7 -52
- package/dist/modules/customers/components/detail/MiniWeekCalendar.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/components/detail/ScheduleActivityDialog.js +231 -216
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/dashboard/helpers.js +4 -3
- package/dist/modules/customers/components/detail/dashboard/helpers.js.map +2 -2
- package/dist/modules/customers/components/detail/legacyActivities.js +69 -0
- package/dist/modules/customers/components/detail/legacyActivities.js.map +7 -0
- package/dist/modules/customers/components/formConfig.js +14 -10
- package/dist/modules/customers/components/formConfig.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 +5 -2
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/customers/extension-points.js +42 -0
- package/dist/modules/customers/extension-points.js.map +7 -0
- package/dist/modules/customers/lib/calendar/format.js +8 -4
- package/dist/modules/customers/lib/calendar/format.js.map +2 -2
- package/dist/modules/customers/lib/dealStatus.js +38 -0
- package/dist/modules/customers/lib/dealStatus.js.map +7 -0
- package/dist/modules/customers/lib/dealsSummaryQueries.js +144 -0
- package/dist/modules/customers/lib/dealsSummaryQueries.js.map +7 -0
- package/dist/modules/customers/lib/optionalBaseCurrency.js +19 -0
- package/dist/modules/customers/lib/optionalBaseCurrency.js.map +7 -0
- package/dist/modules/customers/lib/visibilityFilter.js +6 -4
- package/dist/modules/customers/lib/visibilityFilter.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/customers/utils/phoneDuplicates.js +1 -2
- package/dist/modules/customers/utils/phoneDuplicates.js.map +2 -2
- package/dist/modules/dashboards/api/layout/[itemId]/route.js +6 -3
- package/dist/modules/dashboards/api/layout/[itemId]/route.js.map +2 -2
- package/dist/modules/dashboards/api/layout/route.js +22 -9
- package/dist/modules/dashboards/api/layout/route.js.map +2 -2
- package/dist/modules/dashboards/api/roles/widgets/route.js +9 -3
- package/dist/modules/dashboards/api/roles/widgets/route.js.map +2 -2
- package/dist/modules/dashboards/api/users/widgets/route.js +9 -3
- package/dist/modules/dashboards/api/users/widgets/route.js.map +2 -2
- package/dist/modules/dashboards/api/widgets/catalog.js +6 -3
- package/dist/modules/dashboards/api/widgets/catalog.js.map +2 -2
- package/dist/modules/dashboards/api/widgets/data/batch/route.js +12 -3
- package/dist/modules/dashboards/api/widgets/data/batch/route.js.map +2 -2
- package/dist/modules/dashboards/api/widgets/data/route.js +28 -3
- package/dist/modules/dashboards/api/widgets/data/route.js.map +2 -2
- package/dist/modules/dashboards/api/widgets/data/schema.js +28 -18
- package/dist/modules/dashboards/api/widgets/data/schema.js.map +2 -2
- package/dist/modules/dashboards/components/UnlabelledAmountNotice.js +33 -0
- package/dist/modules/dashboards/components/UnlabelledAmountNotice.js.map +7 -0
- package/dist/modules/dashboards/lib/access.js +5 -3
- package/dist/modules/dashboards/lib/access.js.map +2 -2
- package/dist/modules/dashboards/lib/aggregations.js +113 -46
- package/dist/modules/dashboards/lib/aggregations.js.map +2 -2
- package/dist/modules/dashboards/lib/exactDecimal.js +69 -0
- package/dist/modules/dashboards/lib/exactDecimal.js.map +7 -0
- package/dist/modules/dashboards/lib/formatters.js +84 -11
- package/dist/modules/dashboards/lib/formatters.js.map +2 -2
- package/dist/modules/dashboards/lib/optionalBaseCurrency.js +11 -0
- package/dist/modules/dashboards/lib/optionalBaseCurrency.js.map +7 -0
- package/dist/modules/dashboards/services/widgetDataService.js +316 -14
- package/dist/modules/dashboards/services/widgetDataService.js.map +2 -2
- package/dist/modules/dashboards/subscribers/invalidateWidgetDataCache.js +26 -0
- package/dist/modules/dashboards/subscribers/invalidateWidgetDataCache.js.map +7 -0
- package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.js +9 -3
- package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/config.js +52 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/config.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.js +52 -30
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js +2 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.js +9 -3
- package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js +8 -3
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js +26 -18
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js +22 -14
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js +10 -4
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.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/data_sync/backend/data-sync/page.js +5 -4
- package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
- package/dist/modules/data_sync/components/IntegrationScheduleTab.js +5 -5
- package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
- package/dist/modules/data_sync/extension-points.js +13 -0
- package/dist/modules/data_sync/extension-points.js.map +7 -0
- package/dist/modules/data_sync/lib/queue-policy.js +15 -0
- package/dist/modules/data_sync/lib/queue-policy.js.map +7 -0
- package/dist/modules/data_sync/lib/queue.js +16 -1
- package/dist/modules/data_sync/lib/queue.js.map +2 -2
- package/dist/modules/data_sync/lib/start-run.js +2 -1
- package/dist/modules/data_sync/lib/start-run.js.map +2 -2
- package/dist/modules/data_sync/lib/sync-engine.js +35 -2
- package/dist/modules/data_sync/lib/sync-engine.js.map +2 -2
- package/dist/modules/data_sync/lib/sync-run-service.js +70 -2
- package/dist/modules/data_sync/lib/sync-run-service.js.map +2 -2
- package/dist/modules/data_sync/workers/sync-export.js +9 -2
- package/dist/modules/data_sync/workers/sync-export.js.map +2 -2
- package/dist/modules/data_sync/workers/sync-import.js +9 -2
- package/dist/modules/data_sync/workers/sync-import.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/dictionaries/api/[dictionaryId]/entries/route.js +34 -12
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js.map +2 -2
- package/dist/modules/dictionaries/api/openapi.js +15 -2
- package/dist/modules/dictionaries/api/openapi.js.map +2 -2
- package/dist/modules/dictionaries/components/DictionaryEntrySelect.js +1 -1
- package/dist/modules/dictionaries/components/DictionaryEntrySelect.js.map +2 -2
- package/dist/modules/dictionaries/components/hooks/useDictionaryEntries.js +30 -29
- package/dist/modules/dictionaries/components/hooks/useDictionaryEntries.js.map +2 -2
- package/dist/modules/dictionaries/data/validators.js +7 -0
- package/dist/modules/dictionaries/data/validators.js.map +2 -2
- package/dist/modules/dictionaries/lib/clientEntries.js +4 -3
- package/dist/modules/dictionaries/lib/clientEntries.js.map +2 -2
- package/dist/modules/dictionaries/lib/fetchAllEntries.js +43 -0
- package/dist/modules/dictionaries/lib/fetchAllEntries.js.map +7 -0
- package/dist/modules/directory/api/organization-branding/route.js +10 -3
- package/dist/modules/directory/api/organization-branding/route.js.map +2 -2
- package/dist/modules/directory/api/organization-switcher/route.js +84 -20
- package/dist/modules/directory/api/organization-switcher/route.js.map +2 -2
- package/dist/modules/directory/api/organizations/route.js +7 -0
- package/dist/modules/directory/api/organizations/route.js.map +3 -3
- package/dist/modules/directory/api/tenants/route.js +8 -2
- package/dist/modules/directory/api/tenants/route.js.map +2 -2
- package/dist/modules/directory/backend/directory/branding/page.js +31 -8
- package/dist/modules/directory/backend/directory/branding/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js +7 -16
- package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/organizations/page.js +2 -1
- package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/tenants/page.js +2 -1
- package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
- package/dist/modules/directory/commands/organizations.js +8 -1
- package/dist/modules/directory/commands/organizations.js.map +2 -2
- package/dist/modules/directory/commands/tenants.js +6 -0
- package/dist/modules/directory/commands/tenants.js.map +2 -2
- package/dist/modules/directory/data/entities.js +4 -0
- package/dist/modules/directory/data/entities.js.map +2 -2
- package/dist/modules/directory/data/validators.js +2 -0
- package/dist/modules/directory/data/validators.js.map +2 -2
- package/dist/modules/directory/extension-points.js +14 -0
- package/dist/modules/directory/extension-points.js.map +7 -0
- package/dist/modules/directory/migrations/Migration20260626145500_directory_logo_preserve_aspect_ratio.js +13 -0
- package/dist/modules/directory/migrations/Migration20260626145500_directory_logo_preserve_aspect_ratio.js.map +7 -0
- package/dist/modules/directory/subscribers/invalidateOrgScopeCache.js +5 -1
- package/dist/modules/directory/subscribers/invalidateOrgScopeCache.js.map +2 -2
- package/dist/modules/directory/utils/organizationScope.js +11 -3
- package/dist/modules/directory/utils/organizationScope.js.map +2 -2
- package/dist/modules/entities/api/definitions.js +53 -3
- package/dist/modules/entities/api/definitions.js.map +2 -2
- package/dist/modules/entities/api/entities.js +21 -2
- package/dist/modules/entities/api/entities.js.map +2 -2
- 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/api/records.js +11 -28
- package/dist/modules/entities/api/records.js.map +2 -2
- package/dist/modules/entities/api/sidebar-entities.js +34 -12
- package/dist/modules/entities/api/sidebar-entities.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/[entityId]/page.js +1 -1
- package/dist/modules/entities/backend/entities/user/[entityId]/page.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +23 -4
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
- 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/cli.js +193 -19
- package/dist/modules/entities/cli.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/entities/components/RecordListRelationCell.js +63 -0
- package/dist/modules/entities/components/RecordListRelationCell.js.map +7 -0
- package/dist/modules/entities/components/SystemEntitiesTable.js +2 -1
- package/dist/modules/entities/components/SystemEntitiesTable.js.map +2 -2
- package/dist/modules/entities/components/UserEntitiesTable.js +2 -1
- package/dist/modules/entities/components/UserEntitiesTable.js.map +2 -2
- package/dist/modules/entities/components/recordListRelationDisplays.js +80 -0
- package/dist/modules/entities/components/recordListRelationDisplays.js.map +7 -0
- package/dist/modules/entities/extension-points.js +21 -0
- package/dist/modules/entities/extension-points.js.map +7 -0
- package/dist/modules/entities/lib/entityAcl.js +87 -9
- package/dist/modules/entities/lib/entityAcl.js.map +3 -3
- package/dist/modules/feature_toggles/components/FeatureGuard.js +3 -2
- package/dist/modules/feature_toggles/components/FeatureGuard.js.map +2 -2
- package/dist/modules/feature_toggles/components/FeatureToggleOverrideCard.js +1 -1
- package/dist/modules/feature_toggles/components/FeatureToggleOverrideCard.js.map +2 -2
- package/dist/modules/feature_toggles/components/hooks/staleTime.js +5 -0
- package/dist/modules/feature_toggles/components/hooks/staleTime.js.map +7 -0
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagBoolean.js +5 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagBoolean.js.map +2 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagJson.js +5 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagJson.js.map +2 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagNumber.js +5 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagNumber.js.map +2 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagString.js +5 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagString.js.map +2 -2
- package/dist/modules/inbox_ops/ai-tools.js +5 -2
- package/dist/modules/inbox_ops/ai-tools.js.map +2 -2
- package/dist/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.js +14 -1
- package/dist/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.js.map +2 -2
- package/dist/modules/inbox_ops/api/proposals/route.js +16 -1
- package/dist/modules/inbox_ops/api/proposals/route.js.map +2 -2
- 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/backend/inbox-ops/log/page.js +6 -6
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js.map +2 -2
- package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js +25 -20
- package/dist/modules/inbox_ops/components/proposals/EditActionDialog.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/inbox_ops/subscribers/search-reindex-proposal-created.js +32 -0
- package/dist/modules/inbox_ops/subscribers/search-reindex-proposal-created.js.map +7 -0
- 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/backend/integrations/[id]/page.js +2 -4
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/integrations/extension-points.js +30 -0
- package/dist/modules/integrations/extension-points.js.map +7 -0
- package/dist/modules/integrations/lib/organization-scope.js +2 -9
- package/dist/modules/integrations/lib/organization-scope.js.map +2 -2
- package/dist/modules/integrations/widgets/injection/external-ids/widget.client.js +0 -5
- package/dist/modules/integrations/widgets/injection/external-ids/widget.client.js.map +2 -2
- package/dist/modules/integrations/widgets/injection/external-ids/widget.js +14 -0
- package/dist/modules/integrations/widgets/injection/external-ids/widget.js.map +7 -0
- package/dist/modules/messages/api/[id]/route.js +15 -0
- package/dist/modules/messages/api/[id]/route.js.map +2 -2
- package/dist/modules/messages/api/route.js +77 -8
- package/dist/modules/messages/api/route.js.map +2 -2
- package/dist/modules/messages/components/ComposeMessagePageClient.js +2 -1
- package/dist/modules/messages/components/ComposeMessagePageClient.js.map +2 -2
- package/dist/modules/messages/components/MessageDetailPageClient.js +3 -2
- package/dist/modules/messages/components/MessageDetailPageClient.js.map +2 -2
- package/dist/modules/messages/components/MessagesInboxPageClient.js +2 -1
- package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
- package/dist/modules/messages/components/message-detail/panels/dialogs.js +1 -1
- package/dist/modules/messages/components/message-detail/panels/dialogs.js.map +1 -1
- package/dist/modules/messages/extension-points.js +16 -0
- package/dist/modules/messages/extension-points.js.map +7 -0
- package/dist/modules/messages/lib/participantScope.js +15 -0
- package/dist/modules/messages/lib/participantScope.js.map +7 -0
- package/dist/modules/messages/lib/routeHelpers.js +1 -3
- package/dist/modules/messages/lib/routeHelpers.js.map +2 -2
- package/dist/modules/messages/lib/searchLookup.js +8 -16
- package/dist/modules/messages/lib/searchLookup.js.map +2 -2
- package/dist/modules/messages/search.js +10 -5
- package/dist/modules/messages/search.js.map +2 -2
- package/dist/modules/notifications/api/route.js +83 -4
- package/dist/modules/notifications/api/route.js.map +2 -2
- package/dist/modules/notifications/api/unread-count/route.js +25 -6
- package/dist/modules/notifications/api/unread-count/route.js.map +2 -2
- package/dist/modules/notifications/di.js +1 -1
- package/dist/modules/notifications/di.js.map +2 -2
- package/dist/modules/notifications/events.js +4 -2
- package/dist/modules/notifications/events.js.map +2 -2
- package/dist/modules/notifications/lib/notificationRecipients.js +6 -7
- package/dist/modules/notifications/lib/notificationRecipients.js.map +2 -2
- package/dist/modules/notifications/lib/notificationScope.js +26 -0
- package/dist/modules/notifications/lib/notificationScope.js.map +7 -0
- package/dist/modules/notifications/lib/notificationService.js +48 -4
- package/dist/modules/notifications/lib/notificationService.js.map +2 -2
- package/dist/modules/notifications/lib/routeHelpers.js +16 -2
- package/dist/modules/notifications/lib/routeHelpers.js.map +2 -2
- package/dist/modules/payment_gateways/api/capture/route.js +1 -1
- package/dist/modules/payment_gateways/api/capture/route.js.map +2 -2
- package/dist/modules/payment_gateways/api/sessions/route.js +6 -3
- package/dist/modules/payment_gateways/api/sessions/route.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/backend/payment-gateways/page.js +3 -2
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js.map +2 -2
- package/dist/modules/payment_gateways/data/entities.js +11 -0
- package/dist/modules/payment_gateways/data/entities.js.map +2 -2
- package/dist/modules/payment_gateways/di.js +17 -1
- package/dist/modules/payment_gateways/di.js.map +2 -2
- package/dist/modules/payment_gateways/extension-points.js +19 -0
- package/dist/modules/payment_gateways/extension-points.js.map +7 -0
- package/dist/modules/payment_gateways/lib/capture-ledger.js +183 -0
- package/dist/modules/payment_gateways/lib/capture-ledger.js.map +7 -0
- package/dist/modules/payment_gateways/lib/gateway-service.js +93 -14
- package/dist/modules/payment_gateways/lib/gateway-service.js.map +2 -2
- package/dist/modules/payment_gateways/lib/order-amount-reconciliation.js +58 -0
- package/dist/modules/payment_gateways/lib/order-amount-reconciliation.js.map +7 -0
- package/dist/modules/payment_gateways/lib/payment-operation-idempotency.js +1 -0
- package/dist/modules/payment_gateways/lib/payment-operation-idempotency.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/Migration20260725101500_payment_gateways.js +16 -0
- package/dist/modules/payment_gateways/migrations/Migration20260725101500_payment_gateways.js.map +7 -0
- 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/planner/components/AvailabilityRulesEditor.js +4 -4
- package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
- package/dist/modules/planner/components/unavailabilityReasons.js +3 -3
- package/dist/modules/planner/components/unavailabilityReasons.js.map +2 -2
- package/dist/modules/portal/extension-points.js +32 -0
- package/dist/modules/portal/extension-points.js.map +7 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/dashboard/page.js +3 -3
- package/dist/modules/portal/frontend/[orgSlug]/portal/dashboard/page.js.map +2 -2
- 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/frontend/[orgSlug]/portal/login/page.js +4 -4
- package/dist/modules/portal/frontend/[orgSlug]/portal/login/page.js.map +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/page.js +3 -3
- package/dist/modules/portal/frontend/[orgSlug]/portal/page.js.map +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/profile/page.js +3 -3
- package/dist/modules/portal/frontend/[orgSlug]/portal/profile/page.js.map +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/reset-password/page.js +4 -4
- package/dist/modules/portal/frontend/[orgSlug]/portal/reset-password/page.js.map +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/signup/page.js +4 -4
- package/dist/modules/portal/frontend/[orgSlug]/portal/signup/page.js.map +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/verify/page.js +1 -1
- package/dist/modules/portal/frontend/[orgSlug]/portal/verify/page.js.map +2 -2
- package/dist/modules/portal/lib/navigation.js +7 -0
- package/dist/modules/portal/lib/navigation.js.map +7 -0
- package/dist/modules/progress/lib/progressService.js +2 -0
- package/dist/modules/progress/lib/progressService.js.map +2 -2
- package/dist/modules/progress/lib/progressServiceImpl.js +322 -104
- package/dist/modules/progress/lib/progressServiceImpl.js.map +2 -2
- package/dist/modules/query_index/api/openapi.js +13 -1
- package/dist/modules/query_index/api/openapi.js.map +2 -2
- package/dist/modules/query_index/api/reindex.js +10 -0
- package/dist/modules/query_index/api/reindex.js.map +2 -2
- package/dist/modules/query_index/api/status.js +165 -105
- package/dist/modules/query_index/api/status.js.map +2 -2
- package/dist/modules/query_index/cli.js +125 -1
- package/dist/modules/query_index/cli.js.map +2 -2
- package/dist/modules/query_index/components/QueryIndexesTable.js +130 -42
- package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
- 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/di.js +3 -0
- package/dist/modules/query_index/di.js.map +2 -2
- package/dist/modules/query_index/events.js +20 -0
- package/dist/modules/query_index/events.js.map +7 -0
- package/dist/modules/query_index/extension-points.js +13 -0
- package/dist/modules/query_index/extension-points.js.map +7 -0
- package/dist/modules/query_index/lib/batch.js +11 -4
- package/dist/modules/query_index/lib/batch.js.map +2 -2
- package/dist/modules/query_index/lib/coverage.js +21 -9
- package/dist/modules/query_index/lib/coverage.js.map +2 -2
- package/dist/modules/query_index/lib/document.js +12 -5
- package/dist/modules/query_index/lib/document.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +105 -48
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/query_index/lib/indexer.js +95 -19
- package/dist/modules/query_index/lib/indexer.js.map +2 -2
- package/dist/modules/query_index/lib/reindexer.js +43 -37
- package/dist/modules/query_index/lib/reindexer.js.map +2 -2
- package/dist/modules/query_index/lib/search-tokens.js +34 -15
- package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
- package/dist/modules/query_index/lib/subscriber-scope.js +2 -3
- package/dist/modules/query_index/lib/subscriber-scope.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/query_index/subscribers/coverage_refresh.js +4 -0
- package/dist/modules/query_index/subscribers/coverage_refresh.js.map +2 -2
- package/dist/modules/query_index/subscribers/delete_one.js +53 -1
- package/dist/modules/query_index/subscribers/delete_one.js.map +3 -3
- package/dist/modules/query_index/subscribers/upsert_one.js +60 -0
- package/dist/modules/query_index/subscribers/upsert_one.js.map +3 -3
- package/dist/modules/resources/api/resources.js +2 -0
- package/dist/modules/resources/api/resources.js.map +2 -2
- package/dist/modules/resources/backend/resources/resource-types/page.js +2 -1
- package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/[id]/page.js +3 -2
- package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/page.js +2 -1
- package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
- package/dist/modules/resources/commands/resources.js +9 -0
- package/dist/modules/resources/commands/resources.js.map +2 -2
- package/dist/modules/resources/components/detail/dictionaries.js +3 -3
- package/dist/modules/resources/components/detail/dictionaries.js.map +2 -2
- package/dist/modules/resources/data/entities.js +3 -0
- package/dist/modules/resources/data/entities.js.map +2 -2
- package/dist/modules/resources/data/validators.js +6 -2
- package/dist/modules/resources/data/validators.js.map +2 -2
- package/dist/modules/resources/extension-points.js +14 -0
- package/dist/modules/resources/extension-points.js.map +7 -0
- package/dist/modules/resources/lib/seeds.js +16 -9
- package/dist/modules/resources/lib/seeds.js.map +2 -2
- package/dist/modules/resources/migrations/Migration20260608231000.js +13 -0
- package/dist/modules/resources/migrations/Migration20260608231000.js.map +7 -0
- package/dist/modules/sales/analytics.js +7 -3
- package/dist/modules/sales/analytics.js.map +2 -2
- package/dist/modules/sales/api/document-history/route.js +2 -1
- package/dist/modules/sales/api/document-history/route.js.map +2 -2
- package/dist/modules/sales/api/documents/factory.js +14 -3
- package/dist/modules/sales/api/documents/factory.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +11 -3
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/create/page.js +11 -14
- package/dist/modules/sales/backend/sales/documents/create/page.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +184 -23
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/components/documents/ItemsSection.js +31 -11
- package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/LineItemDialog.js +12 -5
- package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentForm.js +48 -2
- package/dist/modules/sales/components/documents/SalesDocumentForm.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js +4 -1
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesOrderDraftLines.js +167 -0
- package/dist/modules/sales/components/documents/SalesOrderDraftLines.js.map +7 -0
- package/dist/modules/sales/components/useSalesChannelsEnabled.js +2 -35
- package/dist/modules/sales/components/useSalesChannelsEnabled.js.map +2 -2
- package/dist/modules/sales/data/validators.js +32 -5
- package/dist/modules/sales/data/validators.js.map +2 -2
- package/dist/modules/sales/di.js +7 -0
- package/dist/modules/sales/di.js.map +2 -2
- package/dist/modules/sales/events.js +1 -0
- package/dist/modules/sales/events.js.map +2 -2
- package/dist/modules/sales/extension-points.js +36 -0
- package/dist/modules/sales/extension-points.js.map +7 -0
- package/dist/modules/sales/lib/historyHelpers.js +69 -1
- package/dist/modules/sales/lib/historyHelpers.js.map +2 -2
- package/dist/modules/sales/services/paymentOrderTotalResolver.js +52 -0
- package/dist/modules/sales/services/paymentOrderTotalResolver.js.map +7 -0
- package/dist/modules/sales/widgets/injection/document-history/widget.client.js +51 -2
- package/dist/modules/sales/widgets/injection/document-history/widget.client.js.map +2 -2
- package/dist/modules/sales/workflows.js +10 -7
- package/dist/modules/sales/workflows.js.map +2 -2
- 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/dist/modules/shipping_carriers/lib/shipment-wizard/components/PackageEditor.js +1 -1
- package/dist/modules/shipping_carriers/lib/shipment-wizard/components/PackageEditor.js.map +1 -1
- package/dist/modules/staff/api/interceptors.js +5 -3
- package/dist/modules/staff/api/interceptors.js.map +2 -2
- package/dist/modules/staff/api/leave-requests.js +45 -42
- package/dist/modules/staff/api/leave-requests.js.map +2 -2
- package/dist/modules/staff/components/detail/dictionaries.js +3 -3
- package/dist/modules/staff/components/detail/dictionaries.js.map +2 -2
- package/dist/modules/sync_excel/api/upload/route.js +15 -2
- package/dist/modules/sync_excel/api/upload/route.js.map +2 -2
- package/dist/modules/sync_excel/widgets/injection/upload-config/widget.client.js +1 -1
- package/dist/modules/sync_excel/widgets/injection/upload-config/widget.client.js.map +2 -2
- package/dist/modules/wms/components/backend/ReleaseReservationDialog.js +1 -1
- package/dist/modules/wms/components/backend/ReleaseReservationDialog.js.map +1 -1
- package/dist/modules/wms/components/backend/WmsConfigurationPage.js +5 -4
- package/dist/modules/wms/components/backend/WmsConfigurationPage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js +4 -3
- package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsLocationDetailPage.js +3 -2
- package/dist/modules/wms/components/backend/WmsLocationDetailPage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsLotDetailPage.js +3 -2
- package/dist/modules/wms/components/backend/WmsLotDetailPage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsLotsListPage.js +2 -1
- package/dist/modules/wms/components/backend/WmsLotsListPage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsSkuDetailPage.js +3 -2
- package/dist/modules/wms/components/backend/WmsSkuDetailPage.js.map +2 -2
- package/dist/modules/wms/extension-points.js +26 -0
- package/dist/modules/wms/extension-points.js.map +7 -0
- package/dist/modules/workflows/backend/definitions/[id]/page.js +2 -2
- package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/create/page.js +1 -1
- package/dist/modules/workflows/backend/definitions/create/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/page.js +3 -2
- package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js +9 -6
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
- package/dist/modules/workflows/backend/instances/page.js +10 -9
- package/dist/modules/workflows/backend/instances/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/page.js +8 -7
- package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
- package/dist/modules/workflows/components/ActivitiesEditor.js +69 -13
- package/dist/modules/workflows/components/ActivitiesEditor.js.map +2 -2
- package/dist/modules/workflows/components/BusinessRulesSelector.js +1 -1
- package/dist/modules/workflows/components/BusinessRulesSelector.js.map +2 -2
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js +3 -3
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +2 -2
- package/dist/modules/workflows/components/EdgeEditDialogCrudForm.js +1 -2
- package/dist/modules/workflows/components/EdgeEditDialogCrudForm.js.map +2 -2
- package/dist/modules/workflows/components/NodeEditDialog.js +3 -3
- package/dist/modules/workflows/components/NodeEditDialog.js.map +2 -2
- package/dist/modules/workflows/components/NodeEditDialogCrudForm.js +4 -5
- package/dist/modules/workflows/components/NodeEditDialogCrudForm.js.map +2 -2
- package/dist/modules/workflows/components/StepsEditor.js +2 -2
- package/dist/modules/workflows/components/StepsEditor.js.map +2 -2
- package/dist/modules/workflows/components/TransitionsEditor.js +207 -165
- package/dist/modules/workflows/components/TransitionsEditor.js.map +2 -2
- package/dist/modules/workflows/components/WorkflowGraphImpl.js +1 -1
- package/dist/modules/workflows/components/WorkflowGraphImpl.js.map +2 -2
- package/dist/modules/workflows/components/WorkflowLegend.js +1 -1
- package/dist/modules/workflows/components/WorkflowLegend.js.map +2 -2
- package/dist/modules/workflows/components/WorkflowSelector.js +1 -1
- package/dist/modules/workflows/components/WorkflowSelector.js.map +2 -2
- package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js +1 -1
- package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js.map +2 -2
- package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js +2 -2
- package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js.map +2 -2
- package/dist/modules/workflows/components/fields/MappingArrayEditor.js +1 -1
- package/dist/modules/workflows/components/fields/MappingArrayEditor.js.map +2 -2
- package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js +1 -1
- package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js.map +2 -2
- package/dist/modules/workflows/components/fields/WorkflowSelectorField.js +4 -4
- package/dist/modules/workflows/components/fields/WorkflowSelectorField.js.map +2 -2
- package/dist/modules/workflows/data/validators.js +34 -1
- package/dist/modules/workflows/data/validators.js.map +3 -3
- package/dist/modules/workflows/events.js +1 -0
- package/dist/modules/workflows/events.js.map +2 -2
- package/dist/modules/workflows/extension-points.js +15 -0
- package/dist/modules/workflows/extension-points.js.map +7 -0
- package/dist/modules/workflows/lib/activity-executor.js +59 -14
- package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
- package/dist/modules/workflows/lib/format-validation-error.js +46 -1
- package/dist/modules/workflows/lib/format-validation-error.js.map +2 -2
- package/dist/modules/workflows/widgets/injection/order-approval/context-keys.js +10 -0
- package/dist/modules/workflows/widgets/injection/order-approval/context-keys.js.map +7 -0
- package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js +21 -10
- package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js.map +2 -2
- package/generated/entities/attachment_quota_reservation/index.ts +15 -0
- package/generated/entities/customer_deal_person_link/index.ts +1 -0
- package/generated/entities/customer_user_invitation/index.ts +1 -0
- package/generated/entities/gateway_payment_operation/index.ts +1 -0
- package/generated/entities/gateway_transaction/index.ts +1 -0
- package/generated/entities/organization/index.ts +1 -0
- package/generated/entities/resources_resource/index.ts +1 -0
- package/generated/entities.ids.generated.ts +3 -1
- package/generated/entity-fields-registry.ts +23 -0
- package/package.json +19 -18
- package/src/bootstrap.ts +17 -2
- package/src/helpers/integration/salesFixtures.ts +34 -2
- package/src/helpers/integration/salesUi.ts +8 -0
- package/src/modules/api_keys/backend/api-keys/page.tsx +2 -1
- package/src/modules/api_keys/extension-points.ts +13 -0
- package/src/modules/api_keys/i18n/ko.json +42 -0
- package/src/modules/attachments/api/route.ts +130 -9
- package/src/modules/attachments/backend/config/attachments/page.tsx +1 -1
- package/src/modules/attachments/data/entities.ts +59 -0
- package/src/modules/attachments/di.ts +9 -1
- package/src/modules/attachments/fields/attachment.tsx +1 -1
- package/src/modules/attachments/i18n/de.json +15 -0
- package/src/modules/attachments/i18n/en.json +15 -0
- package/src/modules/attachments/i18n/es.json +15 -0
- package/src/modules/attachments/i18n/ko.json +175 -0
- package/src/modules/attachments/i18n/pl.json +15 -0
- package/src/modules/attachments/lib/drivers/index.ts +1 -1
- package/src/modules/attachments/lib/drivers/localDriver.ts +23 -8
- package/src/modules/attachments/lib/drivers/types.ts +5 -0
- package/src/modules/attachments/lib/quota-recovery-queue.ts +16 -0
- package/src/modules/attachments/lib/quota-service.ts +442 -0
- package/src/modules/attachments/lib/upload-limits.ts +35 -0
- package/src/modules/attachments/migrations/.snapshot-open-mercato.json +648 -120
- package/src/modules/attachments/migrations/Migration20260709234741_attachments.ts +12 -0
- package/src/modules/attachments/workers/quota-recovery.ts +68 -0
- package/src/modules/audit_logs/api/audit-logs/access/route.ts +5 -0
- package/src/modules/audit_logs/api/audit-logs/actions/export/route.ts +5 -0
- package/src/modules/audit_logs/api/audit-logs/actions/route.ts +5 -0
- package/src/modules/audit_logs/api/audit-logs/readScope.ts +28 -0
- package/src/modules/audit_logs/components/AccessLogsTable.tsx +2 -1
- package/src/modules/audit_logs/components/AuditLogsActions.tsx +3 -2
- package/src/modules/audit_logs/extension-points.ts +11 -0
- package/src/modules/audit_logs/i18n/ko.json +66 -0
- package/src/modules/auth/AGENTS.md +12 -8
- package/src/modules/auth/api/admin/nav.ts +28 -4
- package/src/modules/auth/api/profile/route.ts +8 -2
- package/src/modules/auth/api/users/route.ts +8 -28
- package/src/modules/auth/backend/auth/profile/page.tsx +1 -0
- package/src/modules/auth/backend/profile/change-password/page.tsx +1 -0
- package/src/modules/auth/backend/roles/page.tsx +2 -1
- package/src/modules/auth/backend/settings/page.tsx +17 -8
- package/src/modules/auth/backend/users/page.tsx +2 -1
- package/src/modules/auth/cli.ts +1 -1
- package/src/modules/auth/components/UserConsentsPanel.tsx +9 -9
- package/src/modules/auth/extension-points.ts +18 -0
- package/src/modules/auth/frontend/login.tsx +7 -3
- package/src/modules/auth/frontend/reset.tsx +2 -2
- package/src/modules/auth/i18n/de.json +1 -0
- package/src/modules/auth/i18n/en.json +1 -0
- package/src/modules/auth/i18n/es.json +1 -0
- package/src/modules/auth/i18n/ko.json +255 -0
- package/src/modules/auth/i18n/pl.json +1 -0
- package/src/modules/auth/lib/backendChrome.tsx +71 -33
- package/src/modules/auth/lib/setup-app.ts +21 -2
- package/src/modules/auth/lib/tenantAccess.ts +8 -0
- package/src/modules/auth/services/rbacService.ts +41 -46
- 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/backend/rules/page.tsx +2 -1
- 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/ConditionRow.tsx +9 -6
- package/src/modules/business_rules/components/utils/actionValidation.ts +6 -0
- package/src/modules/business_rules/events.ts +10 -0
- package/src/modules/business_rules/extension-points.ts +10 -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/ko.json +396 -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/catalog/backend/catalog/products/[id]/page.tsx +6 -5
- package/src/modules/catalog/backend/catalog/products/create/page.tsx +7 -6
- package/src/modules/catalog/components/PriceKindSettings.tsx +3 -3
- package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +2 -1
- package/src/modules/catalog/components/products/ProductCategorizeSection.tsx +3 -3
- package/src/modules/catalog/components/products/ProductMediaManager.tsx +1 -1
- package/src/modules/catalog/components/products/ProductsDataTable.tsx +3 -2
- package/src/modules/catalog/components/products/VariantBuilder.tsx +5 -5
- package/src/modules/catalog/events.ts +1 -0
- package/src/modules/catalog/extension-points.ts +24 -0
- package/src/modules/catalog/i18n/de.json +18 -0
- package/src/modules/catalog/i18n/en.json +18 -0
- package/src/modules/catalog/i18n/es.json +18 -0
- package/src/modules/catalog/i18n/ko.json +723 -0
- package/src/modules/catalog/i18n/pl.json +18 -0
- package/src/modules/catalog/widgets/injection/product-bulk-delete/widget.ts +15 -5
- package/src/modules/catalog/widgets/injection/product-seo/widget.ts +1 -1
- package/src/modules/communication_channels/api/post/test-seed/route.ts +69 -2
- 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/communication_channels/backend/communication_channels/channels/page.tsx +2 -1
- package/src/modules/communication_channels/backend/profile/communication-channels/page.tsx +8 -7
- package/src/modules/communication_channels/data/enrichers.ts +6 -26
- package/src/modules/communication_channels/extension-points.ts +17 -0
- package/src/modules/communication_channels/i18n/de.json +2 -2
- package/src/modules/communication_channels/i18n/en.json +2 -2
- package/src/modules/communication_channels/i18n/es.json +2 -2
- package/src/modules/communication_channels/i18n/ko.json +138 -0
- package/src/modules/communication_channels/i18n/pl.json +2 -2
- package/src/modules/communication_channels/lib/access-control.ts +3 -3
- package/src/modules/configs/backend/config/system-status/page.tsx +2 -1
- package/src/modules/configs/extension-points.ts +15 -0
- package/src/modules/configs/i18n/ko.json +197 -0
- package/src/modules/configs/lib/upgrade-actions.ts +14 -0
- package/src/modules/currencies/backend/currencies/page.tsx +2 -1
- package/src/modules/currencies/backend/exchange-rates/page.tsx +2 -1
- package/src/modules/currencies/di.ts +4 -1
- package/src/modules/currencies/extension-points.ts +11 -0
- package/src/modules/currencies/i18n/de.json +1 -0
- package/src/modules/currencies/i18n/en.json +1 -0
- package/src/modules/currencies/i18n/es.json +1 -0
- package/src/modules/currencies/i18n/ko.json +160 -0
- package/src/modules/currencies/i18n/pl.json +1 -0
- package/src/modules/currencies/services/baseCurrencyService.ts +59 -0
- package/src/modules/customer_accounts/AGENTS.md +3 -3
- package/src/modules/customer_accounts/api/admin/users/[id].ts +16 -1
- package/src/modules/customer_accounts/api/admin/users-invite.ts +81 -3
- package/src/modules/customer_accounts/api/invitations/accept.ts +1 -2
- package/src/modules/customer_accounts/api/login.ts +4 -2
- package/src/modules/customer_accounts/api/magic-link/verify.ts +4 -2
- package/src/modules/customer_accounts/api/portal/feature-check.ts +5 -7
- package/src/modules/customer_accounts/api/portal/nav.ts +5 -3
- package/src/modules/customer_accounts/api/portal/profile.ts +5 -1
- package/src/modules/customer_accounts/api/portal/sessions-refresh.ts +3 -3
- package/src/modules/customer_accounts/api/portal/users-invite.ts +25 -1
- package/src/modules/customer_accounts/backend/customer_accounts/roles/page.tsx +2 -1
- package/src/modules/customer_accounts/backend/customer_accounts/settings/domain/components/Diagnostics.tsx +2 -2
- package/src/modules/customer_accounts/backend/customer_accounts/users/page.tsx +2 -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/extension-points.ts +11 -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/ko.json +354 -0
- package/src/modules/customer_accounts/i18n/pl.json +6 -0
- package/src/modules/customer_accounts/lib/customerAuth.ts +8 -2
- package/src/modules/customer_accounts/lib/customerAuthServer.ts +1 -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/services/customerRbacService.ts +16 -3
- package/src/modules/customer_accounts/setup.ts +7 -0
- 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/portal-ai-assistant-trigger/widget.client.tsx +1 -3
- package/src/modules/customer_accounts/widgets/injection-table.ts +4 -1
- package/src/modules/customers/analytics.ts +3 -0
- package/src/modules/customers/api/companies/[id]/route.ts +3 -4
- 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/api/deals/aggregate/route.ts +5 -4
- package/src/modules/customers/api/deals/summary/route.ts +15 -162
- package/src/modules/customers/api/people/[id]/companies/enriched/route.ts +3 -2
- package/src/modules/customers/api/utils.ts +25 -37
- package/src/modules/customers/backend/customers/companies/[id]/page.tsx +2 -1
- package/src/modules/customers/backend/customers/companies/page.tsx +2 -1
- package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +17 -5
- package/src/modules/customers/backend/customers/deals/[id]/hooks/types.ts +1 -0
- package/src/modules/customers/backend/customers/deals/[id]/page.tsx +19 -12
- package/src/modules/customers/backend/customers/deals/page.tsx +2 -1
- package/src/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.tsx +35 -3
- package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +11 -2
- package/src/modules/customers/backend/customers/people/[id]/page.tsx +2 -1
- package/src/modules/customers/backend/customers/people/page.tsx +2 -1
- package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +29 -10
- package/src/modules/customers/cli.ts +28 -11
- package/src/modules/customers/commands/deals.ts +50 -9
- package/src/modules/customers/commands/people.ts +3 -0
- package/src/modules/customers/components/CustomerTodosTable.tsx +2 -1
- package/src/modules/customers/components/calendar/CalendarEventEditor.tsx +1 -1
- package/src/modules/customers/components/detail/ActiveDealCard.tsx +2 -1
- package/src/modules/customers/components/detail/ActivitiesDayStrip.tsx +2 -3
- package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +30 -7
- package/src/modules/customers/components/detail/CompanyKpiBar.tsx +6 -5
- package/src/modules/customers/components/detail/ConfirmDealLostDialog.tsx +2 -2
- package/src/modules/customers/components/detail/DealDetailTabs.tsx +34 -9
- package/src/modules/customers/components/detail/DealForm.tsx +5 -1
- package/src/modules/customers/components/detail/DealsSection.tsx +1 -1
- package/src/modules/customers/components/detail/MiniWeekCalendar.tsx +8 -57
- package/src/modules/customers/components/detail/PersonDetailTabs.tsx +34 -9
- package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +29 -14
- package/src/modules/customers/components/detail/dashboard/helpers.ts +4 -3
- package/src/modules/customers/components/detail/legacyActivities.ts +79 -0
- package/src/modules/customers/components/formConfig.tsx +12 -8
- package/src/modules/customers/data/entities.ts +9 -1
- package/src/modules/customers/data/validators.ts +6 -1
- package/src/modules/customers/extension-points.ts +40 -0
- package/src/modules/customers/i18n/de.json +72 -0
- package/src/modules/customers/i18n/en.json +72 -0
- package/src/modules/customers/i18n/es.json +72 -0
- package/src/modules/customers/i18n/ko.json +2855 -0
- package/src/modules/customers/i18n/pl.json +72 -0
- package/src/modules/customers/lib/calendar/format.ts +10 -4
- package/src/modules/customers/lib/dealStatus.ts +48 -0
- package/src/modules/customers/lib/dealsSummaryQueries.ts +211 -0
- package/src/modules/customers/lib/optionalBaseCurrency.ts +34 -0
- package/src/modules/customers/lib/visibilityFilter.ts +7 -5
- 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/customers/utils/phoneDuplicates.ts +6 -3
- package/src/modules/dashboards/api/layout/[itemId]/route.ts +6 -3
- package/src/modules/dashboards/api/layout/route.ts +22 -9
- package/src/modules/dashboards/api/roles/widgets/route.ts +9 -3
- package/src/modules/dashboards/api/users/widgets/route.ts +9 -3
- package/src/modules/dashboards/api/widgets/catalog.ts +6 -3
- package/src/modules/dashboards/api/widgets/data/batch/route.ts +12 -1
- package/src/modules/dashboards/api/widgets/data/route.ts +29 -1
- package/src/modules/dashboards/api/widgets/data/schema.ts +49 -19
- package/src/modules/dashboards/components/UnlabelledAmountNotice.tsx +43 -0
- package/src/modules/dashboards/i18n/de.json +5 -0
- package/src/modules/dashboards/i18n/en.json +5 -0
- package/src/modules/dashboards/i18n/es.json +5 -0
- package/src/modules/dashboards/i18n/ko.json +118 -0
- package/src/modules/dashboards/i18n/pl.json +5 -0
- package/src/modules/dashboards/lib/access.ts +5 -3
- package/src/modules/dashboards/lib/aggregations.ts +198 -48
- package/src/modules/dashboards/lib/exactDecimal.ts +96 -0
- package/src/modules/dashboards/lib/formatters.ts +137 -12
- package/src/modules/dashboards/lib/optionalBaseCurrency.ts +22 -0
- package/src/modules/dashboards/services/widgetDataService.ts +453 -12
- package/src/modules/dashboards/subscribers/invalidateWidgetDataCache.ts +32 -0
- package/src/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.tsx +9 -3
- package/src/modules/dashboards/widgets/dashboard/pipeline-summary/config.ts +86 -0
- package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.tsx +42 -21
- package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.tsx +9 -3
- package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.tsx +7 -2
- package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.tsx +25 -15
- package/src/modules/dashboards/widgets/dashboard/top-customers/widget.client.tsx +21 -11
- package/src/modules/dashboards/widgets/dashboard/top-products/widget.client.tsx +9 -3
- 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/data_sync/backend/data-sync/page.tsx +5 -4
- package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +5 -5
- package/src/modules/data_sync/extension-points.ts +10 -0
- package/src/modules/data_sync/i18n/ko.json +125 -0
- package/src/modules/data_sync/lib/adapter.ts +18 -0
- package/src/modules/data_sync/lib/queue-policy.ts +30 -0
- package/src/modules/data_sync/lib/queue.ts +19 -1
- package/src/modules/data_sync/lib/start-run.ts +2 -1
- package/src/modules/data_sync/lib/sync-engine.ts +46 -0
- package/src/modules/data_sync/lib/sync-run-service.ts +82 -1
- package/src/modules/data_sync/workers/sync-export.ts +8 -1
- package/src/modules/data_sync/workers/sync-import.ts +8 -1
- 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 +58 -0
- package/src/modules/design_system/i18n/en.json +58 -0
- package/src/modules/design_system/i18n/es.json +58 -0
- package/src/modules/design_system/i18n/ko.json +58 -0
- package/src/modules/design_system/i18n/pl.json +58 -0
- package/src/modules/design_system/index.ts +7 -0
- package/src/modules/design_system/setup.ts +12 -0
- package/src/modules/dictionaries/api/[dictionaryId]/entries/route.ts +39 -11
- package/src/modules/dictionaries/api/openapi.ts +19 -0
- package/src/modules/dictionaries/components/DictionaryEntrySelect.tsx +1 -1
- package/src/modules/dictionaries/components/hooks/useDictionaryEntries.ts +35 -36
- package/src/modules/dictionaries/data/validators.ts +14 -0
- package/src/modules/dictionaries/i18n/ko.json +130 -0
- package/src/modules/dictionaries/lib/clientEntries.ts +4 -3
- package/src/modules/dictionaries/lib/fetchAllEntries.ts +72 -0
- package/src/modules/directory/api/organization-branding/route.ts +12 -1
- package/src/modules/directory/api/organization-switcher/route.ts +97 -26
- package/src/modules/directory/api/organizations/route.ts +7 -0
- package/src/modules/directory/api/tenants/route.ts +9 -1
- package/src/modules/directory/backend/directory/branding/page.tsx +34 -9
- package/src/modules/directory/backend/directory/organizations/[id]/edit/page.tsx +10 -14
- package/src/modules/directory/backend/directory/organizations/page.tsx +2 -1
- package/src/modules/directory/backend/directory/tenants/page.tsx +2 -1
- package/src/modules/directory/commands/organizations.ts +9 -1
- package/src/modules/directory/commands/tenants.ts +6 -0
- package/src/modules/directory/data/entities.ts +3 -0
- package/src/modules/directory/data/validators.ts +2 -0
- package/src/modules/directory/extension-points.ts +11 -0
- package/src/modules/directory/i18n/de.json +4 -1
- package/src/modules/directory/i18n/en.json +4 -1
- package/src/modules/directory/i18n/es.json +4 -1
- package/src/modules/directory/i18n/ko.json +105 -0
- package/src/modules/directory/i18n/pl.json +4 -1
- package/src/modules/directory/migrations/.snapshot-open-mercato.json +18 -1
- package/src/modules/directory/migrations/Migration20260626145500_directory_logo_preserve_aspect_ratio.ts +13 -0
- package/src/modules/directory/subscribers/invalidateOrgScopeCache.ts +4 -1
- package/src/modules/directory/utils/organizationScope.ts +9 -3
- package/src/modules/entities/api/definitions.ts +55 -3
- package/src/modules/entities/api/entities.ts +30 -2
- package/src/modules/entities/api/entity-settings.ts +66 -22
- package/src/modules/entities/api/records.ts +15 -31
- package/src/modules/entities/api/sidebar-entities.ts +43 -14
- 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/[entityId]/page.tsx +1 -1
- package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +96 -75
- package/src/modules/entities/backend/entities/user/create/page.tsx +16 -7
- package/src/modules/entities/cli.ts +238 -21
- package/src/modules/entities/components/EntitySettingsManager.tsx +160 -0
- package/src/modules/entities/components/RecordListRelationCell.tsx +90 -0
- package/src/modules/entities/components/SystemEntitiesTable.tsx +2 -1
- package/src/modules/entities/components/UserEntitiesTable.tsx +2 -1
- package/src/modules/entities/components/recordListRelationDisplays.ts +109 -0
- package/src/modules/entities/extension-points.ts +18 -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/ko.json +260 -0
- package/src/modules/entities/i18n/pl.json +9 -0
- package/src/modules/entities/lib/entityAcl.ts +98 -11
- package/src/modules/feature_toggles/components/FeatureGuard.tsx +9 -2
- package/src/modules/feature_toggles/components/FeatureToggleOverrideCard.tsx +1 -1
- package/src/modules/feature_toggles/components/hooks/staleTime.ts +5 -0
- package/src/modules/feature_toggles/components/hooks/useFeatureFlagBoolean.ts +13 -1
- package/src/modules/feature_toggles/components/hooks/useFeatureFlagJson.ts +12 -3
- package/src/modules/feature_toggles/components/hooks/useFeatureFlagNumber.ts +10 -1
- package/src/modules/feature_toggles/components/hooks/useFeatureFlagString.ts +10 -1
- package/src/modules/feature_toggles/i18n/ko.json +96 -0
- package/src/modules/inbox_ops/ai-tools.ts +5 -3
- package/src/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.ts +17 -1
- package/src/modules/inbox_ops/api/proposals/route.ts +20 -1
- package/src/modules/inbox_ops/api/webhook/inbound.ts +14 -12
- package/src/modules/inbox_ops/backend/inbox-ops/log/page.tsx +6 -6
- package/src/modules/inbox_ops/components/proposals/EditActionDialog.tsx +24 -19
- package/src/modules/inbox_ops/components/proposals/types.ts +1 -0
- 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/ko.json +196 -0
- package/src/modules/inbox_ops/i18n/pl.json +3 -0
- package/src/modules/inbox_ops/search.ts +20 -4
- package/src/modules/inbox_ops/subscribers/search-reindex-proposal-created.ts +39 -0
- 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/backend/integrations/[id]/page.tsx +2 -2
- package/src/modules/integrations/extension-points.ts +27 -0
- package/src/modules/integrations/i18n/ko.json +129 -0
- package/src/modules/integrations/lib/organization-scope.ts +5 -25
- package/src/modules/integrations/widgets/injection/external-ids/widget.client.tsx +0 -5
- package/src/modules/integrations/widgets/injection/external-ids/widget.ts +13 -0
- package/src/modules/messages/api/[id]/route.ts +21 -0
- package/src/modules/messages/api/route.ts +109 -9
- package/src/modules/messages/components/ComposeMessagePageClient.tsx +2 -1
- package/src/modules/messages/components/MessageDetailPageClient.tsx +3 -2
- package/src/modules/messages/components/MessagesInboxPageClient.tsx +2 -1
- package/src/modules/messages/components/message-detail/panels/dialogs.tsx +1 -1
- package/src/modules/messages/extension-points.ts +13 -0
- 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/ko.json +263 -0
- package/src/modules/messages/i18n/pl.json +2 -0
- package/src/modules/messages/lib/participantScope.ts +64 -0
- package/src/modules/messages/lib/routeHelpers.ts +4 -6
- package/src/modules/messages/lib/searchLookup.ts +11 -34
- package/src/modules/messages/search.ts +11 -5
- package/src/modules/notifications/api/route.ts +123 -3
- package/src/modules/notifications/api/unread-count/route.ts +42 -5
- package/src/modules/notifications/di.ts +1 -1
- package/src/modules/notifications/events.ts +2 -0
- package/src/modules/notifications/i18n/ko.json +55 -0
- package/src/modules/notifications/lib/notificationRecipients.ts +6 -8
- package/src/modules/notifications/lib/notificationScope.ts +40 -0
- package/src/modules/notifications/lib/notificationService.ts +63 -1
- package/src/modules/notifications/lib/routeHelpers.ts +19 -2
- package/src/modules/payment_gateways/api/capture/route.ts +1 -1
- package/src/modules/payment_gateways/api/sessions/route.ts +6 -3
- package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +13 -1
- package/src/modules/payment_gateways/backend/payment-gateways/page.tsx +3 -2
- package/src/modules/payment_gateways/data/entities.ts +13 -2
- package/src/modules/payment_gateways/di.ts +28 -2
- package/src/modules/payment_gateways/extension-points.ts +16 -0
- package/src/modules/payment_gateways/i18n/de.json +8 -1
- package/src/modules/payment_gateways/i18n/en.json +8 -1
- package/src/modules/payment_gateways/i18n/es.json +8 -1
- package/src/modules/payment_gateways/i18n/ko.json +87 -0
- package/src/modules/payment_gateways/i18n/pl.json +8 -1
- package/src/modules/payment_gateways/lib/capture-ledger.ts +260 -0
- package/src/modules/payment_gateways/lib/gateway-service.ts +114 -18
- package/src/modules/payment_gateways/lib/order-amount-reconciliation.ts +93 -0
- package/src/modules/payment_gateways/lib/payment-operation-idempotency.ts +1 -0
- package/src/modules/payment_gateways/lib/session-idempotency.ts +36 -0
- package/src/modules/payment_gateways/migrations/.snapshot-open-mercato.json +44 -1
- package/src/modules/payment_gateways/migrations/Migration20260725101500_payment_gateways.ts +21 -0
- 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/planner/components/AvailabilityRulesEditor.tsx +4 -4
- package/src/modules/planner/components/unavailabilityReasons.ts +3 -3
- package/src/modules/planner/i18n/ko.json +565 -0
- package/src/modules/portal/extension-points.ts +30 -0
- package/src/modules/portal/frontend/[orgSlug]/portal/dashboard/page.tsx +3 -3
- 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/frontend/[orgSlug]/portal/login/page.tsx +4 -4
- package/src/modules/portal/frontend/[orgSlug]/portal/page.tsx +3 -3
- package/src/modules/portal/frontend/[orgSlug]/portal/profile/page.tsx +3 -3
- package/src/modules/portal/frontend/[orgSlug]/portal/reset-password/page.tsx +5 -5
- package/src/modules/portal/frontend/[orgSlug]/portal/signup/page.tsx +4 -4
- package/src/modules/portal/frontend/[orgSlug]/portal/verify/page.tsx +1 -1
- 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/ko.json +143 -0
- package/src/modules/portal/i18n/pl.json +18 -0
- package/src/modules/portal/lib/navigation.ts +3 -0
- package/src/modules/progress/AGENTS.md +11 -1
- package/src/modules/progress/i18n/ko.json +20 -0
- package/src/modules/progress/lib/progressService.ts +1 -0
- package/src/modules/progress/lib/progressServiceImpl.ts +385 -117
- package/src/modules/query_index/api/openapi.ts +12 -0
- package/src/modules/query_index/api/reindex.ts +15 -0
- package/src/modules/query_index/api/status.ts +238 -136
- package/src/modules/query_index/cli.ts +180 -1
- package/src/modules/query_index/components/QueryIndexesTable.tsx +194 -47
- package/src/modules/query_index/data/entities.ts +7 -0
- package/src/modules/query_index/di.ts +6 -0
- package/src/modules/query_index/events.ts +17 -0
- package/src/modules/query_index/extension-points.ts +10 -0
- package/src/modules/query_index/i18n/de.json +5 -3
- package/src/modules/query_index/i18n/en.json +5 -3
- package/src/modules/query_index/i18n/es.json +5 -3
- package/src/modules/query_index/i18n/ko.json +69 -0
- package/src/modules/query_index/i18n/pl.json +5 -3
- package/src/modules/query_index/lib/batch.ts +11 -4
- package/src/modules/query_index/lib/coverage.ts +47 -14
- package/src/modules/query_index/lib/document.ts +35 -4
- package/src/modules/query_index/lib/engine.ts +136 -59
- package/src/modules/query_index/lib/indexer.ts +130 -21
- package/src/modules/query_index/lib/reindexer.ts +62 -40
- package/src/modules/query_index/lib/search-tokens.ts +48 -16
- package/src/modules/query_index/lib/subscriber-scope.ts +2 -7
- 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/query_index/subscribers/coverage_refresh.ts +4 -0
- package/src/modules/query_index/subscribers/delete_one.ts +65 -1
- package/src/modules/query_index/subscribers/upsert_one.ts +68 -1
- package/src/modules/resources/api/resources.ts +2 -0
- package/src/modules/resources/backend/resources/resource-types/page.tsx +2 -1
- package/src/modules/resources/backend/resources/resources/[id]/page.tsx +9 -3
- package/src/modules/resources/backend/resources/resources/page.tsx +2 -1
- package/src/modules/resources/commands/resources.ts +10 -0
- package/src/modules/resources/components/detail/dictionaries.ts +3 -3
- package/src/modules/resources/data/entities.ts +3 -0
- package/src/modules/resources/data/validators.ts +5 -0
- package/src/modules/resources/extension-points.ts +11 -0
- package/src/modules/resources/i18n/ko.json +770 -0
- package/src/modules/resources/lib/seeds.ts +16 -9
- package/src/modules/resources/migrations/.snapshot-open-mercato.json +17 -1
- package/src/modules/resources/migrations/Migration20260608231000.ts +13 -0
- package/src/modules/sales/analytics.ts +4 -0
- package/src/modules/sales/api/document-history/route.ts +1 -0
- package/src/modules/sales/api/documents/factory.ts +28 -3
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +11 -3
- package/src/modules/sales/backend/sales/documents/create/page.tsx +2 -4
- package/src/modules/sales/commands/documents.ts +298 -31
- package/src/modules/sales/components/documents/ItemsSection.tsx +34 -11
- package/src/modules/sales/components/documents/LineItemDialog.tsx +13 -5
- package/src/modules/sales/components/documents/SalesDocumentForm.tsx +48 -6
- package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +6 -1
- package/src/modules/sales/components/documents/SalesOrderDraftLines.tsx +198 -0
- package/src/modules/sales/components/documents/lineItemTypes.ts +1 -0
- package/src/modules/sales/components/useSalesChannelsEnabled.ts +2 -48
- package/src/modules/sales/data/validators.ts +59 -6
- package/src/modules/sales/di.ts +9 -0
- package/src/modules/sales/events.ts +1 -0
- package/src/modules/sales/extension-points.ts +33 -0
- package/src/modules/sales/i18n/de.json +22 -0
- package/src/modules/sales/i18n/en.json +22 -0
- package/src/modules/sales/i18n/es.json +22 -0
- package/src/modules/sales/i18n/ko.json +1442 -0
- package/src/modules/sales/i18n/pl.json +22 -0
- package/src/modules/sales/lib/historyHelpers.ts +88 -1
- package/src/modules/sales/services/paymentOrderTotalResolver.ts +67 -0
- package/src/modules/sales/widgets/injection/document-history/widget.client.tsx +64 -3
- package/src/modules/sales/workflows.ts +10 -7
- package/src/modules/shipping_carriers/api/webhook/[provider]/route.ts +11 -1
- package/src/modules/shipping_carriers/i18n/ko.json +85 -0
- package/src/modules/shipping_carriers/lib/shipment-wizard/components/PackageEditor.tsx +1 -1
- package/src/modules/staff/api/interceptors.ts +6 -4
- package/src/modules/staff/api/leave-requests.ts +54 -47
- package/src/modules/staff/components/detail/dictionaries.ts +3 -3
- package/src/modules/staff/i18n/ko.json +1162 -0
- package/src/modules/sync_excel/api/upload/route.ts +15 -2
- package/src/modules/sync_excel/i18n/ko.json +107 -0
- package/src/modules/sync_excel/widgets/injection/upload-config/widget.client.tsx +1 -1
- package/src/modules/translations/i18n/ko.json +45 -0
- package/src/modules/wms/components/backend/ReleaseReservationDialog.tsx +1 -1
- package/src/modules/wms/components/backend/WmsConfigurationPage.tsx +5 -4
- package/src/modules/wms/components/backend/WmsInventoryConsolePage.tsx +4 -3
- package/src/modules/wms/components/backend/WmsLocationDetailPage.tsx +3 -2
- package/src/modules/wms/components/backend/WmsLotDetailPage.tsx +3 -2
- package/src/modules/wms/components/backend/WmsLotsListPage.tsx +2 -1
- package/src/modules/wms/components/backend/WmsSkuDetailPage.tsx +3 -2
- package/src/modules/wms/extension-points.ts +23 -0
- package/src/modules/wms/i18n/de.json +2 -0
- package/src/modules/wms/i18n/en.json +2 -0
- package/src/modules/wms/i18n/es.json +2 -0
- package/src/modules/wms/i18n/ko.json +1053 -0
- package/src/modules/wms/i18n/pl.json +2 -0
- package/src/modules/workflows/backend/definitions/[id]/page.tsx +2 -2
- package/src/modules/workflows/backend/definitions/create/page.tsx +1 -1
- package/src/modules/workflows/backend/definitions/page.tsx +3 -2
- package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +16 -7
- package/src/modules/workflows/backend/instances/page.tsx +10 -9
- package/src/modules/workflows/backend/tasks/page.tsx +8 -7
- package/src/modules/workflows/components/ActivitiesEditor.tsx +98 -14
- package/src/modules/workflows/components/BusinessRulesSelector.tsx +1 -1
- package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +3 -3
- package/src/modules/workflows/components/EdgeEditDialogCrudForm.tsx +1 -2
- package/src/modules/workflows/components/NodeEditDialog.tsx +3 -3
- package/src/modules/workflows/components/NodeEditDialogCrudForm.tsx +4 -5
- package/src/modules/workflows/components/StepsEditor.tsx +2 -2
- package/src/modules/workflows/components/TransitionsEditor.tsx +78 -20
- package/src/modules/workflows/components/WorkflowGraphImpl.tsx +1 -1
- package/src/modules/workflows/components/WorkflowLegend.tsx +1 -1
- package/src/modules/workflows/components/WorkflowSelector.tsx +1 -1
- package/src/modules/workflows/components/fields/BusinessRuleConditionsEditor.tsx +1 -1
- package/src/modules/workflows/components/fields/FormFieldArrayEditor.tsx +2 -2
- package/src/modules/workflows/components/fields/MappingArrayEditor.tsx +1 -1
- package/src/modules/workflows/components/fields/StartPreConditionsEditor.tsx +1 -1
- package/src/modules/workflows/components/fields/WorkflowSelectorField.tsx +4 -4
- package/src/modules/workflows/data/validators.ts +52 -1
- package/src/modules/workflows/events.ts +1 -0
- package/src/modules/workflows/extension-points.ts +12 -0
- package/src/modules/workflows/i18n/de.json +3 -0
- package/src/modules/workflows/i18n/en.json +3 -0
- package/src/modules/workflows/i18n/es.json +3 -0
- package/src/modules/workflows/i18n/ko.json +1204 -0
- package/src/modules/workflows/i18n/pl.json +3 -0
- package/src/modules/workflows/lib/activity-executor.ts +99 -20
- package/src/modules/workflows/lib/format-validation-error.ts +60 -0
- package/src/modules/workflows/widgets/injection/order-approval/context-keys.ts +18 -0
- package/src/modules/workflows/widgets/injection/order-approval/widget.client.tsx +27 -11
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/directory/api/organizations/route.ts"],
|
|
4
|
-
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { logCrudAccess, makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { Organization, Tenant } from '@open-mercato/core/modules/directory/data/entities'\nimport { organizationCreateSchema, organizationUpdateSchema } from '@open-mercato/core/modules/directory/data/validators'\nimport {\n computeHierarchyForOrganizations,\n type ComputedHierarchy,\n type ComputedOrganizationNode,\n} from '@open-mercato/core/modules/directory/lib/hierarchy'\nimport { isAllOrganizationsSelection } from '@open-mercato/core/modules/directory/constants'\nimport {\n getSelectedOrganizationFromRequest,\n resolveOrganizationScopeForRequest,\n} from '@open-mercato/core/modules/directory/utils/organizationScope'\nimport { loadCustomFieldValues } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { E } from '#generated/entities.ids.generated'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { FilterQuery } from '@mikro-orm/core'\nimport { organizationCrudEvents, organizationCrudIndexer } from '@open-mercato/core/modules/directory/commands/organizations'\nimport type { OpenApiMethodDoc, OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { parseBooleanToken } from '@open-mercato/shared/lib/boolean'\nimport {\n directoryTag,\n directoryErrorSchema,\n directoryOkSchema,\n organizationListResponseSchema,\n} from '../openapi'\nimport { resolveIsSuperAdmin, enforceTenantSelection } from '@open-mercato/core/modules/auth/lib/tenantAccess'\nimport { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\n\ntype CrudInput = Record<string, unknown>\nconst rawBodySchema = z.object({}).passthrough()\n\ntype TreeNode = {\n id: string\n name: string\n parentId: string | null\n tenantId: string | null\n depth: number\n ancestorIds: string[]\n childIds: string[]\n descendantIds: string[]\n isActive: boolean\n treePath: string | null\n pathLabel: string\n children: TreeNode[]\n}\n\nconst viewSchema = z.object({\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(50),\n search: z.string().optional(),\n view: z.enum(['options', 'manage', 'tree']).default('options'),\n ids: z.string().optional(),\n tenantId: z.string().uuid().optional(),\n includeInactive: z.enum(['true', 'false']).optional(),\n status: z.enum(['all', 'active', 'inactive']).optional(),\n})\n\nfunction parseIds(raw: string | null): string[] | null {\n if (!raw) return null\n const ids = raw.split(',').map((s) => s.trim()).filter(Boolean)\n return ids.length ? Array.from(new Set(ids)) : null\n}\n\nfunction stringId(value: unknown): string {\n return String(value)\n}\n\nfunction enforceTenantScope(\n authTenantId: string | null,\n requestedTenantId: string | null,\n isSuperAdmin: boolean,\n): string | null {\n if (isSuperAdmin) {\n return requestedTenantId || authTenantId || null\n }\n if (authTenantId && requestedTenantId && requestedTenantId !== authTenantId) {\n return null\n }\n return requestedTenantId || authTenantId\n}\n\nconst crud = makeCrudRoute<CrudInput, CrudInput, Record<string, unknown>>({\n metadata: {\n GET: { requireAuth: true, requireFeatures: ['directory.organizations.view'] },\n POST: { requireAuth: true, requireFeatures: ['directory.organizations.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['directory.organizations.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['directory.organizations.manage'] },\n },\n orm: {\n entity: Organization,\n idField: 'id',\n orgField: null,\n tenantField: null,\n softDeleteField: 'deletedAt',\n },\n events: organizationCrudEvents,\n indexer: organizationCrudIndexer,\n actions: {\n create: {\n commandId: 'directory.organizations.create',\n schema: rawBodySchema,\n mapInput: ({ parsed }) => parsed,\n response: ({ result }) => ({ id: String(result.id) }),\n status: 201,\n },\n update: {\n commandId: 'directory.organizations.update',\n schema: rawBodySchema,\n mapInput: ({ parsed }) => parsed,\n response: () => ({ ok: true }),\n },\n delete: {\n commandId: 'directory.organizations.delete',\n response: () => ({ ok: true }),\n },\n },\n})\n\nexport const metadata = crud.metadata\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) return NextResponse.json({ items: [] }, { status: 401 })\n\n const url = new URL(req.url)\n const parsed = viewSchema.safeParse({\n page: url.searchParams.get('page') ?? undefined,\n pageSize: url.searchParams.get('pageSize') ?? undefined,\n search: url.searchParams.get('search') ?? undefined,\n view: url.searchParams.get('view') ?? undefined,\n ids: url.searchParams.get('ids') ?? undefined,\n tenantId: url.searchParams.get('tenantId') ?? undefined,\n includeInactive: url.searchParams.get('includeInactive') ?? undefined,\n status: url.searchParams.get('status') ?? undefined,\n })\n if (!parsed.success) return NextResponse.json({ items: [] }, { status: 400 })\n\n const query = parsed.data\n const ids = parseIds(query.ids ?? null)\n const requestedTenantRaw = query.tenantId ?? null\n const normalizedRequestedTenantId = requestedTenantRaw && requestedTenantRaw.toLowerCase() === 'all' ? null : requestedTenantRaw\n const authTenantId = auth.tenantId ?? null\n const container = await createRequestContainer()\n const isSuperAdmin = await resolveIsSuperAdmin({ auth, container })\n const em = (container.resolve('em') as EntityManager)\n const allowAllTenants = isSuperAdmin && !normalizedRequestedTenantId && query.view === 'manage'\n let tenantId = allowAllTenants ? null : enforceTenantScope(authTenantId, normalizedRequestedTenantId, isSuperAdmin)\n const status = query.status ?? 'all'\n const includeInactive = parseBooleanToken(query.includeInactive) === true || status !== 'active'\n\n if (!allowAllTenants && !tenantId && !authTenantId && ids?.length) {\n let scopedIds = ids\n if (!isSuperAdmin) {\n let allowedIds: string[] | null = null\n try {\n const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req })\n allowedIds = Array.isArray(scope.allowedIds) ? scope.allowedIds : null\n } catch {}\n const allowedSet = allowedIds ? new Set(allowedIds) : new Set<string>()\n scopedIds = ids.filter((id) => allowedSet.has(id))\n }\n if (scopedIds.length) {\n const scopedOrgs: Organization[] = await findWithDecryption(\n em,\n Organization,\n { id: { $in: scopedIds }, deletedAt: null },\n { populate: ['tenant'] },\n { tenantId: authTenantId, organizationId: null },\n )\n const tenantCandidates = new Set<string>()\n for (const org of scopedOrgs) {\n const orgTenantId = org.tenant?.id ? stringId(org.tenant.id) : ''\n if (orgTenantId) tenantCandidates.add(orgTenantId)\n }\n if (tenantCandidates.size === 1) {\n const candidateTenantId = Array.from(tenantCandidates)[0] ?? null\n try {\n tenantId = await enforceTenantSelection({ auth, container }, candidateTenantId)\n } catch (error) {\n if (isCrudHttpError(error)) {\n return NextResponse.json(error.body, { status: error.status })\n }\n throw error\n }\n } else if (tenantCandidates.size > 1) {\n return NextResponse.json({ items: [], error: 'Tenant scope required' }, { status: 400 })\n }\n }\n }\n\n if (!allowAllTenants && !tenantId) {\n const candidateOrgIds = new Set<string>()\n const cookieOrgId = getSelectedOrganizationFromRequest(req)\n const effectiveCookieOrgId = cookieOrgId && !isAllOrganizationsSelection(cookieOrgId) ? cookieOrgId : null\n if (effectiveCookieOrgId) candidateOrgIds.add(effectiveCookieOrgId)\n if (auth.orgId) candidateOrgIds.add(auth.orgId)\n\n try {\n const scope = await resolveOrganizationScopeForRequest({\n container,\n auth,\n request: req,\n selectedId: effectiveCookieOrgId ?? undefined,\n })\n if (scope.selectedId) candidateOrgIds.add(scope.selectedId)\n if (Array.isArray(scope.filterIds) && scope.filterIds.length) {\n candidateOrgIds.add(scope.filterIds[0]!)\n }\n if (Array.isArray(scope.allowedIds) && scope.allowedIds.length) {\n candidateOrgIds.add(scope.allowedIds[0]!)\n }\n } catch {}\n\n for (const orgId of candidateOrgIds) {\n if (!orgId) continue\n const org = await findOneWithDecryption(\n em,\n Organization,\n { id: orgId, deletedAt: null },\n { populate: ['tenant'] },\n { tenantId: authTenantId, organizationId: orgId },\n )\n if (org?.tenant && org.tenant.id) {\n tenantId = stringId(org.tenant.id)\n break\n }\n }\n }\n\n if (!allowAllTenants && !tenantId) {\n return NextResponse.json({ items: [], error: 'Tenant scope required' }, { status: 400 })\n }\n\n if (query.view === 'options') {\n if (!tenantId) {\n return NextResponse.json({ items: [], error: 'Tenant scope required' }, { status: 400 })\n }\n const where: FilterQuery<Organization> = { tenant: tenantId, deletedAt: null }\n if (status === 'active') where.isActive = true\n if (status === 'inactive') where.isActive = false\n if (status === 'all' && !includeInactive) where.isActive = true\n if (ids) where.id = { $in: ids }\n const orgs = await em.find(Organization, where, { orderBy: { name: 'ASC' } })\n const items = orgs.map((org) => ({\n id: stringId(org.id),\n name: org.name,\n logoUrl: org.logoUrl ?? null,\n parentId: org.parentId ?? null,\n tenantId: tenantId,\n isActive: !!org.isActive,\n depth: org.depth ?? 0,\n treePath: org.treePath ?? stringId(org.id),\n }))\n await logCrudAccess({\n container,\n auth,\n request: req,\n items,\n idField: 'id',\n resourceKind: 'directory.organization',\n organizationId: null,\n tenantId,\n query,\n accessType: ids && ids.length === 1 ? 'read:item' : undefined,\n })\n return NextResponse.json({ items })\n }\n\n if (query.view === 'tree') {\n if (!tenantId) {\n return NextResponse.json({ items: [], error: 'Tenant scope required' }, { status: 400 })\n }\n const orgListFilter: FilterQuery<Organization> = { tenant: tenantId, deletedAt: null }\n const orgs = await em.find(Organization, orgListFilter, { orderBy: { name: 'ASC' } })\n const hierarchy = computeHierarchyForOrganizations(orgs, tenantId)\n const nodeMap = new Map<string, { node: ComputedOrganizationNode; children: TreeNode[] }>()\n const roots: TreeNode[] = []\n for (const node of hierarchy.ordered) {\n const treeNode: TreeNode = {\n id: node.id,\n name: node.name,\n parentId: node.parentId,\n tenantId: node.tenantId,\n depth: node.depth,\n ancestorIds: node.ancestorIds,\n childIds: node.childIds,\n descendantIds: node.descendantIds,\n isActive: node.isActive,\n treePath: node.treePath,\n pathLabel: node.pathLabel,\n children: [],\n }\n nodeMap.set(node.id, { node, children: treeNode.children })\n if (node.parentId && nodeMap.has(node.parentId)) {\n const parentEntry = nodeMap.get(node.parentId)!\n parentEntry.children.push(treeNode)\n } else {\n roots.push(treeNode)\n }\n }\n await logCrudAccess({\n container,\n auth,\n request: req,\n items: roots,\n idField: 'id',\n resourceKind: 'directory.organization',\n organizationId: null,\n tenantId,\n query,\n })\n return NextResponse.json({ items: roots })\n }\n\n if (query.view !== 'manage') {\n return NextResponse.json({ items: [] }, { status: 400 })\n }\n\n if (allowAllTenants) {\n // Multi-tenant aggregate view for super administrators\n const search = (query.search || '').trim().toLowerCase()\n const allOrgs = await findWithDecryption(\n em,\n Organization,\n { deletedAt: null },\n { orderBy: { name: 'ASC' }, populate: ['tenant'] },\n { tenantId: null, organizationId: null },\n )\n const byTenant = new Map<string, Organization[]>()\n for (const org of allOrgs) {\n const tenantEntity = org.tenant\n const tid = tenantEntity ? stringId(tenantEntity.id) : null\n if (!tid) continue\n if (!byTenant.has(tid)) byTenant.set(tid, [])\n byTenant.get(tid)!.push(org)\n }\n\n const slugByOrgId = new Map<string, string | null>()\n const updatedAtByOrgId = new Map<string, string | null>()\n const logoUrlByOrgId = new Map<string, string | null>()\n for (const org of allOrgs) {\n slugByOrgId.set(String(org.id), org.slug ?? null)\n updatedAtByOrgId.set(String(org.id), org.updatedAt instanceof Date ? org.updatedAt.toISOString() : null)\n logoUrlByOrgId.set(String(org.id), org.logoUrl ?? null)\n }\n\n const tenantIds = Array.from(byTenant.keys())\n const tenants = tenantIds.length\n ? await em.find(Tenant, { id: { $in: tenantIds as unknown as string[] } })\n : []\n const tenantNameMap = tenants.reduce<Record<string, string>>((acc, tenant) => {\n const tid = stringId(tenant.id)\n const name = typeof tenant.name === 'string' && tenant.name.length > 0 ? tenant.name : tid\n acc[tid] = name\n return acc\n }, {})\n\n const hierarchies = new Map<string, ComputedHierarchy>()\n const orderedNodes: Array<{ tenantId: string; node: ComputedOrganizationNode }> = []\n for (const [tid, orgs] of byTenant.entries()) {\n const hierarchy = computeHierarchyForOrganizations(orgs, tid)\n hierarchies.set(tid, hierarchy)\n for (const node of hierarchy.ordered) {\n orderedNodes.push({ tenantId: tid, node })\n }\n }\n\n let rows = orderedNodes\n if (query.status === 'active') {\n rows = rows.filter((entry) => entry.node.isActive)\n } else if (query.status === 'inactive') {\n rows = rows.filter((entry) => !entry.node.isActive)\n }\n\n if (search) {\n rows = rows.filter(({ node }) => {\n const pathLabel = (node.pathLabel || '').toLowerCase()\n return node.name.toLowerCase().includes(search) || pathLabel.includes(search)\n })\n }\n if (ids) {\n const idSet = new Set(ids)\n rows = rows.filter(({ node }) => idSet.has(node.id))\n }\n\n rows.sort((a, b) => {\n const nameA = tenantNameMap[a.tenantId] ?? a.tenantId\n const nameB = tenantNameMap[b.tenantId] ?? b.tenantId\n const tenantCompare = nameA.localeCompare(nameB)\n if (tenantCompare !== 0) return tenantCompare\n return a.node.pathLabel.localeCompare(b.node.pathLabel)\n })\n\n const total = rows.length\n const pageSize = query.pageSize\n const page = query.page\n const start = (page - 1) * pageSize\n const paged = rows.slice(start, start + pageSize)\n const recordIds: string[] = []\n const tenantIdByRecord: Record<string, string | null> = {}\n const organizationIdByRecord: Record<string, string | null> = {}\n for (const entry of paged) {\n const recordId = String(entry.node.id)\n recordIds.push(recordId)\n tenantIdByRecord[recordId] = entry.tenantId\n organizationIdByRecord[recordId] = recordId\n }\n const tenantFallbacks = Array.from(new Set(recordIds.map((id) => tenantIdByRecord[id]).filter((value): value is string => typeof value === 'string' && value.length > 0)))\n const cfByOrg = recordIds.length\n ? await loadCustomFieldValues({\n em,\n entityId: E.directory.organization,\n recordIds,\n tenantIdByRecord,\n organizationIdByRecord,\n tenantFallbacks,\n })\n : {}\n const items = paged.map(({ tenantId: tid, node }) => {\n const hierarchy = hierarchies.get(tid)\n const parentName = node.parentId && hierarchy ? hierarchy.map.get(node.parentId)?.name ?? null : null\n const pathLabel = node.pathLabel || node.name\n const recordId = String(node.id)\n return {\n id: node.id,\n name: node.name,\n slug: slugByOrgId.get(recordId) ?? null,\n updatedAt: updatedAtByOrgId.get(recordId) ?? null,\n logoUrl: logoUrlByOrgId.get(recordId) ?? null,\n tenantId: tid,\n tenantName: tenantNameMap[tid] ?? tid,\n parentId: node.parentId,\n parentName,\n depth: node.depth,\n rootId: node.rootId,\n treePath: node.treePath,\n pathLabel,\n ancestorIds: node.ancestorIds,\n childIds: node.childIds,\n descendantIds: node.descendantIds,\n childrenCount: node.childIds.length,\n descendantsCount: node.descendantIds.length,\n isActive: node.isActive,\n ...(cfByOrg[recordId] ?? {}),\n }\n })\n const totalPages = Math.max(1, Math.ceil(total / pageSize))\n await logCrudAccess({\n container,\n auth,\n request: req,\n items,\n idField: 'id',\n resourceKind: 'directory.organization',\n organizationId: null,\n tenantId: null,\n query,\n accessType: ids && ids.length === 1 ? 'read:item' : undefined,\n })\n return NextResponse.json({ items, total, page, pageSize, totalPages, isSuperAdmin })\n }\n\n if (!tenantId) {\n return NextResponse.json({ items: [], error: 'Tenant scope required' }, { status: 400 })\n }\n\n const orgListFilter: FilterQuery<Organization> = { tenant: tenantId, deletedAt: null }\n const orgs = await em.find(Organization, orgListFilter, { orderBy: { name: 'ASC' } })\n const hierarchy = computeHierarchyForOrganizations(orgs, tenantId)\n const slugByOrgId = new Map<string, string | null>()\n const logoUrlByOrgId = new Map<string, string | null>()\n const updatedAtByOrgId = new Map<string, string | null>()\n for (const org of orgs) {\n slugByOrgId.set(String(org.id), org.slug ?? null)\n logoUrlByOrgId.set(String(org.id), org.logoUrl ?? null)\n updatedAtByOrgId.set(String(org.id), org.updatedAt instanceof Date ? org.updatedAt.toISOString() : null)\n }\n\n // Manage view: paginated flat list for a single tenant\n const search = (query.search || '').trim().toLowerCase()\n let rows = hierarchy.ordered\n if (status === 'active') {\n rows = rows.filter((node) => node.isActive)\n } else if (status === 'inactive') {\n rows = rows.filter((node) => !node.isActive)\n }\n\n if (search) {\n rows = rows.filter((node) => {\n const pathLabel = (node.pathLabel || '').toLowerCase()\n return node.name.toLowerCase().includes(search) || pathLabel.includes(search)\n })\n }\n if (ids) {\n const idSet = new Set(ids)\n rows = rows.filter((node) => idSet.has(node.id))\n }\n\n const total = rows.length\n const pageSize = query.pageSize\n const page = query.page\n const start = (page - 1) * pageSize\n const paged = rows.slice(start, start + pageSize)\n const recordIds: string[] = []\n const tenantIdByRecord: Record<string, string | null> = {}\n const organizationIdByRecord: Record<string, string | null> = {}\n for (const node of paged) {\n const recordId = String(node.id)\n recordIds.push(recordId)\n tenantIdByRecord[recordId] = node.tenantId ? String(node.tenantId) : null\n organizationIdByRecord[recordId] = recordId\n }\n const cfByOrg = recordIds.length\n ? await loadCustomFieldValues({\n em,\n entityId: E.directory.organization,\n recordIds,\n tenantIdByRecord,\n organizationIdByRecord,\n tenantFallbacks: tenantId ? [tenantId] : [],\n })\n : {}\n let tenantName: string | null = null\n if (isSuperAdmin && tenantId) {\n const tenant = await em.findOne(Tenant, { id: tenantId })\n if (tenant) {\n const display = typeof tenant.name === 'string' && tenant.name.length > 0 ? tenant.name : stringId(tenant.id)\n tenantName = display\n }\n }\n const items = paged.map((node) => {\n const parentName = node.parentId ? hierarchy.map.get(node.parentId)?.name ?? null : null\n const pathLabel = node.pathLabel || node.name\n const recordId = String(node.id)\n return {\n id: node.id,\n name: node.name,\n slug: slugByOrgId.get(recordId) ?? null,\n logoUrl: logoUrlByOrgId.get(recordId) ?? null,\n updatedAt: updatedAtByOrgId.get(recordId) ?? null,\n tenantId: node.tenantId,\n tenantName,\n parentId: node.parentId,\n parentName,\n depth: node.depth,\n rootId: node.rootId,\n treePath: node.treePath,\n pathLabel,\n ancestorIds: node.ancestorIds,\n childIds: node.childIds,\n descendantIds: node.descendantIds,\n childrenCount: node.childIds.length,\n descendantsCount: node.descendantIds.length,\n isActive: node.isActive,\n ...(cfByOrg[recordId] ?? {}),\n }\n })\n const totalPages = Math.max(1, Math.ceil(total / pageSize))\n await logCrudAccess({\n container,\n auth,\n request: req,\n items,\n idField: 'id',\n resourceKind: 'directory.organization',\n organizationId: null,\n tenantId,\n query,\n accessType: ids && ids.length === 1 ? 'read:item' : undefined,\n })\n return NextResponse.json({ items, total, page, pageSize, totalPages, isSuperAdmin })\n}\n\nexport const POST = crud.POST\nexport const PUT = crud.PUT\nexport const DELETE = crud.DELETE\n\nconst organizationCreateResponseSchema = z.object({\n id: z.string().uuid(),\n})\n\nconst organizationDeleteRequestSchema = z.object({\n id: z.string().uuid(),\n})\n\nconst organizationsGetDoc: OpenApiMethodDoc = {\n summary: 'List organizations',\n description: 'Returns organizations using options, tree, or paginated manage view depending on the `view` parameter.',\n tags: [directoryTag],\n query: viewSchema,\n responses: [\n { status: 200, description: 'Organization data for the requested view.', schema: organizationListResponseSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid query or tenant scope', schema: directoryErrorSchema },\n { status: 401, description: 'Authentication required', schema: directoryErrorSchema },\n ],\n}\n\nconst organizationsPostDoc: OpenApiMethodDoc = {\n summary: 'Create organization',\n description: 'Creates a new organization within a tenant and optionally assigns hierarchy relationships.',\n tags: [directoryTag],\n requestBody: {\n contentType: 'application/json',\n schema: organizationCreateSchema,\n description: 'Organization attributes and optional hierarchy configuration.',\n },\n responses: [\n { status: 201, description: 'Organization created.', schema: organizationCreateResponseSchema },\n ],\n errors: [\n { status: 400, description: 'Validation failed', schema: directoryErrorSchema },\n { status: 401, description: 'Authentication required', schema: directoryErrorSchema },\n { status: 403, description: 'Missing directory.organizations.manage feature', schema: directoryErrorSchema },\n ],\n}\n\nconst organizationsPutDoc: OpenApiMethodDoc = {\n summary: 'Update organization',\n description: 'Updates organization details and hierarchy assignments.',\n tags: [directoryTag],\n requestBody: {\n contentType: 'application/json',\n schema: organizationUpdateSchema,\n description: 'Organization identifier followed by fields to update.',\n },\n responses: [\n { status: 200, description: 'Organization updated.', schema: directoryOkSchema },\n ],\n errors: [\n { status: 400, description: 'Validation failed', schema: directoryErrorSchema },\n { status: 401, description: 'Authentication required', schema: directoryErrorSchema },\n { status: 403, description: 'Missing directory.organizations.manage feature', schema: directoryErrorSchema },\n ],\n}\n\nconst organizationsDeleteDoc: OpenApiMethodDoc = {\n summary: 'Delete organization',\n description: 'Soft deletes an organization identified by id.',\n tags: [directoryTag],\n requestBody: {\n contentType: 'application/json',\n schema: organizationDeleteRequestSchema,\n description: 'Identifier of the organization to delete.',\n },\n responses: [\n { status: 200, description: 'Organization deleted.', schema: directoryOkSchema },\n ],\n errors: [\n { status: 400, description: 'Validation failed', schema: directoryErrorSchema },\n { status: 401, description: 'Authentication required', schema: directoryErrorSchema },\n { status: 403, description: 'Missing directory.organizations.manage feature', schema: directoryErrorSchema },\n ],\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: directoryTag,\n summary: 'Manage organizations',\n methods: {\n GET: organizationsGetDoc,\n POST: organizationsPostDoc,\n PUT: organizationsPutDoc,\n DELETE: organizationsDeleteDoc,\n },\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["orgs", "items", "orgListFilter", "hierarchy", "search", "slugByOrgId", "updatedAtByOrgId", "logoUrlByOrgId", "rows", "total", "pageSize", "page", "start", "paged", "recordIds", "tenantIdByRecord", "organizationIdByRecord", "cfByOrg", "totalPages"]
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { logCrudAccess, makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { Organization, Tenant } from '@open-mercato/core/modules/directory/data/entities'\nimport { organizationCreateSchema, organizationUpdateSchema } from '@open-mercato/core/modules/directory/data/validators'\nimport {\n computeHierarchyForOrganizations,\n type ComputedHierarchy,\n type ComputedOrganizationNode,\n} from '@open-mercato/core/modules/directory/lib/hierarchy'\nimport { isAllOrganizationsSelection } from '@open-mercato/core/modules/directory/constants'\nimport {\n getSelectedOrganizationFromRequest,\n resolveOrganizationScopeForRequest,\n} from '@open-mercato/core/modules/directory/utils/organizationScope'\nimport { loadCustomFieldValues } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { E } from '#generated/entities.ids.generated'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { FilterQuery } from '@mikro-orm/core'\nimport { organizationCrudEvents, organizationCrudIndexer } from '@open-mercato/core/modules/directory/commands/organizations'\nimport type { OpenApiMethodDoc, OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { parseBooleanToken } from '@open-mercato/shared/lib/boolean'\nimport {\n directoryTag,\n directoryErrorSchema,\n directoryOkSchema,\n organizationListResponseSchema,\n} from '../openapi'\nimport { resolveIsSuperAdmin, enforceTenantSelection } from '@open-mercato/core/modules/auth/lib/tenantAccess'\nimport { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\n\ntype CrudInput = Record<string, unknown>\nconst rawBodySchema = z.object({}).passthrough()\n\ntype TreeNode = {\n id: string\n name: string\n parentId: string | null\n tenantId: string | null\n depth: number\n ancestorIds: string[]\n childIds: string[]\n descendantIds: string[]\n isActive: boolean\n treePath: string | null\n pathLabel: string\n children: TreeNode[]\n}\n\nconst viewSchema = z.object({\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(50),\n search: z.string().optional(),\n view: z.enum(['options', 'manage', 'tree']).default('options'),\n ids: z.string().optional(),\n tenantId: z.string().uuid().optional(),\n includeInactive: z.enum(['true', 'false']).optional(),\n status: z.enum(['all', 'active', 'inactive']).optional(),\n})\n\nfunction parseIds(raw: string | null): string[] | null {\n if (!raw) return null\n const ids = raw.split(',').map((s) => s.trim()).filter(Boolean)\n return ids.length ? Array.from(new Set(ids)) : null\n}\n\nfunction stringId(value: unknown): string {\n return String(value)\n}\n\nfunction enforceTenantScope(\n authTenantId: string | null,\n requestedTenantId: string | null,\n isSuperAdmin: boolean,\n): string | null {\n if (isSuperAdmin) {\n return requestedTenantId || authTenantId || null\n }\n if (authTenantId && requestedTenantId && requestedTenantId !== authTenantId) {\n return null\n }\n return requestedTenantId || authTenantId\n}\n\nconst crud = makeCrudRoute<CrudInput, CrudInput, Record<string, unknown>>({\n metadata: {\n GET: { requireAuth: true, requireFeatures: ['directory.organizations.view'] },\n POST: { requireAuth: true, requireFeatures: ['directory.organizations.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['directory.organizations.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['directory.organizations.manage'] },\n },\n orm: {\n entity: Organization,\n idField: 'id',\n orgField: null,\n tenantField: null,\n softDeleteField: 'deletedAt',\n },\n events: organizationCrudEvents,\n indexer: organizationCrudIndexer,\n actions: {\n create: {\n commandId: 'directory.organizations.create',\n schema: rawBodySchema,\n mapInput: ({ parsed }) => parsed,\n response: ({ result }) => ({ id: String(result.id) }),\n status: 201,\n },\n update: {\n commandId: 'directory.organizations.update',\n schema: rawBodySchema,\n mapInput: ({ parsed }) => parsed,\n response: () => ({ ok: true }),\n },\n delete: {\n commandId: 'directory.organizations.delete',\n response: () => ({ ok: true }),\n },\n },\n})\n\nexport const metadata = crud.metadata\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) return NextResponse.json({ items: [] }, { status: 401 })\n\n const url = new URL(req.url)\n const parsed = viewSchema.safeParse({\n page: url.searchParams.get('page') ?? undefined,\n pageSize: url.searchParams.get('pageSize') ?? undefined,\n search: url.searchParams.get('search') ?? undefined,\n view: url.searchParams.get('view') ?? undefined,\n ids: url.searchParams.get('ids') ?? undefined,\n tenantId: url.searchParams.get('tenantId') ?? undefined,\n includeInactive: url.searchParams.get('includeInactive') ?? undefined,\n status: url.searchParams.get('status') ?? undefined,\n })\n if (!parsed.success) return NextResponse.json({ items: [] }, { status: 400 })\n\n const query = parsed.data\n const ids = parseIds(query.ids ?? null)\n const requestedTenantRaw = query.tenantId ?? null\n const normalizedRequestedTenantId = requestedTenantRaw && requestedTenantRaw.toLowerCase() === 'all' ? null : requestedTenantRaw\n const authTenantId = auth.tenantId ?? null\n const container = await createRequestContainer()\n const isSuperAdmin = await resolveIsSuperAdmin({ auth, container })\n const em = (container.resolve('em') as EntityManager)\n const allowAllTenants = isSuperAdmin && !normalizedRequestedTenantId && query.view === 'manage'\n let tenantId = allowAllTenants ? null : enforceTenantScope(authTenantId, normalizedRequestedTenantId, isSuperAdmin)\n const status = query.status ?? 'all'\n const includeInactive = parseBooleanToken(query.includeInactive) === true || status !== 'active'\n\n if (!allowAllTenants && !tenantId && !authTenantId && ids?.length) {\n let scopedIds = ids\n if (!isSuperAdmin) {\n let allowedIds: string[] | null = null\n try {\n const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req })\n allowedIds = Array.isArray(scope.allowedIds) ? scope.allowedIds : null\n } catch {}\n const allowedSet = allowedIds ? new Set(allowedIds) : new Set<string>()\n scopedIds = ids.filter((id) => allowedSet.has(id))\n }\n if (scopedIds.length) {\n const scopedOrgs: Organization[] = await findWithDecryption(\n em,\n Organization,\n { id: { $in: scopedIds }, deletedAt: null },\n { populate: ['tenant'] },\n { tenantId: authTenantId, organizationId: null },\n )\n const tenantCandidates = new Set<string>()\n for (const org of scopedOrgs) {\n const orgTenantId = org.tenant?.id ? stringId(org.tenant.id) : ''\n if (orgTenantId) tenantCandidates.add(orgTenantId)\n }\n if (tenantCandidates.size === 1) {\n const candidateTenantId = Array.from(tenantCandidates)[0] ?? null\n try {\n tenantId = await enforceTenantSelection({ auth, container }, candidateTenantId)\n } catch (error) {\n if (isCrudHttpError(error)) {\n return NextResponse.json(error.body, { status: error.status })\n }\n throw error\n }\n } else if (tenantCandidates.size > 1) {\n return NextResponse.json({ items: [], error: 'Tenant scope required' }, { status: 400 })\n }\n }\n }\n\n if (!allowAllTenants && !tenantId) {\n const candidateOrgIds = new Set<string>()\n const cookieOrgId = getSelectedOrganizationFromRequest(req)\n const effectiveCookieOrgId = cookieOrgId && !isAllOrganizationsSelection(cookieOrgId) ? cookieOrgId : null\n if (effectiveCookieOrgId) candidateOrgIds.add(effectiveCookieOrgId)\n if (auth.orgId) candidateOrgIds.add(auth.orgId)\n\n try {\n const scope = await resolveOrganizationScopeForRequest({\n container,\n auth,\n request: req,\n selectedId: effectiveCookieOrgId ?? undefined,\n })\n if (scope.selectedId) candidateOrgIds.add(scope.selectedId)\n if (Array.isArray(scope.filterIds) && scope.filterIds.length) {\n candidateOrgIds.add(scope.filterIds[0]!)\n }\n if (Array.isArray(scope.allowedIds) && scope.allowedIds.length) {\n candidateOrgIds.add(scope.allowedIds[0]!)\n }\n } catch {}\n\n for (const orgId of candidateOrgIds) {\n if (!orgId) continue\n const org = await findOneWithDecryption(\n em,\n Organization,\n { id: orgId, deletedAt: null },\n { populate: ['tenant'] },\n { tenantId: authTenantId, organizationId: orgId },\n )\n if (org?.tenant && org.tenant.id) {\n tenantId = stringId(org.tenant.id)\n break\n }\n }\n }\n\n if (!allowAllTenants && !tenantId) {\n return NextResponse.json({ items: [], error: 'Tenant scope required' }, { status: 400 })\n }\n\n if (query.view === 'options') {\n if (!tenantId) {\n return NextResponse.json({ items: [], error: 'Tenant scope required' }, { status: 400 })\n }\n const where: FilterQuery<Organization> = { tenant: tenantId, deletedAt: null }\n if (status === 'active') where.isActive = true\n if (status === 'inactive') where.isActive = false\n if (status === 'all' && !includeInactive) where.isActive = true\n if (ids) where.id = { $in: ids }\n const orgs = await em.find(Organization, where, { orderBy: { name: 'ASC' } })\n const items = orgs.map((org) => ({\n id: stringId(org.id),\n name: org.name,\n logoUrl: org.logoUrl ?? null,\n logoPreserveAspectRatio: !!org.logoPreserveAspectRatio,\n parentId: org.parentId ?? null,\n tenantId: tenantId,\n isActive: !!org.isActive,\n depth: org.depth ?? 0,\n treePath: org.treePath ?? stringId(org.id),\n }))\n await logCrudAccess({\n container,\n auth,\n request: req,\n items,\n idField: 'id',\n resourceKind: 'directory.organization',\n organizationId: null,\n tenantId,\n query,\n accessType: ids && ids.length === 1 ? 'read:item' : undefined,\n })\n return NextResponse.json({ items })\n }\n\n if (query.view === 'tree') {\n if (!tenantId) {\n return NextResponse.json({ items: [], error: 'Tenant scope required' }, { status: 400 })\n }\n const orgListFilter: FilterQuery<Organization> = { tenant: tenantId, deletedAt: null }\n const orgs = await em.find(Organization, orgListFilter, { orderBy: { name: 'ASC' } })\n const hierarchy = computeHierarchyForOrganizations(orgs, tenantId)\n const nodeMap = new Map<string, { node: ComputedOrganizationNode; children: TreeNode[] }>()\n const roots: TreeNode[] = []\n for (const node of hierarchy.ordered) {\n const treeNode: TreeNode = {\n id: node.id,\n name: node.name,\n parentId: node.parentId,\n tenantId: node.tenantId,\n depth: node.depth,\n ancestorIds: node.ancestorIds,\n childIds: node.childIds,\n descendantIds: node.descendantIds,\n isActive: node.isActive,\n treePath: node.treePath,\n pathLabel: node.pathLabel,\n children: [],\n }\n nodeMap.set(node.id, { node, children: treeNode.children })\n if (node.parentId && nodeMap.has(node.parentId)) {\n const parentEntry = nodeMap.get(node.parentId)!\n parentEntry.children.push(treeNode)\n } else {\n roots.push(treeNode)\n }\n }\n await logCrudAccess({\n container,\n auth,\n request: req,\n items: roots,\n idField: 'id',\n resourceKind: 'directory.organization',\n organizationId: null,\n tenantId,\n query,\n })\n return NextResponse.json({ items: roots })\n }\n\n if (query.view !== 'manage') {\n return NextResponse.json({ items: [] }, { status: 400 })\n }\n\n if (allowAllTenants) {\n // Multi-tenant aggregate view for super administrators\n const search = (query.search || '').trim().toLowerCase()\n const allOrgs = await findWithDecryption(\n em,\n Organization,\n { deletedAt: null },\n { orderBy: { name: 'ASC' }, populate: ['tenant'] },\n { tenantId: null, organizationId: null },\n )\n const byTenant = new Map<string, Organization[]>()\n for (const org of allOrgs) {\n const tenantEntity = org.tenant\n const tid = tenantEntity ? stringId(tenantEntity.id) : null\n if (!tid) continue\n if (!byTenant.has(tid)) byTenant.set(tid, [])\n byTenant.get(tid)!.push(org)\n }\n\n const slugByOrgId = new Map<string, string | null>()\n const updatedAtByOrgId = new Map<string, string | null>()\n const logoUrlByOrgId = new Map<string, string | null>()\n const logoPreserveAspectRatioByOrgId = new Map<string, boolean>()\n for (const org of allOrgs) {\n slugByOrgId.set(String(org.id), org.slug ?? null)\n updatedAtByOrgId.set(String(org.id), org.updatedAt instanceof Date ? org.updatedAt.toISOString() : null)\n logoUrlByOrgId.set(String(org.id), org.logoUrl ?? null)\n logoPreserveAspectRatioByOrgId.set(String(org.id), !!org.logoPreserveAspectRatio)\n }\n\n const tenantIds = Array.from(byTenant.keys())\n const tenants = tenantIds.length\n ? await em.find(Tenant, { id: { $in: tenantIds as unknown as string[] } })\n : []\n const tenantNameMap = tenants.reduce<Record<string, string>>((acc, tenant) => {\n const tid = stringId(tenant.id)\n const name = typeof tenant.name === 'string' && tenant.name.length > 0 ? tenant.name : tid\n acc[tid] = name\n return acc\n }, {})\n\n const hierarchies = new Map<string, ComputedHierarchy>()\n const orderedNodes: Array<{ tenantId: string; node: ComputedOrganizationNode }> = []\n for (const [tid, orgs] of byTenant.entries()) {\n const hierarchy = computeHierarchyForOrganizations(orgs, tid)\n hierarchies.set(tid, hierarchy)\n for (const node of hierarchy.ordered) {\n orderedNodes.push({ tenantId: tid, node })\n }\n }\n\n let rows = orderedNodes\n if (query.status === 'active') {\n rows = rows.filter((entry) => entry.node.isActive)\n } else if (query.status === 'inactive') {\n rows = rows.filter((entry) => !entry.node.isActive)\n }\n\n if (search) {\n rows = rows.filter(({ node }) => {\n const pathLabel = (node.pathLabel || '').toLowerCase()\n return node.name.toLowerCase().includes(search) || pathLabel.includes(search)\n })\n }\n if (ids) {\n const idSet = new Set(ids)\n rows = rows.filter(({ node }) => idSet.has(node.id))\n }\n\n rows.sort((a, b) => {\n const nameA = tenantNameMap[a.tenantId] ?? a.tenantId\n const nameB = tenantNameMap[b.tenantId] ?? b.tenantId\n const tenantCompare = nameA.localeCompare(nameB)\n if (tenantCompare !== 0) return tenantCompare\n return a.node.pathLabel.localeCompare(b.node.pathLabel)\n })\n\n const total = rows.length\n const pageSize = query.pageSize\n const page = query.page\n const start = (page - 1) * pageSize\n const paged = rows.slice(start, start + pageSize)\n const recordIds: string[] = []\n const tenantIdByRecord: Record<string, string | null> = {}\n const organizationIdByRecord: Record<string, string | null> = {}\n for (const entry of paged) {\n const recordId = String(entry.node.id)\n recordIds.push(recordId)\n tenantIdByRecord[recordId] = entry.tenantId\n organizationIdByRecord[recordId] = recordId\n }\n const tenantFallbacks = Array.from(new Set(recordIds.map((id) => tenantIdByRecord[id]).filter((value): value is string => typeof value === 'string' && value.length > 0)))\n const cfByOrg = recordIds.length\n ? await loadCustomFieldValues({\n em,\n entityId: E.directory.organization,\n recordIds,\n tenantIdByRecord,\n organizationIdByRecord,\n tenantFallbacks,\n })\n : {}\n const items = paged.map(({ tenantId: tid, node }) => {\n const hierarchy = hierarchies.get(tid)\n const parentName = node.parentId && hierarchy ? hierarchy.map.get(node.parentId)?.name ?? null : null\n const pathLabel = node.pathLabel || node.name\n const recordId = String(node.id)\n return {\n id: node.id,\n name: node.name,\n slug: slugByOrgId.get(recordId) ?? null,\n updatedAt: updatedAtByOrgId.get(recordId) ?? null,\n logoUrl: logoUrlByOrgId.get(recordId) ?? null,\n logoPreserveAspectRatio: logoPreserveAspectRatioByOrgId.get(recordId) ?? false,\n tenantId: tid,\n tenantName: tenantNameMap[tid] ?? tid,\n parentId: node.parentId,\n parentName,\n depth: node.depth,\n rootId: node.rootId,\n treePath: node.treePath,\n pathLabel,\n ancestorIds: node.ancestorIds,\n childIds: node.childIds,\n descendantIds: node.descendantIds,\n childrenCount: node.childIds.length,\n descendantsCount: node.descendantIds.length,\n isActive: node.isActive,\n ...(cfByOrg[recordId] ?? {}),\n }\n })\n const totalPages = Math.max(1, Math.ceil(total / pageSize))\n await logCrudAccess({\n container,\n auth,\n request: req,\n items,\n idField: 'id',\n resourceKind: 'directory.organization',\n organizationId: null,\n tenantId: null,\n query,\n accessType: ids && ids.length === 1 ? 'read:item' : undefined,\n })\n return NextResponse.json({ items, total, page, pageSize, totalPages, isSuperAdmin })\n }\n\n if (!tenantId) {\n return NextResponse.json({ items: [], error: 'Tenant scope required' }, { status: 400 })\n }\n\n const orgListFilter: FilterQuery<Organization> = { tenant: tenantId, deletedAt: null }\n const orgs = await em.find(Organization, orgListFilter, { orderBy: { name: 'ASC' } })\n const hierarchy = computeHierarchyForOrganizations(orgs, tenantId)\n const slugByOrgId = new Map<string, string | null>()\n const logoUrlByOrgId = new Map<string, string | null>()\n const logoPreserveAspectRatioByOrgId = new Map<string, boolean>()\n const updatedAtByOrgId = new Map<string, string | null>()\n for (const org of orgs) {\n slugByOrgId.set(String(org.id), org.slug ?? null)\n logoUrlByOrgId.set(String(org.id), org.logoUrl ?? null)\n logoPreserveAspectRatioByOrgId.set(String(org.id), !!org.logoPreserveAspectRatio)\n updatedAtByOrgId.set(String(org.id), org.updatedAt instanceof Date ? org.updatedAt.toISOString() : null)\n }\n\n // Manage view: paginated flat list for a single tenant\n const search = (query.search || '').trim().toLowerCase()\n let rows = hierarchy.ordered\n if (status === 'active') {\n rows = rows.filter((node) => node.isActive)\n } else if (status === 'inactive') {\n rows = rows.filter((node) => !node.isActive)\n }\n\n if (search) {\n rows = rows.filter((node) => {\n const pathLabel = (node.pathLabel || '').toLowerCase()\n return node.name.toLowerCase().includes(search) || pathLabel.includes(search)\n })\n }\n if (ids) {\n const idSet = new Set(ids)\n rows = rows.filter((node) => idSet.has(node.id))\n }\n\n const total = rows.length\n const pageSize = query.pageSize\n const page = query.page\n const start = (page - 1) * pageSize\n const paged = rows.slice(start, start + pageSize)\n const recordIds: string[] = []\n const tenantIdByRecord: Record<string, string | null> = {}\n const organizationIdByRecord: Record<string, string | null> = {}\n for (const node of paged) {\n const recordId = String(node.id)\n recordIds.push(recordId)\n tenantIdByRecord[recordId] = node.tenantId ? String(node.tenantId) : null\n organizationIdByRecord[recordId] = recordId\n }\n const cfByOrg = recordIds.length\n ? await loadCustomFieldValues({\n em,\n entityId: E.directory.organization,\n recordIds,\n tenantIdByRecord,\n organizationIdByRecord,\n tenantFallbacks: tenantId ? [tenantId] : [],\n })\n : {}\n let tenantName: string | null = null\n if (isSuperAdmin && tenantId) {\n const tenant = await em.findOne(Tenant, { id: tenantId })\n if (tenant) {\n const display = typeof tenant.name === 'string' && tenant.name.length > 0 ? tenant.name : stringId(tenant.id)\n tenantName = display\n }\n }\n const items = paged.map((node) => {\n const parentName = node.parentId ? hierarchy.map.get(node.parentId)?.name ?? null : null\n const pathLabel = node.pathLabel || node.name\n const recordId = String(node.id)\n return {\n id: node.id,\n name: node.name,\n slug: slugByOrgId.get(recordId) ?? null,\n logoUrl: logoUrlByOrgId.get(recordId) ?? null,\n logoPreserveAspectRatio: logoPreserveAspectRatioByOrgId.get(recordId) ?? false,\n updatedAt: updatedAtByOrgId.get(recordId) ?? null,\n tenantId: node.tenantId,\n tenantName,\n parentId: node.parentId,\n parentName,\n depth: node.depth,\n rootId: node.rootId,\n treePath: node.treePath,\n pathLabel,\n ancestorIds: node.ancestorIds,\n childIds: node.childIds,\n descendantIds: node.descendantIds,\n childrenCount: node.childIds.length,\n descendantsCount: node.descendantIds.length,\n isActive: node.isActive,\n ...(cfByOrg[recordId] ?? {}),\n }\n })\n const totalPages = Math.max(1, Math.ceil(total / pageSize))\n await logCrudAccess({\n container,\n auth,\n request: req,\n items,\n idField: 'id',\n resourceKind: 'directory.organization',\n organizationId: null,\n tenantId,\n query,\n accessType: ids && ids.length === 1 ? 'read:item' : undefined,\n })\n return NextResponse.json({ items, total, page, pageSize, totalPages, isSuperAdmin })\n}\n\nexport const POST = crud.POST\nexport const PUT = crud.PUT\nexport const DELETE = crud.DELETE\n\nconst organizationCreateResponseSchema = z.object({\n id: z.string().uuid(),\n})\n\nconst organizationDeleteRequestSchema = z.object({\n id: z.string().uuid(),\n})\n\nconst organizationsGetDoc: OpenApiMethodDoc = {\n summary: 'List organizations',\n description: 'Returns organizations using options, tree, or paginated manage view depending on the `view` parameter.',\n tags: [directoryTag],\n query: viewSchema,\n responses: [\n { status: 200, description: 'Organization data for the requested view.', schema: organizationListResponseSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid query or tenant scope', schema: directoryErrorSchema },\n { status: 401, description: 'Authentication required', schema: directoryErrorSchema },\n ],\n}\n\nconst organizationsPostDoc: OpenApiMethodDoc = {\n summary: 'Create organization',\n description: 'Creates a new organization within a tenant and optionally assigns hierarchy relationships.',\n tags: [directoryTag],\n requestBody: {\n contentType: 'application/json',\n schema: organizationCreateSchema,\n description: 'Organization attributes and optional hierarchy configuration.',\n },\n responses: [\n { status: 201, description: 'Organization created.', schema: organizationCreateResponseSchema },\n ],\n errors: [\n { status: 400, description: 'Validation failed', schema: directoryErrorSchema },\n { status: 401, description: 'Authentication required', schema: directoryErrorSchema },\n { status: 403, description: 'Missing directory.organizations.manage feature', schema: directoryErrorSchema },\n ],\n}\n\nconst organizationsPutDoc: OpenApiMethodDoc = {\n summary: 'Update organization',\n description: 'Updates organization details and hierarchy assignments.',\n tags: [directoryTag],\n requestBody: {\n contentType: 'application/json',\n schema: organizationUpdateSchema,\n description: 'Organization identifier followed by fields to update.',\n },\n responses: [\n { status: 200, description: 'Organization updated.', schema: directoryOkSchema },\n ],\n errors: [\n { status: 400, description: 'Validation failed', schema: directoryErrorSchema },\n { status: 401, description: 'Authentication required', schema: directoryErrorSchema },\n { status: 403, description: 'Missing directory.organizations.manage feature', schema: directoryErrorSchema },\n ],\n}\n\nconst organizationsDeleteDoc: OpenApiMethodDoc = {\n summary: 'Delete organization',\n description: 'Soft deletes an organization identified by id.',\n tags: [directoryTag],\n requestBody: {\n contentType: 'application/json',\n schema: organizationDeleteRequestSchema,\n description: 'Identifier of the organization to delete.',\n },\n responses: [\n { status: 200, description: 'Organization deleted.', schema: directoryOkSchema },\n ],\n errors: [\n { status: 400, description: 'Validation failed', schema: directoryErrorSchema },\n { status: 401, description: 'Authentication required', schema: directoryErrorSchema },\n { status: 403, description: 'Missing directory.organizations.manage feature', schema: directoryErrorSchema },\n ],\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: directoryTag,\n summary: 'Manage organizations',\n methods: {\n GET: organizationsGetDoc,\n POST: organizationsPostDoc,\n PUT: organizationsPutDoc,\n DELETE: organizationsDeleteDoc,\n },\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAClB,SAAS,eAAe,qBAAqB;AAC7C,SAAS,0BAA0B;AACnC,SAAS,8BAA8B;AACvC,SAAS,cAAc,cAAc;AACrC,SAAS,0BAA0B,gCAAgC;AACnE;AAAA,EACE;AAAA,OAGK;AACP,SAAS,mCAAmC;AAC5C;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,6BAA6B;AACtC,SAAS,SAAS;AAGlB,SAAS,wBAAwB,+BAA+B;AAEhE,SAAS,yBAAyB;AAClC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,qBAAqB,8BAA8B;AAC5D,SAAS,uBAAuB;AAChC,SAAS,oBAAoB,6BAA6B;AAG1D,MAAM,gBAAgB,EAAE,OAAO,CAAC,CAAC,EAAE,YAAY;AAiB/C,MAAM,aAAa,EAAE,OAAO;AAAA,EAC1B,MAAM,EAAE,OAAO,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC;AAAA,EACxC,UAAU,EAAE,OAAO,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE;AAAA,EACtD,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,MAAM,EAAE,KAAK,CAAC,WAAW,UAAU,MAAM,CAAC,EAAE,QAAQ,SAAS;AAAA,EAC7D,KAAK,EAAE,OAAO,EAAE,SAAS;AAAA,EACzB,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS;AAAA,EACrC,iBAAiB,EAAE,KAAK,CAAC,QAAQ,OAAO,CAAC,EAAE,SAAS;AAAA,EACpD,QAAQ,EAAE,KAAK,CAAC,OAAO,UAAU,UAAU,CAAC,EAAE,SAAS;AACzD,CAAC;AAED,SAAS,SAAS,KAAqC;AACrD,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,MAAM,IAAI,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AAC9D,SAAO,IAAI,SAAS,MAAM,KAAK,IAAI,IAAI,GAAG,CAAC,IAAI;AACjD;AAEA,SAAS,SAAS,OAAwB;AACxC,SAAO,OAAO,KAAK;AACrB;AAEA,SAAS,mBACP,cACA,mBACA,cACe;AACf,MAAI,cAAc;AAChB,WAAO,qBAAqB,gBAAgB;AAAA,EAC9C;AACA,MAAI,gBAAgB,qBAAqB,sBAAsB,cAAc;AAC3E,WAAO;AAAA,EACT;AACA,SAAO,qBAAqB;AAC9B;AAEA,MAAM,OAAO,cAA6D;AAAA,EACxE,UAAU;AAAA,IACR,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,8BAA8B,EAAE;AAAA,IAC5E,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,gCAAgC,EAAE;AAAA,IAC/E,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,gCAAgC,EAAE;AAAA,IAC9E,QAAQ,EAAE,aAAa,MAAM,iBAAiB,CAAC,gCAAgC,EAAE;AAAA,EACnF;AAAA,EACA,KAAK;AAAA,IACH,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,UAAU;AAAA,IACV,aAAa;AAAA,IACb,iBAAiB;AAAA,EACnB;AAAA,EACA,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,SAAS;AAAA,IACP,QAAQ;AAAA,MACN,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,UAAU,CAAC,EAAE,OAAO,MAAM;AAAA,MAC1B,UAAU,CAAC,EAAE,OAAO,OAAO,EAAE,IAAI,OAAO,OAAO,EAAE,EAAE;AAAA,MACnD,QAAQ;AAAA,IACV;AAAA,IACA,QAAQ;AAAA,MACN,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,UAAU,CAAC,EAAE,OAAO,MAAM;AAAA,MAC1B,UAAU,OAAO,EAAE,IAAI,KAAK;AAAA,IAC9B;AAAA,IACA,QAAQ;AAAA,MACN,WAAW;AAAA,MACX,UAAU,OAAO,EAAE,IAAI,KAAK;AAAA,IAC9B;AAAA,EACF;AACF,CAAC;AAEM,MAAM,WAAW,KAAK;AAE7B,eAAsB,IAAI,KAAc;AACtC,QAAM,OAAO,MAAM,mBAAmB,GAAG;AACzC,MAAI,CAAC,KAAM,QAAO,aAAa,KAAK,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,QAAQ,IAAI,CAAC;AAElE,QAAM,MAAM,IAAI,IAAI,IAAI,GAAG;AAC3B,QAAM,SAAS,WAAW,UAAU;AAAA,IAClC,MAAM,IAAI,aAAa,IAAI,MAAM,KAAK;AAAA,IACtC,UAAU,IAAI,aAAa,IAAI,UAAU,KAAK;AAAA,IAC9C,QAAQ,IAAI,aAAa,IAAI,QAAQ,KAAK;AAAA,IAC1C,MAAM,IAAI,aAAa,IAAI,MAAM,KAAK;AAAA,IACtC,KAAK,IAAI,aAAa,IAAI,KAAK,KAAK;AAAA,IACpC,UAAU,IAAI,aAAa,IAAI,UAAU,KAAK;AAAA,IAC9C,iBAAiB,IAAI,aAAa,IAAI,iBAAiB,KAAK;AAAA,IAC5D,QAAQ,IAAI,aAAa,IAAI,QAAQ,KAAK;AAAA,EAC5C,CAAC;AACD,MAAI,CAAC,OAAO,QAAS,QAAO,aAAa,KAAK,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,QAAQ,IAAI,CAAC;AAE5E,QAAM,QAAQ,OAAO;AACrB,QAAM,MAAM,SAAS,MAAM,OAAO,IAAI;AACtC,QAAM,qBAAqB,MAAM,YAAY;AAC7C,QAAM,8BAA8B,sBAAsB,mBAAmB,YAAY,MAAM,QAAQ,OAAO;AAC9G,QAAM,eAAe,KAAK,YAAY;AACtC,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,eAAe,MAAM,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAClE,QAAM,KAAM,UAAU,QAAQ,IAAI;AAClC,QAAM,kBAAkB,gBAAgB,CAAC,+BAA+B,MAAM,SAAS;AACvF,MAAI,WAAW,kBAAkB,OAAO,mBAAmB,cAAc,6BAA6B,YAAY;AAClH,QAAM,SAAS,MAAM,UAAU;AAC/B,QAAM,kBAAkB,kBAAkB,MAAM,eAAe,MAAM,QAAQ,WAAW;AAExF,MAAI,CAAC,mBAAmB,CAAC,YAAY,CAAC,gBAAgB,KAAK,QAAQ;AACjE,QAAI,YAAY;AAChB,QAAI,CAAC,cAAc;AACjB,UAAI,aAA8B;AAClC,UAAI;AACF,cAAM,QAAQ,MAAM,mCAAmC,EAAE,WAAW,MAAM,SAAS,IAAI,CAAC;AACxF,qBAAa,MAAM,QAAQ,MAAM,UAAU,IAAI,MAAM,aAAa;AAAA,MACpE,QAAQ;AAAA,MAAC;AACT,YAAM,aAAa,aAAa,IAAI,IAAI,UAAU,IAAI,oBAAI,IAAY;AACtE,kBAAY,IAAI,OAAO,CAAC,OAAO,WAAW,IAAI,EAAE,CAAC;AAAA,IACnD;AACA,QAAI,UAAU,QAAQ;AACpB,YAAM,aAA6B,MAAM;AAAA,QACvC;AAAA,QACA;AAAA,QACA,EAAE,IAAI,EAAE,KAAK,UAAU,GAAG,WAAW,KAAK;AAAA,QAC1C,EAAE,UAAU,CAAC,QAAQ,EAAE;AAAA,QACvB,EAAE,UAAU,cAAc,gBAAgB,KAAK;AAAA,MACjD;AACA,YAAM,mBAAmB,oBAAI,IAAY;AACzC,iBAAW,OAAO,YAAY;AAC5B,cAAM,cAAc,IAAI,QAAQ,KAAK,SAAS,IAAI,OAAO,EAAE,IAAI;AAC/D,YAAI,YAAa,kBAAiB,IAAI,WAAW;AAAA,MACnD;AACA,UAAI,iBAAiB,SAAS,GAAG;AAC/B,cAAM,oBAAoB,MAAM,KAAK,gBAAgB,EAAE,CAAC,KAAK;AAC7D,YAAI;AACF,qBAAW,MAAM,uBAAuB,EAAE,MAAM,UAAU,GAAG,iBAAiB;AAAA,QAChF,SAAS,OAAO;AACd,cAAI,gBAAgB,KAAK,GAAG;AAC1B,mBAAO,aAAa,KAAK,MAAM,MAAM,EAAE,QAAQ,MAAM,OAAO,CAAC;AAAA,UAC/D;AACA,gBAAM;AAAA,QACR;AAAA,MACF,WAAW,iBAAiB,OAAO,GAAG;AACpC,eAAO,aAAa,KAAK,EAAE,OAAO,CAAC,GAAG,OAAO,wBAAwB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,MACzF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,mBAAmB,CAAC,UAAU;AACjC,UAAM,kBAAkB,oBAAI,IAAY;AACxC,UAAM,cAAc,mCAAmC,GAAG;AAC1D,UAAM,uBAAuB,eAAe,CAAC,4BAA4B,WAAW,IAAI,cAAc;AACtG,QAAI,qBAAsB,iBAAgB,IAAI,oBAAoB;AAClE,QAAI,KAAK,MAAO,iBAAgB,IAAI,KAAK,KAAK;AAE9C,QAAI;AACF,YAAM,QAAQ,MAAM,mCAAmC;AAAA,QACrD;AAAA,QACA;AAAA,QACA,SAAS;AAAA,QACT,YAAY,wBAAwB;AAAA,MACtC,CAAC;AACD,UAAI,MAAM,WAAY,iBAAgB,IAAI,MAAM,UAAU;AAC1D,UAAI,MAAM,QAAQ,MAAM,SAAS,KAAK,MAAM,UAAU,QAAQ;AAC5D,wBAAgB,IAAI,MAAM,UAAU,CAAC,CAAE;AAAA,MACzC;AACA,UAAI,MAAM,QAAQ,MAAM,UAAU,KAAK,MAAM,WAAW,QAAQ;AAC9D,wBAAgB,IAAI,MAAM,WAAW,CAAC,CAAE;AAAA,MAC1C;AAAA,IACF,QAAQ;AAAA,IAAC;AAET,eAAW,SAAS,iBAAiB;AACnC,UAAI,CAAC,MAAO;AACZ,YAAM,MAAM,MAAM;AAAA,QAChB;AAAA,QACA;AAAA,QACA,EAAE,IAAI,OAAO,WAAW,KAAK;AAAA,QAC7B,EAAE,UAAU,CAAC,QAAQ,EAAE;AAAA,QACvB,EAAE,UAAU,cAAc,gBAAgB,MAAM;AAAA,MAClD;AACA,UAAI,KAAK,UAAU,IAAI,OAAO,IAAI;AAChC,mBAAW,SAAS,IAAI,OAAO,EAAE;AACjC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,mBAAmB,CAAC,UAAU;AACjC,WAAO,aAAa,KAAK,EAAE,OAAO,CAAC,GAAG,OAAO,wBAAwB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACzF;AAEA,MAAI,MAAM,SAAS,WAAW;AAC5B,QAAI,CAAC,UAAU;AACb,aAAO,aAAa,KAAK,EAAE,OAAO,CAAC,GAAG,OAAO,wBAAwB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IACzF;AACA,UAAM,QAAmC,EAAE,QAAQ,UAAU,WAAW,KAAK;AAC7E,QAAI,WAAW,SAAU,OAAM,WAAW;AAC1C,QAAI,WAAW,WAAY,OAAM,WAAW;AAC5C,QAAI,WAAW,SAAS,CAAC,gBAAiB,OAAM,WAAW;AAC3D,QAAI,IAAK,OAAM,KAAK,EAAE,KAAK,IAAI;AAC/B,UAAMA,QAAO,MAAM,GAAG,KAAK,cAAc,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,EAAE,CAAC;AAC5E,UAAMC,SAAQD,MAAK,IAAI,CAAC,SAAS;AAAA,MAC/B,IAAI,SAAS,IAAI,EAAE;AAAA,MACnB,MAAM,IAAI;AAAA,MACV,SAAS,IAAI,WAAW;AAAA,MACxB,yBAAyB,CAAC,CAAC,IAAI;AAAA,MAC/B,UAAU,IAAI,YAAY;AAAA,MAC1B;AAAA,MACA,UAAU,CAAC,CAAC,IAAI;AAAA,MAChB,OAAO,IAAI,SAAS;AAAA,MACpB,UAAU,IAAI,YAAY,SAAS,IAAI,EAAE;AAAA,IAC3C,EAAE;AACF,UAAM,cAAc;AAAA,MAClB;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,OAAAC;AAAA,MACA,SAAS;AAAA,MACT,cAAc;AAAA,MACd,gBAAgB;AAAA,MAChB;AAAA,MACA;AAAA,MACA,YAAY,OAAO,IAAI,WAAW,IAAI,cAAc;AAAA,IACtD,CAAC;AACD,WAAO,aAAa,KAAK,EAAE,OAAAA,OAAM,CAAC;AAAA,EACpC;AAEA,MAAI,MAAM,SAAS,QAAQ;AACzB,QAAI,CAAC,UAAU;AACb,aAAO,aAAa,KAAK,EAAE,OAAO,CAAC,GAAG,OAAO,wBAAwB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IACzF;AACA,UAAMC,iBAA2C,EAAE,QAAQ,UAAU,WAAW,KAAK;AACrF,UAAMF,QAAO,MAAM,GAAG,KAAK,cAAcE,gBAAe,EAAE,SAAS,EAAE,MAAM,MAAM,EAAE,CAAC;AACpF,UAAMC,aAAY,iCAAiCH,OAAM,QAAQ;AACjE,UAAM,UAAU,oBAAI,IAAsE;AAC1F,UAAM,QAAoB,CAAC;AAC3B,eAAW,QAAQG,WAAU,SAAS;AACpC,YAAM,WAAqB;AAAA,QACzB,IAAI,KAAK;AAAA,QACT,MAAM,KAAK;AAAA,QACX,UAAU,KAAK;AAAA,QACf,UAAU,KAAK;AAAA,QACf,OAAO,KAAK;AAAA,QACZ,aAAa,KAAK;AAAA,QAClB,UAAU,KAAK;AAAA,QACf,eAAe,KAAK;AAAA,QACpB,UAAU,KAAK;AAAA,QACf,UAAU,KAAK;AAAA,QACf,WAAW,KAAK;AAAA,QAChB,UAAU,CAAC;AAAA,MACb;AACA,cAAQ,IAAI,KAAK,IAAI,EAAE,MAAM,UAAU,SAAS,SAAS,CAAC;AAC1D,UAAI,KAAK,YAAY,QAAQ,IAAI,KAAK,QAAQ,GAAG;AAC/C,cAAM,cAAc,QAAQ,IAAI,KAAK,QAAQ;AAC7C,oBAAY,SAAS,KAAK,QAAQ;AAAA,MACpC,OAAO;AACL,cAAM,KAAK,QAAQ;AAAA,MACrB;AAAA,IACF;AACA,UAAM,cAAc;AAAA,MAClB;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,OAAO;AAAA,MACP,SAAS;AAAA,MACT,cAAc;AAAA,MACd,gBAAgB;AAAA,MAChB;AAAA,MACA;AAAA,IACF,CAAC;AACD,WAAO,aAAa,KAAK,EAAE,OAAO,MAAM,CAAC;AAAA,EAC3C;AAEA,MAAI,MAAM,SAAS,UAAU;AAC3B,WAAO,aAAa,KAAK,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACzD;AAEA,MAAI,iBAAiB;AAEnB,UAAMC,WAAU,MAAM,UAAU,IAAI,KAAK,EAAE,YAAY;AACvD,UAAM,UAAU,MAAM;AAAA,MACpB;AAAA,MACA;AAAA,MACA,EAAE,WAAW,KAAK;AAAA,MAClB,EAAE,SAAS,EAAE,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,EAAE;AAAA,MACjD,EAAE,UAAU,MAAM,gBAAgB,KAAK;AAAA,IACzC;AACA,UAAM,WAAW,oBAAI,IAA4B;AACjD,eAAW,OAAO,SAAS;AACzB,YAAM,eAAe,IAAI;AACzB,YAAM,MAAM,eAAe,SAAS,aAAa,EAAE,IAAI;AACvD,UAAI,CAAC,IAAK;AACV,UAAI,CAAC,SAAS,IAAI,GAAG,EAAG,UAAS,IAAI,KAAK,CAAC,CAAC;AAC5C,eAAS,IAAI,GAAG,EAAG,KAAK,GAAG;AAAA,IAC7B;AAEA,UAAMC,eAAc,oBAAI,IAA2B;AACnD,UAAMC,oBAAmB,oBAAI,IAA2B;AACxD,UAAMC,kBAAiB,oBAAI,IAA2B;AACtD,UAAMC,kCAAiC,oBAAI,IAAqB;AAChE,eAAW,OAAO,SAAS;AACzB,MAAAH,aAAY,IAAI,OAAO,IAAI,EAAE,GAAG,IAAI,QAAQ,IAAI;AAChD,MAAAC,kBAAiB,IAAI,OAAO,IAAI,EAAE,GAAG,IAAI,qBAAqB,OAAO,IAAI,UAAU,YAAY,IAAI,IAAI;AACvG,MAAAC,gBAAe,IAAI,OAAO,IAAI,EAAE,GAAG,IAAI,WAAW,IAAI;AACtD,MAAAC,gCAA+B,IAAI,OAAO,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,uBAAuB;AAAA,IAClF;AAEA,UAAM,YAAY,MAAM,KAAK,SAAS,KAAK,CAAC;AAC5C,UAAM,UAAU,UAAU,SACtB,MAAM,GAAG,KAAK,QAAQ,EAAE,IAAI,EAAE,KAAK,UAAiC,EAAE,CAAC,IACvE,CAAC;AACL,UAAM,gBAAgB,QAAQ,OAA+B,CAAC,KAAK,WAAW;AAC5E,YAAM,MAAM,SAAS,OAAO,EAAE;AAC9B,YAAM,OAAO,OAAO,OAAO,SAAS,YAAY,OAAO,KAAK,SAAS,IAAI,OAAO,OAAO;AACvF,UAAI,GAAG,IAAI;AACX,aAAO;AAAA,IACT,GAAG,CAAC,CAAC;AAEL,UAAM,cAAc,oBAAI,IAA+B;AACvD,UAAM,eAA4E,CAAC;AACnF,eAAW,CAAC,KAAKR,KAAI,KAAK,SAAS,QAAQ,GAAG;AAC5C,YAAMG,aAAY,iCAAiCH,OAAM,GAAG;AAC5D,kBAAY,IAAI,KAAKG,UAAS;AAC9B,iBAAW,QAAQA,WAAU,SAAS;AACpC,qBAAa,KAAK,EAAE,UAAU,KAAK,KAAK,CAAC;AAAA,MAC3C;AAAA,IACF;AAEA,QAAIM,QAAO;AACX,QAAI,MAAM,WAAW,UAAU;AAC7B,MAAAA,QAAOA,MAAK,OAAO,CAAC,UAAU,MAAM,KAAK,QAAQ;AAAA,IACnD,WAAW,MAAM,WAAW,YAAY;AACtC,MAAAA,QAAOA,MAAK,OAAO,CAAC,UAAU,CAAC,MAAM,KAAK,QAAQ;AAAA,IACpD;AAEA,QAAIL,SAAQ;AACV,MAAAK,QAAOA,MAAK,OAAO,CAAC,EAAE,KAAK,MAAM;AAC/B,cAAM,aAAa,KAAK,aAAa,IAAI,YAAY;AACrD,eAAO,KAAK,KAAK,YAAY,EAAE,SAASL,OAAM,KAAK,UAAU,SAASA,OAAM;AAAA,MAC9E,CAAC;AAAA,IACH;AACA,QAAI,KAAK;AACP,YAAM,QAAQ,IAAI,IAAI,GAAG;AACzB,MAAAK,QAAOA,MAAK,OAAO,CAAC,EAAE,KAAK,MAAM,MAAM,IAAI,KAAK,EAAE,CAAC;AAAA,IACrD;AAEA,IAAAA,MAAK,KAAK,CAAC,GAAG,MAAM;AAClB,YAAM,QAAQ,cAAc,EAAE,QAAQ,KAAK,EAAE;AAC7C,YAAM,QAAQ,cAAc,EAAE,QAAQ,KAAK,EAAE;AAC7C,YAAM,gBAAgB,MAAM,cAAc,KAAK;AAC/C,UAAI,kBAAkB,EAAG,QAAO;AAChC,aAAO,EAAE,KAAK,UAAU,cAAc,EAAE,KAAK,SAAS;AAAA,IACxD,CAAC;AAED,UAAMC,SAAQD,MAAK;AACnB,UAAME,YAAW,MAAM;AACvB,UAAMC,QAAO,MAAM;AACnB,UAAMC,UAASD,QAAO,KAAKD;AAC3B,UAAMG,SAAQL,MAAK,MAAMI,QAAOA,SAAQF,SAAQ;AAChD,UAAMI,aAAsB,CAAC;AAC7B,UAAMC,oBAAkD,CAAC;AACzD,UAAMC,0BAAwD,CAAC;AAC/D,eAAW,SAASH,QAAO;AACzB,YAAM,WAAW,OAAO,MAAM,KAAK,EAAE;AACrC,MAAAC,WAAU,KAAK,QAAQ;AACvB,MAAAC,kBAAiB,QAAQ,IAAI,MAAM;AACnC,MAAAC,wBAAuB,QAAQ,IAAI;AAAA,IACrC;AACA,UAAM,kBAAkB,MAAM,KAAK,IAAI,IAAIF,WAAU,IAAI,CAAC,OAAOC,kBAAiB,EAAE,CAAC,EAAE,OAAO,CAAC,UAA2B,OAAO,UAAU,YAAY,MAAM,SAAS,CAAC,CAAC,CAAC;AACzK,UAAME,WAAUH,WAAU,SACtB,MAAM,sBAAsB;AAAA,MAC1B;AAAA,MACA,UAAU,EAAE,UAAU;AAAA,MACtB,WAAAA;AAAA,MACA,kBAAAC;AAAA,MACA,wBAAAC;AAAA,MACA;AAAA,IACF,CAAC,IACD,CAAC;AACL,UAAMhB,SAAQa,OAAM,IAAI,CAAC,EAAE,UAAU,KAAK,KAAK,MAAM;AACnD,YAAMX,aAAY,YAAY,IAAI,GAAG;AACrC,YAAM,aAAa,KAAK,YAAYA,aAAYA,WAAU,IAAI,IAAI,KAAK,QAAQ,GAAG,QAAQ,OAAO;AACjG,YAAM,YAAY,KAAK,aAAa,KAAK;AACzC,YAAM,WAAW,OAAO,KAAK,EAAE;AAC/B,aAAO;AAAA,QACL,IAAI,KAAK;AAAA,QACT,MAAM,KAAK;AAAA,QACX,MAAME,aAAY,IAAI,QAAQ,KAAK;AAAA,QACnC,WAAWC,kBAAiB,IAAI,QAAQ,KAAK;AAAA,QAC7C,SAASC,gBAAe,IAAI,QAAQ,KAAK;AAAA,QACzC,yBAAyBC,gCAA+B,IAAI,QAAQ,KAAK;AAAA,QACzE,UAAU;AAAA,QACV,YAAY,cAAc,GAAG,KAAK;AAAA,QAClC,UAAU,KAAK;AAAA,QACf;AAAA,QACA,OAAO,KAAK;AAAA,QACZ,QAAQ,KAAK;AAAA,QACb,UAAU,KAAK;AAAA,QACf;AAAA,QACA,aAAa,KAAK;AAAA,QAClB,UAAU,KAAK;AAAA,QACf,eAAe,KAAK;AAAA,QACpB,eAAe,KAAK,SAAS;AAAA,QAC7B,kBAAkB,KAAK,cAAc;AAAA,QACrC,UAAU,KAAK;AAAA,QACf,GAAIU,SAAQ,QAAQ,KAAK,CAAC;AAAA,MAC5B;AAAA,IACF,CAAC;AACD,UAAMC,cAAa,KAAK,IAAI,GAAG,KAAK,KAAKT,SAAQC,SAAQ,CAAC;AAC1D,UAAM,cAAc;AAAA,MAClB;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,OAAAV;AAAA,MACA,SAAS;AAAA,MACT,cAAc;AAAA,MACd,gBAAgB;AAAA,MAChB,UAAU;AAAA,MACV;AAAA,MACA,YAAY,OAAO,IAAI,WAAW,IAAI,cAAc;AAAA,IACtD,CAAC;AACD,WAAO,aAAa,KAAK,EAAE,OAAAA,QAAO,OAAAS,QAAO,MAAAE,OAAM,UAAAD,WAAU,YAAAQ,aAAY,aAAa,CAAC;AAAA,EACrF;AAEA,MAAI,CAAC,UAAU;AACb,WAAO,aAAa,KAAK,EAAE,OAAO,CAAC,GAAG,OAAO,wBAAwB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACzF;AAEA,QAAM,gBAA2C,EAAE,QAAQ,UAAU,WAAW,KAAK;AACrF,QAAM,OAAO,MAAM,GAAG,KAAK,cAAc,eAAe,EAAE,SAAS,EAAE,MAAM,MAAM,EAAE,CAAC;AACpF,QAAM,YAAY,iCAAiC,MAAM,QAAQ;AACjE,QAAM,cAAc,oBAAI,IAA2B;AACnD,QAAM,iBAAiB,oBAAI,IAA2B;AACtD,QAAM,iCAAiC,oBAAI,IAAqB;AAChE,QAAM,mBAAmB,oBAAI,IAA2B;AACxD,aAAW,OAAO,MAAM;AACtB,gBAAY,IAAI,OAAO,IAAI,EAAE,GAAG,IAAI,QAAQ,IAAI;AAChD,mBAAe,IAAI,OAAO,IAAI,EAAE,GAAG,IAAI,WAAW,IAAI;AACtD,mCAA+B,IAAI,OAAO,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,uBAAuB;AAChF,qBAAiB,IAAI,OAAO,IAAI,EAAE,GAAG,IAAI,qBAAqB,OAAO,IAAI,UAAU,YAAY,IAAI,IAAI;AAAA,EACzG;AAGA,QAAM,UAAU,MAAM,UAAU,IAAI,KAAK,EAAE,YAAY;AACvD,MAAI,OAAO,UAAU;AACrB,MAAI,WAAW,UAAU;AACvB,WAAO,KAAK,OAAO,CAAC,SAAS,KAAK,QAAQ;AAAA,EAC5C,WAAW,WAAW,YAAY;AAChC,WAAO,KAAK,OAAO,CAAC,SAAS,CAAC,KAAK,QAAQ;AAAA,EAC7C;AAEA,MAAI,QAAQ;AACV,WAAO,KAAK,OAAO,CAAC,SAAS;AAC3B,YAAM,aAAa,KAAK,aAAa,IAAI,YAAY;AACrD,aAAO,KAAK,KAAK,YAAY,EAAE,SAAS,MAAM,KAAK,UAAU,SAAS,MAAM;AAAA,IAC9E,CAAC;AAAA,EACH;AACA,MAAI,KAAK;AACP,UAAM,QAAQ,IAAI,IAAI,GAAG;AACzB,WAAO,KAAK,OAAO,CAAC,SAAS,MAAM,IAAI,KAAK,EAAE,CAAC;AAAA,EACjD;AAEA,QAAM,QAAQ,KAAK;AACnB,QAAM,WAAW,MAAM;AACvB,QAAM,OAAO,MAAM;AACnB,QAAM,SAAS,OAAO,KAAK;AAC3B,QAAM,QAAQ,KAAK,MAAM,OAAO,QAAQ,QAAQ;AAChD,QAAM,YAAsB,CAAC;AAC7B,QAAM,mBAAkD,CAAC;AACzD,QAAM,yBAAwD,CAAC;AAC/D,aAAW,QAAQ,OAAO;AACxB,UAAM,WAAW,OAAO,KAAK,EAAE;AAC/B,cAAU,KAAK,QAAQ;AACvB,qBAAiB,QAAQ,IAAI,KAAK,WAAW,OAAO,KAAK,QAAQ,IAAI;AACrE,2BAAuB,QAAQ,IAAI;AAAA,EACrC;AACA,QAAM,UAAU,UAAU,SACtB,MAAM,sBAAsB;AAAA,IAC1B;AAAA,IACA,UAAU,EAAE,UAAU;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA,iBAAiB,WAAW,CAAC,QAAQ,IAAI,CAAC;AAAA,EAC5C,CAAC,IACD,CAAC;AACL,MAAI,aAA4B;AAChC,MAAI,gBAAgB,UAAU;AAC5B,UAAM,SAAS,MAAM,GAAG,QAAQ,QAAQ,EAAE,IAAI,SAAS,CAAC;AACxD,QAAI,QAAQ;AACV,YAAM,UAAU,OAAO,OAAO,SAAS,YAAY,OAAO,KAAK,SAAS,IAAI,OAAO,OAAO,SAAS,OAAO,EAAE;AAC5G,mBAAa;AAAA,IACf;AAAA,EACF;AACA,QAAM,QAAQ,MAAM,IAAI,CAAC,SAAS;AAChC,UAAM,aAAa,KAAK,WAAW,UAAU,IAAI,IAAI,KAAK,QAAQ,GAAG,QAAQ,OAAO;AACpF,UAAM,YAAY,KAAK,aAAa,KAAK;AACzC,UAAM,WAAW,OAAO,KAAK,EAAE;AAC/B,WAAO;AAAA,MACL,IAAI,KAAK;AAAA,MACT,MAAM,KAAK;AAAA,MACX,MAAM,YAAY,IAAI,QAAQ,KAAK;AAAA,MACnC,SAAS,eAAe,IAAI,QAAQ,KAAK;AAAA,MACzC,yBAAyB,+BAA+B,IAAI,QAAQ,KAAK;AAAA,MACzE,WAAW,iBAAiB,IAAI,QAAQ,KAAK;AAAA,MAC7C,UAAU,KAAK;AAAA,MACf;AAAA,MACA,UAAU,KAAK;AAAA,MACf;AAAA,MACA,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf;AAAA,MACA,aAAa,KAAK;AAAA,MAClB,UAAU,KAAK;AAAA,MACf,eAAe,KAAK;AAAA,MACpB,eAAe,KAAK,SAAS;AAAA,MAC7B,kBAAkB,KAAK,cAAc;AAAA,MACrC,UAAU,KAAK;AAAA,MACf,GAAI,QAAQ,QAAQ,KAAK,CAAC;AAAA,IAC5B;AAAA,EACF,CAAC;AACD,QAAM,aAAa,KAAK,IAAI,GAAG,KAAK,KAAK,QAAQ,QAAQ,CAAC;AAC1D,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA,SAAS;AAAA,IACT,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB;AAAA,IACA;AAAA,IACA,YAAY,OAAO,IAAI,WAAW,IAAI,cAAc;AAAA,EACtD,CAAC;AACD,SAAO,aAAa,KAAK,EAAE,OAAO,OAAO,MAAM,UAAU,YAAY,aAAa,CAAC;AACrF;AAEO,MAAM,OAAO,KAAK;AAClB,MAAM,MAAM,KAAK;AACjB,MAAM,SAAS,KAAK;AAE3B,MAAM,mCAAmC,EAAE,OAAO;AAAA,EAChD,IAAI,EAAE,OAAO,EAAE,KAAK;AACtB,CAAC;AAED,MAAM,kCAAkC,EAAE,OAAO;AAAA,EAC/C,IAAI,EAAE,OAAO,EAAE,KAAK;AACtB,CAAC;AAED,MAAM,sBAAwC;AAAA,EAC5C,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM,CAAC,YAAY;AAAA,EACnB,OAAO;AAAA,EACP,WAAW;AAAA,IACT,EAAE,QAAQ,KAAK,aAAa,6CAA6C,QAAQ,+BAA+B;AAAA,EAClH;AAAA,EACA,QAAQ;AAAA,IACN,EAAE,QAAQ,KAAK,aAAa,iCAAiC,QAAQ,qBAAqB;AAAA,IAC1F,EAAE,QAAQ,KAAK,aAAa,2BAA2B,QAAQ,qBAAqB;AAAA,EACtF;AACF;AAEA,MAAM,uBAAyC;AAAA,EAC7C,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM,CAAC,YAAY;AAAA,EACnB,aAAa;AAAA,IACX,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,aAAa;AAAA,EACf;AAAA,EACA,WAAW;AAAA,IACT,EAAE,QAAQ,KAAK,aAAa,yBAAyB,QAAQ,iCAAiC;AAAA,EAChG;AAAA,EACA,QAAQ;AAAA,IACN,EAAE,QAAQ,KAAK,aAAa,qBAAqB,QAAQ,qBAAqB;AAAA,IAC9E,EAAE,QAAQ,KAAK,aAAa,2BAA2B,QAAQ,qBAAqB;AAAA,IACpF,EAAE,QAAQ,KAAK,aAAa,kDAAkD,QAAQ,qBAAqB;AAAA,EAC7G;AACF;AAEA,MAAM,sBAAwC;AAAA,EAC5C,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM,CAAC,YAAY;AAAA,EACnB,aAAa;AAAA,IACX,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,aAAa;AAAA,EACf;AAAA,EACA,WAAW;AAAA,IACT,EAAE,QAAQ,KAAK,aAAa,yBAAyB,QAAQ,kBAAkB;AAAA,EACjF;AAAA,EACA,QAAQ;AAAA,IACN,EAAE,QAAQ,KAAK,aAAa,qBAAqB,QAAQ,qBAAqB;AAAA,IAC9E,EAAE,QAAQ,KAAK,aAAa,2BAA2B,QAAQ,qBAAqB;AAAA,IACpF,EAAE,QAAQ,KAAK,aAAa,kDAAkD,QAAQ,qBAAqB;AAAA,EAC7G;AACF;AAEA,MAAM,yBAA2C;AAAA,EAC/C,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM,CAAC,YAAY;AAAA,EACnB,aAAa;AAAA,IACX,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,aAAa;AAAA,EACf;AAAA,EACA,WAAW;AAAA,IACT,EAAE,QAAQ,KAAK,aAAa,yBAAyB,QAAQ,kBAAkB;AAAA,EACjF;AAAA,EACA,QAAQ;AAAA,IACN,EAAE,QAAQ,KAAK,aAAa,qBAAqB,QAAQ,qBAAqB;AAAA,IAC9E,EAAE,QAAQ,KAAK,aAAa,2BAA2B,QAAQ,qBAAqB;AAAA,IACpF,EAAE,QAAQ,KAAK,aAAa,kDAAkD,QAAQ,qBAAqB;AAAA,EAC7G;AACF;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,KAAK;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AACF;",
|
|
6
|
+
"names": ["orgs", "items", "orgListFilter", "hierarchy", "search", "slugByOrgId", "updatedAtByOrgId", "logoUrlByOrgId", "logoPreserveAspectRatioByOrgId", "rows", "total", "pageSize", "page", "start", "paged", "recordIds", "tenantIdByRecord", "organizationIdByRecord", "cfByOrg", "totalPages"]
|
|
7
7
|
}
|
|
@@ -2,6 +2,7 @@ import { NextResponse } from "next/server";
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { logCrudAccess, makeCrudRoute } from "@open-mercato/shared/lib/crud/factory";
|
|
4
4
|
import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
|
|
5
|
+
import { resolveIsSuperAdmin } from "@open-mercato/core/modules/auth/lib/tenantAccess";
|
|
5
6
|
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
|
|
6
7
|
import { Tenant } from "@open-mercato/core/modules/directory/data/entities";
|
|
7
8
|
import { tenantCreateSchema, tenantUpdateSchema } from "@open-mercato/core/modules/directory/data/validators";
|
|
@@ -73,6 +74,11 @@ async function GET(req) {
|
|
|
73
74
|
if (!auth) {
|
|
74
75
|
return NextResponse.json({ items: [], total: 0, page: 1, pageSize: 50, totalPages: 1 }, { status: 401 });
|
|
75
76
|
}
|
|
77
|
+
const container = await createRequestContainer();
|
|
78
|
+
const isSuperAdmin = await resolveIsSuperAdmin({ auth, container });
|
|
79
|
+
if (!isSuperAdmin) {
|
|
80
|
+
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
|
|
81
|
+
}
|
|
76
82
|
const url = new URL(req.url);
|
|
77
83
|
const parsed = listQuerySchema.safeParse({
|
|
78
84
|
id: url.searchParams.get("id") ?? void 0,
|
|
@@ -89,7 +95,6 @@ async function GET(req) {
|
|
|
89
95
|
{ status: 400 }
|
|
90
96
|
);
|
|
91
97
|
}
|
|
92
|
-
const container = await createRequestContainer();
|
|
93
98
|
const em = container.resolve("em");
|
|
94
99
|
const { id, page, pageSize, search, sortField, sortDir, isActive } = parsed.data;
|
|
95
100
|
const where = { deletedAt: null };
|
|
@@ -210,7 +215,8 @@ const tenantGetDoc = {
|
|
|
210
215
|
],
|
|
211
216
|
errors: [
|
|
212
217
|
{ status: 400, description: "Invalid query parameters", schema: directoryErrorSchema },
|
|
213
|
-
{ status: 401, description: "Authentication required", schema: directoryErrorSchema }
|
|
218
|
+
{ status: 401, description: "Authentication required", schema: directoryErrorSchema },
|
|
219
|
+
{ status: 403, description: "Requires super-admin", schema: directoryErrorSchema }
|
|
214
220
|
]
|
|
215
221
|
};
|
|
216
222
|
const tenantPostDoc = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/directory/api/tenants/route.ts"],
|
|
4
|
-
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { logCrudAccess, makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { Tenant } from '@open-mercato/core/modules/directory/data/entities'\nimport { tenantCreateSchema, tenantUpdateSchema } from '@open-mercato/core/modules/directory/data/validators'\nimport { loadCustomFieldValues, buildCustomFieldFiltersFromQuery } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { resolveRecordIdsForCustomFieldFilters } from './tenant-cf-filter'\nimport { E } from '#generated/entities.ids.generated'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { FilterQuery } from '@mikro-orm/core'\nimport { tenantCrudEvents, tenantCrudIndexer } from '@open-mercato/core/modules/directory/commands/tenants'\nimport type { OpenApiMethodDoc, OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { directoryTag, directoryErrorSchema, directoryOkSchema, tenantListResponseSchema } from '../openapi'\nimport { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'\nimport { parseBooleanToken } from '@open-mercato/shared/lib/boolean'\n\nconst listQuerySchema = z.object({\n id: z.string().uuid().optional(),\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(50),\n search: z.string().optional(),\n sortField: z.enum(['name', 'createdAt', 'updatedAt']).optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n isActive: z.enum(['true', 'false']).optional(),\n}).passthrough()\n\ntype TenantRow = {\n id: string\n name: string\n isActive: boolean\n createdAt: string | null\n updatedAt: string | null\n} & Record<string, unknown>\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['directory.tenants.view'] },\n POST: { requireAuth: true, requireFeatures: ['directory.tenants.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['directory.tenants.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['directory.tenants.manage'] },\n}\n\nexport const metadata = routeMetadata\n\nconst rawBodySchema = z.object({}).passthrough()\ntype CrudInput = Record<string, unknown>\n\nconst crud = makeCrudRoute<CrudInput, CrudInput, Record<string, unknown>>({\n metadata: routeMetadata,\n orm: {\n entity: Tenant,\n idField: 'id',\n orgField: null,\n tenantField: null,\n softDeleteField: 'deletedAt',\n },\n events: tenantCrudEvents,\n indexer: tenantCrudIndexer,\n actions: {\n create: {\n commandId: 'directory.tenants.create',\n schema: rawBodySchema,\n mapInput: ({ parsed }) => parsed,\n response: ({ result }) => ({ id: String(result.id) }),\n status: 201,\n },\n update: {\n commandId: 'directory.tenants.update',\n schema: rawBodySchema,\n mapInput: ({ parsed }) => parsed,\n response: () => ({ ok: true }),\n },\n delete: {\n commandId: 'directory.tenants.delete',\n response: () => ({ ok: true }),\n },\n },\n})\n\nconst toRow = (tenant: Tenant, cf: Record<string, unknown>): TenantRow => ({\n id: String(tenant.id),\n name: String(tenant.name),\n isActive: !!tenant.isActive,\n createdAt: tenant.createdAt ? tenant.createdAt.toISOString() : null,\n updatedAt: tenant.updatedAt ? tenant.updatedAt.toISOString() : null,\n ...cf,\n})\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ items: [], total: 0, page: 1, pageSize: 50, totalPages: 1 }, { status: 401 })\n }\n\n const url = new URL(req.url)\n const parsed = listQuerySchema.safeParse({\n id: url.searchParams.get('id') ?? undefined,\n page: url.searchParams.get('page') ?? undefined,\n pageSize: url.searchParams.get('pageSize') ?? undefined,\n search: url.searchParams.get('search') ?? undefined,\n sortField: url.searchParams.get('sortField') ?? undefined,\n sortDir: url.searchParams.get('sortDir') ?? undefined,\n isActive: url.searchParams.get('isActive') ?? undefined,\n })\n if (!parsed.success) {\n return NextResponse.json(\n { error: 'Invalid query parameters', details: parsed.error.flatten() },\n { status: 400 },\n )\n }\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n\n const { id, page, pageSize, search, sortField, sortDir, isActive } = parsed.data\n const where: FilterQuery<Tenant> = { deletedAt: null }\n if (id) where.id = id\n if (search) {\n Object.assign(where, { name: { $ilike: `%${escapeLikePattern(search)}%` } })\n }\n const active = parseBooleanToken(isActive)\n if (active !== null) where.isActive = active\n\n const fieldMap: Record<string, string> = { name: 'name', createdAt: 'createdAt', updatedAt: 'updatedAt' }\n const orderBy: Record<string, 'ASC' | 'DESC'> = {}\n if (sortField) {\n const mapped = fieldMap[sortField] || 'name'\n orderBy[mapped] = sortDir === 'desc' ? 'DESC' : 'ASC'\n } else {\n orderBy.name = 'ASC'\n }\n\n const rawQuery = Array.from(url.searchParams.keys()).reduce<Record<string, unknown>>((acc, key) => {\n const values = url.searchParams.getAll(key)\n if (!values.length) return acc\n acc[key] = values.length === 1 ? values[0] : values\n return acc\n }, {})\n\n const cfFilters = await buildCustomFieldFiltersFromQuery({\n entityId: E.directory.tenant,\n query: rawQuery,\n em,\n tenantId: auth.tenantId ?? null,\n })\n const cfFilterEntries = Object.entries(cfFilters).map(([rawKey, condition]) => {\n const normalizedKey = rawKey.startsWith('cf:') ? rawKey.slice(3) : rawKey.replace(/^cf_/, '')\n return [normalizedKey, condition] as const\n })\n\n const loadCfValues = (tenants: Tenant[]): Promise<Record<string, Record<string, unknown>>> => {\n const recordIds = tenants.map((tenant) => String(tenant.id))\n if (!recordIds.length) return Promise.resolve({})\n const tenantIdByRecord: Record<string, string | null> = {}\n const organizationIdByRecord: Record<string, string | null> = {}\n for (const rid of recordIds) {\n tenantIdByRecord[rid] = null\n organizationIdByRecord[rid] = null\n }\n return loadCustomFieldValues({\n em,\n entityId: E.directory.tenant,\n recordIds,\n tenantIdByRecord,\n organizationIdByRecord,\n tenantFallbacks: auth.tenantId ? [auth.tenantId] : [],\n })\n }\n\n const start = (page - 1) * pageSize\n\n let pageTenants: Tenant[]\n let total: number\n let cfValues: Record<string, Record<string, unknown>>\n\n if (cfFilterEntries.length) {\n // Custom-field values live in a separate store, so first resolve the bounded\n // set of matching tenant ids from that store, then push pagination to the\n // database via findAndCount instead of loading the whole tenant table.\n const matchedIds = await resolveRecordIdsForCustomFieldFilters({\n em,\n entityId: E.directory.tenant,\n tenantId: auth.tenantId ?? null,\n filters: cfFilterEntries,\n })\n const existingId = where.id\n const idFilter = typeof existingId === 'string'\n ? (matchedIds.has(existingId) ? [existingId] : [])\n : Array.from(matchedIds)\n\n if (!idFilter.length) {\n total = 0\n pageTenants = []\n cfValues = {}\n } else {\n where.id = { $in: idFilter }\n const [rows, count] = await em.findAndCount(Tenant, where, { orderBy, limit: pageSize, offset: start })\n total = count\n pageTenants = rows\n cfValues = await loadCfValues(rows)\n }\n } else {\n // No JS-side filtering applies, so pagination is pushed to the database\n // instead of fetching the whole table and slicing in memory.\n const [rows, count] = await em.findAndCount(Tenant, where, { orderBy, limit: pageSize, offset: start })\n total = count\n pageTenants = rows\n cfValues = await loadCfValues(rows)\n }\n\n const items = pageTenants.map((tenant) => {\n const rid = String(tenant.id)\n const cf = cfValues[rid] ?? {}\n return toRow(tenant, cf)\n })\n const totalPages = Math.max(1, Math.ceil(total / pageSize))\n\n await logCrudAccess({\n container,\n auth,\n request: req,\n items,\n idField: 'id',\n resourceKind: 'directory.tenant',\n organizationId: null,\n tenantId: auth.tenantId ?? null,\n query: rawQuery,\n accessType: id ? 'read:item' : undefined,\n })\n\n return NextResponse.json({ items, total, page, pageSize, totalPages })\n}\n\nexport const POST = crud.POST\nexport const PUT = crud.PUT\nexport const DELETE = crud.DELETE\n\nconst tenantCreateResponseSchema = z.object({\n id: z.string().uuid(),\n})\n\nconst tenantDeleteRequestSchema = z.object({\n id: z.string().uuid(),\n})\n\nconst tenantGetDoc: OpenApiMethodDoc = {\n summary: 'List tenants',\n description: 'Returns tenants visible to the current user with optional search and pagination.',\n tags: [directoryTag],\n query: listQuerySchema,\n responses: [\n { status: 200, description: 'Paged list of tenants.', schema: tenantListResponseSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid query parameters', schema: directoryErrorSchema },\n { status: 401, description: 'Authentication required', schema: directoryErrorSchema },\n ],\n}\n\nconst tenantPostDoc: OpenApiMethodDoc = {\n summary: 'Create tenant',\n description: 'Creates a new tenant and returns its identifier.',\n tags: [directoryTag],\n requestBody: {\n contentType: 'application/json',\n schema: tenantCreateSchema,\n description: 'Tenant name and optional activation flag.',\n },\n responses: [\n { status: 201, description: 'Tenant created.', schema: tenantCreateResponseSchema },\n ],\n errors: [\n { status: 400, description: 'Validation failed', schema: directoryErrorSchema },\n { status: 401, description: 'Authentication required', schema: directoryErrorSchema },\n { status: 403, description: 'Missing directory.tenants.manage feature', schema: directoryErrorSchema },\n ],\n}\n\nconst tenantPutDoc: OpenApiMethodDoc = {\n summary: 'Update tenant',\n description: 'Updates tenant properties such as name or activation state.',\n tags: [directoryTag],\n requestBody: {\n contentType: 'application/json',\n schema: tenantUpdateSchema,\n description: 'Tenant identifier with fields to update.',\n },\n responses: [\n { status: 200, description: 'Tenant updated.', schema: directoryOkSchema },\n ],\n errors: [\n { status: 400, description: 'Validation failed', schema: directoryErrorSchema },\n { status: 401, description: 'Authentication required', schema: directoryErrorSchema },\n { status: 403, description: 'Missing directory.tenants.manage feature', schema: directoryErrorSchema },\n ],\n}\n\nconst tenantDeleteDoc: OpenApiMethodDoc = {\n summary: 'Delete tenant',\n description: 'Soft deletes the tenant identified by id.',\n tags: [directoryTag],\n requestBody: {\n contentType: 'application/json',\n schema: tenantDeleteRequestSchema,\n description: 'Identifier of the tenant to remove.',\n },\n responses: [\n { status: 200, description: 'Tenant removed.', schema: directoryOkSchema },\n ],\n errors: [\n { status: 400, description: 'Validation failed', schema: directoryErrorSchema },\n { status: 401, description: 'Authentication required', schema: directoryErrorSchema },\n { status: 403, description: 'Missing directory.tenants.manage feature', schema: directoryErrorSchema },\n ],\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: directoryTag,\n summary: 'Manage tenants',\n methods: {\n GET: tenantGetDoc,\n POST: tenantPostDoc,\n PUT: tenantPutDoc,\n DELETE: tenantDeleteDoc,\n },\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAClB,SAAS,eAAe,qBAAqB;AAC7C,SAAS,0BAA0B;AACnC,SAAS,8BAA8B;
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { logCrudAccess, makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { resolveIsSuperAdmin } from '@open-mercato/core/modules/auth/lib/tenantAccess'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\n\nimport { Tenant } from '@open-mercato/core/modules/directory/data/entities'\nimport { tenantCreateSchema, tenantUpdateSchema } from '@open-mercato/core/modules/directory/data/validators'\nimport { loadCustomFieldValues, buildCustomFieldFiltersFromQuery } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { resolveRecordIdsForCustomFieldFilters } from './tenant-cf-filter'\nimport { E } from '#generated/entities.ids.generated'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { FilterQuery } from '@mikro-orm/core'\nimport { tenantCrudEvents, tenantCrudIndexer } from '@open-mercato/core/modules/directory/commands/tenants'\nimport type { OpenApiMethodDoc, OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { directoryTag, directoryErrorSchema, directoryOkSchema, tenantListResponseSchema } from '../openapi'\nimport { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'\nimport { parseBooleanToken } from '@open-mercato/shared/lib/boolean'\n\nconst listQuerySchema = z.object({\n id: z.string().uuid().optional(),\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(50),\n search: z.string().optional(),\n sortField: z.enum(['name', 'createdAt', 'updatedAt']).optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n isActive: z.enum(['true', 'false']).optional(),\n}).passthrough()\n\ntype TenantRow = {\n id: string\n name: string\n isActive: boolean\n createdAt: string | null\n updatedAt: string | null\n} & Record<string, unknown>\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['directory.tenants.view'] },\n POST: { requireAuth: true, requireFeatures: ['directory.tenants.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['directory.tenants.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['directory.tenants.manage'] },\n}\n\nexport const metadata = routeMetadata\n\nconst rawBodySchema = z.object({}).passthrough()\ntype CrudInput = Record<string, unknown>\n\nconst crud = makeCrudRoute<CrudInput, CrudInput, Record<string, unknown>>({\n metadata: routeMetadata,\n orm: {\n entity: Tenant,\n idField: 'id',\n orgField: null,\n tenantField: null,\n softDeleteField: 'deletedAt',\n },\n events: tenantCrudEvents,\n indexer: tenantCrudIndexer,\n actions: {\n create: {\n commandId: 'directory.tenants.create',\n schema: rawBodySchema,\n mapInput: ({ parsed }) => parsed,\n response: ({ result }) => ({ id: String(result.id) }),\n status: 201,\n },\n update: {\n commandId: 'directory.tenants.update',\n schema: rawBodySchema,\n mapInput: ({ parsed }) => parsed,\n response: () => ({ ok: true }),\n },\n delete: {\n commandId: 'directory.tenants.delete',\n response: () => ({ ok: true }),\n },\n },\n})\n\nconst toRow = (tenant: Tenant, cf: Record<string, unknown>): TenantRow => ({\n id: String(tenant.id),\n name: String(tenant.name),\n isActive: !!tenant.isActive,\n createdAt: tenant.createdAt ? tenant.createdAt.toISOString() : null,\n updatedAt: tenant.updatedAt ? tenant.updatedAt.toISOString() : null,\n ...cf,\n})\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ items: [], total: 0, page: 1, pageSize: 50, totalPages: 1 }, { status: 401 })\n }\n\n const container = await createRequestContainer()\n const isSuperAdmin = await resolveIsSuperAdmin({ auth, container })\n if (!isSuperAdmin) {\n return NextResponse.json({ error: 'Forbidden' }, { status: 403 })\n }\n\n const url = new URL(req.url)\n const parsed = listQuerySchema.safeParse({\n id: url.searchParams.get('id') ?? undefined,\n page: url.searchParams.get('page') ?? undefined,\n pageSize: url.searchParams.get('pageSize') ?? undefined,\n search: url.searchParams.get('search') ?? undefined,\n sortField: url.searchParams.get('sortField') ?? undefined,\n sortDir: url.searchParams.get('sortDir') ?? undefined,\n isActive: url.searchParams.get('isActive') ?? undefined,\n })\n if (!parsed.success) {\n return NextResponse.json(\n { error: 'Invalid query parameters', details: parsed.error.flatten() },\n { status: 400 },\n )\n }\n\n const em = container.resolve('em') as EntityManager\n\n const { id, page, pageSize, search, sortField, sortDir, isActive } = parsed.data\n const where: FilterQuery<Tenant> = { deletedAt: null }\n if (id) where.id = id\n if (search) {\n Object.assign(where, { name: { $ilike: `%${escapeLikePattern(search)}%` } })\n }\n const active = parseBooleanToken(isActive)\n if (active !== null) where.isActive = active\n\n const fieldMap: Record<string, string> = { name: 'name', createdAt: 'createdAt', updatedAt: 'updatedAt' }\n const orderBy: Record<string, 'ASC' | 'DESC'> = {}\n if (sortField) {\n const mapped = fieldMap[sortField] || 'name'\n orderBy[mapped] = sortDir === 'desc' ? 'DESC' : 'ASC'\n } else {\n orderBy.name = 'ASC'\n }\n\n const rawQuery = Array.from(url.searchParams.keys()).reduce<Record<string, unknown>>((acc, key) => {\n const values = url.searchParams.getAll(key)\n if (!values.length) return acc\n acc[key] = values.length === 1 ? values[0] : values\n return acc\n }, {})\n\n const cfFilters = await buildCustomFieldFiltersFromQuery({\n entityId: E.directory.tenant,\n query: rawQuery,\n em,\n tenantId: auth.tenantId ?? null,\n })\n const cfFilterEntries = Object.entries(cfFilters).map(([rawKey, condition]) => {\n const normalizedKey = rawKey.startsWith('cf:') ? rawKey.slice(3) : rawKey.replace(/^cf_/, '')\n return [normalizedKey, condition] as const\n })\n\n const loadCfValues = (tenants: Tenant[]): Promise<Record<string, Record<string, unknown>>> => {\n const recordIds = tenants.map((tenant) => String(tenant.id))\n if (!recordIds.length) return Promise.resolve({})\n const tenantIdByRecord: Record<string, string | null> = {}\n const organizationIdByRecord: Record<string, string | null> = {}\n for (const rid of recordIds) {\n tenantIdByRecord[rid] = null\n organizationIdByRecord[rid] = null\n }\n return loadCustomFieldValues({\n em,\n entityId: E.directory.tenant,\n recordIds,\n tenantIdByRecord,\n organizationIdByRecord,\n tenantFallbacks: auth.tenantId ? [auth.tenantId] : [],\n })\n }\n\n const start = (page - 1) * pageSize\n\n let pageTenants: Tenant[]\n let total: number\n let cfValues: Record<string, Record<string, unknown>>\n\n if (cfFilterEntries.length) {\n // Custom-field values live in a separate store, so first resolve the bounded\n // set of matching tenant ids from that store, then push pagination to the\n // database via findAndCount instead of loading the whole tenant table.\n const matchedIds = await resolveRecordIdsForCustomFieldFilters({\n em,\n entityId: E.directory.tenant,\n tenantId: auth.tenantId ?? null,\n filters: cfFilterEntries,\n })\n const existingId = where.id\n const idFilter = typeof existingId === 'string'\n ? (matchedIds.has(existingId) ? [existingId] : [])\n : Array.from(matchedIds)\n\n if (!idFilter.length) {\n total = 0\n pageTenants = []\n cfValues = {}\n } else {\n where.id = { $in: idFilter }\n const [rows, count] = await em.findAndCount(Tenant, where, { orderBy, limit: pageSize, offset: start })\n total = count\n pageTenants = rows\n cfValues = await loadCfValues(rows)\n }\n } else {\n // No JS-side filtering applies, so pagination is pushed to the database\n // instead of fetching the whole table and slicing in memory.\n const [rows, count] = await em.findAndCount(Tenant, where, { orderBy, limit: pageSize, offset: start })\n total = count\n pageTenants = rows\n cfValues = await loadCfValues(rows)\n }\n\n const items = pageTenants.map((tenant) => {\n const rid = String(tenant.id)\n const cf = cfValues[rid] ?? {}\n return toRow(tenant, cf)\n })\n const totalPages = Math.max(1, Math.ceil(total / pageSize))\n\n await logCrudAccess({\n container,\n auth,\n request: req,\n items,\n idField: 'id',\n resourceKind: 'directory.tenant',\n organizationId: null,\n tenantId: auth.tenantId ?? null,\n query: rawQuery,\n accessType: id ? 'read:item' : undefined,\n })\n\n return NextResponse.json({ items, total, page, pageSize, totalPages })\n}\n\nexport const POST = crud.POST\nexport const PUT = crud.PUT\nexport const DELETE = crud.DELETE\n\nconst tenantCreateResponseSchema = z.object({\n id: z.string().uuid(),\n})\n\nconst tenantDeleteRequestSchema = z.object({\n id: z.string().uuid(),\n})\n\nconst tenantGetDoc: OpenApiMethodDoc = {\n summary: 'List tenants',\n description: 'Returns tenants visible to the current user with optional search and pagination.',\n tags: [directoryTag],\n query: listQuerySchema,\n responses: [\n { status: 200, description: 'Paged list of tenants.', schema: tenantListResponseSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid query parameters', schema: directoryErrorSchema },\n { status: 401, description: 'Authentication required', schema: directoryErrorSchema },\n { status: 403, description: 'Requires super-admin', schema: directoryErrorSchema },\n ],\n}\n\nconst tenantPostDoc: OpenApiMethodDoc = {\n summary: 'Create tenant',\n description: 'Creates a new tenant and returns its identifier.',\n tags: [directoryTag],\n requestBody: {\n contentType: 'application/json',\n schema: tenantCreateSchema,\n description: 'Tenant name and optional activation flag.',\n },\n responses: [\n { status: 201, description: 'Tenant created.', schema: tenantCreateResponseSchema },\n ],\n errors: [\n { status: 400, description: 'Validation failed', schema: directoryErrorSchema },\n { status: 401, description: 'Authentication required', schema: directoryErrorSchema },\n { status: 403, description: 'Missing directory.tenants.manage feature', schema: directoryErrorSchema },\n ],\n}\n\nconst tenantPutDoc: OpenApiMethodDoc = {\n summary: 'Update tenant',\n description: 'Updates tenant properties such as name or activation state.',\n tags: [directoryTag],\n requestBody: {\n contentType: 'application/json',\n schema: tenantUpdateSchema,\n description: 'Tenant identifier with fields to update.',\n },\n responses: [\n { status: 200, description: 'Tenant updated.', schema: directoryOkSchema },\n ],\n errors: [\n { status: 400, description: 'Validation failed', schema: directoryErrorSchema },\n { status: 401, description: 'Authentication required', schema: directoryErrorSchema },\n { status: 403, description: 'Missing directory.tenants.manage feature', schema: directoryErrorSchema },\n ],\n}\n\nconst tenantDeleteDoc: OpenApiMethodDoc = {\n summary: 'Delete tenant',\n description: 'Soft deletes the tenant identified by id.',\n tags: [directoryTag],\n requestBody: {\n contentType: 'application/json',\n schema: tenantDeleteRequestSchema,\n description: 'Identifier of the tenant to remove.',\n },\n responses: [\n { status: 200, description: 'Tenant removed.', schema: directoryOkSchema },\n ],\n errors: [\n { status: 400, description: 'Validation failed', schema: directoryErrorSchema },\n { status: 401, description: 'Authentication required', schema: directoryErrorSchema },\n { status: 403, description: 'Missing directory.tenants.manage feature', schema: directoryErrorSchema },\n ],\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: directoryTag,\n summary: 'Manage tenants',\n methods: {\n GET: tenantGetDoc,\n POST: tenantPostDoc,\n PUT: tenantPutDoc,\n DELETE: tenantDeleteDoc,\n },\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -12,6 +12,7 @@ import { buildOptimisticLockHeader } from "@open-mercato/ui/backend/utils/optimi
|
|
|
12
12
|
import { surfaceRecordConflict } from "@open-mercato/ui/backend/conflicts";
|
|
13
13
|
import { Button } from "@open-mercato/ui/primitives/button";
|
|
14
14
|
import { Input } from "@open-mercato/ui/primitives/input";
|
|
15
|
+
import { SwitchField } from "@open-mercato/ui/primitives/switch-field";
|
|
15
16
|
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
16
17
|
const BRANDING_API = "/api/directory/organization-branding";
|
|
17
18
|
const BRANDING_ENTITY_ID = "directory.organization";
|
|
@@ -19,6 +20,7 @@ function OrganizationBrandingPage() {
|
|
|
19
20
|
const t = useT();
|
|
20
21
|
const queryClient = useQueryClient();
|
|
21
22
|
const [logoUrl, setLogoUrl] = React.useState("");
|
|
23
|
+
const [logoPreserveAspectRatio, setLogoPreserveAspectRatio] = React.useState(false);
|
|
22
24
|
const [selectedFile, setSelectedFile] = React.useState(null);
|
|
23
25
|
const [filePreviewUrl, setFilePreviewUrl] = React.useState(null);
|
|
24
26
|
const [saving, setSaving] = React.useState(false);
|
|
@@ -37,8 +39,9 @@ function OrganizationBrandingPage() {
|
|
|
37
39
|
});
|
|
38
40
|
React.useEffect(() => {
|
|
39
41
|
setLogoUrl(data?.logoUrl ?? "");
|
|
42
|
+
setLogoPreserveAspectRatio(data?.logoPreserveAspectRatio ?? false);
|
|
40
43
|
setSelectedFile(null);
|
|
41
|
-
}, [data?.logoUrl]);
|
|
44
|
+
}, [data?.logoPreserveAspectRatio, data?.logoUrl]);
|
|
42
45
|
React.useEffect(() => {
|
|
43
46
|
if (!selectedFile || typeof URL === "undefined") {
|
|
44
47
|
setFilePreviewUrl(null);
|
|
@@ -64,11 +67,12 @@ function OrganizationBrandingPage() {
|
|
|
64
67
|
},
|
|
65
68
|
{ errorMessage: t("directory.branding.errors.upload", "Failed to upload logo") }
|
|
66
69
|
);
|
|
67
|
-
return upload?.item.
|
|
70
|
+
return upload?.item.url ?? upload?.item.thumbnailUrl ?? null;
|
|
68
71
|
}, [selectedFile, t]);
|
|
69
72
|
const saveBranding = React.useCallback(async (nextLogoUrl, options) => {
|
|
70
73
|
if (!data) return;
|
|
71
74
|
const shouldUpload = Boolean(selectedFile && !options?.skipUpload);
|
|
75
|
+
const resolvedLogoPreserveAspectRatio = options?.logoPreserveAspectRatio ?? logoPreserveAspectRatio;
|
|
72
76
|
setSaving(true);
|
|
73
77
|
try {
|
|
74
78
|
await runMutation({
|
|
@@ -82,7 +86,10 @@ function OrganizationBrandingPage() {
|
|
|
82
86
|
{
|
|
83
87
|
method: "PUT",
|
|
84
88
|
headers: { "content-type": "application/json" },
|
|
85
|
-
body: JSON.stringify({
|
|
89
|
+
body: JSON.stringify({
|
|
90
|
+
logoUrl: resolvedLogoUrl || null,
|
|
91
|
+
logoPreserveAspectRatio: resolvedLogoPreserveAspectRatio
|
|
92
|
+
})
|
|
86
93
|
},
|
|
87
94
|
{ errorMessage: t("directory.branding.errors.save", "Failed to update organization branding") }
|
|
88
95
|
)
|
|
@@ -97,6 +104,7 @@ function OrganizationBrandingPage() {
|
|
|
97
104
|
mutationPayload: {
|
|
98
105
|
organizationId: data.organizationId,
|
|
99
106
|
logoUrl: (nextLogoUrl ?? logoUrl.trim()) || null,
|
|
107
|
+
logoPreserveAspectRatio: resolvedLogoPreserveAspectRatio,
|
|
100
108
|
hasUpload: shouldUpload
|
|
101
109
|
}
|
|
102
110
|
});
|
|
@@ -113,7 +121,7 @@ function OrganizationBrandingPage() {
|
|
|
113
121
|
} finally {
|
|
114
122
|
setSaving(false);
|
|
115
123
|
}
|
|
116
|
-
}, [data, logoUrl, queryClient, runMutation, selectedFile, t, uploadLogo]);
|
|
124
|
+
}, [data, logoPreserveAspectRatio, logoUrl, queryClient, runMutation, selectedFile, t, uploadLogo]);
|
|
117
125
|
const handleSubmit = React.useCallback((event) => {
|
|
118
126
|
event.preventDefault();
|
|
119
127
|
void saveBranding();
|
|
@@ -148,7 +156,7 @@ function OrganizationBrandingPage() {
|
|
|
148
156
|
{
|
|
149
157
|
src: currentPreviewUrl,
|
|
150
158
|
alt: t("directory.branding.previewAlt", "{{name}} logo preview", { name: data.organizationName }),
|
|
151
|
-
className:
|
|
159
|
+
className: `h-full w-full ${logoPreserveAspectRatio ? "object-contain" : "rounded-full object-cover"}`
|
|
152
160
|
}
|
|
153
161
|
) : /* @__PURE__ */ jsx(ImagePlus, { className: "size-10 text-muted-foreground", "aria-hidden": true }) }),
|
|
154
162
|
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: data.organizationName }),
|
|
@@ -163,7 +171,7 @@ function OrganizationBrandingPage() {
|
|
|
163
171
|
ref: fileInputRef,
|
|
164
172
|
id: "organization-logo-file",
|
|
165
173
|
type: "file",
|
|
166
|
-
accept: "image/png,image/jpeg,image/webp
|
|
174
|
+
accept: "image/png,image/jpeg,image/webp",
|
|
167
175
|
onChange: (event) => {
|
|
168
176
|
const file = event.currentTarget.files?.[0];
|
|
169
177
|
if (!file) return;
|
|
@@ -171,7 +179,7 @@ function OrganizationBrandingPage() {
|
|
|
171
179
|
}
|
|
172
180
|
}
|
|
173
181
|
),
|
|
174
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("directory.branding.file.hint", "PNG, JPG,
|
|
182
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("directory.branding.file.hint", "PNG, JPG, or WebP works best. Uploaded files are stored as organization attachments.") })
|
|
175
183
|
] }),
|
|
176
184
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
177
185
|
/* @__PURE__ */ jsx("label", { htmlFor: "organization-logo-url", className: "text-sm font-medium", children: t("directory.branding.url.label", "Logo URL") }),
|
|
@@ -186,6 +194,20 @@ function OrganizationBrandingPage() {
|
|
|
186
194
|
),
|
|
187
195
|
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("directory.branding.url.hint", "Use an external image URL or leave empty to fall back to the default Open Mercato logo.") })
|
|
188
196
|
] }),
|
|
197
|
+
/* @__PURE__ */ jsx(
|
|
198
|
+
SwitchField,
|
|
199
|
+
{
|
|
200
|
+
id: "organization-logo-preserve-aspect-ratio",
|
|
201
|
+
label: t("directory.branding.aspectRatio.label", "Keep the aspect ratio"),
|
|
202
|
+
description: t(
|
|
203
|
+
"directory.branding.aspectRatio.description",
|
|
204
|
+
"When disabled, the sidebar crops the logo into the standard icon shape."
|
|
205
|
+
),
|
|
206
|
+
checked: logoPreserveAspectRatio,
|
|
207
|
+
disabled: saving,
|
|
208
|
+
onCheckedChange: setLogoPreserveAspectRatio
|
|
209
|
+
}
|
|
210
|
+
),
|
|
189
211
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
190
212
|
/* @__PURE__ */ jsxs(Button, { type: "submit", disabled: saving, children: [
|
|
191
213
|
saving ? /* @__PURE__ */ jsx(Loader2, { className: "mr-2 size-4 animate-spin", "aria-hidden": true }) : /* @__PURE__ */ jsx(Save, { className: "mr-2 size-4", "aria-hidden": true }),
|
|
@@ -201,7 +223,8 @@ function OrganizationBrandingPage() {
|
|
|
201
223
|
setSelectedFile(null);
|
|
202
224
|
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
203
225
|
setLogoUrl("");
|
|
204
|
-
|
|
226
|
+
setLogoPreserveAspectRatio(false);
|
|
227
|
+
void saveBranding("", { skipUpload: true, logoPreserveAspectRatio: false });
|
|
205
228
|
},
|
|
206
229
|
children: [
|
|
207
230
|
/* @__PURE__ */ jsx(RotateCcw, { className: "mr-2 size-4", "aria-hidden": true }),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/directory/backend/directory/branding/page.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { ImagePlus, Loader2, RotateCcw, Save } from 'lucide-react'\nimport { Page, PageBody, PageHeader } from '@open-mercato/ui/backend/Page'\nimport { LoadingMessage, ErrorMessage } from '@open-mercato/ui/backend/detail'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { apiCallOrThrow, readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\ntype BrandingPayload = {\n organizationId: string\n organizationName: string\n tenantId: string\n logoUrl: string | null\n updatedAt: string | null\n}\n\ntype UploadPayload = {\n ok: true\n item: {\n id: string\n url: string\n thumbnailUrl?: string\n }\n}\n\nconst BRANDING_API = '/api/directory/organization-branding'\nconst BRANDING_ENTITY_ID = 'directory.organization'\n\nexport default function OrganizationBrandingPage() {\n const t = useT()\n const queryClient = useQueryClient()\n const [logoUrl, setLogoUrl] = React.useState('')\n const [selectedFile, setSelectedFile] = React.useState<File | null>(null)\n const [filePreviewUrl, setFilePreviewUrl] = React.useState<string | null>(null)\n const [saving, setSaving] = React.useState(false)\n const fileInputRef = React.useRef<HTMLInputElement | null>(null)\n const { runMutation } = useGuardedMutation({\n contextId: 'directory.organization-branding',\n blockedMessage: t('directory.branding.errors.blocked', 'Branding save was blocked.'),\n })\n\n const { data, isLoading, error } = useQuery<BrandingPayload>({\n queryKey: ['directory-organization-branding'],\n queryFn: () => readApiResultOrThrow<BrandingPayload>(\n BRANDING_API,\n undefined,\n { errorMessage: t('directory.branding.errors.load', 'Failed to load organization branding') },\n ),\n })\n\n React.useEffect(() => {\n setLogoUrl(data?.logoUrl ?? '')\n setSelectedFile(null)\n }, [data?.logoUrl])\n\n React.useEffect(() => {\n if (!selectedFile || typeof URL === 'undefined') {\n setFilePreviewUrl(null)\n return\n }\n const nextPreviewUrl = URL.createObjectURL(selectedFile)\n setFilePreviewUrl(nextPreviewUrl)\n return () => URL.revokeObjectURL(nextPreviewUrl)\n }, [selectedFile])\n\n const currentPreviewUrl = filePreviewUrl ?? logoUrl\n\n const uploadLogo = React.useCallback(async (organizationId: string): Promise<string | null> => {\n if (!selectedFile) return null\n const form = new FormData()\n form.set('entityId', BRANDING_ENTITY_ID)\n form.set('recordId', organizationId)\n form.set('file', selectedFile)\n form.set('tags', JSON.stringify(['organization-logo']))\n\n const upload = await readApiResultOrThrow<UploadPayload>(\n '/api/attachments',\n {\n method: 'POST',\n body: form,\n },\n { errorMessage: t('directory.branding.errors.upload', 'Failed to upload logo') },\n )\n return upload?.item.thumbnailUrl ?? upload?.item.url ?? null\n }, [selectedFile, t])\n\n const saveBranding = React.useCallback(async (nextLogoUrl?: string, options?: { skipUpload?: boolean }) => {\n if (!data) return\n const shouldUpload = Boolean(selectedFile && !options?.skipUpload)\n setSaving(true)\n try {\n await runMutation({\n operation: async () => {\n const uploadedLogoUrl = shouldUpload ? await uploadLogo(data.organizationId) : null\n const resolvedLogoUrl = uploadedLogoUrl ?? nextLogoUrl ?? logoUrl.trim()\n const response = await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(data.updatedAt),\n () => apiCallOrThrow<BrandingPayload>(\n BRANDING_API,\n {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ logoUrl: resolvedLogoUrl || null }),\n },\n { errorMessage: t('directory.branding.errors.save', 'Failed to update organization branding') },\n ),\n )\n return response.result\n },\n context: {\n entityId: BRANDING_ENTITY_ID,\n recordId: data.organizationId,\n operation: 'update-branding',\n },\n mutationPayload: {\n organizationId: data.organizationId,\n logoUrl: (nextLogoUrl ?? logoUrl.trim()) || null,\n hasUpload: shouldUpload,\n },\n })\n await queryClient.invalidateQueries({ queryKey: ['directory-organization-branding'] })\n window.dispatchEvent(new Event('om:refresh-sidebar'))\n setSelectedFile(null)\n if (fileInputRef.current) fileInputRef.current.value = ''\n flash(t('directory.branding.flash.saved', 'Organization branding updated'), 'success')\n } catch (err: unknown) {\n if (surfaceRecordConflict(err, t)) return\n const fallback = t('directory.branding.errors.save', 'Failed to update organization branding')\n const message = err instanceof Error ? err.message : fallback\n flash(message, 'error')\n } finally {\n setSaving(false)\n }\n }, [data, logoUrl, queryClient, runMutation, selectedFile, t, uploadLogo])\n\n const handleSubmit = React.useCallback((event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault()\n void saveBranding()\n }, [saveBranding])\n\n if (isLoading) {\n return <LoadingMessage label={t('directory.branding.loading', 'Loading organization branding...')} />\n }\n\n if (error || !data) {\n return (\n <ErrorMessage\n label={t('directory.branding.errors.load', 'Failed to load organization branding')}\n description={error instanceof Error ? error.message : undefined}\n />\n )\n }\n\n return (\n <Page>\n <PageHeader\n title={t('directory.branding.title', 'Organization branding')}\n description={t(\n 'directory.branding.description',\n 'Set the logo used in the backend sidebar for the currently selected organization.',\n )}\n />\n <PageBody>\n <form className=\"space-y-5\" onSubmit={handleSubmit}>\n <div className=\"grid gap-5 lg:grid-cols-[260px_1fr]\">\n <div className=\"space-y-3\">\n <div className=\"flex aspect-square w-full max-w-[220px] items-center justify-center overflow-hidden rounded-lg border bg-muted/30\">\n {currentPreviewUrl ? (\n <img\n src={currentPreviewUrl}\n alt={t('directory.branding.previewAlt', '{{name}} logo preview', { name: data.organizationName })}\n className=\"h-full w-full object-contain\"\n />\n ) : (\n <ImagePlus className=\"size-10 text-muted-foreground\" aria-hidden />\n )}\n </div>\n <p className=\"text-sm font-medium text-foreground\">{data.organizationName}</p>\n <p className=\"text-xs text-muted-foreground\">\n {t('directory.branding.currentScope', 'Current organization')}\n </p>\n </div>\n\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <label htmlFor=\"organization-logo-file\" className=\"text-sm font-medium\">\n {t('directory.branding.file.label', 'Upload logo')}\n </label>\n <Input\n ref={fileInputRef}\n id=\"organization-logo-file\"\n type=\"file\"\n accept=\"image/png,image/jpeg,image/webp,image/svg+xml\"\n onChange={(event) => {\n const file = event.currentTarget.files?.[0]\n if (!file) return\n setSelectedFile(file)\n }}\n />\n <p className=\"text-xs text-muted-foreground\">\n {t('directory.branding.file.hint', 'PNG, JPG, WebP, or SVG works best. Uploaded files are stored as organization attachments.')}\n </p>\n </div>\n\n <div className=\"space-y-2\">\n <label htmlFor=\"organization-logo-url\" className=\"text-sm font-medium\">\n {t('directory.branding.url.label', 'Logo URL')}\n </label>\n <Input\n id=\"organization-logo-url\"\n value={logoUrl}\n onChange={(event) => setLogoUrl(event.currentTarget.value)}\n placeholder={t('directory.branding.url.placeholder', 'https://example.com/logo.svg')}\n />\n <p className=\"text-xs text-muted-foreground\">\n {t('directory.branding.url.hint', 'Use an external image URL or leave empty to fall back to the default Open Mercato logo.')}\n </p>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button type=\"submit\" disabled={saving}>\n {saving ? <Loader2 className=\"mr-2 size-4 animate-spin\" aria-hidden /> : <Save className=\"mr-2 size-4\" aria-hidden />}\n {t('directory.branding.actions.save', 'Save branding')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled={saving}\n onClick={() => {\n setSelectedFile(null)\n if (fileInputRef.current) fileInputRef.current.value = ''\n setLogoUrl('')\n void saveBranding('', { skipUpload: true })\n }}\n >\n <RotateCcw className=\"mr-2 size-4\" aria-hidden />\n {t('directory.branding.actions.reset', 'Use default logo')}\n </Button>\n </div>\n </div>\n </div>\n </form>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { ImagePlus, Loader2, RotateCcw, Save } from 'lucide-react'\nimport { Page, PageBody, PageHeader } from '@open-mercato/ui/backend/Page'\nimport { LoadingMessage, ErrorMessage } from '@open-mercato/ui/backend/detail'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { apiCallOrThrow, readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { SwitchField } from '@open-mercato/ui/primitives/switch-field'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\ntype BrandingPayload = {\n organizationId: string\n organizationName: string\n tenantId: string\n logoUrl: string | null\n logoPreserveAspectRatio: boolean\n updatedAt: string | null\n}\n\ntype UploadPayload = {\n ok: true\n item: {\n id: string\n url: string\n thumbnailUrl?: string\n }\n}\n\nconst BRANDING_API = '/api/directory/organization-branding'\nconst BRANDING_ENTITY_ID = 'directory.organization'\n\nexport default function OrganizationBrandingPage() {\n const t = useT()\n const queryClient = useQueryClient()\n const [logoUrl, setLogoUrl] = React.useState('')\n const [logoPreserveAspectRatio, setLogoPreserveAspectRatio] = React.useState(false)\n const [selectedFile, setSelectedFile] = React.useState<File | null>(null)\n const [filePreviewUrl, setFilePreviewUrl] = React.useState<string | null>(null)\n const [saving, setSaving] = React.useState(false)\n const fileInputRef = React.useRef<HTMLInputElement | null>(null)\n const { runMutation } = useGuardedMutation({\n contextId: 'directory.organization-branding',\n blockedMessage: t('directory.branding.errors.blocked', 'Branding save was blocked.'),\n })\n\n const { data, isLoading, error } = useQuery<BrandingPayload>({\n queryKey: ['directory-organization-branding'],\n queryFn: () => readApiResultOrThrow<BrandingPayload>(\n BRANDING_API,\n undefined,\n { errorMessage: t('directory.branding.errors.load', 'Failed to load organization branding') },\n ),\n })\n\n React.useEffect(() => {\n setLogoUrl(data?.logoUrl ?? '')\n setLogoPreserveAspectRatio(data?.logoPreserveAspectRatio ?? false)\n setSelectedFile(null)\n }, [data?.logoPreserveAspectRatio, data?.logoUrl])\n\n React.useEffect(() => {\n if (!selectedFile || typeof URL === 'undefined') {\n setFilePreviewUrl(null)\n return\n }\n const nextPreviewUrl = URL.createObjectURL(selectedFile)\n setFilePreviewUrl(nextPreviewUrl)\n return () => URL.revokeObjectURL(nextPreviewUrl)\n }, [selectedFile])\n\n const currentPreviewUrl = filePreviewUrl ?? logoUrl\n\n const uploadLogo = React.useCallback(async (organizationId: string): Promise<string | null> => {\n if (!selectedFile) return null\n const form = new FormData()\n form.set('entityId', BRANDING_ENTITY_ID)\n form.set('recordId', organizationId)\n form.set('file', selectedFile)\n form.set('tags', JSON.stringify(['organization-logo']))\n\n const upload = await readApiResultOrThrow<UploadPayload>(\n '/api/attachments',\n {\n method: 'POST',\n body: form,\n },\n { errorMessage: t('directory.branding.errors.upload', 'Failed to upload logo') },\n )\n return upload?.item.url ?? upload?.item.thumbnailUrl ?? null\n }, [selectedFile, t])\n\n const saveBranding = React.useCallback(async (\n nextLogoUrl?: string,\n options?: { skipUpload?: boolean; logoPreserveAspectRatio?: boolean },\n ) => {\n if (!data) return\n const shouldUpload = Boolean(selectedFile && !options?.skipUpload)\n const resolvedLogoPreserveAspectRatio = options?.logoPreserveAspectRatio ?? logoPreserveAspectRatio\n setSaving(true)\n try {\n await runMutation({\n operation: async () => {\n const uploadedLogoUrl = shouldUpload ? await uploadLogo(data.organizationId) : null\n const resolvedLogoUrl = uploadedLogoUrl ?? nextLogoUrl ?? logoUrl.trim()\n const response = await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(data.updatedAt),\n () => apiCallOrThrow<BrandingPayload>(\n BRANDING_API,\n {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n logoUrl: resolvedLogoUrl || null,\n logoPreserveAspectRatio: resolvedLogoPreserveAspectRatio,\n }),\n },\n { errorMessage: t('directory.branding.errors.save', 'Failed to update organization branding') },\n ),\n )\n return response.result\n },\n context: {\n entityId: BRANDING_ENTITY_ID,\n recordId: data.organizationId,\n operation: 'update-branding',\n },\n mutationPayload: {\n organizationId: data.organizationId,\n logoUrl: (nextLogoUrl ?? logoUrl.trim()) || null,\n logoPreserveAspectRatio: resolvedLogoPreserveAspectRatio,\n hasUpload: shouldUpload,\n },\n })\n await queryClient.invalidateQueries({ queryKey: ['directory-organization-branding'] })\n window.dispatchEvent(new Event('om:refresh-sidebar'))\n setSelectedFile(null)\n if (fileInputRef.current) fileInputRef.current.value = ''\n flash(t('directory.branding.flash.saved', 'Organization branding updated'), 'success')\n } catch (err: unknown) {\n if (surfaceRecordConflict(err, t)) return\n const fallback = t('directory.branding.errors.save', 'Failed to update organization branding')\n const message = err instanceof Error ? err.message : fallback\n flash(message, 'error')\n } finally {\n setSaving(false)\n }\n }, [data, logoPreserveAspectRatio, logoUrl, queryClient, runMutation, selectedFile, t, uploadLogo])\n\n const handleSubmit = React.useCallback((event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault()\n void saveBranding()\n }, [saveBranding])\n\n if (isLoading) {\n return <LoadingMessage label={t('directory.branding.loading', 'Loading organization branding...')} />\n }\n\n if (error || !data) {\n return (\n <ErrorMessage\n label={t('directory.branding.errors.load', 'Failed to load organization branding')}\n description={error instanceof Error ? error.message : undefined}\n />\n )\n }\n\n return (\n <Page>\n <PageHeader\n title={t('directory.branding.title', 'Organization branding')}\n description={t(\n 'directory.branding.description',\n 'Set the logo used in the backend sidebar for the currently selected organization.',\n )}\n />\n <PageBody>\n <form className=\"space-y-5\" onSubmit={handleSubmit}>\n <div className=\"grid gap-5 lg:grid-cols-[260px_1fr]\">\n <div className=\"space-y-3\">\n <div className=\"flex aspect-square w-full max-w-[220px] items-center justify-center overflow-hidden rounded-lg border bg-muted/30\">\n {currentPreviewUrl ? (\n <img\n src={currentPreviewUrl}\n alt={t('directory.branding.previewAlt', '{{name}} logo preview', { name: data.organizationName })}\n className={`h-full w-full ${logoPreserveAspectRatio ? 'object-contain' : 'rounded-full object-cover'}`}\n />\n ) : (\n <ImagePlus className=\"size-10 text-muted-foreground\" aria-hidden />\n )}\n </div>\n <p className=\"text-sm font-medium text-foreground\">{data.organizationName}</p>\n <p className=\"text-xs text-muted-foreground\">\n {t('directory.branding.currentScope', 'Current organization')}\n </p>\n </div>\n\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <label htmlFor=\"organization-logo-file\" className=\"text-sm font-medium\">\n {t('directory.branding.file.label', 'Upload logo')}\n </label>\n <Input\n ref={fileInputRef}\n id=\"organization-logo-file\"\n type=\"file\"\n accept=\"image/png,image/jpeg,image/webp\"\n onChange={(event) => {\n const file = event.currentTarget.files?.[0]\n if (!file) return\n setSelectedFile(file)\n }}\n />\n <p className=\"text-xs text-muted-foreground\">\n {t('directory.branding.file.hint', 'PNG, JPG, or WebP works best. Uploaded files are stored as organization attachments.')}\n </p>\n </div>\n\n <div className=\"space-y-2\">\n <label htmlFor=\"organization-logo-url\" className=\"text-sm font-medium\">\n {t('directory.branding.url.label', 'Logo URL')}\n </label>\n <Input\n id=\"organization-logo-url\"\n value={logoUrl}\n onChange={(event) => setLogoUrl(event.currentTarget.value)}\n placeholder={t('directory.branding.url.placeholder', 'https://example.com/logo.svg')}\n />\n <p className=\"text-xs text-muted-foreground\">\n {t('directory.branding.url.hint', 'Use an external image URL or leave empty to fall back to the default Open Mercato logo.')}\n </p>\n </div>\n\n <SwitchField\n id=\"organization-logo-preserve-aspect-ratio\"\n label={t('directory.branding.aspectRatio.label', 'Keep the aspect ratio')}\n description={t(\n 'directory.branding.aspectRatio.description',\n 'When disabled, the sidebar crops the logo into the standard icon shape.',\n )}\n checked={logoPreserveAspectRatio}\n disabled={saving}\n onCheckedChange={setLogoPreserveAspectRatio}\n />\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button type=\"submit\" disabled={saving}>\n {saving ? <Loader2 className=\"mr-2 size-4 animate-spin\" aria-hidden /> : <Save className=\"mr-2 size-4\" aria-hidden />}\n {t('directory.branding.actions.save', 'Save branding')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled={saving}\n onClick={() => {\n setSelectedFile(null)\n if (fileInputRef.current) fileInputRef.current.value = ''\n setLogoUrl('')\n setLogoPreserveAspectRatio(false)\n void saveBranding('', { skipUpload: true, logoPreserveAspectRatio: false })\n }}\n >\n <RotateCcw className=\"mr-2 size-4\" aria-hidden />\n {t('directory.branding.actions.reset', 'Use default logo')}\n </Button>\n </div>\n </div>\n </div>\n </form>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|