@backstage/plugin-events-backend 0.2.21 → 0.3.0-next.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 CHANGED
@@ -1,22 +1,82 @@
1
1
  # @backstage/plugin-events-backend
2
2
 
3
- ## 0.2.21
3
+ ## 0.3.0-next.0
4
4
 
5
- ### Patch Changes
5
+ ### Minor Changes
6
6
 
7
- - Updated dependencies
8
- - @backstage/backend-common@0.21.2
9
- - @backstage/backend-plugin-api@0.6.12
10
- - @backstage/plugin-events-node@0.2.21
7
+ - c4bd794: BREAKING CHANGE: Migrate `HttpPostIngressEventPublisher` and `eventsPlugin` to use `EventsService`.
11
8
 
12
- ## 0.2.20
9
+ Uses the `EventsService` instead of `EventBroker` at `HttpPostIngressEventPublisher`,
10
+ dropping the use of `EventPublisher` including `setEventBroker(..)`.
11
+
12
+ Now, `HttpPostIngressEventPublisher.fromConfig` requires `events: EventsService` as option.
13
+
14
+ ```diff
15
+ const http = HttpPostIngressEventPublisher.fromConfig({
16
+ config: env.config,
17
+ + events: env.events,
18
+ logger: env.logger,
19
+ });
20
+ http.bind(eventsRouter);
21
+
22
+ // e.g. at packages/backend/src/plugins/events.ts
23
+ - await new EventsBackend(env.logger)
24
+ - .setEventBroker(env.eventBroker)
25
+ - .addPublishers(http)
26
+ - .start();
27
+
28
+ // or for other kinds of setups
29
+ - await Promise.all(http.map(publisher => publisher.setEventBroker(eventBroker)));
30
+ ```
31
+
32
+ `eventsPlugin` uses the `eventsServiceRef` as dependency.
33
+ Unsupported (and deprecated) extension point methods will throw an error to prevent unintended behavior.
34
+
35
+ ```ts
36
+ import { eventsServiceRef } from '@backstage/plugin-events-node';
37
+ ```
13
38
 
14
39
  ### Patch Changes
15
40
 
41
+ - 56969b6: Add new `EventsService` as well as `eventsServiceRef` for the new backend system.
42
+
43
+ **Summary:**
44
+
45
+ - new:
46
+ `EventsService`, `eventsServiceRef`, `TestEventsService`
47
+ - deprecated:
48
+ `EventBroker`, `EventPublisher`, `EventSubscriber`, `DefaultEventBroker`, `EventsBackend`,
49
+ most parts of `EventsExtensionPoint` (alpha),
50
+ `TestEventBroker`, `TestEventPublisher`, `TestEventSubscriber`
51
+
52
+ Add the `eventsServiceRef` as dependency to your backend plugins
53
+ or backend plugin modules.
54
+
55
+ **Details:**
56
+
57
+ The previous implementation using the `EventsExtensionPoint` was added in the early stages
58
+ of the new backend system and does not respect the plugin isolation.
59
+ This made it not compatible anymore with the new backend system.
60
+
61
+ Additionally, the previous interfaces had some room for simplification,
62
+ supporting less exposure of internal concerns as well.
63
+
64
+ Hereby, this change adds a new `EventsService` interface as replacement for the now deprecated `EventBroker`.
65
+ The new interface does not require any `EventPublisher` or `EventSubscriber` interfaces anymore.
66
+ Instead, it is expected that the `EventsService` gets passed into publishers and subscribers,
67
+ and used internally. There is no need to expose anything of that at their own interfaces.
68
+
69
+ Most parts of `EventsExtensionPoint` (alpha) are deprecated as well and were not usable
70
+ (by other plugins or their modules) anyway.
71
+
72
+ The `DefaultEventBroker` implementation is deprecated and wraps the new `DefaultEventsService` implementation.
73
+ Optionally, an instance can be passed as argument to allow mixed setups to operate alongside.
74
+
16
75
  - Updated dependencies
17
- - @backstage/backend-common@0.21.1
18
- - @backstage/backend-plugin-api@0.6.11
19
- - @backstage/plugin-events-node@0.2.20
76
+ - @backstage/plugin-events-node@0.3.0-next.0
77
+ - @backstage/backend-common@0.21.3-next.0
78
+ - @backstage/backend-plugin-api@0.6.13-next.0
79
+ - @backstage/config@1.1.2-next.0
20
80
 
21
81
  ## 0.2.19
22
82
 
package/README.md CHANGED
@@ -1,137 +1,84 @@
1
- # events-backend
1
+ # `@backstage/plugin-events-backend`
2
2
 
3
3
  Welcome to the events-backend backend plugin!
4
4
 
5
- This plugin provides the wiring of all extension points
6
- for managing events as defined by [plugin-events-node](../events-node)
7
- including backend plugin `EventsPlugin` and `EventsBackend`.
8
-
9
- Additionally, it uses a simple in-process implementation for
10
- the `EventBroker` by default which you can replace with a more sophisticated
11
- implementation of your choice as you need (e.g., via module).
12
-
13
- Some of these (non-exhaustive) may provide added persistence,
14
- or use external systems like AWS EventBridge, AWS SNS, Kafka, etc.
5
+ This package is based on [events-node](../events-node) and its `eventsServiceRef`
6
+ that is at the core of the event support.
7
+ It provides an `eventsPlugin` (exported as `default`).
15
8
 
16
9
  By default, the plugin ships with support to receive events via HTTP endpoints
17
- `POST /api/events/http/{topic}` and will publish these
18
- to the used event broker.
10
+ `POST /api/events/http/{topic}` and will publish these to the `EventsService`.
11
+
12
+ HTTP ingresses can be enabled by config, or using the extension point
13
+ of the `eventsPlugin`.
14
+ Additionally, the latter allows to add a request validator
15
+ (e.g., signature verification).
19
16
 
20
17
  ## Installation
21
18
 
22
19
  ```bash
23
20
  # From your Backstage root directory
24
- yarn --cwd packages/backend add @backstage/plugin-events-backend @backstage/plugin-events-node
21
+ yarn --cwd packages/backend add @backstage/plugin-events-backend
25
22
  ```
26
23
 
27
- ### Add to backend
28
-
29
- ```ts title="packages/backend/src/index.ts"
30
- backend.add(import('@backstage/plugin-events-backend/alpha'));
31
- ```
32
-
33
- ### Add to backend (old)
34
-
35
- #### Event Broker
36
-
37
- First you will need to add and implementation of the `EventBroker` interface to the backend plugin environment.
38
- This will allow event broker instance any backend plugins to publish and subscribe to events in order to communicate
39
- between them.
40
-
41
- Add the following to `makeCreateEnv`
42
-
43
- ```diff
24
+ ```ts
44
25
  // packages/backend/src/index.ts
45
- + import { DefaultEventBroker } from '@backstage/plugin-events-backend';
46
- + const eventBroker = new DefaultEventBroker(root.child({ type: 'plugin' }));
47
- ```
48
-
49
- Then update plugin environment to include the event broker.
50
-
51
- ```diff
52
- // packages/backend/src/types.ts
53
- + import { EventBroker } from '@backstage/plugin-events-node';
54
- + eventBroker: EventBroker;
26
+ backend.add(import('@backstage/plugin-events-backend/alpha'));
55
27
  ```
56
28
 
57
- #### Publishing and Subscribing to events with the broker
29
+ ### Legacy Backend System
58
30
 
59
- Backend plugins are passed the event broker in the plugin environment at startup of the application. The plugin can
60
- make use of this to communicate between parts of the application.
61
-
62
- Here is an example of a plugin publishing a payload to a topic.
63
-
64
- ```typescript jsx
65
- export default async function createPlugin(
66
- env: PluginEnvironment,
67
- ): Promise<Router> {
68
- env.eventBroker.publish({
69
- topic: 'publish.example',
70
- eventPayload: { message: 'Hello, World!' },
71
- metadata: {},
72
- });
73
- }
74
- ```
75
-
76
- Here is an example of a plugin subscribing to a topic.
31
+ ```ts
32
+ // packages/backend/src/plugins/events.ts
33
+ import { HttpPostIngressEventPublisher } from '@backstage/plugin-events-backend';
34
+ import { Router } from 'express';
35
+ import { PluginEnvironment } from '../types';
77
36
 
78
- ```typescript jsx
79
37
  export default async function createPlugin(
80
38
  env: PluginEnvironment,
81
39
  ): Promise<Router> {
82
- env.eventBroker.subscribe([
83
- {
84
- supportsEventTopics: ['publish.example'],
85
- onEvent: async (params: EventParams) => {
86
- env.logger.info(`receieved ${params.topic} event`);
87
- },
88
- },
89
- ]);
90
- }
91
- ```
92
-
93
- #### Implementing an `EventSubscriber` class
94
-
95
- More complex solutions might need the creation of a class that implements the `EventSubscriber` interface. e.g.
96
-
97
- ```typescript jsx
98
- import { EventSubscriber } from './EventSubscriber';
40
+ const eventsRouter = Router();
99
41
 
100
- class ExampleSubscriber implements EventSubscriber {
101
- // ...
102
-
103
- supportsEventTopics() {
104
- return ['publish.example'];
105
- }
42
+ const http = HttpPostIngressEventPublisher.fromConfig({
43
+ config: env.config,
44
+ events: env.events,
45
+ logger: env.logger,
46
+ });
47
+ http.bind(eventsRouter);
106
48
 
107
- async onEvent(params: EventParams) {
108
- env.logger.info(`receieved ${params.topic} event`);
109
- }
49
+ return eventsRouter;
110
50
  }
111
51
  ```
112
52
 
113
- #### Events Backend
114
-
115
- The events backend plugin provides a router to handler http events and publish the http requests onto the event
116
- broker.
53
+ ### Event-based Entity Providers
117
54
 
118
- To configure it add a file [`packages/backend/src/plugins/events.ts`](../../packages/backend/src/plugins/events.ts)
119
- to your Backstage project.
55
+ You can implement the `EventSubscriber` interface on an `EntityProviders` to allow it to handle events from other plugins e.g. the event backend plugin
56
+ mentioned above.
120
57
 
121
- Additionally, add the events plugin to your backend.
58
+ Assuming you have configured the `eventBroker` into the `PluginEnvironment` you can pass the broker to the entity provider for it to subscribe.
122
59
 
123
60
  ```diff
124
- // packages/backend/src/index.ts
125
- // [...]
126
- +import events from './plugins/events';
127
- // [...]
128
- + const eventsEnv = useHotMemoize(module, () => createEnv('events'));
129
- // [...]
130
- + apiRouter.use('/events', await events(eventsEnv));
131
- // [...]
61
+ // packages/backend/src/plugins/catalog.ts
62
+ import { CatalogBuilder } from '@backstage/plugin-catalog-backend';
63
+ +import { DemoEventBasedEntityProvider } from './DemoEventBasedEntityProvider';
64
+ import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend';
65
+ import { Router } from 'express';
66
+ import { PluginEnvironment } from '../types';
67
+
68
+ export default async function createPlugin(
69
+ env: PluginEnvironment,
70
+ ): Promise<Router> {
71
+ const builder = await CatalogBuilder.create(env);
72
+ builder.addProcessor(new ScaffolderEntitiesProcessor());
73
+ + const demoProvider = new DemoEventBasedEntityProvider({ logger: env.logger, topics: ['example'], eventBroker: env.eventBroker });
74
+ + builder.addEntityProvider(demoProvider);
75
+ const { processingEngine, router } = await builder.build();
76
+ await processingEngine.start();
77
+ return router;
78
+ }
132
79
  ```
133
80
 
134
- #### Configuration
81
+ ## Configuration
135
82
 
136
83
  In order to create HTTP endpoints to receive events for a certain
137
84
  topic, you need to add them at your configuration:
@@ -161,57 +108,18 @@ in combination with suitable event subscribers.
161
108
 
162
109
  However, it is not limited to these use cases.
163
110
 
164
- ### Event-based Entity Providers
165
-
166
- You can implement the `EventSubscriber` interface on an `EntityProviders` to allow it to handle events from other plugins e.g. the event backend plugin
167
- mentioned above.
168
-
169
- Assuming you have configured the `eventBroker` into the `PluginEnvironment` you can pass the broker to the entity provider for it to subscribe.
170
-
171
- ```diff
172
- // packages/backend/src/plugins/catalog.ts
173
- import { CatalogBuilder } from '@backstage/plugin-catalog-backend';
174
- +import { DemoEventBasedEntityProvider } from './DemoEventBasedEntityProvider';
175
- import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend';
176
- import { Router } from 'express';
177
- import { PluginEnvironment } from '../types';
178
-
179
- export default async function createPlugin(
180
- env: PluginEnvironment,
181
- ): Promise<Router> {
182
- const builder = await CatalogBuilder.create(env);
183
- builder.addProcessor(new ScaffolderEntitiesProcessor());
184
- + const demoProvider = new DemoEventBasedEntityProvider({ logger: env.logger, topics: ['example'], eventBroker: env.eventBroker });
185
- + builder.addEntityProvider(demoProvider);
186
- const { processingEngine, router } = await builder.build();
187
- await processingEngine.start();
188
- return router;
189
- }
190
- ```
191
-
192
111
  ## Use Cases
193
112
 
194
- ### Custom Event Broker
195
-
196
- Example using the `EventsBackend`:
197
-
198
- ```ts
199
- new EventsBackend(env.logger)
200
- .setEventBroker(yourEventBroker)
201
- // [...]
202
- .start();
203
- ```
204
-
205
- Example using a module:
113
+ ### Request Validator
206
114
 
207
115
  ```ts
208
- import { eventsExtensionPoint } from '@backstage/plugin-events-node';
116
+ import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha';
209
117
 
210
118
  // [...]
211
119
 
212
- export const yourModuleEventsModule = createBackendModule({
120
+ export const eventsModuleYourFeature = createBackendModule({
213
121
  pluginId: 'events',
214
- moduleId: 'your-module',
122
+ moduleId: 'your-feature',
215
123
  register(env) {
216
124
  // [...]
217
125
  env.registerInit({
@@ -222,22 +130,22 @@ export const yourModuleEventsModule = createBackendModule({
222
130
  },
223
131
  async init({ /* ... */ events /*, ... */ }) {
224
132
  // [...]
225
- const yourEventBroker = new YourEventBroker();
226
- // [...]
227
- events.setEventBroker(yourEventBroker);
133
+ events.addHttpPostIngress({
134
+ topic: 'your-topic',
135
+ validator: yourValidator,
136
+ });
228
137
  },
229
138
  });
230
139
  },
231
140
  });
232
141
  ```
233
142
 
234
- ### Request Validator
235
-
236
- Example using the `EventsBackend`:
143
+ #### Legacy Backend System
237
144
 
238
145
  ```ts
239
146
  const http = HttpPostIngressEventPublisher.fromConfig({
240
147
  config: env.config,
148
+ events: env.events,
241
149
  ingresses: {
242
150
  yourTopic: {
243
151
  validator: yourValidator,
@@ -246,39 +154,4 @@ const http = HttpPostIngressEventPublisher.fromConfig({
246
154
  logger: env.logger,
247
155
  });
248
156
  http.bind(router);
249
-
250
- await new EventsBackend(env.logger)
251
- .addPublishers(http)
252
- // [...]
253
- .start();
254
- ```
255
-
256
- Example using a module:
257
-
258
- ```ts
259
- import { eventsExtensionPoint } from '@backstage/plugin-events-node';
260
-
261
- // [...]
262
-
263
- export const eventsModuleYourFeature = createBackendModule({
264
- pluginId: 'events',
265
- moduleId: 'your-feature',
266
- register(env) {
267
- // [...]
268
- env.registerInit({
269
- deps: {
270
- // [...]
271
- events: eventsExtensionPoint,
272
- // [...]
273
- },
274
- async init({ /* ... */ events /*, ... */ }) {
275
- // [...]
276
- events.addHttpPostIngress({
277
- topic: 'your-topic',
278
- validator: yourValidator,
279
- });
280
- },
281
- });
282
- },
283
- });
284
157
  ```
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-events-backend",
3
- "version": "0.2.21",
3
+ "version": "0.3.0-next.0",
4
4
  "main": "../dist/alpha.cjs.js",
5
5
  "types": "../dist/alpha.d.ts"
6
6
  }
package/dist/alpha.cjs.js CHANGED
@@ -3,10 +3,11 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var backendPluginApi = require('@backstage/backend-plugin-api');
6
- var backendCommon = require('@backstage/backend-common');
7
6
  var alpha = require('@backstage/plugin-events-node/alpha');
8
- var HttpPostIngressEventPublisher = require('./cjs/HttpPostIngressEventPublisher-6e928c08.cjs.js');
7
+ var pluginEventsNode = require('@backstage/plugin-events-node');
9
8
  var Router = require('express-promise-router');
9
+ var HttpPostIngressEventPublisher = require('./cjs/HttpPostIngressEventPublisher-a08684c9.cjs.js');
10
+ require('@backstage/backend-common');
10
11
  require('express');
11
12
 
12
13
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
@@ -26,48 +27,34 @@ var __privateAdd = (obj, member, value) => {
26
27
  throw TypeError("Cannot add the same private member more than once");
27
28
  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
28
29
  };
29
- var __privateSet = (obj, member, value, setter) => {
30
- __accessCheck(obj, member, "write to private field");
31
- setter ? setter.call(obj, value) : member.set(obj, value);
32
- return value;
33
- };
34
- var _eventBroker, _httpPostIngresses, _publishers, _subscribers;
30
+ var _httpPostIngresses;
35
31
  class EventsExtensionPointImpl {
36
32
  constructor() {
37
- __privateAdd(this, _eventBroker, void 0);
38
33
  __privateAdd(this, _httpPostIngresses, []);
39
- __privateAdd(this, _publishers, []);
40
- __privateAdd(this, _subscribers, []);
41
34
  }
42
- setEventBroker(eventBroker) {
43
- __privateSet(this, _eventBroker, eventBroker);
35
+ setEventBroker(_) {
36
+ throw new Error(
37
+ "setEventBroker is not supported anymore; use eventsServiceRef instead"
38
+ );
44
39
  }
45
- addPublishers(...publishers) {
46
- __privateGet(this, _publishers).push(...publishers.flat());
40
+ addPublishers(_) {
41
+ throw new Error(
42
+ "addPublishers is not supported anymore; use EventsService instead"
43
+ );
47
44
  }
48
- addSubscribers(...subscribers) {
49
- __privateGet(this, _subscribers).push(...subscribers.flat());
45
+ addSubscribers(_) {
46
+ throw new Error(
47
+ "addSubscribers is not supported anymore; use EventsService instead"
48
+ );
50
49
  }
51
50
  addHttpPostIngress(options) {
52
51
  __privateGet(this, _httpPostIngresses).push(options);
53
52
  }
54
- get eventBroker() {
55
- return __privateGet(this, _eventBroker);
56
- }
57
- get publishers() {
58
- return __privateGet(this, _publishers);
59
- }
60
- get subscribers() {
61
- return __privateGet(this, _subscribers);
62
- }
63
53
  get httpPostIngresses() {
64
54
  return __privateGet(this, _httpPostIngresses);
65
55
  }
66
56
  }
67
- _eventBroker = new WeakMap();
68
57
  _httpPostIngresses = new WeakMap();
69
- _publishers = new WeakMap();
70
- _subscribers = new WeakMap();
71
58
  const eventsPlugin = backendPluginApi.createBackendPlugin({
72
59
  pluginId: "events",
73
60
  register(env) {
@@ -76,12 +63,11 @@ const eventsPlugin = backendPluginApi.createBackendPlugin({
76
63
  env.registerInit({
77
64
  deps: {
78
65
  config: backendPluginApi.coreServices.rootConfig,
66
+ events: pluginEventsNode.eventsServiceRef,
79
67
  logger: backendPluginApi.coreServices.logger,
80
68
  router: backendPluginApi.coreServices.httpRouter
81
69
  },
82
- async init({ config, logger, router }) {
83
- var _a;
84
- const winstonLogger = backendCommon.loggerToWinstonLogger(logger);
70
+ async init({ config, events, logger, router }) {
85
71
  const ingresses = Object.fromEntries(
86
72
  extensionPoint.httpPostIngresses.map((ingress) => [
87
73
  ingress.topic,
@@ -90,15 +76,13 @@ const eventsPlugin = backendPluginApi.createBackendPlugin({
90
76
  );
91
77
  const http = HttpPostIngressEventPublisher.HttpPostIngressEventPublisher.fromConfig({
92
78
  config,
79
+ events,
93
80
  ingresses,
94
- logger: winstonLogger
81
+ logger
95
82
  });
96
83
  const eventsRouter = Router__default["default"]();
97
84
  http.bind(eventsRouter);
98
85
  router.use(eventsRouter);
99
- const eventBroker = (_a = extensionPoint.eventBroker) != null ? _a : new HttpPostIngressEventPublisher.DefaultEventBroker(winstonLogger);
100
- eventBroker.subscribe(extensionPoint.subscribers);
101
- [extensionPoint.publishers, http].flat().forEach((publisher) => publisher.setEventBroker(eventBroker));
102
86
  }
103
87
  });
104
88
  }
@@ -1 +1 @@
1
- {"version":3,"file":"alpha.cjs.js","sources":["../src/service/EventsPlugin.ts"],"sourcesContent":["/*\n * Copyright 2022 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 {\n createBackendPlugin,\n coreServices,\n} from '@backstage/backend-plugin-api';\nimport { loggerToWinstonLogger } from '@backstage/backend-common';\nimport {\n eventsExtensionPoint,\n EventsExtensionPoint,\n} from '@backstage/plugin-events-node/alpha';\nimport {\n EventBroker,\n EventPublisher,\n EventSubscriber,\n HttpPostIngressOptions,\n} from '@backstage/plugin-events-node';\nimport { DefaultEventBroker } from './DefaultEventBroker';\nimport Router from 'express-promise-router';\nimport { HttpPostIngressEventPublisher } from './http';\n\nclass EventsExtensionPointImpl implements EventsExtensionPoint {\n #eventBroker: EventBroker | undefined;\n #httpPostIngresses: HttpPostIngressOptions[] = [];\n #publishers: EventPublisher[] = [];\n #subscribers: EventSubscriber[] = [];\n\n setEventBroker(eventBroker: EventBroker): void {\n this.#eventBroker = eventBroker;\n }\n\n addPublishers(\n ...publishers: Array<EventPublisher | Array<EventPublisher>>\n ): void {\n this.#publishers.push(...publishers.flat());\n }\n\n addSubscribers(\n ...subscribers: Array<EventSubscriber | Array<EventSubscriber>>\n ): void {\n this.#subscribers.push(...subscribers.flat());\n }\n\n addHttpPostIngress(options: HttpPostIngressOptions) {\n this.#httpPostIngresses.push(options);\n }\n\n get eventBroker() {\n return this.#eventBroker;\n }\n\n get publishers() {\n return this.#publishers;\n }\n\n get subscribers() {\n return this.#subscribers;\n }\n\n get httpPostIngresses() {\n return this.#httpPostIngresses;\n }\n}\n\n/**\n * Events plugin\n *\n * @alpha\n */\nexport const eventsPlugin = createBackendPlugin({\n pluginId: 'events',\n register(env) {\n const extensionPoint = new EventsExtensionPointImpl();\n env.registerExtensionPoint(eventsExtensionPoint, extensionPoint);\n\n env.registerInit({\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n router: coreServices.httpRouter,\n },\n async init({ config, logger, router }) {\n const winstonLogger = loggerToWinstonLogger(logger);\n\n const ingresses = Object.fromEntries(\n extensionPoint.httpPostIngresses.map(ingress => [\n ingress.topic,\n ingress as Omit<HttpPostIngressOptions, 'topic'>,\n ]),\n );\n\n const http = HttpPostIngressEventPublisher.fromConfig({\n config,\n ingresses,\n logger: winstonLogger,\n });\n const eventsRouter = Router();\n http.bind(eventsRouter);\n router.use(eventsRouter);\n\n const eventBroker =\n extensionPoint.eventBroker ?? new DefaultEventBroker(winstonLogger);\n\n eventBroker.subscribe(extensionPoint.subscribers);\n [extensionPoint.publishers, http]\n .flat()\n .forEach(publisher => publisher.setEventBroker(eventBroker));\n },\n });\n },\n});\n"],"names":["createBackendPlugin","eventsExtensionPoint","coreServices","loggerToWinstonLogger","HttpPostIngressEventPublisher","Router","DefaultEventBroker"],"mappings":"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"}
1
+ {"version":3,"file":"alpha.cjs.js","sources":["../src/service/EventsPlugin.ts"],"sourcesContent":["/*\n * Copyright 2022 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 {\n createBackendPlugin,\n coreServices,\n} from '@backstage/backend-plugin-api';\nimport {\n eventsExtensionPoint,\n EventsExtensionPoint,\n} from '@backstage/plugin-events-node/alpha';\nimport {\n eventsServiceRef,\n HttpPostIngressOptions,\n} from '@backstage/plugin-events-node';\nimport Router from 'express-promise-router';\nimport { HttpPostIngressEventPublisher } from './http';\n\nclass EventsExtensionPointImpl implements EventsExtensionPoint {\n #httpPostIngresses: HttpPostIngressOptions[] = [];\n\n setEventBroker(_: any): void {\n throw new Error(\n 'setEventBroker is not supported anymore; use eventsServiceRef instead',\n );\n }\n\n addPublishers(_: any): void {\n throw new Error(\n 'addPublishers is not supported anymore; use EventsService instead',\n );\n }\n\n addSubscribers(_: any): void {\n throw new Error(\n 'addSubscribers is not supported anymore; use EventsService instead',\n );\n }\n\n addHttpPostIngress(options: HttpPostIngressOptions) {\n this.#httpPostIngresses.push(options);\n }\n\n get httpPostIngresses() {\n return this.#httpPostIngresses;\n }\n}\n\n/**\n * Events plugin\n *\n * @alpha\n */\nexport const eventsPlugin = createBackendPlugin({\n pluginId: 'events',\n register(env) {\n const extensionPoint = new EventsExtensionPointImpl();\n env.registerExtensionPoint(eventsExtensionPoint, extensionPoint);\n\n env.registerInit({\n deps: {\n config: coreServices.rootConfig,\n events: eventsServiceRef,\n logger: coreServices.logger,\n router: coreServices.httpRouter,\n },\n async init({ config, events, logger, router }) {\n const ingresses = Object.fromEntries(\n extensionPoint.httpPostIngresses.map(ingress => [\n ingress.topic,\n ingress as Omit<HttpPostIngressOptions, 'topic'>,\n ]),\n );\n\n const http = HttpPostIngressEventPublisher.fromConfig({\n config,\n events,\n ingresses,\n logger,\n });\n const eventsRouter = Router();\n http.bind(eventsRouter);\n router.use(eventsRouter);\n },\n });\n },\n});\n"],"names":["createBackendPlugin","eventsExtensionPoint","coreServices","eventsServiceRef","HttpPostIngressEventPublisher","Router"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAA,kBAAA,CAAA;AA+BA,MAAM,wBAAyD,CAAA;AAAA,EAA/D,WAAA,GAAA;AACE,IAAA,YAAA,CAAA,IAAA,EAAA,kBAAA,EAA+C,EAAC,CAAA,CAAA;AAAA,GAAA;AAAA,EAEhD,eAAe,CAAc,EAAA;AAC3B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,uEAAA;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEA,cAAc,CAAc,EAAA;AAC1B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,mEAAA;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEA,eAAe,CAAc,EAAA;AAC3B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,oEAAA;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEA,mBAAmB,OAAiC,EAAA;AAClD,IAAK,YAAA,CAAA,IAAA,EAAA,kBAAA,CAAA,CAAmB,KAAK,OAAO,CAAA,CAAA;AAAA,GACtC;AAAA,EAEA,IAAI,iBAAoB,GAAA;AACtB,IAAA,OAAO,YAAK,CAAA,IAAA,EAAA,kBAAA,CAAA,CAAA;AAAA,GACd;AACF,CAAA;AA3BE,kBAAA,GAAA,IAAA,OAAA,EAAA,CAAA;AAkCK,MAAM,eAAeA,oCAAoB,CAAA;AAAA,EAC9C,QAAU,EAAA,QAAA;AAAA,EACV,SAAS,GAAK,EAAA;AACZ,IAAM,MAAA,cAAA,GAAiB,IAAI,wBAAyB,EAAA,CAAA;AACpD,IAAI,GAAA,CAAA,sBAAA,CAAuBC,4BAAsB,cAAc,CAAA,CAAA;AAE/D,IAAA,GAAA,CAAI,YAAa,CAAA;AAAA,MACf,IAAM,EAAA;AAAA,QACJ,QAAQC,6BAAa,CAAA,UAAA;AAAA,QACrB,MAAQ,EAAAC,iCAAA;AAAA,QACR,QAAQD,6BAAa,CAAA,MAAA;AAAA,QACrB,QAAQA,6BAAa,CAAA,UAAA;AAAA,OACvB;AAAA,MACA,MAAM,IAAK,CAAA,EAAE,QAAQ,MAAQ,EAAA,MAAA,EAAQ,QAAU,EAAA;AAC7C,QAAA,MAAM,YAAY,MAAO,CAAA,WAAA;AAAA,UACvB,cAAA,CAAe,iBAAkB,CAAA,GAAA,CAAI,CAAW,OAAA,KAAA;AAAA,YAC9C,OAAQ,CAAA,KAAA;AAAA,YACR,OAAA;AAAA,WACD,CAAA;AAAA,SACH,CAAA;AAEA,QAAM,MAAA,IAAA,GAAOE,4DAA8B,UAAW,CAAA;AAAA,UACpD,MAAA;AAAA,UACA,MAAA;AAAA,UACA,SAAA;AAAA,UACA,MAAA;AAAA,SACD,CAAA,CAAA;AACD,QAAA,MAAM,eAAeC,0BAAO,EAAA,CAAA;AAC5B,QAAA,IAAA,CAAK,KAAK,YAAY,CAAA,CAAA;AACtB,QAAA,MAAA,CAAO,IAAI,YAAY,CAAA,CAAA;AAAA,OACzB;AAAA,KACD,CAAA,CAAA;AAAA,GACH;AACF,CAAC;;;;"}
@@ -9,49 +9,6 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
9
9
  var express__default = /*#__PURE__*/_interopDefaultLegacy(express);
10
10
  var Router__default = /*#__PURE__*/_interopDefaultLegacy(Router);
11
11
 
12
- var __defProp$1 = Object.defineProperty;
13
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
14
- var __publicField$1 = (obj, key, value) => {
15
- __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
16
- return value;
17
- };
18
- class DefaultEventBroker {
19
- constructor(logger) {
20
- this.logger = logger;
21
- __publicField$1(this, "subscribers", {});
22
- }
23
- async publish(params) {
24
- var _a;
25
- this.logger.debug(
26
- `Event received: topic=${params.topic}, metadata=${JSON.stringify(
27
- params.metadata
28
- )}, payload=${JSON.stringify(params.eventPayload)}`
29
- );
30
- const subscribed = (_a = this.subscribers[params.topic]) != null ? _a : [];
31
- await Promise.all(
32
- subscribed.map(async (subscriber) => {
33
- try {
34
- await subscriber.onEvent(params);
35
- } catch (error) {
36
- this.logger.error(
37
- `Subscriber "${subscriber.constructor.name}" failed to process event`,
38
- error
39
- );
40
- }
41
- })
42
- );
43
- }
44
- subscribe(...subscribers) {
45
- subscribers.flat().forEach((subscriber) => {
46
- subscriber.supportsEventTopics().forEach((topic) => {
47
- var _a;
48
- this.subscribers[topic] = (_a = this.subscribers[topic]) != null ? _a : [];
49
- this.subscribers[topic].push(subscriber);
50
- });
51
- });
52
- }
53
- }
54
-
55
12
  var __accessCheck = (obj, member, msg) => {
56
13
  if (!member.has(obj))
57
14
  throw TypeError("Cannot " + msg);
@@ -91,17 +48,11 @@ class RequestValidationContextImpl {
91
48
  }
92
49
  _rejectionDetails = new WeakMap();
93
50
 
94
- var __defProp = Object.defineProperty;
95
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
96
- var __publicField = (obj, key, value) => {
97
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
98
- return value;
99
- };
100
51
  class HttpPostIngressEventPublisher {
101
- constructor(logger, ingresses) {
52
+ constructor(events, logger, ingresses) {
53
+ this.events = events;
102
54
  this.logger = logger;
103
55
  this.ingresses = ingresses;
104
- __publicField(this, "eventBroker");
105
56
  }
106
57
  static fromConfig(env) {
107
58
  var _a, _b;
@@ -112,14 +63,11 @@ class HttpPostIngressEventPublisher {
112
63
  ingresses[topic] = {};
113
64
  }
114
65
  });
115
- return new HttpPostIngressEventPublisher(env.logger, ingresses);
66
+ return new HttpPostIngressEventPublisher(env.events, env.logger, ingresses);
116
67
  }
117
68
  bind(router) {
118
69
  router.use("/http", this.createRouter(this.ingresses));
119
70
  }
120
- async setEventBroker(eventBroker) {
121
- this.eventBroker = eventBroker;
122
- }
123
71
  createRouter(ingresses) {
124
72
  const router = Router__default["default"]();
125
73
  router.use(express__default["default"].json());
@@ -143,7 +91,7 @@ class HttpPostIngressEventPublisher {
143
91
  return;
144
92
  }
145
93
  const eventPayload = request.body;
146
- await this.eventBroker.publish({
94
+ await this.events.publish({
147
95
  topic,
148
96
  eventPayload,
149
97
  metadata: request.headers
@@ -154,6 +102,5 @@ class HttpPostIngressEventPublisher {
154
102
  }
155
103
  }
156
104
 
157
- exports.DefaultEventBroker = DefaultEventBroker;
158
105
  exports.HttpPostIngressEventPublisher = HttpPostIngressEventPublisher;
159
- //# sourceMappingURL=HttpPostIngressEventPublisher-6e928c08.cjs.js.map
106
+ //# sourceMappingURL=HttpPostIngressEventPublisher-a08684c9.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HttpPostIngressEventPublisher-a08684c9.cjs.js","sources":["../../src/service/http/validation/RequestValidationContextImpl.ts","../../src/service/http/HttpPostIngressEventPublisher.ts"],"sourcesContent":["/*\n * Copyright 2022 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 {\n RequestRejectionDetails,\n RequestValidationContext,\n} from '@backstage/plugin-events-node';\n\nexport class RequestValidationContextImpl implements RequestValidationContext {\n #rejectionDetails: RequestRejectionDetails | undefined;\n\n reject(details?: Partial<RequestRejectionDetails>): void {\n this.#rejectionDetails = {\n status: details?.status ?? 403,\n payload: details?.payload ?? {},\n };\n }\n\n wasRejected(): boolean {\n return this.#rejectionDetails !== undefined;\n }\n\n get rejectionDetails() {\n return this.#rejectionDetails;\n }\n}\n","/*\n * Copyright 2022 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 { errorHandler } from '@backstage/backend-common';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport {\n EventsService,\n HttpPostIngressOptions,\n RequestValidator,\n} from '@backstage/plugin-events-node';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { RequestValidationContextImpl } from './validation';\n\n/**\n * Publishes events received from their origin (e.g., webhook events from an SCM system)\n * via HTTP POST endpoint and passes the request body as event payload to the registered subscribers.\n *\n * @public\n */\n// TODO(pjungermann): add prom metrics? (see plugins/catalog-backend/src/util/metrics.ts, etc.)\nexport class HttpPostIngressEventPublisher {\n static fromConfig(env: {\n config: Config;\n events: EventsService;\n ingresses?: { [topic: string]: Omit<HttpPostIngressOptions, 'topic'> };\n logger: LoggerService;\n }): HttpPostIngressEventPublisher {\n const topics =\n env.config.getOptionalStringArray('events.http.topics') ?? [];\n\n const ingresses = env.ingresses ?? {};\n topics.forEach(topic => {\n // don't overwrite topic settings\n // (e.g., added at the config as well as argument)\n if (!ingresses[topic]) {\n ingresses[topic] = {};\n }\n });\n\n return new HttpPostIngressEventPublisher(env.events, env.logger, ingresses);\n }\n\n private constructor(\n private readonly events: EventsService,\n private readonly logger: LoggerService,\n private readonly ingresses: {\n [topic: string]: Omit<HttpPostIngressOptions, 'topic'>;\n },\n ) {}\n\n bind(router: express.Router): void {\n router.use('/http', this.createRouter(this.ingresses));\n }\n\n private createRouter(ingresses: {\n [topic: string]: Omit<HttpPostIngressOptions, 'topic'>;\n }): express.Router {\n const router = Router();\n router.use(express.json());\n\n Object.keys(ingresses).forEach(topic =>\n this.addRouteForTopic(router, topic, ingresses[topic].validator),\n );\n\n router.use(errorHandler());\n return router;\n }\n\n private addRouteForTopic(\n router: express.Router,\n topic: string,\n validator?: RequestValidator,\n ): void {\n const path = `/${topic}`;\n\n router.post(path, async (request, response) => {\n const requestDetails = {\n body: request.body,\n headers: request.headers,\n };\n const context = new RequestValidationContextImpl();\n await validator?.(requestDetails, context);\n if (context.wasRejected()) {\n response\n .status(context.rejectionDetails!.status)\n .json(context.rejectionDetails!.payload);\n return;\n }\n\n const eventPayload = request.body;\n await this.events.publish({\n topic,\n eventPayload,\n metadata: request.headers,\n });\n\n response.status(202).json({ status: 'accepted' });\n });\n\n // TODO(pjungermann): We don't really know the externally defined path prefix here,\n // however it is more useful for users to have it. Is there a better way?\n this.logger.info(`Registered /api/events/http${path} to receive events`);\n }\n}\n"],"names":["Router","express","errorHandler"],"mappings":"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"}
package/dist/index.cjs.js CHANGED
@@ -2,11 +2,44 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var HttpPostIngressEventPublisher = require('./cjs/HttpPostIngressEventPublisher-6e928c08.cjs.js');
5
+ var pluginEventsNode = require('@backstage/plugin-events-node');
6
+ var HttpPostIngressEventPublisher = require('./cjs/HttpPostIngressEventPublisher-a08684c9.cjs.js');
6
7
  require('@backstage/backend-common');
7
8
  require('express');
8
9
  require('express-promise-router');
9
10
 
11
+ var __defProp$1 = Object.defineProperty;
12
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
13
+ var __publicField$1 = (obj, key, value) => {
14
+ __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
15
+ return value;
16
+ };
17
+ class DefaultEventBroker {
18
+ /**
19
+ *
20
+ * @param logger - logger
21
+ * @param events - replacement that gets wrapped to support not yet migrated implementations.
22
+ * An instance can be passed (required for a mixed mode), otherwise a new instance gets created internally.
23
+ * @deprecated use `DefaultEventsService` directly instead
24
+ */
25
+ constructor(logger, events) {
26
+ __publicField$1(this, "events");
27
+ this.events = events != null ? events : pluginEventsNode.DefaultEventsService.create({ logger });
28
+ }
29
+ async publish(params) {
30
+ return this.events.publish(params);
31
+ }
32
+ subscribe(...subscribers) {
33
+ subscribers.flat().forEach(async (subscriber) => {
34
+ await this.events.subscribe({
35
+ id: subscriber.constructor.name,
36
+ topics: subscriber.supportsEventTopics(),
37
+ onEvent: subscriber.onEvent.bind(subscriber)
38
+ });
39
+ });
40
+ }
41
+ }
42
+
10
43
  var __defProp = Object.defineProperty;
11
44
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
12
45
  var __publicField = (obj, key, value) => {
@@ -18,7 +51,7 @@ class EventsBackend {
18
51
  __publicField(this, "eventBroker");
19
52
  __publicField(this, "publishers", []);
20
53
  __publicField(this, "subscribers", []);
21
- this.eventBroker = new HttpPostIngressEventPublisher.DefaultEventBroker(logger);
54
+ this.eventBroker = new DefaultEventBroker(logger);
22
55
  }
23
56
  setEventBroker(eventBroker) {
24
57
  this.eventBroker = eventBroker;
@@ -43,7 +76,7 @@ class EventsBackend {
43
76
  }
44
77
  }
45
78
 
46
- exports.DefaultEventBroker = HttpPostIngressEventPublisher.DefaultEventBroker;
47
79
  exports.HttpPostIngressEventPublisher = HttpPostIngressEventPublisher.HttpPostIngressEventPublisher;
80
+ exports.DefaultEventBroker = DefaultEventBroker;
48
81
  exports.EventsBackend = EventsBackend;
49
82
  //# sourceMappingURL=index.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/service/EventsBackend.ts"],"sourcesContent":["/*\n * Copyright 2022 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 {\n EventBroker,\n EventPublisher,\n EventSubscriber,\n} from '@backstage/plugin-events-node';\nimport { Logger } from 'winston';\nimport { DefaultEventBroker } from './DefaultEventBroker';\n\n/**\n * A builder that helps wire up all component parts of the event management.\n *\n * @public\n */\nexport class EventsBackend {\n private eventBroker: EventBroker;\n private publishers: EventPublisher[] = [];\n private subscribers: EventSubscriber[] = [];\n\n constructor(logger: Logger) {\n this.eventBroker = new DefaultEventBroker(logger);\n }\n\n setEventBroker(eventBroker: EventBroker): EventsBackend {\n this.eventBroker = eventBroker;\n return this;\n }\n\n addPublishers(\n ...publishers: Array<EventPublisher | Array<EventPublisher>>\n ): EventsBackend {\n this.publishers.push(...publishers.flat());\n return this;\n }\n\n addSubscribers(\n ...subscribers: Array<EventSubscriber | Array<EventSubscriber>>\n ): EventsBackend {\n this.subscribers.push(...subscribers.flat());\n return this;\n }\n\n /**\n * Wires up and returns all component parts of the event management.\n */\n async start(): Promise<void> {\n this.eventBroker.subscribe(this.subscribers);\n this.publishers.forEach(publisher =>\n publisher.setEventBroker(this.eventBroker),\n );\n }\n}\n"],"names":["DefaultEventBroker"],"mappings":";;;;;;;;;;;;;;;AA6BO,MAAM,aAAc,CAAA;AAAA,EAKzB,YAAY,MAAgB,EAAA;AAJ5B,IAAQ,aAAA,CAAA,IAAA,EAAA,aAAA,CAAA,CAAA;AACR,IAAA,aAAA,CAAA,IAAA,EAAQ,cAA+B,EAAC,CAAA,CAAA;AACxC,IAAA,aAAA,CAAA,IAAA,EAAQ,eAAiC,EAAC,CAAA,CAAA;AAGxC,IAAK,IAAA,CAAA,WAAA,GAAc,IAAIA,gDAAA,CAAmB,MAAM,CAAA,CAAA;AAAA,GAClD;AAAA,EAEA,eAAe,WAAyC,EAAA;AACtD,IAAA,IAAA,CAAK,WAAc,GAAA,WAAA,CAAA;AACnB,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAAA,EAEA,iBACK,UACY,EAAA;AACf,IAAA,IAAA,CAAK,UAAW,CAAA,IAAA,CAAK,GAAG,UAAA,CAAW,MAAM,CAAA,CAAA;AACzC,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAAA,EAEA,kBACK,WACY,EAAA;AACf,IAAA,IAAA,CAAK,WAAY,CAAA,IAAA,CAAK,GAAG,WAAA,CAAY,MAAM,CAAA,CAAA;AAC3C,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAuB,GAAA;AAC3B,IAAK,IAAA,CAAA,WAAA,CAAY,SAAU,CAAA,IAAA,CAAK,WAAW,CAAA,CAAA;AAC3C,IAAA,IAAA,CAAK,UAAW,CAAA,OAAA;AAAA,MAAQ,CACtB,SAAA,KAAA,SAAA,CAAU,cAAe,CAAA,IAAA,CAAK,WAAW,CAAA;AAAA,KAC3C,CAAA;AAAA,GACF;AACF;;;;;;"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/service/DefaultEventBroker.ts","../src/service/EventsBackend.ts"],"sourcesContent":["/*\n * Copyright 2022 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 { LoggerService } from '@backstage/backend-plugin-api';\nimport {\n DefaultEventsService,\n EventBroker,\n EventParams,\n EventsService,\n EventSubscriber,\n} from '@backstage/plugin-events-node';\n\n/**\n * In process event broker which will pass the event to all registered subscribers\n * interested in it.\n * Events will not be persisted in any form.\n *\n * @public\n * @deprecated use `DefaultEventsService` from `@backstage/plugin-events-node` instead\n */\nexport class DefaultEventBroker implements EventBroker {\n private readonly events: EventsService;\n\n /**\n *\n * @param logger - logger\n * @param events - replacement that gets wrapped to support not yet migrated implementations.\n * An instance can be passed (required for a mixed mode), otherwise a new instance gets created internally.\n * @deprecated use `DefaultEventsService` directly instead\n */\n constructor(logger: LoggerService, events?: EventsService) {\n this.events = events ?? DefaultEventsService.create({ logger });\n }\n\n async publish(params: EventParams): Promise<void> {\n return this.events.publish(params);\n }\n\n subscribe(\n ...subscribers: Array<EventSubscriber | Array<EventSubscriber>>\n ): void {\n subscribers.flat().forEach(async subscriber => {\n await this.events.subscribe({\n id: subscriber.constructor.name,\n topics: subscriber.supportsEventTopics(),\n onEvent: subscriber.onEvent.bind(subscriber),\n });\n });\n }\n}\n","/*\n * Copyright 2022 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 {\n EventBroker,\n EventPublisher,\n EventSubscriber,\n} from '@backstage/plugin-events-node';\nimport { Logger } from 'winston';\nimport { DefaultEventBroker } from './DefaultEventBroker';\n\n/**\n * A builder that helps wire up all component parts of the event management.\n *\n * @public\n * @deprecated `EventBroker`, `EventPublisher`, and `EventSubscriber` got replaced by `EventsService` and its methods.\n */\nexport class EventsBackend {\n private eventBroker: EventBroker;\n private publishers: EventPublisher[] = [];\n private subscribers: EventSubscriber[] = [];\n\n constructor(logger: Logger) {\n this.eventBroker = new DefaultEventBroker(logger);\n }\n\n setEventBroker(eventBroker: EventBroker): EventsBackend {\n this.eventBroker = eventBroker;\n return this;\n }\n\n addPublishers(\n ...publishers: Array<EventPublisher | Array<EventPublisher>>\n ): EventsBackend {\n this.publishers.push(...publishers.flat());\n return this;\n }\n\n addSubscribers(\n ...subscribers: Array<EventSubscriber | Array<EventSubscriber>>\n ): EventsBackend {\n this.subscribers.push(...subscribers.flat());\n return this;\n }\n\n /**\n * Wires up and returns all component parts of the event management.\n */\n async start(): Promise<void> {\n this.eventBroker.subscribe(this.subscribers);\n this.publishers.forEach(publisher =>\n publisher.setEventBroker(this.eventBroker),\n );\n }\n}\n"],"names":["__publicField","DefaultEventsService"],"mappings":";;;;;;;;;;;;;;;;AAiCO,MAAM,kBAA0C,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUrD,WAAA,CAAY,QAAuB,MAAwB,EAAA;AAT3D,IAAiBA,eAAA,CAAA,IAAA,EAAA,QAAA,CAAA,CAAA;AAUf,IAAA,IAAA,CAAK,SAAS,MAAU,IAAA,IAAA,GAAA,MAAA,GAAAC,qCAAA,CAAqB,MAAO,CAAA,EAAE,QAAQ,CAAA,CAAA;AAAA,GAChE;AAAA,EAEA,MAAM,QAAQ,MAAoC,EAAA;AAChD,IAAO,OAAA,IAAA,CAAK,MAAO,CAAA,OAAA,CAAQ,MAAM,CAAA,CAAA;AAAA,GACnC;AAAA,EAEA,aACK,WACG,EAAA;AACN,IAAA,WAAA,CAAY,IAAK,EAAA,CAAE,OAAQ,CAAA,OAAM,UAAc,KAAA;AAC7C,MAAM,MAAA,IAAA,CAAK,OAAO,SAAU,CAAA;AAAA,QAC1B,EAAA,EAAI,WAAW,WAAY,CAAA,IAAA;AAAA,QAC3B,MAAA,EAAQ,WAAW,mBAAoB,EAAA;AAAA,QACvC,OAAS,EAAA,UAAA,CAAW,OAAQ,CAAA,IAAA,CAAK,UAAU,CAAA;AAAA,OAC5C,CAAA,CAAA;AAAA,KACF,CAAA,CAAA;AAAA,GACH;AACF;;;;;;;;AChCO,MAAM,aAAc,CAAA;AAAA,EAKzB,YAAY,MAAgB,EAAA;AAJ5B,IAAQ,aAAA,CAAA,IAAA,EAAA,aAAA,CAAA,CAAA;AACR,IAAA,aAAA,CAAA,IAAA,EAAQ,cAA+B,EAAC,CAAA,CAAA;AACxC,IAAA,aAAA,CAAA,IAAA,EAAQ,eAAiC,EAAC,CAAA,CAAA;AAGxC,IAAK,IAAA,CAAA,WAAA,GAAc,IAAI,kBAAA,CAAmB,MAAM,CAAA,CAAA;AAAA,GAClD;AAAA,EAEA,eAAe,WAAyC,EAAA;AACtD,IAAA,IAAA,CAAK,WAAc,GAAA,WAAA,CAAA;AACnB,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAAA,EAEA,iBACK,UACY,EAAA;AACf,IAAA,IAAA,CAAK,UAAW,CAAA,IAAA,CAAK,GAAG,UAAA,CAAW,MAAM,CAAA,CAAA;AACzC,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAAA,EAEA,kBACK,WACY,EAAA;AACf,IAAA,IAAA,CAAK,WAAY,CAAA,IAAA,CAAK,GAAG,WAAA,CAAY,MAAM,CAAA,CAAA;AAC3C,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAuB,GAAA;AAC3B,IAAK,IAAA,CAAA,WAAA,CAAY,SAAU,CAAA,IAAA,CAAK,WAAW,CAAA,CAAA;AAC3C,IAAA,IAAA,CAAK,UAAW,CAAA,OAAA;AAAA,MAAQ,CACtB,SAAA,KAAA,SAAA,CAAU,cAAe,CAAA,IAAA,CAAK,WAAW,CAAA;AAAA,KAC3C,CAAA;AAAA,GACF;AACF;;;;;;"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import { EventBroker, EventPublisher, EventSubscriber, HttpPostIngressOptions, EventParams } from '@backstage/plugin-events-node';
1
+ import { EventBroker, EventPublisher, EventSubscriber, EventsService, EventParams, HttpPostIngressOptions } from '@backstage/plugin-events-node';
2
2
  import { Logger } from 'winston';
3
+ import { LoggerService } from '@backstage/backend-plugin-api';
3
4
  import { Config } from '@backstage/config';
4
5
  import express from 'express';
5
6
 
@@ -7,6 +8,7 @@ import express from 'express';
7
8
  * A builder that helps wire up all component parts of the event management.
8
9
  *
9
10
  * @public
11
+ * @deprecated `EventBroker`, `EventPublisher`, and `EventSubscriber` got replaced by `EventsService` and its methods.
10
12
  */
11
13
  declare class EventsBackend {
12
14
  private eventBroker;
@@ -22,43 +24,50 @@ declare class EventsBackend {
22
24
  start(): Promise<void>;
23
25
  }
24
26
 
27
+ /**
28
+ * In process event broker which will pass the event to all registered subscribers
29
+ * interested in it.
30
+ * Events will not be persisted in any form.
31
+ *
32
+ * @public
33
+ * @deprecated use `DefaultEventsService` from `@backstage/plugin-events-node` instead
34
+ */
35
+ declare class DefaultEventBroker implements EventBroker {
36
+ private readonly events;
37
+ /**
38
+ *
39
+ * @param logger - logger
40
+ * @param events - replacement that gets wrapped to support not yet migrated implementations.
41
+ * An instance can be passed (required for a mixed mode), otherwise a new instance gets created internally.
42
+ * @deprecated use `DefaultEventsService` directly instead
43
+ */
44
+ constructor(logger: LoggerService, events?: EventsService);
45
+ publish(params: EventParams): Promise<void>;
46
+ subscribe(...subscribers: Array<EventSubscriber | Array<EventSubscriber>>): void;
47
+ }
48
+
25
49
  /**
26
50
  * Publishes events received from their origin (e.g., webhook events from an SCM system)
27
51
  * via HTTP POST endpoint and passes the request body as event payload to the registered subscribers.
28
52
  *
29
53
  * @public
30
54
  */
31
- declare class HttpPostIngressEventPublisher implements EventPublisher {
55
+ declare class HttpPostIngressEventPublisher {
56
+ private readonly events;
32
57
  private readonly logger;
33
58
  private readonly ingresses;
34
- private eventBroker?;
35
59
  static fromConfig(env: {
36
60
  config: Config;
61
+ events: EventsService;
37
62
  ingresses?: {
38
63
  [topic: string]: Omit<HttpPostIngressOptions, 'topic'>;
39
64
  };
40
- logger: Logger;
65
+ logger: LoggerService;
41
66
  }): HttpPostIngressEventPublisher;
42
67
  private constructor();
43
68
  bind(router: express.Router): void;
44
- setEventBroker(eventBroker: EventBroker): Promise<void>;
45
69
  private createRouter;
46
70
  private addRouteForTopic;
47
71
  }
48
72
 
49
- /**
50
- * In process event broker which will pass the event to all registered subscribers
51
- * interested in it.
52
- * Events will not be persisted in any form.
53
- *
54
- * @public
55
- */
56
- declare class DefaultEventBroker implements EventBroker {
57
- private readonly logger;
58
- constructor(logger: Logger);
59
- private readonly subscribers;
60
- publish(params: EventParams): Promise<void>;
61
- subscribe(...subscribers: Array<EventSubscriber | Array<EventSubscriber>>): void;
62
- }
63
-
64
73
  export { DefaultEventBroker, EventsBackend, HttpPostIngressEventPublisher };
package/package.json CHANGED
@@ -1,12 +1,19 @@
1
1
  {
2
2
  "name": "@backstage/plugin-events-backend",
3
- "version": "0.2.21",
4
- "main": "./dist/index.cjs.js",
5
- "types": "./dist/index.d.ts",
6
- "license": "Apache-2.0",
3
+ "version": "0.3.0-next.0",
4
+ "backstage": {
5
+ "role": "backend-plugin"
6
+ },
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
10
+ "homepage": "https://backstage.io",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "https://github.com/backstage/backstage",
14
+ "directory": "plugins/events-backend"
15
+ },
16
+ "license": "Apache-2.0",
10
17
  "exports": {
11
18
  ".": {
12
19
  "require": "./dist/index.cjs.js",
@@ -20,45 +27,38 @@
20
27
  },
21
28
  "./package.json": "./package.json"
22
29
  },
23
- "backstage": {
24
- "role": "backend-plugin"
25
- },
26
- "homepage": "https://backstage.io",
27
- "repository": {
28
- "type": "git",
29
- "url": "https://github.com/backstage/backstage",
30
- "directory": "plugins/events-backend"
31
- },
30
+ "main": "./dist/index.cjs.js",
31
+ "types": "./dist/index.d.ts",
32
+ "files": [
33
+ "config.d.ts",
34
+ "dist",
35
+ "alpha"
36
+ ],
32
37
  "scripts": {
33
- "start": "backstage-cli package start",
34
38
  "build": "backstage-cli package build",
35
- "lint": "backstage-cli package lint",
36
- "test": "backstage-cli package test",
37
39
  "clean": "backstage-cli package clean",
40
+ "lint": "backstage-cli package lint",
38
41
  "prepack": "backstage-cli package prepack",
39
- "postpack": "backstage-cli package postpack"
42
+ "postpack": "backstage-cli package postpack",
43
+ "start": "backstage-cli package start",
44
+ "test": "backstage-cli package test"
40
45
  },
41
46
  "dependencies": {
42
- "@backstage/backend-common": "^0.21.2",
43
- "@backstage/backend-plugin-api": "^0.6.12",
44
- "@backstage/config": "^1.1.1",
45
- "@backstage/plugin-events-node": "^0.2.21",
47
+ "@backstage/backend-common": "^0.21.3-next.0",
48
+ "@backstage/backend-plugin-api": "^0.6.13-next.0",
49
+ "@backstage/config": "^1.1.2-next.0",
50
+ "@backstage/plugin-events-node": "^0.3.0-next.0",
46
51
  "@types/express": "^4.17.6",
47
52
  "express": "^4.17.1",
48
53
  "express-promise-router": "^4.1.0",
49
54
  "winston": "^3.2.1"
50
55
  },
51
56
  "devDependencies": {
52
- "@backstage/backend-common": "^0.21.2",
53
- "@backstage/backend-test-utils": "^0.3.2",
54
- "@backstage/cli": "^0.25.2",
55
- "@backstage/plugin-events-backend-test-utils": "^0.1.22",
57
+ "@backstage/backend-common": "^0.21.3-next.0",
58
+ "@backstage/backend-test-utils": "^0.3.3-next.0",
59
+ "@backstage/cli": "^0.25.3-next.0",
60
+ "@backstage/plugin-events-backend-test-utils": "^0.1.23-next.0",
56
61
  "supertest": "^6.1.3"
57
62
  },
58
- "files": [
59
- "config.d.ts",
60
- "dist",
61
- "alpha"
62
- ],
63
63
  "configSchema": "config.d.ts"
64
64
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"HttpPostIngressEventPublisher-6e928c08.cjs.js","sources":["../../src/service/DefaultEventBroker.ts","../../src/service/http/validation/RequestValidationContextImpl.ts","../../src/service/http/HttpPostIngressEventPublisher.ts"],"sourcesContent":["/*\n * Copyright 2022 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 {\n EventBroker,\n EventParams,\n EventSubscriber,\n} from '@backstage/plugin-events-node';\nimport { Logger } from 'winston';\n\n/**\n * In process event broker which will pass the event to all registered subscribers\n * interested in it.\n * Events will not be persisted in any form.\n *\n * @public\n */\n// TODO(pjungermann): add prom metrics? (see plugins/catalog-backend/src/util/metrics.ts, etc.)\nexport class DefaultEventBroker implements EventBroker {\n constructor(private readonly logger: Logger) {}\n\n private readonly subscribers: {\n [topic: string]: EventSubscriber[];\n } = {};\n\n async publish(params: EventParams): Promise<void> {\n this.logger.debug(\n `Event received: topic=${params.topic}, metadata=${JSON.stringify(\n params.metadata,\n )}, payload=${JSON.stringify(params.eventPayload)}`,\n );\n\n const subscribed = this.subscribers[params.topic] ?? [];\n await Promise.all(\n subscribed.map(async subscriber => {\n try {\n await subscriber.onEvent(params);\n } catch (error) {\n this.logger.error(\n `Subscriber \"${subscriber.constructor.name}\" failed to process event`,\n error,\n );\n }\n }),\n );\n }\n\n subscribe(\n ...subscribers: Array<EventSubscriber | Array<EventSubscriber>>\n ): void {\n subscribers.flat().forEach(subscriber => {\n subscriber.supportsEventTopics().forEach(topic => {\n this.subscribers[topic] = this.subscribers[topic] ?? [];\n this.subscribers[topic].push(subscriber);\n });\n });\n }\n}\n","/*\n * Copyright 2022 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 {\n RequestRejectionDetails,\n RequestValidationContext,\n} from '@backstage/plugin-events-node';\n\nexport class RequestValidationContextImpl implements RequestValidationContext {\n #rejectionDetails: RequestRejectionDetails | undefined;\n\n reject(details?: Partial<RequestRejectionDetails>): void {\n this.#rejectionDetails = {\n status: details?.status ?? 403,\n payload: details?.payload ?? {},\n };\n }\n\n wasRejected(): boolean {\n return this.#rejectionDetails !== undefined;\n }\n\n get rejectionDetails() {\n return this.#rejectionDetails;\n }\n}\n","/*\n * Copyright 2022 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 { errorHandler } from '@backstage/backend-common';\nimport { Config } from '@backstage/config';\nimport {\n EventBroker,\n EventPublisher,\n HttpPostIngressOptions,\n RequestValidator,\n} from '@backstage/plugin-events-node';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { Logger } from 'winston';\nimport { RequestValidationContextImpl } from './validation';\n\n/**\n * Publishes events received from their origin (e.g., webhook events from an SCM system)\n * via HTTP POST endpoint and passes the request body as event payload to the registered subscribers.\n *\n * @public\n */\n// TODO(pjungermann): add prom metrics? (see plugins/catalog-backend/src/util/metrics.ts, etc.)\nexport class HttpPostIngressEventPublisher implements EventPublisher {\n private eventBroker?: EventBroker;\n\n static fromConfig(env: {\n config: Config;\n ingresses?: { [topic: string]: Omit<HttpPostIngressOptions, 'topic'> };\n logger: Logger;\n }): HttpPostIngressEventPublisher {\n const topics =\n env.config.getOptionalStringArray('events.http.topics') ?? [];\n\n const ingresses = env.ingresses ?? {};\n topics.forEach(topic => {\n // don't overwrite topic settings\n // (e.g., added at the config as well as argument)\n if (!ingresses[topic]) {\n ingresses[topic] = {};\n }\n });\n\n return new HttpPostIngressEventPublisher(env.logger, ingresses);\n }\n\n private constructor(\n private readonly logger: Logger,\n private readonly ingresses: {\n [topic: string]: Omit<HttpPostIngressOptions, 'topic'>;\n },\n ) {}\n\n bind(router: express.Router): void {\n router.use('/http', this.createRouter(this.ingresses));\n }\n\n async setEventBroker(eventBroker: EventBroker): Promise<void> {\n this.eventBroker = eventBroker;\n }\n\n private createRouter(ingresses: {\n [topic: string]: Omit<HttpPostIngressOptions, 'topic'>;\n }): express.Router {\n const router = Router();\n router.use(express.json());\n\n Object.keys(ingresses).forEach(topic =>\n this.addRouteForTopic(router, topic, ingresses[topic].validator),\n );\n\n router.use(errorHandler());\n return router;\n }\n\n private addRouteForTopic(\n router: express.Router,\n topic: string,\n validator?: RequestValidator,\n ): void {\n const path = `/${topic}`;\n\n router.post(path, async (request, response) => {\n const requestDetails = {\n body: request.body,\n headers: request.headers,\n };\n const context = new RequestValidationContextImpl();\n await validator?.(requestDetails, context);\n if (context.wasRejected()) {\n response\n .status(context.rejectionDetails!.status)\n .json(context.rejectionDetails!.payload);\n return;\n }\n\n const eventPayload = request.body;\n await this.eventBroker!.publish({\n topic,\n eventPayload,\n metadata: request.headers,\n });\n\n response.status(202).json({ status: 'accepted' });\n });\n\n // TODO(pjungermann): We don't really know the externally defined path prefix here,\n // however it is more useful for users to have it. Is there a better way?\n this.logger.info(`Registered /api/events/http${path} to receive events`);\n }\n}\n"],"names":["__publicField","Router","express","errorHandler"],"mappings":"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"}