@open-mercato/core 0.4.7-develop-0a657b411f → 0.4.7-develop-e249d3e7d0
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/carrier_shipment/index.js +37 -0
- package/dist/generated/entities/carrier_shipment/index.js.map +7 -0
- package/dist/generated/entities/gateway_transaction/index.js +47 -0
- package/dist/generated/entities/gateway_transaction/index.js.map +7 -0
- package/dist/generated/entities/webhook_processed_event/index.js +17 -0
- package/dist/generated/entities/webhook_processed_event/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +10 -1
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +6 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/cancel.js +14 -5
- package/dist/modules/data_sync/api/runs/[id]/cancel.js.map +2 -2
- package/dist/modules/data_sync/backend/data-sync/page.meta.js +2 -2
- package/dist/modules/data_sync/backend/data-sync/page.meta.js.map +1 -1
- package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js +37 -12
- package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js.map +2 -2
- package/dist/modules/directory/api/get/tenants/lookup.js +1 -0
- package/dist/modules/directory/api/get/tenants/lookup.js.map +2 -2
- package/dist/modules/integrations/api/[id]/route.js +38 -11
- package/dist/modules/integrations/api/[id]/route.js.map +2 -2
- package/dist/modules/integrations/api/logs/route.js +52 -26
- package/dist/modules/integrations/api/logs/route.js.map +2 -2
- package/dist/modules/integrations/api/route.js +37 -7
- package/dist/modules/integrations/api/route.js.map +2 -2
- package/dist/modules/integrations/api/umes-read.js +121 -0
- package/dist/modules/integrations/api/umes-read.js.map +7 -0
- package/dist/modules/integrations/backend/integrations/[id]/page.js +715 -183
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +30 -9
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/detail-page-widgets.js +46 -0
- package/dist/modules/integrations/backend/integrations/detail-page-widgets.js.map +7 -0
- package/dist/modules/integrations/backend/integrations/page.js +78 -62
- package/dist/modules/integrations/backend/integrations/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/page.meta.js +2 -2
- package/dist/modules/integrations/backend/integrations/page.meta.js.map +1 -1
- package/dist/modules/integrations/setup.js +2 -2
- package/dist/modules/integrations/setup.js.map +2 -2
- package/dist/modules/payment_gateways/acl.js +12 -0
- package/dist/modules/payment_gateways/acl.js.map +7 -0
- package/dist/modules/payment_gateways/api/cancel/route.js +55 -0
- package/dist/modules/payment_gateways/api/cancel/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/capture/route.js +55 -0
- package/dist/modules/payment_gateways/api/capture/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/interceptors.js +24 -0
- package/dist/modules/payment_gateways/api/interceptors.js.map +7 -0
- package/dist/modules/payment_gateways/api/openapi.js +5 -0
- package/dist/modules/payment_gateways/api/openapi.js.map +7 -0
- package/dist/modules/payment_gateways/api/refund/route.js +56 -0
- package/dist/modules/payment_gateways/api/refund/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/sessions/route.js +74 -0
- package/dist/modules/payment_gateways/api/sessions/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/status/route.js +66 -0
- package/dist/modules/payment_gateways/api/status/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/transactions/[id]/route.js +118 -0
- package/dist/modules/payment_gateways/api/transactions/[id]/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/transactions/route.js +113 -0
- package/dist/modules/payment_gateways/api/transactions/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +136 -0
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +7 -0
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js +496 -0
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js.map +7 -0
- package/dist/modules/payment_gateways/backend/payment-gateways/page.meta.js +23 -0
- package/dist/modules/payment_gateways/backend/payment-gateways/page.meta.js.map +7 -0
- package/dist/modules/payment_gateways/data/enrichers.js +5 -0
- package/dist/modules/payment_gateways/data/enrichers.js.map +7 -0
- package/dist/modules/payment_gateways/data/entities.js +131 -0
- package/dist/modules/payment_gateways/data/entities.js.map +7 -0
- package/dist/modules/payment_gateways/data/validators.js +57 -0
- package/dist/modules/payment_gateways/data/validators.js.map +7 -0
- package/dist/modules/payment_gateways/di.js +16 -0
- package/dist/modules/payment_gateways/di.js.map +7 -0
- package/dist/modules/payment_gateways/events.js +21 -0
- package/dist/modules/payment_gateways/events.js.map +7 -0
- package/dist/modules/payment_gateways/i18n/en.js +6 -0
- package/dist/modules/payment_gateways/i18n/en.js.map +7 -0
- package/dist/modules/payment_gateways/i18n/pl.js +6 -0
- package/dist/modules/payment_gateways/i18n/pl.js.map +7 -0
- package/dist/modules/payment_gateways/index.js +9 -0
- package/dist/modules/payment_gateways/index.js.map +7 -0
- package/dist/modules/payment_gateways/lib/gateway-service.js +378 -0
- package/dist/modules/payment_gateways/lib/gateway-service.js.map +7 -0
- package/dist/modules/payment_gateways/lib/queue.js +17 -0
- package/dist/modules/payment_gateways/lib/queue.js.map +7 -0
- package/dist/modules/payment_gateways/lib/status-machine.js +29 -0
- package/dist/modules/payment_gateways/lib/status-machine.js.map +7 -0
- package/dist/modules/payment_gateways/lib/webhook-processor.js +88 -0
- package/dist/modules/payment_gateways/lib/webhook-processor.js.map +7 -0
- package/dist/modules/payment_gateways/lib/webhook-utils.js +42 -0
- package/dist/modules/payment_gateways/lib/webhook-utils.js.map +7 -0
- package/dist/modules/payment_gateways/migrations/Migration20260305122155.js +19 -0
- package/dist/modules/payment_gateways/migrations/Migration20260305122155.js.map +7 -0
- package/dist/modules/payment_gateways/setup.js +13 -0
- package/dist/modules/payment_gateways/setup.js.map +7 -0
- package/dist/modules/payment_gateways/widgets/injection-table.js +7 -0
- package/dist/modules/payment_gateways/widgets/injection-table.js.map +7 -0
- package/dist/modules/payment_gateways/workers/status-poller.js +44 -0
- package/dist/modules/payment_gateways/workers/status-poller.js.map +7 -0
- package/dist/modules/payment_gateways/workers/webhook-processor.js +20 -0
- package/dist/modules/payment_gateways/workers/webhook-processor.js.map +7 -0
- package/dist/modules/sales/data/enrichers.js +72 -0
- package/dist/modules/sales/data/enrichers.js.map +7 -0
- package/dist/modules/sales/lib/makeSalesLineRoute.js +3 -0
- package/dist/modules/sales/lib/makeSalesLineRoute.js.map +2 -2
- package/dist/modules/sales/widgets/injection/payment-gateway-config-field/widget.js +29 -0
- package/dist/modules/sales/widgets/injection/payment-gateway-config-field/widget.js.map +7 -0
- package/dist/modules/sales/widgets/injection/payment-gateway-status-column/widget.js +23 -0
- package/dist/modules/sales/widgets/injection/payment-gateway-status-column/widget.js.map +7 -0
- package/dist/modules/sales/widgets/injection-table.js +13 -1
- package/dist/modules/sales/widgets/injection-table.js.map +2 -2
- package/dist/modules/shipping_carriers/acl.js +10 -0
- package/dist/modules/shipping_carriers/acl.js.map +7 -0
- package/dist/modules/shipping_carriers/api/cancel/route.js +55 -0
- package/dist/modules/shipping_carriers/api/cancel/route.js.map +7 -0
- package/dist/modules/shipping_carriers/api/interceptors.js +21 -0
- package/dist/modules/shipping_carriers/api/interceptors.js.map +7 -0
- package/dist/modules/shipping_carriers/api/openapi.js +5 -0
- package/dist/modules/shipping_carriers/api/openapi.js.map +7 -0
- package/dist/modules/shipping_carriers/api/rates/route.js +55 -0
- package/dist/modules/shipping_carriers/api/rates/route.js.map +7 -0
- package/dist/modules/shipping_carriers/api/shipments/route.js +61 -0
- package/dist/modules/shipping_carriers/api/shipments/route.js.map +7 -0
- package/dist/modules/shipping_carriers/api/tracking/route.js +58 -0
- package/dist/modules/shipping_carriers/api/tracking/route.js.map +7 -0
- package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js +119 -0
- package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js.map +7 -0
- package/dist/modules/shipping_carriers/data/enrichers.js +82 -0
- package/dist/modules/shipping_carriers/data/enrichers.js.map +7 -0
- package/dist/modules/shipping_carriers/data/entities.js +80 -0
- package/dist/modules/shipping_carriers/data/entities.js.map +7 -0
- package/dist/modules/shipping_carriers/data/validators.js +49 -0
- package/dist/modules/shipping_carriers/data/validators.js.map +7 -0
- package/dist/modules/shipping_carriers/di.js +15 -0
- package/dist/modules/shipping_carriers/di.js.map +7 -0
- package/dist/modules/shipping_carriers/events.js +19 -0
- package/dist/modules/shipping_carriers/events.js.map +7 -0
- package/dist/modules/shipping_carriers/i18n/en.js +11 -0
- package/dist/modules/shipping_carriers/i18n/en.js.map +7 -0
- package/dist/modules/shipping_carriers/i18n/pl.js +11 -0
- package/dist/modules/shipping_carriers/i18n/pl.js.map +7 -0
- package/dist/modules/shipping_carriers/index.js +9 -0
- package/dist/modules/shipping_carriers/index.js.map +7 -0
- package/dist/modules/shipping_carriers/lib/adapter-registry.js +29 -0
- package/dist/modules/shipping_carriers/lib/adapter-registry.js.map +7 -0
- package/dist/modules/shipping_carriers/lib/adapter.js +1 -0
- package/dist/modules/shipping_carriers/lib/adapter.js.map +7 -0
- package/dist/modules/shipping_carriers/lib/queue.js +17 -0
- package/dist/modules/shipping_carriers/lib/queue.js.map +7 -0
- package/dist/modules/shipping_carriers/lib/shipping-service.js +155 -0
- package/dist/modules/shipping_carriers/lib/shipping-service.js.map +7 -0
- package/dist/modules/shipping_carriers/lib/status-sync.js +37 -0
- package/dist/modules/shipping_carriers/lib/status-sync.js.map +7 -0
- package/dist/modules/shipping_carriers/migrations/Migration20260305170000.js +16 -0
- package/dist/modules/shipping_carriers/migrations/Migration20260305170000.js.map +7 -0
- package/dist/modules/shipping_carriers/setup.js +13 -0
- package/dist/modules/shipping_carriers/setup.js.map +7 -0
- package/dist/modules/shipping_carriers/widgets/injection/create-shipment-button/widget.js +25 -0
- package/dist/modules/shipping_carriers/widgets/injection/create-shipment-button/widget.js.map +7 -0
- package/dist/modules/shipping_carriers/widgets/injection/tracking-column/widget.js +23 -0
- package/dist/modules/shipping_carriers/widgets/injection/tracking-column/widget.js.map +7 -0
- package/dist/modules/shipping_carriers/widgets/injection/tracking-status-badge/widget.js +40 -0
- package/dist/modules/shipping_carriers/widgets/injection/tracking-status-badge/widget.js.map +7 -0
- package/dist/modules/shipping_carriers/widgets/injection-table.js +24 -0
- package/dist/modules/shipping_carriers/widgets/injection-table.js.map +7 -0
- package/dist/modules/shipping_carriers/workers/status-poller.js +21 -0
- package/dist/modules/shipping_carriers/workers/status-poller.js.map +7 -0
- package/dist/modules/shipping_carriers/workers/webhook-processor.js +54 -0
- package/dist/modules/shipping_carriers/workers/webhook-processor.js.map +7 -0
- package/dist/modules/translations/api/get/locales.js +1 -0
- package/dist/modules/translations/api/get/locales.js.map +2 -2
- package/dist/modules/translations/api/put/locales.js +1 -0
- package/dist/modules/translations/api/put/locales.js.map +2 -2
- package/generated/entities/carrier_shipment/index.ts +17 -0
- package/generated/entities/gateway_transaction/index.ts +22 -0
- package/generated/entities/webhook_processed_event/index.ts +7 -0
- package/generated/entities.ids.generated.ts +10 -1
- package/generated/entity-fields-registry.ts +6 -0
- package/jest.config.cjs +1 -0
- package/package.json +5 -2
- package/src/modules/auth/i18n/de.json +1 -0
- package/src/modules/auth/i18n/en.json +1 -0
- package/src/modules/auth/i18n/es.json +1 -0
- package/src/modules/auth/i18n/pl.json +1 -0
- package/src/modules/data_sync/api/runs/[id]/cancel.ts +18 -5
- package/src/modules/data_sync/backend/data-sync/page.meta.ts +2 -2
- package/src/modules/data_sync/backend/data-sync/runs/[id]/page.tsx +50 -12
- package/src/modules/directory/api/get/tenants/lookup.ts +1 -0
- package/src/modules/integrations/AGENTS.md +31 -0
- package/src/modules/integrations/api/[id]/route.ts +38 -11
- package/src/modules/integrations/api/logs/route.ts +53 -27
- package/src/modules/integrations/api/route.ts +31 -1
- package/src/modules/integrations/api/umes-read.ts +177 -0
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +902 -202
- package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +43 -9
- package/src/modules/integrations/backend/integrations/detail-page-widgets.ts +74 -0
- package/src/modules/integrations/backend/integrations/page.meta.ts +2 -2
- package/src/modules/integrations/backend/integrations/page.tsx +65 -54
- package/src/modules/integrations/i18n/de.json +15 -0
- package/src/modules/integrations/i18n/en.json +15 -0
- package/src/modules/integrations/i18n/es.json +15 -0
- package/src/modules/integrations/i18n/pl.json +15 -0
- package/src/modules/integrations/setup.ts +2 -2
- package/src/modules/payment_gateways/acl.ts +8 -0
- package/src/modules/payment_gateways/api/cancel/route.ts +56 -0
- package/src/modules/payment_gateways/api/capture/route.ts +56 -0
- package/src/modules/payment_gateways/api/interceptors.ts +22 -0
- package/src/modules/payment_gateways/api/openapi.ts +1 -0
- package/src/modules/payment_gateways/api/refund/route.ts +57 -0
- package/src/modules/payment_gateways/api/sessions/route.ts +76 -0
- package/src/modules/payment_gateways/api/status/route.ts +69 -0
- package/src/modules/payment_gateways/api/transactions/[id]/route.ts +123 -0
- package/src/modules/payment_gateways/api/transactions/route.ts +120 -0
- package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +161 -0
- package/src/modules/payment_gateways/backend/payment-gateways/page.meta.ts +19 -0
- package/src/modules/payment_gateways/backend/payment-gateways/page.tsx +660 -0
- package/src/modules/payment_gateways/data/enrichers.ts +8 -0
- package/src/modules/payment_gateways/data/entities.ts +106 -0
- package/src/modules/payment_gateways/data/validators.ts +67 -0
- package/src/modules/payment_gateways/di.ts +26 -0
- package/src/modules/payment_gateways/events.ts +17 -0
- package/src/modules/payment_gateways/i18n/de.json +77 -0
- package/src/modules/payment_gateways/i18n/en.json +77 -0
- package/src/modules/payment_gateways/i18n/en.ts +4 -0
- package/src/modules/payment_gateways/i18n/es.json +77 -0
- package/src/modules/payment_gateways/i18n/pl.json +77 -0
- package/src/modules/payment_gateways/i18n/pl.ts +4 -0
- package/src/modules/payment_gateways/index.ts +5 -0
- package/src/modules/payment_gateways/lib/gateway-service.ts +486 -0
- package/src/modules/payment_gateways/lib/queue.ts +19 -0
- package/src/modules/payment_gateways/lib/status-machine.ts +28 -0
- package/src/modules/payment_gateways/lib/webhook-processor.ts +133 -0
- package/src/modules/payment_gateways/lib/webhook-utils.ts +52 -0
- package/src/modules/payment_gateways/migrations/.snapshot-open-mercato.json +373 -0
- package/src/modules/payment_gateways/migrations/Migration20260305122155.ts +20 -0
- package/src/modules/payment_gateways/setup.ts +11 -0
- package/src/modules/payment_gateways/widgets/injection-table.ts +9 -0
- package/src/modules/payment_gateways/workers/status-poller.ts +58 -0
- package/src/modules/payment_gateways/workers/webhook-processor.ts +30 -0
- package/src/modules/sales/data/enrichers.ts +120 -0
- package/src/modules/sales/lib/makeSalesLineRoute.ts +3 -0
- package/src/modules/sales/widgets/injection/payment-gateway-config-field/widget.ts +28 -0
- package/src/modules/sales/widgets/injection/payment-gateway-status-column/widget.ts +22 -0
- package/src/modules/sales/widgets/injection-table.ts +12 -0
- package/src/modules/shipping_carriers/acl.ts +6 -0
- package/src/modules/shipping_carriers/api/cancel/route.ts +53 -0
- package/src/modules/shipping_carriers/api/interceptors.ts +19 -0
- package/src/modules/shipping_carriers/api/openapi.ts +1 -0
- package/src/modules/shipping_carriers/api/rates/route.ts +53 -0
- package/src/modules/shipping_carriers/api/shipments/route.ts +59 -0
- package/src/modules/shipping_carriers/api/tracking/route.ts +56 -0
- package/src/modules/shipping_carriers/api/webhook/[provider]/route.ts +134 -0
- package/src/modules/shipping_carriers/data/enrichers.ts +89 -0
- package/src/modules/shipping_carriers/data/entities.ts +60 -0
- package/src/modules/shipping_carriers/data/validators.ts +48 -0
- package/src/modules/shipping_carriers/di.ts +20 -0
- package/src/modules/shipping_carriers/events.ts +16 -0
- package/src/modules/shipping_carriers/i18n/de.json +7 -0
- package/src/modules/shipping_carriers/i18n/en.json +7 -0
- package/src/modules/shipping_carriers/i18n/en.ts +7 -0
- package/src/modules/shipping_carriers/i18n/es.json +7 -0
- package/src/modules/shipping_carriers/i18n/pl.json +7 -0
- package/src/modules/shipping_carriers/i18n/pl.ts +7 -0
- package/src/modules/shipping_carriers/index.ts +5 -0
- package/src/modules/shipping_carriers/lib/adapter-registry.ts +33 -0
- package/src/modules/shipping_carriers/lib/adapter.ts +93 -0
- package/src/modules/shipping_carriers/lib/queue.ts +19 -0
- package/src/modules/shipping_carriers/lib/shipping-service.ts +204 -0
- package/src/modules/shipping_carriers/lib/status-sync.ts +38 -0
- package/src/modules/shipping_carriers/migrations/Migration20260305170000.ts +14 -0
- package/src/modules/shipping_carriers/setup.ts +11 -0
- package/src/modules/shipping_carriers/widgets/injection/create-shipment-button/widget.ts +24 -0
- package/src/modules/shipping_carriers/widgets/injection/tracking-column/widget.ts +22 -0
- package/src/modules/shipping_carriers/widgets/injection/tracking-status-badge/widget.tsx +44 -0
- package/src/modules/shipping_carriers/widgets/injection-table.ts +22 -0
- package/src/modules/shipping_carriers/workers/status-poller.ts +33 -0
- package/src/modules/shipping_carriers/workers/webhook-processor.ts +79 -0
- package/src/modules/translations/api/get/locales.ts +1 -0
- package/src/modules/translations/api/put/locales.ts +1 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/modules/data_sync/backend/data-sync/runs/%5Bid%5D/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useParams, useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Card, CardHeader, CardTitle, CardContent } from '@open-mercato/ui/primitives/card'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Progress } from '@open-mercato/ui/primitives/progress'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { LoadingMessage } from '@open-mercato/ui/backend/detail'\nimport { ErrorMessage } from '@open-mercato/ui/backend/detail'\n\ntype SyncRunDetail = {\n id: string\n integrationId: string\n entityType: string\n direction: 'import' | 'export'\n status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled' | 'paused'\n createdCount: number\n updatedCount: number\n skippedCount: number\n failedCount: number\n batchesCompleted: number\n lastError: string | null\n progressJobId: string | null\n progressJob: {\n id: string\n status: string\n progressPercent: number\n processedCount: number\n totalCount: number | null\n etaSeconds: number | null\n } | null\n triggeredBy: string | null\n createdAt: string\n updatedAt: string\n}\n\ntype LogEntry = {\n id: string\n level: 'info' | 'warn' | 'error'\n message: string\n createdAt: string\n}\n\nconst STATUS_STYLES: Record<string, string> = {\n pending: 'bg-gray-100 text-gray-800',\n running: 'bg-blue-100 text-blue-800',\n completed: 'bg-green-100 text-green-800',\n failed: 'bg-red-100 text-red-800',\n cancelled: 'bg-yellow-100 text-yellow-800',\n paused: 'bg-orange-100 text-orange-800',\n}\n\nconst LOG_LEVEL_STYLES: Record<string, string> = {\n info: 'bg-blue-100 text-blue-800',\n warn: 'bg-yellow-100 text-yellow-800',\n error: 'bg-red-100 text-red-800',\n}\n\nexport default function SyncRunDetailPage() {\n const params = useParams<{ id: string }>()\n const router = useRouter()\n const runId = params.id\n const t = useT()\n\n const [run, setRun] = React.useState<SyncRunDetail | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [logs, setLogs] = React.useState<LogEntry[]>([])\n const [isLoadingLogs, setIsLoadingLogs] = React.useState(false)\n\n const loadRun = React.useCallback(async () => {\n const call = await apiCall<SyncRunDetail>(\n `/api/data_sync/runs/${encodeURIComponent(runId)}`,\n undefined,\n { fallback: null },\n )\n if (!call.ok || !call.result) {\n setError(t('data_sync.runs.detail.loadError'))\n setIsLoading(false)\n return\n }\n setRun(call.result)\n setIsLoading(false)\n }, [runId, t])\n\n const loadLogs = React.useCallback(async () => {\n setIsLoadingLogs(true)\n const params = new URLSearchParams({ runId, pageSize: '50' })\n const call = await apiCall<{ items: LogEntry[] }>(\n `/api/integrations/logs?${params.toString()}`,\n undefined,\n { fallback: { items: [] } },\n )\n if (call.ok && call.result) {\n setLogs(call.result.items)\n }\n setIsLoadingLogs(false)\n }, [runId])\n\n React.useEffect(() => {\n void loadRun()\n void loadLogs()\n }, [loadRun, loadLogs])\n\n React.useEffect(() => {\n if (!run || (run.status !== 'running' && run.status !== 'pending')) return\n const interval = setInterval(() => { void loadRun() }, 4000)\n return () => clearInterval(interval)\n }, [run?.status, loadRun])\n\n const handleCancel = React.useCallback(async () => {\n const call = await apiCall(`/api/data_sync/runs/${encodeURIComponent(runId)}/cancel`, {\n method: 'POST',\n }, { fallback: null })\n if (call.ok) {\n flash(t('data_sync.runs.detail.cancelSuccess'), 'success')\n void loadRun()\n } else {\n flash(t('data_sync.runs.detail.cancelError'), 'error')\n }\n }, [runId, t, loadRun])\n\n const handleRetry = React.useCallback(async () => {\n const call = await apiCall<{ id: string }>(`/api/data_sync/runs/${encodeURIComponent(runId)}/retry`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ fromBeginning: false }),\n }, { fallback: null })\n if (call.ok && call.result) {\n flash(t('data_sync.runs.detail.retrySuccess'), 'success')\n router.push(`/backend/data-sync/runs/${encodeURIComponent(call.result.id)}`)\n } else {\n flash(t('data_sync.runs.detail.retryError'), 'error')\n }\n }, [router, runId, t])\n\n if (isLoading) return <Page><PageBody><LoadingMessage label={t('data_sync.runs.detail.title')} /></PageBody></Page>\n if (error || !run) return <Page><PageBody><ErrorMessage label={error ?? t('data_sync.runs.detail.loadError')} /></PageBody></Page>\n\n const totalProcessed = run.createdCount + run.updatedCount + run.skippedCount + run.failedCount\n const progressPercent = run.progressJob?.progressPercent ?? (run.status === 'completed' ? 100 : 0)\n\n return (\n <Page>\n <PageBody className=\"space-y-6\">\n <div>\n <Link href=\"/backend/data-sync\" className=\"text-sm text-muted-foreground hover:underline\">\n {t('data_sync.runs.detail.back')}\n </Link>\n </div>\n\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">{run.integrationId} \u2014 {run.entityType}</h1>\n <div className=\"flex gap-2 mt-2\">\n <Badge variant=\"outline\">{t(`data_sync.dashboard.direction.${run.direction}`)}</Badge>\n <Badge variant=\"secondary\" className={STATUS_STYLES[run.status] ?? ''}>\n {t(`data_sync.dashboard.status.${run.status}`)}\n </Badge>\n {run.triggeredBy && <Badge variant=\"outline\">{run.triggeredBy}</Badge>}\n </div>\n </div>\n <div className=\"flex gap-2\">\n {(run.status === 'running' || run.status === 'pending') && (\n <Button type=\"button\" variant=\"destructive\" size=\"sm\" onClick={() => void handleCancel()}>\n {t('data_sync.runs.detail.cancel')}\n </Button>\n )}\n {run.status === 'failed' && (\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => void handleRetry()}>\n {t('data_sync.runs.detail.retry')}\n </Button>\n )}\n </div>\n </div>\n\n {(run.status === 'running' || run.status === 'pending') && (\n <Card>\n <CardHeader>\n <CardTitle>{t('data_sync.runs.detail.progress')}</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <Progress value={progressPercent} className=\"h-3\" />\n <div className=\"flex items-center justify-between text-sm text-muted-foreground\">\n <span>{t('data_sync.runs.detail.progress.itemsProcessed', { count: totalProcessed })}</span>\n <span>{t('data_sync.runs.detail.progress.batches', { count: run.batchesCompleted })}</span>\n </div>\n </CardContent>\n </Card>\n )}\n\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-4\">\n <Card>\n <CardContent className=\"pt-6 text-center\">\n <div className=\"text-2xl font-bold text-green-600\">{run.createdCount}</div>\n <p className=\"text-sm text-muted-foreground\">{t('data_sync.runs.detail.counters.created')}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-6 text-center\">\n <div className=\"text-2xl font-bold text-blue-600\">{run.updatedCount}</div>\n <p className=\"text-sm text-muted-foreground\">{t('data_sync.runs.detail.counters.updated')}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-6 text-center\">\n <div className=\"text-2xl font-bold text-gray-600\">{run.skippedCount}</div>\n <p className=\"text-sm text-muted-foreground\">{t('data_sync.runs.detail.counters.skipped')}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-6 text-center\">\n <div className=\"text-2xl font-bold text-red-600\">{run.failedCount}</div>\n <p className=\"text-sm text-muted-foreground\">{t('data_sync.runs.detail.counters.failed')}</p>\n </CardContent>\n </Card>\n </div>\n\n {run.lastError && (\n <Card className=\"border-red-200 bg-red-50\">\n <CardHeader>\n <CardTitle className=\"text-red-800\">{t('data_sync.runs.detail.error')}</CardTitle>\n </CardHeader>\n <CardContent>\n <pre className=\"text-sm text-red-700 whitespace-pre-wrap\">{run.lastError}</pre>\n </CardContent>\n </Card>\n )}\n\n <Card>\n <CardHeader>\n <CardTitle>{t('data_sync.runs.detail.logs')}</CardTitle>\n </CardHeader>\n <CardContent>\n {isLoadingLogs ? (\n <div className=\"flex justify-center py-4\"><Spinner /></div>\n ) : logs.length === 0 ? (\n <p className=\"text-muted-foreground text-sm\">{t('data_sync.runs.detail.noLogs')}</p>\n ) : (\n <div className=\"rounded-lg border\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-4 py-2 text-left font-medium\">{t('data_sync.runs.detail.logs.time')}</th>\n <th className=\"px-4 py-2 text-left font-medium\">{t('data_sync.runs.detail.logs.level')}</th>\n <th className=\"px-4 py-2 text-left font-medium\">{t('data_sync.runs.detail.logs.message')}</th>\n </tr>\n </thead>\n <tbody>\n {logs.map((log) => (\n <tr key={log.id} className=\"border-b last:border-0\">\n <td className=\"px-4 py-2 text-muted-foreground whitespace-nowrap\">\n {new Date(log.createdAt).toLocaleString()}\n </td>\n <td className=\"px-4 py-2\">\n <Badge variant=\"secondary\" className={LOG_LEVEL_STYLES[log.level] ?? ''}>\n {log.level}\n </Badge>\n </td>\n <td className=\"px-4 py-2\">{log.message}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </CardContent>\n </Card>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { usePathname, useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Card, CardHeader, CardTitle, CardContent } from '@open-mercato/ui/primitives/card'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Progress } from '@open-mercato/ui/primitives/progress'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { LoadingMessage } from '@open-mercato/ui/backend/detail'\nimport { ErrorMessage } from '@open-mercato/ui/backend/detail'\n\ntype SyncRunDetail = {\n id: string\n integrationId: string\n entityType: string\n direction: 'import' | 'export'\n status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled' | 'paused'\n createdCount: number\n updatedCount: number\n skippedCount: number\n failedCount: number\n batchesCompleted: number\n lastError: string | null\n progressJobId: string | null\n progressJob: {\n id: string\n status: string\n progressPercent: number\n processedCount: number\n totalCount: number | null\n etaSeconds: number | null\n } | null\n triggeredBy: string | null\n createdAt: string\n updatedAt: string\n}\n\ntype LogEntry = {\n id: string\n level: 'info' | 'warn' | 'error'\n message: string\n createdAt: string\n}\n\nconst STATUS_STYLES: Record<string, string> = {\n pending: 'bg-gray-100 text-gray-800',\n running: 'bg-blue-100 text-blue-800',\n completed: 'bg-green-100 text-green-800',\n failed: 'bg-red-100 text-red-800',\n cancelled: 'bg-yellow-100 text-yellow-800',\n paused: 'bg-orange-100 text-orange-800',\n}\n\nconst LOG_LEVEL_STYLES: Record<string, string> = {\n info: 'bg-blue-100 text-blue-800',\n warn: 'bg-yellow-100 text-yellow-800',\n error: 'bg-red-100 text-red-800',\n}\n\ntype SyncRunDetailPageProps = {\n params?: {\n id?: string | string[]\n }\n}\n\nfunction resolveRouteId(value: string | string[] | undefined): string | undefined {\n if (Array.isArray(value)) return value[0]\n return value\n}\n\nfunction resolvePathnameId(pathname: string): string | undefined {\n const parts = pathname.split('/').filter(Boolean)\n const runId = parts.at(-1)\n if (!runId || runId === 'runs' || runId === 'data-sync') return undefined\n return decodeURIComponent(runId)\n}\n\nexport default function SyncRunDetailPage({ params }: SyncRunDetailPageProps) {\n const pathname = usePathname()\n const router = useRouter()\n const runId = resolveRouteId(params?.id) ?? resolvePathnameId(pathname)\n const t = useT()\n\n const [run, setRun] = React.useState<SyncRunDetail | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [logs, setLogs] = React.useState<LogEntry[]>([])\n const [isLoadingLogs, setIsLoadingLogs] = React.useState(false)\n\n const resolveCurrentRunId = React.useCallback(() => {\n return runId ?? (\n typeof window !== 'undefined'\n ? resolvePathnameId(window.location.pathname)\n : undefined\n )\n }, [runId])\n\n const loadRun = React.useCallback(async () => {\n const currentRunId = resolveCurrentRunId()\n if (!currentRunId) {\n setError(t('data_sync.runs.detail.loadError'))\n setIsLoading(false)\n return\n }\n const call = await apiCall<SyncRunDetail>(\n `/api/data_sync/runs/${encodeURIComponent(currentRunId)}`,\n undefined,\n { fallback: null },\n )\n if (!call.ok || !call.result) {\n setError(t('data_sync.runs.detail.loadError'))\n setIsLoading(false)\n return\n }\n setRun(call.result)\n setIsLoading(false)\n }, [resolveCurrentRunId, t])\n\n const loadLogs = React.useCallback(async () => {\n const currentRunId = resolveCurrentRunId()\n if (!currentRunId) return\n setIsLoadingLogs(true)\n const params = new URLSearchParams({ runId: currentRunId, pageSize: '50' })\n const call = await apiCall<{ items: LogEntry[] }>(\n `/api/integrations/logs?${params.toString()}`,\n undefined,\n { fallback: { items: [] } },\n )\n if (call.ok && call.result) {\n setLogs(call.result.items)\n }\n setIsLoadingLogs(false)\n }, [resolveCurrentRunId])\n\n React.useEffect(() => {\n void loadRun()\n void loadLogs()\n }, [loadRun, loadLogs])\n\n React.useEffect(() => {\n if (!run || (run.status !== 'running' && run.status !== 'pending')) return\n const interval = setInterval(() => { void loadRun() }, 4000)\n return () => clearInterval(interval)\n }, [run?.status, loadRun])\n\n const handleCancel = React.useCallback(async () => {\n const currentRunId = resolveCurrentRunId()\n if (!currentRunId) return\n const call = await apiCall(`/api/data_sync/runs/${encodeURIComponent(currentRunId)}/cancel`, {\n method: 'POST',\n }, { fallback: null })\n if (call.ok) {\n flash(t('data_sync.runs.detail.cancelSuccess'), 'success')\n void loadRun()\n } else {\n flash(t('data_sync.runs.detail.cancelError'), 'error')\n }\n }, [resolveCurrentRunId, t, loadRun])\n\n const handleRetry = React.useCallback(async () => {\n const currentRunId = resolveCurrentRunId()\n if (!currentRunId) return\n const call = await apiCall<{ id: string }>(`/api/data_sync/runs/${encodeURIComponent(currentRunId)}/retry`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ fromBeginning: false }),\n }, { fallback: null })\n if (call.ok && call.result) {\n flash(t('data_sync.runs.detail.retrySuccess'), 'success')\n router.push(`/backend/data-sync/runs/${encodeURIComponent(call.result.id)}`)\n } else {\n flash(t('data_sync.runs.detail.retryError'), 'error')\n }\n }, [resolveCurrentRunId, router, t])\n\n if (isLoading) return <Page><PageBody><LoadingMessage label={t('data_sync.runs.detail.title')} /></PageBody></Page>\n if (error || !run) return <Page><PageBody><ErrorMessage label={error ?? t('data_sync.runs.detail.loadError')} /></PageBody></Page>\n\n const totalProcessed = run.createdCount + run.updatedCount + run.skippedCount + run.failedCount\n const progressPercent = run.progressJob?.progressPercent ?? (run.status === 'completed' ? 100 : 0)\n\n return (\n <Page>\n <PageBody className=\"space-y-6\">\n <div>\n <Link href=\"/backend/data-sync\" className=\"text-sm text-muted-foreground hover:underline\">\n {t('data_sync.runs.detail.back')}\n </Link>\n </div>\n\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">{run.integrationId} \u2014 {run.entityType}</h1>\n <div className=\"flex gap-2 mt-2\">\n <Badge variant=\"outline\">{t(`data_sync.dashboard.direction.${run.direction}`)}</Badge>\n <Badge variant=\"secondary\" className={STATUS_STYLES[run.status] ?? ''}>\n {t(`data_sync.dashboard.status.${run.status}`)}\n </Badge>\n {run.triggeredBy && <Badge variant=\"outline\">{run.triggeredBy}</Badge>}\n </div>\n </div>\n <div className=\"flex gap-2\">\n {(run.status === 'running' || run.status === 'pending') && (\n <Button type=\"button\" variant=\"destructive\" size=\"sm\" onClick={() => void handleCancel()}>\n {t('data_sync.runs.detail.cancel')}\n </Button>\n )}\n {run.status === 'failed' && (\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => void handleRetry()}>\n {t('data_sync.runs.detail.retry')}\n </Button>\n )}\n </div>\n </div>\n\n {(run.status === 'running' || run.status === 'pending') && (\n <Card>\n <CardHeader>\n <CardTitle>{t('data_sync.runs.detail.progress')}</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <Progress value={progressPercent} className=\"h-3\" />\n <div className=\"flex items-center justify-between text-sm text-muted-foreground\">\n <span>{t('data_sync.runs.detail.progress.itemsProcessed', { count: totalProcessed })}</span>\n <span>{t('data_sync.runs.detail.progress.batches', { count: run.batchesCompleted })}</span>\n </div>\n </CardContent>\n </Card>\n )}\n\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-4\">\n <Card>\n <CardContent className=\"pt-6 text-center\">\n <div className=\"text-2xl font-bold text-green-600\">{run.createdCount}</div>\n <p className=\"text-sm text-muted-foreground\">{t('data_sync.runs.detail.counters.created')}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-6 text-center\">\n <div className=\"text-2xl font-bold text-blue-600\">{run.updatedCount}</div>\n <p className=\"text-sm text-muted-foreground\">{t('data_sync.runs.detail.counters.updated')}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-6 text-center\">\n <div className=\"text-2xl font-bold text-gray-600\">{run.skippedCount}</div>\n <p className=\"text-sm text-muted-foreground\">{t('data_sync.runs.detail.counters.skipped')}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-6 text-center\">\n <div className=\"text-2xl font-bold text-red-600\">{run.failedCount}</div>\n <p className=\"text-sm text-muted-foreground\">{t('data_sync.runs.detail.counters.failed')}</p>\n </CardContent>\n </Card>\n </div>\n\n {run.lastError && (\n <Card className=\"border-red-200 bg-red-50\">\n <CardHeader>\n <CardTitle className=\"text-red-800\">{t('data_sync.runs.detail.error')}</CardTitle>\n </CardHeader>\n <CardContent>\n <pre className=\"text-sm text-red-700 whitespace-pre-wrap\">{run.lastError}</pre>\n </CardContent>\n </Card>\n )}\n\n <Card>\n <CardHeader>\n <CardTitle>{t('data_sync.runs.detail.logs')}</CardTitle>\n </CardHeader>\n <CardContent>\n {isLoadingLogs ? (\n <div className=\"flex justify-center py-4\"><Spinner /></div>\n ) : logs.length === 0 ? (\n <p className=\"text-muted-foreground text-sm\">{t('data_sync.runs.detail.noLogs')}</p>\n ) : (\n <div className=\"rounded-lg border\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-4 py-2 text-left font-medium\">{t('data_sync.runs.detail.logs.time')}</th>\n <th className=\"px-4 py-2 text-left font-medium\">{t('data_sync.runs.detail.logs.level')}</th>\n <th className=\"px-4 py-2 text-left font-medium\">{t('data_sync.runs.detail.logs.message')}</th>\n </tr>\n </thead>\n <tbody>\n {logs.map((log) => (\n <tr key={log.id} className=\"border-b last:border-0\">\n <td className=\"px-4 py-2 text-muted-foreground whitespace-nowrap\">\n {new Date(log.createdAt).toLocaleString()}\n </td>\n <td className=\"px-4 py-2\">\n <Badge variant=\"secondary\" className={LOG_LEVEL_STYLES[log.level] ?? ''}>\n {log.level}\n </Badge>\n </td>\n <td className=\"px-4 py-2\">{log.message}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </CardContent>\n </Card>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["params"]
|
|
7
7
|
}
|
|
@@ -3,6 +3,7 @@ import { z } from "zod";
|
|
|
3
3
|
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
|
|
4
4
|
import { Tenant } from "@open-mercato/core/modules/directory/data/entities";
|
|
5
5
|
const metadata = {
|
|
6
|
+
path: "/directory/tenants/lookup",
|
|
6
7
|
GET: {
|
|
7
8
|
requireAuth: false
|
|
8
9
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/directory/api/get/tenants/lookup.ts"],
|
|
4
|
-
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { Tenant } from '@open-mercato/core/modules/directory/data/entities'\nimport type { OpenApiMethodDoc, OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\n\nexport const metadata = {\n GET: {\n requireAuth: false,\n },\n}\n\nconst tenantLookupQuerySchema = z.object({\n tenantId: z.string().uuid(),\n})\n\nexport async function GET(req: Request) {\n const url = new URL(req.url)\n const tenantId = url.searchParams.get('tenantId') || url.searchParams.get('tenant') || ''\n const parsed = tenantLookupQuerySchema.safeParse({ tenantId })\n if (!parsed.success) {\n return NextResponse.json({ ok: false, error: 'Invalid tenant id.' }, { status: 400 })\n }\n\n const container = await createRequestContainer()\n const em = (container.resolve('em') as EntityManager)\n const tenant = await em.findOne(Tenant, { id: parsed.data.tenantId, deletedAt: null })\n if (!tenant) {\n return NextResponse.json({ ok: false, error: 'Tenant not found.' }, { status: 404 })\n }\n return NextResponse.json({\n ok: true,\n tenant: { id: String(tenant.id), name: tenant.name },\n })\n}\n\nconst lookupTag = 'Directory'\n\nconst tenantLookupSuccessSchema = z.object({\n ok: z.literal(true),\n tenant: z.object({\n id: z.string().uuid(),\n name: z.string(),\n }),\n})\n\nconst tenantLookupErrorSchema = z.object({\n ok: z.literal(false),\n error: z.string(),\n})\n\nconst tenantLookupDoc: OpenApiMethodDoc = {\n summary: 'Public tenant lookup',\n description: 'Resolves tenant metadata for login/activation flows.',\n tags: [lookupTag],\n query: tenantLookupQuerySchema,\n responses: [\n { status: 200, description: 'Tenant resolved.', schema: tenantLookupSuccessSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid tenant id', schema: tenantLookupErrorSchema },\n { status: 404, description: 'Tenant not found', schema: tenantLookupErrorSchema },\n ],\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: lookupTag,\n summary: 'Public tenant lookup',\n methods: {\n GET: tenantLookupDoc,\n },\n}\n\nexport default GET\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAElB,SAAS,8BAA8B;AACvC,SAAS,cAAc;AAGhB,MAAM,WAAW;AAAA,EACtB,KAAK;AAAA,IACH,aAAa;AAAA,EACf;AACF;AAEA,MAAM,0BAA0B,EAAE,OAAO;AAAA,EACvC,UAAU,EAAE,OAAO,EAAE,KAAK;AAC5B,CAAC;AAED,eAAsB,IAAI,KAAc;AACtC,QAAM,MAAM,IAAI,IAAI,IAAI,GAAG;AAC3B,QAAM,WAAW,IAAI,aAAa,IAAI,UAAU,KAAK,IAAI,aAAa,IAAI,QAAQ,KAAK;AACvF,QAAM,SAAS,wBAAwB,UAAU,EAAE,SAAS,CAAC;AAC7D,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,aAAa,KAAK,EAAE,IAAI,OAAO,OAAO,qBAAqB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACtF;AAEA,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,KAAM,UAAU,QAAQ,IAAI;AAClC,QAAM,SAAS,MAAM,GAAG,QAAQ,QAAQ,EAAE,IAAI,OAAO,KAAK,UAAU,WAAW,KAAK,CAAC;AACrF,MAAI,CAAC,QAAQ;AACX,WAAO,aAAa,KAAK,EAAE,IAAI,OAAO,OAAO,oBAAoB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACrF;AACA,SAAO,aAAa,KAAK;AAAA,IACvB,IAAI;AAAA,IACJ,QAAQ,EAAE,IAAI,OAAO,OAAO,EAAE,GAAG,MAAM,OAAO,KAAK;AAAA,EACrD,CAAC;AACH;AAEA,MAAM,YAAY;AAElB,MAAM,4BAA4B,EAAE,OAAO;AAAA,EACzC,IAAI,EAAE,QAAQ,IAAI;AAAA,EAClB,QAAQ,EAAE,OAAO;AAAA,IACf,IAAI,EAAE,OAAO,EAAE,KAAK;AAAA,IACpB,MAAM,EAAE,OAAO;AAAA,EACjB,CAAC;AACH,CAAC;AAED,MAAM,0BAA0B,EAAE,OAAO;AAAA,EACvC,IAAI,EAAE,QAAQ,KAAK;AAAA,EACnB,OAAO,EAAE,OAAO;AAClB,CAAC;AAED,MAAM,kBAAoC;AAAA,EACxC,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM,CAAC,SAAS;AAAA,EAChB,OAAO;AAAA,EACP,WAAW;AAAA,IACT,EAAE,QAAQ,KAAK,aAAa,oBAAoB,QAAQ,0BAA0B;AAAA,EACpF;AAAA,EACA,QAAQ;AAAA,IACN,EAAE,QAAQ,KAAK,aAAa,qBAAqB,QAAQ,wBAAwB;AAAA,IACjF,EAAE,QAAQ,KAAK,aAAa,oBAAoB,QAAQ,wBAAwB;AAAA,EAClF;AACF;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,KAAK;AAAA,EACP;AACF;AAEA,IAAO,iBAAQ;",
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { Tenant } from '@open-mercato/core/modules/directory/data/entities'\nimport type { OpenApiMethodDoc, OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\n\nexport const metadata = {\n path: '/directory/tenants/lookup',\n GET: {\n requireAuth: false,\n },\n}\n\nconst tenantLookupQuerySchema = z.object({\n tenantId: z.string().uuid(),\n})\n\nexport async function GET(req: Request) {\n const url = new URL(req.url)\n const tenantId = url.searchParams.get('tenantId') || url.searchParams.get('tenant') || ''\n const parsed = tenantLookupQuerySchema.safeParse({ tenantId })\n if (!parsed.success) {\n return NextResponse.json({ ok: false, error: 'Invalid tenant id.' }, { status: 400 })\n }\n\n const container = await createRequestContainer()\n const em = (container.resolve('em') as EntityManager)\n const tenant = await em.findOne(Tenant, { id: parsed.data.tenantId, deletedAt: null })\n if (!tenant) {\n return NextResponse.json({ ok: false, error: 'Tenant not found.' }, { status: 404 })\n }\n return NextResponse.json({\n ok: true,\n tenant: { id: String(tenant.id), name: tenant.name },\n })\n}\n\nconst lookupTag = 'Directory'\n\nconst tenantLookupSuccessSchema = z.object({\n ok: z.literal(true),\n tenant: z.object({\n id: z.string().uuid(),\n name: z.string(),\n }),\n})\n\nconst tenantLookupErrorSchema = z.object({\n ok: z.literal(false),\n error: z.string(),\n})\n\nconst tenantLookupDoc: OpenApiMethodDoc = {\n summary: 'Public tenant lookup',\n description: 'Resolves tenant metadata for login/activation flows.',\n tags: [lookupTag],\n query: tenantLookupQuerySchema,\n responses: [\n { status: 200, description: 'Tenant resolved.', schema: tenantLookupSuccessSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid tenant id', schema: tenantLookupErrorSchema },\n { status: 404, description: 'Tenant not found', schema: tenantLookupErrorSchema },\n ],\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: lookupTag,\n summary: 'Public tenant lookup',\n methods: {\n GET: tenantLookupDoc,\n },\n}\n\nexport default GET\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAElB,SAAS,8BAA8B;AACvC,SAAS,cAAc;AAGhB,MAAM,WAAW;AAAA,EACtB,MAAM;AAAA,EACN,KAAK;AAAA,IACH,aAAa;AAAA,EACf;AACF;AAEA,MAAM,0BAA0B,EAAE,OAAO;AAAA,EACvC,UAAU,EAAE,OAAO,EAAE,KAAK;AAC5B,CAAC;AAED,eAAsB,IAAI,KAAc;AACtC,QAAM,MAAM,IAAI,IAAI,IAAI,GAAG;AAC3B,QAAM,WAAW,IAAI,aAAa,IAAI,UAAU,KAAK,IAAI,aAAa,IAAI,QAAQ,KAAK;AACvF,QAAM,SAAS,wBAAwB,UAAU,EAAE,SAAS,CAAC;AAC7D,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,aAAa,KAAK,EAAE,IAAI,OAAO,OAAO,qBAAqB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACtF;AAEA,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,KAAM,UAAU,QAAQ,IAAI;AAClC,QAAM,SAAS,MAAM,GAAG,QAAQ,QAAQ,EAAE,IAAI,OAAO,KAAK,UAAU,WAAW,KAAK,CAAC;AACrF,MAAI,CAAC,QAAQ;AACX,WAAO,aAAa,KAAK,EAAE,IAAI,OAAO,OAAO,oBAAoB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACrF;AACA,SAAO,aAAa,KAAK;AAAA,IACvB,IAAI;AAAA,IACJ,QAAQ,EAAE,IAAI,OAAO,OAAO,EAAE,GAAG,MAAM,OAAO,KAAK;AAAA,EACrD,CAAC;AACH;AAEA,MAAM,YAAY;AAElB,MAAM,4BAA4B,EAAE,OAAO;AAAA,EACzC,IAAI,EAAE,QAAQ,IAAI;AAAA,EAClB,QAAQ,EAAE,OAAO;AAAA,IACf,IAAI,EAAE,OAAO,EAAE,KAAK;AAAA,IACpB,MAAM,EAAE,OAAO;AAAA,EACjB,CAAC;AACH,CAAC;AAED,MAAM,0BAA0B,EAAE,OAAO;AAAA,EACvC,IAAI,EAAE,QAAQ,KAAK;AAAA,EACnB,OAAO,EAAE,OAAO;AAClB,CAAC;AAED,MAAM,kBAAoC;AAAA,EACxC,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM,CAAC,SAAS;AAAA,EAChB,OAAO;AAAA,EACP,WAAW;AAAA,IACT,EAAE,QAAQ,KAAK,aAAa,oBAAoB,QAAQ,0BAA0B;AAAA,EACpF;AAAA,EACA,QAAQ;AAAA,IACN,EAAE,QAAQ,KAAK,aAAa,qBAAqB,QAAQ,wBAAwB;AAAA,IACjF,EAAE,QAAQ,KAAK,aAAa,oBAAoB,QAAQ,wBAAwB;AAAA,EAClF;AACF;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,KAAK;AAAA,EACP;AACF;AAEA,IAAO,iBAAQ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -3,6 +3,11 @@ import { z } from "zod";
|
|
|
3
3
|
import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
|
|
4
4
|
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
|
|
5
5
|
import { getBundle, getBundleIntegrations, getIntegration } from "@open-mercato/shared/modules/integrations/types";
|
|
6
|
+
import {
|
|
7
|
+
finalizeIntegrationsReadResponse,
|
|
8
|
+
integrationApiRoutePaths,
|
|
9
|
+
runIntegrationsReadBeforeInterceptors
|
|
10
|
+
} from "../umes-read.js";
|
|
6
11
|
const idParamsSchema = z.object({ id: z.string().min(1) });
|
|
7
12
|
const metadata = {
|
|
8
13
|
GET: { requireAuth: true, requireFeatures: ["integrations.view"] }
|
|
@@ -26,6 +31,15 @@ async function GET(req, ctx) {
|
|
|
26
31
|
return NextResponse.json({ error: "Integration not found" }, { status: 404 });
|
|
27
32
|
}
|
|
28
33
|
const container = await createRequestContainer();
|
|
34
|
+
const beforeInterceptors = await runIntegrationsReadBeforeInterceptors({
|
|
35
|
+
routePath: integrationApiRoutePaths.detail,
|
|
36
|
+
request: req,
|
|
37
|
+
auth,
|
|
38
|
+
container
|
|
39
|
+
});
|
|
40
|
+
if (!beforeInterceptors.ok) {
|
|
41
|
+
return NextResponse.json(beforeInterceptors.body, { status: beforeInterceptors.statusCode });
|
|
42
|
+
}
|
|
29
43
|
const credentialsService = container.resolve("integrationCredentialsService");
|
|
30
44
|
const stateService = container.resolve("integrationStateService");
|
|
31
45
|
const scope = { organizationId: auth.orgId, tenantId: auth.tenantId };
|
|
@@ -51,18 +65,31 @@ async function GET(req, ctx) {
|
|
|
51
65
|
};
|
|
52
66
|
})
|
|
53
67
|
) : [];
|
|
54
|
-
return
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
68
|
+
return finalizeIntegrationsReadResponse({
|
|
69
|
+
routePath: integrationApiRoutePaths.detail,
|
|
70
|
+
request: req,
|
|
71
|
+
auth,
|
|
72
|
+
container,
|
|
73
|
+
interceptorRequest: beforeInterceptors.request,
|
|
74
|
+
beforeMetadata: beforeInterceptors.metadataByInterceptor,
|
|
75
|
+
enrich: {
|
|
76
|
+
targetEntity: "integrations.integration",
|
|
77
|
+
recordKeys: ["integration"],
|
|
78
|
+
listKeys: ["bundleIntegrations"]
|
|
64
79
|
},
|
|
65
|
-
|
|
80
|
+
body: {
|
|
81
|
+
integration,
|
|
82
|
+
bundle,
|
|
83
|
+
bundleIntegrations,
|
|
84
|
+
state: {
|
|
85
|
+
isEnabled: state?.isEnabled ?? true,
|
|
86
|
+
apiVersion: state?.apiVersion ?? null,
|
|
87
|
+
reauthRequired: state?.reauthRequired ?? false,
|
|
88
|
+
lastHealthStatus: state?.lastHealthStatus ?? null,
|
|
89
|
+
lastHealthCheckedAt: state?.lastHealthCheckedAt?.toISOString() ?? null
|
|
90
|
+
},
|
|
91
|
+
hasCredentials: Boolean(credentials)
|
|
92
|
+
}
|
|
66
93
|
});
|
|
67
94
|
}
|
|
68
95
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/integrations/api/%5Bid%5D/route.ts"],
|
|
4
|
-
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getBundle, getBundleIntegrations, getIntegration } from '@open-mercato/shared/modules/integrations/types'\nimport type { CredentialsService } from '../../lib/credentials-service'\nimport type { IntegrationStateService } from '../../lib/state-service'\n\nconst idParamsSchema = z.object({ id: z.string().min(1) })\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['integrations.view'] },\n}\n\nexport const openApi = {\n tags: ['Integrations'],\n summary: 'Get integration detail',\n}\n\nexport async function GET(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')\n ? await (ctx.params as Promise<{ id?: string }>)\n : (ctx.params as { id?: string } | undefined)\n\n const parsedParams = idParamsSchema.safeParse(rawParams)\n if (!parsedParams.success) {\n return NextResponse.json({ error: 'Invalid integration id' }, { status: 400 })\n }\n\n const integration = getIntegration(parsedParams.data.id)\n if (!integration) {\n return NextResponse.json({ error: 'Integration not found' }, { status: 404 })\n }\n\n const container = await createRequestContainer()\n const credentialsService = container.resolve('integrationCredentialsService') as CredentialsService\n const stateService = container.resolve('integrationStateService') as IntegrationStateService\n const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }\n\n const [credentials, state] = await Promise.all([\n credentialsService.resolve(integration.id, scope),\n stateService.get(integration.id, scope),\n ])\n\n const bundle = integration.bundleId ? getBundle(integration.bundleId) : undefined\n const bundleIntegrations = integration.bundleId\n ? await Promise.all(\n getBundleIntegrations(integration.bundleId).map(async (item) => {\n const itemState = await stateService.get(item.id, scope)\n const resolvedState = {\n isEnabled: itemState?.isEnabled ?? true,\n apiVersion: itemState?.apiVersion ?? null,\n reauthRequired: itemState?.reauthRequired ?? false,\n lastHealthStatus: itemState?.lastHealthStatus ?? null,\n lastHealthCheckedAt: itemState?.lastHealthCheckedAt?.toISOString() ?? null,\n }\n return {\n ...item,\n isEnabled: resolvedState.isEnabled,\n state: resolvedState,\n }\n }),\n )\n : []\n\n return
|
|
5
|
-
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAClB,SAAS,0BAA0B;AACnC,SAAS,8BAA8B;AACvC,SAAS,WAAW,uBAAuB,sBAAsB;
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getBundle, getBundleIntegrations, getIntegration } from '@open-mercato/shared/modules/integrations/types'\nimport type { CredentialsService } from '../../lib/credentials-service'\nimport type { IntegrationStateService } from '../../lib/state-service'\nimport {\n finalizeIntegrationsReadResponse,\n integrationApiRoutePaths,\n runIntegrationsReadBeforeInterceptors,\n} from '../umes-read'\n\nconst idParamsSchema = z.object({ id: z.string().min(1) })\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['integrations.view'] },\n}\n\nexport const openApi = {\n tags: ['Integrations'],\n summary: 'Get integration detail',\n}\n\nexport async function GET(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')\n ? await (ctx.params as Promise<{ id?: string }>)\n : (ctx.params as { id?: string } | undefined)\n\n const parsedParams = idParamsSchema.safeParse(rawParams)\n if (!parsedParams.success) {\n return NextResponse.json({ error: 'Invalid integration id' }, { status: 400 })\n }\n\n const integration = getIntegration(parsedParams.data.id)\n if (!integration) {\n return NextResponse.json({ error: 'Integration not found' }, { status: 404 })\n }\n\n const container = await createRequestContainer()\n const beforeInterceptors = await runIntegrationsReadBeforeInterceptors({\n routePath: integrationApiRoutePaths.detail,\n request: req,\n auth,\n container,\n })\n if (!beforeInterceptors.ok) {\n return NextResponse.json(beforeInterceptors.body, { status: beforeInterceptors.statusCode })\n }\n const credentialsService = container.resolve('integrationCredentialsService') as CredentialsService\n const stateService = container.resolve('integrationStateService') as IntegrationStateService\n const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }\n\n const [credentials, state] = await Promise.all([\n credentialsService.resolve(integration.id, scope),\n stateService.get(integration.id, scope),\n ])\n\n const bundle = integration.bundleId ? getBundle(integration.bundleId) : undefined\n const bundleIntegrations = integration.bundleId\n ? await Promise.all(\n getBundleIntegrations(integration.bundleId).map(async (item) => {\n const itemState = await stateService.get(item.id, scope)\n const resolvedState = {\n isEnabled: itemState?.isEnabled ?? true,\n apiVersion: itemState?.apiVersion ?? null,\n reauthRequired: itemState?.reauthRequired ?? false,\n lastHealthStatus: itemState?.lastHealthStatus ?? null,\n lastHealthCheckedAt: itemState?.lastHealthCheckedAt?.toISOString() ?? null,\n }\n return {\n ...item,\n isEnabled: resolvedState.isEnabled,\n state: resolvedState,\n }\n }),\n )\n : []\n\n return finalizeIntegrationsReadResponse({\n routePath: integrationApiRoutePaths.detail,\n request: req,\n auth,\n container,\n interceptorRequest: beforeInterceptors.request,\n beforeMetadata: beforeInterceptors.metadataByInterceptor,\n enrich: {\n targetEntity: 'integrations.integration',\n recordKeys: ['integration'],\n listKeys: ['bundleIntegrations'],\n },\n body: {\n integration,\n bundle,\n bundleIntegrations,\n state: {\n isEnabled: state?.isEnabled ?? true,\n apiVersion: state?.apiVersion ?? null,\n reauthRequired: state?.reauthRequired ?? false,\n lastHealthStatus: state?.lastHealthStatus ?? null,\n lastHealthCheckedAt: state?.lastHealthCheckedAt?.toISOString() ?? null,\n },\n hasCredentials: Boolean(credentials),\n },\n })\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -2,6 +2,11 @@ import { NextResponse } from "next/server";
|
|
|
2
2
|
import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
|
|
3
3
|
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
|
|
4
4
|
import { listIntegrationLogsQuerySchema } from "@open-mercato/core/modules/integrations/data/validators";
|
|
5
|
+
import {
|
|
6
|
+
finalizeIntegrationsReadResponse,
|
|
7
|
+
integrationApiRoutePaths,
|
|
8
|
+
runIntegrationsReadBeforeInterceptors
|
|
9
|
+
} from "../umes-read.js";
|
|
5
10
|
const metadata = {
|
|
6
11
|
GET: { requireAuth: true, requireFeatures: ["integrations.manage"] }
|
|
7
12
|
};
|
|
@@ -14,42 +19,63 @@ async function GET(req) {
|
|
|
14
19
|
if (!auth?.tenantId || !auth.orgId) {
|
|
15
20
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
16
21
|
}
|
|
17
|
-
const
|
|
22
|
+
const container = await createRequestContainer();
|
|
23
|
+
const beforeInterceptors = await runIntegrationsReadBeforeInterceptors({
|
|
24
|
+
routePath: integrationApiRoutePaths.logs,
|
|
25
|
+
request: req,
|
|
26
|
+
auth,
|
|
27
|
+
container
|
|
28
|
+
});
|
|
29
|
+
if (!beforeInterceptors.ok) {
|
|
30
|
+
return NextResponse.json(beforeInterceptors.body, { status: beforeInterceptors.statusCode });
|
|
31
|
+
}
|
|
32
|
+
const query = beforeInterceptors.request.query ?? {};
|
|
18
33
|
const parsed = listIntegrationLogsQuerySchema.safeParse({
|
|
19
|
-
integrationId:
|
|
20
|
-
level:
|
|
21
|
-
runId:
|
|
22
|
-
entityType:
|
|
23
|
-
entityId:
|
|
24
|
-
page:
|
|
25
|
-
pageSize:
|
|
34
|
+
integrationId: typeof query.integrationId === "string" ? query.integrationId : void 0,
|
|
35
|
+
level: typeof query.level === "string" ? query.level : void 0,
|
|
36
|
+
runId: typeof query.runId === "string" ? query.runId : void 0,
|
|
37
|
+
entityType: typeof query.entityType === "string" ? query.entityType : void 0,
|
|
38
|
+
entityId: typeof query.entityId === "string" ? query.entityId : void 0,
|
|
39
|
+
page: typeof query.page === "string" ? query.page : void 0,
|
|
40
|
+
pageSize: typeof query.pageSize === "string" ? query.pageSize : void 0
|
|
26
41
|
});
|
|
27
42
|
if (!parsed.success) {
|
|
28
43
|
return NextResponse.json({ error: "Invalid query", details: parsed.error.flatten() }, { status: 400 });
|
|
29
44
|
}
|
|
30
|
-
const container = await createRequestContainer();
|
|
31
45
|
const logService = container.resolve("integrationLogService");
|
|
32
46
|
const { items, total } = await logService.query(parsed.data, {
|
|
33
47
|
organizationId: auth.orgId,
|
|
34
48
|
tenantId: auth.tenantId
|
|
35
49
|
});
|
|
36
|
-
return
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
return finalizeIntegrationsReadResponse({
|
|
51
|
+
routePath: integrationApiRoutePaths.logs,
|
|
52
|
+
request: req,
|
|
53
|
+
auth,
|
|
54
|
+
container,
|
|
55
|
+
interceptorRequest: beforeInterceptors.request,
|
|
56
|
+
beforeMetadata: beforeInterceptors.metadataByInterceptor,
|
|
57
|
+
enrich: {
|
|
58
|
+
targetEntity: "integrations.log",
|
|
59
|
+
listKeys: ["items"]
|
|
60
|
+
},
|
|
61
|
+
body: {
|
|
62
|
+
items: items.map((item) => ({
|
|
63
|
+
id: item.id,
|
|
64
|
+
integrationId: item.integrationId,
|
|
65
|
+
runId: item.runId ?? null,
|
|
66
|
+
scopeEntityType: item.scopeEntityType ?? null,
|
|
67
|
+
scopeEntityId: item.scopeEntityId ?? null,
|
|
68
|
+
level: item.level,
|
|
69
|
+
message: item.message,
|
|
70
|
+
code: item.code ?? null,
|
|
71
|
+
payload: item.payload ?? null,
|
|
72
|
+
createdAt: item.createdAt.toISOString()
|
|
73
|
+
})),
|
|
74
|
+
total,
|
|
75
|
+
page: parsed.data.page,
|
|
76
|
+
pageSize: parsed.data.pageSize,
|
|
77
|
+
totalPages: Math.max(1, Math.ceil(total / parsed.data.pageSize))
|
|
78
|
+
}
|
|
53
79
|
});
|
|
54
80
|
}
|
|
55
81
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/integrations/api/logs/route.ts"],
|
|
4
|
-
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { listIntegrationLogsQuerySchema } from '@open-mercato/core/modules/integrations/data/validators'\nimport type { IntegrationLogService } from '@open-mercato/core/modules/integrations/lib/log-service'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['integrations.manage'] },\n}\n\nexport const openApi = {\n tags: ['Integrations'],\n summary: 'List integration logs',\n}\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const
|
|
5
|
-
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AACnC,SAAS,8BAA8B;AACvC,SAAS,sCAAsC;
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { listIntegrationLogsQuerySchema } from '@open-mercato/core/modules/integrations/data/validators'\nimport type { IntegrationLogService } from '@open-mercato/core/modules/integrations/lib/log-service'\nimport {\n finalizeIntegrationsReadResponse,\n integrationApiRoutePaths,\n runIntegrationsReadBeforeInterceptors,\n} from '../umes-read'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['integrations.manage'] },\n}\n\nexport const openApi = {\n tags: ['Integrations'],\n summary: 'List integration logs',\n}\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const container = await createRequestContainer()\n const beforeInterceptors = await runIntegrationsReadBeforeInterceptors({\n routePath: integrationApiRoutePaths.logs,\n request: req,\n auth,\n container,\n })\n if (!beforeInterceptors.ok) {\n return NextResponse.json(beforeInterceptors.body, { status: beforeInterceptors.statusCode })\n }\n\n const query = beforeInterceptors.request.query ?? {}\n const parsed = listIntegrationLogsQuerySchema.safeParse({\n integrationId: typeof query.integrationId === 'string' ? query.integrationId : undefined,\n level: typeof query.level === 'string' ? query.level : undefined,\n runId: typeof query.runId === 'string' ? query.runId : undefined,\n entityType: typeof query.entityType === 'string' ? query.entityType : undefined,\n entityId: typeof query.entityId === 'string' ? query.entityId : undefined,\n page: typeof query.page === 'string' ? query.page : undefined,\n pageSize: typeof query.pageSize === 'string' ? query.pageSize : undefined,\n })\n\n if (!parsed.success) {\n return NextResponse.json({ error: 'Invalid query', details: parsed.error.flatten() }, { status: 400 })\n }\n const logService = container.resolve('integrationLogService') as IntegrationLogService\n\n const { items, total } = await logService.query(parsed.data, {\n organizationId: auth.orgId as string,\n tenantId: auth.tenantId,\n })\n\n return finalizeIntegrationsReadResponse({\n routePath: integrationApiRoutePaths.logs,\n request: req,\n auth,\n container,\n interceptorRequest: beforeInterceptors.request,\n beforeMetadata: beforeInterceptors.metadataByInterceptor,\n enrich: {\n targetEntity: 'integrations.log',\n listKeys: ['items'],\n },\n body: {\n items: items.map((item) => ({\n id: item.id,\n integrationId: item.integrationId,\n runId: item.runId ?? null,\n scopeEntityType: item.scopeEntityType ?? null,\n scopeEntityId: item.scopeEntityId ?? null,\n level: item.level,\n message: item.message,\n code: item.code ?? null,\n payload: item.payload ?? null,\n createdAt: item.createdAt.toISOString(),\n })),\n total,\n page: parsed.data.page,\n pageSize: parsed.data.pageSize,\n totalPages: Math.max(1, Math.ceil(total / parsed.data.pageSize)),\n },\n })\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AACnC,SAAS,8BAA8B;AACvC,SAAS,sCAAsC;AAE/C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,qBAAqB,EAAE;AACrE;AAEO,MAAM,UAAU;AAAA,EACrB,MAAM,CAAC,cAAc;AAAA,EACrB,SAAS;AACX;AAEA,eAAsB,IAAI,KAAc;AACtC,QAAM,OAAO,MAAM,mBAAmB,GAAG;AACzC,MAAI,CAAC,MAAM,YAAY,CAAC,KAAK,OAAO;AAClC,WAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACrE;AAEA,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,qBAAqB,MAAM,sCAAsC;AAAA,IACrE,WAAW,yBAAyB;AAAA,IACpC,SAAS;AAAA,IACT;AAAA,IACA;AAAA,EACF,CAAC;AACD,MAAI,CAAC,mBAAmB,IAAI;AAC1B,WAAO,aAAa,KAAK,mBAAmB,MAAM,EAAE,QAAQ,mBAAmB,WAAW,CAAC;AAAA,EAC7F;AAEA,QAAM,QAAQ,mBAAmB,QAAQ,SAAS,CAAC;AACnD,QAAM,SAAS,+BAA+B,UAAU;AAAA,IACtD,eAAe,OAAO,MAAM,kBAAkB,WAAW,MAAM,gBAAgB;AAAA,IAC/E,OAAO,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ;AAAA,IACvD,OAAO,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ;AAAA,IACvD,YAAY,OAAO,MAAM,eAAe,WAAW,MAAM,aAAa;AAAA,IACtE,UAAU,OAAO,MAAM,aAAa,WAAW,MAAM,WAAW;AAAA,IAChE,MAAM,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;AAAA,IACpD,UAAU,OAAO,MAAM,aAAa,WAAW,MAAM,WAAW;AAAA,EAClE,CAAC;AAED,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,aAAa,KAAK,EAAE,OAAO,iBAAiB,SAAS,OAAO,MAAM,QAAQ,EAAE,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACvG;AACA,QAAM,aAAa,UAAU,QAAQ,uBAAuB;AAE5D,QAAM,EAAE,OAAO,MAAM,IAAI,MAAM,WAAW,MAAM,OAAO,MAAM;AAAA,IAC3D,gBAAgB,KAAK;AAAA,IACrB,UAAU,KAAK;AAAA,EACjB,CAAC;AAED,SAAO,iCAAiC;AAAA,IACtC,WAAW,yBAAyB;AAAA,IACpC,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA,oBAAoB,mBAAmB;AAAA,IACvC,gBAAgB,mBAAmB;AAAA,IACnC,QAAQ;AAAA,MACN,cAAc;AAAA,MACd,UAAU,CAAC,OAAO;AAAA,IACpB;AAAA,IACA,MAAM;AAAA,MACJ,OAAO,MAAM,IAAI,CAAC,UAAU;AAAA,QAC1B,IAAI,KAAK;AAAA,QACT,eAAe,KAAK;AAAA,QACpB,OAAO,KAAK,SAAS;AAAA,QACrB,iBAAiB,KAAK,mBAAmB;AAAA,QACzC,eAAe,KAAK,iBAAiB;AAAA,QACrC,OAAO,KAAK;AAAA,QACZ,SAAS,KAAK;AAAA,QACd,MAAM,KAAK,QAAQ;AAAA,QACnB,SAAS,KAAK,WAAW;AAAA,QACzB,WAAW,KAAK,UAAU,YAAY;AAAA,MACxC,EAAE;AAAA,MACF;AAAA,MACA,MAAM,OAAO,KAAK;AAAA,MAClB,UAAU,OAAO,KAAK;AAAA,MACtB,YAAY,KAAK,IAAI,GAAG,KAAK,KAAK,QAAQ,OAAO,KAAK,QAAQ,CAAC;AAAA,IACjE;AAAA,EACF,CAAC;AACH;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -3,6 +3,11 @@ import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
|
|
|
3
3
|
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
|
|
4
4
|
import { getAllBundles, getAllIntegrations } from "@open-mercato/shared/modules/integrations/types";
|
|
5
5
|
import { buildIntegrationsCrudOpenApi, createPagedListResponseSchema, integrationInfoSchema } from "./openapi.js";
|
|
6
|
+
import {
|
|
7
|
+
finalizeIntegrationsReadResponse,
|
|
8
|
+
integrationApiRoutePaths,
|
|
9
|
+
runIntegrationsReadBeforeInterceptors
|
|
10
|
+
} from "./umes-read.js";
|
|
6
11
|
const metadata = {
|
|
7
12
|
GET: { requireAuth: true, requireFeatures: ["integrations.view"] }
|
|
8
13
|
};
|
|
@@ -18,6 +23,15 @@ async function GET(req) {
|
|
|
18
23
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
19
24
|
}
|
|
20
25
|
const container = await createRequestContainer();
|
|
26
|
+
const beforeInterceptors = await runIntegrationsReadBeforeInterceptors({
|
|
27
|
+
routePath: integrationApiRoutePaths.list,
|
|
28
|
+
request: req,
|
|
29
|
+
auth,
|
|
30
|
+
container
|
|
31
|
+
});
|
|
32
|
+
if (!beforeInterceptors.ok) {
|
|
33
|
+
return NextResponse.json(beforeInterceptors.body, { status: beforeInterceptors.statusCode });
|
|
34
|
+
}
|
|
21
35
|
const credentialsService = container.resolve("integrationCredentialsService");
|
|
22
36
|
const stateService = container.resolve("integrationStateService");
|
|
23
37
|
const rows = await Promise.all(
|
|
@@ -29,10 +43,14 @@ async function GET(req) {
|
|
|
29
43
|
return {
|
|
30
44
|
id: integration.id,
|
|
31
45
|
title: integration.title,
|
|
46
|
+
description: integration.description ?? null,
|
|
32
47
|
category: integration.category ?? null,
|
|
33
48
|
hub: integration.hub ?? null,
|
|
34
49
|
providerKey: integration.providerKey ?? null,
|
|
35
50
|
bundleId: integration.bundleId ?? null,
|
|
51
|
+
author: integration.author ?? null,
|
|
52
|
+
company: integration.company ?? null,
|
|
53
|
+
version: integration.version ?? null,
|
|
36
54
|
hasCredentials: Boolean(resolvedCredentials),
|
|
37
55
|
isEnabled: state?.isEnabled ?? true,
|
|
38
56
|
apiVersion: state?.apiVersion ?? null
|
|
@@ -51,13 +69,25 @@ async function GET(req) {
|
|
|
51
69
|
enabledCount
|
|
52
70
|
};
|
|
53
71
|
});
|
|
54
|
-
return
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
72
|
+
return finalizeIntegrationsReadResponse({
|
|
73
|
+
routePath: integrationApiRoutePaths.list,
|
|
74
|
+
request: req,
|
|
75
|
+
auth,
|
|
76
|
+
container,
|
|
77
|
+
interceptorRequest: beforeInterceptors.request,
|
|
78
|
+
beforeMetadata: beforeInterceptors.metadataByInterceptor,
|
|
79
|
+
enrich: {
|
|
80
|
+
targetEntity: "integrations.integration",
|
|
81
|
+
listKeys: ["items"]
|
|
82
|
+
},
|
|
83
|
+
body: {
|
|
84
|
+
items: rows,
|
|
85
|
+
bundles,
|
|
86
|
+
total: rows.length,
|
|
87
|
+
page: 1,
|
|
88
|
+
pageSize: 100,
|
|
89
|
+
totalPages: 1
|
|
90
|
+
}
|
|
61
91
|
});
|
|
62
92
|
}
|
|
63
93
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/integrations/api/route.ts"],
|
|
4
|
-
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport type { CredentialsService } from '../lib/credentials-service'\nimport type { IntegrationStateService } from '../lib/state-service'\nimport { getAllBundles, getAllIntegrations } from '@open-mercato/shared/modules/integrations/types'\nimport { buildIntegrationsCrudOpenApi, createPagedListResponseSchema, integrationInfoSchema } from './openapi'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['integrations.view'] },\n}\n\nexport const openApi = buildIntegrationsCrudOpenApi({\n resourceName: 'Integration',\n pluralName: 'Integrations',\n listResponseSchema: createPagedListResponseSchema(integrationInfoSchema),\n querySchema: undefined,\n})\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const container = await createRequestContainer()\n const credentialsService = container.resolve('integrationCredentialsService') as CredentialsService\n const stateService = container.resolve('integrationStateService') as IntegrationStateService\n\n const rows = await Promise.all(\n getAllIntegrations().map(async (integration) => {\n const [resolvedCredentials, state] = await Promise.all([\n credentialsService.resolve(integration.id, { organizationId: auth.orgId as string, tenantId: auth.tenantId as string }),\n stateService.get(integration.id, { organizationId: auth.orgId as string, tenantId: auth.tenantId as string }),\n ])\n\n return {\n id: integration.id,\n title: integration.title,\n category: integration.category ?? null,\n hub: integration.hub ?? null,\n providerKey: integration.providerKey ?? null,\n bundleId: integration.bundleId ?? null,\n hasCredentials: Boolean(resolvedCredentials),\n isEnabled: state?.isEnabled ?? true,\n apiVersion: state?.apiVersion ?? null,\n }\n }),\n )\n\n const bundles = getAllBundles().map((bundle) => {\n const bundleIntegrations = rows.filter((row) => row.bundleId === bundle.id)\n const enabledCount = bundleIntegrations.reduce((count, integration) => count + (integration.isEnabled ? 1 : 0), 0)\n\n return {\n id: bundle.id,\n title: bundle.title,\n description: bundle.description,\n icon: bundle.icon ?? null,\n integrationCount: bundleIntegrations.length,\n enabledCount,\n }\n })\n\n return
|
|
5
|
-
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AACnC,SAAS,8BAA8B;AAGvC,SAAS,eAAe,0BAA0B;AAClD,SAAS,8BAA8B,+BAA+B,6BAA6B;
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport type { CredentialsService } from '../lib/credentials-service'\nimport type { IntegrationStateService } from '../lib/state-service'\nimport { getAllBundles, getAllIntegrations } from '@open-mercato/shared/modules/integrations/types'\nimport { buildIntegrationsCrudOpenApi, createPagedListResponseSchema, integrationInfoSchema } from './openapi'\nimport {\n finalizeIntegrationsReadResponse,\n integrationApiRoutePaths,\n runIntegrationsReadBeforeInterceptors,\n} from './umes-read'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['integrations.view'] },\n}\n\nexport const openApi = buildIntegrationsCrudOpenApi({\n resourceName: 'Integration',\n pluralName: 'Integrations',\n listResponseSchema: createPagedListResponseSchema(integrationInfoSchema),\n querySchema: undefined,\n})\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const container = await createRequestContainer()\n const beforeInterceptors = await runIntegrationsReadBeforeInterceptors({\n routePath: integrationApiRoutePaths.list,\n request: req,\n auth,\n container,\n })\n if (!beforeInterceptors.ok) {\n return NextResponse.json(beforeInterceptors.body, { status: beforeInterceptors.statusCode })\n }\n const credentialsService = container.resolve('integrationCredentialsService') as CredentialsService\n const stateService = container.resolve('integrationStateService') as IntegrationStateService\n\n const rows = await Promise.all(\n getAllIntegrations().map(async (integration) => {\n const [resolvedCredentials, state] = await Promise.all([\n credentialsService.resolve(integration.id, { organizationId: auth.orgId as string, tenantId: auth.tenantId as string }),\n stateService.get(integration.id, { organizationId: auth.orgId as string, tenantId: auth.tenantId as string }),\n ])\n\n return {\n id: integration.id,\n title: integration.title,\n description: integration.description ?? null,\n category: integration.category ?? null,\n hub: integration.hub ?? null,\n providerKey: integration.providerKey ?? null,\n bundleId: integration.bundleId ?? null,\n author: integration.author ?? null,\n company: integration.company ?? null,\n version: integration.version ?? null,\n hasCredentials: Boolean(resolvedCredentials),\n isEnabled: state?.isEnabled ?? true,\n apiVersion: state?.apiVersion ?? null,\n }\n }),\n )\n\n const bundles = getAllBundles().map((bundle) => {\n const bundleIntegrations = rows.filter((row) => row.bundleId === bundle.id)\n const enabledCount = bundleIntegrations.reduce((count, integration) => count + (integration.isEnabled ? 1 : 0), 0)\n\n return {\n id: bundle.id,\n title: bundle.title,\n description: bundle.description,\n icon: bundle.icon ?? null,\n integrationCount: bundleIntegrations.length,\n enabledCount,\n }\n })\n\n return finalizeIntegrationsReadResponse({\n routePath: integrationApiRoutePaths.list,\n request: req,\n auth,\n container,\n interceptorRequest: beforeInterceptors.request,\n beforeMetadata: beforeInterceptors.metadataByInterceptor,\n enrich: {\n targetEntity: 'integrations.integration',\n listKeys: ['items'],\n },\n body: {\n items: rows,\n bundles,\n total: rows.length,\n page: 1,\n pageSize: 100,\n totalPages: 1,\n },\n })\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import { runApiInterceptorsAfter, runApiInterceptorsBefore } from "@open-mercato/shared/lib/crud/interceptor-runner";
|
|
3
|
+
import { applyResponseEnrichers, applyResponseEnricherToRecord } from "@open-mercato/shared/lib/crud/enricher-runner";
|
|
4
|
+
const integrationApiRoutePaths = {
|
|
5
|
+
list: "integrations",
|
|
6
|
+
detail: "integrations/detail",
|
|
7
|
+
logs: "integrations/logs"
|
|
8
|
+
};
|
|
9
|
+
function headersToObject(headers) {
|
|
10
|
+
return Object.fromEntries(headers.entries());
|
|
11
|
+
}
|
|
12
|
+
function searchParamsToObject(url) {
|
|
13
|
+
const entries = {};
|
|
14
|
+
url.searchParams.forEach((value, key) => {
|
|
15
|
+
entries[key] = value;
|
|
16
|
+
});
|
|
17
|
+
return entries;
|
|
18
|
+
}
|
|
19
|
+
function toUserFeatures(features) {
|
|
20
|
+
if (!Array.isArray(features)) return [];
|
|
21
|
+
return features.filter((value) => typeof value === "string");
|
|
22
|
+
}
|
|
23
|
+
function mergeAdditiveRecord(base, candidate) {
|
|
24
|
+
const additions = Object.fromEntries(
|
|
25
|
+
Object.entries(candidate).filter(([key]) => !(key in base))
|
|
26
|
+
);
|
|
27
|
+
return {
|
|
28
|
+
...base,
|
|
29
|
+
...additions
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function mergeAdditiveBody(baseBody, candidateBody) {
|
|
33
|
+
return mergeAdditiveRecord(baseBody, candidateBody);
|
|
34
|
+
}
|
|
35
|
+
function getEnricherContext(input) {
|
|
36
|
+
return {
|
|
37
|
+
organizationId: input.auth.orgId,
|
|
38
|
+
tenantId: input.auth.tenantId,
|
|
39
|
+
userId: input.auth.sub ?? "",
|
|
40
|
+
em: input.container.resolve("em"),
|
|
41
|
+
container: input.container,
|
|
42
|
+
userFeatures: toUserFeatures(input.auth.features)
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
async function runIntegrationsReadBeforeInterceptors(input) {
|
|
46
|
+
const url = new URL(input.request.url);
|
|
47
|
+
return runApiInterceptorsBefore({
|
|
48
|
+
routePath: input.routePath,
|
|
49
|
+
method: "GET",
|
|
50
|
+
request: {
|
|
51
|
+
method: "GET",
|
|
52
|
+
url: input.request.url,
|
|
53
|
+
headers: headersToObject(input.request.headers),
|
|
54
|
+
query: searchParamsToObject(url)
|
|
55
|
+
},
|
|
56
|
+
context: getEnricherContext(input)
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
async function applySafeRecordEnrichment(record, targetEntity, context) {
|
|
60
|
+
const enriched = await applyResponseEnricherToRecord(record, targetEntity, context);
|
|
61
|
+
return mergeAdditiveRecord(record, enriched.record);
|
|
62
|
+
}
|
|
63
|
+
async function applySafeListEnrichment(items, targetEntity, context) {
|
|
64
|
+
const enriched = await applyResponseEnrichers(items, targetEntity, context);
|
|
65
|
+
return items.map((item, index) => {
|
|
66
|
+
const enrichedItem = enriched.items[index];
|
|
67
|
+
if (!enrichedItem) return item;
|
|
68
|
+
return mergeAdditiveRecord(item, enrichedItem);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
async function finalizeIntegrationsReadResponse(input) {
|
|
72
|
+
const method = input.method ?? "GET";
|
|
73
|
+
const baseBody = input.body;
|
|
74
|
+
const context = getEnricherContext(input);
|
|
75
|
+
const intercepted = await runApiInterceptorsAfter({
|
|
76
|
+
routePath: input.routePath,
|
|
77
|
+
method,
|
|
78
|
+
request: input.interceptorRequest,
|
|
79
|
+
response: {
|
|
80
|
+
statusCode: 200,
|
|
81
|
+
body: baseBody,
|
|
82
|
+
headers: {}
|
|
83
|
+
},
|
|
84
|
+
context,
|
|
85
|
+
metadataByInterceptor: input.beforeMetadata
|
|
86
|
+
});
|
|
87
|
+
if (!intercepted.ok) {
|
|
88
|
+
return NextResponse.json(intercepted.body, { status: intercepted.statusCode, headers: intercepted.headers });
|
|
89
|
+
}
|
|
90
|
+
let responseBody = mergeAdditiveBody(baseBody, intercepted.body);
|
|
91
|
+
if (input.enrich) {
|
|
92
|
+
const { targetEntity, recordKeys = [], listKeys = [] } = input.enrich;
|
|
93
|
+
for (const key of recordKeys) {
|
|
94
|
+
const current = responseBody[key];
|
|
95
|
+
if (!current || typeof current !== "object" || Array.isArray(current)) continue;
|
|
96
|
+
responseBody = {
|
|
97
|
+
...responseBody,
|
|
98
|
+
[key]: await applySafeRecordEnrichment(current, targetEntity, context)
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
for (const key of listKeys) {
|
|
102
|
+
const current = responseBody[key];
|
|
103
|
+
if (!Array.isArray(current)) continue;
|
|
104
|
+
const records = current.filter(
|
|
105
|
+
(item) => typeof item === "object" && item !== null && !Array.isArray(item)
|
|
106
|
+
);
|
|
107
|
+
if (records.length !== current.length) continue;
|
|
108
|
+
responseBody = {
|
|
109
|
+
...responseBody,
|
|
110
|
+
[key]: await applySafeListEnrichment(records, targetEntity, context)
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return NextResponse.json(responseBody, { headers: intercepted.headers });
|
|
115
|
+
}
|
|
116
|
+
export {
|
|
117
|
+
finalizeIntegrationsReadResponse,
|
|
118
|
+
integrationApiRoutePaths,
|
|
119
|
+
runIntegrationsReadBeforeInterceptors
|
|
120
|
+
};
|
|
121
|
+
//# sourceMappingURL=umes-read.js.map
|