@open-mercato/webhooks 0.7.1-develop.7105.1.0d2f4c6651 → 0.7.1-develop.7111.1.c0d5d7286f

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.
@@ -2,7 +2,7 @@
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { extensionPoints } from "@open-mercato/webhooks/modules/webhooks/extension-points";
5
- import { useParams, usePathname, useRouter } from "next/navigation";
5
+ import { useRouter } from "next/navigation";
6
6
  import { RotateCw } from "lucide-react";
7
7
  import { Page, PageBody } from "@open-mercato/ui/backend/Page";
8
8
  import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
@@ -37,12 +37,10 @@ const statusVariantMap = {
37
37
  expired: "destructive"
38
38
  };
39
39
  const DELIVERY_AUTO_REFRESH_INTERVAL_MS = 3e4;
40
- function WebhookDetailPage() {
41
- const params = useParams();
42
- const pathname = usePathname();
40
+ function WebhookDetailPage({ params }) {
43
41
  const router = useRouter();
44
42
  const t = useT();
45
- const webhookId = React.useMemo(() => resolveWebhookId(params?.id, pathname), [params?.id, pathname]);
43
+ const webhookId = params?.id ?? null;
46
44
  const [webhook, setWebhook] = React.useState(null);
47
45
  const [isLoading, setIsLoading] = React.useState(true);
48
46
  const [error, setError] = React.useState(null);
@@ -656,22 +654,6 @@ function WebhookDetailPage() {
656
654
  ] }) : null
657
655
  ] }) });
658
656
  }
659
- function resolveWebhookId(paramValue, pathname) {
660
- if (typeof paramValue === "string" && paramValue.trim().length > 0) {
661
- return paramValue;
662
- }
663
- if (Array.isArray(paramValue)) {
664
- const first = paramValue.find((value) => typeof value === "string" && value.trim().length > 0);
665
- if (first) return first;
666
- }
667
- if (typeof pathname === "string") {
668
- const match = pathname.match(/\/backend\/webhooks\/([^/?#]+)/);
669
- if (match?.[1]) {
670
- return decodeURIComponent(match[1]);
671
- }
672
- }
673
- return null;
674
- }
675
657
  export {
676
658
  WebhookDetailPage as default
677
659
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/webhooks/backend/webhooks/%5Bid%5D/page.tsx"],
4
- "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { extensionPoints } from '@open-mercato/webhooks/modules/webhooks/extension-points'\nimport { useParams, usePathname, useRouter } from 'next/navigation'\nimport { RotateCw } from 'lucide-react'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\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, ErrorMessage, RecordNotFoundState } from '@open-mercato/ui/backend/detail'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { useAppEvent } from '@open-mercato/ui/backend/injection/useAppEvent'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { FormHeader } from '@open-mercato/ui/backend/forms'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { deleteCrud, updateCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport {\n buildWebhookFormContentHeader,\n buildWebhookFormFields,\n buildWebhookFormGroups,\n createWebhookInitialValues,\n normalizeWebhookFormPayload,\n type WebhookFormValues,\n} from '../../../components/webhook-form-config'\nimport { useWebhookFeatureAccess } from '../useWebhookFeatureAccess'\nimport { WebhookSecretPanel } from '../../../components/WebhookSecretPanel'\n\ntype Webhook = {\n id: string\n name: string\n description: string | null\n url: string\n subscribedEvents: string[]\n httpMethod: 'POST' | 'PUT' | 'PATCH'\n isActive: boolean\n maxRetries: number\n timeoutMs: number\n rateLimitPerMinute: number\n autoDisableThreshold: number\n consecutiveFailures: number\n lastSuccessAt: string | null\n lastFailureAt: string | null\n customHeaders: Record<string, string> | null\n createdAt: string\n updatedAt: string\n maskedSecret: string\n previousSecretSetAt: string | null\n}\n\ntype DeliveryRow = {\n id: string\n webhookId: string\n eventType: string\n messageId: string\n status: string\n responseStatus: number | null\n errorMessage: string | null\n attemptNumber: number\n maxAttempts: number\n durationMs: number | null\n targetUrl: string\n enqueuedAt: string\n lastAttemptAt: string | null\n deliveredAt: string | null\n createdAt: string\n}\n\ntype DeliveryResponse = {\n items: DeliveryRow[]\n total: number\n page: number\n pageSize: number\n totalPages: number\n totalIsCapped?: boolean\n}\n\ntype DeliveryDetail = DeliveryRow & {\n payload: Record<string, unknown>\n responseBody: string | null\n responseHeaders: Record<string, string> | null\n nextRetryAt: string | null\n updatedAt: string\n}\n\nconst statusVariantMap: Record<string, 'default' | 'secondary' | 'destructive' | 'outline'> = {\n delivered: 'default',\n pending: 'secondary',\n sending: 'outline',\n failed: 'destructive',\n expired: 'destructive',\n}\nconst DELIVERY_AUTO_REFRESH_INTERVAL_MS = 30000\n\nexport default function WebhookDetailPage() {\n const params = useParams()\n const pathname = usePathname()\n const router = useRouter()\n const t = useT()\n const webhookId = React.useMemo(() => resolveWebhookId(params?.id, pathname), [params?.id, pathname])\n\n const [webhook, setWebhook] = React.useState<Webhook | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n const [isEditing, setIsEditing] = React.useState(false)\n\n const [deliveries, setDeliveries] = React.useState<DeliveryRow[]>([])\n const [deliveryPage, setDeliveryPage] = React.useState(1)\n const [deliveryTotal, setDeliveryTotal] = React.useState(0)\n const [deliveryTotalPages, setDeliveryTotalPages] = React.useState(1)\n const [deliveryTotalIsCapped, setDeliveryTotalIsCapped] = React.useState(false)\n const [deliveriesLoading, setDeliveriesLoading] = React.useState(false)\n const [isRefreshingDeliveries, setIsRefreshingDeliveries] = React.useState(false)\n const [testDelivery, setTestDelivery] = React.useState<DeliveryDetail | null>(null)\n const [selectedDelivery, setSelectedDelivery] = React.useState<DeliveryDetail | null>(null)\n const [selectedDeliveryLoading, setSelectedDeliveryLoading] = React.useState(false)\n const [revealedSecret, setRevealedSecret] = React.useState<string | null>(null)\n const refreshInFlightRef = React.useRef(false)\n const access = useWebhookFeatureAccess()\n\n const fetchWebhook = React.useCallback(async (options?: { silent?: boolean }) => {\n if (!webhookId) {\n setIsNotFound(true)\n setIsLoading(false)\n return\n }\n\n const silent = options?.silent === true\n if (!silent) {\n setIsLoading(true)\n }\n\n setError(null)\n setIsNotFound(false)\n\n try {\n const call = await apiCall<Webhook>(\n `/api/webhooks/${encodeURIComponent(webhookId)}`,\n undefined,\n { fallback: null },\n )\n\n if (call.ok && call.result) {\n setWebhook(call.result)\n return\n }\n\n if (call.status === 404) {\n setIsNotFound(true)\n } else {\n setError(t('webhooks.detail.loadError'))\n }\n } catch (loadError) {\n setError(loadError instanceof Error ? loadError.message : t('webhooks.detail.loadError'))\n } finally {\n if (!silent) {\n setIsLoading(false)\n }\n }\n }, [t, webhookId])\n\n const fetchDeliveries = React.useCallback(async (options?: { silent?: boolean }) => {\n if (!webhookId) return\n\n const silent = options?.silent === true\n if (!silent) {\n setDeliveriesLoading(true)\n }\n\n try {\n const params = new URLSearchParams()\n params.set('webhookId', webhookId)\n params.set('page', String(deliveryPage))\n params.set('pageSize', '20')\n\n const fallback: DeliveryResponse = { items: [], total: 0, page: deliveryPage, pageSize: 20, totalPages: 1 }\n const call = await apiCall<DeliveryResponse>(\n `/api/webhooks/deliveries?${params.toString()}`,\n undefined,\n { fallback },\n )\n\n if (call.ok && call.result) {\n setDeliveries(call.result.items)\n setDeliveryTotal(call.result.total)\n setDeliveryTotalPages(call.result.totalPages)\n setDeliveryTotalIsCapped(call.result.totalIsCapped === true)\n }\n } finally {\n if (!silent) {\n setDeliveriesLoading(false)\n }\n }\n }, [deliveryPage, webhookId])\n\n const fetchDeliveryDetail = React.useCallback(async (deliveryId: string): Promise<DeliveryDetail | null> => {\n const call = await apiCall<DeliveryDetail>(\n `/api/webhooks/deliveries/${encodeURIComponent(deliveryId)}`,\n undefined,\n { fallback: null },\n )\n\n if (!call.ok || !call.result) {\n return null\n }\n\n return call.result\n }, [])\n\n const refreshDeliveryState = React.useCallback(async () => {\n if (!webhookId || refreshInFlightRef.current) return\n\n refreshInFlightRef.current = true\n setIsRefreshingDeliveries(true)\n\n try {\n await Promise.all([\n fetchWebhook({ silent: true }),\n fetchDeliveries({ silent: true }),\n ])\n\n const detailIds = [selectedDelivery?.id, testDelivery?.id].filter(\n (value): value is string => typeof value === 'string' && value.length > 0,\n )\n\n if (detailIds.length > 0) {\n const details = await Promise.all(detailIds.map((deliveryId) => fetchDeliveryDetail(deliveryId)))\n const detailMap = new Map<string, DeliveryDetail>()\n\n for (const detail of details) {\n if (detail) {\n detailMap.set(detail.id, detail)\n }\n }\n\n if (selectedDelivery?.id) {\n setSelectedDelivery((current) => current?.id ? (detailMap.get(current.id) ?? current) : current)\n }\n\n if (testDelivery?.id) {\n setTestDelivery((current) => current?.id ? (detailMap.get(current.id) ?? current) : current)\n }\n }\n } finally {\n refreshInFlightRef.current = false\n setIsRefreshingDeliveries(false)\n }\n }, [fetchDeliveries, fetchDeliveryDetail, fetchWebhook, selectedDelivery?.id, testDelivery?.id, webhookId])\n\n React.useEffect(() => {\n void fetchWebhook()\n }, [fetchWebhook])\n\n React.useEffect(() => {\n if (!webhookId) return\n void fetchDeliveries()\n }, [fetchDeliveries, webhookId])\n\n useAppEvent('webhooks.delivery.*', (event) => {\n const eventWebhookId = typeof event.payload?.webhookId === 'string' ? event.payload.webhookId : null\n if (eventWebhookId !== webhookId) return\n void refreshDeliveryState()\n }, [refreshDeliveryState, webhookId])\n\n React.useEffect(() => {\n if (!webhookId || isEditing) return\n\n const intervalId = window.setInterval(() => {\n if (document.visibilityState !== 'visible') return\n void refreshDeliveryState()\n }, DELIVERY_AUTO_REFRESH_INTERVAL_MS)\n\n return () => {\n window.clearInterval(intervalId)\n }\n }, [isEditing, refreshDeliveryState, webhookId])\n\n const handleToggleActive = React.useCallback(async () => {\n if (!webhook) return\n try {\n const call = await apiCall<Webhook>(\n `/api/webhooks/${encodeURIComponent(webhook.id)}`,\n {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ isActive: !webhook.isActive }),\n },\n { fallback: null },\n )\n if (call.ok) {\n setWebhook((prev) => prev ? { ...prev, isActive: !prev.isActive } : prev)\n flash(t('webhooks.form.updateSuccess'), 'success')\n void refreshDeliveryState()\n }\n } catch {\n flash(t('webhooks.form.updateError'), 'error')\n }\n }, [refreshDeliveryState, webhook, t])\n\n const handleRotateSecret = React.useCallback(async () => {\n if (!webhook) return\n try {\n const call = await apiCall<{ secret: string }>(\n `/api/webhooks/${encodeURIComponent(webhook.id)}/rotate-secret`,\n { method: 'POST' },\n { fallback: null },\n )\n if (!call.ok || !call.result) {\n flash(t('webhooks.detail.rotateError'), 'error')\n return\n }\n setRevealedSecret(call.result.secret)\n flash(t('webhooks.detail.rotateSuccess'), 'success')\n void refreshDeliveryState()\n } catch {\n flash(t('webhooks.detail.rotateError'), 'error')\n }\n }, [refreshDeliveryState, t, webhook])\n\n const handleTest = React.useCallback(async () => {\n if (!webhook) return\n try {\n const call = await apiCall<{ delivery: DeliveryDetail }>(\n `/api/webhooks/${encodeURIComponent(webhook.id)}/test`,\n { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({}) },\n { fallback: null },\n )\n if (!call.ok || !call.result) {\n flash(t('webhooks.detail.testError'), 'error')\n return\n }\n const deliveryStatus = call.result.delivery.status\n setTestDelivery(call.result.delivery)\n flash(\n deliveryStatus === 'delivered' ? t('webhooks.detail.testSuccess') : t('webhooks.detail.testQueued'),\n deliveryStatus === 'delivered' ? 'success' : 'error',\n )\n void refreshDeliveryState()\n } catch {\n flash(t('webhooks.detail.testError'), 'error')\n }\n }, [refreshDeliveryState, t, webhook])\n\n const handleRetryDelivery = React.useCallback(async (deliveryId: string) => {\n try {\n const call = await apiCall(\n `/api/webhooks/deliveries/${encodeURIComponent(deliveryId)}/retry`,\n { method: 'POST' },\n { fallback: null },\n )\n if (!call.ok) {\n flash(t('webhooks.deliveries.retryError'), 'error')\n return\n }\n flash(t('webhooks.deliveries.retrySuccess'), 'success')\n void refreshDeliveryState()\n } catch {\n flash(t('webhooks.deliveries.retryError'), 'error')\n }\n }, [refreshDeliveryState, t])\n\n const handleDelete = React.useCallback(async () => {\n if (!webhook) return\n try {\n await deleteCrud(`webhooks/${encodeURIComponent(webhook.id)}`, {\n fallbackResult: null,\n headers: buildOptimisticLockHeader(webhook.updatedAt),\n })\n flash(t('webhooks.list.deleteSuccess'), 'success')\n router.push('/backend/webhooks')\n } catch (error) {\n if (surfaceRecordConflict(error, t)) return\n flash(t('webhooks.list.deleteError'), 'error')\n }\n }, [router, t, webhook])\n\n const handleDeliveryOpen = React.useCallback(async (deliveryId: string) => {\n setSelectedDeliveryLoading(true)\n try {\n const detail = await fetchDeliveryDetail(deliveryId)\n if (!detail) {\n flash(t('webhooks.deliveries.loadError'), 'error')\n return\n }\n setSelectedDelivery(detail)\n } catch {\n flash(t('webhooks.deliveries.loadError'), 'error')\n } finally {\n setSelectedDeliveryLoading(false)\n }\n }, [fetchDeliveryDetail, t])\n\n const deliveryColumns = React.useMemo<ColumnDef<DeliveryRow>[]>(() => [\n { accessorKey: 'eventType', header: t('webhooks.deliveries.columns.event') },\n {\n accessorKey: 'status',\n header: t('webhooks.deliveries.columns.status'),\n cell: ({ row }) => (\n <Badge variant={statusVariantMap[row.original.status] ?? 'secondary'}>\n {t(`webhooks.deliveries.status.${row.original.status}` as Parameters<typeof t>[0])}\n </Badge>\n ),\n },\n {\n accessorKey: 'responseStatus',\n header: t('webhooks.deliveries.columns.responseStatus'),\n cell: ({ row }) => row.original.responseStatus ?? '\u2014',\n },\n {\n accessorKey: 'attemptNumber',\n header: t('webhooks.deliveries.columns.attempts'),\n cell: ({ row }) => `${row.original.attemptNumber}/${row.original.maxAttempts}`,\n },\n {\n accessorKey: 'durationMs',\n header: t('webhooks.deliveries.columns.duration'),\n cell: ({ row }) => row.original.durationMs != null ? `${row.original.durationMs}ms` : '\u2014',\n },\n {\n accessorKey: 'createdAt',\n header: t('webhooks.deliveries.columns.enqueuedAt'),\n cell: ({ row }) => {\n try { return new Date(row.original.enqueuedAt).toLocaleString() }\n catch { return '\u2014' }\n },\n },\n ], [t])\n\n const fields = React.useMemo(() => buildWebhookFormFields(t), [t])\n const groups = React.useMemo(() => buildWebhookFormGroups(t), [t])\n const contentHeader = React.useMemo(() => buildWebhookFormContentHeader(t), [t])\n const menuActions = React.useMemo(() => {\n const items: Array<{ id: string; label: string; onSelect: () => void }> = []\n const isActive = webhook?.isActive ?? false\n\n if (access.canManage) {\n items.push(\n {\n id: 'edit',\n label: t('webhooks.list.actions.edit'),\n onSelect: () => setIsEditing(true),\n },\n {\n id: 'toggle-active',\n label: isActive ? t('webhooks.detail.actions.deactivate') : t('webhooks.detail.actions.activate'),\n onSelect: () => { void handleToggleActive() },\n },\n )\n }\n\n if (access.canSecrets) {\n items.push({\n id: 'rotate-secret',\n label: t('webhooks.detail.actions.rotateSecret'),\n onSelect: () => { void handleRotateSecret() },\n })\n }\n\n if (access.canTest) {\n items.push({\n id: 'test',\n label: t('webhooks.detail.actions.test'),\n onSelect: () => { void handleTest() },\n })\n }\n\n if (access.canManage) {\n items.push({\n id: 'delete',\n label: t('webhooks.list.actions.delete'),\n onSelect: () => { void handleDelete() },\n })\n }\n\n return items\n }, [access.canManage, access.canSecrets, access.canTest, handleDelete, handleRotateSecret, handleTest, handleToggleActive, t, webhook?.isActive])\n\n if (isLoading) return <Page><PageBody><LoadingMessage label={t('webhooks.detail.loading')} /></PageBody></Page>\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('webhooks.errors.notFound')}\n backHref=\"/backend/webhooks\"\n backLabel={t('webhooks.detail.backToList', 'Back to webhooks')}\n />\n </PageBody>\n </Page>\n )\n }\n if (error || !webhook) return <Page><PageBody><ErrorMessage label={error ?? t('webhooks.detail.loadError')} /></PageBody></Page>\n\n if (isEditing) {\n return (\n <Page>\n <PageBody>\n <CrudForm\n title={t('webhooks.form.title.edit')}\n backHref={`/backend/webhooks/${webhook.id}`}\n fields={fields}\n groups={groups}\n initialValues={createWebhookInitialValues(webhook)}\n optimisticLockUpdatedAt={webhook.updatedAt}\n submitLabel={t('common.save')}\n cancelHref={`/backend/webhooks/${webhook.id}`}\n contentHeader={contentHeader}\n onDelete={access.canManage ? handleDelete : undefined}\n onSubmit={async (values) => {\n const payload = normalizeWebhookFormPayload(values as WebhookFormValues, t)\n await updateCrud(`webhooks/${encodeURIComponent(webhook.id)}`, payload)\n flash(t('webhooks.form.updateSuccess'), 'success')\n setIsEditing(false)\n await refreshDeliveryState()\n }}\n />\n </PageBody>\n </Page>\n )\n }\n\n return (\n <Page>\n <PageBody>\n {revealedSecret ? (\n <WebhookSecretPanel secret={revealedSecret} onClose={() => setRevealedSecret(null)} />\n ) : null}\n <FormHeader\n mode=\"detail\"\n title={webhook.name}\n entityTypeLabel={t('webhooks.nav.title')}\n statusBadge={\n <Badge\n className={webhook.isActive\n ? 'border-transparent bg-status-success-bg text-status-success-text'\n : 'border-transparent bg-status-neutral-bg text-status-neutral-text'}\n >\n {webhook.isActive ? t('webhooks.list.status.active') : t('webhooks.list.status.inactive')}\n </Badge>\n }\n backHref=\"/backend/webhooks\"\n menuActions={menuActions}\n />\n\n <div className=\"mt-6 space-y-4\">\n {!access.isLoading && !access.canManage && !access.canSecrets && !access.canTest ? (\n <Alert status=\"information\">\n <AlertDescription>{t('webhooks.detail.readOnlyTip')}</AlertDescription>\n </Alert>\n ) : null}\n <div className=\"grid gap-3 lg:grid-cols-2\">\n <Alert status=\"information\">\n <AlertDescription>{t('webhooks.detail.deliveryTip')}</AlertDescription>\n </Alert>\n <Alert status=\"information\">\n <AlertDescription>{t('webhooks.detail.signatureTip')}</AlertDescription>\n </Alert>\n </div>\n <div className=\"grid grid-cols-2 gap-4 text-sm\">\n <div>\n <span className=\"text-muted-foreground\">{t('webhooks.form.url')}:</span>\n <code className=\"ml-2 text-xs break-all\">{webhook.url}</code>\n </div>\n <div>\n <span className=\"text-muted-foreground\">{t('webhooks.form.httpMethod')}:</span>\n <span className=\"ml-2\">{webhook.httpMethod}</span>\n </div>\n <div>\n <span className=\"text-muted-foreground\">{t('webhooks.form.subscribedEvents')}:</span>\n <span className=\"ml-2 text-xs\">{webhook.subscribedEvents.join(', ')}</span>\n </div>\n <div>\n <span className=\"text-muted-foreground\">{t('webhooks.form.maxRetries')}:</span>\n <span className=\"ml-2\">{webhook.maxRetries}</span>\n </div>\n <div>\n <span className=\"text-muted-foreground\">{t('webhooks.form.rateLimitPerMinute')}:</span>\n <span className=\"ml-2\">{webhook.rateLimitPerMinute}</span>\n </div>\n <div>\n <span className=\"text-muted-foreground\">{t('webhooks.form.autoDisableThreshold')}:</span>\n <span className=\"ml-2\">{webhook.autoDisableThreshold}</span>\n </div>\n <div>\n <span className=\"text-muted-foreground\">{t('webhooks.detail.consecutiveFailures')}:</span>\n <span className=\"ml-2\">{webhook.consecutiveFailures}</span>\n </div>\n <div>\n <span className=\"text-muted-foreground\">{t('webhooks.form.secret')}:</span>\n <span className=\"ml-2 inline-flex items-center gap-2\">\n <span className=\"font-mono text-xs\">{webhook.maskedSecret}</span>\n {access.canSecrets ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"h-7 px-2 text-xs\"\n onClick={() => { void handleRotateSecret() }}\n >\n <RotateCw className=\"mr-1.5 size-3.5\" />\n {t('webhooks.detail.actions.rotateSecret')}\n </Button>\n ) : null}\n </span>\n </div>\n <div>\n <span className=\"text-muted-foreground\">{t('webhooks.list.columns.lastDelivery')}:</span>\n <span className=\"ml-2\">{webhook.lastSuccessAt ?? webhook.lastFailureAt ?? '\u2014'}</span>\n </div>\n <div>\n <span className=\"text-muted-foreground\">{t('webhooks.detail.previousSecretSetAt')}:</span>\n <span className=\"ml-2\">{webhook.previousSecretSetAt ?? '\u2014'}</span>\n </div>\n <div className=\"col-span-2\">\n <span className=\"text-muted-foreground\">{t('webhooks.form.customHeaders')}:</span>\n <pre className=\"mt-2 rounded border bg-muted/50 p-3 text-xs\">\n {webhook.customHeaders ? JSON.stringify(webhook.customHeaders, null, 2) : '\u2014'}\n </pre>\n </div>\n </div>\n </div>\n\n {testDelivery ? (\n <div className=\"mt-8 rounded-lg border bg-card p-4\">\n <h2 className=\"text-sm font-semibold\">{t('webhooks.detail.testResult')}</h2>\n <div className=\"mt-3 grid gap-2 text-sm\">\n <div>{t('webhooks.deliveries.columns.status')}: {testDelivery.status}</div>\n <div>{t('webhooks.deliveries.columns.responseStatus')}: {testDelivery.responseStatus ?? '\u2014'}</div>\n <div>{t('webhooks.deliveries.columns.duration')}: {testDelivery.durationMs != null ? `${testDelivery.durationMs}ms` : '\u2014'}</div>\n <pre className=\"overflow-auto rounded border bg-muted/50 p-3 text-xs\">\n {JSON.stringify(testDelivery.payload, null, 2)}\n </pre>\n </div>\n </div>\n ) : null}\n\n <div className=\"mt-8\">\n <DataTable\n title={t('webhooks.deliveries.title')}\n actions={(\n <div className=\"flex items-center gap-2\">\n <span className=\"hidden text-xs text-muted-foreground md:inline\">\n {t('webhooks.deliveries.autoRefreshHint')}\n </span>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => { void refreshDeliveryState() }}\n disabled={isRefreshingDeliveries}\n >\n {isRefreshingDeliveries\n ? t('webhooks.deliveries.refreshing')\n : t('webhooks.deliveries.refresh')}\n </Button>\n </div>\n )}\n columns={deliveryColumns}\n data={deliveries}\n onRowClick={(row) => { void handleDeliveryOpen(row.id) }}\n rowActions={(row) => {\n const items: Array<{ id: string; label: string; onSelect: () => void }> = [\n {\n id: 'view-details',\n label: t('webhooks.deliveries.actions.viewDetails'),\n onSelect: () => { void handleDeliveryOpen(row.id) },\n },\n ]\n\n if (access.canManage && (row.status === 'failed' || row.status === 'expired')) {\n items.push({\n id: 'retry',\n label: t('webhooks.deliveries.actions.retry'),\n onSelect: () => { void handleRetryDelivery(row.id) },\n })\n }\n\n return <RowActions items={items} />\n }}\n perspective={{ tableId: extensionPoints.hosts.deliveriesTable.tableId }}\n pagination={{\n page: deliveryPage,\n pageSize: 20,\n total: deliveryTotal,\n totalPages: deliveryTotalPages,\n totalIsCapped: deliveryTotalIsCapped,\n onPageChange: setDeliveryPage,\n }}\n isLoading={deliveriesLoading || isRefreshingDeliveries}\n />\n </div>\n\n {selectedDelivery || selectedDeliveryLoading ? (\n <div className=\"mt-6 rounded-lg border bg-card p-4\">\n <h2 className=\"text-sm font-semibold\">{t('webhooks.deliveries.detailTitle')}</h2>\n {selectedDeliveryLoading || !selectedDelivery ? (\n <div className=\"mt-3 text-sm text-muted-foreground\">{t('common.loading')}</div>\n ) : (\n <div className=\"mt-3 space-y-4 text-sm\">\n <div>{t('webhooks.deliveries.columns.status')}: {selectedDelivery.status}</div>\n <div>{t('webhooks.deliveries.columns.responseStatus')}: {selectedDelivery.responseStatus ?? '\u2014'}</div>\n <div>{t('webhooks.deliveries.columns.duration')}: {selectedDelivery.durationMs != null ? `${selectedDelivery.durationMs}ms` : '\u2014'}</div>\n <div>\n <div className=\"mb-2 font-medium\">{t('webhooks.deliveries.requestBody')}</div>\n <pre className=\"overflow-auto rounded border bg-muted/50 p-3 text-xs\">\n {JSON.stringify(selectedDelivery.payload, null, 2)}\n </pre>\n </div>\n <div>\n <div className=\"mb-2 font-medium\">{t('webhooks.deliveries.responseBody')}</div>\n <pre className=\"overflow-auto rounded border bg-muted/50 p-3 text-xs\">\n {selectedDelivery.responseBody ?? '\u2014'}\n </pre>\n </div>\n <div>\n <div className=\"mb-2 font-medium\">{t('webhooks.deliveries.responseHeaders')}</div>\n <pre className=\"overflow-auto rounded border bg-muted/50 p-3 text-xs\">\n {selectedDelivery.responseHeaders ? JSON.stringify(selectedDelivery.responseHeaders, null, 2) : '\u2014'}\n </pre>\n </div>\n </div>\n )}\n </div>\n ) : null}\n </PageBody>\n </Page>\n )\n}\n\nfunction resolveWebhookId(paramValue: string | string[] | undefined, pathname: string | null): string | null {\n if (typeof paramValue === 'string' && paramValue.trim().length > 0) {\n return paramValue\n }\n\n if (Array.isArray(paramValue)) {\n const first = paramValue.find((value) => typeof value === 'string' && value.trim().length > 0)\n if (first) return first\n }\n\n if (typeof pathname === 'string') {\n const match = pathname.match(/\\/backend\\/webhooks\\/([^/?#]+)/)\n if (match?.[1]) {\n return decodeURIComponent(match[1])\n }\n }\n\n return null\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { extensionPoints } from '@open-mercato/webhooks/modules/webhooks/extension-points'\nimport { useRouter } from 'next/navigation'\nimport { RotateCw } from 'lucide-react'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\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, ErrorMessage, RecordNotFoundState } from '@open-mercato/ui/backend/detail'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { useAppEvent } from '@open-mercato/ui/backend/injection/useAppEvent'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { FormHeader } from '@open-mercato/ui/backend/forms'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { deleteCrud, updateCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport {\n buildWebhookFormContentHeader,\n buildWebhookFormFields,\n buildWebhookFormGroups,\n createWebhookInitialValues,\n normalizeWebhookFormPayload,\n type WebhookFormValues,\n} from '../../../components/webhook-form-config'\nimport { useWebhookFeatureAccess } from '../useWebhookFeatureAccess'\nimport { WebhookSecretPanel } from '../../../components/WebhookSecretPanel'\n\ntype Webhook = {\n id: string\n name: string\n description: string | null\n url: string\n subscribedEvents: string[]\n httpMethod: 'POST' | 'PUT' | 'PATCH'\n isActive: boolean\n maxRetries: number\n timeoutMs: number\n rateLimitPerMinute: number\n autoDisableThreshold: number\n consecutiveFailures: number\n lastSuccessAt: string | null\n lastFailureAt: string | null\n customHeaders: Record<string, string> | null\n createdAt: string\n updatedAt: string\n maskedSecret: string\n previousSecretSetAt: string | null\n}\n\ntype DeliveryRow = {\n id: string\n webhookId: string\n eventType: string\n messageId: string\n status: string\n responseStatus: number | null\n errorMessage: string | null\n attemptNumber: number\n maxAttempts: number\n durationMs: number | null\n targetUrl: string\n enqueuedAt: string\n lastAttemptAt: string | null\n deliveredAt: string | null\n createdAt: string\n}\n\ntype DeliveryResponse = {\n items: DeliveryRow[]\n total: number\n page: number\n pageSize: number\n totalPages: number\n totalIsCapped?: boolean\n}\n\ntype DeliveryDetail = DeliveryRow & {\n payload: Record<string, unknown>\n responseBody: string | null\n responseHeaders: Record<string, string> | null\n nextRetryAt: string | null\n updatedAt: string\n}\n\nconst statusVariantMap: Record<string, 'default' | 'secondary' | 'destructive' | 'outline'> = {\n delivered: 'default',\n pending: 'secondary',\n sending: 'outline',\n failed: 'destructive',\n expired: 'destructive',\n}\nconst DELIVERY_AUTO_REFRESH_INTERVAL_MS = 30000\n\nexport default function WebhookDetailPage({ params }: { params?: { id?: string } }) {\n const router = useRouter()\n const t = useT()\n const webhookId = params?.id ?? null\n\n const [webhook, setWebhook] = React.useState<Webhook | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n const [isEditing, setIsEditing] = React.useState(false)\n\n const [deliveries, setDeliveries] = React.useState<DeliveryRow[]>([])\n const [deliveryPage, setDeliveryPage] = React.useState(1)\n const [deliveryTotal, setDeliveryTotal] = React.useState(0)\n const [deliveryTotalPages, setDeliveryTotalPages] = React.useState(1)\n const [deliveryTotalIsCapped, setDeliveryTotalIsCapped] = React.useState(false)\n const [deliveriesLoading, setDeliveriesLoading] = React.useState(false)\n const [isRefreshingDeliveries, setIsRefreshingDeliveries] = React.useState(false)\n const [testDelivery, setTestDelivery] = React.useState<DeliveryDetail | null>(null)\n const [selectedDelivery, setSelectedDelivery] = React.useState<DeliveryDetail | null>(null)\n const [selectedDeliveryLoading, setSelectedDeliveryLoading] = React.useState(false)\n const [revealedSecret, setRevealedSecret] = React.useState<string | null>(null)\n const refreshInFlightRef = React.useRef(false)\n const access = useWebhookFeatureAccess()\n\n const fetchWebhook = React.useCallback(async (options?: { silent?: boolean }) => {\n if (!webhookId) {\n setIsNotFound(true)\n setIsLoading(false)\n return\n }\n\n const silent = options?.silent === true\n if (!silent) {\n setIsLoading(true)\n }\n\n setError(null)\n setIsNotFound(false)\n\n try {\n const call = await apiCall<Webhook>(\n `/api/webhooks/${encodeURIComponent(webhookId)}`,\n undefined,\n { fallback: null },\n )\n\n if (call.ok && call.result) {\n setWebhook(call.result)\n return\n }\n\n if (call.status === 404) {\n setIsNotFound(true)\n } else {\n setError(t('webhooks.detail.loadError'))\n }\n } catch (loadError) {\n setError(loadError instanceof Error ? loadError.message : t('webhooks.detail.loadError'))\n } finally {\n if (!silent) {\n setIsLoading(false)\n }\n }\n }, [t, webhookId])\n\n const fetchDeliveries = React.useCallback(async (options?: { silent?: boolean }) => {\n if (!webhookId) return\n\n const silent = options?.silent === true\n if (!silent) {\n setDeliveriesLoading(true)\n }\n\n try {\n const params = new URLSearchParams()\n params.set('webhookId', webhookId)\n params.set('page', String(deliveryPage))\n params.set('pageSize', '20')\n\n const fallback: DeliveryResponse = { items: [], total: 0, page: deliveryPage, pageSize: 20, totalPages: 1 }\n const call = await apiCall<DeliveryResponse>(\n `/api/webhooks/deliveries?${params.toString()}`,\n undefined,\n { fallback },\n )\n\n if (call.ok && call.result) {\n setDeliveries(call.result.items)\n setDeliveryTotal(call.result.total)\n setDeliveryTotalPages(call.result.totalPages)\n setDeliveryTotalIsCapped(call.result.totalIsCapped === true)\n }\n } finally {\n if (!silent) {\n setDeliveriesLoading(false)\n }\n }\n }, [deliveryPage, webhookId])\n\n const fetchDeliveryDetail = React.useCallback(async (deliveryId: string): Promise<DeliveryDetail | null> => {\n const call = await apiCall<DeliveryDetail>(\n `/api/webhooks/deliveries/${encodeURIComponent(deliveryId)}`,\n undefined,\n { fallback: null },\n )\n\n if (!call.ok || !call.result) {\n return null\n }\n\n return call.result\n }, [])\n\n const refreshDeliveryState = React.useCallback(async () => {\n if (!webhookId || refreshInFlightRef.current) return\n\n refreshInFlightRef.current = true\n setIsRefreshingDeliveries(true)\n\n try {\n await Promise.all([\n fetchWebhook({ silent: true }),\n fetchDeliveries({ silent: true }),\n ])\n\n const detailIds = [selectedDelivery?.id, testDelivery?.id].filter(\n (value): value is string => typeof value === 'string' && value.length > 0,\n )\n\n if (detailIds.length > 0) {\n const details = await Promise.all(detailIds.map((deliveryId) => fetchDeliveryDetail(deliveryId)))\n const detailMap = new Map<string, DeliveryDetail>()\n\n for (const detail of details) {\n if (detail) {\n detailMap.set(detail.id, detail)\n }\n }\n\n if (selectedDelivery?.id) {\n setSelectedDelivery((current) => current?.id ? (detailMap.get(current.id) ?? current) : current)\n }\n\n if (testDelivery?.id) {\n setTestDelivery((current) => current?.id ? (detailMap.get(current.id) ?? current) : current)\n }\n }\n } finally {\n refreshInFlightRef.current = false\n setIsRefreshingDeliveries(false)\n }\n }, [fetchDeliveries, fetchDeliveryDetail, fetchWebhook, selectedDelivery?.id, testDelivery?.id, webhookId])\n\n React.useEffect(() => {\n void fetchWebhook()\n }, [fetchWebhook])\n\n React.useEffect(() => {\n if (!webhookId) return\n void fetchDeliveries()\n }, [fetchDeliveries, webhookId])\n\n useAppEvent('webhooks.delivery.*', (event) => {\n const eventWebhookId = typeof event.payload?.webhookId === 'string' ? event.payload.webhookId : null\n if (eventWebhookId !== webhookId) return\n void refreshDeliveryState()\n }, [refreshDeliveryState, webhookId])\n\n React.useEffect(() => {\n if (!webhookId || isEditing) return\n\n const intervalId = window.setInterval(() => {\n if (document.visibilityState !== 'visible') return\n void refreshDeliveryState()\n }, DELIVERY_AUTO_REFRESH_INTERVAL_MS)\n\n return () => {\n window.clearInterval(intervalId)\n }\n }, [isEditing, refreshDeliveryState, webhookId])\n\n const handleToggleActive = React.useCallback(async () => {\n if (!webhook) return\n try {\n const call = await apiCall<Webhook>(\n `/api/webhooks/${encodeURIComponent(webhook.id)}`,\n {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ isActive: !webhook.isActive }),\n },\n { fallback: null },\n )\n if (call.ok) {\n setWebhook((prev) => prev ? { ...prev, isActive: !prev.isActive } : prev)\n flash(t('webhooks.form.updateSuccess'), 'success')\n void refreshDeliveryState()\n }\n } catch {\n flash(t('webhooks.form.updateError'), 'error')\n }\n }, [refreshDeliveryState, webhook, t])\n\n const handleRotateSecret = React.useCallback(async () => {\n if (!webhook) return\n try {\n const call = await apiCall<{ secret: string }>(\n `/api/webhooks/${encodeURIComponent(webhook.id)}/rotate-secret`,\n { method: 'POST' },\n { fallback: null },\n )\n if (!call.ok || !call.result) {\n flash(t('webhooks.detail.rotateError'), 'error')\n return\n }\n setRevealedSecret(call.result.secret)\n flash(t('webhooks.detail.rotateSuccess'), 'success')\n void refreshDeliveryState()\n } catch {\n flash(t('webhooks.detail.rotateError'), 'error')\n }\n }, [refreshDeliveryState, t, webhook])\n\n const handleTest = React.useCallback(async () => {\n if (!webhook) return\n try {\n const call = await apiCall<{ delivery: DeliveryDetail }>(\n `/api/webhooks/${encodeURIComponent(webhook.id)}/test`,\n { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({}) },\n { fallback: null },\n )\n if (!call.ok || !call.result) {\n flash(t('webhooks.detail.testError'), 'error')\n return\n }\n const deliveryStatus = call.result.delivery.status\n setTestDelivery(call.result.delivery)\n flash(\n deliveryStatus === 'delivered' ? t('webhooks.detail.testSuccess') : t('webhooks.detail.testQueued'),\n deliveryStatus === 'delivered' ? 'success' : 'error',\n )\n void refreshDeliveryState()\n } catch {\n flash(t('webhooks.detail.testError'), 'error')\n }\n }, [refreshDeliveryState, t, webhook])\n\n const handleRetryDelivery = React.useCallback(async (deliveryId: string) => {\n try {\n const call = await apiCall(\n `/api/webhooks/deliveries/${encodeURIComponent(deliveryId)}/retry`,\n { method: 'POST' },\n { fallback: null },\n )\n if (!call.ok) {\n flash(t('webhooks.deliveries.retryError'), 'error')\n return\n }\n flash(t('webhooks.deliveries.retrySuccess'), 'success')\n void refreshDeliveryState()\n } catch {\n flash(t('webhooks.deliveries.retryError'), 'error')\n }\n }, [refreshDeliveryState, t])\n\n const handleDelete = React.useCallback(async () => {\n if (!webhook) return\n try {\n await deleteCrud(`webhooks/${encodeURIComponent(webhook.id)}`, {\n fallbackResult: null,\n headers: buildOptimisticLockHeader(webhook.updatedAt),\n })\n flash(t('webhooks.list.deleteSuccess'), 'success')\n router.push('/backend/webhooks')\n } catch (error) {\n if (surfaceRecordConflict(error, t)) return\n flash(t('webhooks.list.deleteError'), 'error')\n }\n }, [router, t, webhook])\n\n const handleDeliveryOpen = React.useCallback(async (deliveryId: string) => {\n setSelectedDeliveryLoading(true)\n try {\n const detail = await fetchDeliveryDetail(deliveryId)\n if (!detail) {\n flash(t('webhooks.deliveries.loadError'), 'error')\n return\n }\n setSelectedDelivery(detail)\n } catch {\n flash(t('webhooks.deliveries.loadError'), 'error')\n } finally {\n setSelectedDeliveryLoading(false)\n }\n }, [fetchDeliveryDetail, t])\n\n const deliveryColumns = React.useMemo<ColumnDef<DeliveryRow>[]>(() => [\n { accessorKey: 'eventType', header: t('webhooks.deliveries.columns.event') },\n {\n accessorKey: 'status',\n header: t('webhooks.deliveries.columns.status'),\n cell: ({ row }) => (\n <Badge variant={statusVariantMap[row.original.status] ?? 'secondary'}>\n {t(`webhooks.deliveries.status.${row.original.status}` as Parameters<typeof t>[0])}\n </Badge>\n ),\n },\n {\n accessorKey: 'responseStatus',\n header: t('webhooks.deliveries.columns.responseStatus'),\n cell: ({ row }) => row.original.responseStatus ?? '\u2014',\n },\n {\n accessorKey: 'attemptNumber',\n header: t('webhooks.deliveries.columns.attempts'),\n cell: ({ row }) => `${row.original.attemptNumber}/${row.original.maxAttempts}`,\n },\n {\n accessorKey: 'durationMs',\n header: t('webhooks.deliveries.columns.duration'),\n cell: ({ row }) => row.original.durationMs != null ? `${row.original.durationMs}ms` : '\u2014',\n },\n {\n accessorKey: 'createdAt',\n header: t('webhooks.deliveries.columns.enqueuedAt'),\n cell: ({ row }) => {\n try { return new Date(row.original.enqueuedAt).toLocaleString() }\n catch { return '\u2014' }\n },\n },\n ], [t])\n\n const fields = React.useMemo(() => buildWebhookFormFields(t), [t])\n const groups = React.useMemo(() => buildWebhookFormGroups(t), [t])\n const contentHeader = React.useMemo(() => buildWebhookFormContentHeader(t), [t])\n const menuActions = React.useMemo(() => {\n const items: Array<{ id: string; label: string; onSelect: () => void }> = []\n const isActive = webhook?.isActive ?? false\n\n if (access.canManage) {\n items.push(\n {\n id: 'edit',\n label: t('webhooks.list.actions.edit'),\n onSelect: () => setIsEditing(true),\n },\n {\n id: 'toggle-active',\n label: isActive ? t('webhooks.detail.actions.deactivate') : t('webhooks.detail.actions.activate'),\n onSelect: () => { void handleToggleActive() },\n },\n )\n }\n\n if (access.canSecrets) {\n items.push({\n id: 'rotate-secret',\n label: t('webhooks.detail.actions.rotateSecret'),\n onSelect: () => { void handleRotateSecret() },\n })\n }\n\n if (access.canTest) {\n items.push({\n id: 'test',\n label: t('webhooks.detail.actions.test'),\n onSelect: () => { void handleTest() },\n })\n }\n\n if (access.canManage) {\n items.push({\n id: 'delete',\n label: t('webhooks.list.actions.delete'),\n onSelect: () => { void handleDelete() },\n })\n }\n\n return items\n }, [access.canManage, access.canSecrets, access.canTest, handleDelete, handleRotateSecret, handleTest, handleToggleActive, t, webhook?.isActive])\n\n if (isLoading) return <Page><PageBody><LoadingMessage label={t('webhooks.detail.loading')} /></PageBody></Page>\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('webhooks.errors.notFound')}\n backHref=\"/backend/webhooks\"\n backLabel={t('webhooks.detail.backToList', 'Back to webhooks')}\n />\n </PageBody>\n </Page>\n )\n }\n if (error || !webhook) return <Page><PageBody><ErrorMessage label={error ?? t('webhooks.detail.loadError')} /></PageBody></Page>\n\n if (isEditing) {\n return (\n <Page>\n <PageBody>\n <CrudForm\n title={t('webhooks.form.title.edit')}\n backHref={`/backend/webhooks/${webhook.id}`}\n fields={fields}\n groups={groups}\n initialValues={createWebhookInitialValues(webhook)}\n optimisticLockUpdatedAt={webhook.updatedAt}\n submitLabel={t('common.save')}\n cancelHref={`/backend/webhooks/${webhook.id}`}\n contentHeader={contentHeader}\n onDelete={access.canManage ? handleDelete : undefined}\n onSubmit={async (values) => {\n const payload = normalizeWebhookFormPayload(values as WebhookFormValues, t)\n await updateCrud(`webhooks/${encodeURIComponent(webhook.id)}`, payload)\n flash(t('webhooks.form.updateSuccess'), 'success')\n setIsEditing(false)\n await refreshDeliveryState()\n }}\n />\n </PageBody>\n </Page>\n )\n }\n\n return (\n <Page>\n <PageBody>\n {revealedSecret ? (\n <WebhookSecretPanel secret={revealedSecret} onClose={() => setRevealedSecret(null)} />\n ) : null}\n <FormHeader\n mode=\"detail\"\n title={webhook.name}\n entityTypeLabel={t('webhooks.nav.title')}\n statusBadge={\n <Badge\n className={webhook.isActive\n ? 'border-transparent bg-status-success-bg text-status-success-text'\n : 'border-transparent bg-status-neutral-bg text-status-neutral-text'}\n >\n {webhook.isActive ? t('webhooks.list.status.active') : t('webhooks.list.status.inactive')}\n </Badge>\n }\n backHref=\"/backend/webhooks\"\n menuActions={menuActions}\n />\n\n <div className=\"mt-6 space-y-4\">\n {!access.isLoading && !access.canManage && !access.canSecrets && !access.canTest ? (\n <Alert status=\"information\">\n <AlertDescription>{t('webhooks.detail.readOnlyTip')}</AlertDescription>\n </Alert>\n ) : null}\n <div className=\"grid gap-3 lg:grid-cols-2\">\n <Alert status=\"information\">\n <AlertDescription>{t('webhooks.detail.deliveryTip')}</AlertDescription>\n </Alert>\n <Alert status=\"information\">\n <AlertDescription>{t('webhooks.detail.signatureTip')}</AlertDescription>\n </Alert>\n </div>\n <div className=\"grid grid-cols-2 gap-4 text-sm\">\n <div>\n <span className=\"text-muted-foreground\">{t('webhooks.form.url')}:</span>\n <code className=\"ml-2 text-xs break-all\">{webhook.url}</code>\n </div>\n <div>\n <span className=\"text-muted-foreground\">{t('webhooks.form.httpMethod')}:</span>\n <span className=\"ml-2\">{webhook.httpMethod}</span>\n </div>\n <div>\n <span className=\"text-muted-foreground\">{t('webhooks.form.subscribedEvents')}:</span>\n <span className=\"ml-2 text-xs\">{webhook.subscribedEvents.join(', ')}</span>\n </div>\n <div>\n <span className=\"text-muted-foreground\">{t('webhooks.form.maxRetries')}:</span>\n <span className=\"ml-2\">{webhook.maxRetries}</span>\n </div>\n <div>\n <span className=\"text-muted-foreground\">{t('webhooks.form.rateLimitPerMinute')}:</span>\n <span className=\"ml-2\">{webhook.rateLimitPerMinute}</span>\n </div>\n <div>\n <span className=\"text-muted-foreground\">{t('webhooks.form.autoDisableThreshold')}:</span>\n <span className=\"ml-2\">{webhook.autoDisableThreshold}</span>\n </div>\n <div>\n <span className=\"text-muted-foreground\">{t('webhooks.detail.consecutiveFailures')}:</span>\n <span className=\"ml-2\">{webhook.consecutiveFailures}</span>\n </div>\n <div>\n <span className=\"text-muted-foreground\">{t('webhooks.form.secret')}:</span>\n <span className=\"ml-2 inline-flex items-center gap-2\">\n <span className=\"font-mono text-xs\">{webhook.maskedSecret}</span>\n {access.canSecrets ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"h-7 px-2 text-xs\"\n onClick={() => { void handleRotateSecret() }}\n >\n <RotateCw className=\"mr-1.5 size-3.5\" />\n {t('webhooks.detail.actions.rotateSecret')}\n </Button>\n ) : null}\n </span>\n </div>\n <div>\n <span className=\"text-muted-foreground\">{t('webhooks.list.columns.lastDelivery')}:</span>\n <span className=\"ml-2\">{webhook.lastSuccessAt ?? webhook.lastFailureAt ?? '\u2014'}</span>\n </div>\n <div>\n <span className=\"text-muted-foreground\">{t('webhooks.detail.previousSecretSetAt')}:</span>\n <span className=\"ml-2\">{webhook.previousSecretSetAt ?? '\u2014'}</span>\n </div>\n <div className=\"col-span-2\">\n <span className=\"text-muted-foreground\">{t('webhooks.form.customHeaders')}:</span>\n <pre className=\"mt-2 rounded border bg-muted/50 p-3 text-xs\">\n {webhook.customHeaders ? JSON.stringify(webhook.customHeaders, null, 2) : '\u2014'}\n </pre>\n </div>\n </div>\n </div>\n\n {testDelivery ? (\n <div className=\"mt-8 rounded-lg border bg-card p-4\">\n <h2 className=\"text-sm font-semibold\">{t('webhooks.detail.testResult')}</h2>\n <div className=\"mt-3 grid gap-2 text-sm\">\n <div>{t('webhooks.deliveries.columns.status')}: {testDelivery.status}</div>\n <div>{t('webhooks.deliveries.columns.responseStatus')}: {testDelivery.responseStatus ?? '\u2014'}</div>\n <div>{t('webhooks.deliveries.columns.duration')}: {testDelivery.durationMs != null ? `${testDelivery.durationMs}ms` : '\u2014'}</div>\n <pre className=\"overflow-auto rounded border bg-muted/50 p-3 text-xs\">\n {JSON.stringify(testDelivery.payload, null, 2)}\n </pre>\n </div>\n </div>\n ) : null}\n\n <div className=\"mt-8\">\n <DataTable\n title={t('webhooks.deliveries.title')}\n actions={(\n <div className=\"flex items-center gap-2\">\n <span className=\"hidden text-xs text-muted-foreground md:inline\">\n {t('webhooks.deliveries.autoRefreshHint')}\n </span>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => { void refreshDeliveryState() }}\n disabled={isRefreshingDeliveries}\n >\n {isRefreshingDeliveries\n ? t('webhooks.deliveries.refreshing')\n : t('webhooks.deliveries.refresh')}\n </Button>\n </div>\n )}\n columns={deliveryColumns}\n data={deliveries}\n onRowClick={(row) => { void handleDeliveryOpen(row.id) }}\n rowActions={(row) => {\n const items: Array<{ id: string; label: string; onSelect: () => void }> = [\n {\n id: 'view-details',\n label: t('webhooks.deliveries.actions.viewDetails'),\n onSelect: () => { void handleDeliveryOpen(row.id) },\n },\n ]\n\n if (access.canManage && (row.status === 'failed' || row.status === 'expired')) {\n items.push({\n id: 'retry',\n label: t('webhooks.deliveries.actions.retry'),\n onSelect: () => { void handleRetryDelivery(row.id) },\n })\n }\n\n return <RowActions items={items} />\n }}\n perspective={{ tableId: extensionPoints.hosts.deliveriesTable.tableId }}\n pagination={{\n page: deliveryPage,\n pageSize: 20,\n total: deliveryTotal,\n totalPages: deliveryTotalPages,\n totalIsCapped: deliveryTotalIsCapped,\n onPageChange: setDeliveryPage,\n }}\n isLoading={deliveriesLoading || isRefreshingDeliveries}\n />\n </div>\n\n {selectedDelivery || selectedDeliveryLoading ? (\n <div className=\"mt-6 rounded-lg border bg-card p-4\">\n <h2 className=\"text-sm font-semibold\">{t('webhooks.deliveries.detailTitle')}</h2>\n {selectedDeliveryLoading || !selectedDelivery ? (\n <div className=\"mt-3 text-sm text-muted-foreground\">{t('common.loading')}</div>\n ) : (\n <div className=\"mt-3 space-y-4 text-sm\">\n <div>{t('webhooks.deliveries.columns.status')}: {selectedDelivery.status}</div>\n <div>{t('webhooks.deliveries.columns.responseStatus')}: {selectedDelivery.responseStatus ?? '\u2014'}</div>\n <div>{t('webhooks.deliveries.columns.duration')}: {selectedDelivery.durationMs != null ? `${selectedDelivery.durationMs}ms` : '\u2014'}</div>\n <div>\n <div className=\"mb-2 font-medium\">{t('webhooks.deliveries.requestBody')}</div>\n <pre className=\"overflow-auto rounded border bg-muted/50 p-3 text-xs\">\n {JSON.stringify(selectedDelivery.payload, null, 2)}\n </pre>\n </div>\n <div>\n <div className=\"mb-2 font-medium\">{t('webhooks.deliveries.responseBody')}</div>\n <pre className=\"overflow-auto rounded border bg-muted/50 p-3 text-xs\">\n {selectedDelivery.responseBody ?? '\u2014'}\n </pre>\n </div>\n <div>\n <div className=\"mb-2 font-medium\">{t('webhooks.deliveries.responseHeaders')}</div>\n <pre className=\"overflow-auto rounded border bg-muted/50 p-3 text-xs\">\n {selectedDelivery.responseHeaders ? JSON.stringify(selectedDelivery.responseHeaders, null, 2) : '\u2014'}\n </pre>\n </div>\n </div>\n )}\n </div>\n ) : null}\n </PageBody>\n </Page>\n )\n}\n\n"],
5
+ "mappings": "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",
6
6
  "names": ["params", "error"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/webhooks",
3
- "version": "0.7.1-develop.7105.1.0d2f4c6651",
3
+ "version": "0.7.1-develop.7111.1.c0d5d7286f",
4
4
  "license": "MIT",
5
5
  "description": "Webhooks module for Open Mercato — Standard Webhooks compliant outbound/inbound delivery",
6
6
  "type": "module",
@@ -70,19 +70,19 @@
70
70
  }
71
71
  },
72
72
  "dependencies": {
73
- "@open-mercato/core": "0.7.1-develop.7105.1.0d2f4c6651",
74
- "@open-mercato/queue": "0.7.1-develop.7105.1.0d2f4c6651",
75
- "@open-mercato/ui": "0.7.1-develop.7105.1.0d2f4c6651",
73
+ "@open-mercato/core": "0.7.1-develop.7111.1.c0d5d7286f",
74
+ "@open-mercato/queue": "0.7.1-develop.7111.1.c0d5d7286f",
75
+ "@open-mercato/ui": "0.7.1-develop.7111.1.c0d5d7286f",
76
76
  "svix": "^1.99.1"
77
77
  },
78
78
  "peerDependencies": {
79
79
  "@mikro-orm/postgresql": "^7.0.14",
80
- "@open-mercato/shared": "0.7.1-develop.7105.1.0d2f4c6651",
80
+ "@open-mercato/shared": "0.7.1-develop.7111.1.c0d5d7286f",
81
81
  "react": "^19.0.0",
82
82
  "react-dom": "^19.0.0"
83
83
  },
84
84
  "devDependencies": {
85
- "@open-mercato/shared": "0.7.1-develop.7105.1.0d2f4c6651",
85
+ "@open-mercato/shared": "0.7.1-develop.7111.1.c0d5d7286f",
86
86
  "@types/jest": "^30.0.0",
87
87
  "@types/react": "^19.2.17",
88
88
  "@types/react-dom": "^19.2.3",
@@ -1,7 +1,7 @@
1
1
  "use client"
2
2
  import * as React from 'react'
3
3
  import { extensionPoints } from '@open-mercato/webhooks/modules/webhooks/extension-points'
4
- import { useParams, usePathname, useRouter } from 'next/navigation'
4
+ import { useRouter } from 'next/navigation'
5
5
  import { RotateCw } from 'lucide-react'
6
6
  import { Page, PageBody } from '@open-mercato/ui/backend/Page'
7
7
  import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
@@ -97,12 +97,10 @@ const statusVariantMap: Record<string, 'default' | 'secondary' | 'destructive' |
97
97
  }
98
98
  const DELIVERY_AUTO_REFRESH_INTERVAL_MS = 30000
99
99
 
100
- export default function WebhookDetailPage() {
101
- const params = useParams()
102
- const pathname = usePathname()
100
+ export default function WebhookDetailPage({ params }: { params?: { id?: string } }) {
103
101
  const router = useRouter()
104
102
  const t = useT()
105
- const webhookId = React.useMemo(() => resolveWebhookId(params?.id, pathname), [params?.id, pathname])
103
+ const webhookId = params?.id ?? null
106
104
 
107
105
  const [webhook, setWebhook] = React.useState<Webhook | null>(null)
108
106
  const [isLoading, setIsLoading] = React.useState(true)
@@ -733,22 +731,3 @@ export default function WebhookDetailPage() {
733
731
  )
734
732
  }
735
733
 
736
- function resolveWebhookId(paramValue: string | string[] | undefined, pathname: string | null): string | null {
737
- if (typeof paramValue === 'string' && paramValue.trim().length > 0) {
738
- return paramValue
739
- }
740
-
741
- if (Array.isArray(paramValue)) {
742
- const first = paramValue.find((value) => typeof value === 'string' && value.trim().length > 0)
743
- if (first) return first
744
- }
745
-
746
- if (typeof pathname === 'string') {
747
- const match = pathname.match(/\/backend\/webhooks\/([^/?#]+)/)
748
- if (match?.[1]) {
749
- return decodeURIComponent(match[1])
750
- }
751
- }
752
-
753
- return null
754
- }