@open-mercato/core 0.4.2-canary-3b5064ce72 → 0.4.2-canary-7732371765
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.ids.generated.js +1 -5
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +0 -2
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/api_docs/frontend/docs/api/page.js +2 -3
- 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 +0 -4
- package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentPartitionSettings.js +0 -2
- package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
- package/dist/modules/auth/api/admin/nav.js +3 -4
- package/dist/modules/auth/api/admin/nav.js.map +2 -2
- package/dist/modules/auth/api/login.js +6 -25
- package/dist/modules/auth/api/login.js.map +2 -2
- package/dist/modules/auth/api/reset/confirm.js +2 -25
- package/dist/modules/auth/api/reset/confirm.js.map +2 -2
- package/dist/modules/auth/api/reset.js +0 -23
- package/dist/modules/auth/api/reset.js.map +2 -2
- package/dist/modules/auth/api/sidebar/preferences/route.js +9 -14
- package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +2 -4
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/backend/roles/[id]/edit/page.js +1 -4
- 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 +3 -18
- package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
- package/dist/modules/auth/backend/users/create/page.js +2 -15
- 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 +11 -25
- package/dist/modules/auth/cli.js.map +2 -2
- package/dist/modules/auth/commands/users.js +2 -59
- package/dist/modules/auth/commands/users.js.map +2 -2
- package/dist/modules/auth/data/validators.js +3 -6
- package/dist/modules/auth/data/validators.js.map +2 -2
- package/dist/modules/auth/frontend/login.js +3 -112
- package/dist/modules/auth/frontend/login.js.map +2 -2
- package/dist/modules/auth/frontend/reset/[token]/page.js +10 -20
- package/dist/modules/auth/frontend/reset/[token]/page.js.map +2 -2
- package/dist/modules/auth/lib/setup-app.js +8 -42
- package/dist/modules/auth/lib/setup-app.js.map +2 -2
- package/dist/modules/auth/services/authService.js +3 -24
- package/dist/modules/auth/services/authService.js.map +2 -2
- package/dist/modules/business_rules/api/execute/route.js +1 -7
- package/dist/modules/business_rules/api/execute/route.js.map +2 -2
- package/dist/modules/business_rules/backend/rules/page.js +0 -4
- package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
- package/dist/modules/business_rules/backend/sets/page.js +0 -3
- package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
- package/dist/modules/business_rules/cli.js +1 -2
- package/dist/modules/business_rules/cli.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-engine.js +3 -33
- package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
- package/dist/modules/catalog/components/PriceKindSettings.js +0 -2
- 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 +0 -2
- package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
- package/dist/modules/configs/cli.js +0 -6
- 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 +1 -48
- package/dist/modules/configs/lib/system-status.js.map +2 -2
- package/dist/modules/configs/lib/upgrade-actions.js +0 -18
- package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
- package/dist/modules/currencies/backend/currencies/page.js +0 -3
- package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
- package/dist/modules/currencies/backend/exchange-rates/page.js +0 -2
- package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/page.js +0 -3
- package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/page.js +0 -3
- package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/page.js +0 -3
- package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +0 -31
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/components/CustomerTodosTable.js +0 -1
- package/dist/modules/customers/components/CustomerTodosTable.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/customer-todos/widget.js +1 -2
- package/dist/modules/customers/widgets/dashboard/customer-todos/widget.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/new-customers/widget.js +1 -2
- package/dist/modules/customers/widgets/dashboard/new-customers/widget.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/new-deals/widget.js +1 -2
- package/dist/modules/customers/widgets/dashboard/new-deals/widget.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/next-interactions/widget.js +1 -2
- package/dist/modules/customers/widgets/dashboard/next-interactions/widget.js.map +2 -2
- package/dist/modules/dashboards/cli.js +5 -44
- package/dist/modules/dashboards/cli.js.map +2 -2
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +11 -16
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +3 -3
- package/dist/modules/dashboards/services/widgetDataService.js +3 -139
- package/dist/modules/dashboards/services/widgetDataService.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.js +1 -2
- package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.js +1 -2
- 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 +1 -2
- package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.js +1 -2
- package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js +1 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.js +1 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.js +1 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.js +1 -2
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.js +1 -2
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.js +1 -2
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.js.map +2 -2
- package/dist/modules/dictionaries/components/DictionaryTable.js +0 -2
- package/dist/modules/dictionaries/components/DictionaryTable.js.map +2 -2
- 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/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 +7 -63
- package/dist/modules/query_index/cli.js.map +2 -2
- package/dist/modules/query_index/components/QueryIndexesTable.js +1 -7
- 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 +0 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.js +0 -2
- package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +0 -53
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/commands/payments.js +0 -26
- 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 +0 -2
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
- package/dist/modules/sales/components/documents/AdjustmentsSection.js +0 -2
- package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/PaymentsSection.js +1 -2
- package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js +0 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
- 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 +0 -79
- package/dist/modules/staff/commands/leave-requests.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/page.js +0 -5
- package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
- package/dist/modules/workflows/backend/instances/page.js +0 -3
- package/dist/modules/workflows/backend/instances/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/page.js +0 -3
- 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 +6 -14
- package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
- package/generated/entities.ids.generated.ts +1 -5
- package/generated/entity-fields-registry.ts +0 -2
- package/package.json +2 -2
- package/src/modules/api_docs/frontend/docs/api/page.tsx +2 -3
- package/src/modules/api_keys/backend/api-keys/page.tsx +1 -1
- package/src/modules/attachments/components/AttachmentLibrary.tsx +0 -4
- package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +0 -2
- 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 +0 -2
- package/src/modules/auth/api/admin/nav.ts +6 -10
- package/src/modules/auth/api/login.ts +7 -26
- package/src/modules/auth/api/reset/confirm.ts +2 -25
- package/src/modules/auth/api/reset.ts +0 -23
- package/src/modules/auth/api/sidebar/preferences/route.ts +12 -21
- package/src/modules/auth/api/users/route.ts +2 -5
- package/src/modules/auth/backend/roles/[id]/edit/page.tsx +1 -4
- package/src/modules/auth/backend/roles/page.tsx +3 -3
- package/src/modules/auth/backend/users/[id]/edit/page.tsx +3 -22
- package/src/modules/auth/backend/users/create/page.tsx +2 -19
- package/src/modules/auth/backend/users/page.tsx +3 -3
- package/src/modules/auth/cli.ts +11 -38
- package/src/modules/auth/commands/users.ts +2 -73
- package/src/modules/auth/data/validators.ts +2 -6
- package/src/modules/auth/frontend/login.tsx +5 -134
- package/src/modules/auth/frontend/reset/[token]/page.tsx +11 -24
- package/src/modules/auth/i18n/de.json +1 -48
- package/src/modules/auth/i18n/en.json +1 -48
- package/src/modules/auth/i18n/es.json +1 -48
- package/src/modules/auth/i18n/pl.json +1 -48
- package/src/modules/auth/lib/setup-app.ts +9 -58
- package/src/modules/auth/services/authService.ts +4 -27
- package/src/modules/business_rules/api/execute/route.ts +1 -8
- package/src/modules/business_rules/backend/rules/page.tsx +0 -4
- package/src/modules/business_rules/backend/sets/page.tsx +0 -3
- package/src/modules/business_rules/cli.ts +1 -2
- package/src/modules/business_rules/i18n/en.json +1 -3
- package/src/modules/business_rules/lib/__tests__/rule-engine.test.ts +0 -51
- package/src/modules/business_rules/lib/rule-engine.ts +3 -57
- package/src/modules/catalog/components/PriceKindSettings.tsx +0 -2
- package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +2 -2
- package/src/modules/catalog/components/products/ProductsDataTable.tsx +0 -2
- package/src/modules/catalog/i18n/en.json +1 -3
- package/src/modules/configs/cli.ts +0 -6
- package/src/modules/configs/components/CachePanel.tsx +4 -4
- package/src/modules/configs/i18n/en.json +2 -12
- package/src/modules/configs/i18n/pl.json +2 -12
- package/src/modules/configs/lib/system-status.ts +1 -48
- package/src/modules/configs/lib/system-status.types.ts +0 -1
- package/src/modules/configs/lib/upgrade-actions.ts +0 -18
- package/src/modules/currencies/backend/currencies/page.tsx +0 -3
- package/src/modules/currencies/backend/exchange-rates/page.tsx +0 -2
- package/src/modules/customers/backend/customers/companies/page.tsx +0 -3
- package/src/modules/customers/backend/customers/deals/page.tsx +0 -3
- package/src/modules/customers/backend/customers/people/page.tsx +0 -3
- package/src/modules/customers/commands/deals.ts +0 -39
- package/src/modules/customers/components/CustomerTodosTable.tsx +0 -1
- package/src/modules/customers/i18n/en.json +1 -5
- 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 +5 -55
- package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +11 -22
- package/src/modules/dashboards/services/widgetDataService.ts +4 -164
- 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 +0 -2
- 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 +4 -3
- package/src/modules/feature_toggles/components/OverridesTable.tsx +1 -1
- package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +2 -2
- package/src/modules/query_index/cli.ts +13 -82
- package/src/modules/query_index/components/QueryIndexesTable.tsx +2 -8
- 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 +0 -2
- package/src/modules/sales/backend/sales/channels/page.tsx +0 -2
- package/src/modules/sales/commands/documents.ts +0 -65
- package/src/modules/sales/commands/payments.ts +0 -33
- 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 +0 -2
- package/src/modules/sales/components/documents/AdjustmentsSection.tsx +0 -2
- package/src/modules/sales/components/documents/PaymentsSection.tsx +1 -2
- package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +0 -2
- package/src/modules/sales/i18n/de.json +0 -20
- package/src/modules/sales/i18n/en.json +1 -25
- package/src/modules/sales/i18n/es.json +0 -20
- package/src/modules/sales/i18n/pl.json +0 -20
- 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 +0 -94
- package/src/modules/staff/i18n/de.json +0 -4
- package/src/modules/staff/i18n/en.json +1 -9
- package/src/modules/staff/i18n/es.json +0 -4
- package/src/modules/staff/i18n/pl.json +0 -4
- package/src/modules/workflows/backend/definitions/page.tsx +0 -5
- package/src/modules/workflows/backend/instances/page.tsx +1 -4
- package/src/modules/workflows/backend/tasks/page.tsx +1 -4
- package/src/modules/workflows/cli.ts +12 -12
- package/src/modules/workflows/i18n/en.json +1 -3
- package/src/modules/workflows/lib/transition-handler.ts +6 -18
- package/dist/generated/entities/notification/index.js +0 -57
- package/dist/generated/entities/notification/index.js.map +0 -7
- package/dist/modules/auth/api/profile/route.js +0 -157
- package/dist/modules/auth/api/profile/route.js.map +0 -7
- package/dist/modules/auth/backend/auth/profile/page.js +0 -141
- package/dist/modules/auth/backend/auth/profile/page.js.map +0 -7
- package/dist/modules/auth/backend/auth/profile/page.meta.js +0 -13
- package/dist/modules/auth/backend/auth/profile/page.meta.js.map +0 -7
- package/dist/modules/auth/notifications.js +0 -112
- package/dist/modules/auth/notifications.js.map +0 -7
- package/dist/modules/business_rules/notifications.js +0 -28
- package/dist/modules/business_rules/notifications.js.map +0 -7
- package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js +0 -37
- package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js.map +0 -7
- package/dist/modules/catalog/notifications.js +0 -28
- package/dist/modules/catalog/notifications.js.map +0 -7
- package/dist/modules/catalog/subscribers/low-stock-notification.js +0 -38
- package/dist/modules/catalog/subscribers/low-stock-notification.js.map +0 -7
- package/dist/modules/customers/notifications.js +0 -48
- package/dist/modules/customers/notifications.js.map +0 -7
- package/dist/modules/dashboards/lib/role-widgets.js +0 -58
- package/dist/modules/dashboards/lib/role-widgets.js.map +0 -7
- package/dist/modules/directory/api/get/tenants/lookup.js +0 -70
- package/dist/modules/directory/api/get/tenants/lookup.js.map +0 -7
- package/dist/modules/notifications/acl.js +0 -11
- package/dist/modules/notifications/acl.js.map +0 -7
- package/dist/modules/notifications/api/[id]/action/route.js +0 -74
- package/dist/modules/notifications/api/[id]/action/route.js.map +0 -7
- package/dist/modules/notifications/api/[id]/dismiss/route.js +0 -15
- package/dist/modules/notifications/api/[id]/dismiss/route.js.map +0 -7
- package/dist/modules/notifications/api/[id]/read/route.js +0 -15
- package/dist/modules/notifications/api/[id]/read/route.js.map +0 -7
- package/dist/modules/notifications/api/[id]/restore/route.js +0 -53
- package/dist/modules/notifications/api/[id]/restore/route.js.map +0 -7
- package/dist/modules/notifications/api/batch/route.js +0 -17
- package/dist/modules/notifications/api/batch/route.js.map +0 -7
- package/dist/modules/notifications/api/feature/route.js +0 -17
- package/dist/modules/notifications/api/feature/route.js.map +0 -7
- package/dist/modules/notifications/api/mark-all-read/route.js +0 -35
- package/dist/modules/notifications/api/mark-all-read/route.js.map +0 -7
- package/dist/modules/notifications/api/openapi.js +0 -76
- package/dist/modules/notifications/api/openapi.js.map +0 -7
- package/dist/modules/notifications/api/role/route.js +0 -17
- package/dist/modules/notifications/api/role/route.js.map +0 -7
- package/dist/modules/notifications/api/route.js +0 -85
- package/dist/modules/notifications/api/route.js.map +0 -7
- package/dist/modules/notifications/api/settings/route.js +0 -155
- package/dist/modules/notifications/api/settings/route.js.map +0 -7
- package/dist/modules/notifications/api/unread-count/route.js +0 -38
- package/dist/modules/notifications/api/unread-count/route.js.map +0 -7
- package/dist/modules/notifications/backend/config/notifications/page.js +0 -10
- package/dist/modules/notifications/backend/config/notifications/page.js.map +0 -7
- package/dist/modules/notifications/backend/config/notifications/page.meta.js +0 -24
- package/dist/modules/notifications/backend/config/notifications/page.meta.js.map +0 -7
- package/dist/modules/notifications/cli.js +0 -16
- package/dist/modules/notifications/cli.js.map +0 -7
- package/dist/modules/notifications/data/entities.js +0 -112
- package/dist/modules/notifications/data/entities.js.map +0 -7
- package/dist/modules/notifications/data/validators.js +0 -98
- package/dist/modules/notifications/data/validators.js.map +0 -7
- package/dist/modules/notifications/di.js +0 -13
- package/dist/modules/notifications/di.js.map +0 -7
- package/dist/modules/notifications/emails/NotificationEmail.js +0 -58
- package/dist/modules/notifications/emails/NotificationEmail.js.map +0 -7
- package/dist/modules/notifications/frontend/NotificationInboxPageClient.js +0 -44
- package/dist/modules/notifications/frontend/NotificationInboxPageClient.js.map +0 -7
- package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js +0 -220
- package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js.map +0 -7
- package/dist/modules/notifications/index.js +0 -14
- package/dist/modules/notifications/index.js.map +0 -7
- package/dist/modules/notifications/lib/deliveryConfig.js +0 -107
- package/dist/modules/notifications/lib/deliveryConfig.js.map +0 -7
- package/dist/modules/notifications/lib/deliveryStrategies.js +0 -14
- package/dist/modules/notifications/lib/deliveryStrategies.js.map +0 -7
- package/dist/modules/notifications/lib/events.js +0 -12
- package/dist/modules/notifications/lib/events.js.map +0 -7
- package/dist/modules/notifications/lib/notificationBuilder.js +0 -66
- package/dist/modules/notifications/lib/notificationBuilder.js.map +0 -7
- package/dist/modules/notifications/lib/notificationFactory.js +0 -54
- package/dist/modules/notifications/lib/notificationFactory.js.map +0 -7
- package/dist/modules/notifications/lib/notificationMapper.js +0 -34
- package/dist/modules/notifications/lib/notificationMapper.js.map +0 -7
- package/dist/modules/notifications/lib/notificationRecipients.js +0 -35
- package/dist/modules/notifications/lib/notificationRecipients.js.map +0 -7
- package/dist/modules/notifications/lib/notificationService.js +0 -279
- package/dist/modules/notifications/lib/notificationService.js.map +0 -7
- package/dist/modules/notifications/lib/routeHelpers.js +0 -101
- package/dist/modules/notifications/lib/routeHelpers.js.map +0 -7
- package/dist/modules/notifications/lib/safeHref.js +0 -24
- package/dist/modules/notifications/lib/safeHref.js.map +0 -7
- package/dist/modules/notifications/migrations/Migration20260123000001.js +0 -70
- package/dist/modules/notifications/migrations/Migration20260123000001.js.map +0 -7
- package/dist/modules/notifications/migrations/Migration20260126150000.js +0 -37
- package/dist/modules/notifications/migrations/Migration20260126150000.js.map +0 -7
- package/dist/modules/notifications/migrations/Migration20260129082610.js +0 -13
- package/dist/modules/notifications/migrations/Migration20260129082610.js.map +0 -7
- package/dist/modules/notifications/subscribers/deliver-notification.js +0 -165
- package/dist/modules/notifications/subscribers/deliver-notification.js.map +0 -7
- package/dist/modules/notifications/workers/create-notification.worker.js +0 -70
- package/dist/modules/notifications/workers/create-notification.worker.js.map +0 -7
- package/dist/modules/sales/notifications.client.js +0 -51
- package/dist/modules/sales/notifications.client.js.map +0 -7
- package/dist/modules/sales/notifications.js +0 -88
- package/dist/modules/sales/notifications.js.map +0 -7
- package/dist/modules/sales/subscribers/quote-expiring-notification.js +0 -38
- package/dist/modules/sales/subscribers/quote-expiring-notification.js.map +0 -7
- package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js +0 -137
- package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js.map +0 -7
- package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js +0 -137
- package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js.map +0 -7
- package/dist/modules/sales/widgets/notifications/index.js +0 -7
- package/dist/modules/sales/widgets/notifications/index.js.map +0 -7
- package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js +0 -60
- package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js.map +0 -7
- package/dist/modules/staff/notifications.js +0 -75
- package/dist/modules/staff/notifications.js.map +0 -7
- package/dist/modules/workflows/notifications.js +0 -28
- package/dist/modules/workflows/notifications.js.map +0 -7
- package/dist/modules/workflows/subscribers/task-assigned-notification.js +0 -38
- package/dist/modules/workflows/subscribers/task-assigned-notification.js.map +0 -7
- package/generated/entities/notification/index.ts +0 -27
- package/src/modules/auth/api/profile/route.ts +0 -163
- package/src/modules/auth/backend/auth/profile/page.meta.ts +0 -9
- package/src/modules/auth/backend/auth/profile/page.tsx +0 -174
- package/src/modules/auth/notifications.ts +0 -109
- package/src/modules/business_rules/notifications.ts +0 -25
- package/src/modules/business_rules/subscribers/rule-execution-failed-notification.ts +0 -50
- package/src/modules/catalog/notifications.ts +0 -25
- package/src/modules/catalog/subscribers/low-stock-notification.ts +0 -52
- package/src/modules/customers/notifications.ts +0 -44
- package/src/modules/dashboards/lib/role-widgets.ts +0 -80
- package/src/modules/directory/api/get/tenants/lookup.ts +0 -75
- package/src/modules/notifications/__tests__/deliver-notification.test.ts +0 -195
- package/src/modules/notifications/__tests__/deliveryStrategies.test.ts +0 -19
- package/src/modules/notifications/__tests__/notificationService.test.ts +0 -208
- package/src/modules/notifications/acl.ts +0 -7
- package/src/modules/notifications/api/[id]/action/route.ts +0 -75
- package/src/modules/notifications/api/[id]/dismiss/route.ts +0 -12
- package/src/modules/notifications/api/[id]/read/route.ts +0 -12
- package/src/modules/notifications/api/[id]/restore/route.ts +0 -53
- package/src/modules/notifications/api/batch/route.ts +0 -14
- package/src/modules/notifications/api/feature/route.ts +0 -14
- package/src/modules/notifications/api/mark-all-read/route.ts +0 -34
- package/src/modules/notifications/api/openapi.ts +0 -76
- package/src/modules/notifications/api/role/route.ts +0 -14
- package/src/modules/notifications/api/route.ts +0 -92
- package/src/modules/notifications/api/settings/route.ts +0 -157
- package/src/modules/notifications/api/unread-count/route.ts +0 -38
- package/src/modules/notifications/backend/config/notifications/page.meta.ts +0 -22
- package/src/modules/notifications/backend/config/notifications/page.tsx +0 -12
- package/src/modules/notifications/cli.ts +0 -18
- package/src/modules/notifications/data/entities.ts +0 -99
- package/src/modules/notifications/data/validators.ts +0 -115
- package/src/modules/notifications/di.ts +0 -11
- package/src/modules/notifications/emails/NotificationEmail.tsx +0 -98
- package/src/modules/notifications/frontend/NotificationInboxPageClient.tsx +0 -42
- package/src/modules/notifications/frontend/NotificationSettingsPageClient.tsx +0 -233
- package/src/modules/notifications/i18n/de.json +0 -50
- package/src/modules/notifications/i18n/en.json +0 -50
- package/src/modules/notifications/i18n/es.json +0 -50
- package/src/modules/notifications/i18n/pl.json +0 -50
- package/src/modules/notifications/index.ts +0 -12
- package/src/modules/notifications/lib/deliveryConfig.ts +0 -153
- package/src/modules/notifications/lib/deliveryStrategies.ts +0 -50
- package/src/modules/notifications/lib/events.ts +0 -48
- package/src/modules/notifications/lib/notificationBuilder.ts +0 -121
- package/src/modules/notifications/lib/notificationFactory.ts +0 -76
- package/src/modules/notifications/lib/notificationMapper.ts +0 -33
- package/src/modules/notifications/lib/notificationRecipients.ts +0 -83
- package/src/modules/notifications/lib/notificationService.ts +0 -414
- package/src/modules/notifications/lib/routeHelpers.ts +0 -151
- package/src/modules/notifications/lib/safeHref.ts +0 -29
- package/src/modules/notifications/migrations/.snapshot-open-mercato.json +0 -336
- package/src/modules/notifications/migrations/Migration20260123000001.ts +0 -73
- package/src/modules/notifications/migrations/Migration20260126150000.ts +0 -39
- package/src/modules/notifications/migrations/Migration20260129082610.ts +0 -13
- package/src/modules/notifications/subscribers/deliver-notification.ts +0 -204
- package/src/modules/notifications/workers/create-notification.worker.ts +0 -122
- package/src/modules/sales/notifications.client.ts +0 -65
- package/src/modules/sales/notifications.ts +0 -82
- package/src/modules/sales/subscribers/quote-expiring-notification.ts +0 -53
- package/src/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.tsx +0 -156
- package/src/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.tsx +0 -156
- package/src/modules/sales/widgets/notifications/index.ts +0 -2
- package/src/modules/sales/widgets/notifications/useSalesDocumentTotals.ts +0 -81
- package/src/modules/staff/notifications.ts +0 -71
- package/src/modules/workflows/notifications.ts +0 -25
- package/src/modules/workflows/subscribers/task-assigned-notification.ts +0 -53
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/modules/query_index/cli.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ModuleCli } from '@open-mercato/shared/modules/registry'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { Knex } from 'knex'\nimport { createProgressBar } from '@open-mercato/shared/lib/cli/progress'\nimport { resolveTenantEncryptionService } from '@open-mercato/shared/lib/encryption/customFieldValues'\nimport { decryptIndexDocForSearch, encryptIndexDocForStorage } from '@open-mercato/shared/lib/encryption/indexDoc'\nimport { parseBooleanToken } from '@open-mercato/shared/lib/boolean'\n\ntype ProgressBarHandle = {\n update(completed: number): void\n complete(): void\n}\nimport { resolveEntityTableName } from '@open-mercato/shared/lib/query/engine'\nimport { recordIndexerError } from '@open-mercato/shared/lib/indexers/error-log'\nimport { recordIndexerLog } from '@open-mercato/shared/lib/indexers/status-log'\nimport { upsertIndexBatch, type AnyRow } from './lib/batch'\nimport { reindexEntity, DEFAULT_REINDEX_PARTITIONS } from './lib/reindexer'\nimport { purgeIndexScope } from './lib/purge'\nimport { flattenSystemEntityIds } from '@open-mercato/shared/lib/entities/system-entities'\nimport type { VectorIndexService } from '@open-mercato/search/vector'\n\ntype ParsedArgs = Record<string, string | boolean>\n\ntype PartitionProgressInfo = { processed: number; total: number }\n\nfunction isIndexerVerbose(): boolean {\n const parsed = parseBooleanToken(process.env.OM_INDEXER_VERBOSE ?? '')\n return parsed === true\n}\n\nfunction createGroupedProgress(label: string, partitionTargets: number[]) {\n const totals = new Map<number, number>()\n const processed = new Map<number, number>()\n let bar: ProgressBarHandle | null = null\n\n const getTotals = () => {\n let total = 0\n let done = 0\n for (const value of totals.values()) total += value\n for (const value of processed.values()) done += value\n return { total, done }\n }\n\n const tryInitBar = () => {\n if (bar) return\n if (totals.size < partitionTargets.length) return\n const { total } = getTotals()\n if (total <= 0) return\n bar = createProgressBar(label, total) as ProgressBarHandle\n }\n\n return {\n onProgress(partition: number, info: PartitionProgressInfo) {\n processed.set(partition, info.processed)\n if (!totals.has(partition)) totals.set(partition, info.total)\n tryInitBar()\n if (!bar) return\n const { done } = getTotals()\n bar.update(done)\n },\n complete() {\n if (bar) bar.complete()\n },\n getTotals,\n }\n}\n\nfunction parseArgs(rest: string[]): ParsedArgs {\n const args: ParsedArgs = {}\n for (let i = 0; i < rest.length; i += 1) {\n const part = rest[i]\n if (!part?.startsWith('--')) continue\n const [rawKey, rawValue] = part.slice(2).split('=')\n if (!rawKey) continue\n if (rawValue !== undefined) {\n args[rawKey] = rawValue\n } else if (i + 1 < rest.length && !rest[i + 1]!.startsWith('--')) {\n args[rawKey] = rest[i + 1]!\n i += 1\n } else {\n args[rawKey] = true\n }\n }\n return args\n}\n\nfunction stringOption(args: ParsedArgs, ...keys: string[]): string | undefined {\n for (const key of keys) {\n const raw = args[key]\n if (typeof raw !== 'string') continue\n const trimmed = raw.trim()\n if (trimmed.length > 0) return trimmed\n }\n return undefined\n}\n\nfunction numberOption(args: ParsedArgs, ...keys: string[]): number | undefined {\n for (const key of keys) {\n const raw = args[key]\n if (typeof raw === 'number') return raw\n if (typeof raw === 'string') {\n const parsed = Number(raw)\n if (Number.isFinite(parsed)) return parsed\n }\n }\n return undefined\n}\n\nfunction flagEnabled(args: ParsedArgs, ...keys: string[]): boolean {\n for (const key of keys) {\n const raw = args[key]\n if (raw === undefined) continue\n if (raw === true) return true\n if (raw === false) continue\n if (typeof raw === 'string') {\n const trimmed = raw.trim()\n if (!trimmed) return true\n const parsed = parseBooleanToken(trimmed)\n return parsed === null ? true : parsed\n }\n }\n return false\n}\n\nfunction toPositiveInt(value: number | undefined): number | undefined {\n if (value === undefined) return undefined\n const n = Math.floor(value)\n if (!Number.isFinite(n) || n <= 0) return undefined\n return n\n}\n\nfunction toNonNegativeInt(value: number | undefined, fallback = 0): number {\n if (value === undefined) return fallback\n const n = Math.floor(value)\n if (!Number.isFinite(n) || n < 0) return fallback\n return n\n}\n\nconst DEFAULT_BATCH_SIZE = 200\n\ntype RebuildExecutionOptions = {\n em: EntityManager\n knex: Knex\n entityType: string\n tableName: string\n orgOverride?: string\n tenantOverride?: string\n global: boolean\n includeDeleted: boolean\n limit?: number\n offset: number\n recordId?: string\n batchSize: number\n progressLabel?: string\n supportsOrgFilter: boolean\n supportsTenantFilter: boolean\n supportsDeletedFilter: boolean\n}\n\ntype RebuildResult = {\n processed: number\n matched: number\n}\nasync function rebuildEntityIndexes(options: RebuildExecutionOptions): Promise<RebuildResult> {\n const {\n em,\n knex,\n entityType,\n tableName,\n orgOverride,\n tenantOverride,\n global,\n includeDeleted,\n limit,\n offset,\n recordId,\n batchSize,\n progressLabel,\n supportsOrgFilter,\n supportsTenantFilter,\n supportsDeletedFilter,\n } = options\n\n const encryption = resolveTenantEncryptionService(em as any)\n const dekKeyCache = new Map<string | null, string | null>()\n\n const encryptDoc = async (\n targetEntity: string,\n doc: Record<string, unknown>,\n scope: { organizationId: string | null; tenantId: string | null },\n ) => {\n try {\n return await encryptIndexDocForStorage(\n targetEntity,\n doc,\n { tenantId: scope.tenantId ?? null, organizationId: scope.organizationId ?? null },\n encryption,\n )\n } catch {\n return doc\n }\n }\n\n const decryptDoc = async (\n targetEntity: string,\n doc: Record<string, unknown>,\n scope: { organizationId: string | null; tenantId: string | null },\n ) => {\n try {\n return await decryptIndexDocForSearch(\n targetEntity,\n doc,\n { tenantId: scope.tenantId ?? null, organizationId: scope.organizationId ?? null },\n encryption,\n dekKeyCache,\n )\n } catch {\n return doc\n }\n }\n\n const filters: Record<string, unknown> = {}\n if (!global) {\n if (orgOverride !== undefined && supportsOrgFilter) filters.organization_id = orgOverride\n if (tenantOverride !== undefined && supportsTenantFilter) filters.tenant_id = tenantOverride\n }\n if (!includeDeleted && supportsDeletedFilter) filters.deleted_at = null\n\n const baseQuery = knex(tableName).where(filters)\n\n if (recordId) {\n const row = await baseQuery.clone().where({ id: recordId }).first<AnyRow>()\n if (!row) return { processed: 0, matched: 0 }\n const bar = createProgressBar(progressLabel ?? `Rebuilding ${entityType}`, 1)\n await upsertIndexBatch(knex, entityType, [row], { orgId: orgOverride, tenantId: tenantOverride }, { encryptDoc, decryptDoc })\n bar.update(1)\n bar.complete()\n return { processed: 1, matched: 1 }\n }\n\n const countRow = await baseQuery.clone().count<{ count: string }>({ count: '*' }).first()\n const totalRaw = countRow?.count ?? (countRow as any)?.['count(*)']\n const total = totalRaw ? Number(totalRaw) : 0\n const effectiveOffset = Math.max(0, offset)\n const matchedWithoutLimit = Math.max(0, total - effectiveOffset)\n const limitValue = toPositiveInt(limit)\n const intended = limitValue !== undefined ? Math.min(matchedWithoutLimit, limitValue) : matchedWithoutLimit\n if (!Number.isFinite(intended) || intended <= 0) {\n return { processed: 0, matched: 0 }\n }\n\n const bar = createProgressBar(progressLabel ?? `Rebuilding ${entityType}`, intended)\n let processed = 0\n let cursorOffset = effectiveOffset\n let remaining = limitValue\n\n while (processed < intended) {\n const chunkLimit = remaining !== undefined ? Math.min(batchSize, remaining) : batchSize\n const chunk = await baseQuery\n .clone()\n .select('*')\n .orderBy('id')\n .limit(chunkLimit)\n .offset(cursorOffset)\n if (!chunk.length) break\n\n await upsertIndexBatch(knex, entityType, chunk as AnyRow[], {\n orgId: orgOverride,\n tenantId: tenantOverride,\n }, { encryptDoc, decryptDoc })\n\n processed += chunk.length\n cursorOffset += chunk.length\n if (remaining !== undefined) remaining -= chunk.length\n bar.update(processed)\n if (remaining !== undefined && remaining <= 0) break\n }\n\n if (processed < intended) {\n bar.update(processed)\n }\n bar.complete()\n return { processed, matched: intended }\n}\n\nasync function getColumnSet(knex: Knex, tableName: string): Promise<Set<string>> {\n try {\n const info = await knex(tableName).columnInfo()\n return new Set(Object.keys(info).map((key) => key.toLowerCase()))\n } catch {\n return new Set<string>()\n }\n}\n\ntype ScopeDescriptor = {\n global: boolean\n orgId?: string\n tenantId?: string\n includeDeleted: boolean\n supportsOrg: boolean\n supportsTenant: boolean\n supportsDeleted: boolean\n}\n\nfunction describeScope(scope: ScopeDescriptor): string {\n const parts: string[] = []\n if (scope.global) parts.push('global')\n if (!scope.global && scope.orgId && scope.supportsOrg) parts.push(`org=${scope.orgId}`)\n if (!scope.global && scope.tenantId && scope.supportsTenant) parts.push(`tenant=${scope.tenantId}`)\n if (!scope.includeDeleted && scope.supportsDeleted) parts.push('active-only')\n return parts.length ? ` (${parts.join(' ')})` : ''\n}\n\nconst rebuild: ModuleCli = {\n command: 'rebuild',\n async run(rest) {\n const args = parseArgs(rest)\n const entity = stringOption(args, 'entity', 'e')\n if (!entity) {\n console.error(\n 'Usage: mercato query_index rebuild --entity <module:entity> [--record <id>] [--org <id>] [--tenant <id>] [--global] [--withDeleted] [--limit <n>] [--offset <n>]',\n )\n return\n }\n\n const globalFlag = flagEnabled(args, 'global')\n const includeDeleted = flagEnabled(args, 'withDeleted')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n const recordId = stringOption(args, 'record', 'recordId', 'id')\n const limit = toPositiveInt(numberOption(args, 'limit'))\n const offset = toNonNegativeInt(numberOption(args, 'offset'))\n const batchSize = toPositiveInt(numberOption(args, 'batch', 'chunk', 'size')) ?? DEFAULT_BATCH_SIZE\n\n const container = await createRequestContainer()\n const em = (container.resolve('em') as EntityManager)\n try {\n const knex = em.getConnection().getKnex()\n const tableName = resolveEntityTableName(em, entity)\n const columns = await getColumnSet(knex, tableName)\n const supportsOrg = columns.has('organization_id')\n const supportsTenant = columns.has('tenant_id')\n const supportsDeleted = columns.has('deleted_at')\n\n if (!globalFlag && orgId && !supportsOrg) {\n console.warn(`[query_index] ${entity} does not expose organization_id, ignoring --org filter`)\n }\n if (!globalFlag && tenantId && !supportsTenant) {\n console.warn(`[query_index] ${entity} does not expose tenant_id, ignoring --tenant filter`)\n }\n if (!includeDeleted && !supportsDeleted) {\n console.warn(`[query_index] ${entity} does not expose deleted_at, cannot skip deleted rows`)\n }\n\n const result = await rebuildEntityIndexes({\n em,\n knex,\n entityType: entity,\n tableName,\n orgOverride: orgId,\n tenantOverride: tenantId,\n global: globalFlag,\n includeDeleted,\n limit,\n offset,\n recordId,\n batchSize,\n progressLabel: recordId ? `Rebuilding ${entity} record ${recordId}` : `Rebuilding ${entity}`,\n supportsOrgFilter: supportsOrg,\n supportsTenantFilter: supportsTenant,\n supportsDeletedFilter: supportsDeleted,\n })\n\n if (recordId) {\n if (result.processed === 0) {\n console.log(`No matching row found for ${entity} with id ${recordId}`)\n } else {\n console.log(`Rebuilt index for ${entity} record ${recordId}`)\n }\n return\n }\n\n const scopeLabel = describeScope({\n global: globalFlag,\n orgId,\n tenantId,\n includeDeleted,\n supportsOrg,\n supportsTenant,\n supportsDeleted,\n })\n\n if (result.matched === 0) {\n console.log(`No rows matched filters for ${entity}${scopeLabel}`)\n return\n }\n\n console.log(`Rebuilt ${result.processed} row(s) for ${entity}${scopeLabel}`)\n } catch (error) {\n await recordIndexerError(\n { em },\n {\n source: 'query_index',\n handler: 'cli:query_index.rebuild',\n error,\n entityType: entity,\n recordId,\n tenantId,\n organizationId: orgId,\n payload: { args },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nconst rebuildAll: ModuleCli = {\n command: 'rebuild-all',\n async run(rest) {\n const args = parseArgs(rest)\n const globalFlag = flagEnabled(args, 'global')\n const includeDeleted = flagEnabled(args, 'withDeleted')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n const limit = toPositiveInt(numberOption(args, 'limit'))\n const offset = toNonNegativeInt(numberOption(args, 'offset'))\n const batchSize = toPositiveInt(numberOption(args, 'batch', 'chunk', 'size')) ?? DEFAULT_BATCH_SIZE\n const recordId = stringOption(args, 'record', 'recordId', 'id')\n if (recordId) {\n console.error('`rebuild-all` does not support --record. Use `mercato query_index rebuild --record <id>` instead.')\n return\n }\n\n const container = await createRequestContainer()\n const em = (container.resolve('em') as EntityManager)\n try {\n const knex = em.getConnection().getKnex()\n\n const { getEntityIds } = await import('@open-mercato/shared/lib/encryption/entityIds')\n const entityIds = flattenSystemEntityIds(getEntityIds() as Record<string, Record<string, string>>)\n if (!entityIds.length) {\n console.log('No entity definitions registered for query indexing.')\n return\n }\n\n let totalProcessed = 0\n for (let idx = 0; idx < entityIds.length; idx += 1) {\n const entity = entityIds[idx]!\n const tableName = resolveEntityTableName(em, entity)\n const columns = await getColumnSet(knex, tableName)\n const supportsOrg = columns.has('organization_id')\n const supportsTenant = columns.has('tenant_id')\n const supportsDeleted = columns.has('deleted_at')\n\n if (!globalFlag && orgId && !supportsOrg) {\n console.warn(`[query_index] ${entity} does not expose organization_id, ignoring --org filter`)\n }\n if (!globalFlag && tenantId && !supportsTenant) {\n console.warn(`[query_index] ${entity} does not expose tenant_id, ignoring --tenant filter`)\n }\n if (!includeDeleted && !supportsDeleted) {\n console.warn(`[query_index] ${entity} does not expose deleted_at, cannot skip deleted rows`)\n }\n\n const scopeLabel = describeScope({\n global: globalFlag,\n orgId,\n tenantId,\n includeDeleted,\n supportsOrg,\n supportsTenant,\n supportsDeleted,\n })\n\n console.log(`[${idx + 1}/${entityIds.length}] Rebuilding ${entity}${scopeLabel}`)\n const result = await rebuildEntityIndexes({\n em,\n knex,\n entityType: entity,\n tableName,\n orgOverride: orgId,\n tenantOverride: tenantId,\n global: globalFlag,\n includeDeleted,\n limit,\n offset,\n batchSize,\n supportsOrgFilter: supportsOrg,\n supportsTenantFilter: supportsTenant,\n supportsDeletedFilter: supportsDeleted,\n })\n totalProcessed += result.processed\n if (result.matched === 0) {\n console.log(' -> no rows matched filters')\n } else {\n console.log(` -> processed ${result.processed} row(s)`)\n }\n }\n\n console.log(`Finished rebuilding all query indexes (processed ${totalProcessed} row(s))`)\n } catch (error) {\n await recordIndexerError(\n { em },\n {\n source: 'query_index',\n handler: 'cli:query_index.rebuild-all',\n error,\n tenantId,\n organizationId: orgId,\n payload: { args },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nconst reindex: ModuleCli = {\n command: 'reindex',\n async run(rest) {\n const args = parseArgs(rest)\n const entity = stringOption(args, 'entity', 'e')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n const force = flagEnabled(args, 'force', 'full')\n const batchSize = toPositiveInt(numberOption(args, 'batch', 'chunk', 'size'))\n const partitionsOption = toPositiveInt(numberOption(args, 'partitions', 'partitionCount', 'parallel'))\n const partitionIndexOptionRaw = numberOption(args, 'partition', 'partitionIndex')\n const resetCoverageFlag = flagEnabled(args, 'resetCoverage')\n const skipResetCoverageFlag = flagEnabled(args, 'skipResetCoverage', 'noResetCoverage')\n const skipPurge = flagEnabled(args, 'skipPurge', 'noPurge')\n\n const container = await createRequestContainer()\n const baseEm = (container.resolve('em') as EntityManager)\n const partitionIndexOption =\n partitionIndexOptionRaw === undefined ? undefined : toNonNegativeInt(partitionIndexOptionRaw, 0)\n const partitionCount = Math.max(\n 1,\n partitionsOption ?? DEFAULT_REINDEX_PARTITIONS,\n )\n\n if (partitionIndexOption !== undefined && partitionIndexOption >= partitionCount) {\n console.error(`partitionIndex (${partitionIndexOption}) must be < partitionCount (${partitionCount})`)\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n return\n }\n\n const partitionTargets =\n partitionIndexOption !== undefined\n ? [partitionIndexOption]\n : Array.from({ length: partitionCount }, (_, idx) => idx)\n\n const shouldResetCoverage = (partition: number): boolean => {\n if (resetCoverageFlag) return true\n if (skipResetCoverageFlag) return false\n if (partitionIndexOption !== undefined) return partitionIndexOption === 0\n return partition === partitionTargets[0]\n }\n\n try {\n if (entity) {\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex started for ${entity}`,\n entityType: entity,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n force,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n skipPurge,\n },\n },\n ).catch(() => undefined)\n if (!skipPurge) {\n console.log(`Purging existing index rows for ${entity}...`)\n await purgeIndexScope(baseEm, { entityType: entity, organizationId: orgId, tenantId })\n }\n console.log(`Reindexing ${entity}${force ? ' (forced)' : ''} in ${partitionTargets.length} partition(s)...`)\n const verbose = isIndexerVerbose()\n const progressState = verbose ? new Map<number, { last: number }>() : null\n const groupedProgress =\n !verbose && partitionTargets.length > 1\n ? createGroupedProgress(`Reindexing ${entity}`, partitionTargets)\n : null\n const renderProgress = (part: number, entityId: string, info: PartitionProgressInfo) => {\n if (!progressState) return\n const state = progressState.get(part) ?? { last: 0 }\n const now = Date.now()\n if (now - state.last < 1000 && info.processed < info.total) return\n state.last = now\n progressState.set(part, state)\n const percent = info.total > 0 ? ((info.processed / info.total) * 100).toFixed(2) : '0.00'\n console.log(\n ` [${entityId}] partition ${part + 1}/${partitionCount}: ${info.processed.toLocaleString()} / ${info.total.toLocaleString()} (${percent}%)`,\n )\n }\n\n const stats = await Promise.all(\n partitionTargets.map(async (part, idx) => {\n const label = partitionTargets.length > 1 ? ` [partition ${part + 1}/${partitionCount}]` : ''\n if (partitionTargets.length === 1) {\n console.log(` -> processing${label}`)\n } else if (verbose && idx === 0) {\n console.log(` -> processing partitions in parallel (count=${partitionTargets.length})`)\n }\n const partitionContainer = await createRequestContainer()\n const partitionEm = partitionContainer.resolve<EntityManager>('em')\n let partitionVectorService: VectorIndexService | null = null\n try {\n partitionVectorService = partitionContainer.resolve<VectorIndexService>('vectorIndexService')\n } catch {\n partitionVectorService = null\n }\n try {\n let progressBar: ProgressBarHandle | null = null\n const useBar = partitionTargets.length === 1\n const partitionStats = await reindexEntity(partitionEm, {\n entityType: entity,\n tenantId,\n organizationId: orgId,\n force,\n batchSize,\n emitVectorizeEvents: false,\n partitionCount,\n partitionIndex: part,\n resetCoverage: shouldResetCoverage(part),\n vectorService: partitionVectorService,\n onProgress(info) {\n if (useBar) {\n if (info.total > 0 && !progressBar) {\n progressBar = createProgressBar(\n `Reindexing ${entity}${label}`,\n info.total,\n ) as ProgressBarHandle\n }\n progressBar?.update(info.processed)\n } else if (groupedProgress) {\n groupedProgress.onProgress(part, info)\n } else {\n renderProgress(part, entity, info)\n }\n },\n })\n if (progressBar) {\n (progressBar as ProgressBarHandle).complete()\n }\n if (!useBar && groupedProgress) {\n groupedProgress.onProgress(part, { processed: partitionStats.processed, total: partitionStats.total })\n } else if (!useBar) {\n renderProgress(part, entity, { processed: partitionStats.processed, total: partitionStats.total })\n } else {\n console.log(\n ` processed ${partitionStats.processed} row(s)${partitionStats.total ? ` (base ${partitionStats.total})` : ''}`,\n )\n }\n return partitionStats.processed\n } finally {\n if (typeof (partitionContainer as any)?.dispose === 'function') {\n await (partitionContainer as any).dispose()\n }\n }\n }),\n )\n groupedProgress?.complete()\n const totalProcessed = stats.reduce((acc, value) => acc + value, 0)\n console.log(`Finished ${entity}: processed ${totalProcessed} row(s) across ${partitionTargets.length} partition(s)`)\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex completed for ${entity}`,\n entityType: entity,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n processed: totalProcessed,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n },\n },\n ).catch(() => undefined)\n return\n }\n\n const { getEntityIds } = await import('@open-mercato/shared/lib/encryption/entityIds')\n const entityIds = flattenSystemEntityIds(getEntityIds() as Record<string, Record<string, string>>)\n if (!entityIds.length) {\n console.log('No entity definitions registered for query indexing.')\n return\n }\n for (let idx = 0; idx < entityIds.length; idx += 1) {\n const id = entityIds[idx]!\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex started for ${id}`,\n entityType: id,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n force,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n skipPurge,\n },\n },\n ).catch(() => undefined)\n if (!skipPurge) {\n console.log(`[${idx + 1}/${entityIds.length}] Purging existing index rows for ${id}...`)\n await purgeIndexScope(baseEm, { entityType: id, organizationId: orgId, tenantId })\n }\n console.log(\n `[${idx + 1}/${entityIds.length}] Reindexing ${id}${force ? ' (forced)' : ''} in ${partitionTargets.length} partition(s)...`,\n )\n const verbose = isIndexerVerbose()\n const progressState = verbose ? new Map<number, { last: number }>() : null\n const groupedProgress =\n !verbose && partitionTargets.length > 1\n ? createGroupedProgress(`Reindexing ${id}`, partitionTargets)\n : null\n const renderProgress = (part: number, entityId: string, info: PartitionProgressInfo) => {\n if (!progressState) return\n const state = progressState.get(part) ?? { last: 0 }\n const now = Date.now()\n if (now - state.last < 1000 && info.processed < info.total) return\n state.last = now\n progressState.set(part, state)\n const percent = info.total > 0 ? ((info.processed / info.total) * 100).toFixed(2) : '0.00'\n console.log(\n ` [${entityId}] partition ${part + 1}/${partitionCount}: ${info.processed.toLocaleString()} / ${info.total.toLocaleString()} (${percent}%)`,\n )\n }\n\n const partitionResults = await Promise.all(\n partitionTargets.map(async (part, partitionIdx) => {\n const label = partitionTargets.length > 1 ? ` [partition ${part + 1}/${partitionCount}]` : ''\n if (partitionTargets.length === 1) {\n console.log(` -> processing${label}`)\n } else if (verbose && partitionIdx === 0) {\n console.log(` -> processing partitions in parallel (count=${partitionTargets.length})`)\n }\n const partitionContainer = await createRequestContainer()\n const partitionEm = partitionContainer.resolve<EntityManager>('em')\n let partitionVectorService: VectorIndexService | null = null\n try {\n partitionVectorService = partitionContainer.resolve<VectorIndexService>('vectorIndexService')\n } catch {\n partitionVectorService = null\n }\n try {\n let progressBar: ProgressBarHandle | null = null\n const useBar = partitionTargets.length === 1\n const result = await reindexEntity(partitionEm, {\n entityType: id,\n tenantId,\n organizationId: orgId,\n force,\n batchSize,\n emitVectorizeEvents: false,\n partitionCount,\n partitionIndex: part,\n resetCoverage: shouldResetCoverage(part),\n vectorService: partitionVectorService,\n onProgress(info) {\n if (useBar) {\n if (info.total > 0 && !progressBar) {\n progressBar = createProgressBar(`Reindexing ${id}${label}`, info.total) as ProgressBarHandle\n }\n progressBar?.update(info.processed)\n } else if (groupedProgress) {\n groupedProgress.onProgress(part, info)\n } else {\n renderProgress(part, id, info)\n }\n },\n })\n if (progressBar) {\n (progressBar as ProgressBarHandle).complete()\n }\n if (!useBar && groupedProgress) {\n groupedProgress.onProgress(part, { processed: result.processed, total: result.total })\n } else if (!useBar) {\n renderProgress(part, id, { processed: result.processed, total: result.total })\n } else {\n console.log(\n ` processed ${result.processed} row(s)${result.total ? ` (base ${result.total})` : ''}`,\n )\n }\n return result.processed\n } finally {\n if (typeof (partitionContainer as any)?.dispose === 'function') {\n await (partitionContainer as any).dispose()\n }\n }\n }),\n )\n groupedProgress?.complete()\n const totalProcessed = partitionResults.reduce((acc, value) => acc + value, 0)\n console.log(` -> ${id} complete: processed ${totalProcessed} row(s) across ${partitionTargets.length} partition(s)`)\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex completed for ${id}`,\n entityType: id,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n processed: totalProcessed,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n },\n },\n ).catch(() => undefined)\n }\n console.log(`Finished reindexing ${entityIds.length} entities`)\n } catch (error) {\n const targetLabel = entity ?? 'multiple entities'\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n level: 'warn',\n message: `Reindex failed for ${targetLabel}`,\n entityType: entity ?? null,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n error: error instanceof Error ? error.message : String(error),\n },\n },\n ).catch(() => undefined)\n await recordIndexerError(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n error,\n entityType: entity ?? null,\n tenantId,\n organizationId: orgId ?? null,\n payload: {\n args,\n partitionTargets,\n partitionCount,\n partitionIndex: partitionIndexOption,\n force,\n skipPurge,\n },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nconst purge: ModuleCli = {\n command: 'purge',\n async run(rest) {\n const args = parseArgs(rest)\n const entity = stringOption(args, 'entity', 'e')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n\n const container = await createRequestContainer()\n let em: EntityManager | null = null\n try {\n em = (container.resolve('em') as EntityManager)\n } catch {\n em = null\n }\n\n try {\n const bus = container.resolve('eventBus') as {\n emitEvent(event: string, payload: any, options?: any): Promise<void>\n }\n if (entity) {\n await bus.emitEvent(\n 'query_index.purge',\n { entityType: entity, organizationId: orgId, tenantId },\n { persistent: true },\n )\n await recordIndexerLog(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n message: `Purge requested for ${entity}`,\n entityType: entity,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n },\n ).catch(() => undefined)\n console.log(`Scheduled purge for ${entity}`)\n return\n }\n\n const { getEntityIds } = await import('@open-mercato/shared/lib/encryption/entityIds')\n const entityIds = flattenSystemEntityIds(getEntityIds() as Record<string, Record<string, string>>)\n for (const id of entityIds) {\n await bus.emitEvent(\n 'query_index.purge',\n { entityType: id, organizationId: orgId, tenantId },\n { persistent: true },\n )\n await recordIndexerLog(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n message: `Purge requested for ${id}`,\n entityType: id,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: { mode: 'bulk' },\n },\n ).catch(() => undefined)\n }\n console.log(`Scheduled purge for ${entityIds.length} entities`)\n } catch (error) {\n await recordIndexerLog(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n level: 'warn',\n message: `Purge scheduling failed${entity ? ` for ${entity}` : ''}`,\n entityType: entity ?? null,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: { error: error instanceof Error ? error.message : String(error) },\n },\n ).catch(() => undefined)\n await recordIndexerError(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n error,\n entityType: entity ?? null,\n tenantId,\n organizationId: orgId,\n payload: { args },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nexport default [rebuild, rebuildAll, reindex, purge]\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { ModuleCli } from '@open-mercato/shared/modules/registry'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { Knex } from 'knex'\nimport { createProgressBar } from '@open-mercato/shared/lib/cli/progress'\nimport { resolveTenantEncryptionService } from '@open-mercato/shared/lib/encryption/customFieldValues'\nimport { decryptIndexDocForSearch, encryptIndexDocForStorage } from '@open-mercato/shared/lib/encryption/indexDoc'\nimport { parseBooleanToken } from '@open-mercato/shared/lib/boolean'\n\ntype ProgressBarHandle = {\n update(completed: number): void\n complete(): void\n}\nimport { resolveEntityTableName } from '@open-mercato/shared/lib/query/engine'\nimport { recordIndexerError } from '@open-mercato/shared/lib/indexers/error-log'\nimport { recordIndexerLog } from '@open-mercato/shared/lib/indexers/status-log'\nimport { upsertIndexBatch, type AnyRow } from './lib/batch'\nimport { reindexEntity, DEFAULT_REINDEX_PARTITIONS } from './lib/reindexer'\nimport { purgeIndexScope } from './lib/purge'\nimport { flattenSystemEntityIds } from '@open-mercato/shared/lib/entities/system-entities'\nimport type { VectorIndexService } from '@open-mercato/search/vector'\n\ntype ParsedArgs = Record<string, string | boolean>\n\nfunction parseArgs(rest: string[]): ParsedArgs {\n const args: ParsedArgs = {}\n for (let i = 0; i < rest.length; i += 1) {\n const part = rest[i]\n if (!part?.startsWith('--')) continue\n const [rawKey, rawValue] = part.slice(2).split('=')\n if (!rawKey) continue\n if (rawValue !== undefined) {\n args[rawKey] = rawValue\n } else if (i + 1 < rest.length && !rest[i + 1]!.startsWith('--')) {\n args[rawKey] = rest[i + 1]!\n i += 1\n } else {\n args[rawKey] = true\n }\n }\n return args\n}\n\nfunction stringOption(args: ParsedArgs, ...keys: string[]): string | undefined {\n for (const key of keys) {\n const raw = args[key]\n if (typeof raw !== 'string') continue\n const trimmed = raw.trim()\n if (trimmed.length > 0) return trimmed\n }\n return undefined\n}\n\nfunction numberOption(args: ParsedArgs, ...keys: string[]): number | undefined {\n for (const key of keys) {\n const raw = args[key]\n if (typeof raw === 'number') return raw\n if (typeof raw === 'string') {\n const parsed = Number(raw)\n if (Number.isFinite(parsed)) return parsed\n }\n }\n return undefined\n}\n\nfunction flagEnabled(args: ParsedArgs, ...keys: string[]): boolean {\n for (const key of keys) {\n const raw = args[key]\n if (raw === undefined) continue\n if (raw === true) return true\n if (raw === false) continue\n if (typeof raw === 'string') {\n const trimmed = raw.trim()\n if (!trimmed) return true\n const parsed = parseBooleanToken(trimmed)\n return parsed === null ? true : parsed\n }\n }\n return false\n}\n\nfunction toPositiveInt(value: number | undefined): number | undefined {\n if (value === undefined) return undefined\n const n = Math.floor(value)\n if (!Number.isFinite(n) || n <= 0) return undefined\n return n\n}\n\nfunction toNonNegativeInt(value: number | undefined, fallback = 0): number {\n if (value === undefined) return fallback\n const n = Math.floor(value)\n if (!Number.isFinite(n) || n < 0) return fallback\n return n\n}\n\nconst DEFAULT_BATCH_SIZE = 200\n\ntype RebuildExecutionOptions = {\n em: EntityManager\n knex: Knex\n entityType: string\n tableName: string\n orgOverride?: string\n tenantOverride?: string\n global: boolean\n includeDeleted: boolean\n limit?: number\n offset: number\n recordId?: string\n batchSize: number\n progressLabel?: string\n supportsOrgFilter: boolean\n supportsTenantFilter: boolean\n supportsDeletedFilter: boolean\n}\n\ntype RebuildResult = {\n processed: number\n matched: number\n}\nasync function rebuildEntityIndexes(options: RebuildExecutionOptions): Promise<RebuildResult> {\n const {\n em,\n knex,\n entityType,\n tableName,\n orgOverride,\n tenantOverride,\n global,\n includeDeleted,\n limit,\n offset,\n recordId,\n batchSize,\n progressLabel,\n supportsOrgFilter,\n supportsTenantFilter,\n supportsDeletedFilter,\n } = options\n\n const encryption = resolveTenantEncryptionService(em as any)\n const dekKeyCache = new Map<string | null, string | null>()\n\n const encryptDoc = async (\n targetEntity: string,\n doc: Record<string, unknown>,\n scope: { organizationId: string | null; tenantId: string | null },\n ) => {\n try {\n return await encryptIndexDocForStorage(\n targetEntity,\n doc,\n { tenantId: scope.tenantId ?? null, organizationId: scope.organizationId ?? null },\n encryption,\n )\n } catch {\n return doc\n }\n }\n\n const decryptDoc = async (\n targetEntity: string,\n doc: Record<string, unknown>,\n scope: { organizationId: string | null; tenantId: string | null },\n ) => {\n try {\n return await decryptIndexDocForSearch(\n targetEntity,\n doc,\n { tenantId: scope.tenantId ?? null, organizationId: scope.organizationId ?? null },\n encryption,\n dekKeyCache,\n )\n } catch {\n return doc\n }\n }\n\n const filters: Record<string, unknown> = {}\n if (!global) {\n if (orgOverride !== undefined && supportsOrgFilter) filters.organization_id = orgOverride\n if (tenantOverride !== undefined && supportsTenantFilter) filters.tenant_id = tenantOverride\n }\n if (!includeDeleted && supportsDeletedFilter) filters.deleted_at = null\n\n const baseQuery = knex(tableName).where(filters)\n\n if (recordId) {\n const row = await baseQuery.clone().where({ id: recordId }).first<AnyRow>()\n if (!row) return { processed: 0, matched: 0 }\n const bar = createProgressBar(progressLabel ?? `Rebuilding ${entityType}`, 1)\n await upsertIndexBatch(knex, entityType, [row], { orgId: orgOverride, tenantId: tenantOverride }, { encryptDoc, decryptDoc })\n bar.update(1)\n bar.complete()\n return { processed: 1, matched: 1 }\n }\n\n const countRow = await baseQuery.clone().count<{ count: string }>({ count: '*' }).first()\n const totalRaw = countRow?.count ?? (countRow as any)?.['count(*)']\n const total = totalRaw ? Number(totalRaw) : 0\n const effectiveOffset = Math.max(0, offset)\n const matchedWithoutLimit = Math.max(0, total - effectiveOffset)\n const limitValue = toPositiveInt(limit)\n const intended = limitValue !== undefined ? Math.min(matchedWithoutLimit, limitValue) : matchedWithoutLimit\n if (!Number.isFinite(intended) || intended <= 0) {\n return { processed: 0, matched: 0 }\n }\n\n const bar = createProgressBar(progressLabel ?? `Rebuilding ${entityType}`, intended)\n let processed = 0\n let cursorOffset = effectiveOffset\n let remaining = limitValue\n\n while (processed < intended) {\n const chunkLimit = remaining !== undefined ? Math.min(batchSize, remaining) : batchSize\n const chunk = await baseQuery\n .clone()\n .select('*')\n .orderBy('id')\n .limit(chunkLimit)\n .offset(cursorOffset)\n if (!chunk.length) break\n\n await upsertIndexBatch(knex, entityType, chunk as AnyRow[], {\n orgId: orgOverride,\n tenantId: tenantOverride,\n }, { encryptDoc, decryptDoc })\n\n processed += chunk.length\n cursorOffset += chunk.length\n if (remaining !== undefined) remaining -= chunk.length\n bar.update(processed)\n if (remaining !== undefined && remaining <= 0) break\n }\n\n if (processed < intended) {\n bar.update(processed)\n }\n bar.complete()\n return { processed, matched: intended }\n}\n\nasync function getColumnSet(knex: Knex, tableName: string): Promise<Set<string>> {\n try {\n const info = await knex(tableName).columnInfo()\n return new Set(Object.keys(info).map((key) => key.toLowerCase()))\n } catch {\n return new Set<string>()\n }\n}\n\ntype ScopeDescriptor = {\n global: boolean\n orgId?: string\n tenantId?: string\n includeDeleted: boolean\n supportsOrg: boolean\n supportsTenant: boolean\n supportsDeleted: boolean\n}\n\nfunction describeScope(scope: ScopeDescriptor): string {\n const parts: string[] = []\n if (scope.global) parts.push('global')\n if (!scope.global && scope.orgId && scope.supportsOrg) parts.push(`org=${scope.orgId}`)\n if (!scope.global && scope.tenantId && scope.supportsTenant) parts.push(`tenant=${scope.tenantId}`)\n if (!scope.includeDeleted && scope.supportsDeleted) parts.push('active-only')\n return parts.length ? ` (${parts.join(' ')})` : ''\n}\n\nconst rebuild: ModuleCli = {\n command: 'rebuild',\n async run(rest) {\n const args = parseArgs(rest)\n const entity = stringOption(args, 'entity', 'e')\n if (!entity) {\n console.error(\n 'Usage: mercato query_index rebuild --entity <module:entity> [--record <id>] [--org <id>] [--tenant <id>] [--global] [--withDeleted] [--limit <n>] [--offset <n>]',\n )\n return\n }\n\n const globalFlag = flagEnabled(args, 'global')\n const includeDeleted = flagEnabled(args, 'withDeleted')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n const recordId = stringOption(args, 'record', 'recordId', 'id')\n const limit = toPositiveInt(numberOption(args, 'limit'))\n const offset = toNonNegativeInt(numberOption(args, 'offset'))\n const batchSize = toPositiveInt(numberOption(args, 'batch', 'chunk', 'size')) ?? DEFAULT_BATCH_SIZE\n\n const container = await createRequestContainer()\n const em = (container.resolve('em') as EntityManager)\n try {\n const knex = em.getConnection().getKnex()\n const tableName = resolveEntityTableName(em, entity)\n const columns = await getColumnSet(knex, tableName)\n const supportsOrg = columns.has('organization_id')\n const supportsTenant = columns.has('tenant_id')\n const supportsDeleted = columns.has('deleted_at')\n\n if (!globalFlag && orgId && !supportsOrg) {\n console.warn(`[query_index] ${entity} does not expose organization_id, ignoring --org filter`)\n }\n if (!globalFlag && tenantId && !supportsTenant) {\n console.warn(`[query_index] ${entity} does not expose tenant_id, ignoring --tenant filter`)\n }\n if (!includeDeleted && !supportsDeleted) {\n console.warn(`[query_index] ${entity} does not expose deleted_at, cannot skip deleted rows`)\n }\n\n const result = await rebuildEntityIndexes({\n em,\n knex,\n entityType: entity,\n tableName,\n orgOverride: orgId,\n tenantOverride: tenantId,\n global: globalFlag,\n includeDeleted,\n limit,\n offset,\n recordId,\n batchSize,\n progressLabel: recordId ? `Rebuilding ${entity} record ${recordId}` : `Rebuilding ${entity}`,\n supportsOrgFilter: supportsOrg,\n supportsTenantFilter: supportsTenant,\n supportsDeletedFilter: supportsDeleted,\n })\n\n if (recordId) {\n if (result.processed === 0) {\n console.log(`No matching row found for ${entity} with id ${recordId}`)\n } else {\n console.log(`Rebuilt index for ${entity} record ${recordId}`)\n }\n return\n }\n\n const scopeLabel = describeScope({\n global: globalFlag,\n orgId,\n tenantId,\n includeDeleted,\n supportsOrg,\n supportsTenant,\n supportsDeleted,\n })\n\n if (result.matched === 0) {\n console.log(`No rows matched filters for ${entity}${scopeLabel}`)\n return\n }\n\n console.log(`Rebuilt ${result.processed} row(s) for ${entity}${scopeLabel}`)\n } catch (error) {\n await recordIndexerError(\n { em },\n {\n source: 'query_index',\n handler: 'cli:query_index.rebuild',\n error,\n entityType: entity,\n recordId,\n tenantId,\n organizationId: orgId,\n payload: { args },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nconst rebuildAll: ModuleCli = {\n command: 'rebuild-all',\n async run(rest) {\n const args = parseArgs(rest)\n const globalFlag = flagEnabled(args, 'global')\n const includeDeleted = flagEnabled(args, 'withDeleted')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n const limit = toPositiveInt(numberOption(args, 'limit'))\n const offset = toNonNegativeInt(numberOption(args, 'offset'))\n const batchSize = toPositiveInt(numberOption(args, 'batch', 'chunk', 'size')) ?? DEFAULT_BATCH_SIZE\n const recordId = stringOption(args, 'record', 'recordId', 'id')\n if (recordId) {\n console.error('`rebuild-all` does not support --record. Use `mercato query_index rebuild --record <id>` instead.')\n return\n }\n\n const container = await createRequestContainer()\n const em = (container.resolve('em') as EntityManager)\n try {\n const knex = em.getConnection().getKnex()\n\n const { getEntityIds } = await import('@open-mercato/shared/lib/encryption/entityIds')\n const entityIds = flattenSystemEntityIds(getEntityIds() as Record<string, Record<string, string>>)\n if (!entityIds.length) {\n console.log('No entity definitions registered for query indexing.')\n return\n }\n\n let totalProcessed = 0\n for (let idx = 0; idx < entityIds.length; idx += 1) {\n const entity = entityIds[idx]!\n const tableName = resolveEntityTableName(em, entity)\n const columns = await getColumnSet(knex, tableName)\n const supportsOrg = columns.has('organization_id')\n const supportsTenant = columns.has('tenant_id')\n const supportsDeleted = columns.has('deleted_at')\n\n if (!globalFlag && orgId && !supportsOrg) {\n console.warn(`[query_index] ${entity} does not expose organization_id, ignoring --org filter`)\n }\n if (!globalFlag && tenantId && !supportsTenant) {\n console.warn(`[query_index] ${entity} does not expose tenant_id, ignoring --tenant filter`)\n }\n if (!includeDeleted && !supportsDeleted) {\n console.warn(`[query_index] ${entity} does not expose deleted_at, cannot skip deleted rows`)\n }\n\n const scopeLabel = describeScope({\n global: globalFlag,\n orgId,\n tenantId,\n includeDeleted,\n supportsOrg,\n supportsTenant,\n supportsDeleted,\n })\n\n console.log(`[${idx + 1}/${entityIds.length}] Rebuilding ${entity}${scopeLabel}`)\n const result = await rebuildEntityIndexes({\n em,\n knex,\n entityType: entity,\n tableName,\n orgOverride: orgId,\n tenantOverride: tenantId,\n global: globalFlag,\n includeDeleted,\n limit,\n offset,\n batchSize,\n supportsOrgFilter: supportsOrg,\n supportsTenantFilter: supportsTenant,\n supportsDeletedFilter: supportsDeleted,\n })\n totalProcessed += result.processed\n if (result.matched === 0) {\n console.log(' -> no rows matched filters')\n } else {\n console.log(` -> processed ${result.processed} row(s)`)\n }\n }\n\n console.log(`Finished rebuilding all query indexes (processed ${totalProcessed} row(s))`)\n } catch (error) {\n await recordIndexerError(\n { em },\n {\n source: 'query_index',\n handler: 'cli:query_index.rebuild-all',\n error,\n tenantId,\n organizationId: orgId,\n payload: { args },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nconst reindex: ModuleCli = {\n command: 'reindex',\n async run(rest) {\n const args = parseArgs(rest)\n const entity = stringOption(args, 'entity', 'e')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n const force = flagEnabled(args, 'force', 'full')\n const batchSize = toPositiveInt(numberOption(args, 'batch', 'chunk', 'size'))\n const partitionsOption = toPositiveInt(numberOption(args, 'partitions', 'partitionCount', 'parallel'))\n const partitionIndexOptionRaw = numberOption(args, 'partition', 'partitionIndex')\n const resetCoverageFlag = flagEnabled(args, 'resetCoverage')\n const skipResetCoverageFlag = flagEnabled(args, 'skipResetCoverage', 'noResetCoverage')\n const skipPurge = flagEnabled(args, 'skipPurge', 'noPurge')\n\n const container = await createRequestContainer()\n const baseEm = (container.resolve('em') as EntityManager)\n const partitionIndexOption =\n partitionIndexOptionRaw === undefined ? undefined : toNonNegativeInt(partitionIndexOptionRaw, 0)\n const partitionCount = Math.max(\n 1,\n partitionsOption ?? DEFAULT_REINDEX_PARTITIONS,\n )\n\n if (partitionIndexOption !== undefined && partitionIndexOption >= partitionCount) {\n console.error(`partitionIndex (${partitionIndexOption}) must be < partitionCount (${partitionCount})`)\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n return\n }\n\n const partitionTargets =\n partitionIndexOption !== undefined\n ? [partitionIndexOption]\n : Array.from({ length: partitionCount }, (_, idx) => idx)\n\n const shouldResetCoverage = (partition: number): boolean => {\n if (resetCoverageFlag) return true\n if (skipResetCoverageFlag) return false\n if (partitionIndexOption !== undefined) return partitionIndexOption === 0\n return partition === partitionTargets[0]\n }\n\n try {\n if (entity) {\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex started for ${entity}`,\n entityType: entity,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n force,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n skipPurge,\n },\n },\n ).catch(() => undefined)\n if (!skipPurge) {\n console.log(`Purging existing index rows for ${entity}...`)\n await purgeIndexScope(baseEm, { entityType: entity, organizationId: orgId, tenantId })\n }\n console.log(`Reindexing ${entity}${force ? ' (forced)' : ''} in ${partitionTargets.length} partition(s)...`)\n const progressState = new Map<number, { last: number }>()\n const renderProgress = (part: number, entityId: string, info: { processed: number; total: number }) => {\n const state = progressState.get(part) ?? { last: 0 }\n const now = Date.now()\n if (now - state.last < 1000 && info.processed < info.total) return\n state.last = now\n progressState.set(part, state)\n const percent = info.total > 0 ? ((info.processed / info.total) * 100).toFixed(2) : '0.00'\n console.log(\n ` [${entityId}] partition ${part + 1}/${partitionCount}: ${info.processed.toLocaleString()} / ${info.total.toLocaleString()} (${percent}%)`,\n )\n }\n\n const stats = await Promise.all(\n partitionTargets.map(async (part, idx) => {\n const label = partitionTargets.length > 1 ? ` [partition ${part + 1}/${partitionCount}]` : ''\n if (partitionTargets.length === 1) {\n console.log(` -> processing${label}`)\n } else if (idx === 0) {\n console.log(` -> processing partitions in parallel (count=${partitionTargets.length})`)\n }\n const partitionContainer = await createRequestContainer()\n const partitionEm = partitionContainer.resolve<EntityManager>('em')\n let partitionVectorService: VectorIndexService | null = null\n try {\n partitionVectorService = partitionContainer.resolve<VectorIndexService>('vectorIndexService')\n } catch {\n partitionVectorService = null\n }\n try {\n let progressBar: ProgressBarHandle | null = null\n const useBar = partitionTargets.length === 1\n const partitionStats = await reindexEntity(partitionEm, {\n entityType: entity,\n tenantId,\n organizationId: orgId,\n force,\n batchSize,\n emitVectorizeEvents: false,\n partitionCount,\n partitionIndex: part,\n resetCoverage: shouldResetCoverage(part),\n vectorService: partitionVectorService,\n onProgress(info) {\n if (useBar) {\n if (info.total > 0 && !progressBar) {\n progressBar = createProgressBar(`Reindexing ${entity}${label}`, info.total) as ProgressBarHandle\n }\n progressBar?.update(info.processed)\n } else {\n renderProgress(part, entity, info)\n }\n },\n })\n if (progressBar) {\n (progressBar as ProgressBarHandle).complete()\n }\n if (!useBar) {\n renderProgress(part, entity, { processed: partitionStats.processed, total: partitionStats.total })\n } else {\n console.log(\n ` processed ${partitionStats.processed} row(s)${partitionStats.total ? ` (base ${partitionStats.total})` : ''}`,\n )\n }\n return partitionStats.processed\n } finally {\n if (typeof (partitionContainer as any)?.dispose === 'function') {\n await (partitionContainer as any).dispose()\n }\n }\n }),\n )\n const totalProcessed = stats.reduce((acc, value) => acc + value, 0)\n console.log(`Finished ${entity}: processed ${totalProcessed} row(s) across ${partitionTargets.length} partition(s)`)\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex completed for ${entity}`,\n entityType: entity,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n processed: totalProcessed,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n },\n },\n ).catch(() => undefined)\n return\n }\n\n const { getEntityIds } = await import('@open-mercato/shared/lib/encryption/entityIds')\n const entityIds = flattenSystemEntityIds(getEntityIds() as Record<string, Record<string, string>>)\n if (!entityIds.length) {\n console.log('No entity definitions registered for query indexing.')\n return\n }\n for (let idx = 0; idx < entityIds.length; idx += 1) {\n const id = entityIds[idx]!\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex started for ${id}`,\n entityType: id,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n force,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n skipPurge,\n },\n },\n ).catch(() => undefined)\n if (!skipPurge) {\n console.log(`[${idx + 1}/${entityIds.length}] Purging existing index rows for ${id}...`)\n await purgeIndexScope(baseEm, { entityType: id, organizationId: orgId, tenantId })\n }\n console.log(\n `[${idx + 1}/${entityIds.length}] Reindexing ${id}${force ? ' (forced)' : ''} in ${partitionTargets.length} partition(s)...`,\n )\n const progressState = new Map<number, { last: number }>()\n const renderProgress = (part: number, entityId: string, info: { processed: number; total: number }) => {\n const state = progressState.get(part) ?? { last: 0 }\n const now = Date.now()\n if (now - state.last < 1000 && info.processed < info.total) return\n state.last = now\n progressState.set(part, state)\n const percent = info.total > 0 ? ((info.processed / info.total) * 100).toFixed(2) : '0.00'\n console.log(\n ` [${entityId}] partition ${part + 1}/${partitionCount}: ${info.processed.toLocaleString()} / ${info.total.toLocaleString()} (${percent}%)`,\n )\n }\n\n const partitionResults = await Promise.all(\n partitionTargets.map(async (part, partitionIdx) => {\n const label = partitionTargets.length > 1 ? ` [partition ${part + 1}/${partitionCount}]` : ''\n if (partitionTargets.length === 1) {\n console.log(` -> processing${label}`)\n } else if (partitionIdx === 0) {\n console.log(` -> processing partitions in parallel (count=${partitionTargets.length})`)\n }\n const partitionContainer = await createRequestContainer()\n const partitionEm = partitionContainer.resolve<EntityManager>('em')\n let partitionVectorService: VectorIndexService | null = null\n try {\n partitionVectorService = partitionContainer.resolve<VectorIndexService>('vectorIndexService')\n } catch {\n partitionVectorService = null\n }\n try {\n let progressBar: ProgressBarHandle | null = null\n const useBar = partitionTargets.length === 1\n const result = await reindexEntity(partitionEm, {\n entityType: id,\n tenantId,\n organizationId: orgId,\n force,\n batchSize,\n emitVectorizeEvents: false,\n partitionCount,\n partitionIndex: part,\n resetCoverage: shouldResetCoverage(part),\n vectorService: partitionVectorService,\n onProgress(info) {\n if (useBar) {\n if (info.total > 0 && !progressBar) {\n progressBar = createProgressBar(`Reindexing ${id}${label}`, info.total) as ProgressBarHandle\n }\n progressBar?.update(info.processed)\n } else {\n renderProgress(part, id, info)\n }\n },\n })\n if (progressBar) {\n (progressBar as ProgressBarHandle).complete()\n }\n if (!useBar) {\n renderProgress(part, id, { processed: result.processed, total: result.total })\n } else {\n console.log(\n ` processed ${result.processed} row(s)${result.total ? ` (base ${result.total})` : ''}`,\n )\n }\n return result.processed\n } finally {\n if (typeof (partitionContainer as any)?.dispose === 'function') {\n await (partitionContainer as any).dispose()\n }\n }\n }),\n )\n const totalProcessed = partitionResults.reduce((acc, value) => acc + value, 0)\n console.log(` -> ${id} complete: processed ${totalProcessed} row(s) across ${partitionTargets.length} partition(s)`)\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex completed for ${id}`,\n entityType: id,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n processed: totalProcessed,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n },\n },\n ).catch(() => undefined)\n }\n console.log(`Finished reindexing ${entityIds.length} entities`)\n } catch (error) {\n const targetLabel = entity ?? 'multiple entities'\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n level: 'warn',\n message: `Reindex failed for ${targetLabel}`,\n entityType: entity ?? null,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n error: error instanceof Error ? error.message : String(error),\n },\n },\n ).catch(() => undefined)\n await recordIndexerError(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n error,\n entityType: entity ?? null,\n tenantId,\n organizationId: orgId ?? null,\n payload: {\n args,\n partitionTargets,\n partitionCount,\n partitionIndex: partitionIndexOption,\n force,\n skipPurge,\n },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nconst purge: ModuleCli = {\n command: 'purge',\n async run(rest) {\n const args = parseArgs(rest)\n const entity = stringOption(args, 'entity', 'e')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n\n const container = await createRequestContainer()\n let em: EntityManager | null = null\n try {\n em = (container.resolve('em') as EntityManager)\n } catch {\n em = null\n }\n\n try {\n const bus = container.resolve('eventBus') as {\n emitEvent(event: string, payload: any, options?: any): Promise<void>\n }\n if (entity) {\n await bus.emitEvent(\n 'query_index.purge',\n { entityType: entity, organizationId: orgId, tenantId },\n { persistent: true },\n )\n await recordIndexerLog(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n message: `Purge requested for ${entity}`,\n entityType: entity,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n },\n ).catch(() => undefined)\n console.log(`Scheduled purge for ${entity}`)\n return\n }\n\n const { getEntityIds } = await import('@open-mercato/shared/lib/encryption/entityIds')\n const entityIds = flattenSystemEntityIds(getEntityIds() as Record<string, Record<string, string>>)\n for (const id of entityIds) {\n await bus.emitEvent(\n 'query_index.purge',\n { entityType: id, organizationId: orgId, tenantId },\n { persistent: true },\n )\n await recordIndexerLog(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n message: `Purge requested for ${id}`,\n entityType: id,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: { mode: 'bulk' },\n },\n ).catch(() => undefined)\n }\n console.log(`Scheduled purge for ${entityIds.length} entities`)\n } catch (error) {\n await recordIndexerLog(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n level: 'warn',\n message: `Purge scheduling failed${entity ? ` for ${entity}` : ''}`,\n entityType: entity ?? null,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: { error: error instanceof Error ? error.message : String(error) },\n },\n ).catch(() => undefined)\n await recordIndexerError(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n error,\n entityType: entity ?? null,\n tenantId,\n organizationId: orgId,\n payload: { args },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nexport default [rebuild, rebuildAll, reindex, purge]\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["bar"]
|
|
7
7
|
}
|
|
@@ -265,14 +265,12 @@ function QueryIndexesTable() {
|
|
|
265
265
|
perspective: { tableId: "query_index.status.list" },
|
|
266
266
|
rowActions: (row) => {
|
|
267
267
|
const items = [
|
|
268
|
-
{
|
|
268
|
+
{ label: t("query_index.table.actions.reindex"), onSelect: () => trigger("reindex", row.entityId) },
|
|
269
269
|
{
|
|
270
|
-
id: "reindex-force",
|
|
271
270
|
label: t("query_index.table.actions.reindexForce"),
|
|
272
271
|
onSelect: () => trigger("reindex", row.entityId, { force: true })
|
|
273
272
|
},
|
|
274
273
|
{
|
|
275
|
-
id: "purge",
|
|
276
274
|
label: t("query_index.table.actions.purge"),
|
|
277
275
|
destructive: true,
|
|
278
276
|
onSelect: () => trigger("purge", row.entityId)
|
|
@@ -281,12 +279,10 @@ function QueryIndexesTable() {
|
|
|
281
279
|
if (row.vectorEnabled) {
|
|
282
280
|
items.push(
|
|
283
281
|
{
|
|
284
|
-
id: "vector-reindex",
|
|
285
282
|
label: t("query_index.table.actions.vectorReindex"),
|
|
286
283
|
onSelect: () => triggerVector("reindex", row.entityId)
|
|
287
284
|
},
|
|
288
285
|
{
|
|
289
|
-
id: "vector-purge",
|
|
290
286
|
label: t("query_index.table.actions.vectorPurge"),
|
|
291
287
|
destructive: true,
|
|
292
288
|
onSelect: () => triggerVector("purge", row.entityId)
|
|
@@ -296,12 +292,10 @@ function QueryIndexesTable() {
|
|
|
296
292
|
if (row.fulltextEnabled) {
|
|
297
293
|
items.push(
|
|
298
294
|
{
|
|
299
|
-
id: "fulltext-reindex",
|
|
300
295
|
label: t("query_index.table.actions.fulltextReindex"),
|
|
301
296
|
onSelect: () => triggerFulltext("reindex", row.entityId)
|
|
302
297
|
},
|
|
303
298
|
{
|
|
304
|
-
id: "fulltext-purge",
|
|
305
299
|
label: t("query_index.table.actions.fulltextPurge"),
|
|
306
300
|
destructive: true,
|
|
307
301
|
onSelect: () => triggerFulltext("purge", row.entityId)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/query_index/components/QueryIndexesTable.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { apiCallOrThrow, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\ntype Translator = (key: string, params?: Record<string, string | number>) => string\n\ntype PartitionStatus = {\n partitionIndex: number | null\n partitionCount: number | null\n status: 'reindexing' | 'purging' | 'stalled' | 'completed'\n processedCount?: number | null\n totalCount?: number | null\n heartbeatAt?: string | null\n startedAt?: string | null\n finishedAt?: string | null\n}\n\ntype JobStatus = {\n status: 'idle' | 'reindexing' | 'purging' | 'stalled'\n startedAt?: string | null\n finishedAt?: string | null\n heartbeatAt?: string | null\n processedCount?: number | null\n totalCount?: number | null\n partitions?: PartitionStatus[]\n scope?: {\n status?: 'reindexing' | 'purging' | 'stalled' | 'completed' | null\n processedCount?: number | null\n totalCount?: number | null\n } | null\n}\n\ntype Row = {\n entityId: string\n label: string\n baseCount: number | null\n indexCount: number | null\n vectorCount: number | null\n vectorEnabled: boolean\n fulltextCount: number | null\n fulltextEnabled: boolean\n ok: boolean\n job?: JobStatus\n}\n\ntype Resp = { items: Row[] }\n\nfunction formatCount(value: number | null): string {\n if (value == null) return '\u2014'\n return value.toLocaleString()\n}\n\nfunction formatNumeric(value: number | null | undefined): string | null {\n if (value == null) return null\n return Number(value).toLocaleString()\n}\n\nfunction formatProgressLabel(\n processed: number | null | undefined,\n total: number | null | undefined,\n t: Translator,\n): string | null {\n const processedText = formatNumeric(processed)\n if (!processedText) return null\n const totalText = formatNumeric(total)\n if (totalText) return t('query_index.table.status.progress', { processed: processedText, total: totalText })\n return t('query_index.table.status.progressSingle', { processed: processedText })\n}\n\nfunction translateJobStatus(t: Translator, status: JobStatus['status'] | undefined, ok: boolean): string {\n if (!status || status === 'idle') {\n return ok ? t('query_index.table.status.in_sync') : t('query_index.table.status.out_of_sync')\n }\n if (status === 'reindexing') return t('query_index.table.status.reindexing')\n if (status === 'purging') return t('query_index.table.status.purging')\n if (status === 'stalled') return t('query_index.table.status.stalled')\n return ok ? t('query_index.table.status.in_sync') : t('query_index.table.status.out_of_sync')\n}\n\nfunction translateScopeStatus(\n t: Translator,\n status: PartitionStatus['status'] | JobStatus['status'] | undefined | null,\n): string {\n if (status === 'reindexing') return t('query_index.table.status.scope.reindexing')\n if (status === 'purging') return t('query_index.table.status.scope.purging')\n if (status === 'stalled') return t('query_index.table.status.scope.stalled')\n return t('query_index.table.status.scope.completed')\n}\n\n\nfunction createColumns(t: Translator): ColumnDef<Row>[] {\n return [\n { id: 'entityId', header: () => t('query_index.table.columns.entity'), accessorKey: 'entityId', meta: { priority: 1 } },\n { id: 'label', header: () => t('query_index.table.columns.label'), accessorKey: 'label', meta: { priority: 2 } },\n {\n id: 'baseCount',\n header: () => t('query_index.table.columns.records'),\n accessorFn: (row) => row.baseCount ?? 0,\n cell: ({ row }) => <span>{formatCount(row.original.baseCount)}</span>,\n meta: { priority: 2 },\n },\n {\n id: 'indexCount',\n header: () => t('query_index.table.columns.indexed'),\n accessorFn: (row) => row.indexCount ?? 0,\n cell: ({ row }) => <span>{formatCount(row.original.indexCount)}</span>,\n meta: { priority: 2 },\n },\n {\n id: 'vectorCount',\n header: () => t('query_index.table.columns.vector'),\n accessorFn: (row) => (row.vectorEnabled ? row.vectorCount ?? 0 : -1),\n cell: ({ row }) => {\n const record = row.original\n if (!record.vectorEnabled) return <span>\u2014</span>\n const ok = record.vectorCount != null && record.baseCount != null && record.vectorCount === record.baseCount\n const display = formatCount(record.vectorCount)\n const className = ok ? 'text-green-600' : 'text-orange-600'\n return <span className={className}>{display}</span>\n },\n meta: { priority: 2 },\n },\n {\n id: 'fulltextCount',\n header: () => t('query_index.table.columns.fulltext'),\n accessorFn: (row) => (row.fulltextEnabled ? row.fulltextCount ?? 0 : -1),\n cell: ({ row }) => {\n const record = row.original\n if (!record.fulltextEnabled) return <span>\u2014</span>\n const ok = record.fulltextCount != null && record.baseCount != null && record.fulltextCount === record.baseCount\n const display = formatCount(record.fulltextCount)\n const className = ok ? 'text-green-600' : 'text-orange-600'\n return <span className={className}>{display}</span>\n },\n meta: { priority: 2 },\n },\n {\n id: 'status',\n header: () => t('query_index.table.columns.status'),\n cell: ({ row }) => {\n const record = row.original\n const job = record.job\n const partitions = job?.partitions ?? []\n const ok = record.ok && (!job || job.status === 'idle')\n const statusText = translateJobStatus(t, job?.status, ok)\n const jobProgress = job ? formatProgressLabel(job.processedCount ?? null, job.totalCount ?? null, t) : null\n const label = jobProgress\n ? t('query_index.table.status.withProgress', { status: statusText, progress: jobProgress })\n : statusText\n const className = job\n ? job.status === 'stalled'\n ? 'text-red-600'\n : job.status === 'reindexing' || job.status === 'purging'\n ? 'text-orange-600'\n : ok\n ? 'text-green-600'\n : 'text-muted-foreground'\n : ok\n ? 'text-green-600'\n : 'text-muted-foreground'\n\n const lines: string[] = []\n\n if (job?.scope && partitions.length <= 1) {\n const scopeStatus = translateScopeStatus(t, job.scope.status ?? null)\n const scopeProgress = formatProgressLabel(job.scope.processedCount ?? null, job.scope.totalCount ?? null, t)\n const scopeLabel = t('query_index.table.status.scopeLabel')\n lines.push(`${scopeLabel}: ${scopeStatus}${scopeProgress ? ` (${scopeProgress})` : ''}`)\n }\n\n if (partitions.length > 1) {\n for (const part of partitions) {\n const partitionLabel =\n part.partitionIndex != null\n ? t('query_index.table.status.partitionLabel', { index: Number(part.partitionIndex) + 1 })\n : t('query_index.table.status.scopeLabel')\n const partitionStatus = translateScopeStatus(t, part.status)\n const partitionProgress = formatProgressLabel(part.processedCount ?? null, part.totalCount ?? null, t)\n lines.push(`${partitionLabel}: ${partitionStatus}${partitionProgress ? ` (${partitionProgress})` : ''}`)\n }\n }\n\n if (record.vectorEnabled) {\n const vectorLabel = t('query_index.table.status.vectorLabel')\n const vectorCount = formatCount(record.vectorCount)\n const vectorTotal = record.baseCount != null ? formatCount(record.baseCount) : null\n const vectorValue = vectorTotal\n ? t('query_index.table.status.vectorValue', { count: vectorCount, total: vectorTotal })\n : vectorCount\n lines.push(`${vectorLabel}: ${vectorValue}`)\n }\n\n return (\n <div className=\"space-y-1\">\n <span className={className}>{label}</span>\n {lines.length > 0 && (\n <div className=\"text-xs text-muted-foreground\">\n {lines.map((line, idx) => (\n <div key={idx}>{line}</div>\n ))}\n </div>\n )}\n </div>\n )\n },\n meta: { priority: 1 },\n },\n ]\n}\n\nexport default function QueryIndexesTable() {\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'entityId', desc: false }])\n const [page, setPage] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const qc = useQueryClient()\n const scopeVersion = useOrganizationScopeVersion()\n const [refreshSeq, setRefreshSeq] = React.useState(0)\n const t = useT()\n const columns = React.useMemo(() => createColumns(t), [t])\n\n const { data, isLoading } = useQuery<Resp>({\n queryKey: ['query-index-status', scopeVersion, refreshSeq],\n queryFn: async () => {\n const baseUrl = '/api/query_index/status'\n const url = refreshSeq > 0 ? `${baseUrl}?refresh=${refreshSeq}` : baseUrl\n return readApiResultOrThrow<Resp>(\n url,\n undefined,\n { errorMessage: t('query_index.table.errors.loadFailed') },\n )\n },\n refetchInterval: 4000,\n })\n\n const rowsAll = data?.items || []\n const rows = React.useMemo(() => {\n if (!search) return rowsAll\n const q = search.toLowerCase()\n return rowsAll.filter((r) => r.entityId.toLowerCase().includes(q) || r.label.toLowerCase().includes(q))\n }, [rowsAll, search])\n\n const trigger = React.useCallback(\n async (action: 'reindex' | 'purge', entityId: string, opts?: { force?: boolean }) => {\n const body: Record<string, unknown> = { entityType: entityId }\n if (opts?.force) body.force = true\n const actionLabel =\n action === 'purge' ? t('query_index.table.actions.purge') : t('query_index.table.actions.reindex')\n const errorMessage = t('query_index.table.errors.actionFailed', { action: actionLabel })\n try {\n await apiCallOrThrow(`/api/query_index/${action}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n }, { errorMessage })\n } catch (err) {\n console.error('query_index.table.trigger', err)\n if (typeof window !== 'undefined') {\n const message = err instanceof Error ? err.message : errorMessage\n window.alert(message)\n }\n }\n qc.invalidateQueries({ queryKey: ['query-index-status'] })\n },\n [qc, t],\n )\n\n const triggerVector = React.useCallback(\n async (action: 'reindex' | 'purge', entityId: string) => {\n if (action === 'purge' && typeof window !== 'undefined') {\n const confirmed = window.confirm(t('query_index.table.confirm.vectorPurge'))\n if (!confirmed) return\n }\n\n const actionLabel = action === 'purge'\n ? t('query_index.table.actions.vectorPurge')\n : t('query_index.table.actions.vectorReindex')\n const errorMessage = t('query_index.table.errors.actionFailed', { action: actionLabel })\n try {\n if (action === 'reindex') {\n await apiCallOrThrow('/api/vector/reindex', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ entityId }),\n }, { errorMessage })\n } else {\n const url = `/api/vector/index?entityId=${encodeURIComponent(entityId)}`\n await apiCallOrThrow(url, { method: 'DELETE' }, { errorMessage })\n }\n } catch (err) {\n console.error('query_index.table.vectorAction', err)\n if (typeof window !== 'undefined') {\n const message = err instanceof Error ? err.message : errorMessage\n window.alert(message)\n }\n }\n qc.invalidateQueries({ queryKey: ['query-index-status'] })\n },\n [qc, t],\n )\n\n const triggerFulltext = React.useCallback(\n async (action: 'reindex' | 'purge', entityId: string) => {\n if (action === 'purge' && typeof window !== 'undefined') {\n const confirmed = window.confirm(t('query_index.table.confirm.fulltextPurge'))\n if (!confirmed) return\n }\n\n const actionLabel = action === 'purge'\n ? t('query_index.table.actions.fulltextPurge')\n : t('query_index.table.actions.fulltextReindex')\n const errorMessage = t('query_index.table.errors.actionFailed', { action: actionLabel })\n try {\n await apiCallOrThrow('/api/search/reindex', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n action: action === 'purge' ? 'clear' : 'reindex',\n entityId,\n }),\n }, { errorMessage })\n } catch (err) {\n console.error('query_index.table.fulltextAction', err)\n if (typeof window !== 'undefined') {\n const message = err instanceof Error ? err.message : errorMessage\n window.alert(message)\n }\n }\n qc.invalidateQueries({ queryKey: ['query-index-status'] })\n },\n [qc, t],\n )\n\n return (\n <DataTable\n title={t('query_index.nav.queryIndexes')}\n actions={(\n <>\n <Button\n variant=\"outline\"\n onClick={() => {\n setRefreshSeq((v) => v + 1)\n qc.invalidateQueries({ queryKey: ['query-index-status'] })\n }}\n >\n {t('query_index.table.refresh')}\n </Button>\n </>\n )}\n columns={columns}\n data={rows}\n searchValue={search}\n searchPlaceholder={t('query_index.table.searchPlaceholder')}\n onSearchChange={(value) => {\n setSearch(value)\n setPage(1)\n }}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n perspective={{ tableId: 'query_index.status.list' }}\n rowActions={(row) => {\n const items: Array<{ id: string; label: string; onSelect: () => void; destructive?: boolean }> = [\n { id: 'reindex', label: t('query_index.table.actions.reindex'), onSelect: () => trigger('reindex', row.entityId) },\n {\n id: 'reindex-force',\n label: t('query_index.table.actions.reindexForce'),\n onSelect: () => trigger('reindex', row.entityId, { force: true }),\n },\n {\n id: 'purge',\n label: t('query_index.table.actions.purge'),\n destructive: true,\n onSelect: () => trigger('purge', row.entityId),\n },\n ]\n\n if (row.vectorEnabled) {\n items.push(\n {\n id: 'vector-reindex',\n label: t('query_index.table.actions.vectorReindex'),\n onSelect: () => triggerVector('reindex', row.entityId),\n },\n {\n id: 'vector-purge',\n label: t('query_index.table.actions.vectorPurge'),\n destructive: true,\n onSelect: () => triggerVector('purge', row.entityId),\n },\n )\n }\n\n if (row.fulltextEnabled) {\n items.push(\n {\n id: 'fulltext-reindex',\n label: t('query_index.table.actions.fulltextReindex'),\n onSelect: () => triggerFulltext('reindex', row.entityId),\n },\n {\n id: 'fulltext-purge',\n label: t('query_index.table.actions.fulltextPurge'),\n destructive: true,\n onSelect: () => triggerFulltext('purge', row.entityId),\n },\n )\n }\n\n return <RowActions items={items} />\n }}\n pagination={{ page, pageSize: 50, total: rows.length, totalPages: 1, onPageChange: setPage }}\n isLoading={isLoading}\n />\n )\n}\n"],
|
|
5
|
-
"mappings": ";AAyGyB,SA8OjB,UA9OiB,KA+Ff,YA/Fe;AAxGzB,YAAY,WAAW;AACvB,SAAS,UAAU,sBAAsB;AAEzC,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAC3B,SAAS,cAAc;AACvB,SAAS,gBAAgB,4BAA4B;AACrD,SAAS,mCAAmC;AAC5C,SAAS,YAAY;AA6CrB,SAAS,YAAY,OAA8B;AACjD,MAAI,SAAS,KAAM,QAAO;AAC1B,SAAO,MAAM,eAAe;AAC9B;AAEA,SAAS,cAAc,OAAiD;AACtE,MAAI,SAAS,KAAM,QAAO;AAC1B,SAAO,OAAO,KAAK,EAAE,eAAe;AACtC;AAEA,SAAS,oBACP,WACA,OACA,GACe;AACf,QAAM,gBAAgB,cAAc,SAAS;AAC7C,MAAI,CAAC,cAAe,QAAO;AAC3B,QAAM,YAAY,cAAc,KAAK;AACrC,MAAI,UAAW,QAAO,EAAE,qCAAqC,EAAE,WAAW,eAAe,OAAO,UAAU,CAAC;AAC3G,SAAO,EAAE,2CAA2C,EAAE,WAAW,cAAc,CAAC;AAClF;AAEA,SAAS,mBAAmB,GAAe,QAAyC,IAAqB;AACvG,MAAI,CAAC,UAAU,WAAW,QAAQ;AAChC,WAAO,KAAK,EAAE,kCAAkC,IAAI,EAAE,sCAAsC;AAAA,EAC9F;AACA,MAAI,WAAW,aAAc,QAAO,EAAE,qCAAqC;AAC3E,MAAI,WAAW,UAAW,QAAO,EAAE,kCAAkC;AACrE,MAAI,WAAW,UAAW,QAAO,EAAE,kCAAkC;AACrE,SAAO,KAAK,EAAE,kCAAkC,IAAI,EAAE,sCAAsC;AAC9F;AAEA,SAAS,qBACP,GACA,QACQ;AACR,MAAI,WAAW,aAAc,QAAO,EAAE,2CAA2C;AACjF,MAAI,WAAW,UAAW,QAAO,EAAE,wCAAwC;AAC3E,MAAI,WAAW,UAAW,QAAO,EAAE,wCAAwC;AAC3E,SAAO,EAAE,0CAA0C;AACrD;AAGA,SAAS,cAAc,GAAiC;AACtD,SAAO;AAAA,IACL,EAAE,IAAI,YAAY,QAAQ,MAAM,EAAE,kCAAkC,GAAG,aAAa,YAAY,MAAM,EAAE,UAAU,EAAE,EAAE;AAAA,IACtH,EAAE,IAAI,SAAS,QAAQ,MAAM,EAAE,iCAAiC,GAAG,aAAa,SAAS,MAAM,EAAE,UAAU,EAAE,EAAE;AAAA,IAC/G;AAAA,MACE,IAAI;AAAA,MACJ,QAAQ,MAAM,EAAE,mCAAmC;AAAA,MACnD,YAAY,CAAC,QAAQ,IAAI,aAAa;AAAA,MACtC,MAAM,CAAC,EAAE,IAAI,MAAM,oBAAC,UAAM,sBAAY,IAAI,SAAS,SAAS,GAAE;AAAA,MAC9D,MAAM,EAAE,UAAU,EAAE;AAAA,IACtB;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,QAAQ,MAAM,EAAE,mCAAmC;AAAA,MACnD,YAAY,CAAC,QAAQ,IAAI,cAAc;AAAA,MACvC,MAAM,CAAC,EAAE,IAAI,MAAM,oBAAC,UAAM,sBAAY,IAAI,SAAS,UAAU,GAAE;AAAA,MAC/D,MAAM,EAAE,UAAU,EAAE;AAAA,IACtB;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,QAAQ,MAAM,EAAE,kCAAkC;AAAA,MAClD,YAAY,CAAC,QAAS,IAAI,gBAAgB,IAAI,eAAe,IAAI;AAAA,MACjE,MAAM,CAAC,EAAE,IAAI,MAAM;AACjB,cAAM,SAAS,IAAI;AACnB,YAAI,CAAC,OAAO,cAAe,QAAO,oBAAC,UAAK,oBAAC;AACzC,cAAM,KAAK,OAAO,eAAe,QAAQ,OAAO,aAAa,QAAQ,OAAO,gBAAgB,OAAO;AACnG,cAAM,UAAU,YAAY,OAAO,WAAW;AAC9C,cAAM,YAAY,KAAK,mBAAmB;AAC1C,eAAO,oBAAC,UAAK,WAAuB,mBAAQ;AAAA,MAC9C;AAAA,MACA,MAAM,EAAE,UAAU,EAAE;AAAA,IACtB;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,QAAQ,MAAM,EAAE,oCAAoC;AAAA,MACpD,YAAY,CAAC,QAAS,IAAI,kBAAkB,IAAI,iBAAiB,IAAI;AAAA,MACrE,MAAM,CAAC,EAAE,IAAI,MAAM;AACjB,cAAM,SAAS,IAAI;AACnB,YAAI,CAAC,OAAO,gBAAiB,QAAO,oBAAC,UAAK,oBAAC;AAC3C,cAAM,KAAK,OAAO,iBAAiB,QAAQ,OAAO,aAAa,QAAQ,OAAO,kBAAkB,OAAO;AACvG,cAAM,UAAU,YAAY,OAAO,aAAa;AAChD,cAAM,YAAY,KAAK,mBAAmB;AAC1C,eAAO,oBAAC,UAAK,WAAuB,mBAAQ;AAAA,MAC9C;AAAA,MACA,MAAM,EAAE,UAAU,EAAE;AAAA,IACtB;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,QAAQ,MAAM,EAAE,kCAAkC;AAAA,MAClD,MAAM,CAAC,EAAE,IAAI,MAAM;AACjB,cAAM,SAAS,IAAI;AACnB,cAAM,MAAM,OAAO;AACnB,cAAM,aAAa,KAAK,cAAc,CAAC;AACvC,cAAM,KAAK,OAAO,OAAO,CAAC,OAAO,IAAI,WAAW;AAChD,cAAM,aAAa,mBAAmB,GAAG,KAAK,QAAQ,EAAE;AACxD,cAAM,cAAc,MAAM,oBAAoB,IAAI,kBAAkB,MAAM,IAAI,cAAc,MAAM,CAAC,IAAI;AACvG,cAAM,QAAQ,cACV,EAAE,yCAAyC,EAAE,QAAQ,YAAY,UAAU,YAAY,CAAC,IACxF;AACJ,cAAM,YAAY,MACd,IAAI,WAAW,YACb,iBACA,IAAI,WAAW,gBAAgB,IAAI,WAAW,YAC5C,oBACA,KACE,mBACA,0BACN,KACE,mBACA;AAEN,cAAM,QAAkB,CAAC;AAEzB,YAAI,KAAK,SAAS,WAAW,UAAU,GAAG;AACxC,gBAAM,cAAc,qBAAqB,GAAG,IAAI,MAAM,UAAU,IAAI;AACpE,gBAAM,gBAAgB,oBAAoB,IAAI,MAAM,kBAAkB,MAAM,IAAI,MAAM,cAAc,MAAM,CAAC;AAC3G,gBAAM,aAAa,EAAE,qCAAqC;AAC1D,gBAAM,KAAK,GAAG,UAAU,KAAK,WAAW,GAAG,gBAAgB,KAAK,aAAa,MAAM,EAAE,EAAE;AAAA,QACzF;AAEA,YAAI,WAAW,SAAS,GAAG;AACzB,qBAAW,QAAQ,YAAY;AAC7B,kBAAM,iBACJ,KAAK,kBAAkB,OACnB,EAAE,2CAA2C,EAAE,OAAO,OAAO,KAAK,cAAc,IAAI,EAAE,CAAC,IACvF,EAAE,qCAAqC;AAC7C,kBAAM,kBAAkB,qBAAqB,GAAG,KAAK,MAAM;AAC3D,kBAAM,oBAAoB,oBAAoB,KAAK,kBAAkB,MAAM,KAAK,cAAc,MAAM,CAAC;AACrG,kBAAM,KAAK,GAAG,cAAc,KAAK,eAAe,GAAG,oBAAoB,KAAK,iBAAiB,MAAM,EAAE,EAAE;AAAA,UACzG;AAAA,QACF;AAEA,YAAI,OAAO,eAAe;AACxB,gBAAM,cAAc,EAAE,sCAAsC;AAC5D,gBAAM,cAAc,YAAY,OAAO,WAAW;AAClD,gBAAM,cAAc,OAAO,aAAa,OAAO,YAAY,OAAO,SAAS,IAAI;AAC/E,gBAAM,cAAc,cAChB,EAAE,wCAAwC,EAAE,OAAO,aAAa,OAAO,YAAY,CAAC,IACpF;AACJ,gBAAM,KAAK,GAAG,WAAW,KAAK,WAAW,EAAE;AAAA,QAC7C;AAEA,eACE,qBAAC,SAAI,WAAU,aACb;AAAA,8BAAC,UAAK,WAAuB,iBAAM;AAAA,UAClC,MAAM,SAAS,KACd,oBAAC,SAAI,WAAU,iCACZ,gBAAM,IAAI,CAAC,MAAM,QAChB,oBAAC,SAAe,kBAAN,GAAW,CACtB,GACH;AAAA,WAEJ;AAAA,MAEJ;AAAA,MACA,MAAM,EAAE,UAAU,EAAE;AAAA,IACtB;AAAA,EACF;AACF;AAEe,SAAR,oBAAqC;AAC1C,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAuB,CAAC,EAAE,IAAI,YAAY,MAAM,MAAM,CAAC,CAAC;AAC5F,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAAS,CAAC;AACxC,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAS,EAAE;AAC7C,QAAM,KAAK,eAAe;AAC1B,QAAM,eAAe,4BAA4B;AACjD,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAS,CAAC;AACpD,QAAM,IAAI,KAAK;AACf,QAAM,UAAU,MAAM,QAAQ,MAAM,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;AAEzD,QAAM,EAAE,MAAM,UAAU,IAAI,SAAe;AAAA,IACzC,UAAU,CAAC,sBAAsB,cAAc,UAAU;AAAA,IACzD,SAAS,YAAY;AACnB,YAAM,UAAU;AAChB,YAAM,MAAM,aAAa,IAAI,GAAG,OAAO,YAAY,UAAU,KAAK;AAClE,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,EAAE,cAAc,EAAE,qCAAqC,EAAE;AAAA,MAC3D;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,EACnB,CAAC;AAED,QAAM,UAAU,MAAM,SAAS,CAAC;AAChC,QAAM,OAAO,MAAM,QAAQ,MAAM;AAC/B,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,IAAI,OAAO,YAAY;AAC7B,WAAO,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,SAAS,CAAC,KAAK,EAAE,MAAM,YAAY,EAAE,SAAS,CAAC,CAAC;AAAA,EACxG,GAAG,CAAC,SAAS,MAAM,CAAC;AAEpB,QAAM,UAAU,MAAM;AAAA,IACpB,OAAO,QAA6B,UAAkB,SAA+B;AACnF,YAAM,OAAgC,EAAE,YAAY,SAAS;AAC7D,UAAI,MAAM,MAAO,MAAK,QAAQ;AAC9B,YAAM,cACJ,WAAW,UAAU,EAAE,iCAAiC,IAAI,EAAE,mCAAmC;AACnG,YAAM,eAAe,EAAE,yCAAyC,EAAE,QAAQ,YAAY,CAAC;AACvF,UAAI;AACF,cAAM,eAAe,oBAAoB,MAAM,IAAI;AAAA,UACjD,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,UAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,QAC3B,GAAG,EAAE,aAAa,CAAC;AAAA,MACrB,SAAS,KAAK;AACZ,gBAAQ,MAAM,6BAA6B,GAAG;AAC9C,YAAI,OAAO,WAAW,aAAa;AACjC,gBAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,iBAAO,MAAM,OAAO;AAAA,QACtB;AAAA,MACF;AACA,SAAG,kBAAkB,EAAE,UAAU,CAAC,oBAAoB,EAAE,CAAC;AAAA,IAC3D;AAAA,IACA,CAAC,IAAI,CAAC;AAAA,EACR;AAEA,QAAM,gBAAgB,MAAM;AAAA,IAC1B,OAAO,QAA6B,aAAqB;AACvD,UAAI,WAAW,WAAW,OAAO,WAAW,aAAa;AACvD,cAAM,YAAY,OAAO,QAAQ,EAAE,uCAAuC,CAAC;AAC3E,YAAI,CAAC,UAAW;AAAA,MAClB;AAEA,YAAM,cAAc,WAAW,UAC3B,EAAE,uCAAuC,IACzC,EAAE,yCAAyC;AAC/C,YAAM,eAAe,EAAE,yCAAyC,EAAE,QAAQ,YAAY,CAAC;AACvF,UAAI;AACF,YAAI,WAAW,WAAW;AACxB,gBAAM,eAAe,uBAAuB;AAAA,YAC1C,QAAQ;AAAA,YACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,YAC9C,MAAM,KAAK,UAAU,EAAE,SAAS,CAAC;AAAA,UACnC,GAAG,EAAE,aAAa,CAAC;AAAA,QACrB,OAAO;AACL,gBAAM,MAAM,8BAA8B,mBAAmB,QAAQ,CAAC;AACtE,gBAAM,eAAe,KAAK,EAAE,QAAQ,SAAS,GAAG,EAAE,aAAa,CAAC;AAAA,QAClE;AAAA,MACF,SAAS,KAAK;AACZ,gBAAQ,MAAM,kCAAkC,GAAG;AACnD,YAAI,OAAO,WAAW,aAAa;AACjC,gBAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,iBAAO,MAAM,OAAO;AAAA,QACtB;AAAA,MACF;AACA,SAAG,kBAAkB,EAAE,UAAU,CAAC,oBAAoB,EAAE,CAAC;AAAA,IAC3D;AAAA,IACA,CAAC,IAAI,CAAC;AAAA,EACR;AAEA,QAAM,kBAAkB,MAAM;AAAA,IAC5B,OAAO,QAA6B,aAAqB;AACvD,UAAI,WAAW,WAAW,OAAO,WAAW,aAAa;AACvD,cAAM,YAAY,OAAO,QAAQ,EAAE,yCAAyC,CAAC;AAC7E,YAAI,CAAC,UAAW;AAAA,MAClB;AAEA,YAAM,cAAc,WAAW,UAC3B,EAAE,yCAAyC,IAC3C,EAAE,2CAA2C;AACjD,YAAM,eAAe,EAAE,yCAAyC,EAAE,QAAQ,YAAY,CAAC;AACvF,UAAI;AACF,cAAM,eAAe,uBAAuB;AAAA,UAC1C,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,UAC9C,MAAM,KAAK,UAAU;AAAA,YACnB,QAAQ,WAAW,UAAU,UAAU;AAAA,YACvC;AAAA,UACF,CAAC;AAAA,QACH,GAAG,EAAE,aAAa,CAAC;AAAA,MACrB,SAAS,KAAK;AACZ,gBAAQ,MAAM,oCAAoC,GAAG;AACrD,YAAI,OAAO,WAAW,aAAa;AACjC,gBAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,iBAAO,MAAM,OAAO;AAAA,QACtB;AAAA,MACF;AACA,SAAG,kBAAkB,EAAE,UAAU,CAAC,oBAAoB,EAAE,CAAC;AAAA,IAC3D;AAAA,IACA,CAAC,IAAI,CAAC;AAAA,EACR;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,EAAE,8BAA8B;AAAA,MACvC,SACE,gCACE;AAAA,QAAC;AAAA;AAAA,UACC,SAAQ;AAAA,UACR,SAAS,MAAM;AACb,0BAAc,CAAC,MAAM,IAAI,CAAC;AAC1B,eAAG,kBAAkB,EAAE,UAAU,CAAC,oBAAoB,EAAE,CAAC;AAAA,UAC3D;AAAA,UAEC,YAAE,2BAA2B;AAAA;AAAA,MAChC,GACF;AAAA,MAEF;AAAA,MACA,MAAM;AAAA,MACN,aAAa;AAAA,MACb,mBAAmB,EAAE,qCAAqC;AAAA,MAC1D,gBAAgB,CAAC,UAAU;AACzB,kBAAU,KAAK;AACf,gBAAQ,CAAC;AAAA,MACX;AAAA,MACA,UAAQ;AAAA,MACR;AAAA,MACA,iBAAiB;AAAA,MACjB,aAAa,EAAE,SAAS,0BAA0B;AAAA,MAClD,YAAY,CAAC,QAAQ;AACnB,cAAM,
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { apiCallOrThrow, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\ntype Translator = (key: string, params?: Record<string, string | number>) => string\n\ntype PartitionStatus = {\n partitionIndex: number | null\n partitionCount: number | null\n status: 'reindexing' | 'purging' | 'stalled' | 'completed'\n processedCount?: number | null\n totalCount?: number | null\n heartbeatAt?: string | null\n startedAt?: string | null\n finishedAt?: string | null\n}\n\ntype JobStatus = {\n status: 'idle' | 'reindexing' | 'purging' | 'stalled'\n startedAt?: string | null\n finishedAt?: string | null\n heartbeatAt?: string | null\n processedCount?: number | null\n totalCount?: number | null\n partitions?: PartitionStatus[]\n scope?: {\n status?: 'reindexing' | 'purging' | 'stalled' | 'completed' | null\n processedCount?: number | null\n totalCount?: number | null\n } | null\n}\n\ntype Row = {\n entityId: string\n label: string\n baseCount: number | null\n indexCount: number | null\n vectorCount: number | null\n vectorEnabled: boolean\n fulltextCount: number | null\n fulltextEnabled: boolean\n ok: boolean\n job?: JobStatus\n}\n\ntype Resp = { items: Row[] }\n\nfunction formatCount(value: number | null): string {\n if (value == null) return '\u2014'\n return value.toLocaleString()\n}\n\nfunction formatNumeric(value: number | null | undefined): string | null {\n if (value == null) return null\n return Number(value).toLocaleString()\n}\n\nfunction formatProgressLabel(\n processed: number | null | undefined,\n total: number | null | undefined,\n t: Translator,\n): string | null {\n const processedText = formatNumeric(processed)\n if (!processedText) return null\n const totalText = formatNumeric(total)\n if (totalText) return t('query_index.table.status.progress', { processed: processedText, total: totalText })\n return t('query_index.table.status.progressSingle', { processed: processedText })\n}\n\nfunction translateJobStatus(t: Translator, status: JobStatus['status'] | undefined, ok: boolean): string {\n if (!status || status === 'idle') {\n return ok ? t('query_index.table.status.in_sync') : t('query_index.table.status.out_of_sync')\n }\n if (status === 'reindexing') return t('query_index.table.status.reindexing')\n if (status === 'purging') return t('query_index.table.status.purging')\n if (status === 'stalled') return t('query_index.table.status.stalled')\n return ok ? t('query_index.table.status.in_sync') : t('query_index.table.status.out_of_sync')\n}\n\nfunction translateScopeStatus(\n t: Translator,\n status: PartitionStatus['status'] | JobStatus['status'] | undefined | null,\n): string {\n if (status === 'reindexing') return t('query_index.table.status.scope.reindexing')\n if (status === 'purging') return t('query_index.table.status.scope.purging')\n if (status === 'stalled') return t('query_index.table.status.scope.stalled')\n return t('query_index.table.status.scope.completed')\n}\n\n\nfunction createColumns(t: Translator): ColumnDef<Row>[] {\n return [\n { id: 'entityId', header: () => t('query_index.table.columns.entity'), accessorKey: 'entityId', meta: { priority: 1 } },\n { id: 'label', header: () => t('query_index.table.columns.label'), accessorKey: 'label', meta: { priority: 2 } },\n {\n id: 'baseCount',\n header: () => t('query_index.table.columns.records'),\n accessorFn: (row) => row.baseCount ?? 0,\n cell: ({ row }) => <span>{formatCount(row.original.baseCount)}</span>,\n meta: { priority: 2 },\n },\n {\n id: 'indexCount',\n header: () => t('query_index.table.columns.indexed'),\n accessorFn: (row) => row.indexCount ?? 0,\n cell: ({ row }) => <span>{formatCount(row.original.indexCount)}</span>,\n meta: { priority: 2 },\n },\n {\n id: 'vectorCount',\n header: () => t('query_index.table.columns.vector'),\n accessorFn: (row) => (row.vectorEnabled ? row.vectorCount ?? 0 : -1),\n cell: ({ row }) => {\n const record = row.original\n if (!record.vectorEnabled) return <span>\u2014</span>\n const ok = record.vectorCount != null && record.baseCount != null && record.vectorCount === record.baseCount\n const display = formatCount(record.vectorCount)\n const className = ok ? 'text-green-600' : 'text-orange-600'\n return <span className={className}>{display}</span>\n },\n meta: { priority: 2 },\n },\n {\n id: 'fulltextCount',\n header: () => t('query_index.table.columns.fulltext'),\n accessorFn: (row) => (row.fulltextEnabled ? row.fulltextCount ?? 0 : -1),\n cell: ({ row }) => {\n const record = row.original\n if (!record.fulltextEnabled) return <span>\u2014</span>\n const ok = record.fulltextCount != null && record.baseCount != null && record.fulltextCount === record.baseCount\n const display = formatCount(record.fulltextCount)\n const className = ok ? 'text-green-600' : 'text-orange-600'\n return <span className={className}>{display}</span>\n },\n meta: { priority: 2 },\n },\n {\n id: 'status',\n header: () => t('query_index.table.columns.status'),\n cell: ({ row }) => {\n const record = row.original\n const job = record.job\n const partitions = job?.partitions ?? []\n const ok = record.ok && (!job || job.status === 'idle')\n const statusText = translateJobStatus(t, job?.status, ok)\n const jobProgress = job ? formatProgressLabel(job.processedCount ?? null, job.totalCount ?? null, t) : null\n const label = jobProgress\n ? t('query_index.table.status.withProgress', { status: statusText, progress: jobProgress })\n : statusText\n const className = job\n ? job.status === 'stalled'\n ? 'text-red-600'\n : job.status === 'reindexing' || job.status === 'purging'\n ? 'text-orange-600'\n : ok\n ? 'text-green-600'\n : 'text-muted-foreground'\n : ok\n ? 'text-green-600'\n : 'text-muted-foreground'\n\n const lines: string[] = []\n\n if (job?.scope && partitions.length <= 1) {\n const scopeStatus = translateScopeStatus(t, job.scope.status ?? null)\n const scopeProgress = formatProgressLabel(job.scope.processedCount ?? null, job.scope.totalCount ?? null, t)\n const scopeLabel = t('query_index.table.status.scopeLabel')\n lines.push(`${scopeLabel}: ${scopeStatus}${scopeProgress ? ` (${scopeProgress})` : ''}`)\n }\n\n if (partitions.length > 1) {\n for (const part of partitions) {\n const partitionLabel =\n part.partitionIndex != null\n ? t('query_index.table.status.partitionLabel', { index: Number(part.partitionIndex) + 1 })\n : t('query_index.table.status.scopeLabel')\n const partitionStatus = translateScopeStatus(t, part.status)\n const partitionProgress = formatProgressLabel(part.processedCount ?? null, part.totalCount ?? null, t)\n lines.push(`${partitionLabel}: ${partitionStatus}${partitionProgress ? ` (${partitionProgress})` : ''}`)\n }\n }\n\n if (record.vectorEnabled) {\n const vectorLabel = t('query_index.table.status.vectorLabel')\n const vectorCount = formatCount(record.vectorCount)\n const vectorTotal = record.baseCount != null ? formatCount(record.baseCount) : null\n const vectorValue = vectorTotal\n ? t('query_index.table.status.vectorValue', { count: vectorCount, total: vectorTotal })\n : vectorCount\n lines.push(`${vectorLabel}: ${vectorValue}`)\n }\n\n return (\n <div className=\"space-y-1\">\n <span className={className}>{label}</span>\n {lines.length > 0 && (\n <div className=\"text-xs text-muted-foreground\">\n {lines.map((line, idx) => (\n <div key={idx}>{line}</div>\n ))}\n </div>\n )}\n </div>\n )\n },\n meta: { priority: 1 },\n },\n ]\n}\n\nexport default function QueryIndexesTable() {\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'entityId', desc: false }])\n const [page, setPage] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const qc = useQueryClient()\n const scopeVersion = useOrganizationScopeVersion()\n const [refreshSeq, setRefreshSeq] = React.useState(0)\n const t = useT()\n const columns = React.useMemo(() => createColumns(t), [t])\n\n const { data, isLoading } = useQuery<Resp>({\n queryKey: ['query-index-status', scopeVersion, refreshSeq],\n queryFn: async () => {\n const baseUrl = '/api/query_index/status'\n const url = refreshSeq > 0 ? `${baseUrl}?refresh=${refreshSeq}` : baseUrl\n return readApiResultOrThrow<Resp>(\n url,\n undefined,\n { errorMessage: t('query_index.table.errors.loadFailed') },\n )\n },\n refetchInterval: 4000,\n })\n\n const rowsAll = data?.items || []\n const rows = React.useMemo(() => {\n if (!search) return rowsAll\n const q = search.toLowerCase()\n return rowsAll.filter((r) => r.entityId.toLowerCase().includes(q) || r.label.toLowerCase().includes(q))\n }, [rowsAll, search])\n\n const trigger = React.useCallback(\n async (action: 'reindex' | 'purge', entityId: string, opts?: { force?: boolean }) => {\n const body: Record<string, unknown> = { entityType: entityId }\n if (opts?.force) body.force = true\n const actionLabel =\n action === 'purge' ? t('query_index.table.actions.purge') : t('query_index.table.actions.reindex')\n const errorMessage = t('query_index.table.errors.actionFailed', { action: actionLabel })\n try {\n await apiCallOrThrow(`/api/query_index/${action}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n }, { errorMessage })\n } catch (err) {\n console.error('query_index.table.trigger', err)\n if (typeof window !== 'undefined') {\n const message = err instanceof Error ? err.message : errorMessage\n window.alert(message)\n }\n }\n qc.invalidateQueries({ queryKey: ['query-index-status'] })\n },\n [qc, t],\n )\n\n const triggerVector = React.useCallback(\n async (action: 'reindex' | 'purge', entityId: string) => {\n if (action === 'purge' && typeof window !== 'undefined') {\n const confirmed = window.confirm(t('query_index.table.confirm.vectorPurge'))\n if (!confirmed) return\n }\n\n const actionLabel = action === 'purge'\n ? t('query_index.table.actions.vectorPurge')\n : t('query_index.table.actions.vectorReindex')\n const errorMessage = t('query_index.table.errors.actionFailed', { action: actionLabel })\n try {\n if (action === 'reindex') {\n await apiCallOrThrow('/api/vector/reindex', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ entityId }),\n }, { errorMessage })\n } else {\n const url = `/api/vector/index?entityId=${encodeURIComponent(entityId)}`\n await apiCallOrThrow(url, { method: 'DELETE' }, { errorMessage })\n }\n } catch (err) {\n console.error('query_index.table.vectorAction', err)\n if (typeof window !== 'undefined') {\n const message = err instanceof Error ? err.message : errorMessage\n window.alert(message)\n }\n }\n qc.invalidateQueries({ queryKey: ['query-index-status'] })\n },\n [qc, t],\n )\n\n const triggerFulltext = React.useCallback(\n async (action: 'reindex' | 'purge', entityId: string) => {\n if (action === 'purge' && typeof window !== 'undefined') {\n const confirmed = window.confirm(t('query_index.table.confirm.fulltextPurge'))\n if (!confirmed) return\n }\n\n const actionLabel = action === 'purge'\n ? t('query_index.table.actions.fulltextPurge')\n : t('query_index.table.actions.fulltextReindex')\n const errorMessage = t('query_index.table.errors.actionFailed', { action: actionLabel })\n try {\n await apiCallOrThrow('/api/search/reindex', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n action: action === 'purge' ? 'clear' : 'reindex',\n entityId,\n }),\n }, { errorMessage })\n } catch (err) {\n console.error('query_index.table.fulltextAction', err)\n if (typeof window !== 'undefined') {\n const message = err instanceof Error ? err.message : errorMessage\n window.alert(message)\n }\n }\n qc.invalidateQueries({ queryKey: ['query-index-status'] })\n },\n [qc, t],\n )\n\n return (\n <DataTable\n title={t('query_index.nav.queryIndexes')}\n actions={(\n <>\n <Button\n variant=\"outline\"\n onClick={() => {\n setRefreshSeq((v) => v + 1)\n qc.invalidateQueries({ queryKey: ['query-index-status'] })\n }}\n >\n {t('query_index.table.refresh')}\n </Button>\n </>\n )}\n columns={columns}\n data={rows}\n searchValue={search}\n searchPlaceholder={t('query_index.table.searchPlaceholder')}\n onSearchChange={(value) => {\n setSearch(value)\n setPage(1)\n }}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n perspective={{ tableId: 'query_index.status.list' }}\n rowActions={(row) => {\n const items: Array<{ label: string; onSelect: () => void; destructive?: boolean }> = [\n { label: t('query_index.table.actions.reindex'), onSelect: () => trigger('reindex', row.entityId) },\n {\n label: t('query_index.table.actions.reindexForce'),\n onSelect: () => trigger('reindex', row.entityId, { force: true }),\n },\n {\n label: t('query_index.table.actions.purge'),\n destructive: true,\n onSelect: () => trigger('purge', row.entityId),\n },\n ]\n\n if (row.vectorEnabled) {\n items.push(\n {\n label: t('query_index.table.actions.vectorReindex'),\n onSelect: () => triggerVector('reindex', row.entityId),\n },\n {\n label: t('query_index.table.actions.vectorPurge'),\n destructive: true,\n onSelect: () => triggerVector('purge', row.entityId),\n },\n )\n }\n\n if (row.fulltextEnabled) {\n items.push(\n {\n label: t('query_index.table.actions.fulltextReindex'),\n onSelect: () => triggerFulltext('reindex', row.entityId),\n },\n {\n label: t('query_index.table.actions.fulltextPurge'),\n destructive: true,\n onSelect: () => triggerFulltext('purge', row.entityId),\n },\n )\n }\n\n return <RowActions items={items} />\n }}\n pagination={{ page, pageSize: 50, total: rows.length, totalPages: 1, onPageChange: setPage }}\n isLoading={isLoading}\n />\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -216,8 +216,8 @@ function ResourcesResourceTypesPage() {
|
|
|
216
216
|
RowActions,
|
|
217
217
|
{
|
|
218
218
|
items: [
|
|
219
|
-
{
|
|
220
|
-
...row.resourceCount > 0 ? [] : [{
|
|
219
|
+
{ label: translations.actions.edit, href: `/backend/resources/resource-types/${row.id}/edit` },
|
|
220
|
+
...row.resourceCount > 0 ? [] : [{ label: translations.actions.delete, destructive: true, onSelect: () => handleDelete(row) }]
|
|
221
221
|
]
|
|
222
222
|
}
|
|
223
223
|
),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/resources/backend/resources/resource-types/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport Link from 'next/link'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport type { PluggableList } from 'unified'\nimport ReactMarkdown from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { renderDictionaryColor, renderDictionaryIcon } from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\nimport { Package } from 'lucide-react'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\nconst PAGE_SIZE = 50\nconst MARKDOWN_PLUGINS: PluggableList = [remarkGfm]\nconst MARKDOWN_DESCRIPTION_CLASSNAME =\n 'text-sm text-foreground [&>p]:m-0 [&_ul]:ml-4 [&_ul]:list-disc [&_ol]:ml-4 [&_ol]:list-decimal [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5'\nconst MARKDOWN_SUBTEXT_CLASSNAME =\n 'text-xs text-muted-foreground [&>p]:m-0 [&_ul]:ml-4 [&_ul]:list-disc [&_ol]:ml-4 [&_ol]:list-decimal [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5'\n\ntype ResourceTypeRow = {\n id: string\n name: string\n description: string | null\n appearanceIcon: string | null\n appearanceColor: string | null\n updatedAt: string | null\n resourceCount: number\n}\n\ntype ResourceTypesResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n totalPages?: number\n}\n\nexport default function ResourcesResourceTypesPage() {\n const translate = useT()\n const router = useRouter()\n const scopeVersion = useOrganizationScopeVersion()\n const [rows, setRows] = React.useState<ResourceTypeRow[]>([])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'name', desc: false }])\n const [search, setSearch] = React.useState('')\n const [isLoading, setIsLoading] = React.useState(true)\n const [reloadToken, setReloadToken] = React.useState(0)\n\n const translations = React.useMemo(() => ({\n title: translate('resources.resourceTypes.page.title', 'Resource types'),\n description: translate('resources.resourceTypes.page.description', 'Organize shared resources by category.'),\n table: {\n name: translate('resources.resourceTypes.table.name', 'Name'),\n description: translate('resources.resourceTypes.table.description', 'Description'),\n appearance: translate('resources.resourceTypes.table.appearance', 'Appearance'),\n resources: translate('resources.resourceTypes.table.resources', 'Resources'),\n updatedAt: translate('resources.resourceTypes.table.updatedAt', 'Updated'),\n empty: translate('resources.resourceTypes.table.empty', 'No resource types yet.'),\n search: translate('resources.resourceTypes.table.search', 'Search resource types\u2026'),\n },\n actions: {\n add: translate('resources.resourceTypes.actions.add', 'Add resource type'),\n edit: translate('resources.resourceTypes.actions.edit', 'Edit'),\n delete: translate('resources.resourceTypes.actions.delete', 'Delete'),\n deleteConfirm: translate('resources.resourceTypes.actions.deleteConfirm', 'Delete resource type \"{{name}}\"?'),\n showResources: translate('resources.resourceTypes.actions.showResources', 'Show resources ({{count}})'),\n refresh: translate('resources.resourceTypes.actions.refresh', 'Refresh'),\n },\n form: {\n createTitle: translate('resources.resourceTypes.form.createTitle', 'Add resource type'),\n editTitle: translate('resources.resourceTypes.form.editTitle', 'Edit resource type'),\n name: translate('resources.resourceTypes.form.name', 'Name'),\n description: translate('resources.resourceTypes.form.description', 'Description'),\n save: translate('resources.resourceTypes.form.save', 'Save'),\n cancel: translate('resources.resourceTypes.form.cancel', 'Cancel'),\n },\n messages: {\n saved: translate('resources.resourceTypes.messages.saved', 'Resource type saved.'),\n deleted: translate('resources.resourceTypes.messages.deleted', 'Resource type deleted.'),\n },\n errors: {\n load: translate('resources.resourceTypes.errors.load', 'Failed to load resource types.'),\n save: translate('resources.resourceTypes.errors.save', 'Failed to save resource type.'),\n delete: translate('resources.resourceTypes.errors.delete', 'Failed to delete resource type.'),\n deleteAssigned: translate('resources.resourceTypes.errors.deleteAssigned', 'Resource type has assigned resources.'),\n },\n }), [translate])\n\n const columns = React.useMemo<ColumnDef<ResourceTypeRow>[]>(() => [\n {\n accessorKey: 'name',\n header: translations.table.name,\n meta: { priority: 1, sticky: true },\n cell: ({ row }) => (\n <div className=\"flex flex-col\">\n <span className=\"font-medium\">{row.original.name}</span>\n {row.original.description ? (\n <ReactMarkdown remarkPlugins={MARKDOWN_PLUGINS} className={MARKDOWN_SUBTEXT_CLASSNAME}>\n {row.original.description}\n </ReactMarkdown>\n ) : null}\n </div>\n ),\n },\n {\n accessorKey: 'appearance',\n header: translations.table.appearance,\n meta: { priority: 2 },\n cell: ({ row }) => {\n const icon = row.original.appearanceIcon\n const color = row.original.appearanceColor\n if (!icon && !color) {\n return <span className=\"text-xs text-muted-foreground\">\u2014</span>\n }\n return (\n <div className=\"flex items-center gap-2\">\n {color ? renderDictionaryColor(color) : null}\n {icon ? renderDictionaryIcon(icon) : null}\n </div>\n )\n },\n },\n {\n accessorKey: 'resourceCount',\n header: translations.table.resources,\n meta: { priority: 3 },\n cell: ({ row }) => (\n <Link\n className=\"inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground\"\n href={`/backend/resources/resources?resourceTypeId=${encodeURIComponent(row.original.id)}`}\n onClick={(event) => event.stopPropagation()}\n >\n <Package className=\"h-4 w-4\" aria-hidden />\n {translations.actions.showResources.replace('{{count}}', String(row.original.resourceCount))}\n </Link>\n ),\n },\n {\n accessorKey: 'description',\n header: translations.table.description,\n meta: { priority: 5 },\n cell: ({ row }) => row.original.description ? (\n <ReactMarkdown remarkPlugins={MARKDOWN_PLUGINS} className={MARKDOWN_DESCRIPTION_CLASSNAME}>\n {row.original.description}\n </ReactMarkdown>\n ) : (\n <span className=\"text-xs text-muted-foreground\">\u2014</span>\n ),\n },\n {\n accessorKey: 'updatedAt',\n header: translations.table.updatedAt,\n meta: { priority: 4 },\n cell: ({ row }) => row.original.updatedAt\n ? <span className=\"text-xs text-muted-foreground\">{formatDateTime(row.original.updatedAt)}</span>\n : <span className=\"text-xs text-muted-foreground\">\u2014</span>,\n },\n ], [\n translations.actions.showResources,\n translations.table.appearance,\n translations.table.description,\n translations.table.name,\n translations.table.resources,\n translations.table.updatedAt,\n ])\n\n const loadResourceTypes = React.useCallback(async () => {\n setIsLoading(true)\n try {\n const params = new URLSearchParams({\n page: String(page),\n pageSize: String(PAGE_SIZE),\n })\n const sort = sorting[0]\n if (sort?.id) {\n params.set('sortField', sort.id)\n params.set('sortDir', sort.desc ? 'desc' : 'asc')\n }\n if (search.trim()) {\n params.set('search', search.trim())\n }\n const payload = await readApiResultOrThrow<ResourceTypesResponse>(\n `/api/resources/resource-types?${params.toString()}`,\n undefined,\n { errorMessage: translations.errors.load, fallback: { items: [], total: 0, totalPages: 1 } },\n )\n const items = Array.isArray(payload.items) ? payload.items : []\n setRows(items.map(mapApiResourceType))\n setTotal(typeof payload.total === 'number' ? payload.total : items.length)\n setTotalPages(typeof payload.totalPages === 'number' ? payload.totalPages : Math.max(1, Math.ceil(items.length / PAGE_SIZE)))\n } catch (error) {\n console.error('resources.resource-types.list', error)\n flash(translations.errors.load, 'error')\n } finally {\n setIsLoading(false)\n }\n }, [page, search, sorting, translations.errors.load])\n\n React.useEffect(() => {\n void loadResourceTypes()\n }, [loadResourceTypes, scopeVersion, reloadToken])\n\n const handleSearchChange = React.useCallback((value: string) => {\n setSearch(value)\n setPage(1)\n }, [])\n\n const handleRefresh = React.useCallback(() => {\n setReloadToken((token) => token + 1)\n }, [])\n\n const handleDelete = React.useCallback(async (entry: ResourceTypeRow) => {\n if (entry.resourceCount > 0) {\n flash(translations.errors.deleteAssigned, 'error')\n return\n }\n const message = translations.actions.deleteConfirm.replace('{{name}}', entry.name)\n if (typeof window !== 'undefined' && !window.confirm(message)) return\n try {\n await deleteCrud('resources/resource-types', entry.id, { errorMessage: translations.errors.delete })\n flash(translations.messages.deleted, 'success')\n handleRefresh()\n } catch (error) {\n console.error('resources.resource-types.delete', error)\n flash(translations.errors.delete, 'error')\n }\n }, [handleRefresh, translations.actions.deleteConfirm, translations.errors.delete, translations.errors.deleteAssigned, translations.messages.deleted])\n\n return (\n <Page>\n <PageBody>\n <DataTable<ResourceTypeRow>\n title={translations.title}\n data={rows}\n columns={columns}\n isLoading={isLoading}\n searchValue={search}\n onSearchChange={handleSearchChange}\n searchPlaceholder={translations.table.search}\n emptyState={<p className=\"py-8 text-center text-sm text-muted-foreground\">{translations.table.empty}</p>}\n actions={(\n <Button asChild size=\"sm\">\n <Link href=\"/backend/resources/resource-types/create\">\n {translations.actions.add}\n </Link>\n </Button>\n )}\n refreshButton={{\n label: translations.actions.refresh,\n onRefresh: handleRefresh,\n isRefreshing: isLoading,\n }}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n pagination={{ page, pageSize: PAGE_SIZE, total, totalPages, onPageChange: setPage }}\n rowActions={(row) => (\n <RowActions\n items={[\n { id: 'edit', label: translations.actions.edit, href: `/backend/resources/resource-types/${row.id}/edit` },\n ...(row.resourceCount > 0\n ? []\n : [{ id: 'delete', label: translations.actions.delete, destructive: true, onSelect: () => handleDelete(row) }]),\n ]}\n />\n )}\n onRowClick={(row) => router.push(`/backend/resources/resource-types/${row.id}/edit`)}\n perspective={{ tableId: 'resources.resource-types.list' }}\n />\n </PageBody>\n </Page>\n )\n}\n\nfunction mapApiResourceType(item: Record<string, unknown>): ResourceTypeRow {\n const id = typeof item.id === 'string' ? item.id : ''\n const name = typeof item.name === 'string' && item.name.length ? item.name : id\n const description = typeof item.description === 'string' && item.description.length\n ? item.description\n : typeof item.description === 'string'\n ? item.description\n : null\n const appearanceIcon = typeof item.appearanceIcon === 'string'\n ? item.appearanceIcon\n : typeof item.appearance_icon === 'string'\n ? item.appearance_icon\n : null\n const appearanceColor = typeof item.appearanceColor === 'string'\n ? item.appearanceColor\n : typeof item.appearance_color === 'string'\n ? item.appearance_color\n : null\n const updatedAt = typeof item.updatedAt === 'string'\n ? item.updatedAt\n : typeof item.updated_at === 'string'\n ? item.updated_at\n : null\n const resourceCount = typeof item.resourceCount === 'number'\n ? item.resourceCount\n : typeof item.resource_count === 'number'\n ? item.resource_count\n : 0\n return { id, name, description, appearanceIcon, appearanceColor, updatedAt, resourceCount }\n}\n\nfunction formatDateTime(value: string): string {\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return value\n return date.toLocaleString()\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport Link from 'next/link'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport type { PluggableList } from 'unified'\nimport ReactMarkdown from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { renderDictionaryColor, renderDictionaryIcon } from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\nimport { Package } from 'lucide-react'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\nconst PAGE_SIZE = 50\nconst MARKDOWN_PLUGINS: PluggableList = [remarkGfm]\nconst MARKDOWN_DESCRIPTION_CLASSNAME =\n 'text-sm text-foreground [&>p]:m-0 [&_ul]:ml-4 [&_ul]:list-disc [&_ol]:ml-4 [&_ol]:list-decimal [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5'\nconst MARKDOWN_SUBTEXT_CLASSNAME =\n 'text-xs text-muted-foreground [&>p]:m-0 [&_ul]:ml-4 [&_ul]:list-disc [&_ol]:ml-4 [&_ol]:list-decimal [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5'\n\ntype ResourceTypeRow = {\n id: string\n name: string\n description: string | null\n appearanceIcon: string | null\n appearanceColor: string | null\n updatedAt: string | null\n resourceCount: number\n}\n\ntype ResourceTypesResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n totalPages?: number\n}\n\nexport default function ResourcesResourceTypesPage() {\n const translate = useT()\n const router = useRouter()\n const scopeVersion = useOrganizationScopeVersion()\n const [rows, setRows] = React.useState<ResourceTypeRow[]>([])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'name', desc: false }])\n const [search, setSearch] = React.useState('')\n const [isLoading, setIsLoading] = React.useState(true)\n const [reloadToken, setReloadToken] = React.useState(0)\n\n const translations = React.useMemo(() => ({\n title: translate('resources.resourceTypes.page.title', 'Resource types'),\n description: translate('resources.resourceTypes.page.description', 'Organize shared resources by category.'),\n table: {\n name: translate('resources.resourceTypes.table.name', 'Name'),\n description: translate('resources.resourceTypes.table.description', 'Description'),\n appearance: translate('resources.resourceTypes.table.appearance', 'Appearance'),\n resources: translate('resources.resourceTypes.table.resources', 'Resources'),\n updatedAt: translate('resources.resourceTypes.table.updatedAt', 'Updated'),\n empty: translate('resources.resourceTypes.table.empty', 'No resource types yet.'),\n search: translate('resources.resourceTypes.table.search', 'Search resource types\u2026'),\n },\n actions: {\n add: translate('resources.resourceTypes.actions.add', 'Add resource type'),\n edit: translate('resources.resourceTypes.actions.edit', 'Edit'),\n delete: translate('resources.resourceTypes.actions.delete', 'Delete'),\n deleteConfirm: translate('resources.resourceTypes.actions.deleteConfirm', 'Delete resource type \"{{name}}\"?'),\n showResources: translate('resources.resourceTypes.actions.showResources', 'Show resources ({{count}})'),\n refresh: translate('resources.resourceTypes.actions.refresh', 'Refresh'),\n },\n form: {\n createTitle: translate('resources.resourceTypes.form.createTitle', 'Add resource type'),\n editTitle: translate('resources.resourceTypes.form.editTitle', 'Edit resource type'),\n name: translate('resources.resourceTypes.form.name', 'Name'),\n description: translate('resources.resourceTypes.form.description', 'Description'),\n save: translate('resources.resourceTypes.form.save', 'Save'),\n cancel: translate('resources.resourceTypes.form.cancel', 'Cancel'),\n },\n messages: {\n saved: translate('resources.resourceTypes.messages.saved', 'Resource type saved.'),\n deleted: translate('resources.resourceTypes.messages.deleted', 'Resource type deleted.'),\n },\n errors: {\n load: translate('resources.resourceTypes.errors.load', 'Failed to load resource types.'),\n save: translate('resources.resourceTypes.errors.save', 'Failed to save resource type.'),\n delete: translate('resources.resourceTypes.errors.delete', 'Failed to delete resource type.'),\n deleteAssigned: translate('resources.resourceTypes.errors.deleteAssigned', 'Resource type has assigned resources.'),\n },\n }), [translate])\n\n const columns = React.useMemo<ColumnDef<ResourceTypeRow>[]>(() => [\n {\n accessorKey: 'name',\n header: translations.table.name,\n meta: { priority: 1, sticky: true },\n cell: ({ row }) => (\n <div className=\"flex flex-col\">\n <span className=\"font-medium\">{row.original.name}</span>\n {row.original.description ? (\n <ReactMarkdown remarkPlugins={MARKDOWN_PLUGINS} className={MARKDOWN_SUBTEXT_CLASSNAME}>\n {row.original.description}\n </ReactMarkdown>\n ) : null}\n </div>\n ),\n },\n {\n accessorKey: 'appearance',\n header: translations.table.appearance,\n meta: { priority: 2 },\n cell: ({ row }) => {\n const icon = row.original.appearanceIcon\n const color = row.original.appearanceColor\n if (!icon && !color) {\n return <span className=\"text-xs text-muted-foreground\">\u2014</span>\n }\n return (\n <div className=\"flex items-center gap-2\">\n {color ? renderDictionaryColor(color) : null}\n {icon ? renderDictionaryIcon(icon) : null}\n </div>\n )\n },\n },\n {\n accessorKey: 'resourceCount',\n header: translations.table.resources,\n meta: { priority: 3 },\n cell: ({ row }) => (\n <Link\n className=\"inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground\"\n href={`/backend/resources/resources?resourceTypeId=${encodeURIComponent(row.original.id)}`}\n onClick={(event) => event.stopPropagation()}\n >\n <Package className=\"h-4 w-4\" aria-hidden />\n {translations.actions.showResources.replace('{{count}}', String(row.original.resourceCount))}\n </Link>\n ),\n },\n {\n accessorKey: 'description',\n header: translations.table.description,\n meta: { priority: 5 },\n cell: ({ row }) => row.original.description ? (\n <ReactMarkdown remarkPlugins={MARKDOWN_PLUGINS} className={MARKDOWN_DESCRIPTION_CLASSNAME}>\n {row.original.description}\n </ReactMarkdown>\n ) : (\n <span className=\"text-xs text-muted-foreground\">\u2014</span>\n ),\n },\n {\n accessorKey: 'updatedAt',\n header: translations.table.updatedAt,\n meta: { priority: 4 },\n cell: ({ row }) => row.original.updatedAt\n ? <span className=\"text-xs text-muted-foreground\">{formatDateTime(row.original.updatedAt)}</span>\n : <span className=\"text-xs text-muted-foreground\">\u2014</span>,\n },\n ], [\n translations.actions.showResources,\n translations.table.appearance,\n translations.table.description,\n translations.table.name,\n translations.table.resources,\n translations.table.updatedAt,\n ])\n\n const loadResourceTypes = React.useCallback(async () => {\n setIsLoading(true)\n try {\n const params = new URLSearchParams({\n page: String(page),\n pageSize: String(PAGE_SIZE),\n })\n const sort = sorting[0]\n if (sort?.id) {\n params.set('sortField', sort.id)\n params.set('sortDir', sort.desc ? 'desc' : 'asc')\n }\n if (search.trim()) {\n params.set('search', search.trim())\n }\n const payload = await readApiResultOrThrow<ResourceTypesResponse>(\n `/api/resources/resource-types?${params.toString()}`,\n undefined,\n { errorMessage: translations.errors.load, fallback: { items: [], total: 0, totalPages: 1 } },\n )\n const items = Array.isArray(payload.items) ? payload.items : []\n setRows(items.map(mapApiResourceType))\n setTotal(typeof payload.total === 'number' ? payload.total : items.length)\n setTotalPages(typeof payload.totalPages === 'number' ? payload.totalPages : Math.max(1, Math.ceil(items.length / PAGE_SIZE)))\n } catch (error) {\n console.error('resources.resource-types.list', error)\n flash(translations.errors.load, 'error')\n } finally {\n setIsLoading(false)\n }\n }, [page, search, sorting, translations.errors.load])\n\n React.useEffect(() => {\n void loadResourceTypes()\n }, [loadResourceTypes, scopeVersion, reloadToken])\n\n const handleSearchChange = React.useCallback((value: string) => {\n setSearch(value)\n setPage(1)\n }, [])\n\n const handleRefresh = React.useCallback(() => {\n setReloadToken((token) => token + 1)\n }, [])\n\n const handleDelete = React.useCallback(async (entry: ResourceTypeRow) => {\n if (entry.resourceCount > 0) {\n flash(translations.errors.deleteAssigned, 'error')\n return\n }\n const message = translations.actions.deleteConfirm.replace('{{name}}', entry.name)\n if (typeof window !== 'undefined' && !window.confirm(message)) return\n try {\n await deleteCrud('resources/resource-types', entry.id, { errorMessage: translations.errors.delete })\n flash(translations.messages.deleted, 'success')\n handleRefresh()\n } catch (error) {\n console.error('resources.resource-types.delete', error)\n flash(translations.errors.delete, 'error')\n }\n }, [handleRefresh, translations.actions.deleteConfirm, translations.errors.delete, translations.errors.deleteAssigned, translations.messages.deleted])\n\n return (\n <Page>\n <PageBody>\n <DataTable<ResourceTypeRow>\n title={translations.title}\n data={rows}\n columns={columns}\n isLoading={isLoading}\n searchValue={search}\n onSearchChange={handleSearchChange}\n searchPlaceholder={translations.table.search}\n emptyState={<p className=\"py-8 text-center text-sm text-muted-foreground\">{translations.table.empty}</p>}\n actions={(\n <Button asChild size=\"sm\">\n <Link href=\"/backend/resources/resource-types/create\">\n {translations.actions.add}\n </Link>\n </Button>\n )}\n refreshButton={{\n label: translations.actions.refresh,\n onRefresh: handleRefresh,\n isRefreshing: isLoading,\n }}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n pagination={{ page, pageSize: PAGE_SIZE, total, totalPages, onPageChange: setPage }}\n rowActions={(row) => (\n <RowActions\n items={[\n { label: translations.actions.edit, href: `/backend/resources/resource-types/${row.id}/edit` },\n ...(row.resourceCount > 0\n ? []\n : [{ label: translations.actions.delete, destructive: true, onSelect: () => handleDelete(row) }]),\n ]}\n />\n )}\n onRowClick={(row) => router.push(`/backend/resources/resource-types/${row.id}/edit`)}\n perspective={{ tableId: 'resources.resource-types.list' }}\n />\n </PageBody>\n </Page>\n )\n}\n\nfunction mapApiResourceType(item: Record<string, unknown>): ResourceTypeRow {\n const id = typeof item.id === 'string' ? item.id : ''\n const name = typeof item.name === 'string' && item.name.length ? item.name : id\n const description = typeof item.description === 'string' && item.description.length\n ? item.description\n : typeof item.description === 'string'\n ? item.description\n : null\n const appearanceIcon = typeof item.appearanceIcon === 'string'\n ? item.appearanceIcon\n : typeof item.appearance_icon === 'string'\n ? item.appearance_icon\n : null\n const appearanceColor = typeof item.appearanceColor === 'string'\n ? item.appearanceColor\n : typeof item.appearance_color === 'string'\n ? item.appearance_color\n : null\n const updatedAt = typeof item.updatedAt === 'string'\n ? item.updatedAt\n : typeof item.updated_at === 'string'\n ? item.updated_at\n : null\n const resourceCount = typeof item.resourceCount === 'number'\n ? item.resourceCount\n : typeof item.resource_count === 'number'\n ? item.resource_count\n : 0\n return { id, name, description, appearanceIcon, appearanceColor, updatedAt, resourceCount }\n}\n\nfunction formatDateTime(value: string): string {\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return value\n return date.toLocaleString()\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -378,8 +378,8 @@ function ResourcesResourcesPage() {
|
|
|
378
378
|
rowActions: (row) => {
|
|
379
379
|
if (!canManage || row.rowKind !== "resource") return null;
|
|
380
380
|
return /* @__PURE__ */ jsx(RowActions, { items: [
|
|
381
|
-
{
|
|
382
|
-
{
|
|
381
|
+
{ label: t("common.edit", "Edit"), href: `/backend/resources/resources/${encodeURIComponent(row.id)}` },
|
|
382
|
+
{ label: t("common.delete", "Delete"), destructive: true, onSelect: () => {
|
|
383
383
|
void handleDelete(row);
|
|
384
384
|
} }
|
|
385
385
|
] });
|