@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.
- package/CHANGELOG.md +34 -0
- package/README.md +147 -130
- package/dist/esm/AnalyticsConfigurator.js +22 -17
- package/dist/esm/AnalyticsConfigurator.js.map +1 -1
- package/dist/esm/AnalyticsProvider.js +39 -18
- package/dist/esm/AnalyticsProvider.js.map +1 -1
- package/dist/esm/adapters/ConsoleAnalyticsAdapter.js +15 -1
- package/dist/esm/adapters/ConsoleAnalyticsAdapter.js.map +1 -1
- package/dist/esm/adapters/FusionAnalyticsAdapter.js +32 -3
- package/dist/esm/adapters/FusionAnalyticsAdapter.js.map +1 -1
- package/dist/esm/adapters/index.js.map +1 -1
- package/dist/esm/collectors/AppLoadedCollector.js +21 -5
- package/dist/esm/collectors/AppLoadedCollector.js.map +1 -1
- package/dist/esm/collectors/AppSelectedCollector.js +17 -5
- package/dist/esm/collectors/AppSelectedCollector.js.map +1 -1
- package/dist/esm/collectors/BaseCollector.js +48 -3
- package/dist/esm/collectors/BaseCollector.js.map +1 -1
- package/dist/esm/collectors/ContextSelectedCollector.js +20 -5
- package/dist/esm/collectors/ContextSelectedCollector.js.map +1 -1
- package/dist/esm/collectors/index.js.map +1 -1
- package/dist/esm/collectors/utils/extractAppMetadata.js +25 -4
- package/dist/esm/collectors/utils/extractAppMetadata.js.map +1 -1
- package/dist/esm/collectors/utils/extractContextMetadata.js +13 -2
- package/dist/esm/collectors/utils/extractContextMetadata.js.map +1 -1
- package/dist/esm/enable-analytics.js +18 -3
- package/dist/esm/enable-analytics.js.map +1 -1
- package/dist/esm/index.js +18 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/logExporters/fusionOTLPLogExporter/FusionOTLPLogExporter.js +26 -4
- package/dist/esm/logExporters/fusionOTLPLogExporter/FusionOTLPLogExporter.js.map +1 -1
- package/dist/esm/logExporters/fusionOTLPLogExporter/HttpClientExporterTransport.js +36 -7
- package/dist/esm/logExporters/fusionOTLPLogExporter/HttpClientExporterTransport.js.map +1 -1
- package/dist/esm/logExporters/index.js +8 -0
- package/dist/esm/logExporters/index.js.map +1 -1
- package/dist/esm/module.js +8 -8
- package/dist/esm/version.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/AnalyticsConfigurator.d.ts +22 -17
- package/dist/types/AnalyticsConfigurator.interface.d.ts +41 -12
- package/dist/types/AnalyticsProvider.d.ts +32 -18
- package/dist/types/AnalyticsProvider.interface.d.ts +28 -6
- package/dist/types/adapters/AnalyticsAdapter.interface.d.ts +15 -2
- package/dist/types/adapters/ConsoleAnalyticsAdapter.d.ts +15 -1
- package/dist/types/adapters/FusionAnalyticsAdapter.d.ts +32 -3
- package/dist/types/adapters/index.d.ts +8 -0
- package/dist/types/collectors/AnalyticsCollector.interface.d.ts +11 -2
- package/dist/types/collectors/AppLoadedCollector.d.ts +20 -2
- package/dist/types/collectors/AppSelectedCollector.d.ts +16 -2
- package/dist/types/collectors/BaseCollector.d.ts +58 -3
- package/dist/types/collectors/ContextSelectedCollector.d.ts +19 -2
- package/dist/types/collectors/index.d.ts +8 -0
- package/dist/types/collectors/utils/extractAppMetadata.d.ts +27 -0
- package/dist/types/collectors/utils/extractContextMetadata.d.ts +14 -0
- package/dist/types/enable-analytics.d.ts +19 -3
- package/dist/types/index.d.ts +18 -0
- package/dist/types/logExporters/fusionOTLPLogExporter/FusionOTLPLogExporter.d.ts +21 -3
- package/dist/types/logExporters/fusionOTLPLogExporter/HttpClientExporterTransport.d.ts +24 -1
- package/dist/types/logExporters/index.d.ts +8 -0
- package/dist/types/module.d.ts +15 -15
- package/dist/types/types.d.ts +38 -7
- package/dist/types/version.d.ts +1 -1
- package/package.json +11 -11
- package/src/AnalyticsConfigurator.interface.ts +41 -12
- package/src/AnalyticsConfigurator.ts +22 -17
- package/src/AnalyticsProvider.interface.ts +28 -6
- package/src/AnalyticsProvider.ts +39 -18
- package/src/adapters/AnalyticsAdapter.interface.ts +15 -2
- package/src/adapters/ConsoleAnalyticsAdapter.ts +15 -1
- package/src/adapters/FusionAnalyticsAdapter.ts +32 -3
- package/src/adapters/index.ts +8 -0
- package/src/collectors/AnalyticsCollector.interface.ts +11 -2
- package/src/collectors/AppLoadedCollector.ts +21 -5
- package/src/collectors/AppSelectedCollector.ts +17 -5
- package/src/collectors/BaseCollector.ts +58 -3
- package/src/collectors/ContextSelectedCollector.ts +20 -5
- package/src/collectors/index.ts +8 -0
- package/src/collectors/utils/extractAppMetadata.ts +27 -4
- package/src/collectors/utils/extractContextMetadata.ts +14 -2
- package/src/enable-analytics.ts +19 -3
- package/src/index.ts +19 -0
- package/src/logExporters/fusionOTLPLogExporter/FusionOTLPLogExporter.ts +26 -4
- package/src/logExporters/fusionOTLPLogExporter/HttpClientExporterTransport.ts +36 -7
- package/src/logExporters/index.ts +8 -0
- package/src/module.ts +15 -15
- package/src/types.ts +39 -8
- 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
|
|
6
|
+
* Enables the analytics module on a Fusion Framework module configurator.
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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 {};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
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
|
-
*
|
|
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';
|
package/dist/types/module.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
6
|
+
* Represents the Analytics module type within the Fusion Framework module system.
|
|
7
7
|
*
|
|
8
8
|
* @remarks
|
|
9
|
-
* This type defines a module
|
|
10
|
-
* It specifies the provider and configurator interfaces for analytics
|
|
11
|
-
*
|
|
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
|
-
* @
|
|
14
|
-
* @
|
|
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
|
|
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
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
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";
|
package/dist/types/types.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
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
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* -
|
|
14
|
-
* -
|
|
15
|
-
* -
|
|
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
|
};
|
package/dist/types/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "
|
|
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": "
|
|
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.
|
|
52
|
-
"@equinor/fusion-framework-module": "
|
|
53
|
-
"@equinor/fusion-framework-module-app": "
|
|
54
|
-
"@equinor/fusion-framework-module-
|
|
55
|
-
"@equinor/fusion-framework-module-
|
|
56
|
-
"@equinor/fusion-framework-module-
|
|
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.
|
|
60
|
-
"vitest": "^
|
|
61
|
-
"@equinor/fusion-observable": "^
|
|
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": "
|
|
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
|
-
*
|
|
7
|
+
* Resolved analytics configuration containing the instantiated collectors and adapters.
|
|
8
8
|
*
|
|
9
|
-
* @
|
|
10
|
-
*
|
|
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
|
-
*
|
|
22
|
+
* Configuration-time interface for registering analytics adapters and collectors.
|
|
19
23
|
*
|
|
20
|
-
*
|
|
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
|
-
* @
|
|
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
|
-
*
|
|
45
|
+
* Registers an analytics collector factory identified by a unique key.
|
|
27
46
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
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
|
-
*
|
|
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
|
-
* @
|
|
41
|
-
* @param
|
|
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
|
-
*
|
|
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
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
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
|
|
26
|
-
* @see
|
|
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
|
|
91
|
+
* Registers an analytics collector factory.
|
|
89
92
|
*
|
|
90
|
-
* @
|
|
91
|
-
* @param
|
|
92
|
-
* @
|
|
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
|
|
107
|
+
* Registers an analytics adapter factory.
|
|
104
108
|
*
|
|
105
|
-
* @
|
|
106
|
-
* @param
|
|
107
|
-
* @
|
|
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
|
-
*
|
|
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
|
-
*
|
|
14
|
+
* Pushes a single analytics event to all registered adapters.
|
|
10
15
|
*
|
|
11
|
-
* @param event - The
|
|
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
|
-
*
|
|
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
|
-
* @
|
|
19
|
-
*
|
|
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
|
}
|
package/src/AnalyticsProvider.ts
CHANGED
|
@@ -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
|
-
*
|
|
30
|
+
* Runtime analytics provider that collects events from collectors and dispatches
|
|
31
|
+
* them to adapters.
|
|
24
32
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
105
|
-
* @returns
|
|
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
|
-
*
|
|
4
|
+
* Contract for an analytics adapter that receives events and exports them to a backend.
|
|
5
5
|
*
|
|
6
|
-
* @
|
|
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
|
/**
|