@backstage/plugin-notifications-backend 0.5.12-next.1 → 0.6.0
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/CHANGELOG.md +44 -0
- package/config.d.ts +22 -0
- package/dist/service/router.cjs.js +49 -8
- package/dist/service/router.cjs.js.map +1 -1
- package/package.json +17 -17
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
# @backstage/plugin-notifications-backend
|
|
2
2
|
|
|
3
|
+
## 0.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 87e597c: Adds support for default configuration for an entire notification channel.
|
|
8
|
+
This setting will also be inherited down to origins and topics while still respecting the users individual choices.
|
|
9
|
+
|
|
10
|
+
This will be handy if you want to use a "opt-in" strategy.
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 15fb764: Show default settings for notifications even before receiving first notification.
|
|
15
|
+
|
|
16
|
+
Previously, it was not possible for the users to see or modify their notification settings until they had received at
|
|
17
|
+
least one notification from specific origin or topic.
|
|
18
|
+
This update ensures that default settings are displayed from the outset,
|
|
19
|
+
allowing users to customize their preferences immediately.
|
|
20
|
+
|
|
21
|
+
- 05f60e1: Refactored constructor parameter properties to explicit property declarations for compatibility with TypeScript's `erasableSyntaxOnly` setting. This internal refactoring maintains all existing functionality while ensuring TypeScript compilation compatibility.
|
|
22
|
+
- Updated dependencies
|
|
23
|
+
- @backstage/plugin-catalog-node@1.20.0
|
|
24
|
+
- @backstage/plugin-notifications-common@0.2.0
|
|
25
|
+
- @backstage/backend-plugin-api@1.5.0
|
|
26
|
+
- @backstage/plugin-notifications-node@0.2.21
|
|
27
|
+
- @backstage/config@1.3.6
|
|
28
|
+
- @backstage/catalog-model@1.7.6
|
|
29
|
+
- @backstage/plugin-signals-node@0.1.26
|
|
30
|
+
|
|
31
|
+
## 0.6.0-next.2
|
|
32
|
+
|
|
33
|
+
### Minor Changes
|
|
34
|
+
|
|
35
|
+
- 87e597c: Adds support for default configuration for an entire notification channel.
|
|
36
|
+
This setting will also be inherited down to origins and topics while still respecting the users individual choices.
|
|
37
|
+
|
|
38
|
+
This will be handy if you want to use a "opt-in" strategy.
|
|
39
|
+
|
|
40
|
+
### Patch Changes
|
|
41
|
+
|
|
42
|
+
- Updated dependencies
|
|
43
|
+
- @backstage/plugin-notifications-common@0.2.0-next.1
|
|
44
|
+
- @backstage/backend-plugin-api@1.5.0-next.2
|
|
45
|
+
- @backstage/plugin-notifications-node@0.2.21-next.2
|
|
46
|
+
|
|
3
47
|
## 0.5.12-next.1
|
|
4
48
|
|
|
5
49
|
### Patch Changes
|
package/config.d.ts
CHANGED
|
@@ -33,12 +33,34 @@ export interface Config {
|
|
|
33
33
|
*/
|
|
34
34
|
defaultSettings?: {
|
|
35
35
|
channels?: {
|
|
36
|
+
/**
|
|
37
|
+
* Channel identifier (e.g., 'Web', 'Email')
|
|
38
|
+
*/
|
|
36
39
|
id: string;
|
|
40
|
+
/**
|
|
41
|
+
* Optional flag to enable/disable the channel by default.
|
|
42
|
+
* If not set, defaults to true for backwards compatibility.
|
|
43
|
+
* When set to false, the channel uses an opt-in strategy where
|
|
44
|
+
* origins are disabled by default unless explicitly enabled.
|
|
45
|
+
*/
|
|
46
|
+
enabled?: boolean;
|
|
37
47
|
origins?: {
|
|
48
|
+
/**
|
|
49
|
+
* Origin identifier (e.g., 'plugin:catalog', 'external:jenkins')
|
|
50
|
+
*/
|
|
38
51
|
id: string;
|
|
52
|
+
/**
|
|
53
|
+
* Whether notifications from this origin are enabled by default
|
|
54
|
+
*/
|
|
39
55
|
enabled: boolean;
|
|
40
56
|
topics?: {
|
|
57
|
+
/**
|
|
58
|
+
* Topic identifier (e.g., 'entity-refresh', 'build-failure')
|
|
59
|
+
*/
|
|
41
60
|
id: string;
|
|
61
|
+
/**
|
|
62
|
+
* Whether notifications for this topic are enabled by default
|
|
63
|
+
*/
|
|
42
64
|
enabled: boolean;
|
|
43
65
|
}[];
|
|
44
66
|
}[];
|
|
@@ -54,7 +54,7 @@ async function createRouter(options) {
|
|
|
54
54
|
const getNotificationChannels = () => {
|
|
55
55
|
return [WEB_NOTIFICATION_CHANNEL, ...processors.map((p) => p.getName())];
|
|
56
56
|
};
|
|
57
|
-
const getTopicSettings = (topic, existingOrigin, defaultOriginSettings,
|
|
57
|
+
const getTopicSettings = (topic, existingOrigin, defaultOriginSettings, channelDefaultEnabled) => {
|
|
58
58
|
const existingTopic = existingOrigin?.topics?.find(
|
|
59
59
|
(t) => t.id.toLowerCase() === topic.topic.toLowerCase()
|
|
60
60
|
);
|
|
@@ -63,17 +63,17 @@ async function createRouter(options) {
|
|
|
63
63
|
);
|
|
64
64
|
return {
|
|
65
65
|
id: topic.topic,
|
|
66
|
-
enabled: existingTopic ? existingTopic.enabled : defaultTopicSettings?.enabled ??
|
|
66
|
+
enabled: existingTopic ? existingTopic.enabled : defaultTopicSettings?.enabled ?? channelDefaultEnabled
|
|
67
67
|
};
|
|
68
68
|
};
|
|
69
|
-
const getOriginSettings = (originId, existingChannel, defaultChannelSettings, topics) => {
|
|
69
|
+
const getOriginSettings = (originId, existingChannel, defaultChannelSettings, topics, channelDefaultEnabled, channelHasExplicitEnabled) => {
|
|
70
70
|
const existingOrigin = existingChannel?.origins?.find(
|
|
71
71
|
(o) => o.id.toLowerCase() === originId.toLowerCase()
|
|
72
72
|
);
|
|
73
73
|
const defaultOriginSettings = defaultChannelSettings?.origins?.find(
|
|
74
74
|
(c) => c.id.toLowerCase() === originId.toLowerCase()
|
|
75
75
|
);
|
|
76
|
-
const defaultEnabled = existingOrigin ? existingOrigin.enabled : defaultOriginSettings?.enabled ??
|
|
76
|
+
const defaultEnabled = existingOrigin ? existingOrigin.enabled : defaultOriginSettings?.enabled ?? channelDefaultEnabled;
|
|
77
77
|
return {
|
|
78
78
|
id: originId,
|
|
79
79
|
enabled: defaultEnabled,
|
|
@@ -82,7 +82,7 @@ async function createRouter(options) {
|
|
|
82
82
|
t,
|
|
83
83
|
existingOrigin,
|
|
84
84
|
defaultOriginSettings,
|
|
85
|
-
defaultEnabled
|
|
85
|
+
channelHasExplicitEnabled ? channelDefaultEnabled : defaultEnabled
|
|
86
86
|
)
|
|
87
87
|
)
|
|
88
88
|
};
|
|
@@ -94,14 +94,20 @@ async function createRouter(options) {
|
|
|
94
94
|
const defaultChannelSettings = defaultNotificationSettings?.channels?.find(
|
|
95
95
|
(c) => c.id.toLowerCase() === channelId.toLowerCase()
|
|
96
96
|
);
|
|
97
|
+
const channelEnabled = existingChannel?.enabled ?? defaultChannelSettings?.enabled;
|
|
98
|
+
const defaultEnabledForOrigins = channelEnabled ?? true;
|
|
99
|
+
const channelHasExplicitEnabled = existingChannel?.enabled !== void 0 || defaultChannelSettings?.enabled !== void 0;
|
|
97
100
|
return {
|
|
98
101
|
id: channelId,
|
|
102
|
+
enabled: channelEnabled,
|
|
99
103
|
origins: origins.map(
|
|
100
104
|
(originId) => getOriginSettings(
|
|
101
105
|
originId,
|
|
102
106
|
existingChannel,
|
|
103
107
|
defaultChannelSettings,
|
|
104
|
-
topics
|
|
108
|
+
topics,
|
|
109
|
+
defaultEnabledForOrigins,
|
|
110
|
+
channelHasExplicitEnabled
|
|
105
111
|
)
|
|
106
112
|
)
|
|
107
113
|
};
|
|
@@ -115,7 +121,7 @@ async function createRouter(options) {
|
|
|
115
121
|
if (!channels.includes(channel.id)) {
|
|
116
122
|
channels.push(channel.id);
|
|
117
123
|
}
|
|
118
|
-
for (const origin of channel.origins) {
|
|
124
|
+
for (const origin of channel.origins ?? []) {
|
|
119
125
|
if (!origins.includes(origin.id)) {
|
|
120
126
|
origins.push(origin.id);
|
|
121
127
|
}
|
|
@@ -133,7 +139,42 @@ async function createRouter(options) {
|
|
|
133
139
|
};
|
|
134
140
|
};
|
|
135
141
|
const isNotificationsEnabled = async (opts) => {
|
|
136
|
-
const
|
|
142
|
+
const userSettings = await store.getNotificationSettings({
|
|
143
|
+
user: opts.user
|
|
144
|
+
});
|
|
145
|
+
const settings = {
|
|
146
|
+
channels: [
|
|
147
|
+
{
|
|
148
|
+
id: opts.channel,
|
|
149
|
+
enabled: defaultNotificationSettings?.channels?.find(
|
|
150
|
+
(c) => c.id.toLowerCase() === opts.channel.toLowerCase()
|
|
151
|
+
)?.enabled,
|
|
152
|
+
origins: []
|
|
153
|
+
}
|
|
154
|
+
]
|
|
155
|
+
};
|
|
156
|
+
const userChannel = userSettings.channels.find(
|
|
157
|
+
(c) => c.id.toLowerCase() === opts.channel.toLowerCase()
|
|
158
|
+
);
|
|
159
|
+
if (userChannel) {
|
|
160
|
+
settings.channels[0] = {
|
|
161
|
+
...settings.channels[0],
|
|
162
|
+
enabled: userChannel.enabled ?? settings.channels[0].enabled,
|
|
163
|
+
origins: userChannel.origins ?? []
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
const defaultChannelSettings = defaultNotificationSettings?.channels?.find(
|
|
167
|
+
(c) => c.id.toLowerCase() === opts.channel.toLowerCase()
|
|
168
|
+
);
|
|
169
|
+
if (defaultChannelSettings?.origins && settings.channels[0].enabled !== false) {
|
|
170
|
+
for (const defaultOrigin of defaultChannelSettings.origins) {
|
|
171
|
+
if (!settings.channels[0].origins.some(
|
|
172
|
+
(o) => o.id.toLowerCase() === defaultOrigin.id.toLowerCase()
|
|
173
|
+
)) {
|
|
174
|
+
settings.channels[0].origins.push(defaultOrigin);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
137
178
|
return pluginNotificationsCommon.isNotificationsEnabledFor(
|
|
138
179
|
settings,
|
|
139
180
|
opts.channel,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport express, { Request, Response } from 'express';\nimport Router from 'express-promise-router';\nimport {\n normalizeSeverity,\n NotificationGetOptions,\n NotificationsStore,\n TopicGetOptions,\n} from '../database';\nimport { v4 as uuid } from 'uuid';\nimport { CatalogService } from '@backstage/plugin-catalog-node';\nimport {\n NotificationProcessor,\n NotificationRecipientResolver,\n NotificationSendOptions,\n} from '@backstage/plugin-notifications-node';\nimport { InputError, NotFoundError } from '@backstage/errors';\nimport {\n AuthService,\n HttpAuthService,\n LoggerService,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\nimport { SignalsService } from '@backstage/plugin-signals-node';\nimport {\n ChannelSetting,\n isNotificationsEnabledFor,\n NewNotificationSignal,\n Notification,\n NotificationReadSignal,\n NotificationSettings,\n notificationSeverities,\n NotificationStatus,\n OriginSetting,\n} from '@backstage/plugin-notifications-common';\nimport { parseEntityOrderFieldParams } from './parseEntityOrderFieldParams';\nimport { Config, readDurationFromConfig } from '@backstage/config';\nimport { durationToMilliseconds } from '@backstage/types';\nimport pThrottle from 'p-throttle';\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport { DefaultNotificationRecipientResolver } from './DefaultNotificationRecipientResolver.ts';\n\n/** @internal */\nexport interface RouterOptions {\n logger: LoggerService;\n config: Config;\n store: NotificationsStore;\n auth: AuthService;\n httpAuth: HttpAuthService;\n userInfo: UserInfoService;\n signals?: SignalsService;\n catalog: CatalogService;\n processors?: NotificationProcessor[];\n recipientResolver?: NotificationRecipientResolver;\n}\n\n/** @internal */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const {\n config,\n logger,\n store,\n auth,\n httpAuth,\n userInfo,\n catalog,\n processors = [],\n signals,\n recipientResolver,\n } = options;\n\n const WEB_NOTIFICATION_CHANNEL = 'Web';\n const frontendBaseUrl = config.getString('app.baseUrl');\n const concurrencyLimit =\n config.getOptionalNumber('notifications.concurrencyLimit') ?? 10;\n const throttleInterval = config.has('notifications.throttleInterval')\n ? durationToMilliseconds(\n readDurationFromConfig(config, {\n key: 'notifications.throttleInterval',\n }),\n )\n : 50;\n const throttle = pThrottle({\n limit: concurrencyLimit,\n interval: throttleInterval,\n });\n const defaultNotificationSettings: NotificationSettings | undefined =\n config.getOptional<NotificationSettings>('notifications.defaultSettings');\n\n const usedRecipientResolver =\n recipientResolver ??\n new DefaultNotificationRecipientResolver(auth, catalog);\n\n const getUser = async (req: Request<unknown>) => {\n const credentials = await httpAuth.credentials(req, { allow: ['user'] });\n const info = await userInfo.getUserInfo(credentials);\n return info.userEntityRef;\n };\n\n const getNotificationChannels = () => {\n return [WEB_NOTIFICATION_CHANNEL, ...processors.map(p => p.getName())];\n };\n\n const getTopicSettings = (\n topic: any,\n existingOrigin: OriginSetting | undefined,\n defaultOriginSettings: OriginSetting | undefined,\n defaultEnabled: boolean,\n ) => {\n const existingTopic = existingOrigin?.topics?.find(\n t => t.id.toLowerCase() === topic.topic.toLowerCase(),\n );\n const defaultTopicSettings = defaultOriginSettings?.topics?.find(\n t => t.id.toLowerCase() === topic.topic.toLowerCase(),\n );\n\n return {\n id: topic.topic,\n enabled: existingTopic\n ? existingTopic.enabled\n : defaultTopicSettings?.enabled ?? defaultEnabled,\n };\n };\n\n const getOriginSettings = (\n originId: string,\n existingChannel: ChannelSetting | undefined,\n defaultChannelSettings: ChannelSetting | undefined,\n topics: { origin: string; topic: string }[],\n ) => {\n const existingOrigin = existingChannel?.origins?.find(\n o => o.id.toLowerCase() === originId.toLowerCase(),\n );\n\n const defaultOriginSettings = defaultChannelSettings?.origins?.find(\n c => c.id.toLowerCase() === originId.toLowerCase(),\n );\n\n const defaultEnabled = existingOrigin\n ? existingOrigin.enabled\n : defaultOriginSettings?.enabled ?? true;\n\n return {\n id: originId,\n enabled: defaultEnabled,\n topics: topics\n .filter(t => t.origin === originId)\n .map(t =>\n getTopicSettings(\n t,\n existingOrigin,\n defaultOriginSettings,\n defaultEnabled,\n ),\n ),\n };\n };\n\n const getChannelSettings = (\n channelId: string,\n settings: NotificationSettings,\n origins: string[],\n topics: { origin: string; topic: string }[],\n ) => {\n const existingChannel = settings.channels.find(\n c => c.id.toLowerCase() === channelId.toLowerCase(),\n );\n const defaultChannelSettings = defaultNotificationSettings?.channels?.find(\n c => c.id.toLowerCase() === channelId.toLowerCase(),\n );\n\n return {\n id: channelId,\n origins: origins.map(originId =>\n getOriginSettings(\n originId,\n existingChannel,\n defaultChannelSettings,\n topics,\n ),\n ),\n };\n };\n\n const getNotificationSettings = async (\n user: string,\n ): Promise<NotificationSettings> => {\n const { origins } = await store.getUserNotificationOrigins({ user });\n const { topics } = await store.getUserNotificationTopics({ user });\n const settings = await store.getNotificationSettings({ user });\n const channels = getNotificationChannels();\n\n // Merge existing channels/origins/topics with configured settings\n for (const channel of defaultNotificationSettings?.channels ?? []) {\n if (!channels.includes(channel.id)) {\n channels.push(channel.id);\n }\n\n for (const origin of channel.origins) {\n if (!origins.includes(origin.id)) {\n origins.push(origin.id);\n }\n\n for (const topic of origin.topics ?? []) {\n if (\n !topics.some(t => t.origin === origin.id && t.topic === topic.id)\n ) {\n topics.push({ origin: origin.id, topic: topic.id });\n }\n }\n }\n }\n\n return {\n channels: channels.map(channelId =>\n getChannelSettings(channelId, settings, origins, topics),\n ),\n };\n };\n\n const isNotificationsEnabled = async (opts: {\n user: string;\n channel: string;\n origin: string;\n topic: string | null;\n }) => {\n const settings = await getNotificationSettings(opts.user);\n return isNotificationsEnabledFor(\n settings,\n opts.channel,\n opts.origin,\n opts.topic,\n );\n };\n\n const filterProcessors = async (\n notification:\n | Notification\n | ({ origin: string; user: null } & NotificationSendOptions),\n ) => {\n const result: NotificationProcessor[] = [];\n const { payload, user, origin } = notification;\n\n for (const processor of processors) {\n if (user) {\n const enabled = await isNotificationsEnabled({\n user,\n origin,\n channel: processor.getName(),\n topic: payload.topic ?? null,\n });\n if (!enabled) {\n continue;\n }\n }\n\n if (processor.getNotificationFilters) {\n const filters = processor.getNotificationFilters();\n if (filters.minSeverity) {\n if (\n notificationSeverities.indexOf(payload.severity ?? 'normal') >\n notificationSeverities.indexOf(filters.minSeverity)\n ) {\n continue;\n }\n }\n\n if (filters.maxSeverity) {\n if (\n notificationSeverities.indexOf(payload.severity ?? 'normal') <\n notificationSeverities.indexOf(filters.maxSeverity)\n ) {\n continue;\n }\n }\n\n if (filters.excludedTopics && payload.topic) {\n if (filters.excludedTopics.includes(payload.topic)) {\n continue;\n }\n }\n }\n result.push(processor);\n }\n\n return result;\n };\n\n const processOptions = async (\n opts: NotificationSendOptions,\n origin: string,\n ): Promise<NotificationSendOptions> => {\n const filtered = await filterProcessors({ ...opts, origin, user: null });\n let ret = opts;\n for (const processor of filtered) {\n try {\n ret = processor.processOptions\n ? await processor.processOptions(ret)\n : ret;\n } catch (e) {\n logger.error(\n `Error while processing notification options with ${processor.getName()}: ${e}`,\n );\n }\n }\n return ret;\n };\n\n const preProcessNotification = async (\n notification: Notification,\n opts: NotificationSendOptions,\n ) => {\n const filtered = await filterProcessors(notification);\n let ret = notification;\n for (const processor of filtered) {\n try {\n ret = processor.preProcess\n ? await processor.preProcess(ret, opts)\n : ret;\n } catch (e) {\n logger.error(\n `Error while pre processing notification with ${processor.getName()}: ${e}`,\n );\n }\n }\n return ret;\n };\n\n const postProcessNotification = async (\n notification: Notification,\n opts: NotificationSendOptions,\n ) => {\n const filtered = await filterProcessors(notification);\n for (const processor of filtered) {\n if (processor.postProcess) {\n try {\n await processor.postProcess(notification, opts);\n } catch (e) {\n logger.error(\n `Error while post processing notification with ${processor.getName()}: ${e}`,\n );\n }\n }\n }\n };\n\n const validateLink = (link: string) => {\n const stripLeadingSlash = (s: string) => s.replace(/^\\//, '');\n const ensureTrailingSlash = (s: string) => s.replace(/\\/?$/, '/');\n const url = new URL(\n stripLeadingSlash(link),\n ensureTrailingSlash(frontendBaseUrl),\n );\n if (url.protocol !== 'https:' && url.protocol !== 'http:') {\n throw new Error('Only HTTP/HTTPS links are allowed');\n }\n };\n\n const appendCommonOptions = (\n req: Request,\n opts: NotificationGetOptions | TopicGetOptions,\n ) => {\n if (req.query.search) {\n opts.search = req.query.search.toString();\n }\n if (req.query.read === 'true') {\n opts.read = true;\n } else if (req.query.read === 'false') {\n opts.read = false;\n // or keep undefined\n }\n\n if (req.query.saved === 'true') {\n opts.saved = true;\n } else if (req.query.saved === 'false') {\n opts.saved = false;\n // or keep undefined\n }\n if (req.query.createdAfter) {\n const sinceEpoch = Date.parse(String(req.query.createdAfter));\n if (isNaN(sinceEpoch)) {\n throw new InputError('Unexpected date format');\n }\n opts.createdAfter = new Date(sinceEpoch);\n }\n if (req.query.minimumSeverity) {\n opts.minimumSeverity = normalizeSeverity(\n req.query.minimumSeverity.toString(),\n );\n }\n };\n\n // TODO: Move to use OpenAPI router instead\n const router = Router();\n router.use(express.json());\n\n const listNotificationsHandler = async (req: Request, res: Response) => {\n const user = await getUser(req);\n const opts: NotificationGetOptions = {\n user: user,\n };\n if (req.query.offset) {\n opts.offset = Number.parseInt(req.query.offset.toString(), 10);\n }\n if (req.query.limit) {\n opts.limit = Number.parseInt(req.query.limit.toString(), 10);\n }\n if (req.query.orderField) {\n opts.orderField = parseEntityOrderFieldParams(req.query);\n }\n\n if (req.query.topic) {\n opts.topic = req.query.topic.toString();\n }\n\n appendCommonOptions(req, opts);\n\n const [notifications, totalCount] = await Promise.all([\n store.getNotifications(opts),\n store.getNotificationsCount(opts),\n ]);\n res.json({\n totalCount,\n notifications,\n });\n };\n\n router.get('/', listNotificationsHandler); // Deprecated endpoint\n router.get('/notifications', listNotificationsHandler);\n\n router.get('/status', async (req: Request<any, NotificationStatus>, res) => {\n const user = await getUser(req);\n const status = await store.getStatus({ user });\n res.json(status);\n });\n\n router.get(\n '/settings',\n async (req: Request<any, NotificationSettings>, res) => {\n const user = await getUser(req);\n const response = await getNotificationSettings(user);\n res.json(response);\n },\n );\n\n router.post(\n '/settings',\n async (\n req: Request<any, NotificationSettings, NotificationSettings>,\n res,\n ) => {\n const user = await getUser(req);\n const channels = getNotificationChannels();\n const settings: NotificationSettings = req.body;\n if (settings.channels.some(c => !channels.includes(c.id))) {\n throw new InputError('Invalid channel');\n }\n await store.saveNotificationSettings({ user, settings });\n const response = await getNotificationSettings(user);\n res.json(response);\n },\n );\n\n const getNotificationHandler = async (req: Request, res: Response) => {\n const user = await getUser(req);\n const opts: NotificationGetOptions = {\n user: user,\n limit: 1,\n ids: [req.params.id],\n };\n const notifications = await store.getNotifications(opts);\n if (notifications.length !== 1) {\n throw new NotFoundError('Not found');\n }\n res.json(notifications[0]);\n };\n\n // Get topics\n const listTopicsHandler = async (req: Request, res: Response) => {\n const user = await getUser(req);\n const opts: TopicGetOptions = {\n user: user,\n };\n\n appendCommonOptions(req, opts);\n\n const topics = await store.getTopics(opts);\n res.json(topics);\n };\n\n router.get('/topics', listTopicsHandler);\n\n // Make sure this is the last \"GET\" handler\n router.get('/:id', getNotificationHandler); // Deprecated endpoint\n router.get('/notifications/:id', getNotificationHandler);\n\n const updateNotificationsHandler = async (req: Request, res: Response) => {\n const user = await getUser(req);\n const { ids, read, saved } = req.body;\n if (!ids || !Array.isArray(ids)) {\n throw new InputError();\n }\n\n if (read === true) {\n await store.markRead({ user, ids });\n\n if (signals) {\n await signals.publish<NotificationReadSignal>({\n recipients: { type: 'user', entityRef: [user] },\n message: { action: 'notification_read', notification_ids: ids },\n channel: 'notifications',\n });\n }\n } else if (read === false) {\n await store.markUnread({ user: user, ids });\n\n if (signals) {\n await signals.publish<NotificationReadSignal>({\n recipients: { type: 'user', entityRef: [user] },\n message: { action: 'notification_unread', notification_ids: ids },\n channel: 'notifications',\n });\n }\n }\n\n if (saved === true) {\n await store.markSaved({ user: user, ids });\n } else if (saved === false) {\n await store.markUnsaved({ user: user, ids });\n }\n\n const notifications = await store.getNotifications({ ids, user: user });\n res.json(notifications);\n };\n\n router.post('/update', updateNotificationsHandler); // Deprecated endpoint\n router.post('/notifications/update', updateNotificationsHandler);\n\n const sendBroadcastNotification = async (\n baseNotification: Omit<Notification, 'user' | 'id'>,\n opts: NotificationSendOptions,\n origin: string,\n ) => {\n const { scope } = opts.payload;\n const broadcastNotification = {\n ...baseNotification,\n user: null,\n id: uuid(),\n };\n const notification = await preProcessNotification(\n broadcastNotification,\n opts,\n );\n let existingNotification;\n if (scope) {\n existingNotification = await store.getExistingScopeBroadcast({\n scope,\n origin,\n });\n }\n\n let ret = notification;\n if (existingNotification) {\n const restored = await store.restoreExistingNotification({\n id: existingNotification.id,\n notification: { ...notification, user: '' },\n });\n ret = restored ?? notification;\n } else {\n await store.saveBroadcast(notification);\n }\n\n if (signals) {\n await signals.publish<NewNotificationSignal>({\n recipients: { type: 'broadcast' },\n message: {\n action: 'new_notification',\n notification_id: ret.id,\n },\n channel: 'notifications',\n });\n }\n postProcessNotification(ret, opts);\n return notification;\n };\n\n const sendUserNotification = async (\n baseNotification: Omit<Notification, 'user' | 'id'>,\n user: string,\n opts: NotificationSendOptions,\n origin: string,\n scope?: string,\n ): Promise<Notification | undefined> => {\n const userNotification = {\n ...baseNotification,\n id: uuid(),\n user,\n };\n const notification = await preProcessNotification(userNotification, opts);\n\n const enabled = await isNotificationsEnabled({\n user,\n channel: WEB_NOTIFICATION_CHANNEL,\n origin: userNotification.origin,\n topic: userNotification.payload.topic ?? null,\n });\n\n let ret = notification;\n\n if (!enabled) {\n postProcessNotification(ret, opts);\n return undefined;\n }\n\n let existingNotification;\n if (scope) {\n existingNotification = await store.getExistingScopeNotification({\n user,\n scope,\n origin,\n });\n }\n\n if (existingNotification) {\n const restored = await store.restoreExistingNotification({\n id: existingNotification.id,\n notification,\n });\n ret = restored ?? notification;\n } else {\n await store.saveNotification(notification);\n }\n\n if (signals) {\n await signals.publish<NewNotificationSignal>({\n recipients: { type: 'user', entityRef: [user] },\n message: {\n action: 'new_notification',\n notification_id: ret.id,\n },\n channel: 'notifications',\n });\n }\n postProcessNotification(ret, opts);\n return ret;\n };\n\n const filterNonUserEntityRefs = (refs: string[]): string[] => {\n return refs.filter(ref => {\n try {\n const parsed = parseEntityRef(ref);\n return parsed.kind.toLowerCase() === 'user';\n } catch {\n return false;\n }\n });\n };\n\n const sendUserNotifications = async (\n baseNotification: Omit<Notification, 'user' | 'id'>,\n users: string[],\n opts: NotificationSendOptions,\n origin: string,\n ): Promise<Notification[]> => {\n const { scope } = opts.payload;\n const uniqueUsers = [...new Set(filterNonUserEntityRefs(users))];\n const throttled = throttle((user: string) =>\n sendUserNotification(baseNotification, user, opts, origin, scope),\n );\n const sent = await Promise.all(uniqueUsers.map(user => throttled(user)));\n return sent.filter(n => n !== undefined);\n };\n\n const createNotificationHandler = async (\n req: Request<any, Notification[], NotificationSendOptions>,\n res: Response,\n ) => {\n const credentials = await httpAuth.credentials(req, {\n allow: ['service'],\n });\n\n const origin = credentials.principal.subject;\n const opts = await processOptions(req.body, origin);\n const { recipients, payload } = opts;\n const { title, link } = payload;\n const notifications: Notification[] = [];\n\n if (!recipients || !title) {\n const missing = [\n !title ? 'title' : null,\n !recipients ? 'recipients' : null,\n ].filter(Boolean);\n const err = `Invalid notification request received: missing ${missing.join(\n ', ',\n )}`;\n throw new InputError(err);\n }\n\n if (link) {\n try {\n validateLink(link);\n } catch (e) {\n throw new InputError('Invalid link provided', e);\n }\n }\n\n const baseNotification = {\n payload: {\n ...payload,\n severity: payload.severity ?? 'normal',\n },\n origin,\n created: new Date(),\n };\n\n if (recipients.type === 'broadcast') {\n const broadcast = await sendBroadcastNotification(\n baseNotification,\n opts,\n origin,\n );\n notifications.push(broadcast);\n } else if (recipients.type === 'entity') {\n const entityRefs = [recipients.entityRef].flat();\n const excludedEntityRefs = recipients.excludeEntityRef\n ? [recipients.excludeEntityRef].flat()\n : undefined;\n try {\n const { userEntityRefs } =\n await usedRecipientResolver.resolveNotificationRecipients({\n entityRefs,\n excludedEntityRefs,\n });\n const userNotifications = await sendUserNotifications(\n baseNotification,\n userEntityRefs,\n opts,\n origin,\n );\n notifications.push(...userNotifications);\n } catch (e) {\n throw new InputError('Failed to send user notifications', e);\n }\n } else {\n throw new InputError(\n `Invalid recipients type, please use either 'broadcast' or 'entity'`,\n );\n }\n\n res.json(notifications);\n };\n\n // Add new notification\n router.post('/', createNotificationHandler);\n router.post('/notifications', createNotificationHandler);\n\n return router;\n}\n"],"names":["config","durationToMilliseconds","readDurationFromConfig","pThrottle","DefaultNotificationRecipientResolver","isNotificationsEnabledFor","notificationSeverities","InputError","normalizeSeverity","Router","express","parseEntityOrderFieldParams","NotFoundError","uuid","parseEntityRef"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport express, { Request, Response } from 'express';\nimport Router from 'express-promise-router';\nimport {\n normalizeSeverity,\n NotificationGetOptions,\n NotificationsStore,\n TopicGetOptions,\n} from '../database';\nimport { v4 as uuid } from 'uuid';\nimport { CatalogService } from '@backstage/plugin-catalog-node';\nimport {\n NotificationProcessor,\n NotificationRecipientResolver,\n NotificationSendOptions,\n} from '@backstage/plugin-notifications-node';\nimport { InputError, NotFoundError } from '@backstage/errors';\nimport {\n AuthService,\n HttpAuthService,\n LoggerService,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\nimport { SignalsService } from '@backstage/plugin-signals-node';\nimport {\n ChannelSetting,\n isNotificationsEnabledFor,\n NewNotificationSignal,\n Notification,\n NotificationReadSignal,\n NotificationSettings,\n notificationSeverities,\n NotificationStatus,\n OriginSetting,\n} from '@backstage/plugin-notifications-common';\nimport { parseEntityOrderFieldParams } from './parseEntityOrderFieldParams';\nimport { Config, readDurationFromConfig } from '@backstage/config';\nimport { durationToMilliseconds } from '@backstage/types';\nimport pThrottle from 'p-throttle';\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport { DefaultNotificationRecipientResolver } from './DefaultNotificationRecipientResolver.ts';\n\n/** @internal */\nexport interface RouterOptions {\n logger: LoggerService;\n config: Config;\n store: NotificationsStore;\n auth: AuthService;\n httpAuth: HttpAuthService;\n userInfo: UserInfoService;\n signals?: SignalsService;\n catalog: CatalogService;\n processors?: NotificationProcessor[];\n recipientResolver?: NotificationRecipientResolver;\n}\n\n/** @internal */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const {\n config,\n logger,\n store,\n auth,\n httpAuth,\n userInfo,\n catalog,\n processors = [],\n signals,\n recipientResolver,\n } = options;\n\n const WEB_NOTIFICATION_CHANNEL = 'Web';\n const frontendBaseUrl = config.getString('app.baseUrl');\n const concurrencyLimit =\n config.getOptionalNumber('notifications.concurrencyLimit') ?? 10;\n const throttleInterval = config.has('notifications.throttleInterval')\n ? durationToMilliseconds(\n readDurationFromConfig(config, {\n key: 'notifications.throttleInterval',\n }),\n )\n : 50;\n const throttle = pThrottle({\n limit: concurrencyLimit,\n interval: throttleInterval,\n });\n const defaultNotificationSettings: NotificationSettings | undefined =\n config.getOptional<NotificationSettings>('notifications.defaultSettings');\n\n const usedRecipientResolver =\n recipientResolver ??\n new DefaultNotificationRecipientResolver(auth, catalog);\n\n const getUser = async (req: Request<unknown>) => {\n const credentials = await httpAuth.credentials(req, { allow: ['user'] });\n const info = await userInfo.getUserInfo(credentials);\n return info.userEntityRef;\n };\n\n const getNotificationChannels = () => {\n return [WEB_NOTIFICATION_CHANNEL, ...processors.map(p => p.getName())];\n };\n\n const getTopicSettings = (\n topic: any,\n existingOrigin: OriginSetting | undefined,\n defaultOriginSettings: OriginSetting | undefined,\n channelDefaultEnabled: boolean,\n ) => {\n const existingTopic = existingOrigin?.topics?.find(\n t => t.id.toLowerCase() === topic.topic.toLowerCase(),\n );\n const defaultTopicSettings = defaultOriginSettings?.topics?.find(\n t => t.id.toLowerCase() === topic.topic.toLowerCase(),\n );\n\n // If topic has explicit setting, use it\n // Otherwise check default topic settings from config\n // Otherwise use channel default (not origin enabled state)\n return {\n id: topic.topic,\n enabled: existingTopic\n ? existingTopic.enabled\n : defaultTopicSettings?.enabled ?? channelDefaultEnabled,\n };\n };\n\n const getOriginSettings = (\n originId: string,\n existingChannel: ChannelSetting | undefined,\n defaultChannelSettings: ChannelSetting | undefined,\n topics: { origin: string; topic: string }[],\n channelDefaultEnabled: boolean,\n channelHasExplicitEnabled: boolean,\n ) => {\n const existingOrigin = existingChannel?.origins?.find(\n o => o.id.toLowerCase() === originId.toLowerCase(),\n );\n\n const defaultOriginSettings = defaultChannelSettings?.origins?.find(\n c => c.id.toLowerCase() === originId.toLowerCase(),\n );\n\n const defaultEnabled = existingOrigin\n ? existingOrigin.enabled\n : defaultOriginSettings?.enabled ?? channelDefaultEnabled;\n\n return {\n id: originId,\n enabled: defaultEnabled,\n topics: topics\n .filter(t => t.origin === originId)\n .map(t =>\n getTopicSettings(\n t,\n existingOrigin,\n defaultOriginSettings,\n channelHasExplicitEnabled ? channelDefaultEnabled : defaultEnabled,\n ),\n ),\n };\n };\n\n const getChannelSettings = (\n channelId: string,\n settings: NotificationSettings,\n origins: string[],\n topics: { origin: string; topic: string }[],\n ) => {\n const existingChannel = settings.channels.find(\n c => c.id.toLowerCase() === channelId.toLowerCase(),\n );\n const defaultChannelSettings = defaultNotificationSettings?.channels?.find(\n c => c.id.toLowerCase() === channelId.toLowerCase(),\n );\n\n // Determine channel enabled state\n const channelEnabled =\n existingChannel?.enabled ?? defaultChannelSettings?.enabled;\n\n // Use channel's enabled flag as the default for origins if not explicitly set\n const defaultEnabledForOrigins = channelEnabled ?? true;\n\n // Check if channel has explicit enabled flag (either from user settings or config)\n const channelHasExplicitEnabled =\n existingChannel?.enabled !== undefined ||\n defaultChannelSettings?.enabled !== undefined;\n\n return {\n id: channelId,\n enabled: channelEnabled,\n origins: origins.map(originId =>\n getOriginSettings(\n originId,\n existingChannel,\n defaultChannelSettings,\n topics,\n defaultEnabledForOrigins,\n channelHasExplicitEnabled,\n ),\n ),\n };\n };\n\n const getNotificationSettings = async (\n user: string,\n ): Promise<NotificationSettings> => {\n const { origins } = await store.getUserNotificationOrigins({ user });\n const { topics } = await store.getUserNotificationTopics({ user });\n const settings = await store.getNotificationSettings({ user });\n const channels = getNotificationChannels();\n\n // Merge existing channels/origins/topics with configured settings\n for (const channel of defaultNotificationSettings?.channels ?? []) {\n if (!channels.includes(channel.id)) {\n channels.push(channel.id);\n }\n\n for (const origin of channel.origins ?? []) {\n if (!origins.includes(origin.id)) {\n origins.push(origin.id);\n }\n\n for (const topic of origin.topics ?? []) {\n if (\n !topics.some(t => t.origin === origin.id && t.topic === topic.id)\n ) {\n topics.push({ origin: origin.id, topic: topic.id });\n }\n }\n }\n }\n\n return {\n channels: channels.map(channelId =>\n getChannelSettings(channelId, settings, origins, topics),\n ),\n };\n };\n\n const isNotificationsEnabled = async (opts: {\n user: string;\n channel: string;\n origin: string;\n topic: string | null;\n }) => {\n // Get user's explicit settings from database\n const userSettings = await store.getNotificationSettings({\n user: opts.user,\n });\n\n // Build a minimal settings object with user settings and config defaults\n const settings: NotificationSettings = {\n channels: [\n {\n id: opts.channel,\n enabled: defaultNotificationSettings?.channels?.find(\n c => c.id.toLowerCase() === opts.channel.toLowerCase(),\n )?.enabled,\n origins: [],\n },\n ],\n };\n\n // Add user's channel if it exists\n const userChannel = userSettings.channels.find(\n c => c.id.toLowerCase() === opts.channel.toLowerCase(),\n );\n if (userChannel) {\n settings.channels[0] = {\n ...settings.channels[0],\n enabled: userChannel.enabled ?? settings.channels[0].enabled,\n origins: userChannel.origins ?? [],\n };\n }\n\n // Add config default origins if not in user settings\n // Only add origins if the channel is enabled (not explicitly disabled)\n const defaultChannelSettings = defaultNotificationSettings?.channels?.find(\n c => c.id.toLowerCase() === opts.channel.toLowerCase(),\n );\n if (\n defaultChannelSettings?.origins &&\n settings.channels[0].enabled !== false\n ) {\n for (const defaultOrigin of defaultChannelSettings.origins) {\n if (\n !settings.channels[0].origins.some(\n o => o.id.toLowerCase() === defaultOrigin.id.toLowerCase(),\n )\n ) {\n settings.channels[0].origins.push(defaultOrigin);\n }\n }\n }\n\n return isNotificationsEnabledFor(\n settings,\n opts.channel,\n opts.origin,\n opts.topic,\n );\n };\n\n const filterProcessors = async (\n notification:\n | Notification\n | ({ origin: string; user: null } & NotificationSendOptions),\n ) => {\n const result: NotificationProcessor[] = [];\n const { payload, user, origin } = notification;\n\n for (const processor of processors) {\n if (user) {\n const enabled = await isNotificationsEnabled({\n user,\n origin,\n channel: processor.getName(),\n topic: payload.topic ?? null,\n });\n if (!enabled) {\n continue;\n }\n }\n\n if (processor.getNotificationFilters) {\n const filters = processor.getNotificationFilters();\n if (filters.minSeverity) {\n if (\n notificationSeverities.indexOf(payload.severity ?? 'normal') >\n notificationSeverities.indexOf(filters.minSeverity)\n ) {\n continue;\n }\n }\n\n if (filters.maxSeverity) {\n if (\n notificationSeverities.indexOf(payload.severity ?? 'normal') <\n notificationSeverities.indexOf(filters.maxSeverity)\n ) {\n continue;\n }\n }\n\n if (filters.excludedTopics && payload.topic) {\n if (filters.excludedTopics.includes(payload.topic)) {\n continue;\n }\n }\n }\n result.push(processor);\n }\n\n return result;\n };\n\n const processOptions = async (\n opts: NotificationSendOptions,\n origin: string,\n ): Promise<NotificationSendOptions> => {\n const filtered = await filterProcessors({ ...opts, origin, user: null });\n let ret = opts;\n for (const processor of filtered) {\n try {\n ret = processor.processOptions\n ? await processor.processOptions(ret)\n : ret;\n } catch (e) {\n logger.error(\n `Error while processing notification options with ${processor.getName()}: ${e}`,\n );\n }\n }\n return ret;\n };\n\n const preProcessNotification = async (\n notification: Notification,\n opts: NotificationSendOptions,\n ) => {\n const filtered = await filterProcessors(notification);\n let ret = notification;\n for (const processor of filtered) {\n try {\n ret = processor.preProcess\n ? await processor.preProcess(ret, opts)\n : ret;\n } catch (e) {\n logger.error(\n `Error while pre processing notification with ${processor.getName()}: ${e}`,\n );\n }\n }\n return ret;\n };\n\n const postProcessNotification = async (\n notification: Notification,\n opts: NotificationSendOptions,\n ) => {\n const filtered = await filterProcessors(notification);\n for (const processor of filtered) {\n if (processor.postProcess) {\n try {\n await processor.postProcess(notification, opts);\n } catch (e) {\n logger.error(\n `Error while post processing notification with ${processor.getName()}: ${e}`,\n );\n }\n }\n }\n };\n\n const validateLink = (link: string) => {\n const stripLeadingSlash = (s: string) => s.replace(/^\\//, '');\n const ensureTrailingSlash = (s: string) => s.replace(/\\/?$/, '/');\n const url = new URL(\n stripLeadingSlash(link),\n ensureTrailingSlash(frontendBaseUrl),\n );\n if (url.protocol !== 'https:' && url.protocol !== 'http:') {\n throw new Error('Only HTTP/HTTPS links are allowed');\n }\n };\n\n const appendCommonOptions = (\n req: Request,\n opts: NotificationGetOptions | TopicGetOptions,\n ) => {\n if (req.query.search) {\n opts.search = req.query.search.toString();\n }\n if (req.query.read === 'true') {\n opts.read = true;\n } else if (req.query.read === 'false') {\n opts.read = false;\n // or keep undefined\n }\n\n if (req.query.saved === 'true') {\n opts.saved = true;\n } else if (req.query.saved === 'false') {\n opts.saved = false;\n // or keep undefined\n }\n if (req.query.createdAfter) {\n const sinceEpoch = Date.parse(String(req.query.createdAfter));\n if (isNaN(sinceEpoch)) {\n throw new InputError('Unexpected date format');\n }\n opts.createdAfter = new Date(sinceEpoch);\n }\n if (req.query.minimumSeverity) {\n opts.minimumSeverity = normalizeSeverity(\n req.query.minimumSeverity.toString(),\n );\n }\n };\n\n // TODO: Move to use OpenAPI router instead\n const router = Router();\n router.use(express.json());\n\n const listNotificationsHandler = async (req: Request, res: Response) => {\n const user = await getUser(req);\n const opts: NotificationGetOptions = {\n user: user,\n };\n if (req.query.offset) {\n opts.offset = Number.parseInt(req.query.offset.toString(), 10);\n }\n if (req.query.limit) {\n opts.limit = Number.parseInt(req.query.limit.toString(), 10);\n }\n if (req.query.orderField) {\n opts.orderField = parseEntityOrderFieldParams(req.query);\n }\n\n if (req.query.topic) {\n opts.topic = req.query.topic.toString();\n }\n\n appendCommonOptions(req, opts);\n\n const [notifications, totalCount] = await Promise.all([\n store.getNotifications(opts),\n store.getNotificationsCount(opts),\n ]);\n res.json({\n totalCount,\n notifications,\n });\n };\n\n router.get('/', listNotificationsHandler); // Deprecated endpoint\n router.get('/notifications', listNotificationsHandler);\n\n router.get('/status', async (req: Request<any, NotificationStatus>, res) => {\n const user = await getUser(req);\n const status = await store.getStatus({ user });\n res.json(status);\n });\n\n router.get(\n '/settings',\n async (req: Request<any, NotificationSettings>, res) => {\n const user = await getUser(req);\n const response = await getNotificationSettings(user);\n res.json(response);\n },\n );\n\n router.post(\n '/settings',\n async (\n req: Request<any, NotificationSettings, NotificationSettings>,\n res,\n ) => {\n const user = await getUser(req);\n const channels = getNotificationChannels();\n const settings: NotificationSettings = req.body;\n if (settings.channels.some(c => !channels.includes(c.id))) {\n throw new InputError('Invalid channel');\n }\n await store.saveNotificationSettings({ user, settings });\n const response = await getNotificationSettings(user);\n res.json(response);\n },\n );\n\n const getNotificationHandler = async (req: Request, res: Response) => {\n const user = await getUser(req);\n const opts: NotificationGetOptions = {\n user: user,\n limit: 1,\n ids: [req.params.id],\n };\n const notifications = await store.getNotifications(opts);\n if (notifications.length !== 1) {\n throw new NotFoundError('Not found');\n }\n res.json(notifications[0]);\n };\n\n // Get topics\n const listTopicsHandler = async (req: Request, res: Response) => {\n const user = await getUser(req);\n const opts: TopicGetOptions = {\n user: user,\n };\n\n appendCommonOptions(req, opts);\n\n const topics = await store.getTopics(opts);\n res.json(topics);\n };\n\n router.get('/topics', listTopicsHandler);\n\n // Make sure this is the last \"GET\" handler\n router.get('/:id', getNotificationHandler); // Deprecated endpoint\n router.get('/notifications/:id', getNotificationHandler);\n\n const updateNotificationsHandler = async (req: Request, res: Response) => {\n const user = await getUser(req);\n const { ids, read, saved } = req.body;\n if (!ids || !Array.isArray(ids)) {\n throw new InputError();\n }\n\n if (read === true) {\n await store.markRead({ user, ids });\n\n if (signals) {\n await signals.publish<NotificationReadSignal>({\n recipients: { type: 'user', entityRef: [user] },\n message: { action: 'notification_read', notification_ids: ids },\n channel: 'notifications',\n });\n }\n } else if (read === false) {\n await store.markUnread({ user: user, ids });\n\n if (signals) {\n await signals.publish<NotificationReadSignal>({\n recipients: { type: 'user', entityRef: [user] },\n message: { action: 'notification_unread', notification_ids: ids },\n channel: 'notifications',\n });\n }\n }\n\n if (saved === true) {\n await store.markSaved({ user: user, ids });\n } else if (saved === false) {\n await store.markUnsaved({ user: user, ids });\n }\n\n const notifications = await store.getNotifications({ ids, user: user });\n res.json(notifications);\n };\n\n router.post('/update', updateNotificationsHandler); // Deprecated endpoint\n router.post('/notifications/update', updateNotificationsHandler);\n\n const sendBroadcastNotification = async (\n baseNotification: Omit<Notification, 'user' | 'id'>,\n opts: NotificationSendOptions,\n origin: string,\n ) => {\n const { scope } = opts.payload;\n const broadcastNotification = {\n ...baseNotification,\n user: null,\n id: uuid(),\n };\n const notification = await preProcessNotification(\n broadcastNotification,\n opts,\n );\n let existingNotification;\n if (scope) {\n existingNotification = await store.getExistingScopeBroadcast({\n scope,\n origin,\n });\n }\n\n let ret = notification;\n if (existingNotification) {\n const restored = await store.restoreExistingNotification({\n id: existingNotification.id,\n notification: { ...notification, user: '' },\n });\n ret = restored ?? notification;\n } else {\n await store.saveBroadcast(notification);\n }\n\n if (signals) {\n await signals.publish<NewNotificationSignal>({\n recipients: { type: 'broadcast' },\n message: {\n action: 'new_notification',\n notification_id: ret.id,\n },\n channel: 'notifications',\n });\n }\n postProcessNotification(ret, opts);\n return notification;\n };\n\n const sendUserNotification = async (\n baseNotification: Omit<Notification, 'user' | 'id'>,\n user: string,\n opts: NotificationSendOptions,\n origin: string,\n scope?: string,\n ): Promise<Notification | undefined> => {\n const userNotification = {\n ...baseNotification,\n id: uuid(),\n user,\n };\n const notification = await preProcessNotification(userNotification, opts);\n\n const enabled = await isNotificationsEnabled({\n user,\n channel: WEB_NOTIFICATION_CHANNEL,\n origin: userNotification.origin,\n topic: userNotification.payload.topic ?? null,\n });\n\n let ret = notification;\n\n if (!enabled) {\n postProcessNotification(ret, opts);\n return undefined;\n }\n\n let existingNotification;\n if (scope) {\n existingNotification = await store.getExistingScopeNotification({\n user,\n scope,\n origin,\n });\n }\n\n if (existingNotification) {\n const restored = await store.restoreExistingNotification({\n id: existingNotification.id,\n notification,\n });\n ret = restored ?? notification;\n } else {\n await store.saveNotification(notification);\n }\n\n if (signals) {\n await signals.publish<NewNotificationSignal>({\n recipients: { type: 'user', entityRef: [user] },\n message: {\n action: 'new_notification',\n notification_id: ret.id,\n },\n channel: 'notifications',\n });\n }\n postProcessNotification(ret, opts);\n return ret;\n };\n\n const filterNonUserEntityRefs = (refs: string[]): string[] => {\n return refs.filter(ref => {\n try {\n const parsed = parseEntityRef(ref);\n return parsed.kind.toLowerCase() === 'user';\n } catch {\n return false;\n }\n });\n };\n\n const sendUserNotifications = async (\n baseNotification: Omit<Notification, 'user' | 'id'>,\n users: string[],\n opts: NotificationSendOptions,\n origin: string,\n ): Promise<Notification[]> => {\n const { scope } = opts.payload;\n const uniqueUsers = [...new Set(filterNonUserEntityRefs(users))];\n const throttled = throttle((user: string) =>\n sendUserNotification(baseNotification, user, opts, origin, scope),\n );\n const sent = await Promise.all(uniqueUsers.map(user => throttled(user)));\n return sent.filter(n => n !== undefined);\n };\n\n const createNotificationHandler = async (\n req: Request<any, Notification[], NotificationSendOptions>,\n res: Response,\n ) => {\n const credentials = await httpAuth.credentials(req, {\n allow: ['service'],\n });\n\n const origin = credentials.principal.subject;\n const opts = await processOptions(req.body, origin);\n const { recipients, payload } = opts;\n const { title, link } = payload;\n const notifications: Notification[] = [];\n\n if (!recipients || !title) {\n const missing = [\n !title ? 'title' : null,\n !recipients ? 'recipients' : null,\n ].filter(Boolean);\n const err = `Invalid notification request received: missing ${missing.join(\n ', ',\n )}`;\n throw new InputError(err);\n }\n\n if (link) {\n try {\n validateLink(link);\n } catch (e) {\n throw new InputError('Invalid link provided', e);\n }\n }\n\n const baseNotification = {\n payload: {\n ...payload,\n severity: payload.severity ?? 'normal',\n },\n origin,\n created: new Date(),\n };\n\n if (recipients.type === 'broadcast') {\n const broadcast = await sendBroadcastNotification(\n baseNotification,\n opts,\n origin,\n );\n notifications.push(broadcast);\n } else if (recipients.type === 'entity') {\n const entityRefs = [recipients.entityRef].flat();\n const excludedEntityRefs = recipients.excludeEntityRef\n ? [recipients.excludeEntityRef].flat()\n : undefined;\n try {\n const { userEntityRefs } =\n await usedRecipientResolver.resolveNotificationRecipients({\n entityRefs,\n excludedEntityRefs,\n });\n const userNotifications = await sendUserNotifications(\n baseNotification,\n userEntityRefs,\n opts,\n origin,\n );\n notifications.push(...userNotifications);\n } catch (e) {\n throw new InputError('Failed to send user notifications', e);\n }\n } else {\n throw new InputError(\n `Invalid recipients type, please use either 'broadcast' or 'entity'`,\n );\n }\n\n res.json(notifications);\n };\n\n // Add new notification\n router.post('/', createNotificationHandler);\n router.post('/notifications', createNotificationHandler);\n\n return router;\n}\n"],"names":["config","durationToMilliseconds","readDurationFromConfig","pThrottle","DefaultNotificationRecipientResolver","isNotificationsEnabledFor","notificationSeverities","InputError","normalizeSeverity","Router","express","parseEntityOrderFieldParams","NotFoundError","uuid","parseEntityRef"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAwEA,eAAsB,aACpB,OAAA,EACyB;AACzB,EAAA,MAAM;AAAA,YACJA,QAAA;AAAA,IACA,MAAA;AAAA,IACA,KAAA;AAAA,IACA,IAAA;AAAA,IACA,QAAA;AAAA,IACA,QAAA;AAAA,IACA,OAAA;AAAA,IACA,aAAa,EAAC;AAAA,IACd,OAAA;AAAA,IACA;AAAA,GACF,GAAI,OAAA;AAEJ,EAAA,MAAM,wBAAA,GAA2B,KAAA;AACjC,EAAA,MAAM,eAAA,GAAkBA,QAAA,CAAO,SAAA,CAAU,aAAa,CAAA;AACtD,EAAA,MAAM,gBAAA,GACJA,QAAA,CAAO,iBAAA,CAAkB,gCAAgC,CAAA,IAAK,EAAA;AAChE,EAAA,MAAM,gBAAA,GAAmBA,QAAA,CAAO,GAAA,CAAI,gCAAgC,CAAA,GAChEC,4BAAA;AAAA,IACEC,8BAAuBF,QAAA,EAAQ;AAAA,MAC7B,GAAA,EAAK;AAAA,KACN;AAAA,GACH,GACA,EAAA;AACJ,EAAA,MAAM,WAAWG,0BAAA,CAAU;AAAA,IACzB,KAAA,EAAO,gBAAA;AAAA,IACP,QAAA,EAAU;AAAA,GACX,CAAA;AACD,EAAA,MAAM,2BAAA,GACJH,QAAA,CAAO,WAAA,CAAkC,+BAA+B,CAAA;AAE1E,EAAA,MAAM,qBAAA,GACJ,iBAAA,IACA,IAAII,yEAAA,CAAqC,MAAM,OAAO,CAAA;AAExD,EAAA,MAAM,OAAA,GAAU,OAAO,GAAA,KAA0B;AAC/C,IAAA,MAAM,WAAA,GAAc,MAAM,QAAA,CAAS,WAAA,CAAY,GAAA,EAAK,EAAE,KAAA,EAAO,CAAC,MAAM,CAAA,EAAG,CAAA;AACvE,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,WAAA,CAAY,WAAW,CAAA;AACnD,IAAA,OAAO,IAAA,CAAK,aAAA;AAAA,EACd,CAAA;AAEA,EAAA,MAAM,0BAA0B,MAAM;AACpC,IAAA,OAAO,CAAC,0BAA0B,GAAG,UAAA,CAAW,IAAI,CAAA,CAAA,KAAK,CAAA,CAAE,OAAA,EAAS,CAAC,CAAA;AAAA,EACvE,CAAA;AAEA,EAAA,MAAM,gBAAA,GAAmB,CACvB,KAAA,EACA,cAAA,EACA,uBACA,qBAAA,KACG;AACH,IAAA,MAAM,aAAA,GAAgB,gBAAgB,MAAA,EAAQ,IAAA;AAAA,MAC5C,OAAK,CAAA,CAAE,EAAA,CAAG,aAAY,KAAM,KAAA,CAAM,MAAM,WAAA;AAAY,KACtD;AACA,IAAA,MAAM,oBAAA,GAAuB,uBAAuB,MAAA,EAAQ,IAAA;AAAA,MAC1D,OAAK,CAAA,CAAE,EAAA,CAAG,aAAY,KAAM,KAAA,CAAM,MAAM,WAAA;AAAY,KACtD;AAKA,IAAA,OAAO;AAAA,MACL,IAAI,KAAA,CAAM,KAAA;AAAA,MACV,OAAA,EAAS,aAAA,GACL,aAAA,CAAc,OAAA,GACd,sBAAsB,OAAA,IAAW;AAAA,KACvC;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,oBAAoB,CACxB,QAAA,EACA,iBACA,sBAAA,EACA,MAAA,EACA,uBACA,yBAAA,KACG;AACH,IAAA,MAAM,cAAA,GAAiB,iBAAiB,OAAA,EAAS,IAAA;AAAA,MAC/C,OAAK,CAAA,CAAE,EAAA,CAAG,WAAA,EAAY,KAAM,SAAS,WAAA;AAAY,KACnD;AAEA,IAAA,MAAM,qBAAA,GAAwB,wBAAwB,OAAA,EAAS,IAAA;AAAA,MAC7D,OAAK,CAAA,CAAE,EAAA,CAAG,WAAA,EAAY,KAAM,SAAS,WAAA;AAAY,KACnD;AAEA,IAAA,MAAM,cAAA,GAAiB,cAAA,GACnB,cAAA,CAAe,OAAA,GACf,uBAAuB,OAAA,IAAW,qBAAA;AAEtC,IAAA,OAAO;AAAA,MACL,EAAA,EAAI,QAAA;AAAA,MACJ,OAAA,EAAS,cAAA;AAAA,MACT,QAAQ,MAAA,CACL,MAAA,CAAO,OAAK,CAAA,CAAE,MAAA,KAAW,QAAQ,CAAA,CACjC,GAAA;AAAA,QAAI,CAAA,CAAA,KACH,gBAAA;AAAA,UACE,CAAA;AAAA,UACA,cAAA;AAAA,UACA,qBAAA;AAAA,UACA,4BAA4B,qBAAA,GAAwB;AAAA;AACtD;AACF,KACJ;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,kBAAA,GAAqB,CACzB,SAAA,EACA,QAAA,EACA,SACA,MAAA,KACG;AACH,IAAA,MAAM,eAAA,GAAkB,SAAS,QAAA,CAAS,IAAA;AAAA,MACxC,OAAK,CAAA,CAAE,EAAA,CAAG,WAAA,EAAY,KAAM,UAAU,WAAA;AAAY,KACpD;AACA,IAAA,MAAM,sBAAA,GAAyB,6BAA6B,QAAA,EAAU,IAAA;AAAA,MACpE,OAAK,CAAA,CAAE,EAAA,CAAG,WAAA,EAAY,KAAM,UAAU,WAAA;AAAY,KACpD;AAGA,IAAA,MAAM,cAAA,GACJ,eAAA,EAAiB,OAAA,IAAW,sBAAA,EAAwB,OAAA;AAGtD,IAAA,MAAM,2BAA2B,cAAA,IAAkB,IAAA;AAGnD,IAAA,MAAM,yBAAA,GACJ,eAAA,EAAiB,OAAA,KAAY,MAAA,IAC7B,wBAAwB,OAAA,KAAY,MAAA;AAEtC,IAAA,OAAO;AAAA,MACL,EAAA,EAAI,SAAA;AAAA,MACJ,OAAA,EAAS,cAAA;AAAA,MACT,SAAS,OAAA,CAAQ,GAAA;AAAA,QAAI,CAAA,QAAA,KACnB,iBAAA;AAAA,UACE,QAAA;AAAA,UACA,eAAA;AAAA,UACA,sBAAA;AAAA,UACA,MAAA;AAAA,UACA,wBAAA;AAAA,UACA;AAAA;AACF;AACF,KACF;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,uBAAA,GAA0B,OAC9B,IAAA,KACkC;AAClC,IAAA,MAAM,EAAE,SAAQ,GAAI,MAAM,MAAM,0BAAA,CAA2B,EAAE,MAAM,CAAA;AACnE,IAAA,MAAM,EAAE,QAAO,GAAI,MAAM,MAAM,yBAAA,CAA0B,EAAE,MAAM,CAAA;AACjE,IAAA,MAAM,WAAW,MAAM,KAAA,CAAM,uBAAA,CAAwB,EAAE,MAAM,CAAA;AAC7D,IAAA,MAAM,WAAW,uBAAA,EAAwB;AAGzC,IAAA,KAAA,MAAW,OAAA,IAAW,2BAAA,EAA6B,QAAA,IAAY,EAAC,EAAG;AACjE,MAAA,IAAI,CAAC,QAAA,CAAS,QAAA,CAAS,OAAA,CAAQ,EAAE,CAAA,EAAG;AAClC,QAAA,QAAA,CAAS,IAAA,CAAK,QAAQ,EAAE,CAAA;AAAA,MAC1B;AAEA,MAAA,KAAA,MAAW,MAAA,IAAU,OAAA,CAAQ,OAAA,IAAW,EAAC,EAAG;AAC1C,QAAA,IAAI,CAAC,OAAA,CAAQ,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAAG;AAChC,UAAA,OAAA,CAAQ,IAAA,CAAK,OAAO,EAAE,CAAA;AAAA,QACxB;AAEA,QAAA,KAAA,MAAW,KAAA,IAAS,MAAA,CAAO,MAAA,IAAU,EAAC,EAAG;AACvC,UAAA,IACE,CAAC,MAAA,CAAO,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,MAAA,KAAW,MAAA,CAAO,EAAA,IAAM,CAAA,CAAE,KAAA,KAAU,KAAA,CAAM,EAAE,CAAA,EAChE;AACA,YAAA,MAAA,CAAO,IAAA,CAAK,EAAE,MAAA,EAAQ,MAAA,CAAO,IAAI,KAAA,EAAO,KAAA,CAAM,IAAI,CAAA;AAAA,UACpD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,IAAA,OAAO;AAAA,MACL,UAAU,QAAA,CAAS,GAAA;AAAA,QAAI,CAAA,SAAA,KACrB,kBAAA,CAAmB,SAAA,EAAW,QAAA,EAAU,SAAS,MAAM;AAAA;AACzD,KACF;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,sBAAA,GAAyB,OAAO,IAAA,KAKhC;AAEJ,IAAA,MAAM,YAAA,GAAe,MAAM,KAAA,CAAM,uBAAA,CAAwB;AAAA,MACvD,MAAM,IAAA,CAAK;AAAA,KACZ,CAAA;AAGD,IAAA,MAAM,QAAA,GAAiC;AAAA,MACrC,QAAA,EAAU;AAAA,QACR;AAAA,UACE,IAAI,IAAA,CAAK,OAAA;AAAA,UACT,OAAA,EAAS,6BAA6B,QAAA,EAAU,IAAA;AAAA,YAC9C,OAAK,CAAA,CAAE,EAAA,CAAG,aAAY,KAAM,IAAA,CAAK,QAAQ,WAAA;AAAY,WACvD,EAAG,OAAA;AAAA,UACH,SAAS;AAAC;AACZ;AACF,KACF;AAGA,IAAA,MAAM,WAAA,GAAc,aAAa,QAAA,CAAS,IAAA;AAAA,MACxC,OAAK,CAAA,CAAE,EAAA,CAAG,aAAY,KAAM,IAAA,CAAK,QAAQ,WAAA;AAAY,KACvD;AACA,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,QAAA,CAAS,QAAA,CAAS,CAAC,CAAA,GAAI;AAAA,QACrB,GAAG,QAAA,CAAS,QAAA,CAAS,CAAC,CAAA;AAAA,QACtB,SAAS,WAAA,CAAY,OAAA,IAAW,QAAA,CAAS,QAAA,CAAS,CAAC,CAAA,CAAE,OAAA;AAAA,QACrD,OAAA,EAAS,WAAA,CAAY,OAAA,IAAW;AAAC,OACnC;AAAA,IACF;AAIA,IAAA,MAAM,sBAAA,GAAyB,6BAA6B,QAAA,EAAU,IAAA;AAAA,MACpE,OAAK,CAAA,CAAE,EAAA,CAAG,aAAY,KAAM,IAAA,CAAK,QAAQ,WAAA;AAAY,KACvD;AACA,IAAA,IACE,wBAAwB,OAAA,IACxB,QAAA,CAAS,SAAS,CAAC,CAAA,CAAE,YAAY,KAAA,EACjC;AACA,MAAA,KAAA,MAAW,aAAA,IAAiB,uBAAuB,OAAA,EAAS;AAC1D,QAAA,IACE,CAAC,QAAA,CAAS,QAAA,CAAS,CAAC,EAAE,OAAA,CAAQ,IAAA;AAAA,UAC5B,OAAK,CAAA,CAAE,EAAA,CAAG,aAAY,KAAM,aAAA,CAAc,GAAG,WAAA;AAAY,SAC3D,EACA;AACA,UAAA,QAAA,CAAS,QAAA,CAAS,CAAC,CAAA,CAAE,OAAA,CAAQ,KAAK,aAAa,CAAA;AAAA,QACjD;AAAA,MACF;AAAA,IACF;AAEA,IAAA,OAAOC,mDAAA;AAAA,MACL,QAAA;AAAA,MACA,IAAA,CAAK,OAAA;AAAA,MACL,IAAA,CAAK,MAAA;AAAA,MACL,IAAA,CAAK;AAAA,KACP;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,gBAAA,GAAmB,OACvB,YAAA,KAGG;AACH,IAAA,MAAM,SAAkC,EAAC;AACzC,IAAA,MAAM,EAAE,OAAA,EAAS,IAAA,EAAM,MAAA,EAAO,GAAI,YAAA;AAElC,IAAA,KAAA,MAAW,aAAa,UAAA,EAAY;AAClC,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,MAAM,OAAA,GAAU,MAAM,sBAAA,CAAuB;AAAA,UAC3C,IAAA;AAAA,UACA,MAAA;AAAA,UACA,OAAA,EAAS,UAAU,OAAA,EAAQ;AAAA,UAC3B,KAAA,EAAO,QAAQ,KAAA,IAAS;AAAA,SACzB,CAAA;AACD,QAAA,IAAI,CAAC,OAAA,EAAS;AACZ,UAAA;AAAA,QACF;AAAA,MACF;AAEA,MAAA,IAAI,UAAU,sBAAA,EAAwB;AACpC,QAAA,MAAM,OAAA,GAAU,UAAU,sBAAA,EAAuB;AACjD,QAAA,IAAI,QAAQ,WAAA,EAAa;AACvB,UAAA,IACEC,gDAAA,CAAuB,OAAA,CAAQ,OAAA,CAAQ,QAAA,IAAY,QAAQ,IAC3DA,gDAAA,CAAuB,OAAA,CAAQ,OAAA,CAAQ,WAAW,CAAA,EAClD;AACA,YAAA;AAAA,UACF;AAAA,QACF;AAEA,QAAA,IAAI,QAAQ,WAAA,EAAa;AACvB,UAAA,IACEA,gDAAA,CAAuB,OAAA,CAAQ,OAAA,CAAQ,QAAA,IAAY,QAAQ,IAC3DA,gDAAA,CAAuB,OAAA,CAAQ,OAAA,CAAQ,WAAW,CAAA,EAClD;AACA,YAAA;AAAA,UACF;AAAA,QACF;AAEA,QAAA,IAAI,OAAA,CAAQ,cAAA,IAAkB,OAAA,CAAQ,KAAA,EAAO;AAC3C,UAAA,IAAI,OAAA,CAAQ,cAAA,CAAe,QAAA,CAAS,OAAA,CAAQ,KAAK,CAAA,EAAG;AAClD,YAAA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,MAAA,MAAA,CAAO,KAAK,SAAS,CAAA;AAAA,IACvB;AAEA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AAEA,EAAA,MAAM,cAAA,GAAiB,OACrB,IAAA,EACA,MAAA,KACqC;AACrC,IAAA,MAAM,QAAA,GAAW,MAAM,gBAAA,CAAiB,EAAE,GAAG,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAM,CAAA;AACvE,IAAA,IAAI,GAAA,GAAM,IAAA;AACV,IAAA,KAAA,MAAW,aAAa,QAAA,EAAU;AAChC,MAAA,IAAI;AACF,QAAA,GAAA,GAAM,UAAU,cAAA,GACZ,MAAM,SAAA,CAAU,cAAA,CAAe,GAAG,CAAA,GAClC,GAAA;AAAA,MACN,SAAS,CAAA,EAAG;AACV,QAAA,MAAA,CAAO,KAAA;AAAA,UACL,CAAA,iDAAA,EAAoD,SAAA,CAAU,OAAA,EAAS,KAAK,CAAC,CAAA;AAAA,SAC/E;AAAA,MACF;AAAA,IACF;AACA,IAAA,OAAO,GAAA;AAAA,EACT,CAAA;AAEA,EAAA,MAAM,sBAAA,GAAyB,OAC7B,YAAA,EACA,IAAA,KACG;AACH,IAAA,MAAM,QAAA,GAAW,MAAM,gBAAA,CAAiB,YAAY,CAAA;AACpD,IAAA,IAAI,GAAA,GAAM,YAAA;AACV,IAAA,KAAA,MAAW,aAAa,QAAA,EAAU;AAChC,MAAA,IAAI;AACF,QAAA,GAAA,GAAM,UAAU,UAAA,GACZ,MAAM,UAAU,UAAA,CAAW,GAAA,EAAK,IAAI,CAAA,GACpC,GAAA;AAAA,MACN,SAAS,CAAA,EAAG;AACV,QAAA,MAAA,CAAO,KAAA;AAAA,UACL,CAAA,6CAAA,EAAgD,SAAA,CAAU,OAAA,EAAS,KAAK,CAAC,CAAA;AAAA,SAC3E;AAAA,MACF;AAAA,IACF;AACA,IAAA,OAAO,GAAA;AAAA,EACT,CAAA;AAEA,EAAA,MAAM,uBAAA,GAA0B,OAC9B,YAAA,EACA,IAAA,KACG;AACH,IAAA,MAAM,QAAA,GAAW,MAAM,gBAAA,CAAiB,YAAY,CAAA;AACpD,IAAA,KAAA,MAAW,aAAa,QAAA,EAAU;AAChC,MAAA,IAAI,UAAU,WAAA,EAAa;AACzB,QAAA,IAAI;AACF,UAAA,MAAM,SAAA,CAAU,WAAA,CAAY,YAAA,EAAc,IAAI,CAAA;AAAA,QAChD,SAAS,CAAA,EAAG;AACV,UAAA,MAAA,CAAO,KAAA;AAAA,YACL,CAAA,8CAAA,EAAiD,SAAA,CAAU,OAAA,EAAS,KAAK,CAAC,CAAA;AAAA,WAC5E;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,YAAA,GAAe,CAAC,IAAA,KAAiB;AACrC,IAAA,MAAM,oBAAoB,CAAC,CAAA,KAAc,CAAA,CAAE,OAAA,CAAQ,OAAO,EAAE,CAAA;AAC5D,IAAA,MAAM,sBAAsB,CAAC,CAAA,KAAc,CAAA,CAAE,OAAA,CAAQ,QAAQ,GAAG,CAAA;AAChE,IAAA,MAAM,MAAM,IAAI,GAAA;AAAA,MACd,kBAAkB,IAAI,CAAA;AAAA,MACtB,oBAAoB,eAAe;AAAA,KACrC;AACA,IAAA,IAAI,GAAA,CAAI,QAAA,KAAa,QAAA,IAAY,GAAA,CAAI,aAAa,OAAA,EAAS;AACzD,MAAA,MAAM,IAAI,MAAM,mCAAmC,CAAA;AAAA,IACrD;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,mBAAA,GAAsB,CAC1B,GAAA,EACA,IAAA,KACG;AACH,IAAA,IAAI,GAAA,CAAI,MAAM,MAAA,EAAQ;AACpB,MAAA,IAAA,CAAK,MAAA,GAAS,GAAA,CAAI,KAAA,CAAM,MAAA,CAAO,QAAA,EAAS;AAAA,IAC1C;AACA,IAAA,IAAI,GAAA,CAAI,KAAA,CAAM,IAAA,KAAS,MAAA,EAAQ;AAC7B,MAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,IACd,CAAA,MAAA,IAAW,GAAA,CAAI,KAAA,CAAM,IAAA,KAAS,OAAA,EAAS;AACrC,MAAA,IAAA,CAAK,IAAA,GAAO,KAAA;AAAA,IAEd;AAEA,IAAA,IAAI,GAAA,CAAI,KAAA,CAAM,KAAA,KAAU,MAAA,EAAQ;AAC9B,MAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AAAA,IACf,CAAA,MAAA,IAAW,GAAA,CAAI,KAAA,CAAM,KAAA,KAAU,OAAA,EAAS;AACtC,MAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AAAA,IAEf;AACA,IAAA,IAAI,GAAA,CAAI,MAAM,YAAA,EAAc;AAC1B,MAAA,MAAM,aAAa,IAAA,CAAK,KAAA,CAAM,OAAO,GAAA,CAAI,KAAA,CAAM,YAAY,CAAC,CAAA;AAC5D,MAAA,IAAI,KAAA,CAAM,UAAU,CAAA,EAAG;AACrB,QAAA,MAAM,IAAIC,kBAAW,wBAAwB,CAAA;AAAA,MAC/C;AACA,MAAA,IAAA,CAAK,YAAA,GAAe,IAAI,IAAA,CAAK,UAAU,CAAA;AAAA,IACzC;AACA,IAAA,IAAI,GAAA,CAAI,MAAM,eAAA,EAAiB;AAC7B,MAAA,IAAA,CAAK,eAAA,GAAkBC,4CAAA;AAAA,QACrB,GAAA,CAAI,KAAA,CAAM,eAAA,CAAgB,QAAA;AAAS,OACrC;AAAA,IACF;AAAA,EACF,CAAA;AAGA,EAAA,MAAM,SAASC,uBAAA,EAAO;AACtB,EAAA,MAAA,CAAO,GAAA,CAAIC,wBAAA,CAAQ,IAAA,EAAM,CAAA;AAEzB,EAAA,MAAM,wBAAA,GAA2B,OAAO,GAAA,EAAc,GAAA,KAAkB;AACtE,IAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,GAAG,CAAA;AAC9B,IAAA,MAAM,IAAA,GAA+B;AAAA,MACnC;AAAA,KACF;AACA,IAAA,IAAI,GAAA,CAAI,MAAM,MAAA,EAAQ;AACpB,MAAA,IAAA,CAAK,MAAA,GAAS,OAAO,QAAA,CAAS,GAAA,CAAI,MAAM,MAAA,CAAO,QAAA,IAAY,EAAE,CAAA;AAAA,IAC/D;AACA,IAAA,IAAI,GAAA,CAAI,MAAM,KAAA,EAAO;AACnB,MAAA,IAAA,CAAK,KAAA,GAAQ,OAAO,QAAA,CAAS,GAAA,CAAI,MAAM,KAAA,CAAM,QAAA,IAAY,EAAE,CAAA;AAAA,IAC7D;AACA,IAAA,IAAI,GAAA,CAAI,MAAM,UAAA,EAAY;AACxB,MAAA,IAAA,CAAK,UAAA,GAAaC,uDAAA,CAA4B,GAAA,CAAI,KAAK,CAAA;AAAA,IACzD;AAEA,IAAA,IAAI,GAAA,CAAI,MAAM,KAAA,EAAO;AACnB,MAAA,IAAA,CAAK,KAAA,GAAQ,GAAA,CAAI,KAAA,CAAM,KAAA,CAAM,QAAA,EAAS;AAAA,IACxC;AAEA,IAAA,mBAAA,CAAoB,KAAK,IAAI,CAAA;AAE7B,IAAA,MAAM,CAAC,aAAA,EAAe,UAAU,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,MACpD,KAAA,CAAM,iBAAiB,IAAI,CAAA;AAAA,MAC3B,KAAA,CAAM,sBAAsB,IAAI;AAAA,KACjC,CAAA;AACD,IAAA,GAAA,CAAI,IAAA,CAAK;AAAA,MACP,UAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,MAAA,CAAO,GAAA,CAAI,KAAK,wBAAwB,CAAA;AACxC,EAAA,MAAA,CAAO,GAAA,CAAI,kBAAkB,wBAAwB,CAAA;AAErD,EAAA,MAAA,CAAO,GAAA,CAAI,SAAA,EAAW,OAAO,GAAA,EAAuC,GAAA,KAAQ;AAC1E,IAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,GAAG,CAAA;AAC9B,IAAA,MAAM,SAAS,MAAM,KAAA,CAAM,SAAA,CAAU,EAAE,MAAM,CAAA;AAC7C,IAAA,GAAA,CAAI,KAAK,MAAM,CAAA;AAAA,EACjB,CAAC,CAAA;AAED,EAAA,MAAA,CAAO,GAAA;AAAA,IACL,WAAA;AAAA,IACA,OAAO,KAAyC,GAAA,KAAQ;AACtD,MAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,GAAG,CAAA;AAC9B,MAAA,MAAM,QAAA,GAAW,MAAM,uBAAA,CAAwB,IAAI,CAAA;AACnD,MAAA,GAAA,CAAI,KAAK,QAAQ,CAAA;AAAA,IACnB;AAAA,GACF;AAEA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,WAAA;AAAA,IACA,OACE,KACA,GAAA,KACG;AACH,MAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,GAAG,CAAA;AAC9B,MAAA,MAAM,WAAW,uBAAA,EAAwB;AACzC,MAAA,MAAM,WAAiC,GAAA,CAAI,IAAA;AAC3C,MAAA,IAAI,QAAA,CAAS,QAAA,CAAS,IAAA,CAAK,CAAA,CAAA,KAAK,CAAC,SAAS,QAAA,CAAS,CAAA,CAAE,EAAE,CAAC,CAAA,EAAG;AACzD,QAAA,MAAM,IAAIJ,kBAAW,iBAAiB,CAAA;AAAA,MACxC;AACA,MAAA,MAAM,KAAA,CAAM,wBAAA,CAAyB,EAAE,IAAA,EAAM,UAAU,CAAA;AACvD,MAAA,MAAM,QAAA,GAAW,MAAM,uBAAA,CAAwB,IAAI,CAAA;AACnD,MAAA,GAAA,CAAI,KAAK,QAAQ,CAAA;AAAA,IACnB;AAAA,GACF;AAEA,EAAA,MAAM,sBAAA,GAAyB,OAAO,GAAA,EAAc,GAAA,KAAkB;AACpE,IAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,GAAG,CAAA;AAC9B,IAAA,MAAM,IAAA,GAA+B;AAAA,MACnC,IAAA;AAAA,MACA,KAAA,EAAO,CAAA;AAAA,MACP,GAAA,EAAK,CAAC,GAAA,CAAI,MAAA,CAAO,EAAE;AAAA,KACrB;AACA,IAAA,MAAM,aAAA,GAAgB,MAAM,KAAA,CAAM,gBAAA,CAAiB,IAAI,CAAA;AACvD,IAAA,IAAI,aAAA,CAAc,WAAW,CAAA,EAAG;AAC9B,MAAA,MAAM,IAAIK,qBAAc,WAAW,CAAA;AAAA,IACrC;AACA,IAAA,GAAA,CAAI,IAAA,CAAK,aAAA,CAAc,CAAC,CAAC,CAAA;AAAA,EAC3B,CAAA;AAGA,EAAA,MAAM,iBAAA,GAAoB,OAAO,GAAA,EAAc,GAAA,KAAkB;AAC/D,IAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,GAAG,CAAA;AAC9B,IAAA,MAAM,IAAA,GAAwB;AAAA,MAC5B;AAAA,KACF;AAEA,IAAA,mBAAA,CAAoB,KAAK,IAAI,CAAA;AAE7B,IAAA,MAAM,MAAA,GAAS,MAAM,KAAA,CAAM,SAAA,CAAU,IAAI,CAAA;AACzC,IAAA,GAAA,CAAI,KAAK,MAAM,CAAA;AAAA,EACjB,CAAA;AAEA,EAAA,MAAA,CAAO,GAAA,CAAI,WAAW,iBAAiB,CAAA;AAGvC,EAAA,MAAA,CAAO,GAAA,CAAI,QAAQ,sBAAsB,CAAA;AACzC,EAAA,MAAA,CAAO,GAAA,CAAI,sBAAsB,sBAAsB,CAAA;AAEvD,EAAA,MAAM,0BAAA,GAA6B,OAAO,GAAA,EAAc,GAAA,KAAkB;AACxE,IAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,GAAG,CAAA;AAC9B,IAAA,MAAM,EAAE,GAAA,EAAK,IAAA,EAAM,KAAA,KAAU,GAAA,CAAI,IAAA;AACjC,IAAA,IAAI,CAAC,GAAA,IAAO,CAAC,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,EAAG;AAC/B,MAAA,MAAM,IAAIL,iBAAA,EAAW;AAAA,IACvB;AAEA,IAAA,IAAI,SAAS,IAAA,EAAM;AACjB,MAAA,MAAM,KAAA,CAAM,QAAA,CAAS,EAAE,IAAA,EAAM,KAAK,CAAA;AAElC,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,MAAM,QAAQ,OAAA,CAAgC;AAAA,UAC5C,YAAY,EAAE,IAAA,EAAM,QAAQ,SAAA,EAAW,CAAC,IAAI,CAAA,EAAE;AAAA,UAC9C,OAAA,EAAS,EAAE,MAAA,EAAQ,mBAAA,EAAqB,kBAAkB,GAAA,EAAI;AAAA,UAC9D,OAAA,EAAS;AAAA,SACV,CAAA;AAAA,MACH;AAAA,IACF,CAAA,MAAA,IAAW,SAAS,KAAA,EAAO;AACzB,MAAA,MAAM,KAAA,CAAM,UAAA,CAAW,EAAE,IAAA,EAAY,KAAK,CAAA;AAE1C,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,MAAM,QAAQ,OAAA,CAAgC;AAAA,UAC5C,YAAY,EAAE,IAAA,EAAM,QAAQ,SAAA,EAAW,CAAC,IAAI,CAAA,EAAE;AAAA,UAC9C,OAAA,EAAS,EAAE,MAAA,EAAQ,qBAAA,EAAuB,kBAAkB,GAAA,EAAI;AAAA,UAChE,OAAA,EAAS;AAAA,SACV,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,IAAI,UAAU,IAAA,EAAM;AAClB,MAAA,MAAM,KAAA,CAAM,SAAA,CAAU,EAAE,IAAA,EAAY,KAAK,CAAA;AAAA,IAC3C,CAAA,MAAA,IAAW,UAAU,KAAA,EAAO;AAC1B,MAAA,MAAM,KAAA,CAAM,WAAA,CAAY,EAAE,IAAA,EAAY,KAAK,CAAA;AAAA,IAC7C;AAEA,IAAA,MAAM,gBAAgB,MAAM,KAAA,CAAM,iBAAiB,EAAE,GAAA,EAAK,MAAY,CAAA;AACtE,IAAA,GAAA,CAAI,KAAK,aAAa,CAAA;AAAA,EACxB,CAAA;AAEA,EAAA,MAAA,CAAO,IAAA,CAAK,WAAW,0BAA0B,CAAA;AACjD,EAAA,MAAA,CAAO,IAAA,CAAK,yBAAyB,0BAA0B,CAAA;AAE/D,EAAA,MAAM,yBAAA,GAA4B,OAChC,gBAAA,EACA,IAAA,EACA,MAAA,KACG;AACH,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,IAAA,CAAK,OAAA;AACvB,IAAA,MAAM,qBAAA,GAAwB;AAAA,MAC5B,GAAG,gBAAA;AAAA,MACH,IAAA,EAAM,IAAA;AAAA,MACN,IAAIM,OAAA;AAAK,KACX;AACA,IAAA,MAAM,eAAe,MAAM,sBAAA;AAAA,MACzB,qBAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,IAAI,oBAAA;AACJ,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,oBAAA,GAAuB,MAAM,MAAM,yBAAA,CAA0B;AAAA,QAC3D,KAAA;AAAA,QACA;AAAA,OACD,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,GAAA,GAAM,YAAA;AACV,IAAA,IAAI,oBAAA,EAAsB;AACxB,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,2BAAA,CAA4B;AAAA,QACvD,IAAI,oBAAA,CAAqB,EAAA;AAAA,QACzB,YAAA,EAAc,EAAE,GAAG,YAAA,EAAc,MAAM,EAAA;AAAG,OAC3C,CAAA;AACD,MAAA,GAAA,GAAM,QAAA,IAAY,YAAA;AAAA,IACpB,CAAA,MAAO;AACL,MAAA,MAAM,KAAA,CAAM,cAAc,YAAY,CAAA;AAAA,IACxC;AAEA,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,MAAM,QAAQ,OAAA,CAA+B;AAAA,QAC3C,UAAA,EAAY,EAAE,IAAA,EAAM,WAAA,EAAY;AAAA,QAChC,OAAA,EAAS;AAAA,UACP,MAAA,EAAQ,kBAAA;AAAA,UACR,iBAAiB,GAAA,CAAI;AAAA,SACvB;AAAA,QACA,OAAA,EAAS;AAAA,OACV,CAAA;AAAA,IACH;AACA,IAAA,uBAAA,CAAwB,KAAK,IAAI,CAAA;AACjC,IAAA,OAAO,YAAA;AAAA,EACT,CAAA;AAEA,EAAA,MAAM,uBAAuB,OAC3B,gBAAA,EACA,IAAA,EACA,IAAA,EACA,QACA,KAAA,KACsC;AACtC,IAAA,MAAM,gBAAA,GAAmB;AAAA,MACvB,GAAG,gBAAA;AAAA,MACH,IAAIA,OAAA,EAAK;AAAA,MACT;AAAA,KACF;AACA,IAAA,MAAM,YAAA,GAAe,MAAM,sBAAA,CAAuB,gBAAA,EAAkB,IAAI,CAAA;AAExE,IAAA,MAAM,OAAA,GAAU,MAAM,sBAAA,CAAuB;AAAA,MAC3C,IAAA;AAAA,MACA,OAAA,EAAS,wBAAA;AAAA,MACT,QAAQ,gBAAA,CAAiB,MAAA;AAAA,MACzB,KAAA,EAAO,gBAAA,CAAiB,OAAA,CAAQ,KAAA,IAAS;AAAA,KAC1C,CAAA;AAED,IAAA,IAAI,GAAA,GAAM,YAAA;AAEV,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,uBAAA,CAAwB,KAAK,IAAI,CAAA;AACjC,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,IAAI,oBAAA;AACJ,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,oBAAA,GAAuB,MAAM,MAAM,4BAAA,CAA6B;AAAA,QAC9D,IAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA,OACD,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,oBAAA,EAAsB;AACxB,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,2BAAA,CAA4B;AAAA,QACvD,IAAI,oBAAA,CAAqB,EAAA;AAAA,QACzB;AAAA,OACD,CAAA;AACD,MAAA,GAAA,GAAM,QAAA,IAAY,YAAA;AAAA,IACpB,CAAA,MAAO;AACL,MAAA,MAAM,KAAA,CAAM,iBAAiB,YAAY,CAAA;AAAA,IAC3C;AAEA,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,MAAM,QAAQ,OAAA,CAA+B;AAAA,QAC3C,YAAY,EAAE,IAAA,EAAM,QAAQ,SAAA,EAAW,CAAC,IAAI,CAAA,EAAE;AAAA,QAC9C,OAAA,EAAS;AAAA,UACP,MAAA,EAAQ,kBAAA;AAAA,UACR,iBAAiB,GAAA,CAAI;AAAA,SACvB;AAAA,QACA,OAAA,EAAS;AAAA,OACV,CAAA;AAAA,IACH;AACA,IAAA,uBAAA,CAAwB,KAAK,IAAI,CAAA;AACjC,IAAA,OAAO,GAAA;AAAA,EACT,CAAA;AAEA,EAAA,MAAM,uBAAA,GAA0B,CAAC,IAAA,KAA6B;AAC5D,IAAA,OAAO,IAAA,CAAK,OAAO,CAAA,GAAA,KAAO;AACxB,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,GAASC,4BAAe,GAAG,CAAA;AACjC,QAAA,OAAO,MAAA,CAAO,IAAA,CAAK,WAAA,EAAY,KAAM,MAAA;AAAA,MACvC,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,KAAA;AAAA,MACT;AAAA,IACF,CAAC,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,MAAM,qBAAA,GAAwB,OAC5B,gBAAA,EACA,KAAA,EACA,MACA,MAAA,KAC4B;AAC5B,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,IAAA,CAAK,OAAA;AACvB,IAAA,MAAM,WAAA,GAAc,CAAC,GAAG,IAAI,IAAI,uBAAA,CAAwB,KAAK,CAAC,CAAC,CAAA;AAC/D,IAAA,MAAM,SAAA,GAAY,QAAA;AAAA,MAAS,CAAC,IAAA,KAC1B,oBAAA,CAAqB,kBAAkB,IAAA,EAAM,IAAA,EAAM,QAAQ,KAAK;AAAA,KAClE;AACA,IAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,GAAA,CAAI,WAAA,CAAY,IAAI,CAAA,IAAA,KAAQ,SAAA,CAAU,IAAI,CAAC,CAAC,CAAA;AACvE,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,KAAM,MAAS,CAAA;AAAA,EACzC,CAAA;AAEA,EAAA,MAAM,yBAAA,GAA4B,OAChC,GAAA,EACA,GAAA,KACG;AACH,IAAA,MAAM,WAAA,GAAc,MAAM,QAAA,CAAS,WAAA,CAAY,GAAA,EAAK;AAAA,MAClD,KAAA,EAAO,CAAC,SAAS;AAAA,KAClB,CAAA;AAED,IAAA,MAAM,MAAA,GAAS,YAAY,SAAA,CAAU,OAAA;AACrC,IAAA,MAAM,IAAA,GAAO,MAAM,cAAA,CAAe,GAAA,CAAI,MAAM,MAAM,CAAA;AAClD,IAAA,MAAM,EAAE,UAAA,EAAY,OAAA,EAAQ,GAAI,IAAA;AAChC,IAAA,MAAM,EAAE,KAAA,EAAO,IAAA,EAAK,GAAI,OAAA;AACxB,IAAA,MAAM,gBAAgC,EAAC;AAEvC,IAAA,IAAI,CAAC,UAAA,IAAc,CAAC,KAAA,EAAO;AACzB,MAAA,MAAM,OAAA,GAAU;AAAA,QACd,CAAC,QAAQ,OAAA,GAAU,IAAA;AAAA,QACnB,CAAC,aAAa,YAAA,GAAe;AAAA,OAC/B,CAAE,OAAO,OAAO,CAAA;AAChB,MAAA,MAAM,GAAA,GAAM,kDAAkD,OAAA,CAAQ,IAAA;AAAA,QACpE;AAAA,OACD,CAAA,CAAA;AACD,MAAA,MAAM,IAAIP,kBAAW,GAAG,CAAA;AAAA,IAC1B;AAEA,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,IAAI;AACF,QAAA,YAAA,CAAa,IAAI,CAAA;AAAA,MACnB,SAAS,CAAA,EAAG;AACV,QAAA,MAAM,IAAIA,iBAAA,CAAW,uBAAA,EAAyB,CAAC,CAAA;AAAA,MACjD;AAAA,IACF;AAEA,IAAA,MAAM,gBAAA,GAAmB;AAAA,MACvB,OAAA,EAAS;AAAA,QACP,GAAG,OAAA;AAAA,QACH,QAAA,EAAU,QAAQ,QAAA,IAAY;AAAA,OAChC;AAAA,MACA,MAAA;AAAA,MACA,OAAA,sBAAa,IAAA;AAAK,KACpB;AAEA,IAAA,IAAI,UAAA,CAAW,SAAS,WAAA,EAAa;AACnC,MAAA,MAAM,YAAY,MAAM,yBAAA;AAAA,QACtB,gBAAA;AAAA,QACA,IAAA;AAAA,QACA;AAAA,OACF;AACA,MAAA,aAAA,CAAc,KAAK,SAAS,CAAA;AAAA,IAC9B,CAAA,MAAA,IAAW,UAAA,CAAW,IAAA,KAAS,QAAA,EAAU;AACvC,MAAA,MAAM,UAAA,GAAa,CAAC,UAAA,CAAW,SAAS,EAAE,IAAA,EAAK;AAC/C,MAAA,MAAM,kBAAA,GAAqB,WAAW,gBAAA,GAClC,CAAC,WAAW,gBAAgB,CAAA,CAAE,MAAK,GACnC,MAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAM,EAAE,cAAA,EAAe,GACrB,MAAM,sBAAsB,6BAAA,CAA8B;AAAA,UACxD,UAAA;AAAA,UACA;AAAA,SACD,CAAA;AACH,QAAA,MAAM,oBAAoB,MAAM,qBAAA;AAAA,UAC9B,gBAAA;AAAA,UACA,cAAA;AAAA,UACA,IAAA;AAAA,UACA;AAAA,SACF;AACA,QAAA,aAAA,CAAc,IAAA,CAAK,GAAG,iBAAiB,CAAA;AAAA,MACzC,SAAS,CAAA,EAAG;AACV,QAAA,MAAM,IAAIA,iBAAA,CAAW,mCAAA,EAAqC,CAAC,CAAA;AAAA,MAC7D;AAAA,IACF,CAAA,MAAO;AACL,MAAA,MAAM,IAAIA,iBAAA;AAAA,QACR,CAAA,kEAAA;AAAA,OACF;AAAA,IACF;AAEA,IAAA,GAAA,CAAI,KAAK,aAAa,CAAA;AAAA,EACxB,CAAA;AAGA,EAAA,MAAA,CAAO,IAAA,CAAK,KAAK,yBAAyB,CAAA;AAC1C,EAAA,MAAA,CAAO,IAAA,CAAK,kBAAkB,yBAAyB,CAAA;AAEvD,EAAA,OAAO,MAAA;AACT;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-notifications-backend",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"backstage": {
|
|
5
5
|
"role": "backend-plugin",
|
|
6
6
|
"pluginId": "notifications",
|
|
@@ -42,15 +42,15 @@
|
|
|
42
42
|
"test": "backstage-cli package test"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@backstage/backend-plugin-api": "1.5.0
|
|
46
|
-
"@backstage/catalog-model": "1.7.6
|
|
47
|
-
"@backstage/config": "1.3.6
|
|
48
|
-
"@backstage/errors": "1.2.7",
|
|
49
|
-
"@backstage/plugin-catalog-node": "1.20.0
|
|
50
|
-
"@backstage/plugin-notifications-common": "0.
|
|
51
|
-
"@backstage/plugin-notifications-node": "0.2.21
|
|
52
|
-
"@backstage/plugin-signals-node": "0.1.26
|
|
53
|
-
"@backstage/types": "1.2.2",
|
|
45
|
+
"@backstage/backend-plugin-api": "^1.5.0",
|
|
46
|
+
"@backstage/catalog-model": "^1.7.6",
|
|
47
|
+
"@backstage/config": "^1.3.6",
|
|
48
|
+
"@backstage/errors": "^1.2.7",
|
|
49
|
+
"@backstage/plugin-catalog-node": "^1.20.0",
|
|
50
|
+
"@backstage/plugin-notifications-common": "^0.2.0",
|
|
51
|
+
"@backstage/plugin-notifications-node": "^0.2.21",
|
|
52
|
+
"@backstage/plugin-signals-node": "^0.1.26",
|
|
53
|
+
"@backstage/types": "^1.2.2",
|
|
54
54
|
"express": "^4.17.1",
|
|
55
55
|
"express-promise-router": "^4.1.0",
|
|
56
56
|
"knex": "^3.0.0",
|
|
@@ -58,13 +58,13 @@
|
|
|
58
58
|
"uuid": "^11.0.0"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
|
-
"@backstage/backend-defaults": "0.13.1
|
|
62
|
-
"@backstage/backend-test-utils": "1.10.0
|
|
63
|
-
"@backstage/cli": "0.34.5
|
|
64
|
-
"@backstage/plugin-auth-backend": "0.25.6
|
|
65
|
-
"@backstage/plugin-auth-backend-module-guest-provider": "0.2.14
|
|
66
|
-
"@backstage/plugin-events-backend": "0.5.8
|
|
67
|
-
"@backstage/plugin-signals-backend": "0.3.10
|
|
61
|
+
"@backstage/backend-defaults": "^0.13.1",
|
|
62
|
+
"@backstage/backend-test-utils": "^1.10.0",
|
|
63
|
+
"@backstage/cli": "^0.34.5",
|
|
64
|
+
"@backstage/plugin-auth-backend": "^0.25.6",
|
|
65
|
+
"@backstage/plugin-auth-backend-module-guest-provider": "^0.2.14",
|
|
66
|
+
"@backstage/plugin-events-backend": "^0.5.8",
|
|
67
|
+
"@backstage/plugin-signals-backend": "^0.3.10",
|
|
68
68
|
"@types/express": "^4.17.6",
|
|
69
69
|
"@types/supertest": "^2.0.8",
|
|
70
70
|
"supertest": "^7.0.0"
|