@squide/firefly 15.0.4 → 16.0.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.
Files changed (70) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/AppRouter.js.map +1 -1
  3. package/dist/AppRouterContext.js.map +1 -1
  4. package/dist/AppRouterReducer.d.ts +3 -4
  5. package/dist/AppRouterReducer.js +51 -82
  6. package/dist/AppRouterReducer.js.map +1 -1
  7. package/dist/AppRouterStore.js.map +1 -1
  8. package/dist/FireflyPlugin.d.ts +6 -0
  9. package/dist/FireflyPlugin.js +6 -0
  10. package/dist/FireflyPlugin.js.map +1 -0
  11. package/dist/FireflyProvider.js.map +1 -1
  12. package/dist/FireflyRuntime.d.ts +9 -7
  13. package/dist/FireflyRuntime.js +20 -28
  14. package/dist/FireflyRuntime.js.map +1 -1
  15. package/dist/GlobalDataQueriesError.js.map +1 -1
  16. package/dist/RootRoute.js.map +1 -1
  17. package/dist/honeycomb/activeSpan.js.map +1 -1
  18. package/dist/honeycomb/createTraceContextId.js.map +1 -1
  19. package/dist/honeycomb/initializeHoneycomb.js.map +1 -1
  20. package/dist/honeycomb/registerHoneycombInstrumentation.d.ts +8 -0
  21. package/dist/honeycomb/registerHoneycombInstrumentation.js +19 -136
  22. package/dist/honeycomb/registerHoneycombInstrumentation.js.map +1 -1
  23. package/dist/honeycomb/tracer.js.map +1 -1
  24. package/dist/honeycomb/utils.js.map +1 -1
  25. package/dist/index.d.ts +2 -3
  26. package/dist/index.js +4 -5
  27. package/dist/index.js.map +1 -1
  28. package/dist/initializeFirefly.d.ts +6 -6
  29. package/dist/initializeFirefly.js +26 -35
  30. package/dist/initializeFirefly.js.map +1 -1
  31. package/dist/internal.d.ts +6 -0
  32. package/dist/internal.js +26 -0
  33. package/dist/internal.js.map +1 -0
  34. package/dist/useAppRouterStore.js.map +1 -1
  35. package/dist/useCanFetchProtectedData.js.map +1 -1
  36. package/dist/useCanFetchPublicData.js.map +1 -1
  37. package/dist/useCanRegisterDeferredRegistrations.js.map +1 -1
  38. package/dist/useCanUpdateDeferredRegistrations.js.map +1 -1
  39. package/dist/useDeferredRegistrations.d.ts +1 -5
  40. package/dist/useDeferredRegistrations.js +2 -5
  41. package/dist/useDeferredRegistrations.js.map +1 -1
  42. package/dist/useExecuteOnce.js.map +1 -1
  43. package/dist/useIsActiveRouteProtected.js.map +1 -1
  44. package/dist/useIsBootstrapping.js.map +1 -1
  45. package/dist/useNavigationItems.js.map +1 -1
  46. package/dist/useProtectedDataHandler.js.map +1 -1
  47. package/dist/useProtectedDataQueries.js.map +1 -1
  48. package/dist/usePublicDataHandler.js.map +1 -1
  49. package/dist/usePublicDataQueries.js.map +1 -1
  50. package/dist/useRegisterDeferredRegistrations.d.ts +1 -4
  51. package/dist/useRegisterDeferredRegistrations.js +1 -5
  52. package/dist/useRegisterDeferredRegistrations.js.map +1 -1
  53. package/dist/useStrictRegistrationMode.js +10 -17
  54. package/dist/useStrictRegistrationMode.js.map +1 -1
  55. package/dist/useUpdateDeferredRegistrations.d.ts +3 -4
  56. package/dist/useUpdateDeferredRegistrations.js +6 -6
  57. package/dist/useUpdateDeferredRegistrations.js.map +1 -1
  58. package/package.json +30 -28
  59. package/src/AppRouterReducer.ts +62 -100
  60. package/src/FireflyPlugin.ts +11 -0
  61. package/src/FireflyRuntime.tsx +31 -34
  62. package/src/honeycomb/initializeHoneycomb.ts +0 -2
  63. package/src/honeycomb/registerHoneycombInstrumentation.ts +30 -169
  64. package/src/index.ts +14 -3
  65. package/src/initializeFirefly.ts +51 -48
  66. package/src/internal.ts +22 -0
  67. package/src/useDeferredRegistrations.ts +3 -12
  68. package/src/useRegisterDeferredRegistrations.ts +1 -2
  69. package/src/useStrictRegistrationMode.ts +10 -15
  70. package/src/useUpdateDeferredRegistrations.ts +8 -2
@@ -1,20 +1,19 @@
1
1
  import type { RegisterRouteOptions, RuntimeMethodOptions, RuntimeOptions } from "@squide/core";
2
- import { MswPlugin, MswPluginName } from "@squide/msw";
2
+ import { MswPlugin, MswPluginName, MswState } from "@squide/msw";
3
3
  import { type IReactRouterRuntime, ReactRouterRuntime, ReactRouterRuntimeScope, type Route } from "@squide/react-router";
4
4
  import type { HoneycombInstrumentationPartialClient } from "@workleap-telemetry/core";
5
5
  import type { Logger } from "@workleap/logging";
6
6
  import type { RequestHandler } from "msw";
7
- import { getAreModulesRegistered } from "./AppRouterReducer.ts";
8
7
  import { type AppRouterStore, createAppRouterStore } from "./AppRouterStore.ts";
9
8
 
10
- export interface FireflyRuntimeOptions extends RuntimeOptions {
11
- useMsw?: boolean;
9
+ export interface FireflyRuntimeOptions<TRuntime extends FireflyRuntime = FireflyRuntime> extends RuntimeOptions<TRuntime> {
12
10
  honeycombInstrumentationClient?: HoneycombInstrumentationPartialClient;
13
11
  }
14
12
 
15
13
  export interface RegisterRequestHandlersOptions extends RuntimeMethodOptions {}
16
14
 
17
15
  export interface IFireflyRuntime extends IReactRouterRuntime {
16
+ getMswState(): MswState;
18
17
  registerRequestHandlers: (handlers: RequestHandler[]) => void;
19
18
  get requestHandlers(): RequestHandler[];
20
19
  get appRouterStore(): AppRouterStore;
@@ -22,35 +21,28 @@ export interface IFireflyRuntime extends IReactRouterRuntime {
22
21
  get honeycombInstrumentationClient(): HoneycombInstrumentationPartialClient | undefined;
23
22
  }
24
23
 
25
- export class FireflyRuntime extends ReactRouterRuntime implements IFireflyRuntime {
24
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
25
+ export class FireflyRuntime<TRuntime extends FireflyRuntime = any> extends ReactRouterRuntime<TRuntime> implements IFireflyRuntime {
26
26
  protected _appRouterStore: AppRouterStore;
27
- protected _useMsw: boolean;
28
27
  protected _honeycombInstrumentationClient: HoneycombInstrumentationPartialClient | undefined;
29
28
 
30
- constructor({ plugins, useMsw, honeycombInstrumentationClient, ...options }: FireflyRuntimeOptions = {}) {
31
- if (useMsw) {
32
- super({
33
- plugins: [
34
- ...(plugins ?? []),
35
- runtime => new MswPlugin(runtime)
36
- ],
37
- ...options
38
- });
39
-
40
- this._useMsw = true;
41
- } else {
42
- super({
43
- plugins,
44
- ...options
45
- });
46
-
47
- this._useMsw = false;
48
- }
29
+ constructor({ honeycombInstrumentationClient, ...options }: FireflyRuntimeOptions = {}) {
30
+ super(options);
49
31
 
50
32
  this._appRouterStore = createAppRouterStore(this._logger);
51
33
  this._honeycombInstrumentationClient = honeycombInstrumentationClient;
52
34
  }
53
35
 
36
+ getMswState() {
37
+ const mswPlugin = this.getPlugin(MswPluginName) as MswPlugin;
38
+
39
+ if (!mswPlugin) {
40
+ throw new Error("[squide] Cannot register the provided MSW request handlers because the runtime hasn't been initialized with MSW. Did you instanciate the FireflyRuntime with the \"useMsw\" option?");
41
+ }
42
+
43
+ return mswPlugin.mswState;
44
+ }
45
+
54
46
  registerRequestHandlers(handlers: RequestHandler[], options: RegisterRequestHandlersOptions = {}) {
55
47
  const logger = this._getLogger(options);
56
48
  const mswPlugin = this.getPlugin(MswPluginName) as MswPlugin;
@@ -59,7 +51,7 @@ export class FireflyRuntime extends ReactRouterRuntime implements IFireflyRuntim
59
51
  throw new Error("[squide] Cannot register the provided MSW request handlers because the runtime hasn't been initialized with MSW. Did you instanciate the FireflyRuntime with the \"useMsw\" option?");
60
52
  }
61
53
 
62
- if (getAreModulesRegistered()) {
54
+ if (this.moduleManager.getAreModulesRegistered()) {
63
55
  throw new Error("[squide] Cannot register an MSW request handlers once the modules are registered. Are you trying to register an MSW request handler in a deferred registration function? Only navigation items can be registered in a deferred registration function.");
64
56
  }
65
57
 
@@ -80,7 +72,7 @@ export class FireflyRuntime extends ReactRouterRuntime implements IFireflyRuntim
80
72
  }
81
73
 
82
74
  registerRoute(route: Route, options: RegisterRouteOptions = {}) {
83
- if (getAreModulesRegistered()) {
75
+ if (this.moduleManager.getAreModulesRegistered()) {
84
76
  throw new Error("[squide] Cannot register a route once the modules are registered. Are you trying to register a route in a deferred registration function? Only navigation items can be registered in a deferred registration function.");
85
77
  }
86
78
 
@@ -92,19 +84,23 @@ export class FireflyRuntime extends ReactRouterRuntime implements IFireflyRuntim
92
84
  }
93
85
 
94
86
  get isMswEnabled() {
95
- return this._useMsw;
87
+ return this._plugins.some(x => x.name === MswPluginName);
96
88
  }
97
89
 
98
90
  get honeycombInstrumentationClient() {
99
91
  return this._honeycombInstrumentationClient;
100
92
  }
101
93
 
102
- startScope(logger: Logger): FireflyRuntime {
103
- return (new FireflyRuntimeScope(this, logger) as unknown) as FireflyRuntime;
94
+ startScope(logger: Logger): TRuntime {
95
+ return (new FireflyRuntimeScope(this, logger) as unknown) as TRuntime;
104
96
  }
105
97
  }
106
98
 
107
99
  export class FireflyRuntimeScope<TRuntime extends FireflyRuntime = FireflyRuntime> extends ReactRouterRuntimeScope<TRuntime> implements IFireflyRuntime {
100
+ getMswState() {
101
+ return this._runtime.getMswState();
102
+ }
103
+
108
104
  registerRequestHandlers(handlers: RequestHandler[], options: RegisterRequestHandlersOptions = {}) {
109
105
  this._runtime.registerRequestHandlers(handlers, {
110
106
  ...options,
@@ -112,19 +108,20 @@ export class FireflyRuntimeScope<TRuntime extends FireflyRuntime = FireflyRuntim
112
108
  });
113
109
  }
114
110
 
111
+ // Must define a return type otherwise we get an "error TS2742: The inferred type of 'requestHandlers' cannot be named" error.
115
112
  get requestHandlers(): RequestHandler[] {
116
113
  return this._runtime.requestHandlers;
117
114
  }
118
115
 
119
- get appRouterStore() {
120
- return this._runtime.appRouterStore;
116
+ get appRouterStore(): AppRouterStore {
117
+ throw new Error("[squide] Cannot retrieve the app router store from a runtime scope instance.");
121
118
  }
122
119
 
123
120
  get isMswEnabled() {
124
121
  return this._runtime.isMswEnabled;
125
122
  }
126
123
 
127
- get honeycombInstrumentationClient() {
128
- return this._runtime.honeycombInstrumentationClient;
124
+ get honeycombInstrumentationClient(): HoneycombInstrumentationPartialClient {
125
+ throw new Error("[squide] Cannot retrieve the Honeycomb instrumentation client from a runtime scope instance.");
129
126
  }
130
127
  }
@@ -17,5 +17,3 @@ export async function initializeHoneycomb(runtime: FireflyRuntime) {
17
17
  runtime.logger.information("[squide] Cannot register Honeycomb instrumentation because the host application hasn't provided a client.");
18
18
  }
19
19
  }
20
-
21
-
@@ -20,43 +20,27 @@ import {
20
20
  type LocalModulesRegistrationStartedEventPayload,
21
21
  type ModuleRegistrationError
22
22
  } from "@squide/core";
23
- import {
24
- DeferredRegistrationsUpdateCompletedEvent,
25
- DeferredRegistrationsUpdateStartedEvent,
26
- RemoteModuleDeferredRegistrationFailedEvent,
27
- RemoteModuleDeferredRegistrationUpdateFailedEvent,
28
- type RemoteModuleRegistrationError,
29
- RemoteModuleRegistrationFailedEvent,
30
- RemoteModulesDeferredRegistrationCompletedEvent,
31
- type RemoteModulesDeferredRegistrationCompletedEventPayload,
32
- RemoteModulesDeferredRegistrationStartedEvent,
33
- type RemoteModulesDeferredRegistrationStartedEventPayload,
34
- RemoteModulesDeferredRegistrationsUpdateCompletedEvent,
35
- type RemoteModulesDeferredRegistrationsUpdateCompletedEventPayload,
36
- RemoteModulesDeferredRegistrationsUpdateStartedEvent,
37
- type RemoteModulesDeferredRegistrationsUpdateStartedEventPayload,
38
- RemoteModulesRegistrationCompletedEvent,
39
- type RemoteModulesRegistrationCompletedEventPayload,
40
- RemoteModulesRegistrationStartedEvent,
41
- type RemoteModulesRegistrationStartedEventPayload
42
- } from "@squide/module-federation";
43
23
  import { ApplicationBoostrappedEvent, type AppRouterWaitState, ModulesReadyEvent, ModulesRegisteredEvent, MswReadyEvent, ProtectedDataReadyEvent, PublicDataReadyEvent } from "../AppRouterReducer.ts";
24
+ import { FireflyPlugin } from "../FireflyPlugin.ts";
44
25
  import type { FireflyRuntime } from "../FireflyRuntime.tsx";
45
26
  import { ApplicationBootstrappingStartedEvent } from "../initializeFirefly.ts";
46
27
  import { ProtectedDataFetchFailedEvent, ProtectedDataFetchStartedEvent } from "../useProtectedDataQueries.ts";
47
28
  import { PublicDataFetchFailedEvent, PublicDataFetchStartedEvent } from "../usePublicDataQueries.ts";
29
+ import { DeferredRegistrationsUpdateCompletedEvent, DeferredRegistrationsUpdateStartedEvent } from "../useUpdateDeferredRegistrations.ts";
48
30
  import { type ActiveSpan, createOverrideFetchRequestSpanWithActiveSpanContext, registerActiveSpanStack } from "./activeSpan.ts";
49
31
  import { getTracer } from "./tracer.ts";
50
32
  import { endActiveSpan, startActiveChildSpan, startChildSpan, startSpan, traceError } from "./utils.ts";
51
33
 
52
34
  // TIPS:
53
- // To query those traces in Honeycomb, use the following query filter: "root.name = squide-bootstrapping".
35
+ // To query those traces in Honeycomb, use the following query filter:
36
+ // "root.name = squide-bootstrapping" and
37
+ // "root.name = squide-deferred-registrations-update".
54
38
 
55
- interface AddProtectedListenerOptions extends AddListenerOptions {
39
+ export interface AddProtectedListenerOptions extends AddListenerOptions {
56
40
  onError?: (error: unknown) => void;
57
41
  }
58
42
 
59
- function addProtectedListener(runtime: FireflyRuntime, eventName: EventName, callback: EventCallbackFunction, options?: AddProtectedListenerOptions) {
43
+ export function addProtectedListener(runtime: FireflyRuntime, eventName: EventName, callback: EventCallbackFunction, options?: AddProtectedListenerOptions) {
60
44
  const protectedCallback = (...args: unknown[]) => {
61
45
  try {
62
46
  callback(...args);
@@ -71,6 +55,9 @@ function addProtectedListener(runtime: FireflyRuntime, eventName: EventName, cal
71
55
  runtime.eventBus.addListener(eventName, protectedCallback, options);
72
56
  }
73
57
 
58
+ export type GetSpanFunction = () => Span;
59
+ export type HoneycombTrackingUnmanagedErrorHandler = (error: unknown) => void;
60
+
74
61
  type DataFetchState = "none" | "fetching-data" | "public-data-ready" | "protected-data-ready" | "data-ready" | "data-fetch-failed";
75
62
 
76
63
  export function reduceDataFetchEvents(
@@ -172,12 +159,11 @@ function registerTrackingListeners(runtime: FireflyRuntime) {
172
159
  let bootstrappingSpanHasEnded: boolean = false;
173
160
  let localModuleRegistrationSpan: Span;
174
161
  let localModuleDeferredRegistrationSpan: Span;
175
- let remoteModuleRegistrationSpan: Span;
176
- let remoteModuleDeferredRegistrationSpan: Span;
177
162
  let dataFetchSpan: ActiveSpan;
178
163
  let deferredRegistrationsUpdateSpan: Span;
179
164
  let localModuleDeferredRegistrationsUpdateSpan: ActiveSpan;
180
- let remoteModuleDeferredRegistrationsUpdateSpan: ActiveSpan;
165
+
166
+ const pluginsUnmanagedErrorHandlers: HoneycombTrackingUnmanagedErrorHandler[] = [];
181
167
 
182
168
  const handleUnmanagedError = (error: unknown) => {
183
169
  if (bootstrappingSpan && !bootstrappingSpanHasEnded) {
@@ -195,14 +181,6 @@ function registerTrackingListeners(runtime: FireflyRuntime) {
195
181
  localModuleDeferredRegistrationSpan.end();
196
182
  }
197
183
 
198
- if (remoteModuleRegistrationSpan) {
199
- remoteModuleRegistrationSpan.end();
200
- }
201
-
202
- if (remoteModuleDeferredRegistrationSpan) {
203
- remoteModuleDeferredRegistrationSpan.end();
204
- }
205
-
206
184
  if (dataFetchSpan) {
207
185
  dataFetchSpan.instance.end();
208
186
  }
@@ -215,9 +193,9 @@ function registerTrackingListeners(runtime: FireflyRuntime) {
215
193
  localModuleDeferredRegistrationsUpdateSpan.instance.end();
216
194
  }
217
195
 
218
- if (remoteModuleDeferredRegistrationsUpdateSpan) {
219
- remoteModuleDeferredRegistrationsUpdateSpan.instance.end();
220
- }
196
+ pluginsUnmanagedErrorHandlers.forEach(x => {
197
+ x(error);
198
+ });
221
199
  };
222
200
 
223
201
  addProtectedListener(runtime, ApplicationBootstrappingStartedEvent, () => {
@@ -332,92 +310,6 @@ function registerTrackingListeners(runtime: FireflyRuntime) {
332
310
  onError: handleUnmanagedError
333
311
  });
334
312
 
335
- addProtectedListener(runtime, RemoteModulesRegistrationStartedEvent, (payload: unknown) => {
336
- const attributes = {
337
- "app.squide.remote_count": (payload as RemoteModulesRegistrationStartedEventPayload).remoteCount
338
- };
339
-
340
- if (bootstrappingSpan) {
341
- bootstrappingSpan.addEvent("remote-module-registration-started", attributes);
342
- }
343
-
344
- remoteModuleRegistrationSpan = startChildSpan(bootstrappingSpan, (options, context) => {
345
- return getTracer().startSpan("remote-module-registration", { ...options, attributes }, context);
346
- });
347
- }, {
348
- once: true,
349
- onError: handleUnmanagedError
350
- });
351
-
352
- addProtectedListener(runtime, RemoteModulesRegistrationCompletedEvent, (payload: unknown) => {
353
- if (bootstrappingSpan) {
354
- bootstrappingSpan.addEvent("remote-module-registration-completed", {
355
- "app.squide.remote_count": (payload as RemoteModulesRegistrationCompletedEventPayload).remoteCount
356
- });
357
- }
358
-
359
- if (remoteModuleRegistrationSpan) {
360
- remoteModuleRegistrationSpan.end();
361
- }
362
- }, {
363
- once: true,
364
- onError: handleUnmanagedError
365
- });
366
-
367
- // Can occur multiple times.
368
- addProtectedListener(runtime, RemoteModuleRegistrationFailedEvent, (payload: unknown) => {
369
- const registrationError = payload as RemoteModuleRegistrationError;
370
-
371
- if (remoteModuleRegistrationSpan) {
372
- traceError(remoteModuleRegistrationSpan, registrationError);
373
- }
374
- }, {
375
- onError: handleUnmanagedError
376
- });
377
-
378
- addProtectedListener(runtime, RemoteModulesDeferredRegistrationStartedEvent, (payload: unknown) => {
379
- const attributes = {
380
- "app.squide.registration_count": (payload as RemoteModulesDeferredRegistrationStartedEventPayload).registrationCount
381
- };
382
-
383
- if (bootstrappingSpan) {
384
- bootstrappingSpan.addEvent("remote-module-deferred-registration-started", attributes);
385
- }
386
-
387
- remoteModuleDeferredRegistrationSpan = startChildSpan(bootstrappingSpan, (options, context) => {
388
- return getTracer().startSpan("remote-module-deferred-registration", { ...options, attributes }, context);
389
- });
390
- }, {
391
- once: true,
392
- onError: handleUnmanagedError
393
- });
394
-
395
- addProtectedListener(runtime, RemoteModulesDeferredRegistrationCompletedEvent, (payload: unknown) => {
396
- if (bootstrappingSpan) {
397
- bootstrappingSpan.addEvent("remote-module-deferred-registration-completed", {
398
- "app.squide.registration_count": (payload as RemoteModulesDeferredRegistrationCompletedEventPayload).registrationCount
399
- });
400
- }
401
-
402
- if (remoteModuleDeferredRegistrationSpan) {
403
- remoteModuleDeferredRegistrationSpan.end();
404
- }
405
- }, {
406
- once: true,
407
- onError: handleUnmanagedError
408
- });
409
-
410
- // Can occur multiple times.
411
- addProtectedListener(runtime, RemoteModuleDeferredRegistrationFailedEvent, (payload: unknown) => {
412
- const registrationError = payload as RemoteModuleRegistrationError;
413
-
414
- if (remoteModuleDeferredRegistrationSpan) {
415
- traceError(remoteModuleDeferredRegistrationSpan, registrationError);
416
- }
417
- }, {
418
- onError: handleUnmanagedError
419
- });
420
-
421
313
  const handleFetchDataStarted = () => {
422
314
  dataFetchSpan = startActiveChildSpan(bootstrappingSpan, (options, context) => {
423
315
  const name = "data-fetch";
@@ -576,57 +468,26 @@ function registerTrackingListeners(runtime: FireflyRuntime) {
576
468
  onError: handleUnmanagedError
577
469
  });
578
470
 
579
- // Can occur multiple times.
580
- addProtectedListener(runtime, RemoteModulesDeferredRegistrationsUpdateStartedEvent, (payload: unknown) => {
581
- const attributes = {
582
- "app.squide.registration_count": (payload as RemoteModulesDeferredRegistrationsUpdateStartedEventPayload).registrationCount
583
- };
584
-
585
- if (deferredRegistrationsUpdateSpan) {
586
- deferredRegistrationsUpdateSpan.addEvent("remote-module-deferred-registrations-update-started", attributes);
587
- }
588
-
589
- remoteModuleDeferredRegistrationsUpdateSpan = startActiveChildSpan(deferredRegistrationsUpdateSpan, (options, context) => {
590
- const name = "remote-module-deferred-registrations-update";
591
-
592
- const span = getTracer().startSpan(name, {
593
- attributes,
594
- ...options
595
- }, context);
596
-
597
- return {
598
- name,
599
- span
600
- };
601
- });
602
- }, {
603
- onError: handleUnmanagedError
604
- });
471
+ const getBootstrappingSpan: GetSpanFunction = () => bootstrappingSpan;
472
+ const getDeferredRegistrationsUpdateSpan: GetSpanFunction = () => deferredRegistrationsUpdateSpan;
605
473
 
606
- // Can occur multiple times.
607
- addProtectedListener(runtime, RemoteModulesDeferredRegistrationsUpdateCompletedEvent, (payload: unknown) => {
608
- if (deferredRegistrationsUpdateSpan) {
609
- deferredRegistrationsUpdateSpan.addEvent("remote-module-deferred-registrations-update-completed", {
610
- "app.squide.registration_count": (payload as RemoteModulesDeferredRegistrationsUpdateCompletedEventPayload).registrationCount
611
- });
612
- }
474
+ const handlePluginUnmanagedError: HoneycombTrackingUnmanagedErrorHandler = (error: unknown) => {
475
+ handleUnmanagedError(error);
476
+ };
613
477
 
614
- if (remoteModuleDeferredRegistrationsUpdateSpan) {
615
- endActiveSpan(remoteModuleDeferredRegistrationsUpdateSpan);
616
- }
617
- }, {
618
- onError: handleUnmanagedError
619
- });
478
+ // Register plugins specific handlers for Honeycomb telemetry.
479
+ runtime.plugins.forEach(x => {
480
+ const plugin = x as FireflyPlugin;
620
481
 
621
- // Can occur multiple times.
622
- addProtectedListener(runtime, RemoteModuleDeferredRegistrationUpdateFailedEvent, (payload: unknown) => {
623
- const registrationError = payload as RemoteModuleRegistrationError;
482
+ if (plugin.registerHoneycombTrackingListeners) {
483
+ const unmanagedErrorHandler = plugin.registerHoneycombTrackingListeners(
484
+ getBootstrappingSpan,
485
+ getDeferredRegistrationsUpdateSpan,
486
+ handlePluginUnmanagedError
487
+ );
624
488
 
625
- if (remoteModuleDeferredRegistrationsUpdateSpan) {
626
- traceError(remoteModuleDeferredRegistrationsUpdateSpan.instance, registrationError);
489
+ pluginsUnmanagedErrorHandlers.push(unmanagedErrorHandler);
627
490
  }
628
- }, {
629
- onError: handleUnmanagedError
630
491
  });
631
492
  }
632
493
 
package/src/index.ts CHANGED
@@ -1,14 +1,25 @@
1
1
  export * from "@squide/core";
2
- export * from "@squide/module-federation";
3
2
  export * from "@squide/msw";
4
3
  export * from "@squide/react-router";
5
4
 
5
+ export type { FireflyPlugin } from "./FireflyPlugin.ts";
6
6
  export * from "./FireflyProvider.tsx";
7
7
  export * from "./FireflyRuntime.tsx";
8
8
 
9
9
  export * from "./AppRouter.tsx";
10
- export * from "./AppRouterContext.ts";
11
- export * from "./AppRouterReducer.ts";
10
+ export {
11
+ ActiveRouteIsProtectedEvent,
12
+ ActiveRouteIsPublicEvent,
13
+ ApplicationBoostrappedEvent,
14
+ DeferredRegistrationsUpdatedEvent,
15
+ ModulesReadyEvent,
16
+ ModulesRegisteredEvent,
17
+ MswReadyEvent,
18
+ ProtectedDataReadyEvent,
19
+ ProtectedDataUpdatedEvent,
20
+ PublicDataReadyEvent,
21
+ PublicDataUpdatedEvent
22
+ } from "./AppRouterReducer.ts";
12
23
 
13
24
  export * from "./AppRouterStore.ts";
14
25
  export * from "./GlobalDataQueriesError.ts";
@@ -1,6 +1,5 @@
1
- import { isFunction, registerLocalModules, type ModuleRegisterFunction, type RegisterModulesOptions } from "@squide/core";
2
- import { registerRemoteModules, type RemoteDefinition } from "@squide/module-federation";
3
- import { setMswAsReady } from "@squide/msw";
1
+ import { isFunction, ModuleDefinition, toLocalModuleDefinitions, type ModuleRegisterFunction, type RegisterModulesOptions } from "@squide/core";
2
+ import { MswPlugin } from "@squide/msw";
4
3
  import type { HoneycombInstrumentationPartialClient } from "@workleap-telemetry/core";
5
4
  import { FireflyRuntime, type FireflyRuntimeOptions } from "./FireflyRuntime.tsx";
6
5
  import { initializeHoneycomb } from "./honeycomb/initializeHoneycomb.ts";
@@ -13,26 +12,19 @@ export type StartMswFunction<TRuntime = FireflyRuntime> = (runtime: TRuntime) =>
13
12
 
14
13
  export interface InitializeFireflyOptions<TRuntime extends FireflyRuntime, TContext = unknown, TData = unknown> extends RegisterModulesOptions<TContext>, FireflyRuntimeOptions {
15
14
  localModules?: ModuleRegisterFunction<TRuntime, TContext, TData>[];
16
- remotes?: RemoteDefinition[];
15
+ moduleDefinitions?: ModuleDefinition<TRuntime, TContext, TData>[];
16
+ useMsw?: boolean;
17
17
  honeycombInstrumentationClient?: HoneycombInstrumentationPartialClient;
18
18
  startMsw?: StartMswFunction<FireflyRuntime>;
19
19
  onError?: OnInitializationErrorFunction;
20
20
  }
21
21
 
22
- function propagateRegistrationErrors(results: PromiseSettledResult<unknown[]>, onError: OnInitializationErrorFunction) {
23
- if (results) {
24
- if (results.status === "fulfilled") {
25
- results.value.forEach(x => {
26
- onError(x);
27
- });
28
- }
29
- }
30
- }
31
-
32
- export function bootstrap<TRuntime extends FireflyRuntime = FireflyRuntime, TContext = unknown, TData = unknown>(runtime: TRuntime, options: InitializeFireflyOptions<TRuntime, TContext, TData> = {}) {
22
+ export function bootstrap<TRuntime extends FireflyRuntime = FireflyRuntime, TContext = unknown, TData = unknown>(
23
+ runtime: TRuntime,
24
+ modulesDefinitions: ModuleDefinition<TRuntime, TContext, TData>[],
25
+ options: Omit<InitializeFireflyOptions<TRuntime, TContext, TData>, "localModules" | "moduleDefinitions"> = {}
26
+ ) {
33
27
  const {
34
- localModules = [],
35
- remotes = [],
36
28
  startMsw,
37
29
  onError,
38
30
  context
@@ -40,43 +32,51 @@ export function bootstrap<TRuntime extends FireflyRuntime = FireflyRuntime, TCon
40
32
 
41
33
  runtime.eventBus.dispatch(ApplicationBootstrappingStartedEvent);
42
34
 
43
- Promise.allSettled([
44
- registerLocalModules<TRuntime, TContext, TData>(localModules, runtime, { context }),
45
- registerRemoteModules(remotes, runtime, { context })
46
- ]).then(results => {
47
- if (runtime.isMswEnabled) {
48
- if (!isFunction(startMsw)) {
49
- throw new Error("[squide] When MSW is enabled, the \"startMsw\" function must be provided.");
35
+ runtime.moduleManager.registerModules(modulesDefinitions, { context })
36
+ .then(results => {
37
+ if (runtime.isMswEnabled) {
38
+ if (!isFunction(startMsw)) {
39
+ throw new Error("[squide] When MSW is enabled, the \"startMsw\" function must be provided.");
40
+ }
41
+
42
+ startMsw(runtime)
43
+ .then(() => {
44
+ if (runtime.isMswEnabled) {
45
+ runtime.getMswState().setAsReady();
46
+ }
47
+ })
48
+ .catch((error: unknown) => {
49
+ runtime.logger
50
+ .withText("[squide] An error occured while starting MSW.")
51
+ .withError(error as Error)
52
+ .error();
53
+ });
50
54
  }
51
55
 
52
- startMsw(runtime)
53
- .then(() => {
54
- setMswAsReady();
55
- })
56
- .catch((error: unknown) => {
57
- runtime.logger
58
- .withText("[squide] An error occured while starting MSW.")
59
- .withError(error as Error)
60
- .error();
56
+ if (onError) {
57
+ results.forEach(error => {
58
+ onError(error);
61
59
  });
62
- }
63
-
64
- if (onError) {
65
- propagateRegistrationErrors(results[0], onError);
66
- propagateRegistrationErrors(results[1], onError);
67
- }
68
- });
60
+ }
61
+ });
69
62
  }
70
63
 
71
64
  let hasExecuted = false;
72
65
 
66
+ // Should only be used by tests.
67
+ export function __resetHasExecutedGuard() {
68
+ hasExecuted = false;
69
+ }
70
+
73
71
  export function initializeFirefly<TContext = unknown, TData = unknown>(options: InitializeFireflyOptions<FireflyRuntime, TContext, TData> = {}) {
74
72
  const {
75
73
  mode,
74
+ localModules = [],
75
+ moduleDefinitions = [],
76
76
  useMsw,
77
- loggers,
78
- plugins,
77
+ plugins = [],
79
78
  honeycombInstrumentationClient,
79
+ loggers,
80
80
  onError
81
81
  } = options;
82
82
 
@@ -86,9 +86,12 @@ export function initializeFirefly<TContext = unknown, TData = unknown>(options:
86
86
 
87
87
  hasExecuted = true;
88
88
 
89
+ if (useMsw) {
90
+ plugins.push(x => new MswPlugin(x));
91
+ }
92
+
89
93
  const runtime = new FireflyRuntime({
90
94
  mode,
91
- useMsw,
92
95
  honeycombInstrumentationClient,
93
96
  loggers,
94
97
  plugins
@@ -101,12 +104,12 @@ export function initializeFirefly<TContext = unknown, TData = unknown>(options:
101
104
  }
102
105
  })
103
106
  .finally(() => {
104
- bootstrap(runtime, options);
107
+ bootstrap(
108
+ runtime,
109
+ [...moduleDefinitions, ...toLocalModuleDefinitions(localModules)],
110
+ options
111
+ );
105
112
  });
106
113
 
107
114
  return runtime;
108
115
  }
109
-
110
- export function __resetHasExecuteGuard() {
111
- hasExecuted = false;
112
- }
@@ -0,0 +1,22 @@
1
+ export { AppRouterDispatcherContext, AppRouterStateContext } from "./AppRouterContext.ts";
2
+ export { __clearAppReducerDispatchProxy, __setAppReducerDispatchProxyFactory, useAppRouterReducer, type AppRouterDispatch, type AppRouterState } from "./AppRouterReducer.ts";
3
+
4
+ export type { ActiveSpan, ActiveSpanId } from "./honeycomb/activeSpan.ts";
5
+ export { addProtectedListener, type AddProtectedListenerOptions, type GetSpanFunction, type HoneycombTrackingUnmanagedErrorHandler } from "./honeycomb/registerHoneycombInstrumentation.ts";
6
+ export { getTracer } from "./honeycomb/tracer.ts";
7
+ export {
8
+ endActiveSpan,
9
+ startActiveChildSpan,
10
+ startActiveSpan,
11
+ startChildSpan,
12
+ startSpan,
13
+ traceError,
14
+ type StartActiveChildSpanFactory,
15
+ type StartActiveChildSpanFactoryReturn,
16
+ type StartActiveSpanFactory,
17
+ type StartActiveSpanFactoryReturn,
18
+ type StartChildSpanFactory,
19
+ type StartSpanFactory,
20
+ type TraceErrorOptions
21
+ } from "./honeycomb/utils.ts";
22
+
@@ -5,21 +5,12 @@ import { useCanUpdateDeferredRegistrations } from "./useCanUpdateDeferredRegistr
5
5
  import { useRegisterDeferredRegistrations } from "./useRegisterDeferredRegistrations.ts";
6
6
  import { useUpdateDeferredRegistrations } from "./useUpdateDeferredRegistrations.ts";
7
7
 
8
- export interface DeferredRegistrationsErrorsObject {
9
- localModuleErrors: ModuleRegistrationError[];
10
- remoteModuleErrors: ModuleRegistrationError[];
11
- }
12
-
13
- export type DeferredRegistrationsErrorCallback = (errorsObject: DeferredRegistrationsErrorsObject) => void;
8
+ export type DeferredRegistrationsErrorCallback = (errors: ModuleRegistrationError[]) => void;
14
9
 
15
10
  export interface UseDeferredRegistrationsOptions {
16
11
  onError?: DeferredRegistrationsErrorCallback;
17
12
  }
18
13
 
19
- function hasError({ localModuleErrors, remoteModuleErrors }: DeferredRegistrationsErrorsObject) {
20
- return localModuleErrors.length > 0 || remoteModuleErrors.length > 0;
21
- }
22
-
23
14
  export function useDeferredRegistrations(data: unknown, { onError }: UseDeferredRegistrationsOptions = {}) {
24
15
  const runtime = useRuntime();
25
16
 
@@ -34,7 +25,7 @@ export function useDeferredRegistrations(data: unknown, { onError }: UseDeferred
34
25
  const register = async () => {
35
26
  const errors = await registerDeferredRegistrations(data, runtime);
36
27
 
37
- if (hasError(errors) && onError) {
28
+ if (errors.length > 0 && onError) {
38
29
  onError(errors);
39
30
  }
40
31
  };
@@ -48,7 +39,7 @@ export function useDeferredRegistrations(data: unknown, { onError }: UseDeferred
48
39
  const update = async () => {
49
40
  const errors = await updateDeferredRegistrations(data, runtime);
50
41
 
51
- if (hasError(errors) && onError) {
42
+ if (errors.length > 0 && onError) {
52
43
  onError(errors);
53
44
  }
54
45
  };