@open-mercato/core 0.4.2-canary-f075c3eb92 → 0.4.2-canary-8a04af8836
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/dist/generated/entities/notification/index.js +57 -0
- package/dist/generated/entities/notification/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +5 -1
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +2 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/api_docs/frontend/docs/api/page.js +3 -2
- package/dist/modules/api_docs/frontend/docs/api/page.js.map +2 -2
- package/dist/modules/api_keys/backend/api-keys/page.js +1 -1
- package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentLibrary.js +4 -0
- package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentPartitionSettings.js +2 -0
- package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
- package/dist/modules/auth/api/admin/nav.js +4 -3
- package/dist/modules/auth/api/admin/nav.js.map +2 -2
- package/dist/modules/auth/api/login.js +25 -6
- package/dist/modules/auth/api/login.js.map +2 -2
- package/dist/modules/auth/api/profile/route.js +157 -0
- package/dist/modules/auth/api/profile/route.js.map +7 -0
- package/dist/modules/auth/api/reset/confirm.js +25 -2
- package/dist/modules/auth/api/reset/confirm.js.map +2 -2
- package/dist/modules/auth/api/reset.js +23 -0
- package/dist/modules/auth/api/reset.js.map +2 -2
- package/dist/modules/auth/api/sidebar/preferences/route.js +14 -9
- package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +4 -2
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/backend/auth/profile/page.js +141 -0
- package/dist/modules/auth/backend/auth/profile/page.js.map +7 -0
- package/dist/modules/auth/backend/auth/profile/page.meta.js +13 -0
- package/dist/modules/auth/backend/auth/profile/page.meta.js.map +7 -0
- package/dist/modules/auth/backend/roles/[id]/edit/page.js +4 -1
- package/dist/modules/auth/backend/roles/[id]/edit/page.js.map +2 -2
- package/dist/modules/auth/backend/roles/page.js +3 -3
- package/dist/modules/auth/backend/roles/page.js.map +2 -2
- package/dist/modules/auth/backend/users/[id]/edit/page.js +18 -3
- package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
- package/dist/modules/auth/backend/users/create/page.js +15 -2
- package/dist/modules/auth/backend/users/create/page.js.map +2 -2
- package/dist/modules/auth/backend/users/page.js +3 -3
- package/dist/modules/auth/backend/users/page.js.map +2 -2
- package/dist/modules/auth/cli.js +25 -11
- package/dist/modules/auth/cli.js.map +2 -2
- package/dist/modules/auth/commands/users.js +59 -2
- package/dist/modules/auth/commands/users.js.map +2 -2
- package/dist/modules/auth/data/validators.js +6 -3
- package/dist/modules/auth/data/validators.js.map +2 -2
- package/dist/modules/auth/frontend/login.js +112 -3
- package/dist/modules/auth/frontend/login.js.map +2 -2
- package/dist/modules/auth/frontend/reset/[token]/page.js +20 -10
- package/dist/modules/auth/frontend/reset/[token]/page.js.map +2 -2
- package/dist/modules/auth/lib/setup-app.js +46 -8
- package/dist/modules/auth/lib/setup-app.js.map +2 -2
- package/dist/modules/auth/notifications.js +112 -0
- package/dist/modules/auth/notifications.js.map +7 -0
- package/dist/modules/auth/services/authService.js +24 -3
- package/dist/modules/auth/services/authService.js.map +2 -2
- package/dist/modules/business_rules/api/execute/route.js +7 -1
- package/dist/modules/business_rules/api/execute/route.js.map +2 -2
- package/dist/modules/business_rules/backend/rules/page.js +4 -0
- package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
- package/dist/modules/business_rules/backend/sets/page.js +3 -0
- package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
- package/dist/modules/business_rules/cli.js +2 -1
- package/dist/modules/business_rules/cli.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-engine.js +33 -3
- package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
- package/dist/modules/business_rules/notifications.js +28 -0
- package/dist/modules/business_rules/notifications.js.map +7 -0
- package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js +37 -0
- package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js.map +7 -0
- package/dist/modules/catalog/components/PriceKindSettings.js +2 -0
- package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js +2 -2
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductsDataTable.js +2 -0
- package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
- package/dist/modules/catalog/notifications.js +28 -0
- package/dist/modules/catalog/notifications.js.map +7 -0
- package/dist/modules/catalog/subscribers/low-stock-notification.js +38 -0
- package/dist/modules/catalog/subscribers/low-stock-notification.js.map +7 -0
- package/dist/modules/configs/cli.js +6 -0
- package/dist/modules/configs/cli.js.map +2 -2
- package/dist/modules/configs/components/CachePanel.js +4 -4
- package/dist/modules/configs/components/CachePanel.js.map +2 -2
- package/dist/modules/configs/lib/system-status.js +48 -1
- package/dist/modules/configs/lib/system-status.js.map +2 -2
- package/dist/modules/configs/lib/upgrade-actions.js +138 -306
- package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
- package/dist/modules/currencies/backend/currencies/page.js +3 -0
- package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
- package/dist/modules/currencies/backend/exchange-rates/page.js +2 -0
- package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/page.js +3 -0
- package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/page.js +3 -0
- package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/page.js +3 -0
- package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +31 -0
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/components/CustomerTodosTable.js +1 -0
- package/dist/modules/customers/components/CustomerTodosTable.js.map +2 -2
- package/dist/modules/customers/notifications.js +48 -0
- package/dist/modules/customers/notifications.js.map +7 -0
- package/dist/modules/customers/widgets/dashboard/customer-todos/widget.js +2 -1
- package/dist/modules/customers/widgets/dashboard/customer-todos/widget.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/new-customers/widget.js +2 -1
- package/dist/modules/customers/widgets/dashboard/new-customers/widget.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/new-deals/widget.js +2 -1
- package/dist/modules/customers/widgets/dashboard/new-deals/widget.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/next-interactions/widget.js +2 -1
- package/dist/modules/customers/widgets/dashboard/next-interactions/widget.js.map +2 -2
- package/dist/modules/dashboards/cli.js +44 -5
- package/dist/modules/dashboards/cli.js.map +2 -2
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +16 -11
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +3 -3
- package/dist/modules/dashboards/lib/role-widgets.js +58 -0
- package/dist/modules/dashboards/lib/role-widgets.js.map +7 -0
- package/dist/modules/dashboards/services/widgetDataService.js +139 -3
- package/dist/modules/dashboards/services/widgetDataService.js.map +2 -2
- package/dist/modules/dashboards/setup.js +15 -0
- package/dist/modules/dashboards/setup.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.js.map +2 -2
- package/dist/modules/dictionaries/components/DictionaryTable.js +2 -0
- package/dist/modules/dictionaries/components/DictionaryTable.js.map +2 -2
- package/dist/modules/directory/api/get/tenants/lookup.js +70 -0
- package/dist/modules/directory/api/get/tenants/lookup.js.map +7 -0
- package/dist/modules/directory/backend/directory/organizations/page.js +2 -2
- package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/tenants/page.js +2 -2
- package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
- package/dist/modules/entities/components/SystemEntitiesTable.js +1 -1
- package/dist/modules/entities/components/SystemEntitiesTable.js.map +2 -2
- package/dist/modules/entities/components/UserEntitiesTable.js +2 -2
- package/dist/modules/entities/components/UserEntitiesTable.js.map +2 -2
- package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +3 -3
- package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
- package/dist/modules/feature_toggles/components/OverridesTable.js +1 -1
- package/dist/modules/feature_toggles/components/OverridesTable.js.map +2 -2
- package/dist/modules/notifications/acl.js +11 -0
- package/dist/modules/notifications/acl.js.map +7 -0
- package/dist/modules/notifications/api/[id]/action/route.js +74 -0
- package/dist/modules/notifications/api/[id]/action/route.js.map +7 -0
- package/dist/modules/notifications/api/[id]/dismiss/route.js +15 -0
- package/dist/modules/notifications/api/[id]/dismiss/route.js.map +7 -0
- package/dist/modules/notifications/api/[id]/read/route.js +15 -0
- package/dist/modules/notifications/api/[id]/read/route.js.map +7 -0
- package/dist/modules/notifications/api/[id]/restore/route.js +53 -0
- package/dist/modules/notifications/api/[id]/restore/route.js.map +7 -0
- package/dist/modules/notifications/api/batch/route.js +17 -0
- package/dist/modules/notifications/api/batch/route.js.map +7 -0
- package/dist/modules/notifications/api/feature/route.js +17 -0
- package/dist/modules/notifications/api/feature/route.js.map +7 -0
- package/dist/modules/notifications/api/mark-all-read/route.js +35 -0
- package/dist/modules/notifications/api/mark-all-read/route.js.map +7 -0
- package/dist/modules/notifications/api/openapi.js +76 -0
- package/dist/modules/notifications/api/openapi.js.map +7 -0
- package/dist/modules/notifications/api/role/route.js +17 -0
- package/dist/modules/notifications/api/role/route.js.map +7 -0
- package/dist/modules/notifications/api/route.js +85 -0
- package/dist/modules/notifications/api/route.js.map +7 -0
- package/dist/modules/notifications/api/settings/route.js +155 -0
- package/dist/modules/notifications/api/settings/route.js.map +7 -0
- package/dist/modules/notifications/api/unread-count/route.js +38 -0
- package/dist/modules/notifications/api/unread-count/route.js.map +7 -0
- package/dist/modules/notifications/backend/config/notifications/page.js +10 -0
- package/dist/modules/notifications/backend/config/notifications/page.js.map +7 -0
- package/dist/modules/notifications/backend/config/notifications/page.meta.js +24 -0
- package/dist/modules/notifications/backend/config/notifications/page.meta.js.map +7 -0
- package/dist/modules/notifications/cli.js +16 -0
- package/dist/modules/notifications/cli.js.map +7 -0
- package/dist/modules/notifications/data/entities.js +112 -0
- package/dist/modules/notifications/data/entities.js.map +7 -0
- package/dist/modules/notifications/data/validators.js +98 -0
- package/dist/modules/notifications/data/validators.js.map +7 -0
- package/dist/modules/notifications/di.js +13 -0
- package/dist/modules/notifications/di.js.map +7 -0
- package/dist/modules/notifications/emails/NotificationEmail.js +58 -0
- package/dist/modules/notifications/emails/NotificationEmail.js.map +7 -0
- package/dist/modules/notifications/frontend/NotificationInboxPageClient.js +44 -0
- package/dist/modules/notifications/frontend/NotificationInboxPageClient.js.map +7 -0
- package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js +220 -0
- package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js.map +7 -0
- package/dist/modules/notifications/index.js +14 -0
- package/dist/modules/notifications/index.js.map +7 -0
- package/dist/modules/notifications/lib/deliveryConfig.js +107 -0
- package/dist/modules/notifications/lib/deliveryConfig.js.map +7 -0
- package/dist/modules/notifications/lib/deliveryStrategies.js +14 -0
- package/dist/modules/notifications/lib/deliveryStrategies.js.map +7 -0
- package/dist/modules/notifications/lib/events.js +12 -0
- package/dist/modules/notifications/lib/events.js.map +7 -0
- package/dist/modules/notifications/lib/notificationBuilder.js +66 -0
- package/dist/modules/notifications/lib/notificationBuilder.js.map +7 -0
- package/dist/modules/notifications/lib/notificationFactory.js +54 -0
- package/dist/modules/notifications/lib/notificationFactory.js.map +7 -0
- package/dist/modules/notifications/lib/notificationMapper.js +34 -0
- package/dist/modules/notifications/lib/notificationMapper.js.map +7 -0
- package/dist/modules/notifications/lib/notificationRecipients.js +35 -0
- package/dist/modules/notifications/lib/notificationRecipients.js.map +7 -0
- package/dist/modules/notifications/lib/notificationService.js +279 -0
- package/dist/modules/notifications/lib/notificationService.js.map +7 -0
- package/dist/modules/notifications/lib/routeHelpers.js +101 -0
- package/dist/modules/notifications/lib/routeHelpers.js.map +7 -0
- package/dist/modules/notifications/lib/safeHref.js +24 -0
- package/dist/modules/notifications/lib/safeHref.js.map +7 -0
- package/dist/modules/notifications/migrations/Migration20260123000001.js +70 -0
- package/dist/modules/notifications/migrations/Migration20260123000001.js.map +7 -0
- package/dist/modules/notifications/migrations/Migration20260126150000.js +37 -0
- package/dist/modules/notifications/migrations/Migration20260126150000.js.map +7 -0
- package/dist/modules/notifications/migrations/Migration20260129082610.js +13 -0
- package/dist/modules/notifications/migrations/Migration20260129082610.js.map +7 -0
- package/dist/modules/notifications/subscribers/deliver-notification.js +165 -0
- package/dist/modules/notifications/subscribers/deliver-notification.js.map +7 -0
- package/dist/modules/notifications/workers/create-notification.worker.js +70 -0
- package/dist/modules/notifications/workers/create-notification.worker.js.map +7 -0
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js +2 -2
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
- package/dist/modules/query_index/cli.js +63 -7
- package/dist/modules/query_index/cli.js.map +2 -2
- package/dist/modules/query_index/components/QueryIndexesTable.js +7 -1
- package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
- package/dist/modules/resources/backend/resources/resource-types/page.js +2 -2
- package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/page.js +2 -2
- package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.js +2 -0
- package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.js +2 -0
- package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
- package/dist/modules/sales/cli.js +2 -42
- package/dist/modules/sales/cli.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +53 -0
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/commands/payments.js +26 -0
- package/dist/modules/sales/commands/payments.js.map +2 -2
- package/dist/modules/sales/components/AdjustmentKindSettings.js +2 -2
- package/dist/modules/sales/components/AdjustmentKindSettings.js.map +2 -2
- package/dist/modules/sales/components/PaymentMethodsSettings.js +2 -2
- package/dist/modules/sales/components/PaymentMethodsSettings.js.map +2 -2
- package/dist/modules/sales/components/ShippingMethodsSettings.js +2 -2
- package/dist/modules/sales/components/ShippingMethodsSettings.js.map +2 -2
- package/dist/modules/sales/components/TaxRatesSettings.js +2 -2
- package/dist/modules/sales/components/TaxRatesSettings.js.map +2 -2
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +2 -0
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
- package/dist/modules/sales/components/documents/AdjustmentsSection.js +2 -0
- package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/PaymentsSection.js +2 -1
- package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js +2 -0
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
- package/dist/modules/sales/lib/seeds.js +48 -0
- package/dist/modules/sales/lib/seeds.js.map +7 -0
- package/dist/modules/sales/notifications.client.js +51 -0
- package/dist/modules/sales/notifications.client.js.map +7 -0
- package/dist/modules/sales/notifications.js +88 -0
- package/dist/modules/sales/notifications.js.map +7 -0
- package/dist/modules/sales/subscribers/quote-expiring-notification.js +38 -0
- package/dist/modules/sales/subscribers/quote-expiring-notification.js.map +7 -0
- package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js +137 -0
- package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js.map +7 -0
- package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js +137 -0
- package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js.map +7 -0
- package/dist/modules/sales/widgets/notifications/index.js +7 -0
- package/dist/modules/sales/widgets/notifications/index.js.map +7 -0
- package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js +60 -0
- package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js.map +7 -0
- package/dist/modules/staff/backend/staff/team-members/page.js +1 -1
- package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-roles/page.js +2 -2
- package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/page.js +2 -2
- package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
- package/dist/modules/staff/commands/leave-requests.js +79 -0
- package/dist/modules/staff/commands/leave-requests.js.map +2 -2
- package/dist/modules/staff/notifications.js +75 -0
- package/dist/modules/staff/notifications.js.map +7 -0
- package/dist/modules/workflows/backend/definitions/page.js +5 -0
- package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
- package/dist/modules/workflows/backend/instances/page.js +3 -0
- package/dist/modules/workflows/backend/instances/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/page.js +3 -0
- package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
- package/dist/modules/workflows/cli.js +12 -12
- package/dist/modules/workflows/cli.js.map +2 -2
- package/dist/modules/workflows/lib/transition-handler.js +14 -6
- package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
- package/dist/modules/workflows/notifications.js +28 -0
- package/dist/modules/workflows/notifications.js.map +7 -0
- package/dist/modules/workflows/subscribers/task-assigned-notification.js +38 -0
- package/dist/modules/workflows/subscribers/task-assigned-notification.js.map +7 -0
- package/generated/entities/notification/index.ts +27 -0
- package/generated/entities.ids.generated.ts +5 -1
- package/generated/entity-fields-registry.ts +2 -0
- package/package.json +2 -2
- package/src/modules/api_docs/frontend/docs/api/page.tsx +3 -2
- package/src/modules/api_keys/backend/api-keys/page.tsx +1 -1
- package/src/modules/attachments/components/AttachmentLibrary.tsx +4 -0
- package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +2 -0
- package/src/modules/auth/README.md +1 -1
- package/src/modules/auth/__tests__/cli-setup-acl.test.ts +1 -1
- package/src/modules/auth/api/__tests__/login.test.ts +2 -0
- package/src/modules/auth/api/admin/nav.ts +10 -6
- package/src/modules/auth/api/login.ts +26 -7
- package/src/modules/auth/api/profile/route.ts +163 -0
- package/src/modules/auth/api/reset/confirm.ts +25 -2
- package/src/modules/auth/api/reset.ts +23 -0
- package/src/modules/auth/api/sidebar/preferences/route.ts +21 -12
- package/src/modules/auth/api/users/route.ts +5 -2
- package/src/modules/auth/backend/auth/profile/page.meta.ts +9 -0
- package/src/modules/auth/backend/auth/profile/page.tsx +174 -0
- package/src/modules/auth/backend/roles/[id]/edit/page.tsx +4 -1
- package/src/modules/auth/backend/roles/page.tsx +3 -3
- package/src/modules/auth/backend/users/[id]/edit/page.tsx +22 -3
- package/src/modules/auth/backend/users/create/page.tsx +19 -2
- package/src/modules/auth/backend/users/page.tsx +3 -3
- package/src/modules/auth/cli.ts +38 -11
- package/src/modules/auth/commands/users.ts +73 -2
- package/src/modules/auth/data/validators.ts +6 -2
- package/src/modules/auth/frontend/login.tsx +134 -5
- package/src/modules/auth/frontend/reset/[token]/page.tsx +24 -11
- package/src/modules/auth/i18n/de.json +48 -1
- package/src/modules/auth/i18n/en.json +48 -1
- package/src/modules/auth/i18n/es.json +48 -1
- package/src/modules/auth/i18n/pl.json +48 -1
- package/src/modules/auth/lib/setup-app.ts +63 -9
- package/src/modules/auth/notifications.ts +109 -0
- package/src/modules/auth/services/authService.ts +27 -4
- package/src/modules/business_rules/api/execute/route.ts +8 -1
- package/src/modules/business_rules/backend/rules/page.tsx +4 -0
- package/src/modules/business_rules/backend/sets/page.tsx +3 -0
- package/src/modules/business_rules/cli.ts +2 -1
- package/src/modules/business_rules/i18n/en.json +3 -1
- package/src/modules/business_rules/lib/__tests__/rule-engine.test.ts +51 -0
- package/src/modules/business_rules/lib/rule-engine.ts +57 -3
- package/src/modules/business_rules/notifications.ts +25 -0
- package/src/modules/business_rules/subscribers/rule-execution-failed-notification.ts +50 -0
- package/src/modules/catalog/components/PriceKindSettings.tsx +2 -0
- package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +2 -2
- package/src/modules/catalog/components/products/ProductsDataTable.tsx +2 -0
- package/src/modules/catalog/i18n/en.json +3 -1
- package/src/modules/catalog/notifications.ts +25 -0
- package/src/modules/catalog/subscribers/low-stock-notification.ts +52 -0
- package/src/modules/configs/cli.ts +6 -0
- package/src/modules/configs/components/CachePanel.tsx +4 -4
- package/src/modules/configs/i18n/en.json +12 -2
- package/src/modules/configs/i18n/pl.json +12 -2
- package/src/modules/configs/lib/system-status.ts +48 -1
- package/src/modules/configs/lib/system-status.types.ts +1 -0
- package/src/modules/configs/lib/upgrade-actions.ts +157 -351
- package/src/modules/currencies/backend/currencies/page.tsx +3 -0
- package/src/modules/currencies/backend/exchange-rates/page.tsx +2 -0
- package/src/modules/customers/backend/customers/companies/page.tsx +3 -0
- package/src/modules/customers/backend/customers/deals/page.tsx +3 -0
- package/src/modules/customers/backend/customers/people/page.tsx +3 -0
- package/src/modules/customers/commands/deals.ts +39 -0
- package/src/modules/customers/components/CustomerTodosTable.tsx +1 -0
- package/src/modules/customers/i18n/en.json +5 -1
- package/src/modules/customers/notifications.ts +44 -0
- package/src/modules/customers/widgets/dashboard/customer-todos/widget.ts +2 -2
- package/src/modules/customers/widgets/dashboard/new-customers/widget.ts +2 -2
- package/src/modules/customers/widgets/dashboard/new-deals/widget.ts +2 -2
- package/src/modules/customers/widgets/dashboard/next-interactions/widget.ts +2 -2
- package/src/modules/dashboards/cli.ts +55 -5
- package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +22 -11
- package/src/modules/dashboards/lib/role-widgets.ts +80 -0
- package/src/modules/dashboards/services/widgetDataService.ts +164 -4
- package/src/modules/dashboards/setup.ts +16 -0
- package/src/modules/dashboards/widgets/dashboard/aov-kpi/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/orders-by-status/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/orders-kpi/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/revenue-kpi/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/top-customers/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/top-products/widget.ts +2 -2
- package/src/modules/dictionaries/components/DictionaryTable.tsx +2 -0
- package/src/modules/directory/api/get/tenants/lookup.ts +75 -0
- package/src/modules/directory/backend/directory/organizations/page.tsx +2 -2
- package/src/modules/directory/backend/directory/tenants/page.tsx +2 -2
- package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +2 -2
- package/src/modules/entities/components/SystemEntitiesTable.tsx +1 -1
- package/src/modules/entities/components/UserEntitiesTable.tsx +2 -2
- package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +3 -4
- package/src/modules/feature_toggles/components/OverridesTable.tsx +1 -1
- package/src/modules/notifications/__tests__/deliver-notification.test.ts +195 -0
- package/src/modules/notifications/__tests__/deliveryStrategies.test.ts +19 -0
- package/src/modules/notifications/__tests__/notificationService.test.ts +208 -0
- package/src/modules/notifications/acl.ts +7 -0
- package/src/modules/notifications/api/[id]/action/route.ts +75 -0
- package/src/modules/notifications/api/[id]/dismiss/route.ts +12 -0
- package/src/modules/notifications/api/[id]/read/route.ts +12 -0
- package/src/modules/notifications/api/[id]/restore/route.ts +53 -0
- package/src/modules/notifications/api/batch/route.ts +14 -0
- package/src/modules/notifications/api/feature/route.ts +14 -0
- package/src/modules/notifications/api/mark-all-read/route.ts +34 -0
- package/src/modules/notifications/api/openapi.ts +76 -0
- package/src/modules/notifications/api/role/route.ts +14 -0
- package/src/modules/notifications/api/route.ts +92 -0
- package/src/modules/notifications/api/settings/route.ts +157 -0
- package/src/modules/notifications/api/unread-count/route.ts +38 -0
- package/src/modules/notifications/backend/config/notifications/page.meta.ts +22 -0
- package/src/modules/notifications/backend/config/notifications/page.tsx +12 -0
- package/src/modules/notifications/cli.ts +18 -0
- package/src/modules/notifications/data/entities.ts +99 -0
- package/src/modules/notifications/data/validators.ts +115 -0
- package/src/modules/notifications/di.ts +11 -0
- package/src/modules/notifications/emails/NotificationEmail.tsx +98 -0
- package/src/modules/notifications/frontend/NotificationInboxPageClient.tsx +42 -0
- package/src/modules/notifications/frontend/NotificationSettingsPageClient.tsx +233 -0
- package/src/modules/notifications/i18n/de.json +50 -0
- package/src/modules/notifications/i18n/en.json +50 -0
- package/src/modules/notifications/i18n/es.json +50 -0
- package/src/modules/notifications/i18n/pl.json +50 -0
- package/src/modules/notifications/index.ts +12 -0
- package/src/modules/notifications/lib/deliveryConfig.ts +153 -0
- package/src/modules/notifications/lib/deliveryStrategies.ts +50 -0
- package/src/modules/notifications/lib/events.ts +48 -0
- package/src/modules/notifications/lib/notificationBuilder.ts +121 -0
- package/src/modules/notifications/lib/notificationFactory.ts +76 -0
- package/src/modules/notifications/lib/notificationMapper.ts +33 -0
- package/src/modules/notifications/lib/notificationRecipients.ts +83 -0
- package/src/modules/notifications/lib/notificationService.ts +414 -0
- package/src/modules/notifications/lib/routeHelpers.ts +151 -0
- package/src/modules/notifications/lib/safeHref.ts +29 -0
- package/src/modules/notifications/migrations/.snapshot-open-mercato.json +336 -0
- package/src/modules/notifications/migrations/Migration20260123000001.ts +73 -0
- package/src/modules/notifications/migrations/Migration20260126150000.ts +39 -0
- package/src/modules/notifications/migrations/Migration20260129082610.ts +13 -0
- package/src/modules/notifications/subscribers/deliver-notification.ts +204 -0
- package/src/modules/notifications/workers/create-notification.worker.ts +122 -0
- package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +2 -2
- package/src/modules/query_index/cli.ts +82 -13
- package/src/modules/query_index/components/QueryIndexesTable.tsx +8 -2
- package/src/modules/resources/backend/resources/resource-types/page.tsx +2 -2
- package/src/modules/resources/backend/resources/resources/page.tsx +2 -2
- package/src/modules/sales/backend/sales/channels/offers/page.tsx +2 -0
- package/src/modules/sales/backend/sales/channels/page.tsx +2 -0
- package/src/modules/sales/cli.ts +2 -43
- package/src/modules/sales/commands/documents.ts +65 -0
- package/src/modules/sales/commands/payments.ts +33 -0
- package/src/modules/sales/components/AdjustmentKindSettings.tsx +2 -2
- package/src/modules/sales/components/PaymentMethodsSettings.tsx +2 -2
- package/src/modules/sales/components/ShippingMethodsSettings.tsx +2 -2
- package/src/modules/sales/components/TaxRatesSettings.tsx +2 -2
- package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +2 -0
- package/src/modules/sales/components/documents/AdjustmentsSection.tsx +2 -0
- package/src/modules/sales/components/documents/PaymentsSection.tsx +2 -1
- package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +2 -0
- package/src/modules/sales/i18n/de.json +20 -0
- package/src/modules/sales/i18n/en.json +25 -1
- package/src/modules/sales/i18n/es.json +20 -0
- package/src/modules/sales/i18n/pl.json +20 -0
- package/src/modules/sales/lib/seeds.ts +53 -0
- package/src/modules/sales/notifications.client.ts +65 -0
- package/src/modules/sales/notifications.ts +82 -0
- package/src/modules/sales/subscribers/quote-expiring-notification.ts +53 -0
- package/src/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.tsx +156 -0
- package/src/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.tsx +156 -0
- package/src/modules/sales/widgets/notifications/index.ts +2 -0
- package/src/modules/sales/widgets/notifications/useSalesDocumentTotals.ts +81 -0
- package/src/modules/staff/backend/staff/team-members/page.tsx +1 -1
- package/src/modules/staff/backend/staff/team-roles/page.tsx +2 -2
- package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +2 -2
- package/src/modules/staff/backend/staff/teams/page.tsx +2 -2
- package/src/modules/staff/commands/leave-requests.ts +94 -0
- package/src/modules/staff/i18n/de.json +6 -0
- package/src/modules/staff/i18n/en.json +9 -1
- package/src/modules/staff/i18n/es.json +6 -0
- package/src/modules/staff/i18n/pl.json +6 -0
- package/src/modules/staff/notifications.ts +71 -0
- package/src/modules/workflows/backend/definitions/page.tsx +5 -0
- package/src/modules/workflows/backend/instances/page.tsx +4 -1
- package/src/modules/workflows/backend/tasks/page.tsx +4 -1
- package/src/modules/workflows/cli.ts +12 -12
- package/src/modules/workflows/i18n/en.json +3 -1
- package/src/modules/workflows/lib/__tests__/transition-handler.test.ts +6 -3
- package/src/modules/workflows/lib/transition-handler.ts +18 -6
- package/src/modules/workflows/notifications.ts +25 -0
- package/src/modules/workflows/subscribers/task-assigned-notification.ts +53 -0
|
@@ -1,102 +1,98 @@
|
|
|
1
|
-
import { runWithCacheTenant } from "@open-mercato/cache";
|
|
2
|
-
import { Role, RoleAcl } from "@open-mercato/core/modules/auth/data/entities";
|
|
3
|
-
import { reindexModules } from "@open-mercato/core/modules/configs/lib/reindex-helpers";
|
|
4
|
-
import { collectCrudCacheStats, purgeCrudCacheSegment } from "@open-mercato/shared/lib/crud/cache-stats";
|
|
5
|
-
import { isCrudCacheEnabled, resolveCrudCache } from "@open-mercato/shared/lib/crud/cache";
|
|
6
1
|
import * as semver from "semver";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
2
|
+
import { getModules } from "@open-mercato/shared/lib/modules/registry";
|
|
3
|
+
import { Role, RoleAcl } from "@open-mercato/core/modules/auth/data/entities";
|
|
4
|
+
import { normalizeTenantId } from "@open-mercato/core/modules/auth/lib/tenantAccess";
|
|
5
|
+
function compareVersions(a, b) {
|
|
6
|
+
const cleanA = semver.valid(semver.coerce(a));
|
|
7
|
+
const cleanB = semver.valid(semver.coerce(b));
|
|
8
|
+
if (!cleanA) {
|
|
9
|
+
throw new Error(`Invalid version string: "${a}". Expected a valid semver format (e.g., "1.2.3").`);
|
|
10
|
+
}
|
|
11
|
+
if (!cleanB) {
|
|
12
|
+
throw new Error(`Invalid version string: "${b}". Expected a valid semver format (e.g., "1.2.3").`);
|
|
14
13
|
}
|
|
14
|
+
return semver.compare(cleanA, cleanB);
|
|
15
15
|
}
|
|
16
|
-
function
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
function collectRoleFeatures(modules, moduleIds) {
|
|
17
|
+
const result = {
|
|
18
|
+
superadmin: [],
|
|
19
|
+
admin: [],
|
|
20
|
+
employee: []
|
|
21
|
+
};
|
|
22
|
+
const targetIds = new Set(moduleIds);
|
|
23
|
+
for (const mod of modules) {
|
|
24
|
+
if (!targetIds.has(mod.id)) continue;
|
|
25
|
+
const roleFeatures = mod.setup?.defaultRoleFeatures;
|
|
26
|
+
if (roleFeatures?.superadmin) result.superadmin.push(...roleFeatures.superadmin);
|
|
27
|
+
if (roleFeatures?.admin) result.admin.push(...roleFeatures.admin);
|
|
28
|
+
if (roleFeatures?.employee) result.employee.push(...roleFeatures.employee);
|
|
21
29
|
}
|
|
30
|
+
result.superadmin = Array.from(new Set(result.superadmin));
|
|
31
|
+
result.admin = Array.from(new Set(result.admin));
|
|
32
|
+
result.employee = Array.from(new Set(result.employee));
|
|
33
|
+
return result;
|
|
22
34
|
}
|
|
23
|
-
async function
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
if (!
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
});
|
|
35
|
+
async function findRoleByName(em, name, tenantId) {
|
|
36
|
+
const normalizedTenant = normalizeTenantId(tenantId ?? null) ?? null;
|
|
37
|
+
let role = await em.findOne(Role, { name, tenantId: normalizedTenant });
|
|
38
|
+
if (!role && normalizedTenant !== null) {
|
|
39
|
+
role = await em.findOne(Role, { name, tenantId: null });
|
|
40
|
+
}
|
|
41
|
+
return role;
|
|
42
|
+
}
|
|
43
|
+
async function ensureRoleAclFor(em, role, tenantId, features, options = {}) {
|
|
44
|
+
const existing = await em.findOne(RoleAcl, { role, tenantId });
|
|
34
45
|
if (!existing) {
|
|
35
|
-
em.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
})
|
|
45
|
-
);
|
|
46
|
-
await em.flush();
|
|
47
|
-
return true;
|
|
46
|
+
const acl = em.create(RoleAcl, {
|
|
47
|
+
role,
|
|
48
|
+
tenantId,
|
|
49
|
+
featuresJson: features,
|
|
50
|
+
isSuperAdmin: !!options.isSuperAdmin,
|
|
51
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
52
|
+
});
|
|
53
|
+
await em.persistAndFlush(acl);
|
|
54
|
+
return;
|
|
48
55
|
}
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
const currentFeatures = Array.isArray(existing.featuresJson) ? existing.featuresJson : [];
|
|
57
|
+
const merged = Array.from(/* @__PURE__ */ new Set([...currentFeatures, ...features]));
|
|
58
|
+
const changed = merged.length !== currentFeatures.length || merged.some((value, index) => value !== currentFeatures[index]);
|
|
59
|
+
if (changed) existing.featuresJson = merged;
|
|
60
|
+
if (options.isSuperAdmin && !existing.isSuperAdmin) {
|
|
61
|
+
existing.isSuperAdmin = true;
|
|
54
62
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (byField.has(req.field)) continue;
|
|
58
|
-
byField.set(req.field, req);
|
|
63
|
+
if (changed || options.isSuperAdmin) {
|
|
64
|
+
await em.persistAndFlush(existing);
|
|
59
65
|
}
|
|
60
|
-
const merged = Array.from(byField.values());
|
|
61
|
-
const changed = merged.length !== existingFields.length;
|
|
62
|
-
if (!changed && existing.isActive) return false;
|
|
63
|
-
existing.fieldsJson = merged;
|
|
64
|
-
existing.isActive = true;
|
|
65
|
-
existing.updatedAt = /* @__PURE__ */ new Date();
|
|
66
|
-
await em.flush();
|
|
67
|
-
return true;
|
|
68
66
|
}
|
|
69
|
-
function
|
|
70
|
-
const
|
|
71
|
-
const
|
|
72
|
-
if (!
|
|
73
|
-
|
|
67
|
+
async function ensureRoleAclsForModules(em, tenantId, moduleIds) {
|
|
68
|
+
const modules = getModules();
|
|
69
|
+
const roleFeatures = collectRoleFeatures(modules, moduleIds);
|
|
70
|
+
if (!roleFeatures.superadmin.length && !roleFeatures.admin.length && !roleFeatures.employee.length) {
|
|
71
|
+
return;
|
|
74
72
|
}
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
const normalizedTenant = normalizeTenantId(tenantId) ?? null;
|
|
74
|
+
const [superadminRole, adminRole, employeeRole] = await Promise.all([
|
|
75
|
+
findRoleByName(em, "superadmin", normalizedTenant),
|
|
76
|
+
findRoleByName(em, "admin", normalizedTenant),
|
|
77
|
+
findRoleByName(em, "employee", normalizedTenant)
|
|
78
|
+
]);
|
|
79
|
+
if (superadminRole && roleFeatures.superadmin.length) {
|
|
80
|
+
await ensureRoleAclFor(em, superadminRole, tenantId, roleFeatures.superadmin, { isSuperAdmin: true });
|
|
81
|
+
}
|
|
82
|
+
if (adminRole && roleFeatures.admin.length) {
|
|
83
|
+
await ensureRoleAclFor(em, adminRole, tenantId, roleFeatures.admin);
|
|
84
|
+
}
|
|
85
|
+
if (employeeRole && roleFeatures.employee.length) {
|
|
86
|
+
await ensureRoleAclFor(em, employeeRole, tenantId, roleFeatures.employee);
|
|
77
87
|
}
|
|
78
|
-
return semver.compare(cleanA, cleanB);
|
|
79
88
|
}
|
|
80
|
-
async function
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (!catalogSegments.length) return;
|
|
88
|
-
for (const segment of catalogSegments) {
|
|
89
|
-
try {
|
|
90
|
-
await purgeCrudCacheSegment(cache, segment.segment);
|
|
91
|
-
} catch (error) {
|
|
92
|
-
console.warn("[upgrade-actions] failed to purge catalog cache segment", {
|
|
93
|
-
tenantId,
|
|
94
|
-
segment: segment.segment,
|
|
95
|
-
error
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
});
|
|
89
|
+
async function safeImport(label, loader) {
|
|
90
|
+
try {
|
|
91
|
+
return await loader();
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.warn(`[upgrade-actions] Skipping ${label} because module import failed.`, error);
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
100
96
|
}
|
|
101
97
|
const upgradeActions = [
|
|
102
98
|
{
|
|
@@ -106,60 +102,17 @@ const upgradeActions = [
|
|
|
106
102
|
ctaKey: "upgrades.v034.cta",
|
|
107
103
|
successKey: "upgrades.v034.success",
|
|
108
104
|
loadingKey: "upgrades.v034.loading",
|
|
109
|
-
async run(
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
await reindexModules(em, ["catalog"], { tenantId, organizationId, vectorService });
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
id: "configs.upgrades.auth.admin_business_rules_acl",
|
|
125
|
-
version: "0.3.5",
|
|
126
|
-
messageKey: "upgrades.v035.message",
|
|
127
|
-
ctaKey: "upgrades.v035.cta",
|
|
128
|
-
successKey: "upgrades.v035.success",
|
|
129
|
-
loadingKey: "upgrades.v035.loading",
|
|
130
|
-
async run({ container, em, tenantId }) {
|
|
131
|
-
const normalizedTenantId = tenantId.trim();
|
|
132
|
-
await em.transactional(async (tem) => {
|
|
133
|
-
const adminRole = await tem.findOne(Role, { name: "admin", tenantId: normalizedTenantId, deletedAt: null });
|
|
134
|
-
if (!adminRole) return;
|
|
135
|
-
const roleAcls = await tem.find(RoleAcl, { role: adminRole, tenantId: normalizedTenantId, deletedAt: null });
|
|
136
|
-
let touched = false;
|
|
137
|
-
if (!roleAcls.length) {
|
|
138
|
-
tem.persist(
|
|
139
|
-
tem.create(RoleAcl, {
|
|
140
|
-
role: adminRole,
|
|
141
|
-
tenantId: normalizedTenantId,
|
|
142
|
-
featuresJson: ["business_rules.*"],
|
|
143
|
-
isSuperAdmin: false,
|
|
144
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
145
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
146
|
-
})
|
|
147
|
-
);
|
|
148
|
-
touched = true;
|
|
149
|
-
}
|
|
150
|
-
for (const acl of roleAcls) {
|
|
151
|
-
const features = Array.isArray(acl.featuresJson) ? [...acl.featuresJson] : [];
|
|
152
|
-
if (features.includes("business_rules.*")) continue;
|
|
153
|
-
acl.featuresJson = [...features, "business_rules.*"];
|
|
154
|
-
acl.updatedAt = /* @__PURE__ */ new Date();
|
|
155
|
-
touched = true;
|
|
156
|
-
}
|
|
157
|
-
if (touched) {
|
|
158
|
-
await tem.flush();
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
const rbac = container.resolve("rbacService");
|
|
162
|
-
await rbac.invalidateTenantCache(normalizedTenantId);
|
|
105
|
+
async run(ctx) {
|
|
106
|
+
const catalogSeeds = await safeImport(
|
|
107
|
+
"catalog examples",
|
|
108
|
+
() => import("@open-mercato/core/modules/catalog/lib/seeds")
|
|
109
|
+
);
|
|
110
|
+
if (!catalogSeeds?.installExampleCatalogData) return;
|
|
111
|
+
await catalogSeeds.installExampleCatalogData(
|
|
112
|
+
ctx.container,
|
|
113
|
+
{ tenantId: ctx.tenantId, organizationId: ctx.organizationId },
|
|
114
|
+
ctx.em
|
|
115
|
+
);
|
|
163
116
|
}
|
|
164
117
|
},
|
|
165
118
|
{
|
|
@@ -169,47 +122,16 @@ const upgradeActions = [
|
|
|
169
122
|
ctaKey: "upgrades.v036.cta",
|
|
170
123
|
successKey: "upgrades.v036.success",
|
|
171
124
|
loadingKey: "upgrades.v036.loading",
|
|
172
|
-
async run(
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
await em.transactional(async (tem) => {
|
|
182
|
-
await seedSalesExamples(tem, container, { tenantId, organizationId });
|
|
183
|
-
});
|
|
184
|
-
const vectorService = resolveVectorService(container);
|
|
185
|
-
await reindexModules(em, ["sales", "catalog"], { tenantId, organizationId, vectorService });
|
|
186
|
-
await purgeCatalogCrudCache(container, tenantId);
|
|
187
|
-
}
|
|
188
|
-
},
|
|
189
|
-
{
|
|
190
|
-
id: "configs.upgrades.vector.encryption_vector_search",
|
|
191
|
-
version: "0.3.6",
|
|
192
|
-
messageKey: "upgrades.v036_vector_encryption.message",
|
|
193
|
-
ctaKey: "upgrades.v036_vector_encryption.cta",
|
|
194
|
-
successKey: "upgrades.v036_vector_encryption.success",
|
|
195
|
-
loadingKey: "upgrades.v036_vector_encryption.loading",
|
|
196
|
-
async run({ container, em, tenantId, organizationId }) {
|
|
197
|
-
const normalizedTenantId = tenantId.trim();
|
|
198
|
-
const normalizedOrgId = organizationId ?? null;
|
|
199
|
-
const encryptionService = resolveEncryptionService(container);
|
|
200
|
-
if (!encryptionService?.isEnabled?.()) {
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
const updated = await em.transactional(async (tem) => {
|
|
204
|
-
return ensureVectorSearchEncryptionMap(tem, normalizedTenantId, normalizedOrgId);
|
|
125
|
+
async run(ctx) {
|
|
126
|
+
const salesSeeds = await safeImport(
|
|
127
|
+
"sales examples",
|
|
128
|
+
() => import("@open-mercato/core/modules/sales/seed/examples")
|
|
129
|
+
);
|
|
130
|
+
if (!salesSeeds?.seedSalesExamples) return;
|
|
131
|
+
await salesSeeds.seedSalesExamples(ctx.em, ctx.container, {
|
|
132
|
+
tenantId: ctx.tenantId,
|
|
133
|
+
organizationId: ctx.organizationId
|
|
205
134
|
});
|
|
206
|
-
if (updated) {
|
|
207
|
-
await encryptionService.invalidateMap("vector:vector_search", normalizedTenantId, normalizedOrgId);
|
|
208
|
-
}
|
|
209
|
-
const vectorService = resolveVectorService(container);
|
|
210
|
-
if (vectorService) {
|
|
211
|
-
await vectorService.reindexAll({ tenantId: normalizedTenantId, organizationId: normalizedOrgId, purgeFirst: false });
|
|
212
|
-
}
|
|
213
135
|
}
|
|
214
136
|
},
|
|
215
137
|
{
|
|
@@ -219,60 +141,23 @@ const upgradeActions = [
|
|
|
219
141
|
ctaKey: "upgrades.v0313.cta",
|
|
220
142
|
successKey: "upgrades.v0313.success",
|
|
221
143
|
loadingKey: "upgrades.v0313.loading",
|
|
222
|
-
async run(
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
144
|
+
async run(ctx) {
|
|
145
|
+
const currenciesSeeds = await safeImport(
|
|
146
|
+
"currencies examples",
|
|
147
|
+
() => import("@open-mercato/core/modules/currencies/lib/seeds")
|
|
148
|
+
);
|
|
149
|
+
const workflowsSeeds = await safeImport(
|
|
150
|
+
"workflows examples",
|
|
151
|
+
() => import("@open-mercato/core/modules/workflows/lib/seeds")
|
|
152
|
+
);
|
|
153
|
+
const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId };
|
|
154
|
+
if (currenciesSeeds?.seedExampleCurrencies) {
|
|
155
|
+
await currenciesSeeds.seedExampleCurrencies(ctx.em, scope);
|
|
231
156
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
const workflowsSeeds = await import("@open-mercato/core/modules/workflows/lib/seeds");
|
|
235
|
-
seedExampleWorkflows = workflowsSeeds.seedExampleWorkflows;
|
|
236
|
-
} catch {
|
|
237
|
-
console.warn("[upgrade-actions] workflows module not available, skipping workflow seeding");
|
|
157
|
+
if (workflowsSeeds?.seedExampleWorkflows) {
|
|
158
|
+
await workflowsSeeds.seedExampleWorkflows(ctx.em, scope);
|
|
238
159
|
}
|
|
239
|
-
await em.
|
|
240
|
-
if (seedExampleCurrencies) await seedExampleCurrencies(tem, scope);
|
|
241
|
-
if (seedExampleWorkflows) await seedExampleWorkflows(tem, scope);
|
|
242
|
-
const adminRole = await tem.findOne(Role, { name: "admin", tenantId: normalizedTenantId, deletedAt: null });
|
|
243
|
-
if (!adminRole) return;
|
|
244
|
-
const roleAcls = await tem.find(RoleAcl, { role: adminRole, tenantId: normalizedTenantId, deletedAt: null });
|
|
245
|
-
let touched = false;
|
|
246
|
-
if (!roleAcls.length) {
|
|
247
|
-
tem.persist(
|
|
248
|
-
tem.create(RoleAcl, {
|
|
249
|
-
role: adminRole,
|
|
250
|
-
tenantId: normalizedTenantId,
|
|
251
|
-
featuresJson: ["search.*", "feature_toggles.*", "currencies.*"],
|
|
252
|
-
isSuperAdmin: false,
|
|
253
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
254
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
255
|
-
})
|
|
256
|
-
);
|
|
257
|
-
touched = true;
|
|
258
|
-
}
|
|
259
|
-
for (const acl of roleAcls) {
|
|
260
|
-
const features = Array.isArray(acl.featuresJson) ? [...acl.featuresJson] : [];
|
|
261
|
-
const nextFeatures = new Set(features);
|
|
262
|
-
nextFeatures.add("search.*");
|
|
263
|
-
nextFeatures.add("feature_toggles.*");
|
|
264
|
-
nextFeatures.add("currencies.*");
|
|
265
|
-
if (nextFeatures.size === features.length) continue;
|
|
266
|
-
acl.featuresJson = Array.from(nextFeatures);
|
|
267
|
-
acl.updatedAt = /* @__PURE__ */ new Date();
|
|
268
|
-
touched = true;
|
|
269
|
-
}
|
|
270
|
-
if (touched) {
|
|
271
|
-
await tem.flush();
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
const rbac = container.resolve("rbacService");
|
|
275
|
-
await rbac.invalidateTenantCache(normalizedTenantId);
|
|
160
|
+
await ensureRoleAclsForModules(ctx.em, ctx.tenantId, ["currencies", "workflows"]);
|
|
276
161
|
}
|
|
277
162
|
},
|
|
278
163
|
{
|
|
@@ -282,83 +167,30 @@ const upgradeActions = [
|
|
|
282
167
|
ctaKey: "upgrades.v041.cta",
|
|
283
168
|
successKey: "upgrades.v041.success",
|
|
284
169
|
loadingKey: "upgrades.v041.loading",
|
|
285
|
-
async run(
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
170
|
+
async run(ctx) {
|
|
171
|
+
const plannerSeeds = await safeImport(
|
|
172
|
+
"planner examples",
|
|
173
|
+
() => import("@open-mercato/core/modules/planner/lib/seeds")
|
|
174
|
+
);
|
|
175
|
+
const staffSeeds = await safeImport(
|
|
176
|
+
"staff examples",
|
|
177
|
+
() => import("@open-mercato/core/modules/staff/lib/seeds")
|
|
178
|
+
);
|
|
179
|
+
const resourcesSeeds = await safeImport(
|
|
180
|
+
"resources examples",
|
|
181
|
+
() => import("@open-mercato/core/modules/resources/lib/seeds")
|
|
182
|
+
);
|
|
183
|
+
const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId };
|
|
184
|
+
if (plannerSeeds?.seedPlannerAvailabilityRuleSetDefaults) {
|
|
185
|
+
await plannerSeeds.seedPlannerAvailabilityRuleSetDefaults(ctx.em, scope);
|
|
296
186
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
const staffSeeds = await import("@open-mercato/core/modules/staff/lib/seeds");
|
|
300
|
-
seedStaffTeamExamples = staffSeeds.seedStaffTeamExamples;
|
|
301
|
-
} catch {
|
|
302
|
-
console.warn("[upgrade-actions] staff module not available, skipping staff seeding");
|
|
187
|
+
if (staffSeeds?.seedStaffTeamExamples) {
|
|
188
|
+
await staffSeeds.seedStaffTeamExamples(ctx.em, scope);
|
|
303
189
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
let seedResourcesResourceExamples;
|
|
307
|
-
try {
|
|
308
|
-
const resourcesSeeds = await import("@open-mercato/core/modules/resources/lib/seeds");
|
|
309
|
-
seedResourcesAddressTypes = resourcesSeeds.seedResourcesAddressTypes;
|
|
310
|
-
seedResourcesCapacityUnits = resourcesSeeds.seedResourcesCapacityUnits;
|
|
311
|
-
seedResourcesResourceExamples = resourcesSeeds.seedResourcesResourceExamples;
|
|
312
|
-
} catch {
|
|
313
|
-
console.warn("[upgrade-actions] resources module not available, skipping resources seeding");
|
|
190
|
+
if (resourcesSeeds?.seedResourcesResourceExamples) {
|
|
191
|
+
await resourcesSeeds.seedResourcesResourceExamples(ctx.em, scope);
|
|
314
192
|
}
|
|
315
|
-
await em.
|
|
316
|
-
if (seedPlannerAvailabilityRuleSetDefaults) await seedPlannerAvailabilityRuleSetDefaults(tem, scope);
|
|
317
|
-
if (seedPlannerUnavailabilityReasons) await seedPlannerUnavailabilityReasons(tem, scope);
|
|
318
|
-
if (seedStaffTeamExamples) await seedStaffTeamExamples(tem, scope);
|
|
319
|
-
if (seedResourcesCapacityUnits) await seedResourcesCapacityUnits(tem, scope);
|
|
320
|
-
if (seedResourcesAddressTypes) await seedResourcesAddressTypes(tem, scope);
|
|
321
|
-
if (seedResourcesResourceExamples) await seedResourcesResourceExamples(tem, scope);
|
|
322
|
-
const adminRole = await tem.findOne(Role, { name: "admin", tenantId: normalizedTenantId, deletedAt: null });
|
|
323
|
-
if (!adminRole) return;
|
|
324
|
-
const roleAcls = await tem.find(RoleAcl, { role: adminRole, tenantId: normalizedTenantId, deletedAt: null });
|
|
325
|
-
const addedFeatures = [
|
|
326
|
-
"staff.*",
|
|
327
|
-
"staff.leave_requests.manage",
|
|
328
|
-
"resources.*",
|
|
329
|
-
"planner.*"
|
|
330
|
-
];
|
|
331
|
-
let touched = false;
|
|
332
|
-
if (!roleAcls.length) {
|
|
333
|
-
tem.persist(
|
|
334
|
-
tem.create(RoleAcl, {
|
|
335
|
-
role: adminRole,
|
|
336
|
-
tenantId: normalizedTenantId,
|
|
337
|
-
featuresJson: addedFeatures,
|
|
338
|
-
isSuperAdmin: false,
|
|
339
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
340
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
341
|
-
})
|
|
342
|
-
);
|
|
343
|
-
touched = true;
|
|
344
|
-
}
|
|
345
|
-
for (const acl of roleAcls) {
|
|
346
|
-
const features = Array.isArray(acl.featuresJson) ? [...acl.featuresJson] : [];
|
|
347
|
-
const nextFeatures = new Set(features);
|
|
348
|
-
for (const feature of addedFeatures) nextFeatures.add(feature);
|
|
349
|
-
if (nextFeatures.size === features.length) continue;
|
|
350
|
-
acl.featuresJson = Array.from(nextFeatures);
|
|
351
|
-
acl.updatedAt = /* @__PURE__ */ new Date();
|
|
352
|
-
touched = true;
|
|
353
|
-
}
|
|
354
|
-
if (touched) {
|
|
355
|
-
await tem.flush();
|
|
356
|
-
}
|
|
357
|
-
});
|
|
358
|
-
const rbac = container.resolve("rbacService");
|
|
359
|
-
await rbac.invalidateTenantCache(normalizedTenantId);
|
|
360
|
-
const vectorService = resolveVectorService(container);
|
|
361
|
-
await reindexModules(em, ["planner", "staff", "resources"], { tenantId, organizationId, vectorService });
|
|
193
|
+
await ensureRoleAclsForModules(ctx.em, ctx.tenantId, ["planner", "staff", "resources"]);
|
|
362
194
|
}
|
|
363
195
|
}
|
|
364
196
|
];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/configs/lib/upgrade-actions.ts"],
|
|
4
|
-
"sourcesContent": ["import { runWithCacheTenant } from '@open-mercato/cache'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { AwilixContainer } from 'awilix'\nimport { Role, RoleAcl } from '@open-mercato/core/modules/auth/data/entities'\nimport type { RbacService } from '@open-mercato/core/modules/auth/services/rbacService'\nimport { reindexModules } from '@open-mercato/core/modules/configs/lib/reindex-helpers'\n// Optional module imports are loaded dynamically inside each upgrade action\n// so the app does not crash when a module is disabled.\nimport { collectCrudCacheStats, purgeCrudCacheSegment } from '@open-mercato/shared/lib/crud/cache-stats'\nimport { isCrudCacheEnabled, resolveCrudCache } from '@open-mercato/shared/lib/crud/cache'\nimport * as semver from 'semver'\nimport type { VectorIndexService } from '@open-mercato/search/vector'\nimport { EncryptionMap } from '@open-mercato/core/modules/entities/data/entities'\nimport { DEFAULT_ENCRYPTION_MAPS } from '@open-mercato/core/modules/entities/lib/encryptionDefaults'\nimport type { TenantDataEncryptionService } from '@open-mercato/shared/lib/encryption/tenantDataEncryptionService'\n\nfunction resolveVectorService(container: AwilixContainer): VectorIndexService | null {\n try {\n return container.resolve<VectorIndexService>('vectorIndexService')\n } catch {\n return null\n }\n}\n\nfunction resolveEncryptionService(container: AwilixContainer): TenantDataEncryptionService | null {\n try {\n return container.resolve<TenantDataEncryptionService>('tenantEncryptionService')\n } catch {\n return null\n }\n}\n\nasync function ensureVectorSearchEncryptionMap(\n em: EntityManager,\n tenantId: string,\n organizationId: string | null,\n): Promise<boolean> {\n const spec = DEFAULT_ENCRYPTION_MAPS.find((entry) => entry.entityId === 'vector:vector_search')\n const required = spec?.fields ?? []\n if (!required.length) return false\n\n const repo = em.getRepository(EncryptionMap)\n const existing = await repo.findOne({\n entityId: 'vector:vector_search',\n tenantId,\n organizationId,\n deletedAt: null,\n })\n\n if (!existing) {\n em.persist(\n em.create(EncryptionMap, {\n entityId: 'vector:vector_search',\n tenantId,\n organizationId,\n fieldsJson: required,\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n }),\n )\n await em.flush()\n return true\n }\n\n const existingFields = Array.isArray(existing.fieldsJson) ? existing.fieldsJson : []\n const byField = new Map<string, { field: string; hashField?: string | null }>()\n for (const item of existingFields) {\n if (!item?.field) continue\n byField.set(item.field, item)\n }\n for (const req of required) {\n if (!req?.field) continue\n if (byField.has(req.field)) continue\n byField.set(req.field, req)\n }\n\n const merged = Array.from(byField.values())\n const changed = merged.length !== existingFields.length\n if (!changed && existing.isActive) return false\n\n existing.fieldsJson = merged\n existing.isActive = true\n existing.updatedAt = new Date()\n await em.flush()\n return true\n}\n\nexport type UpgradeActionContext = {\n tenantId: string\n organizationId: string\n container: AwilixContainer\n em: EntityManager\n}\n\nexport type UpgradeActionDefinition = {\n id: string\n version: string\n messageKey: string\n ctaKey: string\n successKey: string\n loadingKey?: string\n run: (ctx: UpgradeActionContext) => Promise<void>\n}\n\n/**\n * Compare two semantic version strings.\n * Uses the semver library for robust version comparison.\n * Returns negative if a < b, positive if a > b, 0 if equal.\n * Throws an error if either version string is invalid.\n */\nexport function compareVersions(a: string, b: string): number {\n const cleanA = semver.valid(semver.coerce(a))\n const cleanB = semver.valid(semver.coerce(b))\n if (!cleanA) {\n throw new Error(`Invalid version string: \"${a}\". Expected a valid semver format (e.g., \"1.2.3\").`)\n }\n if (!cleanB) {\n throw new Error(`Invalid version string: \"${b}\". Expected a valid semver format (e.g., \"1.2.3\").`)\n }\n return semver.compare(cleanA, cleanB)\n}\n\nasync function purgeCatalogCrudCache(container: AwilixContainer, tenantId: string | null) {\n if (!isCrudCacheEnabled()) return\n const cache = resolveCrudCache(container)\n if (!cache) return\n await runWithCacheTenant(tenantId ?? null, async () => {\n const stats = await collectCrudCacheStats(cache)\n const catalogSegments = stats.segments.filter((segment) => segment.resource?.startsWith('catalog.'))\n if (!catalogSegments.length) return\n for (const segment of catalogSegments) {\n try {\n await purgeCrudCacheSegment(cache, segment.segment)\n } catch (error) {\n console.warn('[upgrade-actions] failed to purge catalog cache segment', {\n tenantId,\n segment: segment.segment,\n error,\n })\n }\n }\n })\n}\n\nexport const upgradeActions: UpgradeActionDefinition[] = [\n {\n id: 'configs.upgrades.catalog.examples',\n version: '0.3.4',\n messageKey: 'upgrades.v034.message',\n ctaKey: 'upgrades.v034.cta',\n successKey: 'upgrades.v034.success',\n loadingKey: 'upgrades.v034.loading',\n async run({ container, em, tenantId, organizationId }) {\n let installExampleCatalogData: typeof import('@open-mercato/core/modules/catalog/lib/seeds')['installExampleCatalogData'] | undefined\n try {\n const catalogSeeds = await import('@open-mercato/core/modules/catalog/lib/seeds')\n installExampleCatalogData = catalogSeeds.installExampleCatalogData\n } catch {\n console.warn('[upgrade-actions] catalog module not available, skipping catalog example data')\n return\n }\n await installExampleCatalogData(container, { tenantId, organizationId }, em)\n const vectorService = resolveVectorService(container)\n await reindexModules(em, ['catalog'], { tenantId, organizationId, vectorService })\n },\n },\n {\n id: 'configs.upgrades.auth.admin_business_rules_acl',\n version: '0.3.5',\n messageKey: 'upgrades.v035.message',\n ctaKey: 'upgrades.v035.cta',\n successKey: 'upgrades.v035.success',\n loadingKey: 'upgrades.v035.loading',\n async run({ container, em, tenantId }) {\n const normalizedTenantId = tenantId.trim()\n await em.transactional(async (tem) => {\n const adminRole = await tem.findOne(Role, { name: 'admin', tenantId: normalizedTenantId, deletedAt: null })\n if (!adminRole) return\n\n const roleAcls = await tem.find(RoleAcl, { role: adminRole, tenantId: normalizedTenantId, deletedAt: null })\n let touched = false\n if (!roleAcls.length) {\n tem.persist(\n tem.create(RoleAcl, {\n role: adminRole,\n tenantId: normalizedTenantId,\n featuresJson: ['business_rules.*'],\n isSuperAdmin: false,\n createdAt: new Date(),\n updatedAt: new Date(),\n }),\n )\n touched = true\n }\n\n for (const acl of roleAcls) {\n const features = Array.isArray(acl.featuresJson) ? [...acl.featuresJson] : []\n if (features.includes('business_rules.*')) continue\n acl.featuresJson = [...features, 'business_rules.*']\n acl.updatedAt = new Date()\n touched = true\n }\n\n if (touched) {\n await tem.flush()\n }\n })\n\n const rbac = container.resolve<RbacService>('rbacService')\n await rbac.invalidateTenantCache(normalizedTenantId)\n },\n },\n {\n id: 'configs.upgrades.sales.examples',\n version: '0.3.6',\n messageKey: 'upgrades.v036.message',\n ctaKey: 'upgrades.v036.cta',\n successKey: 'upgrades.v036.success',\n loadingKey: 'upgrades.v036.loading',\n async run({ container, em, tenantId, organizationId }) {\n let seedSalesExamples: typeof import('@open-mercato/core/modules/sales/seed/examples')['seedSalesExamples'] | undefined\n try {\n const salesSeeds = await import('@open-mercato/core/modules/sales/seed/examples')\n seedSalesExamples = salesSeeds.seedSalesExamples\n } catch {\n console.warn('[upgrade-actions] sales module not available, skipping sales example data')\n return\n }\n await em.transactional(async (tem) => {\n await seedSalesExamples!(tem, container, { tenantId, organizationId })\n })\n const vectorService = resolveVectorService(container)\n await reindexModules(em, ['sales', 'catalog'], { tenantId, organizationId, vectorService })\n await purgeCatalogCrudCache(container, tenantId)\n },\n },\n {\n id: 'configs.upgrades.vector.encryption_vector_search',\n version: '0.3.6',\n messageKey: 'upgrades.v036_vector_encryption.message',\n ctaKey: 'upgrades.v036_vector_encryption.cta',\n successKey: 'upgrades.v036_vector_encryption.success',\n loadingKey: 'upgrades.v036_vector_encryption.loading',\n async run({ container, em, tenantId, organizationId }) {\n const normalizedTenantId = tenantId.trim()\n const normalizedOrgId = organizationId ?? null\n\n const encryptionService = resolveEncryptionService(container)\n if (!encryptionService?.isEnabled?.()) {\n return\n }\n\n const updated = await em.transactional(async (tem) => {\n return ensureVectorSearchEncryptionMap(tem, normalizedTenantId, normalizedOrgId)\n })\n\n if (updated) {\n await encryptionService.invalidateMap('vector:vector_search', normalizedTenantId, normalizedOrgId)\n }\n\n const vectorService = resolveVectorService(container)\n if (vectorService) {\n await vectorService.reindexAll({ tenantId: normalizedTenantId, organizationId: normalizedOrgId, purgeFirst: false })\n }\n },\n },\n {\n id: 'configs.upgrades.examples.currencies_workflows',\n version: '0.3.13',\n messageKey: 'upgrades.v0313.message',\n ctaKey: 'upgrades.v0313.cta',\n successKey: 'upgrades.v0313.success',\n loadingKey: 'upgrades.v0313.loading',\n async run({ container, em, tenantId, organizationId }) {\n const normalizedTenantId = tenantId.trim()\n const scope = { tenantId, organizationId }\n\n let seedExampleCurrencies: typeof import('@open-mercato/core/modules/currencies/lib/seeds')['seedExampleCurrencies'] | undefined\n try {\n const currenciesSeeds = await import('@open-mercato/core/modules/currencies/lib/seeds')\n seedExampleCurrencies = currenciesSeeds.seedExampleCurrencies\n } catch {\n console.warn('[upgrade-actions] currencies module not available, skipping currency seeding')\n }\n\n let seedExampleWorkflows: typeof import('@open-mercato/core/modules/workflows/lib/seeds')['seedExampleWorkflows'] | undefined\n try {\n const workflowsSeeds = await import('@open-mercato/core/modules/workflows/lib/seeds')\n seedExampleWorkflows = workflowsSeeds.seedExampleWorkflows\n } catch {\n console.warn('[upgrade-actions] workflows module not available, skipping workflow seeding')\n }\n\n await em.transactional(async (tem) => {\n if (seedExampleCurrencies) await seedExampleCurrencies(tem, scope)\n if (seedExampleWorkflows) await seedExampleWorkflows(tem, scope)\n\n const adminRole = await tem.findOne(Role, { name: 'admin', tenantId: normalizedTenantId, deletedAt: null })\n if (!adminRole) return\n\n const roleAcls = await tem.find(RoleAcl, { role: adminRole, tenantId: normalizedTenantId, deletedAt: null })\n let touched = false\n if (!roleAcls.length) {\n tem.persist(\n tem.create(RoleAcl, {\n role: adminRole,\n tenantId: normalizedTenantId,\n featuresJson: ['search.*', 'feature_toggles.*', 'currencies.*'],\n isSuperAdmin: false,\n createdAt: new Date(),\n updatedAt: new Date(),\n }),\n )\n touched = true\n }\n\n for (const acl of roleAcls) {\n const features = Array.isArray(acl.featuresJson) ? [...acl.featuresJson] : []\n const nextFeatures = new Set(features)\n nextFeatures.add('search.*')\n nextFeatures.add('feature_toggles.*')\n nextFeatures.add('currencies.*')\n if (nextFeatures.size === features.length) continue\n acl.featuresJson = Array.from(nextFeatures)\n acl.updatedAt = new Date()\n touched = true\n }\n\n if (touched) {\n await tem.flush()\n }\n })\n const rbac = container.resolve<RbacService>('rbacService')\n await rbac.invalidateTenantCache(normalizedTenantId)\n },\n },\n {\n id: 'configs.upgrades.examples.planner_staff_resources',\n version: '0.4.1',\n messageKey: 'upgrades.v041.message',\n ctaKey: 'upgrades.v041.cta',\n successKey: 'upgrades.v041.success',\n loadingKey: 'upgrades.v041.loading',\n async run({ container, em, tenantId, organizationId }) {\n const normalizedTenantId = tenantId.trim()\n const scope = { tenantId, organizationId }\n\n let seedPlannerAvailabilityRuleSetDefaults: typeof import('@open-mercato/core/modules/planner/lib/seeds')['seedPlannerAvailabilityRuleSetDefaults'] | undefined\n let seedPlannerUnavailabilityReasons: typeof import('@open-mercato/core/modules/planner/lib/seeds')['seedPlannerUnavailabilityReasons'] | undefined\n try {\n const plannerSeeds = await import('@open-mercato/core/modules/planner/lib/seeds')\n seedPlannerAvailabilityRuleSetDefaults = plannerSeeds.seedPlannerAvailabilityRuleSetDefaults\n seedPlannerUnavailabilityReasons = plannerSeeds.seedPlannerUnavailabilityReasons\n } catch {\n console.warn('[upgrade-actions] planner module not available, skipping planner seeding')\n }\n\n let seedStaffTeamExamples: typeof import('@open-mercato/core/modules/staff/lib/seeds')['seedStaffTeamExamples'] | undefined\n try {\n const staffSeeds = await import('@open-mercato/core/modules/staff/lib/seeds')\n seedStaffTeamExamples = staffSeeds.seedStaffTeamExamples\n } catch {\n console.warn('[upgrade-actions] staff module not available, skipping staff seeding')\n }\n\n let seedResourcesAddressTypes: typeof import('@open-mercato/core/modules/resources/lib/seeds')['seedResourcesAddressTypes'] | undefined\n let seedResourcesCapacityUnits: typeof import('@open-mercato/core/modules/resources/lib/seeds')['seedResourcesCapacityUnits'] | undefined\n let seedResourcesResourceExamples: typeof import('@open-mercato/core/modules/resources/lib/seeds')['seedResourcesResourceExamples'] | undefined\n try {\n const resourcesSeeds = await import('@open-mercato/core/modules/resources/lib/seeds')\n seedResourcesAddressTypes = resourcesSeeds.seedResourcesAddressTypes\n seedResourcesCapacityUnits = resourcesSeeds.seedResourcesCapacityUnits\n seedResourcesResourceExamples = resourcesSeeds.seedResourcesResourceExamples\n } catch {\n console.warn('[upgrade-actions] resources module not available, skipping resources seeding')\n }\n\n await em.transactional(async (tem) => {\n if (seedPlannerAvailabilityRuleSetDefaults) await seedPlannerAvailabilityRuleSetDefaults(tem, scope)\n if (seedPlannerUnavailabilityReasons) await seedPlannerUnavailabilityReasons(tem, scope)\n if (seedStaffTeamExamples) await seedStaffTeamExamples(tem, scope)\n if (seedResourcesCapacityUnits) await seedResourcesCapacityUnits(tem, scope)\n if (seedResourcesAddressTypes) await seedResourcesAddressTypes(tem, scope)\n if (seedResourcesResourceExamples) await seedResourcesResourceExamples(tem, scope)\n\n const adminRole = await tem.findOne(Role, { name: 'admin', tenantId: normalizedTenantId, deletedAt: null })\n if (!adminRole) return\n\n const roleAcls = await tem.find(RoleAcl, { role: adminRole, tenantId: normalizedTenantId, deletedAt: null })\n const addedFeatures = [\n 'staff.*',\n 'staff.leave_requests.manage',\n 'resources.*',\n 'planner.*',\n ]\n let touched = false\n if (!roleAcls.length) {\n tem.persist(\n tem.create(RoleAcl, {\n role: adminRole,\n tenantId: normalizedTenantId,\n featuresJson: addedFeatures,\n isSuperAdmin: false,\n createdAt: new Date(),\n updatedAt: new Date(),\n }),\n )\n touched = true\n }\n\n for (const acl of roleAcls) {\n const features = Array.isArray(acl.featuresJson) ? [...acl.featuresJson] : []\n const nextFeatures = new Set(features)\n for (const feature of addedFeatures) nextFeatures.add(feature)\n if (nextFeatures.size === features.length) continue\n acl.featuresJson = Array.from(nextFeatures)\n acl.updatedAt = new Date()\n touched = true\n }\n\n if (touched) {\n await tem.flush()\n }\n })\n\n const rbac = container.resolve<RbacService>('rbacService')\n await rbac.invalidateTenantCache(normalizedTenantId)\n\n const vectorService = resolveVectorService(container)\n await reindexModules(em, ['planner', 'staff', 'resources'], { tenantId, organizationId, vectorService })\n },\n },\n]\n\nexport function actionsUpToVersion(version: string): UpgradeActionDefinition[] {\n return upgradeActions\n .filter((action) => compareVersions(action.version, version) <= 0)\n .sort((a, b) => compareVersions(a.version, b.version) || a.id.localeCompare(b.id))\n}\n\nexport function findUpgradeAction(actionId: string, maxVersion: string): UpgradeActionDefinition | undefined {\n const matches = actionsUpToVersion(maxVersion).filter((action) => action.id === actionId)\n if (!matches.length) return undefined\n return matches[matches.length - 1]\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport * as semver from 'semver'\nimport { getModules } from '@open-mercato/shared/lib/modules/registry'\nimport type { Module } from '@open-mercato/shared/modules/registry'\nimport type { AppContainer } from '@open-mercato/shared/lib/di/container'\nimport { Role, RoleAcl } from '@open-mercato/core/modules/auth/data/entities'\nimport { normalizeTenantId } from '@open-mercato/core/modules/auth/lib/tenantAccess'\n\nexport type UpgradeActionContext = {\n tenantId: string\n organizationId: string\n container: AppContainer\n em: EntityManager\n}\n\nexport type UpgradeActionDefinition = {\n id: string\n version: string\n messageKey: string\n ctaKey: string\n successKey: string\n loadingKey?: string\n run: (ctx: UpgradeActionContext) => Promise<void>\n}\n\n/**\n * Compare two semantic version strings.\n * Uses the semver library for robust version comparison.\n * Returns negative if a < b, positive if a > b, 0 if equal.\n * Throws an error if either version string is invalid.\n */\nexport function compareVersions(a: string, b: string): number {\n const cleanA = semver.valid(semver.coerce(a))\n const cleanB = semver.valid(semver.coerce(b))\n if (!cleanA) {\n throw new Error(`Invalid version string: \"${a}\". Expected a valid semver format (e.g., \"1.2.3\").`)\n }\n if (!cleanB) {\n throw new Error(`Invalid version string: \"${b}\". Expected a valid semver format (e.g., \"1.2.3\").`)\n }\n return semver.compare(cleanA, cleanB)\n}\n\ntype RoleName = 'superadmin' | 'admin' | 'employee'\n\nfunction collectRoleFeatures(modules: Module[], moduleIds: string[]): Record<RoleName, string[]> {\n const result: Record<RoleName, string[]> = {\n superadmin: [],\n admin: [],\n employee: [],\n }\n const targetIds = new Set(moduleIds)\n for (const mod of modules) {\n if (!targetIds.has(mod.id)) continue\n const roleFeatures = mod.setup?.defaultRoleFeatures\n if (roleFeatures?.superadmin) result.superadmin.push(...roleFeatures.superadmin)\n if (roleFeatures?.admin) result.admin.push(...roleFeatures.admin)\n if (roleFeatures?.employee) result.employee.push(...roleFeatures.employee)\n }\n result.superadmin = Array.from(new Set(result.superadmin))\n result.admin = Array.from(new Set(result.admin))\n result.employee = Array.from(new Set(result.employee))\n return result\n}\n\nasync function findRoleByName(\n em: EntityManager,\n name: string,\n tenantId: string | null,\n): Promise<Role | null> {\n const normalizedTenant = normalizeTenantId(tenantId ?? null) ?? null\n let role = await em.findOne(Role, { name, tenantId: normalizedTenant })\n if (!role && normalizedTenant !== null) {\n role = await em.findOne(Role, { name, tenantId: null })\n }\n return role\n}\n\nasync function ensureRoleAclFor(\n em: EntityManager,\n role: Role,\n tenantId: string,\n features: string[],\n options: { isSuperAdmin?: boolean } = {},\n) {\n const existing = await em.findOne(RoleAcl, { role, tenantId })\n if (!existing) {\n const acl = em.create(RoleAcl, {\n role,\n tenantId,\n featuresJson: features,\n isSuperAdmin: !!options.isSuperAdmin,\n createdAt: new Date(),\n })\n await em.persistAndFlush(acl)\n return\n }\n const currentFeatures = Array.isArray(existing.featuresJson) ? existing.featuresJson : []\n const merged = Array.from(new Set([...currentFeatures, ...features]))\n const changed =\n merged.length !== currentFeatures.length ||\n merged.some((value, index) => value !== currentFeatures[index])\n if (changed) existing.featuresJson = merged\n if (options.isSuperAdmin && !existing.isSuperAdmin) {\n existing.isSuperAdmin = true\n }\n if (changed || options.isSuperAdmin) {\n await em.persistAndFlush(existing)\n }\n}\n\nasync function ensureRoleAclsForModules(\n em: EntityManager,\n tenantId: string,\n moduleIds: string[],\n) {\n const modules = getModules()\n const roleFeatures = collectRoleFeatures(modules, moduleIds)\n if (!roleFeatures.superadmin.length && !roleFeatures.admin.length && !roleFeatures.employee.length) {\n return\n }\n const normalizedTenant = normalizeTenantId(tenantId) ?? null\n const [superadminRole, adminRole, employeeRole] = await Promise.all([\n findRoleByName(em, 'superadmin', normalizedTenant),\n findRoleByName(em, 'admin', normalizedTenant),\n findRoleByName(em, 'employee', normalizedTenant),\n ])\n if (superadminRole && roleFeatures.superadmin.length) {\n await ensureRoleAclFor(em, superadminRole, tenantId, roleFeatures.superadmin, { isSuperAdmin: true })\n }\n if (adminRole && roleFeatures.admin.length) {\n await ensureRoleAclFor(em, adminRole, tenantId, roleFeatures.admin)\n }\n if (employeeRole && roleFeatures.employee.length) {\n await ensureRoleAclFor(em, employeeRole, tenantId, roleFeatures.employee)\n }\n}\n\nasync function safeImport<T>(label: string, loader: () => Promise<T>): Promise<T | null> {\n try {\n return await loader()\n } catch (error) {\n console.warn(`[upgrade-actions] Skipping ${label} because module import failed.`, error)\n return null\n }\n}\n\nexport const upgradeActions: UpgradeActionDefinition[] = [\n {\n id: 'configs.upgrades.catalog.examples',\n version: '0.3.4',\n messageKey: 'upgrades.v034.message',\n ctaKey: 'upgrades.v034.cta',\n successKey: 'upgrades.v034.success',\n loadingKey: 'upgrades.v034.loading',\n async run(ctx) {\n const catalogSeeds = await safeImport('catalog examples', () =>\n import('@open-mercato/core/modules/catalog/lib/seeds')\n )\n if (!catalogSeeds?.installExampleCatalogData) return\n await catalogSeeds.installExampleCatalogData(\n ctx.container,\n { tenantId: ctx.tenantId, organizationId: ctx.organizationId },\n ctx.em,\n )\n },\n },\n {\n id: 'configs.upgrades.sales.examples',\n version: '0.3.6',\n messageKey: 'upgrades.v036.message',\n ctaKey: 'upgrades.v036.cta',\n successKey: 'upgrades.v036.success',\n loadingKey: 'upgrades.v036.loading',\n async run(ctx) {\n const salesSeeds = await safeImport('sales examples', () =>\n import('@open-mercato/core/modules/sales/seed/examples')\n )\n if (!salesSeeds?.seedSalesExamples) return\n await salesSeeds.seedSalesExamples(ctx.em, ctx.container, {\n tenantId: ctx.tenantId,\n organizationId: ctx.organizationId,\n })\n },\n },\n {\n id: 'configs.upgrades.examples.currencies_workflows',\n version: '0.3.13',\n messageKey: 'upgrades.v0313.message',\n ctaKey: 'upgrades.v0313.cta',\n successKey: 'upgrades.v0313.success',\n loadingKey: 'upgrades.v0313.loading',\n async run(ctx) {\n const currenciesSeeds = await safeImport('currencies examples', () =>\n import('@open-mercato/core/modules/currencies/lib/seeds')\n )\n const workflowsSeeds = await safeImport('workflows examples', () =>\n import('@open-mercato/core/modules/workflows/lib/seeds')\n )\n const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId }\n if (currenciesSeeds?.seedExampleCurrencies) {\n await currenciesSeeds.seedExampleCurrencies(ctx.em, scope)\n }\n if (workflowsSeeds?.seedExampleWorkflows) {\n await workflowsSeeds.seedExampleWorkflows(ctx.em, scope)\n }\n await ensureRoleAclsForModules(ctx.em, ctx.tenantId, ['currencies', 'workflows'])\n },\n },\n {\n id: 'configs.upgrades.examples.planner_staff_resources',\n version: '0.4.1',\n messageKey: 'upgrades.v041.message',\n ctaKey: 'upgrades.v041.cta',\n successKey: 'upgrades.v041.success',\n loadingKey: 'upgrades.v041.loading',\n async run(ctx) {\n const plannerSeeds = await safeImport('planner examples', () =>\n import('@open-mercato/core/modules/planner/lib/seeds')\n )\n const staffSeeds = await safeImport('staff examples', () =>\n import('@open-mercato/core/modules/staff/lib/seeds')\n )\n const resourcesSeeds = await safeImport('resources examples', () =>\n import('@open-mercato/core/modules/resources/lib/seeds')\n )\n const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId }\n if (plannerSeeds?.seedPlannerAvailabilityRuleSetDefaults) {\n await plannerSeeds.seedPlannerAvailabilityRuleSetDefaults(ctx.em, scope)\n }\n if (staffSeeds?.seedStaffTeamExamples) {\n await staffSeeds.seedStaffTeamExamples(ctx.em, scope)\n }\n if (resourcesSeeds?.seedResourcesResourceExamples) {\n await resourcesSeeds.seedResourcesResourceExamples(ctx.em, scope)\n }\n await ensureRoleAclsForModules(ctx.em, ctx.tenantId, ['planner', 'staff', 'resources'])\n },\n },\n]\n\nexport function actionsUpToVersion(version: string): UpgradeActionDefinition[] {\n return upgradeActions\n .filter((action) => compareVersions(action.version, version) <= 0)\n .sort((a, b) => compareVersions(a.version, b.version) || a.id.localeCompare(b.id))\n}\n\nexport function findUpgradeAction(actionId: string, maxVersion: string): UpgradeActionDefinition | undefined {\n const matches = actionsUpToVersion(maxVersion).filter((action) => action.id === actionId)\n if (!matches.length) return undefined\n return matches[matches.length - 1]\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|