Skip to content

Commit 33c4bb1

Browse files
committed
refactor(@angular/cli): decouple AnalyticsCollector from CommandContext
The `AnalyticsCollector` class is made more modular and easier to test by removing its direct dependency on the `CommandContext`. Instead of accepting the entire context object, the constructor now receives only the specific dependencies it requires: the logger, user ID, and package manager information. This improves separation of concerns and simplifies unit testing of the analytics collector.
1 parent 79b69f5 commit 33c4bb1

File tree

2 files changed

+17
-9
lines changed

2 files changed

+17
-9
lines changed

packages/angular/cli/src/analytics/analytics-collector.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9+
import { logging } from '@angular-devkit/core';
910
import { randomUUID } from 'node:crypto';
1011
import * as https from 'node:https';
1112
import * as os from 'node:os';
1213
import * as querystring from 'node:querystring';
1314
import * as semver from 'semver';
14-
import type { CommandContext } from '../command-builder/command-module';
1515
import { ngDebug } from '../utilities/environment-options';
1616
import { assertIsError } from '../utilities/error';
1717
import { VERSION } from '../utilities/version';
@@ -32,8 +32,9 @@ export class AnalyticsCollector {
3232
private readonly userParameters: Record<UserCustomDimension, PrimitiveTypes | undefined>;
3333

3434
constructor(
35-
private context: CommandContext,
35+
private logger: logging.Logger,
3636
userId: string,
37+
packageManagerInfo: { name: string; version: string | undefined },
3738
) {
3839
const requestParameters: Partial<Record<RequestParameter, PrimitiveTypes>> = {
3940
[RequestParameter.ProtocolVersion]: 2,
@@ -63,7 +64,7 @@ export class AnalyticsCollector {
6364
this.requestParameterStringified = querystring.stringify(requestParameters);
6465

6566
const parsedVersion = semver.parse(process.version);
66-
const packageManagerVersion = context.packageManager.version;
67+
const packageManagerVersion = packageManagerInfo.version;
6768

6869
this.userParameters = {
6970
// While architecture is being collect by GA as UserAgentArchitecture.
@@ -75,7 +76,7 @@ export class AnalyticsCollector {
7576
? `${parsedVersion.major}.${parsedVersion.minor}.${parsedVersion.patch}`
7677
: 'other',
7778
[UserCustomDimension.NodeMajorVersion]: parsedVersion?.major,
78-
[UserCustomDimension.PackageManager]: context.packageManager.name,
79+
[UserCustomDimension.PackageManager]: packageManagerInfo.name,
7980
[UserCustomDimension.PackageManagerVersion]: packageManagerVersion,
8081
[UserCustomDimension.PackageManagerMajorVersion]: packageManagerVersion
8182
? +packageManagerVersion.split('.', 1)[0]
@@ -152,7 +153,7 @@ export class AnalyticsCollector {
152153

153154
async flush(): Promise<void> {
154155
const pendingTrackingEvents = this.trackingEventsQueue;
155-
this.context.logger.debug(`Analytics flush size. ${pendingTrackingEvents?.length}.`);
156+
this.logger.debug(`Analytics flush size. ${pendingTrackingEvents?.length}.`);
156157

157158
if (!pendingTrackingEvents?.length) {
158159
return;
@@ -167,7 +168,7 @@ export class AnalyticsCollector {
167168
} catch (error) {
168169
// Failure to report analytics shouldn't crash the CLI.
169170
assertIsError(error);
170-
this.context.logger.debug(`Send analytics error. ${error.message}.`);
171+
this.logger.debug(`Send analytics error. ${error.message}.`);
171172
}
172173
}
173174

packages/angular/cli/src/command-builder/command-module.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,10 @@ export interface CommandContext {
6060

6161
export type OtherOptions = Record<string, unknown>;
6262

63-
export interface CommandModuleImplementation<T extends {} = {}>
64-
extends Omit<YargsCommandModule<{}, T>, 'builder' | 'handler'> {
63+
export interface CommandModuleImplementation<T extends {} = {}> extends Omit<
64+
YargsCommandModule<{}, T>,
65+
'builder' | 'handler'
66+
> {
6567
/** Scope in which the command can be executed in. */
6668
scope: CommandScope;
6769

@@ -187,7 +189,12 @@ export abstract class CommandModule<T extends {} = {}> implements CommandModuleI
187189
['version', 'update', 'analytics'].includes(this.commandName),
188190
);
189191

190-
return userId ? new AnalyticsCollector(this.context, userId) : undefined;
192+
return userId
193+
? new AnalyticsCollector(this.context.logger, userId, {
194+
name: this.context.packageManager.name,
195+
version: this.context.packageManager.version,
196+
})
197+
: undefined;
191198
}
192199

193200
/**

0 commit comments

Comments
 (0)