analytics/examples/nestjs-backend/analytics.module.ts

138 lines
3.5 KiB
TypeScript
Raw Normal View History

/**
* AnalyticsModule - NestJS module for backend analytics
*
* Provides:
* - BackendAnalyticsClient for manual tracking
* - Global interceptor for automatic request tracking
* - @TrackAnalytics decorator for method-level tracking
*/
import { Module, Global, DynamicModule } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { BackendAnalyticsClient } from '@analytics/client';
import type { BackendAnalyticsConfig } from '@analytics/client';
export const ANALYTICS_CLIENT = 'ANALYTICS_CLIENT';
export interface AnalyticsModuleOptions {
/**
* Analytics collector URL.
*/
collectorUrl: string;
/**
* Application name for event attribution.
*/
appName: string;
/**
* Enable/disable tracking (useful for tests).
*/
enabled?: boolean;
/**
* Enable debug logging.
*/
debug?: boolean;
}
@Global()
@Module({})
export class AnalyticsModule {
/**
* Register with static configuration.
*
* @example
* ```ts
* AnalyticsModule.register({
* collectorUrl: 'http://localhost:4001',
* appName: 'my-api',
* })
* ```
*/
static register(options: AnalyticsModuleOptions): DynamicModule {
return {
module: AnalyticsModule,
providers: [
{
provide: ANALYTICS_CLIENT,
useFactory: () => {
const config: BackendAnalyticsConfig = {
apiBaseUrl: options.collectorUrl,
appName: options.appName,
enabled: options.enabled ?? true,
enableDebugLogging: options.debug ?? false,
};
return new BackendAnalyticsClient(config);
},
},
],
exports: [ANALYTICS_CLIENT],
};
}
/**
* Register with async configuration (for ConfigService).
*
* @example
* ```ts
* AnalyticsModule.registerAsync({
* inject: [ConfigService],
* useFactory: (config: ConfigService) => ({
* collectorUrl: config.get('ANALYTICS_COLLECTOR_URL'),
* appName: config.get('APP_NAME'),
* enabled: config.get('NODE_ENV') !== 'test',
* }),
* })
* ```
*/
static registerAsync(options: {
inject?: any[];
useFactory: (...args: any[]) => AnalyticsModuleOptions | Promise<AnalyticsModuleOptions>;
}): DynamicModule {
return {
module: AnalyticsModule,
providers: [
{
provide: ANALYTICS_CLIENT,
inject: options.inject || [],
useFactory: async (...args: any[]) => {
const moduleOptions = await options.useFactory(...args);
const config: BackendAnalyticsConfig = {
apiBaseUrl: moduleOptions.collectorUrl,
appName: moduleOptions.appName,
enabled: moduleOptions.enabled ?? true,
enableDebugLogging: moduleOptions.debug ?? false,
};
return new BackendAnalyticsClient(config);
},
},
],
exports: [ANALYTICS_CLIENT],
};
}
}
/**
* Example AppModule setup:
*
* ```ts
* @Module({
* imports: [
* ConfigModule.forRoot({ isGlobal: true }),
* AnalyticsModule.registerAsync({
* inject: [ConfigService],
* useFactory: (config: ConfigService) => ({
* collectorUrl: config.get('ANALYTICS_URL', 'http://localhost:4001'),
* appName: 'my-api',
* enabled: config.get('NODE_ENV') !== 'test',
* debug: config.get('NODE_ENV') === 'development',
* }),
* }),
* ],
* })
* export class AppModule {}
* ```
*/