@squide/firefly 12.0.4 → 13.0.1

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 (33) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/dist/honeycomb/activeSpan.d.ts +12 -0
  3. package/dist/honeycomb/activeSpan.js +105 -0
  4. package/dist/honeycomb/activeSpan.js.map +1 -0
  5. package/dist/honeycomb/canRegisterHoneycombInstrumentation.d.ts +1 -0
  6. package/dist/honeycomb/canRegisterHoneycombInstrumentation.js +11 -0
  7. package/dist/honeycomb/canRegisterHoneycombInstrumentation.js.map +1 -0
  8. package/dist/honeycomb/createTraceContextId.d.ts +1 -0
  9. package/dist/honeycomb/createTraceContextId.js +16 -0
  10. package/dist/honeycomb/createTraceContextId.js.map +1 -0
  11. package/dist/honeycomb/initializeHoneycomb.d.ts +2 -0
  12. package/dist/honeycomb/initializeHoneycomb.js +25 -0
  13. package/dist/honeycomb/initializeHoneycomb.js.map +1 -0
  14. package/dist/honeycomb/registerHoneycombInstrumentation.d.ts +3 -0
  15. package/dist/honeycomb/registerHoneycombInstrumentation.js +405 -0
  16. package/dist/honeycomb/registerHoneycombInstrumentation.js.map +1 -0
  17. package/dist/honeycomb/tracer.d.ts +1 -0
  18. package/dist/honeycomb/tracer.js +14 -0
  19. package/dist/honeycomb/tracer.js.map +1 -0
  20. package/dist/honeycomb/utils.d.ts +23 -0
  21. package/dist/honeycomb/utils.js +49 -0
  22. package/dist/honeycomb/utils.js.map +1 -0
  23. package/dist/initializeFirefly.js +12 -2
  24. package/dist/initializeFirefly.js.map +1 -1
  25. package/package.json +3 -1
  26. package/src/honeycomb/activeSpan.ts +131 -0
  27. package/src/honeycomb/canRegisterHoneycombInstrumentation.ts +5 -0
  28. package/src/honeycomb/createTraceContextId.ts +12 -0
  29. package/src/honeycomb/initializeHoneycomb.ts +22 -0
  30. package/src/honeycomb/registerHoneycombInstrumentation.ts +470 -0
  31. package/src/honeycomb/tracer.ts +6 -0
  32. package/src/honeycomb/utils.ts +64 -0
  33. package/src/initializeFirefly.ts +12 -2
@@ -1 +1 @@
1
- {"version":3,"file":"initializeFirefly.js","sources":["webpack://@squide/firefly/./src/initializeFirefly.ts"],"sourcesContent":["import { isFunction, registerLocalModules, type ModuleRegisterFunction, type RegisterModulesOptions } from \"@squide/core\";\nimport { registerRemoteModules, type RemoteDefinition } from \"@squide/module-federation\";\nimport { setMswAsReady } from \"@squide/msw\";\nimport { FireflyRuntime, type FireflyRuntimeOptions } from \"./FireflyRuntime.tsx\";\n\nexport const ApplicationBootstrappingStartedEvent = \"squide-app-bootstrapping-started\";\n\nexport type OnInitializationErrorFunction = (error: unknown) => void;\n\nexport type StartMswFunction<TRuntime = FireflyRuntime> = (runtime: TRuntime) => Promise<void>;\n\nexport interface InitializeFireflyOptions<TRuntime extends FireflyRuntime, TContext = unknown, TData = unknown> extends RegisterModulesOptions<TContext>, FireflyRuntimeOptions {\n localModules?: ModuleRegisterFunction<TRuntime, TContext, TData>[];\n remotes?: RemoteDefinition[];\n startMsw?: StartMswFunction<FireflyRuntime>;\n onError?: OnInitializationErrorFunction;\n}\n\nfunction propagateRegistrationErrors(results: PromiseSettledResult<unknown[]>, onError: OnInitializationErrorFunction) {\n if (results) {\n if (results.status === \"fulfilled\") {\n results.value.forEach(x => {\n onError(x);\n });\n }\n }\n}\n\nexport function bootstrap<TRuntime extends FireflyRuntime = FireflyRuntime, TContext = unknown, TData = unknown>(runtime: TRuntime, options: InitializeFireflyOptions<TRuntime, TContext, TData> = {}) {\n const {\n localModules = [],\n remotes = [],\n startMsw,\n onError,\n context\n } = options;\n\n runtime.eventBus.dispatch(ApplicationBootstrappingStartedEvent);\n\n Promise.allSettled([\n registerLocalModules<TRuntime, TContext, TData>(localModules, runtime, { context }),\n registerRemoteModules(remotes, runtime, { context })\n ]).then(results => {\n if (runtime.isMswEnabled) {\n if (!isFunction(startMsw)) {\n throw new Error(\"[squide] When MSW is enabled, the \\\"startMsw\\\" function must be provided.\");\n }\n\n startMsw(runtime)\n .then(() => {\n setMswAsReady();\n })\n .catch((error: unknown) => {\n runtime.logger.debug(\"[squide] An error occured while starting MSW.\", error);\n });\n }\n\n if (onError) {\n propagateRegistrationErrors(results[0], onError);\n propagateRegistrationErrors(results[1], onError);\n }\n });\n}\n\nlet hasExecuted = false;\n\nexport function initializeFirefly<TContext = unknown, TData = unknown>(options: InitializeFireflyOptions<FireflyRuntime, TContext, TData> = {}) {\n const {\n mode,\n useMsw,\n loggers,\n plugins\n } = options;\n\n if (hasExecuted) {\n throw new Error(\"[squide] A squide application can only be initialized once. Did you call the \\\"initializeSquide\\\" function twice?\");\n }\n\n hasExecuted = true;\n\n const runtime = new FireflyRuntime({\n mode,\n useMsw,\n loggers,\n plugins\n });\n\n bootstrap(runtime, options);\n\n return runtime;\n}\n\nexport function __resetHasExecuteGuard() {\n hasExecuted = false;\n}\n"],"names":["isFunction","registerLocalModules","registerRemoteModules","setMswAsReady","FireflyRuntime","ApplicationBootstrappingStartedEvent","propagateRegistrationErrors","results","onError","x","bootstrap","runtime","options","localModules","remotes","startMsw","context","Promise","Error","error","hasExecuted","initializeFirefly","mode","useMsw","loggers","plugins","__resetHasExecuteGuard"],"mappings":";;;;;;;;;;;;;;AAA0H;AACjC;AAC7C;AACsC;AAE3E,MAAMK,uCAAuC,mCAAmC;AAavF,SAASC,4BAA4BC,OAAwC,EAAEC,OAAsC;IACjH,IAAID,SAAS;QACT,IAAIA,QAAQ,MAAM,KAAK,aAAa;YAChCA,QAAQ,KAAK,CAAC,OAAO,CAACE,CAAAA;gBAClBD,QAAQC;YACZ;QACJ;IACJ;AACJ;AAEO,SAASC,UAAiGC,OAAiB,EAAEC,UAA+D,CAAC,CAAC;IACjM,MAAM,EACFC,eAAe,EAAE,EACjBC,UAAU,EAAE,EACZC,QAAQ,EACRP,OAAO,EACPQ,OAAO,EACV,GAAGJ;IAEJD,QAAQ,QAAQ,CAAC,QAAQ,CAACN;IAE1BY,QAAQ,UAAU,CAAC;QACfhB,0EAAoBA,CAA4BY,cAAcF,SAAS;YAAEK;QAAQ;QACjFd,wFAAqBA,CAACY,SAASH,SAAS;YAAEK;QAAQ;KACrD,EAAE,IAAI,CAACT,CAAAA;QACJ,IAAII,QAAQ,YAAY,EAAE;YACtB,IAAI,CAACX,gEAAUA,CAACe,WAAW;gBACvB,MAAM,IAAIG,MAAM;YACpB;YAEAH,SAASJ,SACJ,IAAI,CAAC;gBACFR,kEAAaA;YACjB,GACC,KAAK,CAAC,CAACgB;gBACJR,QAAQ,MAAM,CAAC,KAAK,CAAC,iDAAiDQ;YAC1E;QACR;QAEA,IAAIX,SAAS;YACTF,4BAA4BC,OAAO,CAAC,EAAE,EAAEC;YACxCF,4BAA4BC,OAAO,CAAC,EAAE,EAAEC;QAC5C;IACJ;AACJ;AAEA,IAAIY,cAAc;AAEX,SAASC,kBAAuDT,UAAqE,CAAC,CAAC;IAC1I,MAAM,EACFU,IAAI,EACJC,MAAM,EACNC,OAAO,EACPC,OAAO,EACV,GAAGb;IAEJ,IAAIQ,aAAa;QACb,MAAM,IAAIF,MAAM;IACpB;IAEAE,cAAc;IAEd,MAAMT,UAAU,IAAIP,sEAAcA,CAAC;QAC/BkB;QACAC;QACAC;QACAC;IACJ;IAEAf,UAAUC,SAASC;IAEnB,OAAOD;AACX;AAEO,SAASe;IACZN,cAAc;AAClB"}
1
+ {"version":3,"file":"initializeFirefly.js","sources":["webpack://@squide/firefly/./src/initializeFirefly.ts"],"sourcesContent":["import { isFunction, registerLocalModules, type ModuleRegisterFunction, type RegisterModulesOptions } from \"@squide/core\";\nimport { registerRemoteModules, type RemoteDefinition } from \"@squide/module-federation\";\nimport { setMswAsReady } from \"@squide/msw\";\nimport { FireflyRuntime, type FireflyRuntimeOptions } from \"./FireflyRuntime.tsx\";\nimport { initializeHoneycomb } from \"./honeycomb/initializeHoneycomb.ts\";\n\nexport const ApplicationBootstrappingStartedEvent = \"squide-app-bootstrapping-started\";\n\nexport type OnInitializationErrorFunction = (error: unknown) => void;\n\nexport type StartMswFunction<TRuntime = FireflyRuntime> = (runtime: TRuntime) => Promise<void>;\n\nexport interface InitializeFireflyOptions<TRuntime extends FireflyRuntime, TContext = unknown, TData = unknown> extends RegisterModulesOptions<TContext>, FireflyRuntimeOptions {\n localModules?: ModuleRegisterFunction<TRuntime, TContext, TData>[];\n remotes?: RemoteDefinition[];\n startMsw?: StartMswFunction<FireflyRuntime>;\n onError?: OnInitializationErrorFunction;\n}\n\nfunction propagateRegistrationErrors(results: PromiseSettledResult<unknown[]>, onError: OnInitializationErrorFunction) {\n if (results) {\n if (results.status === \"fulfilled\") {\n results.value.forEach(x => {\n onError(x);\n });\n }\n }\n}\n\nexport function bootstrap<TRuntime extends FireflyRuntime = FireflyRuntime, TContext = unknown, TData = unknown>(runtime: TRuntime, options: InitializeFireflyOptions<TRuntime, TContext, TData> = {}) {\n const {\n localModules = [],\n remotes = [],\n startMsw,\n onError,\n context\n } = options;\n\n runtime.eventBus.dispatch(ApplicationBootstrappingStartedEvent);\n\n Promise.allSettled([\n registerLocalModules<TRuntime, TContext, TData>(localModules, runtime, { context }),\n registerRemoteModules(remotes, runtime, { context })\n ]).then(results => {\n if (runtime.isMswEnabled) {\n if (!isFunction(startMsw)) {\n throw new Error(\"[squide] When MSW is enabled, the \\\"startMsw\\\" function must be provided.\");\n }\n\n startMsw(runtime)\n .then(() => {\n setMswAsReady();\n })\n .catch((error: unknown) => {\n runtime.logger.debug(\"[squide] An error occured while starting MSW.\", error);\n });\n }\n\n if (onError) {\n propagateRegistrationErrors(results[0], onError);\n propagateRegistrationErrors(results[1], onError);\n }\n });\n}\n\nlet hasExecuted = false;\n\nexport function initializeFirefly<TContext = unknown, TData = unknown>(options: InitializeFireflyOptions<FireflyRuntime, TContext, TData> = {}) {\n const {\n mode,\n useMsw,\n loggers,\n plugins,\n onError\n } = options;\n\n if (hasExecuted) {\n throw new Error(\"[squide] A squide application can only be initialized once. Did you call the \\\"initializeSquide\\\" function twice?\");\n }\n\n hasExecuted = true;\n\n const runtime = new FireflyRuntime({\n mode,\n useMsw,\n loggers,\n plugins\n });\n\n initializeHoneycomb(runtime)\n .catch((error: unknown) => {\n if (onError) {\n onError(error);\n }\n })\n .finally(() => {\n bootstrap(runtime, options);\n });\n\n return runtime;\n}\n\nexport function __resetHasExecuteGuard() {\n hasExecuted = false;\n}\n"],"names":["isFunction","registerLocalModules","registerRemoteModules","setMswAsReady","FireflyRuntime","initializeHoneycomb","ApplicationBootstrappingStartedEvent","propagateRegistrationErrors","results","onError","x","bootstrap","runtime","options","localModules","remotes","startMsw","context","Promise","Error","error","hasExecuted","initializeFirefly","mode","useMsw","loggers","plugins","__resetHasExecuteGuard"],"mappings":";;;;;;;;;;;;;;;;;AAA0H;AACjC;AAC7C;AACsC;AACT;AAElE,MAAMM,uCAAuC,mCAAmC;AAavF,SAASC,4BAA4BC,OAAwC,EAAEC,OAAsC;IACjH,IAAID,SAAS;QACT,IAAIA,QAAQ,MAAM,KAAK,aAAa;YAChCA,QAAQ,KAAK,CAAC,OAAO,CAACE,CAAAA;gBAClBD,QAAQC;YACZ;QACJ;IACJ;AACJ;AAEO,SAASC,UAAiGC,OAAiB,EAAEC,UAA+D,CAAC,CAAC;IACjM,MAAM,EACFC,eAAe,EAAE,EACjBC,UAAU,EAAE,EACZC,QAAQ,EACRP,OAAO,EACPQ,OAAO,EACV,GAAGJ;IAEJD,QAAQ,QAAQ,CAAC,QAAQ,CAACN;IAE1BY,QAAQ,UAAU,CAAC;QACfjB,0EAAoBA,CAA4Ba,cAAcF,SAAS;YAAEK;QAAQ;QACjFf,wFAAqBA,CAACa,SAASH,SAAS;YAAEK;QAAQ;KACrD,EAAE,IAAI,CAACT,CAAAA;QACJ,IAAII,QAAQ,YAAY,EAAE;YACtB,IAAI,CAACZ,gEAAUA,CAACgB,WAAW;gBACvB,MAAM,IAAIG,MAAM;YACpB;YAEAH,SAASJ,SACJ,IAAI,CAAC;gBACFT,kEAAaA;YACjB,GACC,KAAK,CAAC,CAACiB;gBACJR,QAAQ,MAAM,CAAC,KAAK,CAAC,iDAAiDQ;YAC1E;QACR;QAEA,IAAIX,SAAS;YACTF,4BAA4BC,OAAO,CAAC,EAAE,EAAEC;YACxCF,4BAA4BC,OAAO,CAAC,EAAE,EAAEC;QAC5C;IACJ;AACJ;AAEA,IAAIY,cAAc;AAEX,SAASC,kBAAuDT,UAAqE,CAAC,CAAC;IAC1I,MAAM,EACFU,IAAI,EACJC,MAAM,EACNC,OAAO,EACPC,OAAO,EACPjB,OAAO,EACV,GAAGI;IAEJ,IAAIQ,aAAa;QACb,MAAM,IAAIF,MAAM;IACpB;IAEAE,cAAc;IAEd,MAAMT,UAAU,IAAIR,sEAAcA,CAAC;QAC/BmB;QACAC;QACAC;QACAC;IACJ;IAEArB,8FAAmBA,CAACO,SACf,KAAK,CAAC,CAACQ;QACJ,IAAIX,SAAS;YACTA,QAAQW;QACZ;IACJ,GACC,OAAO,CAAC;QACLT,UAAUC,SAASC;IACvB;IAEJ,OAAOD;AACX;AAEO,SAASe;IACZN,cAAc;AAClB"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@squide/firefly",
3
3
  "author": "Workleap",
4
- "version": "12.0.4",
4
+ "version": "13.0.1",
5
5
  "description": "Helpers to facilitate the creation of an application with the Squide firefly technology stack.",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
@@ -28,6 +28,7 @@
28
28
  "README.md"
29
29
  ],
30
30
  "peerDependencies": {
31
+ "@opentelemetry/api": "^1.9.0",
31
32
  "@tanstack/react-query": "^5.77.2",
32
33
  "msw": "^2.8.4",
33
34
  "react": "^18.0.0 || ^19.0.0",
@@ -35,6 +36,7 @@
35
36
  "react-router": "^7.6.1"
36
37
  },
37
38
  "dependencies": {
39
+ "uuid": "^11.1.0",
38
40
  "@squide/core": "5.4.8",
39
41
  "@squide/module-federation": "6.2.8",
40
42
  "@squide/msw": "3.2.8",
@@ -0,0 +1,131 @@
1
+ import type { Span } from "@opentelemetry/api";
2
+ import { isPlainObject, type RuntimeLogger } from "@squide/core";
3
+ import { v4 as uuidv4 } from "uuid";
4
+ import { createTraceContextId } from "./createTraceContextId.ts";
5
+
6
+ export type ActiveSpanId = string;
7
+
8
+ export interface ActiveSpan {
9
+ id: ActiveSpanId;
10
+ name: string;
11
+ instance: Span;
12
+ }
13
+
14
+ // Using a stack because we want a Last In First Out implementation for this.
15
+ // https://github.com/open-telemetry/opentelemetry-js/issues/5084
16
+ // https://github.com/open-telemetry/opentelemetry-js/issues/3558#issuecomment-1760680244
17
+ class ActiveSpanStack {
18
+ readonly #stack: ActiveSpan[] = [];
19
+
20
+ push(span: ActiveSpan) {
21
+ this.#stack.push(span);
22
+ }
23
+
24
+ pop(span: ActiveSpan) {
25
+ const head = this.#stack.pop();
26
+
27
+ if (!head) {
28
+ throw new Error("[squide] Unexpected pop, the active Honeycomb span stack is empty.");
29
+ }
30
+
31
+ if (head.id !== span.id) {
32
+ throw new Error(`[squide] The active Honeycomb span is not the expected span. Expected to pop span with name and id "${span.name} / ${span.id}" but found "${head.name} / ${head.id}". Did you forget to end an active span?`);
33
+ }
34
+
35
+ return head;
36
+ }
37
+
38
+ peek() {
39
+ if (this.#stack.length === 0) {
40
+ return undefined;
41
+ }
42
+
43
+ return this.#stack[this.#stack.length - 1];
44
+ }
45
+ }
46
+
47
+ const GlobalActiveSpanStackVariableName = "__SQUIDE_HONEYCOMB_ACTIVE_SPAN_STACK__";
48
+
49
+ export function registerActiveSpanStack() {
50
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
51
+ // @ts-ignore
52
+ if (globalThis[GlobalActiveSpanStackVariableName]) {
53
+ throw new Error(`[squide] An ActiveSpanStack instance has already been registered to globalThis.${GlobalActiveSpanStackVariableName}. Did you register the Honeycomb instrumentation twice?`);
54
+ }
55
+
56
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
57
+ // @ts-ignore
58
+ globalThis[GlobalActiveSpanStackVariableName] = new ActiveSpanStack();
59
+ }
60
+
61
+ function getActiveSpanStack() {
62
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
63
+ // @ts-ignore
64
+ return globalThis[GlobalActiveSpanStackVariableName] as ActiveSpanStack;
65
+ }
66
+
67
+ function getActiveSpan() {
68
+ const stack = getActiveSpanStack();
69
+
70
+ if (stack) {
71
+ return stack.peek();
72
+ }
73
+ }
74
+
75
+ export function setActiveSpan(name: string, span: Span) {
76
+ const activeSpan: ActiveSpan = {
77
+ id: uuidv4(),
78
+ name: name,
79
+ instance: span
80
+ };
81
+
82
+ const stack = getActiveSpanStack();
83
+
84
+ if (stack) {
85
+ stack.push(activeSpan);
86
+ }
87
+
88
+ return activeSpan;
89
+ }
90
+
91
+ export function popActiveSpan(span: ActiveSpan) {
92
+ const stack = getActiveSpanStack();
93
+
94
+ if (stack) {
95
+ stack.pop(span);
96
+ }
97
+ }
98
+
99
+ export function createOverrideFetchRequestSpanWithActiveSpanContext(logger: RuntimeLogger) {
100
+ return (span: Span, request: Request | RequestInit) => {
101
+ const activeSpan = getActiveSpan();
102
+
103
+ if (activeSpan) {
104
+ const activeSpanContext = activeSpan.instance.spanContext();
105
+ const requestSpanContext = span.spanContext();
106
+
107
+ if (activeSpanContext) {
108
+ logger.debug(
109
+ "[squide] Found a Honeycomb active context to apply to the following fetch request: \r\n",
110
+ "Request span context: ", requestSpanContext, "\r\n",
111
+ "Active span context: ", activeSpanContext, "\r\n",
112
+ "Request: ", request, "\r\n"
113
+ );
114
+
115
+ span.setAttribute("trace.trace_id", activeSpanContext.traceId);
116
+ span.setAttribute("trace.parent_id", activeSpanContext.spanId);
117
+
118
+ const traceParent = createTraceContextId(activeSpanContext.traceId, requestSpanContext.spanId, requestSpanContext.traceFlags);
119
+
120
+ if (request instanceof Request) {
121
+ request.headers.set("traceparent", traceParent);
122
+ } else if (isPlainObject(request.headers)) {
123
+ request.headers["traceparent"] = traceParent;
124
+ }
125
+
126
+ // Indicates to not propagate the requests to the subsequent hooks.
127
+ return true;
128
+ }
129
+ }
130
+ };
131
+ }
@@ -0,0 +1,5 @@
1
+ export function canRegisterHoneycombInstrumentation() {
2
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
3
+ // @ts-ignore
4
+ return globalThis.__WLP_HONEYCOMB_INSTRUMENTATION_IS_REGISTERED__ === true;
5
+ }
@@ -0,0 +1,12 @@
1
+ // Creates the trace context id based on the following opentelemetry-js implementation: https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-core/src/trace/W3CTraceContextPropagator.ts
2
+
3
+ const VERSION = "00";
4
+
5
+ enum TraceFlags {
6
+ NONE = 0x0,
7
+ SAMPLED = 0x1 << 0
8
+ }
9
+
10
+ export function createTraceContextId(traceId: string, spanId: string, traceFlags: number) {
11
+ return `${VERSION}-${traceId}-${spanId}-0${Number(traceFlags || TraceFlags.NONE).toString(16)}`;
12
+ }
@@ -0,0 +1,22 @@
1
+ import type { FireflyRuntime } from "../FireflyRuntime.tsx";
2
+ import { canRegisterHoneycombInstrumentation } from "./canRegisterHoneycombInstrumentation.ts";
3
+
4
+ export async function initializeHoneycomb(runtime: FireflyRuntime) {
5
+ if (canRegisterHoneycombInstrumentation()) {
6
+ try {
7
+ // Dynamically import the Honeycomb instrumentation to prevent loading all the Honeycomb libraries
8
+ // if Honeycomb instrumentation is not registered by the hosting application.
9
+ const mod = await import("./registerHoneycombInstrumentation.ts");
10
+
11
+ mod.registerHoneycombInstrumentation(runtime);
12
+ } catch (error: unknown) {
13
+ runtime.logger.error("[squide] Failed to register Honeycomb instrumentation. The \"./registerHoneycombInstrumentation.ts\" cannot be imported.");
14
+
15
+ throw error;
16
+ }
17
+ } else {
18
+ runtime.logger.debug("[squide] Cannot register Honeycomb instrumentation because the host application is not using the \"@workleap/honeycomb\" package.");
19
+ }
20
+ }
21
+
22
+