@autometa/events 0.3.2 → 1.0.0-rc.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/dist/index.js CHANGED
@@ -1,328 +1,412 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/index.ts
31
- var src_exports = {};
32
- __export(src_exports, {
33
- ArgsEventSchema: () => ArgsEventSchema,
34
- EndAfterOptsSchema: () => EndAfterOptsSchema,
35
- EndBeforeOptsSchema: () => EndBeforeOptsSchema,
36
- EndFeatureOptsSchema: () => EndFeatureOptsSchema,
37
- EndRuleOptsSchema: () => EndRuleOptsSchema,
38
- EndScenarioOptsSchema: () => EndScenarioOptsSchema,
39
- EndScenarioOutlineOptsSchema: () => EndScenarioOutlineOptsSchema,
40
- EndSetupOptsSchema: () => EndSetupOptsSchema,
41
- EndStepOptsSchema: () => EndStepOptsSchema,
42
- EndTeardownOptsSchema: () => EndTeardownOptsSchema,
43
- ErrorEventSchema: () => ErrorEventSchema,
44
- EventOptionsSchema: () => EventOptionsSchema,
45
- EventSubscriberSchema: () => EventSubscriberSchema,
46
- ProviderSubscriber: () => ProviderSubscriber,
47
- StartAfterOptsSchema: () => StartAfterOptsSchema,
48
- StartBeforeOptsSchema: () => StartBeforeOptsSchema,
49
- StartFeatureOptsSchema: () => StartFeatureOptsSchema,
50
- StartScenarioOptsSchema: () => StartScenarioOptsSchema,
51
- StartScenarioOutlineOptsSchema: () => StartScenarioOutlineOptsSchema,
52
- StartSetupOptsSchema: () => StartSetupOptsSchema,
53
- StartStepOptsSchema: () => StartStepOptsSchema,
54
- StartTeardownOptsSchema: () => StartTeardownOptsSchema,
55
- Status: () => Status,
56
- StatusSchema: () => StatusSchema,
57
- TestEmitter: () => TestEmitter,
58
- TestEventEmitter: () => TestEventEmitter,
59
- UUIDStringSchema: () => UUIDStringSchema
60
- });
61
- module.exports = __toCommonJS(src_exports);
1
+ import { createToken, createContainer, Scope } from '@autometa/injection';
62
2
 
63
- // src/event-options.ts
64
- var import_zod = require("zod");
65
- var uuidRegex = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/gm;
66
- var UUIDStringSchema = (0, import_zod.string)().regex(uuidRegex).optional();
67
- var StatusSchema = import_zod.z.union([
68
- (0, import_zod.literal)("FAILED"),
69
- (0, import_zod.literal)("BROKEN"),
70
- (0, import_zod.literal)("PASSED"),
71
- (0, import_zod.literal)("SKIPPED")
72
- ]);
73
- var EventOptionsSchema = (0, import_zod.object)({
74
- title: (0, import_zod.string)().optional(),
75
- keyword: (0, import_zod.string)().optional(),
76
- tags: (0, import_zod.string)().array().optional(),
77
- modifier: (0, import_zod.literal)("skip").or((0, import_zod.literal)("only")).optional(),
78
- status: StatusSchema.optional()
79
- });
80
- var ErrorEventSchema = EventOptionsSchema.extend({
81
- error: import_zod.z.instanceof(Error).optional()
82
- });
83
- var ArgsEventSchema = EventOptionsSchema.extend({
84
- args: import_zod.z.array(import_zod.z.unknown()).optional()
85
- });
86
- var StartFeatureOptsSchema = EventOptionsSchema.extend({
87
- path: (0, import_zod.string)().optional()
88
- });
89
- var EndFeatureOptsSchema = ErrorEventSchema;
90
- var EndRuleOptsSchema = ErrorEventSchema;
91
- var StartScenarioOutlineOptsSchema = EventOptionsSchema;
92
- var EndScenarioOutlineOptsSchema = ErrorEventSchema;
93
- var StartScenarioOptsSchema = EventOptionsSchema;
94
- var EndScenarioOptsSchema = ErrorEventSchema;
95
- var StartStepOptsSchema = EventOptionsSchema.extend({
96
- args: import_zod.z.array(import_zod.z.unknown()).optional(),
97
- expression: import_zod.z.string().optional()
98
- });
99
- var EndStepOptsSchema = EventOptionsSchema.extend({
100
- args: import_zod.z.array(import_zod.z.unknown()).optional(),
101
- expression: import_zod.z.string()
102
- }).and(ErrorEventSchema);
103
- var StartBeforeOptsSchema = ArgsEventSchema;
104
- var EndBeforeOptsSchema = ErrorEventSchema;
105
- var StartAfterOptsSchema = ArgsEventSchema;
106
- var EndAfterOptsSchema = ErrorEventSchema;
107
- var StartSetupOptsSchema = ArgsEventSchema;
108
- var EndSetupOptsSchema = ErrorEventSchema;
109
- var StartTeardownOptsSchema = ArgsEventSchema;
110
- var EndTeardownOptsSchema = ErrorEventSchema;
111
-
112
- // src/event-subscriber.ts
113
- var import_zod2 = require("zod");
114
- var EventSubscriberSchema = (0, import_zod2.object)({
115
- onFeature: (0, import_zod2.function)()
116
- });
117
- var ProviderSubscriber = class {
118
- constructor() {
119
- this.addFixtureInstance = (instance) => {
120
- this.fixtures.instances?.push(instance);
3
+ // src/dispatcher.ts
4
+ var EventDispatcherToken = createToken(
5
+ "@autometa/events/dispatcher"
6
+ );
7
+ var EventDispatcher = class _EventDispatcher {
8
+ constructor(container = createContainer()) {
9
+ this.container = container;
10
+ this.subscribers = /* @__PURE__ */ new Map();
11
+ this.sequence = 0;
12
+ }
13
+ static create(options = {}) {
14
+ const container = options.container ?? createContainer();
15
+ if (!container.isRegistered(EventDispatcherToken)) {
16
+ container.registerValue(
17
+ EventDispatcherToken,
18
+ new _EventDispatcher(container),
19
+ { scope: Scope.SINGLETON }
20
+ );
21
+ }
22
+ return container.resolve(EventDispatcherToken);
23
+ }
24
+ /**
25
+ * Subscribe to events of a particular type.
26
+ */
27
+ subscribe(type, subscriber) {
28
+ const set = this.subscribers.get(type) ?? /* @__PURE__ */ new Set();
29
+ set.add(subscriber);
30
+ this.subscribers.set(type, set);
31
+ return () => {
32
+ set.delete(subscriber);
33
+ if (set.size === 0) {
34
+ this.subscribers.delete(type);
35
+ }
36
+ };
37
+ }
38
+ /**
39
+ * Publish an event to all registered subscribers. Subscribers are awaited in
40
+ * series to preserve ordering guarantees; callers can fork when concurrency is
41
+ * desired.
42
+ */
43
+ async dispatch(event) {
44
+ const envelope = {
45
+ sequence: ++this.sequence,
46
+ event
121
47
  };
48
+ const listeners = this.subscribers.get(event.type);
49
+ if (!listeners || listeners.size === 0) {
50
+ return;
51
+ }
52
+ for (const listener of listeners) {
53
+ await listener(envelope);
54
+ }
55
+ }
56
+ clear() {
57
+ this.subscribers.clear();
58
+ this.sequence = 0;
122
59
  }
123
60
  };
124
61
 
125
- // src/test-emitter.ts
126
- var import_events = __toESM(require("events"), 1);
127
- var TestEmitter = class extends import_events.default {
128
- constructor(name) {
129
- super();
130
- this.name = name;
131
- this.promises = [];
132
- this.emitStart = (...args) => {
133
- this.emit(`onStart${this.name}`, ...args);
62
+ // src/emitter.ts
63
+ var defaultIdFactory = () => {
64
+ const crypto = globalThis.crypto;
65
+ if (crypto && typeof crypto.randomUUID === "function") {
66
+ return crypto.randomUUID();
67
+ }
68
+ return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
69
+ };
70
+ var EventEmitter = class {
71
+ constructor(dispatcher, options = {}) {
72
+ this.dispatcher = dispatcher;
73
+ this.createId = options.createId ?? defaultIdFactory;
74
+ this.now = options.now ?? Date.now;
75
+ }
76
+ async featureStarted(options) {
77
+ const event = {
78
+ type: "feature.started",
79
+ feature: options.feature,
80
+ ...this.base(options)
134
81
  };
135
- this.onStart = (action) => {
136
- if (action) {
137
- this.on(`onStart${this.name}`, this.collectPromises(this.name, action));
138
- }
82
+ await this.dispatcher.dispatch(event);
83
+ }
84
+ async featureCompleted(options) {
85
+ const event = {
86
+ type: "feature.completed",
87
+ feature: options.feature,
88
+ ...this.base(options)
139
89
  };
140
- this.onEnd = (action) => {
141
- if (action) {
142
- this.on(`onEnd${this.name}`, this.collectPromises(this.name, action));
143
- }
90
+ await this.dispatcher.dispatch(event);
91
+ }
92
+ async ruleStarted(options) {
93
+ const event = {
94
+ type: "rule.started",
95
+ feature: options.feature,
96
+ rule: options.rule,
97
+ ...this.base(options)
144
98
  };
145
- this.emitEnd = (...args) => {
146
- this.emit(`onEnd${this.name}`, ...args);
99
+ await this.dispatcher.dispatch(event);
100
+ }
101
+ async ruleCompleted(options) {
102
+ const event = {
103
+ type: "rule.completed",
104
+ feature: options.feature,
105
+ rule: options.rule,
106
+ ...this.base(options)
147
107
  };
148
- this.load = (onStart, onEnd) => {
149
- this.onStart(onStart);
150
- this.onEnd(onEnd);
108
+ await this.dispatcher.dispatch(event);
109
+ }
110
+ async scenarioStarted(options) {
111
+ const event = {
112
+ type: "scenario.started",
113
+ feature: options.feature,
114
+ scenario: options.scenario,
115
+ pickle: options.pickle,
116
+ ...options.rule ? { rule: options.rule } : {},
117
+ ...this.base(options)
151
118
  };
152
- this.collectPromises = (name, action) => {
153
- return (...args) => {
154
- try {
155
- const result = action(...args);
156
- if (result instanceof Promise) {
157
- this.promises.push(result);
158
- }
159
- } catch (e) {
160
- console.error(
161
- `Event Subscriber ${name} threw an error ${e.message}`
162
- );
163
- }
164
- };
119
+ await this.dispatcher.dispatch(event);
120
+ }
121
+ async scenarioCompleted(options) {
122
+ const event = {
123
+ type: "scenario.completed",
124
+ feature: options.feature,
125
+ scenario: options.scenario,
126
+ pickle: options.pickle,
127
+ ...options.rule ? { rule: options.rule } : {},
128
+ ...this.base(options)
165
129
  };
166
- this.waitForPromises = async () => {
167
- const settled = await Promise.allSettled(this.promises);
168
- return settled.filter((it) => it.status === "rejected").length;
130
+ await this.dispatcher.dispatch(event);
131
+ }
132
+ async scenarioOutlineStarted(options) {
133
+ const event = {
134
+ type: "scenarioOutline.started",
135
+ feature: options.feature,
136
+ scenarioOutline: options.scenarioOutline,
137
+ ...options.rule ? { rule: options.rule } : {},
138
+ ...this.base(options)
169
139
  };
140
+ await this.dispatcher.dispatch(event);
170
141
  }
171
- };
172
-
173
- // src/test-event-emitter.ts
174
- var TestEventEmitter = class {
175
- constructor() {
176
- this.scenarioOutline = new TestEmitter("ScenarioOutline");
177
- this.feature = new TestEmitter("Feature");
178
- this.rule = new TestEmitter("Rule");
179
- this.scenario = new TestEmitter("Scenario");
180
- this.scenarioWrapper = new TestEmitter("Scenario Wrapper");
181
- this.setup = new TestEmitter("Setup");
182
- this.beforeFeature = new TestEmitter(
183
- "BeforeFeature"
184
- );
185
- this.afterFeature = new TestEmitter("AfterFeature");
186
- this.beforeRule = new TestEmitter("BeforeRule");
187
- this.afterRule = new TestEmitter("AfterRule");
188
- this.beforeScenarioOutline = new TestEmitter(
189
- "BeforeScenarioOutline"
190
- );
191
- this.afterScenarioOutline = new TestEmitter(
192
- "AfterScenarioOutline"
193
- );
194
- this.beforeExamples = new TestEmitter(
195
- "BeforeExamples"
196
- );
197
- this.afterExamples = new TestEmitter(
198
- "AfterExamples"
199
- );
200
- this.teardown = new TestEmitter("Teardown");
201
- this.before = new TestEmitter("Before");
202
- this.after = new TestEmitter("After");
203
- this.step = new TestEmitter("Step");
204
- this.beforeStep = new TestEmitter("BeforeStep");
205
- this.afterStep = new TestEmitter("AfterStep");
206
- this.settleAsyncEvents = async () => {
207
- return await Promise.allSettled([
208
- this.scenarioOutline.waitForPromises(),
209
- this.feature.waitForPromises(),
210
- this.rule.waitForPromises(),
211
- this.scenario.waitForPromises(),
212
- this.scenarioWrapper.waitForPromises(),
213
- this.setup.waitForPromises(),
214
- this.teardown.waitForPromises(),
215
- this.before.waitForPromises(),
216
- this.after.waitForPromises(),
217
- this.step.waitForPromises()
218
- ]);
142
+ async scenarioOutlineCompleted(options) {
143
+ const event = {
144
+ type: "scenarioOutline.completed",
145
+ feature: options.feature,
146
+ scenarioOutline: options.scenarioOutline,
147
+ ...options.rule ? { rule: options.rule } : {},
148
+ ...this.base(options)
219
149
  };
220
- this.load = ({
221
- onFeatureStart,
222
- onFeatureEnd,
223
- onScenarioOutlineStart,
224
- onScenarioOutlineEnd,
225
- onScenarioStart,
226
- onScenarioEnd,
227
- onRuleStart,
228
- onRuleEnd,
229
- onBeforeStart,
230
- onBeforeEnd,
231
- onSetupStart,
232
- onSetupEnd,
233
- onStepStart,
234
- onStepEnd,
235
- onAfterStart,
236
- onAfterEnd,
237
- onTeardownStart,
238
- onTeardownEnd,
239
- onPreScenarioStart,
240
- onPostScenarioEnd,
241
- onBeforeFeatureStart,
242
- onBeforeFeatureEnd,
243
- onAfterFeatureStart,
244
- onAfterFeatureEnd,
245
- onBeforeRuleStart,
246
- onBeforeRuleEnd,
247
- onAfterRuleStart,
248
- onAfterRuleEnd,
249
- onBeforeScenarioOutlineStart,
250
- onBeforeScenarioOutlineEnd,
251
- onAfterScenarioOutlineStart,
252
- onAfterScenarioOutlineEnd,
253
- onBeforeExamplesStart,
254
- onBeforeExamplesEnd,
255
- onAfterExamplesStart,
256
- onBeforeStepStart,
257
- onBeforeStepEnd,
258
- onAfterStepStart,
259
- onAfterStepEnd
260
- }) => {
261
- this.feature.load(onFeatureStart, onFeatureEnd);
262
- this.rule.load(onRuleStart, onRuleEnd);
263
- this.scenarioOutline.load(onScenarioOutlineStart, onScenarioOutlineEnd);
264
- this.scenario.load(onScenarioStart, onScenarioEnd);
265
- this.step.load(onStepStart, onStepEnd);
266
- this.before.load(onBeforeStart, onBeforeEnd);
267
- this.after.load(onAfterStart, onAfterEnd);
268
- this.setup.load(onSetupStart, onSetupEnd);
269
- this.teardown.load(onTeardownStart, onTeardownEnd);
270
- this.scenarioWrapper.load(onPreScenarioStart, onPostScenarioEnd);
271
- this.beforeFeature.load(onBeforeFeatureStart, onBeforeFeatureEnd);
272
- this.afterFeature.load(onAfterFeatureStart, onAfterFeatureEnd);
273
- this.beforeRule.load(onBeforeRuleStart, onBeforeRuleEnd);
274
- this.afterRule.load(onAfterRuleStart, onAfterRuleEnd);
275
- this.beforeScenarioOutline.load(
276
- onBeforeScenarioOutlineStart,
277
- onBeforeScenarioOutlineEnd
278
- );
279
- this.afterScenarioOutline.load(
280
- onAfterScenarioOutlineStart,
281
- onAfterScenarioOutlineEnd
282
- );
283
- this.beforeExamples.load(onBeforeExamplesStart, onBeforeExamplesEnd);
284
- this.afterExamples.load(onAfterExamplesStart, onBeforeStepStart);
285
- this.beforeStep.load(onBeforeStepStart, onBeforeStepEnd);
286
- this.afterStep.load(onAfterStepStart, onAfterStepEnd);
150
+ await this.dispatcher.dispatch(event);
151
+ }
152
+ async exampleStarted(options) {
153
+ const event = {
154
+ type: "example.started",
155
+ feature: options.feature,
156
+ scenarioOutline: options.scenarioOutline,
157
+ example: options.example,
158
+ pickle: options.pickle,
159
+ ...options.rule ? { rule: options.rule } : {},
160
+ ...this.base(options)
161
+ };
162
+ await this.dispatcher.dispatch(event);
163
+ }
164
+ async exampleCompleted(options) {
165
+ const event = {
166
+ type: "example.completed",
167
+ feature: options.feature,
168
+ scenarioOutline: options.scenarioOutline,
169
+ example: options.example,
170
+ pickle: options.pickle,
171
+ ...options.rule ? { rule: options.rule } : {},
172
+ ...this.base(options)
173
+ };
174
+ await this.dispatcher.dispatch(event);
175
+ }
176
+ async backgroundStarted(options) {
177
+ const event = {
178
+ type: "background.started",
179
+ feature: options.feature,
180
+ background: options.background,
181
+ pickle: options.pickle,
182
+ ...options.rule ? { rule: options.rule } : {},
183
+ ...this.base(options)
184
+ };
185
+ await this.dispatcher.dispatch(event);
186
+ }
187
+ async backgroundCompleted(options) {
188
+ const event = {
189
+ type: "background.completed",
190
+ feature: options.feature,
191
+ background: options.background,
192
+ pickle: options.pickle,
193
+ ...options.rule ? { rule: options.rule } : {},
194
+ ...this.base(options)
195
+ };
196
+ await this.dispatcher.dispatch(event);
197
+ }
198
+ async stepStarted(options) {
199
+ const event = {
200
+ type: "step.started",
201
+ feature: options.feature,
202
+ scenario: options.scenario,
203
+ step: options.step,
204
+ pickle: options.pickle,
205
+ ...options.rule ? { rule: options.rule } : {},
206
+ ...this.base(options)
207
+ };
208
+ await this.dispatcher.dispatch(event);
209
+ }
210
+ async stepCompleted(options) {
211
+ const event = {
212
+ type: "step.completed",
213
+ feature: options.feature,
214
+ scenario: options.scenario,
215
+ step: options.step,
216
+ pickle: options.pickle,
217
+ ...options.rule ? { rule: options.rule } : {},
218
+ ...this.base(options)
219
+ };
220
+ await this.dispatcher.dispatch(event);
221
+ }
222
+ async hookStarted(options) {
223
+ const event = {
224
+ type: "hook.started",
225
+ hook: options.hook,
226
+ ...options.hook.feature ? { feature: options.hook.feature } : {},
227
+ ...options.hook.rule ? { rule: options.hook.rule } : {},
228
+ ...options.hook.scenario ? { scenario: options.hook.scenario } : {},
229
+ ...options.hook.scenarioOutline ? { scenarioOutline: options.hook.scenarioOutline } : {},
230
+ ...options.hook.example ? { example: options.hook.example } : {},
231
+ ...options.hook.background ? { background: options.hook.background } : {},
232
+ ...options.hook.step ? { step: options.hook.step } : {},
233
+ ...options.hook.pickle ? { pickle: options.hook.pickle } : {},
234
+ ...this.base(options)
235
+ };
236
+ await this.dispatcher.dispatch(event);
237
+ }
238
+ async hookCompleted(options) {
239
+ const event = {
240
+ type: "hook.completed",
241
+ hook: options.hook,
242
+ ...options.hook.feature ? { feature: options.hook.feature } : {},
243
+ ...options.hook.rule ? { rule: options.hook.rule } : {},
244
+ ...options.hook.scenario ? { scenario: options.hook.scenario } : {},
245
+ ...options.hook.scenarioOutline ? { scenarioOutline: options.hook.scenarioOutline } : {},
246
+ ...options.hook.example ? { example: options.hook.example } : {},
247
+ ...options.hook.background ? { background: options.hook.background } : {},
248
+ ...options.hook.step ? { step: options.hook.step } : {},
249
+ ...options.hook.pickle ? { pickle: options.hook.pickle } : {},
250
+ ...this.base(options)
287
251
  };
252
+ await this.dispatcher.dispatch(event);
288
253
  }
254
+ async statusChanged(options) {
255
+ const event = {
256
+ type: "status.changed",
257
+ status: options.status,
258
+ ...options.previousStatus ? { previousStatus: options.previousStatus } : {},
259
+ ...options.feature ? { feature: options.feature } : {},
260
+ ...options.rule ? { rule: options.rule } : {},
261
+ ...options.scenario ? { scenario: options.scenario } : {},
262
+ ...options.scenarioOutline ? { scenarioOutline: options.scenarioOutline } : {},
263
+ ...options.example ? { example: options.example } : {},
264
+ ...options.pickle ? { pickle: options.pickle } : {},
265
+ ...this.base(options)
266
+ };
267
+ await this.dispatcher.dispatch(event);
268
+ }
269
+ async errorRaised(options) {
270
+ const event = {
271
+ type: "error",
272
+ error: options.error,
273
+ phase: options.phase,
274
+ ...options.feature ? { feature: options.feature } : {},
275
+ ...options.rule ? { rule: options.rule } : {},
276
+ ...options.scenario ? { scenario: options.scenario } : {},
277
+ ...options.scenarioOutline ? { scenarioOutline: options.scenarioOutline } : {},
278
+ ...options.example ? { example: options.example } : {},
279
+ ...options.background ? { background: options.background } : {},
280
+ ...options.pickle ? { pickle: options.pickle } : {},
281
+ ...this.base(options)
282
+ };
283
+ await this.dispatcher.dispatch(event);
284
+ }
285
+ base(options) {
286
+ const base = {
287
+ id: options.id ?? this.createId(),
288
+ timestamp: options.timestamp ?? this.now()
289
+ };
290
+ if (options.metadata !== void 0) {
291
+ base.metadata = options.metadata;
292
+ }
293
+ return base;
294
+ }
295
+ };
296
+
297
+ // src/bus.ts
298
+ var BUS_KEY = Symbol.for("@autometa/events/bus");
299
+ function getEventBus() {
300
+ const store = globalThis;
301
+ const existing = store[BUS_KEY];
302
+ if (existing) {
303
+ return existing;
304
+ }
305
+ const dispatcher = EventDispatcher.create();
306
+ const emitter = new EventEmitter(dispatcher);
307
+ const bus = { dispatcher, emitter };
308
+ store[BUS_KEY] = bus;
309
+ return bus;
310
+ }
311
+ function getEventDispatcher() {
312
+ return getEventBus().dispatcher;
313
+ }
314
+ function getEventEmitter() {
315
+ return getEventBus().emitter;
316
+ }
317
+ function resetEventBus() {
318
+ const store = globalThis;
319
+ const existing = store[BUS_KEY];
320
+ if (existing) {
321
+ existing.dispatcher.clear();
322
+ }
323
+ store[BUS_KEY] = void 0;
324
+ }
325
+
326
+ // src/hooks.ts
327
+ var HookKind = {
328
+ BEFORE_FEATURE: "beforeFeature",
329
+ AFTER_FEATURE: "afterFeature",
330
+ BEFORE_RULE: "beforeRule",
331
+ AFTER_RULE: "afterRule",
332
+ BEFORE_SCENARIO: "beforeScenario",
333
+ AFTER_SCENARIO: "afterScenario",
334
+ BEFORE_SCENARIO_OUTLINE: "beforeScenarioOutline",
335
+ AFTER_SCENARIO_OUTLINE: "afterScenarioOutline",
336
+ BEFORE_EXAMPLE: "beforeExample",
337
+ AFTER_EXAMPLE: "afterExample",
338
+ BEFORE_BACKGROUND: "beforeBackground",
339
+ AFTER_BACKGROUND: "afterBackground",
340
+ BEFORE_STEP: "beforeStep",
341
+ AFTER_STEP: "afterStep",
342
+ SETUP: "setup",
343
+ TEARDOWN: "teardown",
344
+ CUSTOM: "custom"
289
345
  };
290
346
 
291
- // src/test-status.ts
292
- var Status = {
293
- FAILED: "FAILED",
294
- BROKEN: "BROKEN",
295
- PASSED: "PASSED",
296
- SKIPPED: "SKIPPED"
347
+ // src/listener.ts
348
+ function registerTestListener(listener, options = {}) {
349
+ const dispatcher = options.dispatcher ?? getEventDispatcher();
350
+ const unsubscribers = [];
351
+ const subscribe = (type, handler) => {
352
+ if (!handler && !listener.onEvent) {
353
+ return;
354
+ }
355
+ unsubscribers.push(
356
+ dispatcher.subscribe(type, async (envelope) => {
357
+ if (listener.onEvent) {
358
+ await listener.onEvent(envelope);
359
+ }
360
+ if (handler) {
361
+ await handler(envelope);
362
+ }
363
+ })
364
+ );
365
+ };
366
+ subscribe("feature.started", listener.onFeatureStarted);
367
+ subscribe("feature.completed", listener.onFeatureCompleted);
368
+ subscribe("rule.started", listener.onRuleStarted);
369
+ subscribe("rule.completed", listener.onRuleCompleted);
370
+ subscribe("scenario.started", listener.onScenarioStarted);
371
+ subscribe("scenario.completed", listener.onScenarioCompleted);
372
+ subscribe(
373
+ "scenarioOutline.started",
374
+ listener.onScenarioOutlineStarted
375
+ );
376
+ subscribe(
377
+ "scenarioOutline.completed",
378
+ listener.onScenarioOutlineCompleted
379
+ );
380
+ subscribe("example.started", listener.onExampleStarted);
381
+ subscribe("example.completed", listener.onExampleCompleted);
382
+ subscribe("background.started", listener.onBackgroundStarted);
383
+ subscribe("background.completed", listener.onBackgroundCompleted);
384
+ subscribe("step.started", listener.onStepStarted);
385
+ subscribe("step.completed", listener.onStepCompleted);
386
+ subscribe("hook.started", listener.onHookStarted);
387
+ subscribe("hook.completed", listener.onHookCompleted);
388
+ subscribe("status.changed", listener.onStatusChanged);
389
+ subscribe("error", listener.onError);
390
+ return () => {
391
+ for (const unsubscribe of unsubscribers) {
392
+ unsubscribe();
393
+ }
394
+ };
395
+ }
396
+
397
+ // src/status.ts
398
+ var TestStatus = {
399
+ IDLE: "idle",
400
+ RUNNING: "running",
401
+ PASSED: "passed",
402
+ FAILED: "failed",
403
+ SKIPPED: "skipped",
404
+ BROKEN: "broken"
297
405
  };
298
- // Annotate the CommonJS export names for ESM import in node:
299
- 0 && (module.exports = {
300
- ArgsEventSchema,
301
- EndAfterOptsSchema,
302
- EndBeforeOptsSchema,
303
- EndFeatureOptsSchema,
304
- EndRuleOptsSchema,
305
- EndScenarioOptsSchema,
306
- EndScenarioOutlineOptsSchema,
307
- EndSetupOptsSchema,
308
- EndStepOptsSchema,
309
- EndTeardownOptsSchema,
310
- ErrorEventSchema,
311
- EventOptionsSchema,
312
- EventSubscriberSchema,
313
- ProviderSubscriber,
314
- StartAfterOptsSchema,
315
- StartBeforeOptsSchema,
316
- StartFeatureOptsSchema,
317
- StartScenarioOptsSchema,
318
- StartScenarioOutlineOptsSchema,
319
- StartSetupOptsSchema,
320
- StartStepOptsSchema,
321
- StartTeardownOptsSchema,
322
- Status,
323
- StatusSchema,
324
- TestEmitter,
325
- TestEventEmitter,
326
- UUIDStringSchema
327
- });
406
+ function isTerminalStatus(status) {
407
+ return status === TestStatus.PASSED || status === TestStatus.FAILED || status === TestStatus.SKIPPED || status === TestStatus.BROKEN;
408
+ }
409
+
410
+ export { EventDispatcher, EventDispatcherToken, EventEmitter, HookKind, TestStatus, getEventBus, getEventDispatcher, getEventEmitter, isTerminalStatus, registerTestListener, resetEventBus };
411
+ //# sourceMappingURL=out.js.map
328
412
  //# sourceMappingURL=index.js.map