@equinor/fusion-framework-vite-plugin-spa 5.1.0 → 5.2.2

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/README.md CHANGED
@@ -345,6 +345,15 @@ FUSION_SPA_TELEMETRY_CONSOLE_LEVEL=2 # Warning and above
345
345
 
346
346
  For advanced telemetry (e.g. Application Insights), provide a [custom bootstrap file](#providing-custom-bootstrap).
347
347
 
348
+ When used by `@equinor/fusion-framework-dev-server`, the default bootstrap also supports
349
+ OTLP logs through the telemetry module's public `OtlpAdapter`, plus standard OpenTelemetry
350
+ browser request tracing and W3C propagation. Set
351
+ `FUSION_DEV_SERVER_OTLP_ENDPOINT` in the app's dev-server process; no app code change is required.
352
+ The dev server owns the environment bridge and same-origin collection route. The bootstrap
353
+ checks only whether an endpoint is configured; the serve-only dev-server bridge controls
354
+ activation. Explicitly configured app adapters and existing global tracer providers take
355
+ precedence. See [dev-server telemetry configuration](../../dev-server/docs/configuration.md#send-telemetry-to-an-otlp-endpoint).
356
+
348
357
  ## Configuring through `.env` Files
349
358
 
350
359
  The plugin reads environment variables from `.env` files (via Vite's `loadEnv`) and **merges them on top of** values from `generateTemplateEnv`. This lets you keep secrets and per-environment values out of source code.
@@ -392,7 +401,7 @@ FUSION_SPA_MSAL_TENANT_ID=my-tenant-id
392
401
  FUSION_SPA_MSAL_CLIENT_ID=my-client-id
393
402
  FUSION_SPA_MSAL_REDIRECT_URI=https://my-app.com/auth-callback
394
403
  FUSION_SPA_MSAL_REQUIRES_AUTH=true
395
- # Set to skip Entra ID and sign in a mock user instead — for CI/Playwright runs
404
+ # Set to skip Entra ID and sign in a mock user instead — use together with a mock server (see below)
396
405
  FUSION_SPA_MSAL_MOCK=true
397
406
  # Optional: standalone mock-server origin used for session-scoped token acquisition
398
407
  FUSION_SPA_MSAL_MOCK_SERVER_URL=http://localhost:4010
@@ -412,15 +421,30 @@ FUSION_SPA_SERVICE_WORKER_RESOURCES=[{"url":"/app-proxy","rewrite":"/@fusion-api
412
421
 
413
422
  ## Running Against a Mock Client (CI / Playwright)
414
423
 
424
+ Run CI and Playwright suites against the standalone mock server, so both authentication and
425
+ service discovery stay local:
426
+
427
+ ```sh
428
+ ffc mock-server ./mocks --port 4010
429
+ ffc app dev --mock http://localhost:4010
430
+ ```
431
+
415
432
  Setting `FUSION_SPA_MSAL_MOCK=true` swaps the real MSAL client for
416
433
  `@equinor/fusion-framework-module-msal/mock`, which signs in a default mock user with no
417
- Entra ID redirects, popups, or network calls. This is the recommended way to run the dev
418
- server headlessly in GitHub Actions or a Playwright suite.
434
+ Entra ID redirects or popups. Mock tokens are unsigned, so real Fusion services reject them.
435
+ `ffc app dev` and `ffc app serve` therefore also send service discovery to the mock server
436
+ whenever mock auth is on — `FUSION_SPA_MSAL_MOCK_SERVER_URL`, or `http://localhost:4010` when
437
+ only `FUSION_SPA_MSAL_MOCK` is set.
419
438
 
420
439
  ```sh
421
440
  FUSION_SPA_MSAL_MOCK=true
422
441
  ```
423
442
 
443
+ > [!IMPORTANT]
444
+ > A direct Vite setup must point `FUSION_SPA_SERVICE_DISCOVERY_URL` (or the dev server's
445
+ > service discovery URL) at the mock server too. Otherwise every page load sends a mock token
446
+ > to real service discovery and fails with `401`.
447
+
424
448
  By default the mock signs in a generic `Test User`. To select and switch users at runtime, start
425
449
  the standalone mock server with the browser origin explicitly allowed, then point the app at it:
426
450
 
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Abstract base class for telemetry adapters.
3
+ *
4
+ * Provides a common implementation for filtering telemetry items before processing.
5
+ * Subclasses must implement the `_processItem` method to define how telemetry items are handled.
6
+ *
7
+ * @template TelemetryItem - The type representing a telemetry item.
8
+ * @implements {ITelemetryAdapter}
9
+ *
10
+ * @remarks
11
+ * - An optional filter function can be provided to determine which telemetry items should be processed.
12
+ *
13
+ * @example
14
+ * class MyTelemetryAdapter extends BaseTelemetryAdapter {
15
+ * protected _processItem(item: TelemetryItem): void {
16
+ * // Custom processing logic
17
+ * }
18
+ * }
19
+ */
20
+ class BaseTelemetryAdapter {
21
+ #filter;
22
+ #initialized = false;
23
+ /**
24
+ * Creates a new instance of the TelemetryAdapter.
25
+ *
26
+ * @param filter - An optional function to filter telemetry items. If provided, only items for which the function returns true will be processed.
27
+ */
28
+ constructor(filter) {
29
+ this.#filter = filter;
30
+ }
31
+ /**
32
+ * Processes a telemetry item by applying an optional filter before handling it.
33
+ *
34
+ * If a filter is defined and the item does not pass the filter, the method returns early.
35
+ * Otherwise, it delegates the processing of the item to the internal `_processItem` method.
36
+ *
37
+ * @param item - The telemetry item to be processed.
38
+ */
39
+ processItem(item) {
40
+ // If the adapter is not initialized, do not process the item
41
+ if (!this.#initialized) {
42
+ return;
43
+ }
44
+ // If a filter is defined and the item does not pass the filter, do not process the item
45
+ if (this.#filter && !this.#filter(item)) {
46
+ return;
47
+ }
48
+ // Delegate the processing of the item to the internal `_processItem` method
49
+ this._processItem(item);
50
+ }
51
+ /**
52
+ * Initializes the telemetry adapter asynchronously.
53
+ *
54
+ * This method can only be called once. Subsequent calls will return immediately
55
+ * without performing any initialization. It calls the protected `_initialize` method which
56
+ * subclasses can override to provide custom initialization logic.
57
+ *
58
+ * TODO(#5112): Consider changing return type from Promise<void> to Promise<TelemetryItem[]>
59
+ * to allow adapters to return telemetry items (errors/warnings) that occurred during
60
+ * initialization, eliminating the chicken-and-egg problem with reporting init errors.
61
+ *
62
+ * @returns A promise that resolves when initialization is complete.
63
+ * @sealed
64
+ */
65
+ async initialize() {
66
+ // If the adapter is already initialized, do not initialize it again
67
+ if (this.#initialized) {
68
+ return;
69
+ }
70
+ // Initialize the adapter
71
+ await this._initialize();
72
+ // Mark the adapter as initialized
73
+ this.#initialized = true;
74
+ }
75
+ /**
76
+ * Protected initialization method that subclasses can override.
77
+ *
78
+ * This method is called only once during the adapter's lifetime.
79
+ * Subclasses should override this method to perform any necessary async setup.
80
+ * The base implementation is a no-op for adapters that don't need initialization.
81
+ *
82
+ * @returns A promise that resolves when initialization is complete.
83
+ * @protected
84
+ */
85
+ async _initialize() {
86
+ // Default implementation - no-op for adapters that don't need initialization
87
+ }
88
+ }
89
+
90
+ export { BaseTelemetryAdapter as B };
91
+ //# sourceMappingURL=TelemetryAdapter-B6JH_RXA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TelemetryAdapter-B6JH_RXA.js","sources":["../../../modules/telemetry/dist/esm/TelemetryAdapter.js"],"sourcesContent":["/**\n * Abstract base class for telemetry adapters.\n *\n * Provides a common implementation for filtering telemetry items before processing.\n * Subclasses must implement the `_processItem` method to define how telemetry items are handled.\n *\n * @template TelemetryItem - The type representing a telemetry item.\n * @implements {ITelemetryAdapter}\n *\n * @remarks\n * - An optional filter function can be provided to determine which telemetry items should be processed.\n *\n * @example\n * class MyTelemetryAdapter extends BaseTelemetryAdapter {\n * protected _processItem(item: TelemetryItem): void {\n * // Custom processing logic\n * }\n * }\n */\nexport class BaseTelemetryAdapter {\n #filter;\n #initialized = false;\n /**\n * Creates a new instance of the TelemetryAdapter.\n *\n * @param filter - An optional function to filter telemetry items. If provided, only items for which the function returns true will be processed.\n */\n constructor(filter) {\n this.#filter = filter;\n }\n /**\n * Processes a telemetry item by applying an optional filter before handling it.\n *\n * If a filter is defined and the item does not pass the filter, the method returns early.\n * Otherwise, it delegates the processing of the item to the internal `_processItem` method.\n *\n * @param item - The telemetry item to be processed.\n */\n processItem(item) {\n // If the adapter is not initialized, do not process the item\n if (!this.#initialized) {\n return;\n }\n // If a filter is defined and the item does not pass the filter, do not process the item\n if (this.#filter && !this.#filter(item)) {\n return;\n }\n // Delegate the processing of the item to the internal `_processItem` method\n this._processItem(item);\n }\n /**\n * Initializes the telemetry adapter asynchronously.\n *\n * This method can only be called once. Subsequent calls will return immediately\n * without performing any initialization. It calls the protected `_initialize` method which\n * subclasses can override to provide custom initialization logic.\n *\n * TODO(#5112): Consider changing return type from Promise<void> to Promise<TelemetryItem[]>\n * to allow adapters to return telemetry items (errors/warnings) that occurred during\n * initialization, eliminating the chicken-and-egg problem with reporting init errors.\n *\n * @returns A promise that resolves when initialization is complete.\n * @sealed\n */\n async initialize() {\n // If the adapter is already initialized, do not initialize it again\n if (this.#initialized) {\n return;\n }\n // Initialize the adapter\n await this._initialize();\n // Mark the adapter as initialized\n this.#initialized = true;\n }\n /**\n * Protected initialization method that subclasses can override.\n *\n * This method is called only once during the adapter's lifetime.\n * Subclasses should override this method to perform any necessary async setup.\n * The base implementation is a no-op for adapters that don't need initialization.\n *\n * @returns A promise that resolves when initialization is complete.\n * @protected\n */\n async _initialize() {\n // Default implementation - no-op for adapters that don't need initialization\n }\n}\n//# sourceMappingURL=TelemetryAdapter.js.map"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,oBAAoB,CAAC;AAClC,IAAI,OAAO;AACX,IAAI,YAAY,GAAG,KAAK;AACxB;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,MAAM,EAAE;AACxB,QAAQ,IAAI,CAAC,OAAO,GAAG,MAAM;AAC7B,IAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,IAAI,EAAE;AACtB;AACA,QAAQ,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;AAChC,YAAY;AACZ,QAAQ;AACR;AACA,QAAQ,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;AACjD,YAAY;AACZ,QAAQ;AACR;AACA,QAAQ,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;AAC/B,IAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,MAAM,UAAU,GAAG;AACvB;AACA,QAAQ,IAAI,IAAI,CAAC,YAAY,EAAE;AAC/B,YAAY;AACZ,QAAQ;AACR;AACA,QAAQ,MAAM,IAAI,CAAC,WAAW,EAAE;AAChC;AACA,QAAQ,IAAI,CAAC,YAAY,GAAG,IAAI;AAChC,IAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,MAAM,WAAW,GAAG;AACxB;AACA,IAAI;AACJ;;"}