@equinor/fusion-framework-module-analytics 1.0.2 → 2.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 (86) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +147 -130
  3. package/dist/esm/AnalyticsConfigurator.js +22 -17
  4. package/dist/esm/AnalyticsConfigurator.js.map +1 -1
  5. package/dist/esm/AnalyticsProvider.js +39 -18
  6. package/dist/esm/AnalyticsProvider.js.map +1 -1
  7. package/dist/esm/adapters/ConsoleAnalyticsAdapter.js +15 -1
  8. package/dist/esm/adapters/ConsoleAnalyticsAdapter.js.map +1 -1
  9. package/dist/esm/adapters/FusionAnalyticsAdapter.js +32 -3
  10. package/dist/esm/adapters/FusionAnalyticsAdapter.js.map +1 -1
  11. package/dist/esm/adapters/index.js.map +1 -1
  12. package/dist/esm/collectors/AppLoadedCollector.js +21 -5
  13. package/dist/esm/collectors/AppLoadedCollector.js.map +1 -1
  14. package/dist/esm/collectors/AppSelectedCollector.js +17 -5
  15. package/dist/esm/collectors/AppSelectedCollector.js.map +1 -1
  16. package/dist/esm/collectors/BaseCollector.js +48 -3
  17. package/dist/esm/collectors/BaseCollector.js.map +1 -1
  18. package/dist/esm/collectors/ContextSelectedCollector.js +20 -5
  19. package/dist/esm/collectors/ContextSelectedCollector.js.map +1 -1
  20. package/dist/esm/collectors/index.js.map +1 -1
  21. package/dist/esm/collectors/utils/extractAppMetadata.js +25 -4
  22. package/dist/esm/collectors/utils/extractAppMetadata.js.map +1 -1
  23. package/dist/esm/collectors/utils/extractContextMetadata.js +13 -2
  24. package/dist/esm/collectors/utils/extractContextMetadata.js.map +1 -1
  25. package/dist/esm/enable-analytics.js +18 -3
  26. package/dist/esm/enable-analytics.js.map +1 -1
  27. package/dist/esm/index.js +18 -0
  28. package/dist/esm/index.js.map +1 -1
  29. package/dist/esm/logExporters/fusionOTLPLogExporter/FusionOTLPLogExporter.js +26 -4
  30. package/dist/esm/logExporters/fusionOTLPLogExporter/FusionOTLPLogExporter.js.map +1 -1
  31. package/dist/esm/logExporters/fusionOTLPLogExporter/HttpClientExporterTransport.js +36 -7
  32. package/dist/esm/logExporters/fusionOTLPLogExporter/HttpClientExporterTransport.js.map +1 -1
  33. package/dist/esm/logExporters/index.js +8 -0
  34. package/dist/esm/logExporters/index.js.map +1 -1
  35. package/dist/esm/module.js +8 -8
  36. package/dist/esm/version.js +1 -1
  37. package/dist/tsconfig.tsbuildinfo +1 -1
  38. package/dist/types/AnalyticsConfigurator.d.ts +22 -17
  39. package/dist/types/AnalyticsConfigurator.interface.d.ts +41 -12
  40. package/dist/types/AnalyticsProvider.d.ts +32 -18
  41. package/dist/types/AnalyticsProvider.interface.d.ts +28 -6
  42. package/dist/types/adapters/AnalyticsAdapter.interface.d.ts +15 -2
  43. package/dist/types/adapters/ConsoleAnalyticsAdapter.d.ts +15 -1
  44. package/dist/types/adapters/FusionAnalyticsAdapter.d.ts +32 -3
  45. package/dist/types/adapters/index.d.ts +8 -0
  46. package/dist/types/collectors/AnalyticsCollector.interface.d.ts +11 -2
  47. package/dist/types/collectors/AppLoadedCollector.d.ts +20 -2
  48. package/dist/types/collectors/AppSelectedCollector.d.ts +16 -2
  49. package/dist/types/collectors/BaseCollector.d.ts +58 -3
  50. package/dist/types/collectors/ContextSelectedCollector.d.ts +19 -2
  51. package/dist/types/collectors/index.d.ts +8 -0
  52. package/dist/types/collectors/utils/extractAppMetadata.d.ts +27 -0
  53. package/dist/types/collectors/utils/extractContextMetadata.d.ts +14 -0
  54. package/dist/types/enable-analytics.d.ts +19 -3
  55. package/dist/types/index.d.ts +18 -0
  56. package/dist/types/logExporters/fusionOTLPLogExporter/FusionOTLPLogExporter.d.ts +21 -3
  57. package/dist/types/logExporters/fusionOTLPLogExporter/HttpClientExporterTransport.d.ts +24 -1
  58. package/dist/types/logExporters/index.d.ts +8 -0
  59. package/dist/types/module.d.ts +15 -15
  60. package/dist/types/types.d.ts +38 -7
  61. package/dist/types/version.d.ts +1 -1
  62. package/package.json +11 -11
  63. package/src/AnalyticsConfigurator.interface.ts +41 -12
  64. package/src/AnalyticsConfigurator.ts +22 -17
  65. package/src/AnalyticsProvider.interface.ts +28 -6
  66. package/src/AnalyticsProvider.ts +39 -18
  67. package/src/adapters/AnalyticsAdapter.interface.ts +15 -2
  68. package/src/adapters/ConsoleAnalyticsAdapter.ts +15 -1
  69. package/src/adapters/FusionAnalyticsAdapter.ts +32 -3
  70. package/src/adapters/index.ts +8 -0
  71. package/src/collectors/AnalyticsCollector.interface.ts +11 -2
  72. package/src/collectors/AppLoadedCollector.ts +21 -5
  73. package/src/collectors/AppSelectedCollector.ts +17 -5
  74. package/src/collectors/BaseCollector.ts +58 -3
  75. package/src/collectors/ContextSelectedCollector.ts +20 -5
  76. package/src/collectors/index.ts +8 -0
  77. package/src/collectors/utils/extractAppMetadata.ts +27 -4
  78. package/src/collectors/utils/extractContextMetadata.ts +14 -2
  79. package/src/enable-analytics.ts +19 -3
  80. package/src/index.ts +19 -0
  81. package/src/logExporters/fusionOTLPLogExporter/FusionOTLPLogExporter.ts +26 -4
  82. package/src/logExporters/fusionOTLPLogExporter/HttpClientExporterTransport.ts +36 -7
  83. package/src/logExporters/index.ts +8 -0
  84. package/src/module.ts +15 -15
  85. package/src/types.ts +39 -8
  86. package/src/version.ts +1 -1
@@ -1,5 +1,12 @@
1
1
  import { z } from 'zod';
2
2
  import type { ContextItem } from '@equinor/fusion-framework-module-context';
3
+ /**
4
+ * Zod schema for a Fusion context metadata object.
5
+ *
6
+ * @remarks
7
+ * Validates core context fields (id, type) and optional title, externalId,
8
+ * and source. Used by {@link ContextSelectedCollector} and {@link AppLoadedCollector}.
9
+ */
3
10
  export declare const contextSchema: z.ZodNullable<z.ZodOptional<z.ZodObject<{
4
11
  id: z.ZodString;
5
12
  type: z.ZodString;
@@ -7,5 +14,12 @@ export declare const contextSchema: z.ZodNullable<z.ZodOptional<z.ZodObject<{
7
14
  externalId: z.ZodOptional<z.ZodString>;
8
15
  source: z.ZodOptional<z.ZodString>;
9
16
  }, z.core.$strip>>>;
17
+ /** Inferred type from {@link contextSchema}. */
10
18
  export type ContextItemType = z.infer<typeof contextSchema>;
19
+ /**
20
+ * Extracts context metadata from a `ContextItem` for analytics events.
21
+ *
22
+ * @param context - The Fusion context item.
23
+ * @returns An object with id, type, and optional title, externalId, and source.
24
+ */
11
25
  export declare const extractContextMetadata: (context: ContextItem) => z.input<typeof contextSchema>;
@@ -1,11 +1,27 @@
1
1
  import type { IModulesConfigurator } from '@equinor/fusion-framework-module';
2
2
  import type { IAnalyticsConfigurator } from './AnalyticsConfigurator.interface.js';
3
+ /** Callback invoked with the {@link IAnalyticsConfigurator} to register adapters and collectors. */
3
4
  type AnalyticsBuilderCallback = (builder: IAnalyticsConfigurator) => void | Promise<void>;
4
5
  /**
5
- * Enables analytics for agiven module configurator.
6
+ * Enables the analytics module on a Fusion Framework module configurator.
6
7
  *
7
- * @param configurator - The module configurator instance to which analytics should be attached.
8
- * @param callback - An optional callback to further configure the analytics builder. Can be synchronous or asynchronous.
8
+ * Call this helper during application or portal configuration to register
9
+ * adapters and collectors for analytics tracking.
10
+ *
11
+ * @param configurator - The module configurator instance to attach analytics to.
12
+ * @param callback - Optional callback to register adapters and collectors on the analytics builder.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * import { enableAnalytics } from '@equinor/fusion-framework-module-analytics';
17
+ * import { ConsoleAnalyticsAdapter } from '@equinor/fusion-framework-module-analytics/adapters';
18
+ *
19
+ * const configure = (configurator) => {
20
+ * enableAnalytics(configurator, (builder) => {
21
+ * builder.setAdapter('console', async () => new ConsoleAnalyticsAdapter());
22
+ * });
23
+ * };
24
+ * ```
9
25
  */
10
26
  export declare const enableAnalytics: (configurator: IModulesConfigurator<any, any>, callback?: AnalyticsBuilderCallback) => void;
11
27
  export {};
@@ -1,3 +1,21 @@
1
+ /**
2
+ * `@equinor/fusion-framework-module-analytics` — Fusion Framework module for
3
+ * collecting and exporting application analytics using OpenTelemetry standards.
4
+ *
5
+ * @remarks
6
+ * This package provides a pluggable adapter/collector architecture:
7
+ *
8
+ * - **Adapters** receive analytics events and forward them to a backend
9
+ * (e.g. console, OTLP endpoint).
10
+ * - **Collectors** observe application state (context changes, app loads) and
11
+ * emit structured {@link AnalyticsEvent} instances.
12
+ *
13
+ * Import adapters from `'@equinor/fusion-framework-module-analytics/adapters'`,
14
+ * collectors from `'@equinor/fusion-framework-module-analytics/collectors'`,
15
+ * and log exporters from `'@equinor/fusion-framework-module-analytics/logExporters'`.
16
+ *
17
+ * @packageDocumentation
18
+ */
1
19
  export { module as analyticsModule, AnalyticsModule } from './module.js';
2
20
  export { AnalyticsEvent, AnyValue, AnyValueMap } from './types.js';
3
21
  export { AnalyticsProvider } from './AnalyticsProvider.js';
@@ -2,10 +2,28 @@ import type { LogRecordExporter, ReadableLogRecord } from '@opentelemetry/sdk-lo
2
2
  import { OTLPExporterBase } from '@opentelemetry/otlp-exporter-base';
3
3
  import type { IHttpClient } from '@equinor/fusion-framework-module-http';
4
4
  /**
5
- * A log exporter extending OTLPExporterBase but substitute the normal transport
6
- * with a HttpClientExporterTransport. This will use the provided httpClient to
7
- * emit the event.
5
+ * OTLP log exporter that uses a Fusion `IHttpClient` as its HTTP transport.
6
+ *
7
+ * @remarks
8
+ * Extends `OTLPExporterBase` and substitutes the default `fetch`-based transport
9
+ * with {@link HttpClientExporterTransport}, routing log record payloads
10
+ * through the Fusion HTTP module’s configured client (which may include
11
+ * authentication headers, interceptors, and service‑discovery routing).
12
+ *
13
+ * Typically used with {@link FusionAnalyticsAdapter} when the portal provides
14
+ * an HTTP client via service discovery.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { FusionOTLPLogExporter } from '@equinor/fusion-framework-module-analytics/logExporters';
19
+ *
20
+ * const httpClient = await serviceDiscovery.createClient('analytics');
21
+ * const exporter = new FusionOTLPLogExporter(httpClient);
22
+ * ```
8
23
  */
9
24
  export declare class FusionOTLPLogExporter extends OTLPExporterBase<ReadableLogRecord[]> implements LogRecordExporter {
25
+ /**
26
+ * @param httpClient - A Fusion `IHttpClient` used for outbound HTTP transport.
27
+ */
10
28
  constructor(httpClient: IHttpClient);
11
29
  }
@@ -1,12 +1,35 @@
1
1
  import type { IExporterTransport, ExportResponse } from '@opentelemetry/otlp-exporter-base';
2
2
  import type { IHttpClient } from '@equinor/fusion-framework-module-http';
3
3
  /**
4
- * A Exporter Transport to POST events to provided path using the provided httpClient
4
+ * OpenTelemetry exporter transport that posts serialised log records using a
5
+ * Fusion `IHttpClient`.
6
+ *
7
+ * @remarks
8
+ * Implements `IExporterTransport` from `@opentelemetry/otlp-exporter-base`.
9
+ * The transport honours the exporter’s timeout via `AbortController` and
10
+ * inspects response status codes to report retryable failures (429, 502–504).
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * const transport = new HttpClientExporterTransport(httpClient, '/v1/logs');
15
+ * ```
5
16
  */
6
17
  export declare class HttpClientExporterTransport implements IExporterTransport {
7
18
  private httpClient;
8
19
  private path;
20
+ /**
21
+ * @param httpClient - Fusion HTTP client for outgoing requests.
22
+ * @param path - URL path appended to the client’s base URL (default `'/v1/logs'`).
23
+ */
9
24
  constructor(httpClient: IHttpClient, path?: string);
25
+ /**
26
+ * Sends serialised log record data to the configured endpoint.
27
+ *
28
+ * @param data - Serialised OTLP payload as a `Uint8Array`.
29
+ * @param timeoutMillis - Maximum time in milliseconds before the request is aborted.
30
+ * @returns An `ExportResponse` indicating success, retryable failure, or permanent failure.
31
+ */
10
32
  send(data: Uint8Array, timeoutMillis: number): Promise<ExportResponse>;
33
+ /** No-op; the HTTP client does not hold persistent connections. */
11
34
  shutdown(): void;
12
35
  }
@@ -1,2 +1,10 @@
1
+ /**
2
+ * Re-exports for OTLP log exporters used by analytics adapters.
3
+ *
4
+ * @remarks
5
+ * Import from `'@equinor/fusion-framework-module-analytics/logExporters'`.
6
+ *
7
+ * @packageDocumentation
8
+ */
1
9
  export { FusionOTLPLogExporter } from './fusionOTLPLogExporter/FusionOTLPLogExporter.js';
2
10
  export { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';
@@ -3,16 +3,16 @@ import type { IAnalyticsConfigurator } from './AnalyticsConfigurator.interface.j
3
3
  import type { IAnalyticsProvider } from './AnalyticsProvider.interface.js';
4
4
  import { AnalyticsConfigurator } from './AnalyticsConfigurator.js';
5
5
  /**
6
- * Representes the Analytics module within the framework.
6
+ * Represents the Analytics module type within the Fusion Framework module system.
7
7
  *
8
8
  * @remarks
9
- * This type defines a module names `analytics` that integrates with the framwork's module system.
10
- * It specifies the provider and configurator interfaces for analytics functionality, and declares
11
- * its dependencies on itself (`AnalyticsModule`).
9
+ * This type defines a module named `analytics` that integrates with the framework's
10
+ * module system. It specifies the provider and configurator interfaces for analytics
11
+ * functionality, and declares a self-dependency so that child modules can inherit
12
+ * analytics from a parent scope.
12
13
  *
13
- * @typeParam IAnalyticsProvider - The interface for the analytics provider implementation.
14
- * @typeParam IAnalyticsConfigurator - The interface for configuring analytics behavior.
15
- * @typeParam AnalyticsModule - Self-reference to allow for recursive or hierarchical module composition.
14
+ * @see {@link IAnalyticsProvider} for the runtime provider interface.
15
+ * @see {@link IAnalyticsConfigurator} for configuration-time setup.
16
16
  */
17
17
  export type AnalyticsModule = Module<'analytics', IAnalyticsProvider, IAnalyticsConfigurator, [
18
18
  AnalyticsModule
@@ -21,15 +21,15 @@ export type AnalyticsModule = Module<'analytics', IAnalyticsProvider, IAnalytics
21
21
  * Analytics module definition for the Fusion Framework.
22
22
  *
23
23
  * @remarks
24
- * This module provides analytics capabilities by configuring and initializing a analytics provider.
24
+ * This module provides analytics capabilities by configuring and initializing an
25
+ * {@link AnalyticsProvider}. Register it with {@link enableAnalytics} or add it
26
+ * directly to a module configurator.
25
27
  *
26
- * @type {AnalyticsModule}
27
- *
28
- * @property {string} name - The name of the module ('analytics').
29
- * @property {() => AnalyticsConfigurator} configure - Factory function to create a new AnalyticsConfigurator instance.
30
- * @property {(args) => Promise<IAnalyticsProvider>} initialize - Asynchronous initializer that creates and returns a AnalyticsProvider.
31
- * - @param args - Initialization arguments, including configuration and module dependencies.
32
- * - @returns A promise that resolves to an instance of IAnalyticsProvider.
28
+ * - `name` — `'analytics'`
29
+ * - `configure()` — creates a new {@link AnalyticsConfigurator} instance.
30
+ * - `initialize(args)` resolves the configuration, creates an
31
+ * {@link AnalyticsProvider}, calls {@link AnalyticsProvider.initialize},
32
+ * and returns the ready-to-use provider.
33
33
  */
34
34
  export declare const module: {
35
35
  name: "analytics";
@@ -1,22 +1,53 @@
1
+ /**
2
+ * Scalar analytics attribute value: a string, number, or boolean.
3
+ *
4
+ * @remarks
5
+ * Mirrors the OpenTelemetry `AnyValue` scalar subset used in log record
6
+ * attributes and event bodies.
7
+ */
1
8
  export type AnyValueScalar = string | number | boolean;
9
+ /** Array of {@link AnyValue} entries, allowing nested attribute structures. */
2
10
  export type AnyValueArray = Array<AnyValue>;
3
11
  /**
4
- * AnyValueMap is a map from string to AnyValue (attribute value or a nested map)
12
+ * A key–value map where each value is an {@link AnyValue}.
13
+ *
14
+ * Used as the attribute bag on {@link AnalyticsEvent} instances and for
15
+ * nested attribute structures.
5
16
  */
6
17
  export interface AnyValueMap {
7
18
  [attributeKey: string]: AnyValue;
8
19
  }
9
20
  /**
10
- * AnyValue can be one of the following:
11
- * - a scalar value
12
- * - a byte array
13
- * - array of any value
14
- * - map from string to any value
15
- * - empty value
21
+ * A flexible value type compatible with OpenTelemetry log record bodies and attributes.
22
+ *
23
+ * Can be one of the following:
24
+ * - a scalar value (`string | number | boolean`)
25
+ * - a byte array (`Uint8Array`)
26
+ * - an array of any value ({@link AnyValueArray})
27
+ * - a map from string to any value ({@link AnyValueMap})
28
+ * - `null` or `undefined`
16
29
  */
17
30
  export type AnyValue = AnyValueScalar | Uint8Array | AnyValueArray | AnyValueMap | null | undefined;
31
+ /**
32
+ * Represents a single analytics event emitted by a collector and consumed by adapters.
33
+ *
34
+ * @template TValue - The event body type, defaults to {@link AnyValue}.
35
+ * @template TAttr - The attributes map type, defaults to {@link AnyValueMap}.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * const event: AnalyticsEvent = {
40
+ * name: 'button-click',
41
+ * value: 'submit',
42
+ * attributes: { section: 'header', count: 1 },
43
+ * };
44
+ * ```
45
+ */
18
46
  export type AnalyticsEvent<TValue extends AnyValue = AnyValue, TAttr extends AnyValueMap = AnyValueMap> = {
47
+ /** Descriptive event name used to categorise the analytic, e.g. `'context-selected'`. */
19
48
  name: string;
49
+ /** The primary payload of the event. */
20
50
  value: TValue;
51
+ /** Optional metadata attached to the event for filtering and grouping. */
21
52
  attributes?: TAttr;
22
53
  };
@@ -1 +1 @@
1
- export declare const version = "1.0.2";
1
+ export declare const version = "2.0.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/fusion-framework-module-analytics",
3
- "version": "1.0.2",
3
+ "version": "2.0.0",
4
4
  "description": "Fusion module for collecting and exporting application analytics using OpenTelemetry standards",
5
5
  "main": "dist/esm/index.js",
6
6
  "type": "module",
@@ -48,20 +48,20 @@
48
48
  "deepmerge": "^4.3.1",
49
49
  "rxjs": "^7.8.1",
50
50
  "uuid": "^13.0.0",
51
- "zod": "^4.1.11",
52
- "@equinor/fusion-framework-module": "5.0.6",
53
- "@equinor/fusion-framework-module-app": "7.4.1",
54
- "@equinor/fusion-framework-module-context": "7.0.3",
55
- "@equinor/fusion-framework-module-http": "7.0.8",
56
- "@equinor/fusion-framework-module-event": "5.0.1"
51
+ "zod": "^4.3.6",
52
+ "@equinor/fusion-framework-module": "6.0.0",
53
+ "@equinor/fusion-framework-module-app": "8.0.0",
54
+ "@equinor/fusion-framework-module-event": "6.0.0",
55
+ "@equinor/fusion-framework-module-context": "8.0.0",
56
+ "@equinor/fusion-framework-module-http": "8.0.0"
57
57
  },
58
58
  "devDependencies": {
59
- "typescript": "^5.8.2",
60
- "vitest": "^3.2.4",
61
- "@equinor/fusion-observable": "^8.5.8"
59
+ "typescript": "^5.9.3",
60
+ "vitest": "^4.1.0",
61
+ "@equinor/fusion-observable": "^9.0.0"
62
62
  },
63
63
  "peerDependencies": {
64
- "@equinor/fusion-observable": "8.5.8"
64
+ "@equinor/fusion-observable": "9.0.0"
65
65
  },
66
66
  "scripts": {
67
67
  "build": "tsc -b",
@@ -4,29 +4,53 @@ import type { IAnalyticsAdapter } from './adapters/AnalyticsAdapter.interface.js
4
4
  import type { AnalyticsEvent } from './types.js';
5
5
 
6
6
  /**
7
- * Configuration options for setting up analytics within the framework.
7
+ * Resolved analytics configuration containing the instantiated collectors and adapters.
8
8
  *
9
- * @property collectors - Record of analytics collectors keyed by identifier to be used for reporting analytics data.
10
- * @property adapters - Record of analytics adapters keyed by identifier to be used to handle events.
9
+ * @remarks
10
+ * This type is the output of the configuration stage. The module’s `initialize`
11
+ * function receives the resolved `AnalyticsConfig` and passes it to
12
+ * {@link AnalyticsProvider}.
11
13
  */
12
14
  export type AnalyticsConfig = {
15
+ /** Record of analytics collectors keyed by a unique identifier. */
13
16
  collectors: Record<string, IAnalyticsCollector>;
17
+ /** Record of analytics adapters keyed by a unique identifier. */
14
18
  adapters: Record<string, IAnalyticsAdapter>;
15
19
  };
16
20
 
17
21
  /**
18
- * Interface for configuring analytics within the module.
22
+ * Configuration-time interface for registering analytics adapters and collectors.
19
23
  *
20
- * Provides methods to set analytics adapters and collectors.
24
+ * @remarks
25
+ * Obtain an instance of this interface inside the callback passed to
26
+ * {@link enableAnalytics}. Use {@link IAnalyticsConfigurator.setAdapter | setAdapter}
27
+ * and {@link IAnalyticsConfigurator.setCollector | setCollector} to register
28
+ * components. Both methods support method chaining.
21
29
  *
22
- * @interface IAnalyticsConfigurator
30
+ * @example
31
+ * ```ts
32
+ * enableAnalytics(configurator, (builder) => {
33
+ * builder
34
+ * .setAdapter('console', async () => new ConsoleAnalyticsAdapter())
35
+ * .setCollector('context-selected', async (args) => {
36
+ * const ctx = await args.requireInstance('context');
37
+ * const app = await args.requireInstance('app');
38
+ * return new ContextSelectedCollector(ctx, app);
39
+ * });
40
+ * });
41
+ * ```
23
42
  */
24
43
  export interface IAnalyticsConfigurator {
25
44
  /**
26
- * Sets a analytics collector with the given identifier and configuration callback.
45
+ * Registers an analytics collector factory identified by a unique key.
27
46
  *
28
- * @param identifier - The unique identifier for the collector.
29
- * @param callBack - Configuration callback that returns the collector instance.
47
+ * The factory callback receives module-resolution arguments so it can
48
+ * resolve dependencies (e.g. context or app providers) before returning
49
+ * the collector instance.
50
+ *
51
+ * @template T - The concrete analytics event type the collector emits.
52
+ * @param identifier - Unique key for this collector.
53
+ * @param callBack - Async factory that returns the collector instance.
30
54
  * @returns The configurator instance for method chaining.
31
55
  */
32
56
  setCollector<T extends AnalyticsEvent>(
@@ -35,10 +59,15 @@ export interface IAnalyticsConfigurator {
35
59
  ): this;
36
60
 
37
61
  /**
38
- * Sets a analytics adapter with the given identifier and configuration callback.
62
+ * Registers an analytics adapter factory identified by a unique key.
63
+ *
64
+ * The factory callback receives module-resolution arguments so it can
65
+ * resolve dependencies (e.g. service-discovery HTTP clients) before
66
+ * returning the adapter instance.
39
67
  *
40
- * @param identifier - The unique identifier for the adapter.
41
- * @param callBack - Configuration callback that returns the adapter instance.
68
+ * @template T - The concrete analytics event type the adapter handles.
69
+ * @param identifier - Unique key for this adapter.
70
+ * @param callback - Async factory that returns the adapter instance.
42
71
  * @returns The configurator instance for method chaining.
43
72
  */
44
73
  setAdapter<T extends AnalyticsEvent>(
@@ -12,18 +12,21 @@ import { from, type ObservableInput } from 'rxjs';
12
12
  import { map, scan, filter, defaultIfEmpty, shareReplay, mergeMap } from 'rxjs/operators';
13
13
 
14
14
  /**
15
- * Configures analytics settings for the module.
16
- *
17
- * The `AnalyticsConfigurator` class extends `BaseConfigBuilder` to provide a fluent API for
18
- * setting up analytics adapters and collectors.
15
+ * Default {@link IAnalyticsConfigurator} implementation for registering analytics adapters and collectors.
19
16
  *
20
17
  * @remarks
21
- * - Adapters are managed internally and can be set using `setAdapter`.
22
- * - Collectors are managed internally and can be set using `setCollector`.
23
- * - All setter methods return `this` for method chaining.
18
+ * Extends `BaseConfigBuilder` to resolve adapter and collector factories
19
+ * asynchronously at module-initialisation time using RxJS `mergeMap`. Each
20
+ * registered factory is invoked with the module’s `ConfigBuilderCallbackArgs`
21
+ * so it can resolve dependencies from the framework before returning its
22
+ * adapter or collector instance.
23
+ *
24
+ * Use {@link AnalyticsConfigurator.setAdapter | setAdapter} and
25
+ * {@link AnalyticsConfigurator.setCollector | setCollector} to register
26
+ * components. Both methods return `this` for fluent chaining.
24
27
  *
25
- * @see BaseConfigBuilder
26
- * @see IAnalyticsConfigurator
28
+ * @see {@link IAnalyticsConfigurator}
29
+ * @see {@link BaseConfigBuilder}
27
30
  */
28
31
  export class AnalyticsConfigurator
29
32
  extends BaseConfigBuilder<AnalyticsConfig>
@@ -85,11 +88,12 @@ export class AnalyticsConfigurator
85
88
  }
86
89
 
87
90
  /**
88
- * Registers a analytics collector with the configurator.
91
+ * Registers an analytics collector factory.
89
92
  *
90
- * @param identifier - The name of the collector
91
- * @param callback - A callback function that returns an analytics collector instance
92
- * @returns The current instance for method chaining
93
+ * @template T - The concrete analytics event type the collector emits.
94
+ * @param identifier - Unique key for the collector.
95
+ * @param callback - Factory that receives module-resolution args and returns a collector.
96
+ * @returns `this` for method chaining.
93
97
  */
94
98
  setCollector<T extends AnalyticsEvent>(
95
99
  identifier: string,
@@ -100,11 +104,12 @@ export class AnalyticsConfigurator
100
104
  }
101
105
 
102
106
  /**
103
- * Registers a analytics adapter with the configurator.
107
+ * Registers an analytics adapter factory.
104
108
  *
105
- * @param identifier - The name of the adapter
106
- * @param callback - A callback function that returns an analytics adapter instance
107
- * @returns The current instance for method chaining
109
+ * @template T - The concrete analytics event type the adapter handles.
110
+ * @param identifier - Unique key for the adapter.
111
+ * @param callback - Factory that receives module-resolution args and returns an adapter.
112
+ * @returns `this` for method chaining.
108
113
  */
109
114
  setAdapter<T extends AnalyticsEvent>(
110
115
  identifier: string,
@@ -2,21 +2,43 @@ import type { ObservableInput, Subscription } from 'rxjs';
2
2
  import type { AnalyticsEvent } from './types.js';
3
3
 
4
4
  /**
5
- * Interface for analytics providers used to track analytics events.
5
+ * Public interface for the analytics provider exposed by the `analytics` module.
6
+ *
7
+ * @remarks
8
+ * Use `trackAnalytic` to push a single event or `trackAnalytic$` to forward
9
+ * an observable stream of events. Both methods route events to all registered
10
+ * adapters.
6
11
  */
7
12
  export interface IAnalyticsProvider {
8
13
  /**
9
- * Tracks a analytics event.
14
+ * Pushes a single analytics event to all registered adapters.
10
15
  *
11
- * @param event - The analytic event to track.
16
+ * @param event - The analytics event to track.
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * provider.trackAnalytic({
21
+ * name: 'button-click',
22
+ * value: 'save',
23
+ * attributes: { page: 'settings' },
24
+ * });
25
+ * ```
12
26
  */
13
27
  trackAnalytic(event: AnalyticsEvent): void;
14
28
 
15
29
  /**
16
- * Uses a analytics stream and returns both Disposable and Subscription for cleanup.
30
+ * Subscribes to an observable stream of analytics events and forwards each
31
+ * emission to all registered adapters.
32
+ *
33
+ * @param analytic$ - Observable input stream of analytics events.
34
+ * @returns A combined `Disposable & Subscription` handle for cleanup.
17
35
  *
18
- * @param analytic$ - Observable input stream of analytic events.
19
- * @returns Object containing both Disposable and Subscription for proper cleanup.
36
+ * @example
37
+ * ```ts
38
+ * const sub = provider.trackAnalytic$(myEvent$);
39
+ * // later
40
+ * sub.unsubscribe();
41
+ * ```
20
42
  */
21
43
  trackAnalytic$(analytic$: ObservableInput<AnalyticsEvent>): Disposable & Subscription;
22
44
  }
@@ -9,6 +9,13 @@ import { from, type ObservableInput, Subject, Subscription } from 'rxjs';
9
9
  import type { IAnalyticsCollector } from './collectors/AnalyticsCollector.interface.js';
10
10
  import type { IAnalyticsAdapter } from './adapters/AnalyticsAdapter.interface.js';
11
11
 
12
+ /**
13
+ * An RxJS `Subscription` that also implements the TC39 `Disposable` protocol.
14
+ *
15
+ * @remarks
16
+ * Returned by {@link AnalyticsProvider.trackAnalytic$} so callers can clean up
17
+ * with either `subscription.unsubscribe()` or `using` / `Symbol.dispose`.
18
+ */
12
19
  class DisposableSubscription extends Subscription {
13
20
  constructor(subscription: Subscription) {
14
21
  super(subscription.unsubscribe);
@@ -20,14 +27,22 @@ class DisposableSubscription extends Subscription {
20
27
  }
21
28
 
22
29
  /**
23
- * Provides analytics tracking, adapters integration and collectors for application instrumentation.
30
+ * Runtime analytics provider that collects events from collectors and dispatches
31
+ * them to adapters.
24
32
  *
25
- * The `AnalyticsProvider` class is responsible for collecting, processing and relaying analytics
26
- * data to the adapters. The events are collected with collectors.
33
+ * @remarks
34
+ * Created by the analytics module during initialisation. The provider:
35
+ *
36
+ * 1. Initialises all registered adapters and collectors.
37
+ * 2. Subscribes to every collector and merges their events into a shared stream.
38
+ * 3. Forwards each emitted event to every registered adapter via
39
+ * {@link IAnalyticsAdapter.registerAnalytic}.
40
+ *
41
+ * Consumers can also push ad-hoc events with {@link AnalyticsProvider.trackAnalytic}
42
+ * or subscribe an observable stream with {@link AnalyticsProvider.trackAnalytic$}.
27
43
  *
28
- * @typeParam AnalyticsConfig - The configuration type for analytics.
29
- * @implements IAnalyticsProvider
30
44
  * @extends BaseModuleProvider<AnalyticsConfig>
45
+ * @implements IAnalyticsProvider
31
46
  */
32
47
  export class AnalyticsProvider
33
48
  extends BaseModuleProvider<AnalyticsConfig>
@@ -46,16 +61,21 @@ export class AnalyticsProvider
46
61
  }
47
62
 
48
63
  /**
49
- * Initializes the analytics provider with adapters and collectors.
64
+ * Initialises all adapters and collectors, then wires collector output into
65
+ * the adapter pipeline.
66
+ *
67
+ * @remarks
68
+ * Initialisation is idempotent within the module lifecycle — the module calls
69
+ * this once during `module.initialize`. Steps:
70
+ *
71
+ * 1. Initialise all collectors (via `Promise.allSettled`).
72
+ * 2. Initialise all adapters (via `Promise.allSettled`).
73
+ * 3. Subscribe to each collector and forward events into the shared subject.
74
+ * 4. Subscribe to the shared subject and dispatch to every adapter.
50
75
  *
51
- * This method sets up the provider for operation by:
52
- * 1. Storing the provided adapters
53
- * 2. Initializing all adapters
54
- * 3. Storing the provided collectors
55
- * 4. Initializing all collectors
56
- * 5. Setting up subscription for analytics processing
76
+ * All subscriptions are registered as teardowns on the base provider.
57
77
  *
58
- * @returns A promise that resolves when initialization is complete
78
+ * @returns A promise that resolves when all adapters and collectors are initialised.
59
79
  */
60
80
  async initialize(): Promise<void> {
61
81
  const initializedCollectors = Object.values(this.#collectors).map((collector) =>
@@ -89,9 +109,9 @@ export class AnalyticsProvider
89
109
  }
90
110
 
91
111
  /**
92
- * Tracks an analytics event
112
+ * Pushes a single analytics event to all registered adapters.
93
113
  *
94
- * @param event - The analytics event to track
114
+ * @param event - The analytics event to track.
95
115
  */
96
116
  trackAnalytic(event: AnalyticsEvent): void {
97
117
  // @TODO: Validate AnalyticsEvent includes name, value and attributes
@@ -99,10 +119,11 @@ export class AnalyticsProvider
99
119
  }
100
120
 
101
121
  /**
102
- * Uses a analytics stream and returns both Disposable and Subscription for cleanup.
122
+ * Subscribes to an observable stream of analytics events and forwards each
123
+ * emission to all registered adapters.
103
124
  *
104
- * @param analytic$ - Observable input stream of analytic events.
105
- * @returns Object containing both Disposable and Subscription for proper cleanup.
125
+ * @param analytic$ - Observable input stream of analytics events.
126
+ * @returns A {@link DisposableSubscription} supporting both `unsubscribe()` and `Symbol.dispose`.
106
127
  */
107
128
  trackAnalytic$(analytic$: ObservableInput<AnalyticsEvent>): Disposable & Subscription {
108
129
  const subscription = from(analytic$)
@@ -1,9 +1,22 @@
1
1
  import type { AnalyticsEvent } from '../types.js';
2
2
 
3
3
  /**
4
- * Interface representing an analytics adapter responsible for handling analytics events.
4
+ * Contract for an analytics adapter that receives events and exports them to a backend.
5
5
  *
6
- * @template T - The type of analytics event handled by the adapter. Defaults to `AnalyticsEvent`.
6
+ * @remarks
7
+ * Implement this interface to create a custom adapter. Register it via
8
+ * {@link IAnalyticsConfigurator.setAdapter}. The adapter must also implement
9
+ * `Disposable` for resource cleanup.
10
+ *
11
+ * @template T - The analytics event type handled by the adapter, defaults to {@link AnalyticsEvent}.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * class MyAdapter implements IAnalyticsAdapter {
16
+ * registerAnalytic(event) { fetch('/analytics', { method: 'POST', body: JSON.stringify(event) }); }
17
+ * [Symbol.dispose]() { /* cleanup *\/ }
18
+ * }
19
+ * ```
7
20
  */
8
21
  export interface IAnalyticsAdapter<T extends AnalyticsEvent = AnalyticsEvent> extends Disposable {
9
22
  /**