Skip to content

Commit

Permalink
refactor(schematic-utils): remove external deps
Browse files Browse the repository at this point in the history
Get rid of external deps and use their internal counterparts
  • Loading branch information
krzysiek-va committed Jul 30, 2021
1 parent a88c2d3 commit 29b20cf
Show file tree
Hide file tree
Showing 140 changed files with 13,733 additions and 85 deletions.
8 changes: 7 additions & 1 deletion packages/schematic-utils/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
{
"extends": "../../.eslintrc",
"rules": {},
"ignorePatterns": ["!**/*"]
"ignorePatterns": [
"*.spec.ts",
"**/virtual-fs/*",
"**/workspace/*",
"**/logger/*",
"**/analytics/*"
]
}
47 changes: 47 additions & 0 deletions packages/schematic-utils/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion packages/schematic-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@
"scripts": {
"test": "jest",
"build": "tsc -p tsconfig.json",
"lint": "eslint ./src/**/** --ignore-pattern '*.spec.ts'",
"lint": "eslint \"./src/**/**\"",
"preversion": "npm run build"
},
"dependencies": {
"ajv": "^8.6.2",
"ajv-formats": "^2.1.0",
"source-map": "^0.7.3"
},
"devDependencies": {
Expand Down
62 changes: 62 additions & 0 deletions packages/schematic-utils/src/analytics/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

export interface CustomDimensionsAndMetricsOptions {
dimensions?: (boolean | number | string)[];
metrics?: (boolean | number | string)[];
}

export interface EventOptions extends CustomDimensionsAndMetricsOptions {
label?: string;
value?: string;
}

export interface ScreenviewOptions extends CustomDimensionsAndMetricsOptions {
appVersion?: string;
appId?: string;
appInstallerId?: string;
}

export interface PageviewOptions extends CustomDimensionsAndMetricsOptions {
hostname?: string;
title?: string;
}

export interface TimingOptions extends CustomDimensionsAndMetricsOptions {
label?: string;
}

/**
* Interface for managing analytics. This is highly platform dependent, and mostly matches
* Google Analytics. The reason the interface is here is to remove the dependency to an
* implementation from most other places.
*
* The methods exported from this interface more or less match those needed by us in the
* universal analytics package, see https://unpkg.com/@types/[email protected]/index.d.ts
* for typings. We mostly named arguments to make it easier to follow, but didn't change or
* add any semantics to those methods. They're mapping GA and u-a one for one.
*
* The Angular CLI (or any other kind of backend) should forward it to some compatible backend.
*/
export interface Analytics {
event(category: string, action: string, options?: EventOptions): void;
screenview(
screenName: string,
appName: string,
options?: ScreenviewOptions
): void;
pageview(path: string, options?: PageviewOptions): void;
timing(
category: string,
variable: string,
time: string | number,
options?: TimingOptions
): void;

flush(): Promise<void>;
}
153 changes: 153 additions & 0 deletions packages/schematic-utils/src/analytics/forwarder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {
Analytics,
EventOptions,
PageviewOptions,
ScreenviewOptions,
TimingOptions,
} from "./api";
import { JsonObject } from "../json/interface";

export enum AnalyticsReportKind {
Event = "event",
Screenview = "screenview",
Pageview = "pageview",
Timing = "timing",
}

export interface AnalyticsReportBase extends JsonObject {
kind: AnalyticsReportKind;
}

export interface AnalyticsReportEvent extends AnalyticsReportBase {
kind: AnalyticsReportKind.Event;
options: JsonObject & EventOptions;
category: string;
action: string;
}
export interface AnalyticsReportScreenview extends AnalyticsReportBase {
kind: AnalyticsReportKind.Screenview;
options: JsonObject & ScreenviewOptions;
screenName: string;
appName: string;
}
export interface AnalyticsReportPageview extends AnalyticsReportBase {
kind: AnalyticsReportKind.Pageview;
options: JsonObject & PageviewOptions;
path: string;
}
export interface AnalyticsReportTiming extends AnalyticsReportBase {
kind: AnalyticsReportKind.Timing;
options: JsonObject & TimingOptions;
category: string;
variable: string;
time: string | number;
}

export type AnalyticsReport =
| AnalyticsReportEvent
| AnalyticsReportScreenview
| AnalyticsReportPageview
| AnalyticsReportTiming;

/**
* A function that can forward analytics along some stream. AnalyticsReport is already a
* JsonObject descendant, but we force it here so the user knows it's safe to serialize.
*/
export type AnalyticsForwarderFn = (
report: JsonObject & AnalyticsReport
) => void;

/**
* A class that follows the Analytics interface and forwards analytic reports (JavaScript objects).
* AnalyticsReporter is the counterpart which takes analytic reports and report them to another
* Analytics interface.
*/
export class ForwardingAnalytics implements Analytics {
constructor(protected _fn: AnalyticsForwarderFn) {}

event(category: string, action: string, options?: EventOptions) {
this._fn({
kind: AnalyticsReportKind.Event,
category,
action,
options: { ...options } as JsonObject,
});
}
screenview(screenName: string, appName: string, options?: ScreenviewOptions) {
this._fn({
kind: AnalyticsReportKind.Screenview,
screenName,
appName,
options: { ...options } as JsonObject,
});
}
pageview(path: string, options?: PageviewOptions) {
this._fn({
kind: AnalyticsReportKind.Pageview,
path,
options: { ...options } as JsonObject,
});
}
timing(
category: string,
variable: string,
time: string | number,
options?: TimingOptions
): void {
this._fn({
kind: AnalyticsReportKind.Timing,
category,
variable,
time,
options: { ...options } as JsonObject,
});
}

// We do not support flushing.
flush() {
return Promise.resolve();
}
}

export class AnalyticsReporter {
constructor(protected _analytics: Analytics) {}

report(report: AnalyticsReport) {
switch (report.kind) {
case AnalyticsReportKind.Event:
this._analytics.event(report.category, report.action, report.options);
break;
case AnalyticsReportKind.Screenview:
this._analytics.screenview(
report.screenName,
report.appName,
report.options
);
break;
case AnalyticsReportKind.Pageview:
this._analytics.pageview(report.path, report.options);
break;
case AnalyticsReportKind.Timing:
this._analytics.timing(
report.category,
report.variable,
report.time,
report.options
);
break;

default:
throw new Error(
"Unexpected analytics report: " + JSON.stringify(report)
);
}
}
}
86 changes: 86 additions & 0 deletions packages/schematic-utils/src/analytics/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

export * from "./api";
export * from "./forwarder";
export * from "./logging";
export * from "./multi";
export * from "./noop";

/**
* MAKE SURE TO KEEP THIS IN SYNC WITH THE TABLE AND CONTENT IN `/docs/design/analytics.md`.
* WE LIST THOSE DIMENSIONS (AND MORE).
*
* These cannot be in their respective schema.json file because we either change the type
* (e.g. --buildEventLog is string, but we want to know the usage of it, not its value), or
* some validation needs to be done (we cannot record ng add --collection if it's not marked as
* allowed).
*/
export enum NgCliAnalyticsDimensions {
CpuCount = 1,
CpuSpeed = 2,
RamInGigabytes = 3,
NodeVersion = 4,
NgAddCollection = 6,
NgIvyEnabled = 8,
BuildErrors = 20,
}

export enum NgCliAnalyticsMetrics {
NgComponentCount = 1,
UNUSED_2 = 2,
UNUSED_3 = 3,
UNUSED_4 = 4,
BuildTime = 5,
NgOnInitCount = 6,
InitialChunkSize = 7,
TotalChunkCount = 8,
TotalChunkSize = 9,
LazyChunkCount = 10,
LazyChunkSize = 11,
AssetCount = 12,
AssetSize = 13,
PolyfillSize = 14,
CssSize = 15,
}

// This table is used when generating the analytics.md file. It should match the enum above
// or the validate-user-analytics script will fail.
export const NgCliAnalyticsDimensionsFlagInfo: {
[name: string]: [string, string];
} = {
CpuCount: ["CPU Count", "number"],
CpuSpeed: ["CPU Speed", "number"],
RamInGigabytes: ["RAM (In GB)", "number"],
NodeVersion: ["Node Version", "number"],
NgAddCollection: ["--collection", "string"],
NgIvyEnabled: ["Ivy Enabled", "boolean"],
BuildErrors: ["Build Errors (comma separated)", "string"],
};

// This table is used when generating the analytics.md file. It should match the enum above
// or the validate-user-analytics script will fail.
export const NgCliAnalyticsMetricsFlagInfo: {
[name: string]: [string, string];
} = {
NgComponentCount: ["NgComponentCount", "number"],
UNUSED_2: ["UNUSED_2", "none"],
UNUSED_3: ["UNUSED_3", "none"],
UNUSED_4: ["UNUSED_4", "none"],
BuildTime: ["Build Time", "number"],
NgOnInitCount: ["NgOnInit Count", "number"],
InitialChunkSize: ["Initial Chunk Size", "number"],
TotalChunkCount: ["Total Chunk Count", "number"],
TotalChunkSize: ["Total Chunk Size", "number"],
LazyChunkCount: ["Lazy Chunk Count", "number"],
LazyChunkSize: ["Lazy Chunk Size", "number"],
AssetCount: ["Asset Count", "number"],
AssetSize: ["Asset Size", "number"],
PolyfillSize: [" Polyfill Size", "number"],
CssSize: [" Css Size", "number"],
};
Loading

0 comments on commit 29b20cf

Please sign in to comment.