@open-mercato/core 0.4.2-canary-07dbc98202 → 0.4.2-canary-11e19dfb84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generated/entities.ids.generated.js +59 -63
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +0 -2
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/api_docs/frontend/docs/api/page.js +2 -3
- package/dist/modules/api_docs/frontend/docs/api/page.js.map +2 -2
- package/dist/modules/auth/api/admin/nav.js +3 -4
- package/dist/modules/auth/api/admin/nav.js.map +2 -2
- package/dist/modules/auth/api/reset/confirm.js +2 -25
- package/dist/modules/auth/api/reset/confirm.js.map +2 -2
- package/dist/modules/auth/api/reset.js +0 -23
- package/dist/modules/auth/api/reset.js.map +2 -2
- package/dist/modules/auth/api/sidebar/preferences/route.js +9 -14
- package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
- package/dist/modules/auth/commands/users.js +0 -55
- package/dist/modules/auth/commands/users.js.map +2 -2
- package/dist/modules/auth/lib/setup-app.js +0 -1
- package/dist/modules/auth/lib/setup-app.js.map +2 -2
- package/dist/modules/auth/services/authService.js +3 -3
- package/dist/modules/auth/services/authService.js.map +2 -2
- package/dist/modules/configs/cli.js +0 -6
- package/dist/modules/configs/cli.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +0 -31
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +0 -53
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/commands/payments.js +0 -26
- package/dist/modules/sales/commands/payments.js.map +2 -2
- package/dist/modules/staff/commands/leave-requests.js +0 -79
- package/dist/modules/staff/commands/leave-requests.js.map +2 -2
- package/generated/entities.ids.generated.ts +59 -63
- package/generated/entity-fields-registry.ts +0 -2
- package/package.json +2 -2
- package/src/modules/api_docs/frontend/docs/api/page.tsx +2 -3
- package/src/modules/auth/api/admin/nav.ts +6 -10
- package/src/modules/auth/api/reset/confirm.ts +2 -25
- package/src/modules/auth/api/reset.ts +0 -23
- package/src/modules/auth/api/sidebar/preferences/route.ts +12 -21
- package/src/modules/auth/commands/users.ts +0 -68
- package/src/modules/auth/i18n/de.json +1 -29
- package/src/modules/auth/i18n/en.json +1 -29
- package/src/modules/auth/i18n/es.json +1 -29
- package/src/modules/auth/i18n/pl.json +1 -29
- package/src/modules/auth/lib/setup-app.ts +0 -1
- package/src/modules/auth/services/authService.ts +4 -4
- package/src/modules/business_rules/i18n/en.json +1 -3
- package/src/modules/catalog/i18n/en.json +1 -3
- package/src/modules/configs/cli.ts +0 -6
- package/src/modules/customers/commands/deals.ts +0 -39
- package/src/modules/customers/i18n/en.json +1 -5
- package/src/modules/sales/commands/documents.ts +0 -65
- package/src/modules/sales/commands/payments.ts +0 -33
- package/src/modules/sales/i18n/de.json +0 -20
- package/src/modules/sales/i18n/en.json +1 -25
- package/src/modules/sales/i18n/es.json +0 -20
- package/src/modules/sales/i18n/pl.json +0 -20
- package/src/modules/staff/commands/leave-requests.ts +0 -94
- package/src/modules/staff/i18n/de.json +0 -4
- package/src/modules/staff/i18n/en.json +1 -9
- package/src/modules/staff/i18n/es.json +0 -4
- package/src/modules/staff/i18n/pl.json +0 -4
- package/src/modules/workflows/i18n/en.json +1 -3
- package/dist/generated/entities/notification/index.js +0 -57
- package/dist/generated/entities/notification/index.js.map +0 -7
- package/dist/modules/auth/api/profile/route.js +0 -155
- package/dist/modules/auth/api/profile/route.js.map +0 -7
- package/dist/modules/auth/backend/auth/profile/page.js +0 -99
- package/dist/modules/auth/backend/auth/profile/page.js.map +0 -7
- package/dist/modules/auth/backend/auth/profile/page.meta.js +0 -12
- package/dist/modules/auth/backend/auth/profile/page.meta.js.map +0 -7
- package/dist/modules/auth/notifications.js +0 -112
- package/dist/modules/auth/notifications.js.map +0 -7
- package/dist/modules/business_rules/notifications.js +0 -28
- package/dist/modules/business_rules/notifications.js.map +0 -7
- package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js +0 -37
- package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js.map +0 -7
- package/dist/modules/catalog/notifications.js +0 -28
- package/dist/modules/catalog/notifications.js.map +0 -7
- package/dist/modules/catalog/subscribers/low-stock-notification.js +0 -38
- package/dist/modules/catalog/subscribers/low-stock-notification.js.map +0 -7
- package/dist/modules/customers/notifications.js +0 -48
- package/dist/modules/customers/notifications.js.map +0 -7
- package/dist/modules/notifications/acl.js +0 -11
- package/dist/modules/notifications/acl.js.map +0 -7
- package/dist/modules/notifications/api/[id]/action/route.js +0 -74
- package/dist/modules/notifications/api/[id]/action/route.js.map +0 -7
- package/dist/modules/notifications/api/[id]/dismiss/route.js +0 -15
- package/dist/modules/notifications/api/[id]/dismiss/route.js.map +0 -7
- package/dist/modules/notifications/api/[id]/read/route.js +0 -15
- package/dist/modules/notifications/api/[id]/read/route.js.map +0 -7
- package/dist/modules/notifications/api/[id]/restore/route.js +0 -53
- package/dist/modules/notifications/api/[id]/restore/route.js.map +0 -7
- package/dist/modules/notifications/api/batch/route.js +0 -17
- package/dist/modules/notifications/api/batch/route.js.map +0 -7
- package/dist/modules/notifications/api/feature/route.js +0 -17
- package/dist/modules/notifications/api/feature/route.js.map +0 -7
- package/dist/modules/notifications/api/mark-all-read/route.js +0 -35
- package/dist/modules/notifications/api/mark-all-read/route.js.map +0 -7
- package/dist/modules/notifications/api/openapi.js +0 -76
- package/dist/modules/notifications/api/openapi.js.map +0 -7
- package/dist/modules/notifications/api/role/route.js +0 -17
- package/dist/modules/notifications/api/role/route.js.map +0 -7
- package/dist/modules/notifications/api/route.js +0 -85
- package/dist/modules/notifications/api/route.js.map +0 -7
- package/dist/modules/notifications/api/settings/route.js +0 -155
- package/dist/modules/notifications/api/settings/route.js.map +0 -7
- package/dist/modules/notifications/api/unread-count/route.js +0 -38
- package/dist/modules/notifications/api/unread-count/route.js.map +0 -7
- package/dist/modules/notifications/backend/config/notifications/page.js +0 -10
- package/dist/modules/notifications/backend/config/notifications/page.js.map +0 -7
- package/dist/modules/notifications/backend/config/notifications/page.meta.js +0 -24
- package/dist/modules/notifications/backend/config/notifications/page.meta.js.map +0 -7
- package/dist/modules/notifications/cli.js +0 -16
- package/dist/modules/notifications/cli.js.map +0 -7
- package/dist/modules/notifications/data/entities.js +0 -112
- package/dist/modules/notifications/data/entities.js.map +0 -7
- package/dist/modules/notifications/data/validators.js +0 -94
- package/dist/modules/notifications/data/validators.js.map +0 -7
- package/dist/modules/notifications/di.js +0 -13
- package/dist/modules/notifications/di.js.map +0 -7
- package/dist/modules/notifications/emails/NotificationEmail.js +0 -58
- package/dist/modules/notifications/emails/NotificationEmail.js.map +0 -7
- package/dist/modules/notifications/frontend/NotificationInboxPageClient.js +0 -44
- package/dist/modules/notifications/frontend/NotificationInboxPageClient.js.map +0 -7
- package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js +0 -219
- package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js.map +0 -7
- package/dist/modules/notifications/index.js +0 -14
- package/dist/modules/notifications/index.js.map +0 -7
- package/dist/modules/notifications/lib/deliveryConfig.js +0 -105
- package/dist/modules/notifications/lib/deliveryConfig.js.map +0 -7
- package/dist/modules/notifications/lib/events.js +0 -12
- package/dist/modules/notifications/lib/events.js.map +0 -7
- package/dist/modules/notifications/lib/notificationBuilder.js +0 -66
- package/dist/modules/notifications/lib/notificationBuilder.js.map +0 -7
- package/dist/modules/notifications/lib/notificationFactory.js +0 -54
- package/dist/modules/notifications/lib/notificationFactory.js.map +0 -7
- package/dist/modules/notifications/lib/notificationMapper.js +0 -34
- package/dist/modules/notifications/lib/notificationMapper.js.map +0 -7
- package/dist/modules/notifications/lib/notificationRecipients.js +0 -35
- package/dist/modules/notifications/lib/notificationRecipients.js.map +0 -7
- package/dist/modules/notifications/lib/notificationService.js +0 -279
- package/dist/modules/notifications/lib/notificationService.js.map +0 -7
- package/dist/modules/notifications/lib/routeHelpers.js +0 -101
- package/dist/modules/notifications/lib/routeHelpers.js.map +0 -7
- package/dist/modules/notifications/lib/safeHref.js +0 -24
- package/dist/modules/notifications/lib/safeHref.js.map +0 -7
- package/dist/modules/notifications/migrations/Migration20260123000001.js +0 -70
- package/dist/modules/notifications/migrations/Migration20260123000001.js.map +0 -7
- package/dist/modules/notifications/migrations/Migration20260126150000.js +0 -37
- package/dist/modules/notifications/migrations/Migration20260126150000.js.map +0 -7
- package/dist/modules/notifications/subscribers/deliver-notification.js +0 -139
- package/dist/modules/notifications/subscribers/deliver-notification.js.map +0 -7
- package/dist/modules/notifications/workers/create-notification.worker.js +0 -70
- package/dist/modules/notifications/workers/create-notification.worker.js.map +0 -7
- package/dist/modules/sales/notifications.client.js +0 -51
- package/dist/modules/sales/notifications.client.js.map +0 -7
- package/dist/modules/sales/notifications.js +0 -88
- package/dist/modules/sales/notifications.js.map +0 -7
- package/dist/modules/sales/subscribers/quote-expiring-notification.js +0 -38
- package/dist/modules/sales/subscribers/quote-expiring-notification.js.map +0 -7
- package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js +0 -137
- package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js.map +0 -7
- package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js +0 -137
- package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js.map +0 -7
- package/dist/modules/sales/widgets/notifications/index.js +0 -7
- package/dist/modules/sales/widgets/notifications/index.js.map +0 -7
- package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js +0 -60
- package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js.map +0 -7
- package/dist/modules/staff/notifications.js +0 -75
- package/dist/modules/staff/notifications.js.map +0 -7
- package/dist/modules/workflows/notifications.js +0 -28
- package/dist/modules/workflows/notifications.js.map +0 -7
- package/dist/modules/workflows/subscribers/task-assigned-notification.js +0 -38
- package/dist/modules/workflows/subscribers/task-assigned-notification.js.map +0 -7
- package/generated/entities/notification/index.ts +0 -27
- package/src/modules/auth/api/profile/route.ts +0 -160
- package/src/modules/auth/backend/auth/profile/page.meta.ts +0 -8
- package/src/modules/auth/backend/auth/profile/page.tsx +0 -127
- package/src/modules/auth/notifications.ts +0 -109
- package/src/modules/business_rules/notifications.ts +0 -25
- package/src/modules/business_rules/subscribers/rule-execution-failed-notification.ts +0 -50
- package/src/modules/catalog/notifications.ts +0 -25
- package/src/modules/catalog/subscribers/low-stock-notification.ts +0 -52
- package/src/modules/customers/notifications.ts +0 -44
- package/src/modules/notifications/acl.ts +0 -7
- package/src/modules/notifications/api/[id]/action/route.ts +0 -75
- package/src/modules/notifications/api/[id]/dismiss/route.ts +0 -12
- package/src/modules/notifications/api/[id]/read/route.ts +0 -12
- package/src/modules/notifications/api/[id]/restore/route.ts +0 -53
- package/src/modules/notifications/api/batch/route.ts +0 -14
- package/src/modules/notifications/api/feature/route.ts +0 -14
- package/src/modules/notifications/api/mark-all-read/route.ts +0 -34
- package/src/modules/notifications/api/openapi.ts +0 -76
- package/src/modules/notifications/api/role/route.ts +0 -14
- package/src/modules/notifications/api/route.ts +0 -92
- package/src/modules/notifications/api/settings/route.ts +0 -157
- package/src/modules/notifications/api/unread-count/route.ts +0 -38
- package/src/modules/notifications/backend/config/notifications/page.meta.ts +0 -22
- package/src/modules/notifications/backend/config/notifications/page.tsx +0 -12
- package/src/modules/notifications/cli.ts +0 -18
- package/src/modules/notifications/data/entities.ts +0 -99
- package/src/modules/notifications/data/validators.ts +0 -110
- package/src/modules/notifications/di.ts +0 -11
- package/src/modules/notifications/emails/NotificationEmail.tsx +0 -98
- package/src/modules/notifications/frontend/NotificationInboxPageClient.tsx +0 -42
- package/src/modules/notifications/frontend/NotificationSettingsPageClient.tsx +0 -231
- package/src/modules/notifications/i18n/de.json +0 -50
- package/src/modules/notifications/i18n/en.json +0 -50
- package/src/modules/notifications/i18n/es.json +0 -50
- package/src/modules/notifications/i18n/pl.json +0 -50
- package/src/modules/notifications/index.ts +0 -12
- package/src/modules/notifications/lib/deliveryConfig.ts +0 -145
- package/src/modules/notifications/lib/events.ts +0 -48
- package/src/modules/notifications/lib/notificationBuilder.ts +0 -121
- package/src/modules/notifications/lib/notificationFactory.ts +0 -76
- package/src/modules/notifications/lib/notificationMapper.ts +0 -33
- package/src/modules/notifications/lib/notificationRecipients.ts +0 -83
- package/src/modules/notifications/lib/notificationService.ts +0 -414
- package/src/modules/notifications/lib/routeHelpers.ts +0 -151
- package/src/modules/notifications/lib/safeHref.ts +0 -29
- package/src/modules/notifications/migrations/.snapshot-open-mercato.json +0 -300
- package/src/modules/notifications/migrations/Migration20260123000001.ts +0 -73
- package/src/modules/notifications/migrations/Migration20260126150000.ts +0 -39
- package/src/modules/notifications/subscribers/deliver-notification.ts +0 -175
- package/src/modules/notifications/workers/create-notification.worker.ts +0 -122
- package/src/modules/sales/notifications.client.ts +0 -65
- package/src/modules/sales/notifications.ts +0 -82
- package/src/modules/sales/subscribers/quote-expiring-notification.ts +0 -53
- package/src/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.tsx +0 -156
- package/src/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.tsx +0 -156
- package/src/modules/sales/widgets/notifications/index.ts +0 -2
- package/src/modules/sales/widgets/notifications/useSalesDocumentTotals.ts +0 -81
- package/src/modules/staff/notifications.ts +0 -71
- package/src/modules/workflows/notifications.ts +0 -25
- package/src/modules/workflows/subscribers/task-assigned-notification.ts +0 -53
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../src/modules/notifications/frontend/NotificationSettingsPageClient.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { apiCall, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport { Switch } from '@open-mercato/ui/primitives/switch'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@open-mercato/ui/primitives/card'\n\ntype NotificationDeliveryConfig = {\n appUrl?: string\n panelPath: string\n strategies: {\n database: { enabled: boolean }\n email: { enabled: boolean; from?: string; replyTo?: string; subjectPrefix?: string }\n }\n}\n\ntype SettingsResponse = {\n settings?: NotificationDeliveryConfig\n error?: string\n}\n\nconst emptySettings: NotificationDeliveryConfig = {\n panelPath: '/backend/notifications',\n strategies: {\n database: { enabled: true },\n email: { enabled: true },\n },\n}\n\nexport function NotificationSettingsPageClient() {\n const t = useT()\n const [settings, setSettings] = React.useState<NotificationDeliveryConfig | null>(null)\n const [loading, setLoading] = React.useState(true)\n const [saving, setSaving] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n\n const fetchSettings = React.useCallback(async () => {\n setLoading(true)\n setError(null)\n try {\n const body = await readApiResultOrThrow<SettingsResponse>(\n '/api/notifications/settings',\n undefined,\n { errorMessage: t('notifications.settings.loadError', 'Failed to load notification settings'), allowNullResult: true },\n )\n if (body?.settings) {\n setSettings(body.settings)\n } else {\n setSettings(emptySettings)\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : t('notifications.settings.loadError', 'Failed to load notification settings')\n setError(message)\n flash(message, 'error')\n } finally {\n setLoading(false)\n }\n }, [t])\n\n React.useEffect(() => {\n fetchSettings()\n }, [fetchSettings])\n\n const updateSettings = (patch: Partial<NotificationDeliveryConfig>) => {\n setSettings((prev) => (prev ? { ...prev, ...patch } : prev))\n }\n\n const updateStrategy = (\n strategy: keyof NotificationDeliveryConfig['strategies'],\n patch: Partial<NotificationDeliveryConfig['strategies'][keyof NotificationDeliveryConfig['strategies']]>,\n ) => {\n setSettings((prev) => {\n if (!prev) return prev\n return {\n ...prev,\n strategies: {\n ...prev.strategies,\n [strategy]: {\n ...prev.strategies[strategy],\n ...patch,\n },\n },\n }\n })\n }\n\n const handleSave = async () => {\n if (!settings) return\n setSaving(true)\n try {\n const response = await apiCall<SettingsResponse>('/api/notifications/settings', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(settings),\n })\n if (!response.ok) {\n const message = response.result?.error || t('notifications.settings.saveError', 'Failed to save notification settings')\n throw new Error(message)\n }\n if (response.result?.settings) {\n setSettings(response.result.settings)\n }\n flash(t('notifications.settings.saveSuccess', 'Notification settings saved'), 'success')\n } catch (err) {\n const message = err instanceof Error ? err.message : t('notifications.settings.saveError', 'Failed to save notification settings')\n flash(message, 'error')\n } finally {\n setSaving(false)\n }\n }\n\n if (loading || !settings) {\n return (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Spinner size=\"sm\" />\n {t('notifications.settings.loading', 'Loading notification settings...')}\n </div>\n )\n }\n\n return (\n <div className=\"flex flex-col gap-6\">\n <div>\n <h1 className=\"text-2xl font-semibold\">{t('notifications.settings.pageTitle', 'Notification Delivery')}</h1>\n <p className=\"text-muted-foreground text-sm\">\n {t('notifications.settings.pageDescription', 'Configure delivery strategies for in-app notifications.')}\n </p>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>{t('notifications.settings.core.title', 'Core delivery')}</CardTitle>\n <CardDescription>{t('notifications.settings.core.description', 'Control the default notification center and panel link used by external channels.')}</CardDescription>\n </CardHeader>\n <CardContent className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"notifications-app-url\">{t('notifications.settings.core.appUrl', 'Application URL')}</Label>\n <Input\n id=\"notifications-app-url\"\n value={settings.appUrl ?? ''}\n placeholder=\"https://app.open-mercato.com\"\n onChange={(event) => updateSettings({ appUrl: event.target.value || undefined })}\n />\n <p className=\"text-xs text-muted-foreground\">{t('notifications.settings.core.appUrlHint', 'Used to build absolute links in email notifications.')}</p>\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"notifications-panel-path\">{t('notifications.settings.core.panelPath', 'Notification panel path')}</Label>\n <Input\n id=\"notifications-panel-path\"\n value={settings.panelPath}\n onChange={(event) => updateSettings({ panelPath: event.target.value })}\n />\n <p className=\"text-xs text-muted-foreground\">{t('notifications.settings.core.panelPathHint', 'Relative path for the read-only notification panel.')}</p>\n </div>\n <div className=\"flex items-center justify-between rounded-lg border p-3\">\n <div>\n <p className=\"text-sm font-medium\">{t('notifications.settings.core.databaseLabel', 'In-app notifications')}</p>\n <p className=\"text-xs text-muted-foreground\">{t('notifications.settings.core.databaseHint', 'Store notifications in the database for the panel and bell.')}</p>\n </div>\n <Switch\n checked={settings.strategies.database.enabled}\n disabled\n onCheckedChange={(checked) => updateStrategy('database', { enabled: checked })}\n />\n </div>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>{t('notifications.settings.email.title', 'Email strategy')}</CardTitle>\n <CardDescription>{t('notifications.settings.email.description', 'Send notification copies via Resend using React templates.')}</CardDescription>\n </CardHeader>\n <CardContent className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"flex items-center justify-between rounded-lg border p-3 md:col-span-2\">\n <div>\n <p className=\"text-sm font-medium\">{t('notifications.settings.email.enabledLabel', 'Enable email delivery')}</p>\n <p className=\"text-xs text-muted-foreground\">{t('notifications.settings.email.enabledHint', 'Email actions are read-only and link back to the notification center.')}</p>\n </div>\n <Switch\n checked={settings.strategies.email.enabled}\n onCheckedChange={(checked) => updateStrategy('email', { enabled: checked })}\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"notifications-email-from\">{t('notifications.settings.email.from', 'From address')}</Label>\n <Input\n id=\"notifications-email-from\"\n value={settings.strategies.email.from ?? ''}\n placeholder=\"notifications@open-mercato.com\"\n onChange={(event) => updateStrategy('email', { from: event.target.value || undefined })}\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"notifications-email-reply\">{t('notifications.settings.email.replyTo', 'Reply-to')}</Label>\n <Input\n id=\"notifications-email-reply\"\n value={settings.strategies.email.replyTo ?? ''}\n placeholder=\"support@open-mercato.com\"\n onChange={(event) => updateStrategy('email', { replyTo: event.target.value || undefined })}\n />\n </div>\n <div className=\"space-y-2 md:col-span-2\">\n <Label htmlFor=\"notifications-email-subject-prefix\">{t('notifications.settings.email.subjectPrefix', 'Subject prefix')}</Label>\n <Input\n id=\"notifications-email-subject-prefix\"\n value={settings.strategies.email.subjectPrefix ?? ''}\n placeholder=\"[Open Mercato]\"\n onChange={(event) => updateStrategy('email', { subjectPrefix: event.target.value || undefined })}\n />\n </div>\n </CardContent>\n </Card>\n\n <div className=\"flex items-center gap-3\">\n <Button type=\"button\" onClick={handleSave} disabled={saving}>\n {saving ? t('notifications.settings.saving', 'Saving...') : t('notifications.settings.save', 'Save settings')}\n </Button>\n {error && <span className=\"text-sm text-destructive\">{error}</span>}\n </div>\n </div>\n )\n}\n\nexport default NotificationSettingsPageClient\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
const metadata = {
|
|
2
|
-
name: "notifications",
|
|
3
|
-
title: "Notifications",
|
|
4
|
-
version: "0.1.0",
|
|
5
|
-
description: "In-app notifications with module-extensible types and actions.",
|
|
6
|
-
author: "Open Mercato Team",
|
|
7
|
-
license: "Proprietary"
|
|
8
|
-
};
|
|
9
|
-
import { features } from "./acl.js";
|
|
10
|
-
export {
|
|
11
|
-
features,
|
|
12
|
-
metadata
|
|
13
|
-
};
|
|
14
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/modules/notifications/index.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ModuleInfo } from '@open-mercato/shared/modules/registry'\n\nexport const metadata: ModuleInfo = {\n name: 'notifications',\n title: 'Notifications',\n version: '0.1.0',\n description: 'In-app notifications with module-extensible types and actions.',\n author: 'Open Mercato Team',\n license: 'Proprietary',\n}\n\nexport { features } from './acl'\n"],
|
|
5
|
-
"mappings": "AAEO,MAAM,WAAuB;AAAA,EAClC,MAAM;AAAA,EACN,OAAO;AAAA,EACP,SAAS;AAAA,EACT,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,SAAS;AACX;AAEA,SAAS,gBAAgB;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { parseBooleanWithDefault } from "@open-mercato/shared/lib/boolean";
|
|
2
|
-
import { notificationDeliveryConfigSchema } from "../data/validators.js";
|
|
3
|
-
const NOTIFICATIONS_DELIVERY_CONFIG_KEY = "delivery_strategies";
|
|
4
|
-
const envString = (value) => {
|
|
5
|
-
if (!value) return void 0;
|
|
6
|
-
const trimmed = value.trim();
|
|
7
|
-
return trimmed.length ? trimmed : void 0;
|
|
8
|
-
};
|
|
9
|
-
const resolveEnvDefaults = () => {
|
|
10
|
-
const appUrl = envString(
|
|
11
|
-
process.env.NOTIFICATIONS_APP_URL || process.env.APPLICATION_URL || process.env.NEXT_PUBLIC_APP_URL || process.env.APP_URL
|
|
12
|
-
);
|
|
13
|
-
const panelPath = envString(process.env.NOTIFICATIONS_PANEL_PATH);
|
|
14
|
-
const emailEnabled = parseBooleanWithDefault(process.env.NOTIFICATIONS_EMAIL_ENABLED, true);
|
|
15
|
-
const emailFrom = envString(process.env.NOTIFICATIONS_EMAIL_FROM || process.env.EMAIL_FROM);
|
|
16
|
-
const emailReplyTo = envString(process.env.NOTIFICATIONS_EMAIL_REPLY_TO || process.env.ADMIN_EMAIL);
|
|
17
|
-
const emailSubjectPrefix = envString(process.env.NOTIFICATIONS_EMAIL_SUBJECT_PREFIX);
|
|
18
|
-
return {
|
|
19
|
-
appUrl,
|
|
20
|
-
panelPath,
|
|
21
|
-
emailEnabled,
|
|
22
|
-
emailFrom,
|
|
23
|
-
emailReplyTo,
|
|
24
|
-
emailSubjectPrefix
|
|
25
|
-
};
|
|
26
|
-
};
|
|
27
|
-
const DEFAULT_NOTIFICATION_DELIVERY_CONFIG = (() => {
|
|
28
|
-
const env = resolveEnvDefaults();
|
|
29
|
-
return {
|
|
30
|
-
appUrl: env.appUrl,
|
|
31
|
-
panelPath: env.panelPath ?? "/backend/notifications",
|
|
32
|
-
strategies: {
|
|
33
|
-
database: { enabled: true },
|
|
34
|
-
email: {
|
|
35
|
-
enabled: env.emailEnabled,
|
|
36
|
-
from: env.emailFrom,
|
|
37
|
-
replyTo: env.emailReplyTo,
|
|
38
|
-
subjectPrefix: env.emailSubjectPrefix
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
})();
|
|
43
|
-
const normalizeDeliveryConfig = (input) => {
|
|
44
|
-
const parsed = notificationDeliveryConfigSchema.safeParse(input ?? {});
|
|
45
|
-
if (!parsed.success) {
|
|
46
|
-
return { ...DEFAULT_NOTIFICATION_DELIVERY_CONFIG };
|
|
47
|
-
}
|
|
48
|
-
const value = parsed.data ?? {};
|
|
49
|
-
const strategies = value.strategies ?? {};
|
|
50
|
-
return {
|
|
51
|
-
appUrl: value.appUrl,
|
|
52
|
-
panelPath: value.panelPath ?? DEFAULT_NOTIFICATION_DELIVERY_CONFIG.panelPath,
|
|
53
|
-
strategies: {
|
|
54
|
-
database: {
|
|
55
|
-
enabled: DEFAULT_NOTIFICATION_DELIVERY_CONFIG.strategies.database.enabled
|
|
56
|
-
},
|
|
57
|
-
email: {
|
|
58
|
-
enabled: strategies.email?.enabled ?? DEFAULT_NOTIFICATION_DELIVERY_CONFIG.strategies.email.enabled,
|
|
59
|
-
from: strategies.email?.from,
|
|
60
|
-
replyTo: strategies.email?.replyTo,
|
|
61
|
-
subjectPrefix: strategies.email?.subjectPrefix
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
};
|
|
66
|
-
async function resolveNotificationDeliveryConfig(resolver, options) {
|
|
67
|
-
const fallback = options?.defaultValue ?? DEFAULT_NOTIFICATION_DELIVERY_CONFIG;
|
|
68
|
-
let service;
|
|
69
|
-
try {
|
|
70
|
-
service = resolver.resolve("moduleConfigService");
|
|
71
|
-
} catch {
|
|
72
|
-
return { ...fallback };
|
|
73
|
-
}
|
|
74
|
-
try {
|
|
75
|
-
const value = await service.getValue("notifications", NOTIFICATIONS_DELIVERY_CONFIG_KEY, { defaultValue: fallback });
|
|
76
|
-
return normalizeDeliveryConfig(value);
|
|
77
|
-
} catch {
|
|
78
|
-
return { ...fallback };
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
async function saveNotificationDeliveryConfig(resolver, config) {
|
|
82
|
-
let service;
|
|
83
|
-
try {
|
|
84
|
-
service = resolver.resolve("moduleConfigService");
|
|
85
|
-
} catch {
|
|
86
|
-
throw new Error("Configuration service unavailable");
|
|
87
|
-
}
|
|
88
|
-
const normalized = normalizeDeliveryConfig(config);
|
|
89
|
-
await service.setValue("notifications", NOTIFICATIONS_DELIVERY_CONFIG_KEY, normalized);
|
|
90
|
-
}
|
|
91
|
-
function resolveNotificationPanelUrl(config) {
|
|
92
|
-
const base = config.appUrl || process.env.APPLICATION_URL || process.env.NEXT_PUBLIC_APP_URL || process.env.APP_URL;
|
|
93
|
-
if (!base || !base.trim()) {
|
|
94
|
-
return config.panelPath;
|
|
95
|
-
}
|
|
96
|
-
return `${base.replace(/\/$/, "")}${config.panelPath}`;
|
|
97
|
-
}
|
|
98
|
-
export {
|
|
99
|
-
DEFAULT_NOTIFICATION_DELIVERY_CONFIG,
|
|
100
|
-
NOTIFICATIONS_DELIVERY_CONFIG_KEY,
|
|
101
|
-
resolveNotificationDeliveryConfig,
|
|
102
|
-
resolveNotificationPanelUrl,
|
|
103
|
-
saveNotificationDeliveryConfig
|
|
104
|
-
};
|
|
105
|
-
//# sourceMappingURL=deliveryConfig.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../src/modules/notifications/lib/deliveryConfig.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ModuleConfigService } from '@open-mercato/core/modules/configs/lib/module-config-service'\nimport { parseBooleanWithDefault } from '@open-mercato/shared/lib/boolean'\nimport { notificationDeliveryConfigSchema, type NotificationDeliveryConfigInput } from '../data/validators'\n\nexport const NOTIFICATIONS_DELIVERY_CONFIG_KEY = 'delivery_strategies'\n\nexport type NotificationDeliveryStrategyState = {\n enabled: boolean\n}\n\nexport type NotificationEmailDeliveryConfig = NotificationDeliveryStrategyState & {\n from?: string\n replyTo?: string\n subjectPrefix?: string\n}\n\nexport type NotificationDeliveryConfig = {\n appUrl?: string\n panelPath: string\n strategies: {\n database: NotificationDeliveryStrategyState\n email: NotificationEmailDeliveryConfig\n }\n}\n\nconst envString = (value: string | undefined | null) => {\n if (!value) return undefined\n const trimmed = value.trim()\n return trimmed.length ? trimmed : undefined\n}\n\nconst resolveEnvDefaults = () => {\n const appUrl = envString(\n process.env.NOTIFICATIONS_APP_URL ||\n process.env.APPLICATION_URL ||\n process.env.NEXT_PUBLIC_APP_URL ||\n process.env.APP_URL\n )\n const panelPath = envString(process.env.NOTIFICATIONS_PANEL_PATH)\n const emailEnabled = parseBooleanWithDefault(process.env.NOTIFICATIONS_EMAIL_ENABLED, true)\n const emailFrom = envString(process.env.NOTIFICATIONS_EMAIL_FROM || process.env.EMAIL_FROM)\n const emailReplyTo = envString(process.env.NOTIFICATIONS_EMAIL_REPLY_TO || process.env.ADMIN_EMAIL)\n const emailSubjectPrefix = envString(process.env.NOTIFICATIONS_EMAIL_SUBJECT_PREFIX)\n\n return {\n appUrl,\n panelPath,\n emailEnabled,\n emailFrom,\n emailReplyTo,\n emailSubjectPrefix,\n }\n}\n\nexport const DEFAULT_NOTIFICATION_DELIVERY_CONFIG: NotificationDeliveryConfig = (() => {\n const env = resolveEnvDefaults()\n return {\n appUrl: env.appUrl,\n panelPath: env.panelPath ?? '/backend/notifications',\n strategies: {\n database: { enabled: true },\n email: {\n enabled: env.emailEnabled,\n from: env.emailFrom,\n replyTo: env.emailReplyTo,\n subjectPrefix: env.emailSubjectPrefix,\n },\n },\n }\n})()\n\nconst normalizeDeliveryConfig = (input?: unknown | null): NotificationDeliveryConfig => {\n const parsed = notificationDeliveryConfigSchema.safeParse(input ?? {})\n if (!parsed.success) {\n return { ...DEFAULT_NOTIFICATION_DELIVERY_CONFIG }\n }\n\n const value = parsed.data ?? {}\n const strategies = value.strategies ?? {}\n\n return {\n appUrl: value.appUrl,\n panelPath: value.panelPath ?? DEFAULT_NOTIFICATION_DELIVERY_CONFIG.panelPath,\n strategies: {\n database: {\n enabled: DEFAULT_NOTIFICATION_DELIVERY_CONFIG.strategies.database.enabled,\n },\n email: {\n enabled: strategies.email?.enabled ?? DEFAULT_NOTIFICATION_DELIVERY_CONFIG.strategies.email.enabled,\n from: strategies.email?.from,\n replyTo: strategies.email?.replyTo,\n subjectPrefix: strategies.email?.subjectPrefix,\n },\n },\n }\n}\n\ntype Resolver = {\n resolve: <T = unknown>(name: string) => T\n}\n\nexport async function resolveNotificationDeliveryConfig(\n resolver: Resolver,\n options?: { defaultValue?: NotificationDeliveryConfig }\n): Promise<NotificationDeliveryConfig> {\n const fallback = options?.defaultValue ?? DEFAULT_NOTIFICATION_DELIVERY_CONFIG\n let service: ModuleConfigService\n try {\n service = resolver.resolve<ModuleConfigService>('moduleConfigService')\n } catch {\n return { ...fallback }\n }\n try {\n const value = await service.getValue('notifications', NOTIFICATIONS_DELIVERY_CONFIG_KEY, { defaultValue: fallback })\n return normalizeDeliveryConfig(value)\n } catch {\n return { ...fallback }\n }\n}\n\nexport async function saveNotificationDeliveryConfig(\n resolver: Resolver,\n config: NotificationDeliveryConfigInput\n): Promise<void> {\n let service: ModuleConfigService\n try {\n service = resolver.resolve<ModuleConfigService>('moduleConfigService')\n } catch {\n throw new Error('Configuration service unavailable')\n }\n\n const normalized = normalizeDeliveryConfig(config)\n await service.setValue('notifications', NOTIFICATIONS_DELIVERY_CONFIG_KEY, normalized)\n}\n\nexport function resolveNotificationPanelUrl(config: NotificationDeliveryConfig): string | null {\n const base = config.appUrl\n || process.env.APPLICATION_URL\n || process.env.NEXT_PUBLIC_APP_URL\n || process.env.APP_URL\n if (!base || !base.trim()) {\n return config.panelPath\n }\n return `${base.replace(/\\/$/, '')}${config.panelPath}`\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
const NOTIFICATION_EVENTS = {
|
|
2
|
-
CREATED: "notifications.created",
|
|
3
|
-
READ: "notifications.read",
|
|
4
|
-
ACTIONED: "notifications.actioned",
|
|
5
|
-
DISMISSED: "notifications.dismissed",
|
|
6
|
-
RESTORED: "notifications.restored",
|
|
7
|
-
EXPIRED: "notifications.expired"
|
|
8
|
-
};
|
|
9
|
-
export {
|
|
10
|
-
NOTIFICATION_EVENTS
|
|
11
|
-
};
|
|
12
|
-
//# sourceMappingURL=events.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../src/modules/notifications/lib/events.ts"],
|
|
4
|
-
"sourcesContent": ["export const NOTIFICATION_EVENTS = {\n CREATED: 'notifications.created',\n READ: 'notifications.read',\n ACTIONED: 'notifications.actioned',\n DISMISSED: 'notifications.dismissed',\n RESTORED: 'notifications.restored',\n EXPIRED: 'notifications.expired',\n} as const\n\nexport type NotificationCreatedPayload = {\n notificationId: string\n recipientUserId: string\n type: string\n title: string\n tenantId: string\n organizationId?: string | null\n}\n\nexport type NotificationReadPayload = {\n notificationId: string\n userId: string\n tenantId: string\n}\n\nexport type NotificationActionedPayload = {\n notificationId: string\n actionId: string\n userId: string\n tenantId: string\n}\n\nexport type NotificationDismissedPayload = {\n notificationId: string\n userId: string\n tenantId: string\n}\n\nexport type NotificationRestoredPayload = {\n notificationId: string\n userId: string\n tenantId: string\n status: 'read' | 'unread'\n}\n\nexport type NotificationExpiredPayload = {\n notificationIds: string[]\n tenantId: string\n}\n"],
|
|
5
|
-
"mappings": "AAAO,MAAM,sBAAsB;AAAA,EACjC,SAAS;AAAA,EACT,MAAM;AAAA,EACN,UAAU;AAAA,EACV,WAAW;AAAA,EACX,UAAU;AAAA,EACV,SAAS;AACX;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
function mapActions(actions) {
|
|
2
|
-
if (!actions || actions.length === 0) return void 0;
|
|
3
|
-
return actions.map((action) => ({
|
|
4
|
-
id: action.id,
|
|
5
|
-
label: action.labelKey,
|
|
6
|
-
labelKey: action.labelKey,
|
|
7
|
-
variant: action.variant,
|
|
8
|
-
icon: action.icon,
|
|
9
|
-
commandId: action.commandId,
|
|
10
|
-
href: action.href,
|
|
11
|
-
confirmRequired: action.confirmRequired,
|
|
12
|
-
confirmMessage: action.confirmMessageKey
|
|
13
|
-
}));
|
|
14
|
-
}
|
|
15
|
-
function buildBaseNotificationFields(typeDef, options) {
|
|
16
|
-
return {
|
|
17
|
-
type: typeDef.type,
|
|
18
|
-
titleKey: typeDef.titleKey,
|
|
19
|
-
bodyKey: typeDef.bodyKey,
|
|
20
|
-
titleVariables: options.titleVariables,
|
|
21
|
-
bodyVariables: options.bodyVariables,
|
|
22
|
-
title: typeDef.titleKey,
|
|
23
|
-
body: typeDef.bodyKey,
|
|
24
|
-
icon: typeDef.icon,
|
|
25
|
-
severity: typeDef.severity,
|
|
26
|
-
actions: mapActions(typeDef.actions),
|
|
27
|
-
primaryActionId: typeDef.primaryActionId,
|
|
28
|
-
sourceModule: typeDef.module,
|
|
29
|
-
sourceEntityType: options.sourceEntityType,
|
|
30
|
-
sourceEntityId: options.sourceEntityId,
|
|
31
|
-
linkHref: options.linkHref ?? typeDef.linkHref,
|
|
32
|
-
groupKey: options.groupKey,
|
|
33
|
-
expiresAt: options.expiresAt ?? (typeDef.expiresAfterHours ? new Date(Date.now() + typeDef.expiresAfterHours * 60 * 60 * 1e3).toISOString() : void 0)
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
function buildNotificationFromType(typeDef, options) {
|
|
37
|
-
return {
|
|
38
|
-
recipientUserId: options.recipientUserId,
|
|
39
|
-
...buildBaseNotificationFields(typeDef, options)
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
function buildBatchNotificationFromType(typeDef, options) {
|
|
43
|
-
return {
|
|
44
|
-
recipientUserIds: options.recipientUserIds,
|
|
45
|
-
...buildBaseNotificationFields(typeDef, options)
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
function buildRoleNotificationFromType(typeDef, options) {
|
|
49
|
-
return {
|
|
50
|
-
roleId: options.roleId,
|
|
51
|
-
...buildBaseNotificationFields(typeDef, options)
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
function buildFeatureNotificationFromType(typeDef, options) {
|
|
55
|
-
return {
|
|
56
|
-
requiredFeature: options.requiredFeature,
|
|
57
|
-
...buildBaseNotificationFields(typeDef, options)
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
export {
|
|
61
|
-
buildBatchNotificationFromType,
|
|
62
|
-
buildFeatureNotificationFromType,
|
|
63
|
-
buildNotificationFromType,
|
|
64
|
-
buildRoleNotificationFromType
|
|
65
|
-
};
|
|
66
|
-
//# sourceMappingURL=notificationBuilder.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../src/modules/notifications/lib/notificationBuilder.ts"],
|
|
4
|
-
"sourcesContent": ["import type { NotificationTypeDefinition, NotificationTypeAction } from '@open-mercato/shared/modules/notifications/types'\nimport type { CreateNotificationInput, CreateBatchNotificationInput, CreateRoleNotificationInput, CreateFeatureNotificationInput } from '../data/validators'\n\n/**\n * Transform type definition actions to API input actions.\n * Type definitions use labelKey (i18n-first), while API input uses label with optional labelKey.\n */\nfunction mapActions(actions: NotificationTypeAction[] | undefined) {\n if (!actions || actions.length === 0) return undefined\n return actions.map((action) => ({\n id: action.id,\n label: action.labelKey,\n labelKey: action.labelKey,\n variant: action.variant,\n icon: action.icon,\n commandId: action.commandId,\n href: action.href,\n confirmRequired: action.confirmRequired,\n confirmMessage: action.confirmMessageKey,\n }))\n}\n\n/**\n * Common options for building notifications from type definitions\n */\ninterface CommonBuildOptions {\n titleVariables?: Record<string, string>\n bodyVariables?: Record<string, string>\n sourceEntityType?: string\n sourceEntityId?: string\n linkHref?: string\n groupKey?: string\n expiresAt?: string\n}\n\n/**\n * Build base notification fields from a type definition.\n * Shared logic used by all notification builder functions.\n */\nfunction buildBaseNotificationFields(\n typeDef: NotificationTypeDefinition,\n options: CommonBuildOptions\n) {\n return {\n type: typeDef.type,\n titleKey: typeDef.titleKey,\n bodyKey: typeDef.bodyKey,\n titleVariables: options.titleVariables,\n bodyVariables: options.bodyVariables,\n title: typeDef.titleKey,\n body: typeDef.bodyKey,\n icon: typeDef.icon,\n severity: typeDef.severity,\n actions: mapActions(typeDef.actions),\n primaryActionId: typeDef.primaryActionId,\n sourceModule: typeDef.module,\n sourceEntityType: options.sourceEntityType,\n sourceEntityId: options.sourceEntityId,\n linkHref: options.linkHref ?? typeDef.linkHref,\n groupKey: options.groupKey,\n expiresAt: options.expiresAt ?? (\n typeDef.expiresAfterHours\n ? new Date(Date.now() + typeDef.expiresAfterHours * 60 * 60 * 1000).toISOString()\n : undefined\n ),\n }\n}\n\n/**\n * Build a notification input from a type definition with i18n support.\n * This is the recommended way to create notifications - use type definitions from notifications.ts\n * to ensure i18n-first approach.\n */\nexport function buildNotificationFromType(\n typeDef: NotificationTypeDefinition,\n options: CommonBuildOptions & { recipientUserId: string }\n): CreateNotificationInput {\n return {\n recipientUserId: options.recipientUserId,\n ...buildBaseNotificationFields(typeDef, options),\n }\n}\n\n/**\n * Build a batch notification input from a type definition\n */\nexport function buildBatchNotificationFromType(\n typeDef: NotificationTypeDefinition,\n options: CommonBuildOptions & { recipientUserIds: string[] }\n): CreateBatchNotificationInput {\n return {\n recipientUserIds: options.recipientUserIds,\n ...buildBaseNotificationFields(typeDef, options),\n }\n}\n\n/**\n * Build a role notification input from a type definition\n */\nexport function buildRoleNotificationFromType(\n typeDef: NotificationTypeDefinition,\n options: CommonBuildOptions & { roleId: string }\n): CreateRoleNotificationInput {\n return {\n roleId: options.roleId,\n ...buildBaseNotificationFields(typeDef, options),\n }\n}\n\n/**\n * Build a feature-based notification input from a type definition\n */\nexport function buildFeatureNotificationFromType(\n typeDef: NotificationTypeDefinition,\n options: CommonBuildOptions & { requiredFeature: string }\n): CreateFeatureNotificationInput {\n return {\n requiredFeature: options.requiredFeature,\n ...buildBaseNotificationFields(typeDef, options),\n }\n}\n"],
|
|
5
|
-
"mappings": "AAOA,SAAS,WAAW,SAA+C;AACjE,MAAI,CAAC,WAAW,QAAQ,WAAW,EAAG,QAAO;AAC7C,SAAO,QAAQ,IAAI,CAAC,YAAY;AAAA,IAC9B,IAAI,OAAO;AAAA,IACX,OAAO,OAAO;AAAA,IACd,UAAU,OAAO;AAAA,IACjB,SAAS,OAAO;AAAA,IAChB,MAAM,OAAO;AAAA,IACb,WAAW,OAAO;AAAA,IAClB,MAAM,OAAO;AAAA,IACb,iBAAiB,OAAO;AAAA,IACxB,gBAAgB,OAAO;AAAA,EACzB,EAAE;AACJ;AAmBA,SAAS,4BACP,SACA,SACA;AACA,SAAO;AAAA,IACL,MAAM,QAAQ;AAAA,IACd,UAAU,QAAQ;AAAA,IAClB,SAAS,QAAQ;AAAA,IACjB,gBAAgB,QAAQ;AAAA,IACxB,eAAe,QAAQ;AAAA,IACvB,OAAO,QAAQ;AAAA,IACf,MAAM,QAAQ;AAAA,IACd,MAAM,QAAQ;AAAA,IACd,UAAU,QAAQ;AAAA,IAClB,SAAS,WAAW,QAAQ,OAAO;AAAA,IACnC,iBAAiB,QAAQ;AAAA,IACzB,cAAc,QAAQ;AAAA,IACtB,kBAAkB,QAAQ;AAAA,IAC1B,gBAAgB,QAAQ;AAAA,IACxB,UAAU,QAAQ,YAAY,QAAQ;AAAA,IACtC,UAAU,QAAQ;AAAA,IAClB,WAAW,QAAQ,cACjB,QAAQ,oBACJ,IAAI,KAAK,KAAK,IAAI,IAAI,QAAQ,oBAAoB,KAAK,KAAK,GAAI,EAAE,YAAY,IAC9E;AAAA,EAER;AACF;AAOO,SAAS,0BACd,SACA,SACyB;AACzB,SAAO;AAAA,IACL,iBAAiB,QAAQ;AAAA,IACzB,GAAG,4BAA4B,SAAS,OAAO;AAAA,EACjD;AACF;AAKO,SAAS,+BACd,SACA,SAC8B;AAC9B,SAAO;AAAA,IACL,kBAAkB,QAAQ;AAAA,IAC1B,GAAG,4BAA4B,SAAS,OAAO;AAAA,EACjD;AACF;AAKO,SAAS,8BACd,SACA,SAC6B;AAC7B,SAAO;AAAA,IACL,QAAQ,QAAQ;AAAA,IAChB,GAAG,4BAA4B,SAAS,OAAO;AAAA,EACjD;AACF;AAKO,SAAS,iCACd,SACA,SACgC;AAChC,SAAO;AAAA,IACL,iBAAiB,QAAQ;AAAA,IACzB,GAAG,4BAA4B,SAAS,OAAO;AAAA,EACjD;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { Notification } from "../data/entities.js";
|
|
2
|
-
import { NOTIFICATION_EVENTS } from "./events.js";
|
|
3
|
-
import { assertSafeNotificationHref, sanitizeNotificationActions } from "./safeHref.js";
|
|
4
|
-
function buildNotificationEntity(em, input, recipientUserId, ctx) {
|
|
5
|
-
const actions = sanitizeNotificationActions(input.actions);
|
|
6
|
-
const linkHref = assertSafeNotificationHref(input.linkHref);
|
|
7
|
-
return em.create(Notification, {
|
|
8
|
-
recipientUserId,
|
|
9
|
-
type: input.type,
|
|
10
|
-
// i18n-first: store keys and variables for translation at display time
|
|
11
|
-
titleKey: input.titleKey,
|
|
12
|
-
bodyKey: input.bodyKey,
|
|
13
|
-
titleVariables: input.titleVariables,
|
|
14
|
-
bodyVariables: input.bodyVariables,
|
|
15
|
-
// Fallback text (required for backward compatibility)
|
|
16
|
-
title: input.title || input.titleKey || "",
|
|
17
|
-
body: input.body,
|
|
18
|
-
icon: input.icon,
|
|
19
|
-
severity: input.severity ?? "info",
|
|
20
|
-
actionData: actions ? {
|
|
21
|
-
actions,
|
|
22
|
-
primaryActionId: input.primaryActionId
|
|
23
|
-
} : null,
|
|
24
|
-
sourceModule: input.sourceModule,
|
|
25
|
-
sourceEntityType: input.sourceEntityType,
|
|
26
|
-
sourceEntityId: input.sourceEntityId,
|
|
27
|
-
linkHref,
|
|
28
|
-
groupKey: input.groupKey,
|
|
29
|
-
expiresAt: input.expiresAt ? new Date(input.expiresAt) : null,
|
|
30
|
-
tenantId: ctx.tenantId,
|
|
31
|
-
organizationId: ctx.organizationId
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
async function emitNotificationCreated(eventBus, notification, ctx) {
|
|
35
|
-
await eventBus.emit(NOTIFICATION_EVENTS.CREATED, {
|
|
36
|
-
notificationId: notification.id,
|
|
37
|
-
recipientUserId: notification.recipientUserId,
|
|
38
|
-
type: notification.type,
|
|
39
|
-
title: notification.title,
|
|
40
|
-
tenantId: ctx.tenantId,
|
|
41
|
-
organizationId: ctx.organizationId
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
async function emitNotificationCreatedBatch(eventBus, notifications, ctx) {
|
|
45
|
-
for (const notification of notifications) {
|
|
46
|
-
await emitNotificationCreated(eventBus, notification, ctx);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
export {
|
|
50
|
-
buildNotificationEntity,
|
|
51
|
-
emitNotificationCreated,
|
|
52
|
-
emitNotificationCreatedBatch
|
|
53
|
-
};
|
|
54
|
-
//# sourceMappingURL=notificationFactory.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../src/modules/notifications/lib/notificationFactory.ts"],
|
|
4
|
-
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/core'\nimport { Notification } from '../data/entities'\nimport type { CreateNotificationInput } from '../data/validators'\nimport { NOTIFICATION_EVENTS } from './events'\nimport { assertSafeNotificationHref, sanitizeNotificationActions } from './safeHref'\n\nexport type NotificationContentInput = Omit<CreateNotificationInput, 'recipientUserId'>\n\nexport type NotificationTenantContext = {\n tenantId: string\n organizationId?: string | null\n}\n\nexport function buildNotificationEntity(\n em: EntityManager,\n input: NotificationContentInput,\n recipientUserId: string,\n ctx: NotificationTenantContext\n): Notification {\n const actions = sanitizeNotificationActions(input.actions)\n const linkHref = assertSafeNotificationHref(input.linkHref)\n\n return em.create(Notification, {\n recipientUserId,\n type: input.type,\n // i18n-first: store keys and variables for translation at display time\n titleKey: input.titleKey,\n bodyKey: input.bodyKey,\n titleVariables: input.titleVariables,\n bodyVariables: input.bodyVariables,\n // Fallback text (required for backward compatibility)\n title: input.title || input.titleKey || '',\n body: input.body,\n icon: input.icon,\n severity: input.severity ?? 'info',\n actionData: actions\n ? {\n actions,\n primaryActionId: input.primaryActionId,\n }\n : null,\n sourceModule: input.sourceModule,\n sourceEntityType: input.sourceEntityType,\n sourceEntityId: input.sourceEntityId,\n linkHref,\n groupKey: input.groupKey,\n expiresAt: input.expiresAt ? new Date(input.expiresAt) : null,\n tenantId: ctx.tenantId,\n organizationId: ctx.organizationId,\n })\n}\n\nexport async function emitNotificationCreated(\n eventBus: { emit: (event: string, payload: unknown) => Promise<void> },\n notification: Notification,\n ctx: NotificationTenantContext\n): Promise<void> {\n await eventBus.emit(NOTIFICATION_EVENTS.CREATED, {\n notificationId: notification.id,\n recipientUserId: notification.recipientUserId,\n type: notification.type,\n title: notification.title,\n tenantId: ctx.tenantId,\n organizationId: ctx.organizationId,\n })\n}\n\nexport async function emitNotificationCreatedBatch(\n eventBus: { emit: (event: string, payload: unknown) => Promise<void> },\n notifications: Notification[],\n ctx: NotificationTenantContext\n): Promise<void> {\n for (const notification of notifications) {\n await emitNotificationCreated(eventBus, notification, ctx)\n }\n}\n"],
|
|
5
|
-
"mappings": "AACA,SAAS,oBAAoB;AAE7B,SAAS,2BAA2B;AACpC,SAAS,4BAA4B,mCAAmC;AASjE,SAAS,wBACd,IACA,OACA,iBACA,KACc;AACd,QAAM,UAAU,4BAA4B,MAAM,OAAO;AACzD,QAAM,WAAW,2BAA2B,MAAM,QAAQ;AAE1D,SAAO,GAAG,OAAO,cAAc;AAAA,IAC7B;AAAA,IACA,MAAM,MAAM;AAAA;AAAA,IAEZ,UAAU,MAAM;AAAA,IAChB,SAAS,MAAM;AAAA,IACf,gBAAgB,MAAM;AAAA,IACtB,eAAe,MAAM;AAAA;AAAA,IAErB,OAAO,MAAM,SAAS,MAAM,YAAY;AAAA,IACxC,MAAM,MAAM;AAAA,IACZ,MAAM,MAAM;AAAA,IACZ,UAAU,MAAM,YAAY;AAAA,IAC5B,YAAY,UACR;AAAA,MACE;AAAA,MACA,iBAAiB,MAAM;AAAA,IACzB,IACA;AAAA,IACJ,cAAc,MAAM;AAAA,IACpB,kBAAkB,MAAM;AAAA,IACxB,gBAAgB,MAAM;AAAA,IACtB;AAAA,IACA,UAAU,MAAM;AAAA,IAChB,WAAW,MAAM,YAAY,IAAI,KAAK,MAAM,SAAS,IAAI;AAAA,IACzD,UAAU,IAAI;AAAA,IACd,gBAAgB,IAAI;AAAA,EACtB,CAAC;AACH;AAEA,eAAsB,wBACpB,UACA,cACA,KACe;AACf,QAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IAC/C,gBAAgB,aAAa;AAAA,IAC7B,iBAAiB,aAAa;AAAA,IAC9B,MAAM,aAAa;AAAA,IACnB,OAAO,aAAa;AAAA,IACpB,UAAU,IAAI;AAAA,IACd,gBAAgB,IAAI;AAAA,EACtB,CAAC;AACH;AAEA,eAAsB,6BACpB,UACA,eACA,KACe;AACf,aAAW,gBAAgB,eAAe;AACxC,UAAM,wBAAwB,UAAU,cAAc,GAAG;AAAA,EAC3D;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
function toNotificationDto(notification) {
|
|
2
|
-
return {
|
|
3
|
-
id: notification.id,
|
|
4
|
-
type: notification.type,
|
|
5
|
-
title: notification.title,
|
|
6
|
-
body: notification.body,
|
|
7
|
-
titleKey: notification.titleKey,
|
|
8
|
-
bodyKey: notification.bodyKey,
|
|
9
|
-
titleVariables: notification.titleVariables,
|
|
10
|
-
bodyVariables: notification.bodyVariables,
|
|
11
|
-
icon: notification.icon,
|
|
12
|
-
severity: notification.severity,
|
|
13
|
-
status: notification.status,
|
|
14
|
-
actions: notification.actionData?.actions?.map((action) => ({
|
|
15
|
-
id: action.id,
|
|
16
|
-
label: action.label,
|
|
17
|
-
labelKey: action.labelKey,
|
|
18
|
-
variant: action.variant,
|
|
19
|
-
icon: action.icon
|
|
20
|
-
})) ?? [],
|
|
21
|
-
primaryActionId: notification.actionData?.primaryActionId,
|
|
22
|
-
sourceModule: notification.sourceModule,
|
|
23
|
-
sourceEntityType: notification.sourceEntityType,
|
|
24
|
-
sourceEntityId: notification.sourceEntityId,
|
|
25
|
-
linkHref: notification.linkHref,
|
|
26
|
-
createdAt: notification.createdAt.toISOString(),
|
|
27
|
-
readAt: notification.readAt?.toISOString() ?? null,
|
|
28
|
-
actionTaken: notification.actionTaken
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
export {
|
|
32
|
-
toNotificationDto
|
|
33
|
-
};
|
|
34
|
-
//# sourceMappingURL=notificationMapper.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../src/modules/notifications/lib/notificationMapper.ts"],
|
|
4
|
-
"sourcesContent": ["import type { NotificationDto } from '@open-mercato/shared/modules/notifications/types'\nimport { Notification } from '../data/entities'\n\nexport function toNotificationDto(notification: Notification): NotificationDto {\n return {\n id: notification.id,\n type: notification.type,\n title: notification.title,\n body: notification.body,\n titleKey: notification.titleKey,\n bodyKey: notification.bodyKey,\n titleVariables: notification.titleVariables,\n bodyVariables: notification.bodyVariables,\n icon: notification.icon,\n severity: notification.severity,\n status: notification.status,\n actions: notification.actionData?.actions?.map((action) => ({\n id: action.id,\n label: action.label,\n labelKey: action.labelKey,\n variant: action.variant,\n icon: action.icon,\n })) ?? [],\n primaryActionId: notification.actionData?.primaryActionId,\n sourceModule: notification.sourceModule,\n sourceEntityType: notification.sourceEntityType,\n sourceEntityId: notification.sourceEntityId,\n linkHref: notification.linkHref,\n createdAt: notification.createdAt.toISOString(),\n readAt: notification.readAt?.toISOString() ?? null,\n actionTaken: notification.actionTaken,\n }\n}\n"],
|
|
5
|
-
"mappings": "AAGO,SAAS,kBAAkB,cAA6C;AAC7E,SAAO;AAAA,IACL,IAAI,aAAa;AAAA,IACjB,MAAM,aAAa;AAAA,IACnB,OAAO,aAAa;AAAA,IACpB,MAAM,aAAa;AAAA,IACnB,UAAU,aAAa;AAAA,IACvB,SAAS,aAAa;AAAA,IACtB,gBAAgB,aAAa;AAAA,IAC7B,eAAe,aAAa;AAAA,IAC5B,MAAM,aAAa;AAAA,IACnB,UAAU,aAAa;AAAA,IACvB,QAAQ,aAAa;AAAA,IACrB,SAAS,aAAa,YAAY,SAAS,IAAI,CAAC,YAAY;AAAA,MAC1D,IAAI,OAAO;AAAA,MACX,OAAO,OAAO;AAAA,MACd,UAAU,OAAO;AAAA,MACjB,SAAS,OAAO;AAAA,MAChB,MAAM,OAAO;AAAA,IACf,EAAE,KAAK,CAAC;AAAA,IACR,iBAAiB,aAAa,YAAY;AAAA,IAC1C,cAAc,aAAa;AAAA,IAC3B,kBAAkB,aAAa;AAAA,IAC/B,gBAAgB,aAAa;AAAA,IAC7B,UAAU,aAAa;AAAA,IACvB,WAAW,aAAa,UAAU,YAAY;AAAA,IAC9C,QAAQ,aAAa,QAAQ,YAAY,KAAK;AAAA,IAC9C,aAAa,aAAa;AAAA,EAC5B;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { hasFeature } from "@open-mercato/shared/security/features";
|
|
2
|
-
function normalizeFeatures(features) {
|
|
3
|
-
if (!Array.isArray(features)) return void 0;
|
|
4
|
-
const normalized = features.filter((feature) => typeof feature === "string");
|
|
5
|
-
return normalized.length ? normalized : void 0;
|
|
6
|
-
}
|
|
7
|
-
function collectUsersWithFeature(userIdsSet, rows, requiredFeature) {
|
|
8
|
-
for (const row of rows) {
|
|
9
|
-
if (row.is_super_admin) {
|
|
10
|
-
userIdsSet.add(row.user_id);
|
|
11
|
-
continue;
|
|
12
|
-
}
|
|
13
|
-
const features = normalizeFeatures(row.features_json);
|
|
14
|
-
if (features && hasFeature(features, requiredFeature)) {
|
|
15
|
-
userIdsSet.add(row.user_id);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
async function getRecipientUserIdsForRole(knex, tenantId, roleId) {
|
|
20
|
-
const userRoles = await knex("user_roles").join("users", "user_roles.user_id", "users.id").where("user_roles.role_id", roleId).whereNull("user_roles.deleted_at").whereNull("users.deleted_at").where("users.tenant_id", tenantId).select("users.id as user_id");
|
|
21
|
-
return userRoles.map((row) => row.user_id);
|
|
22
|
-
}
|
|
23
|
-
async function getRecipientUserIdsForFeature(knex, tenantId, requiredFeature) {
|
|
24
|
-
const userIdsSet = /* @__PURE__ */ new Set();
|
|
25
|
-
const userAcls = await knex("user_acls").join("users", "user_acls.user_id", "users.id").where("user_acls.tenant_id", tenantId).whereNull("user_acls.deleted_at").whereNull("users.deleted_at").where("users.tenant_id", tenantId).select("users.id as user_id", "user_acls.features_json", "user_acls.is_super_admin");
|
|
26
|
-
collectUsersWithFeature(userIdsSet, userAcls, requiredFeature);
|
|
27
|
-
const roleAcls = await knex("role_acls").join("user_roles", "role_acls.role_id", "user_roles.role_id").join("users", "user_roles.user_id", "users.id").where("role_acls.tenant_id", tenantId).whereNull("role_acls.deleted_at").whereNull("user_roles.deleted_at").whereNull("users.deleted_at").where("users.tenant_id", tenantId).select("users.id as user_id", "role_acls.features_json", "role_acls.is_super_admin");
|
|
28
|
-
collectUsersWithFeature(userIdsSet, roleAcls, requiredFeature);
|
|
29
|
-
return Array.from(userIdsSet);
|
|
30
|
-
}
|
|
31
|
-
export {
|
|
32
|
-
getRecipientUserIdsForFeature,
|
|
33
|
-
getRecipientUserIdsForRole
|
|
34
|
-
};
|
|
35
|
-
//# sourceMappingURL=notificationRecipients.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../src/modules/notifications/lib/notificationRecipients.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Knex } from 'knex'\nimport { hasFeature } from '@open-mercato/shared/security/features'\n\ninterface AclRow {\n user_id: string\n features_json: unknown\n is_super_admin: boolean\n}\n\nfunction normalizeFeatures(features: unknown): string[] | undefined {\n if (!Array.isArray(features)) return undefined\n const normalized = features.filter((feature): feature is string => typeof feature === 'string')\n return normalized.length ? normalized : undefined\n}\n\n/**\n * Extract user IDs from ACL rows that have the required feature or are super admins.\n */\nfunction collectUsersWithFeature(\n userIdsSet: Set<string>,\n rows: AclRow[],\n requiredFeature: string\n): void {\n for (const row of rows) {\n if (row.is_super_admin) {\n userIdsSet.add(row.user_id)\n continue\n }\n\n const features = normalizeFeatures(row.features_json)\n if (features && hasFeature(features, requiredFeature)) {\n userIdsSet.add(row.user_id)\n }\n }\n}\n\nexport async function getRecipientUserIdsForRole(\n knex: Knex,\n tenantId: string,\n roleId: string\n): Promise<string[]> {\n const userRoles = await knex('user_roles')\n .join('users', 'user_roles.user_id', 'users.id')\n .where('user_roles.role_id', roleId)\n .whereNull('user_roles.deleted_at')\n .whereNull('users.deleted_at')\n .where('users.tenant_id', tenantId)\n .select('users.id as user_id')\n\n return userRoles.map((row: { user_id: string }) => row.user_id)\n}\n\nexport async function getRecipientUserIdsForFeature(\n knex: Knex,\n tenantId: string,\n requiredFeature: string\n): Promise<string[]> {\n const userIdsSet = new Set<string>()\n\n const userAcls = await knex('user_acls')\n .join('users', 'user_acls.user_id', 'users.id')\n .where('user_acls.tenant_id', tenantId)\n .whereNull('user_acls.deleted_at')\n .whereNull('users.deleted_at')\n .where('users.tenant_id', tenantId)\n .select('users.id as user_id', 'user_acls.features_json', 'user_acls.is_super_admin')\n\n collectUsersWithFeature(userIdsSet, userAcls, requiredFeature)\n\n const roleAcls = await knex('role_acls')\n .join('user_roles', 'role_acls.role_id', 'user_roles.role_id')\n .join('users', 'user_roles.user_id', 'users.id')\n .where('role_acls.tenant_id', tenantId)\n .whereNull('role_acls.deleted_at')\n .whereNull('user_roles.deleted_at')\n .whereNull('users.deleted_at')\n .where('users.tenant_id', tenantId)\n .select('users.id as user_id', 'role_acls.features_json', 'role_acls.is_super_admin')\n\n collectUsersWithFeature(userIdsSet, roleAcls, requiredFeature)\n\n return Array.from(userIdsSet)\n}\n"],
|
|
5
|
-
"mappings": "AACA,SAAS,kBAAkB;AAQ3B,SAAS,kBAAkB,UAAyC;AAClE,MAAI,CAAC,MAAM,QAAQ,QAAQ,EAAG,QAAO;AACrC,QAAM,aAAa,SAAS,OAAO,CAAC,YAA+B,OAAO,YAAY,QAAQ;AAC9F,SAAO,WAAW,SAAS,aAAa;AAC1C;AAKA,SAAS,wBACP,YACA,MACA,iBACM;AACN,aAAW,OAAO,MAAM;AACtB,QAAI,IAAI,gBAAgB;AACtB,iBAAW,IAAI,IAAI,OAAO;AAC1B;AAAA,IACF;AAEA,UAAM,WAAW,kBAAkB,IAAI,aAAa;AACpD,QAAI,YAAY,WAAW,UAAU,eAAe,GAAG;AACrD,iBAAW,IAAI,IAAI,OAAO;AAAA,IAC5B;AAAA,EACF;AACF;AAEA,eAAsB,2BACpB,MACA,UACA,QACmB;AACnB,QAAM,YAAY,MAAM,KAAK,YAAY,EACtC,KAAK,SAAS,sBAAsB,UAAU,EAC9C,MAAM,sBAAsB,MAAM,EAClC,UAAU,uBAAuB,EACjC,UAAU,kBAAkB,EAC5B,MAAM,mBAAmB,QAAQ,EACjC,OAAO,qBAAqB;AAE/B,SAAO,UAAU,IAAI,CAAC,QAA6B,IAAI,OAAO;AAChE;AAEA,eAAsB,8BACpB,MACA,UACA,iBACmB;AACnB,QAAM,aAAa,oBAAI,IAAY;AAEnC,QAAM,WAAW,MAAM,KAAK,WAAW,EACpC,KAAK,SAAS,qBAAqB,UAAU,EAC7C,MAAM,uBAAuB,QAAQ,EACrC,UAAU,sBAAsB,EAChC,UAAU,kBAAkB,EAC5B,MAAM,mBAAmB,QAAQ,EACjC,OAAO,uBAAuB,2BAA2B,0BAA0B;AAEtF,0BAAwB,YAAY,UAAU,eAAe;AAE7D,QAAM,WAAW,MAAM,KAAK,WAAW,EACpC,KAAK,cAAc,qBAAqB,oBAAoB,EAC5D,KAAK,SAAS,sBAAsB,UAAU,EAC9C,MAAM,uBAAuB,QAAQ,EACrC,UAAU,sBAAsB,EAChC,UAAU,uBAAuB,EACjC,UAAU,kBAAkB,EAC5B,MAAM,mBAAmB,QAAQ,EACjC,OAAO,uBAAuB,2BAA2B,0BAA0B;AAEtF,0BAAwB,YAAY,UAAU,eAAe;AAE7D,SAAO,MAAM,KAAK,UAAU;AAC9B;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|