-
Notifications
You must be signed in to change notification settings - Fork 46
/
Copy pathanalytics-data.ts
162 lines (146 loc) · 4.38 KB
/
analytics-data.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/* Copyright (c) 2020 SAP SE or an SAP affiliate company. All rights reserved. */
import fs from 'fs';
import os from 'os';
import path from 'path';
import { findProjectRoot } from '@sap-cloud-sdk/util';
import { UsageAnalyticsProjectConfig } from './analytics-types';
import { enforceValidConfig } from './config';
import { hash } from './util';
const sdkModulePrefix = '@sap';
/**
* Collects insensitive data for SAP Web Analytics.
* For details, check the following blog post: https://blogs.sap.com/2018/10/23/usage-analytics-s4sdk/
* @param config - Usage analytics config of the given project
* @returns An object that includes information on project development environment
* @hidden
*/
export async function getAnalyticsData(
config: UsageAnalyticsProjectConfig
): Promise<AnalyticsData> {
const projectRootDir = findProjectRoot(path.resolve());
const packageJson = JSON.parse(
fs.readFileSync(path.resolve(projectRootDir, 'package.json'), 'utf8')
);
return {
project_id: getProjectIdentifier(config, packageJson),
os: Object.values(getOperatingSystemInfo()).join(','),
node: getNodeVersion(),
npm: getNpmVersion(),
typescript: usesTypeScript(packageJson),
sdk_dependencies: getSapCloudSdkDependencies(packageJson),
third_party_dependencies: getThirdPartyDependencies(packageJson)
}; // SWA expects a certain column order: please do not change the order of this object!
}
export function getProjectIdentifier(
config: UsageAnalyticsProjectConfig,
packageJson: PackageJson
): string {
if (!config.salt) {
throw Error('Salt is missing in config!');
}
config = enforceValidConfig(config);
const projectName = packageJson.name + config.salt;
return hash(projectName);
}
function usesTypeScript(packageJson: PackageJson): string {
const mergedDeps = {
...packageJson.dependencies,
...packageJson.devDependencies
} as Record<string, string>;
return mergedDeps.typescript ? 'true' : 'false';
}
function getSapCloudSdkDependencies(packageJson: PackageJson): string {
const dependencies = {
...packageJson.dependencies,
...packageJson.devDependencies
};
return Object.entries(dependencies)
.filter(([name]) => name.startsWith(sdkModulePrefix))
.map(dep => dep.join('@'))
.sort()
.join(', ');
}
function getThirdPartyDependencies(packageJson: PackageJson) {
const dependencies = {
...packageJson.dependencies,
...packageJson.devDependencies
};
return Object.entries(dependencies)
.filter(([name]) => !name.startsWith(sdkModulePrefix))
.map(dep => dep.join('@'))
.sort()
.join(', ');
}
function getNpmVersion(): string {
const userAgent = process.env.npm_config_user_agent;
if (!userAgent) {
return 'no version detected'; // Rather return something and get some data than throwing and getting no data
}
// Npm_config_user_agent has "npm/x.x.x node/x.x.x operatingSystemName architecture" format
const npmInfo = userAgent.split(' ')[0];
return sanitizeVersionFormat(npmInfo.slice(4));
}
function getNodeVersion(): string {
const userAgent = process.env.npm_config_user_agent;
if (!userAgent) {
return 'no version detected'; // Rather return something and get some data than throwing and getting no data
}
const nodeInfo = userAgent.split(' ')[1];
return sanitizeVersionFormat(nodeInfo.slice(5));
}
function sanitizeVersionFormat(version: string): string {
return version.startsWith('v') || version.startsWith('^')
? version.slice(1)
: version;
}
function getOperatingSystemInfo(): OperatingSystemInfo {
return {
name: os.platform(),
version: os.release(),
architecture: os.arch()
};
}
/**
* SAP Web Analytics data.
* @hidden
*/
export interface AnalyticsData {
/**
* A unique hash for a given project and salt
*/
project_id: string;
/**
* Node.js version.
*/
node: string;
/**
* NPM version.
*/
npm: string;
/**
* Operating system information.
*/
os: string;
/**
* Installed SAP cloud SDK modules.
*/
sdk_dependencies: string;
/**
* Installed third party dependencies.
*/
third_party_dependencies: string;
/**
* A flag specifying whether TypeScript is installed.
*/
typescript: string;
}
interface PackageJson {
name: string;
dependencies?: Record<string, string>;
devDependencies?: Record<string, string>;
}
interface OperatingSystemInfo {
name: string;
version: string;
architecture: string;
}