@dynatrace/react-native-plugin 2.225.0 → 2.231.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/README.md +31 -6
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceRNBridge.java +10 -0
- package/files/plugin.gradle +1 -1
- package/ios/DynatraceRNBridge.m +11 -0
- package/ios/lib/Dynatrace.xcframework/Info.plist +69 -0
- package/ios/lib/Dynatrace.xcframework/ios-arm64_armv7/Dynatrace.framework/Dynatrace +0 -0
- package/ios/lib/Dynatrace.xcframework/ios-arm64_armv7/Dynatrace.framework/Headers/Dynatrace.h +952 -0
- package/ios/lib/Dynatrace.xcframework/ios-arm64_armv7/Dynatrace.framework/Headers/Framework.h +18 -0
- package/ios/lib/Dynatrace.xcframework/ios-arm64_armv7/Dynatrace.framework/Info.plist +0 -0
- package/ios/lib/Dynatrace.xcframework/ios-arm64_armv7/Dynatrace.framework/Modules/module.modulemap +6 -0
- package/ios/lib/Dynatrace.xcframework/ios-arm64_i386_x86_64-simulator/Dynatrace.framework/Dynatrace +0 -0
- package/ios/lib/Dynatrace.xcframework/ios-arm64_i386_x86_64-simulator/Dynatrace.framework/Headers/Dynatrace.h +952 -0
- package/ios/lib/Dynatrace.xcframework/ios-arm64_i386_x86_64-simulator/Dynatrace.framework/Headers/Framework.h +18 -0
- package/ios/lib/Dynatrace.xcframework/ios-arm64_i386_x86_64-simulator/Dynatrace.framework/Info.plist +0 -0
- package/ios/lib/Dynatrace.xcframework/ios-arm64_i386_x86_64-simulator/Dynatrace.framework/Modules/module.modulemap +6 -0
- package/ios/lib/Dynatrace.xcframework/ios-arm64_i386_x86_64-simulator/Dynatrace.framework/_CodeSignature/CodeResources +147 -0
- package/ios/lib/Dynatrace.xcframework/tvos-arm64/Dynatrace.framework/Dynatrace +0 -0
- package/ios/lib/Dynatrace.xcframework/tvos-arm64/Dynatrace.framework/Headers/Dynatrace.h +952 -0
- package/ios/lib/Dynatrace.xcframework/tvos-arm64/Dynatrace.framework/Headers/Framework.h +18 -0
- package/ios/lib/Dynatrace.xcframework/tvos-arm64/Dynatrace.framework/Info.plist +0 -0
- package/ios/lib/Dynatrace.xcframework/tvos-arm64/Dynatrace.framework/Modules/module.modulemap +6 -0
- package/ios/lib/Dynatrace.xcframework/tvos-arm64_x86_64-simulator/Dynatrace.framework/Dynatrace +0 -0
- package/ios/lib/Dynatrace.xcframework/tvos-arm64_x86_64-simulator/Dynatrace.framework/Headers/Dynatrace.h +952 -0
- package/ios/lib/Dynatrace.xcframework/tvos-arm64_x86_64-simulator/Dynatrace.framework/Headers/Framework.h +18 -0
- package/ios/lib/Dynatrace.xcframework/tvos-arm64_x86_64-simulator/Dynatrace.framework/Info.plist +0 -0
- package/ios/lib/Dynatrace.xcframework/tvos-arm64_x86_64-simulator/Dynatrace.framework/Modules/module.modulemap +6 -0
- package/ios/lib/Dynatrace.xcframework/tvos-arm64_x86_64-simulator/Dynatrace.framework/_CodeSignature/CodeResources +135 -0
- package/lib/community/Picker.js +33 -0
- package/lib/dynatrace-reporter.js +30 -0
- package/lib/dynatrace-transformer.js +50 -0
- package/lib/instrumentor/base/Application.js +17 -0
- package/lib/instrumentor/base/Dynatrace.js +275 -0
- package/lib/instrumentor/base/DynatraceAction.js +66 -0
- package/lib/instrumentor/base/DynatraceBridge.js +5 -0
- package/lib/instrumentor/base/ElementHelper.js +58 -0
- package/lib/instrumentor/base/ErrorHandler.js +52 -0
- package/lib/instrumentor/base/Logger.js +15 -0
- package/lib/instrumentor/base/NullAction.js +27 -0
- package/lib/instrumentor/base/Picker.js +32 -0
- package/lib/instrumentor/base/RefreshControl.js +35 -0
- package/lib/instrumentor/base/Touchable.js +103 -0
- package/lib/instrumentor/base/UserPrivacyOptions.js +22 -0
- package/lib/instrumentor/base/configuration/AutoStartupConfiguration.js +17 -0
- package/lib/instrumentor/base/configuration/Configuration.js +26 -0
- package/lib/instrumentor/base/configuration/ConfigurationDefaults.js +13 -0
- package/lib/instrumentor/base/configuration/ManualStartupConfiguration.js +34 -0
- package/lib/instrumentor/base/interface/IAutoConfiguration.js +2 -0
- package/lib/instrumentor/base/interface/IDynatrace.js +2 -0
- package/lib/instrumentor/base/interface/IDynatraceAction.js +2 -0
- package/lib/instrumentor/base/interface/IDynatraceBridge.js +2 -0
- package/lib/instrumentor/base/interface/IDynatraceProperties.js +2 -0
- package/lib/instrumentor/base/interface/ILogger.js +2 -0
- package/lib/instrumentor/base/model/DataCollectionLevel.js +11 -0
- package/lib/instrumentor/base/model/LogLevel.js +8 -0
- package/lib/instrumentor/base/model/Platform.js +9 -0
- package/lib/instrumentor/base/util/StringUtils.js +8 -0
- package/lib/instrumentor/dynatrace-instrumentation.js +1 -0
- package/lib/instrumentor/model/reference.js +2 -0
- package/lib/instrumentor/model/types.js +16 -0
- package/lib/instrumentor/parser/babel.js +63 -0
- package/lib/jsx-runtime.js +41 -0
- package/lib/metro/getSourceMapInfo.js +22 -0
- package/lib/react/Component.js +68 -0
- package/lib/react-native/RefreshControl.js +14 -0
- package/lib/react-native/Touchables.js +63 -0
- package/lib/react-native/index.js +12 -0
- package/lib/react-native.js +25 -0
- package/package.json +155 -1
- package/scripts/android.js +123 -0
- package/scripts/api/CustomArguments.js +2 -0
- package/scripts/api/CustomArgumentsBuilder.js +2 -0
- package/scripts/api/model/Platform.js +8 -0
- package/scripts/config.js +73 -0
- package/scripts/core/CustomArgumentsBuilderImpl.js +22 -0
- package/scripts/core/CustomArgumentsImpl.js +33 -0
- package/scripts/core/InstrumentCall.js +89 -0
- package/scripts/fileOperationHelper.js +184 -0
- package/scripts/install.js +47 -0
- package/scripts/instrument.js +7 -0
- package/scripts/ios.js +179 -0
- package/scripts/logger.js +79 -0
- package/scripts/pathsConstants.js +60 -0
- package/scripts/start.js +6 -0
- package/scripts/uninstall.js +80 -0
- package/scripts/util/CustomArgumentUtil.js +57 -0
- package/scripts/util/SourceMapUtil.js +30 -0
- package/scripts/util/StartUtil.js +9 -0
- package/scripts/util/instrumentUtil.js +28 -0
- package/typings/react-native-dynatrace.d.ts +6 -0
- package/util/constants.js +0 -4
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CustomArgumentsImpl = void 0;
|
|
4
|
+
class CustomArgumentsImpl {
|
|
5
|
+
constructor(configurationPath, gradlePath, plistPath) {
|
|
6
|
+
this.configurationPath = configurationPath;
|
|
7
|
+
this.gradlePath = gradlePath;
|
|
8
|
+
this.plistPath = plistPath;
|
|
9
|
+
}
|
|
10
|
+
getCustomGradlePath() {
|
|
11
|
+
return this.gradlePath;
|
|
12
|
+
}
|
|
13
|
+
isCustomGradlePathSet() {
|
|
14
|
+
return this.gradlePath !== undefined;
|
|
15
|
+
}
|
|
16
|
+
getCustomPlistPath() {
|
|
17
|
+
return this.plistPath;
|
|
18
|
+
}
|
|
19
|
+
isCustomPlistPathSet() {
|
|
20
|
+
return this.plistPath !== undefined;
|
|
21
|
+
}
|
|
22
|
+
getCustomConfigurationPath() {
|
|
23
|
+
return this.configurationPath;
|
|
24
|
+
}
|
|
25
|
+
isCustomConfigurationPathSet() {
|
|
26
|
+
return this.configurationPath !== undefined;
|
|
27
|
+
}
|
|
28
|
+
isEmpty() {
|
|
29
|
+
return !(this.isCustomConfigurationPathSet() || this.isCustomGradlePathSet()
|
|
30
|
+
|| this.isCustomPlistPathSet());
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.CustomArgumentsImpl = CustomArgumentsImpl;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.instrumentCommand = void 0;
|
|
4
|
+
const logger_1 = require("../logger");
|
|
5
|
+
const config_1 = require("../config");
|
|
6
|
+
const android = require("../android");
|
|
7
|
+
const pathsConstants_1 = require("../pathsConstants");
|
|
8
|
+
const ios_1 = require("../ios");
|
|
9
|
+
const instrumentUtil_1 = require("../util/instrumentUtil");
|
|
10
|
+
const path_1 = require("path");
|
|
11
|
+
const CustomArgumentUtil_1 = require("../util/CustomArgumentUtil");
|
|
12
|
+
const Platform_1 = require("../api/model/Platform");
|
|
13
|
+
const SourceMapUtil_1 = require("../util/SourceMapUtil");
|
|
14
|
+
function instrumentCommand() {
|
|
15
|
+
logger_1.default.logMessageSync("Starting instrumentation of React Native application ..", logger_1.default.INFO);
|
|
16
|
+
instrumentUtil_1.showVersionOfPlugin();
|
|
17
|
+
let pathToConfig = pathsConstants_1.default.getConfigFilePath();
|
|
18
|
+
let pathToGradle = pathsConstants_1.default.getAndroidGradleFile(pathsConstants_1.default.getAndroidFolder());
|
|
19
|
+
let androidAvailable = true;
|
|
20
|
+
let pathToPList = undefined;
|
|
21
|
+
let iosAvailable = true;
|
|
22
|
+
var argv = CustomArgumentUtil_1.parseCommandLine(process.argv.slice(2));
|
|
23
|
+
if (argv.isEmpty()) {
|
|
24
|
+
CustomArgumentUtil_1.clearCustomArguments();
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
CustomArgumentUtil_1.writeCustomArguments(argv);
|
|
28
|
+
}
|
|
29
|
+
if (argv.isCustomConfigurationPathSet()) {
|
|
30
|
+
pathToConfig = argv.getCustomConfigurationPath();
|
|
31
|
+
}
|
|
32
|
+
if (argv.isCustomGradlePathSet()) {
|
|
33
|
+
pathToGradle = argv.getCustomGradlePath();
|
|
34
|
+
androidAvailable = instrumentUtil_1.isPlatformAvailable(pathToGradle, Platform_1.Platform.Android);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
androidAvailable = instrumentUtil_1.isPlatformAvailable(pathsConstants_1.default.getAndroidFolder(), Platform_1.Platform.Android);
|
|
38
|
+
}
|
|
39
|
+
if (argv.isCustomPlistPathSet()) {
|
|
40
|
+
pathToPList = path_1.resolve(argv.getCustomPlistPath());
|
|
41
|
+
iosAvailable = instrumentUtil_1.isPlatformAvailable(pathToPList, Platform_1.Platform.iOS);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
iosAvailable = instrumentUtil_1.isPlatformAvailable(pathsConstants_1.default.getIOSFolder(), Platform_1.Platform.iOS);
|
|
45
|
+
}
|
|
46
|
+
pathToConfig = path_1.resolve(pathToConfig);
|
|
47
|
+
pathToGradle = path_1.resolve(pathToGradle);
|
|
48
|
+
if (iosAvailable || androidAvailable) {
|
|
49
|
+
try {
|
|
50
|
+
logger_1.default.logMessageSync("Trying to read configuration file: " + pathToConfig, logger_1.default.INFO);
|
|
51
|
+
let configAgent = config_1.readConfig(pathToConfig);
|
|
52
|
+
if (androidAvailable) {
|
|
53
|
+
try {
|
|
54
|
+
logger_1.default.logMessageSync("Starting Android Instrumentation with Dynatrace!", logger_1.default.INFO);
|
|
55
|
+
android.instrumentAndroidPlatform(pathToGradle, false);
|
|
56
|
+
android.writeGradleConfig(configAgent.android);
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
logger_1.default.logMessageSync(e.message, logger_1.default.ERROR);
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
logger_1.default.logMessageSync("Finished Android Instrumentation with Dynatrace!", logger_1.default.INFO);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (iosAvailable) {
|
|
66
|
+
try {
|
|
67
|
+
logger_1.default.logMessageSync("Starting iOS Instrumentation with Dynatrace!", logger_1.default.INFO);
|
|
68
|
+
ios_1.default.modifyPListFile(pathToPList, configAgent.ios, false);
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
logger_1.default.logMessageSync(e.message, logger_1.default.ERROR);
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
logger_1.default.logMessageSync("Finished iOS Instrumentation with Dynatrace!", logger_1.default.INFO);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
SourceMapUtil_1.patchMetroSourceMap();
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
logger_1.default.logMessageSync(e, logger_1.default.ERROR);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
logger_1.default.logMessageSync("Both Android and iOS Folder are not available - Skip instrumentation.", logger_1.default.WARNING);
|
|
85
|
+
}
|
|
86
|
+
logger_1.default.logMessageSync("Finished instrumentation of React Native application ..", logger_1.default.INFO);
|
|
87
|
+
logger_1.default.closeLogFile();
|
|
88
|
+
}
|
|
89
|
+
exports.instrumentCommand = instrumentCommand;
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
exports.default = {
|
|
7
|
+
checkIfFileExists,
|
|
8
|
+
checkIfFileExistsSync,
|
|
9
|
+
readTextFromFile,
|
|
10
|
+
readTextFromFileSync,
|
|
11
|
+
writeTextToFile,
|
|
12
|
+
writeTextToFileSync,
|
|
13
|
+
deleteDirectory,
|
|
14
|
+
deleteFile,
|
|
15
|
+
deleteFileSync,
|
|
16
|
+
createDirectorySync,
|
|
17
|
+
renameFile,
|
|
18
|
+
renameFileSync,
|
|
19
|
+
copyFile,
|
|
20
|
+
copyFileSync,
|
|
21
|
+
copyDirectory
|
|
22
|
+
};
|
|
23
|
+
function checkIfFileExists(_file) {
|
|
24
|
+
return new Promise(function (resolve, reject) {
|
|
25
|
+
fs.stat(_file, function (err) {
|
|
26
|
+
if (err) {
|
|
27
|
+
reject(`${err} - File doesn't exist: ${path.resolve(_file)}`);
|
|
28
|
+
}
|
|
29
|
+
resolve(_file);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function checkIfFileExistsSync(_file) {
|
|
34
|
+
fs.statSync(_file);
|
|
35
|
+
return _file;
|
|
36
|
+
}
|
|
37
|
+
function readTextFromFileSync(_file) {
|
|
38
|
+
return fs.readFileSync(_file, "utf8");
|
|
39
|
+
}
|
|
40
|
+
function readTextFromFile(_file) {
|
|
41
|
+
return new Promise(function (resolve, reject) {
|
|
42
|
+
fs.readFile(_file, "utf8", (err, data) => {
|
|
43
|
+
if (err) {
|
|
44
|
+
reject(err + "Could not read the file: " + path.resolve(_file));
|
|
45
|
+
}
|
|
46
|
+
resolve(data);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function writeTextToFile(_file, _text) {
|
|
51
|
+
return new Promise(function (resolve, reject) {
|
|
52
|
+
fs.writeFile(_file, _text, (err) => {
|
|
53
|
+
if (err) {
|
|
54
|
+
reject(err + " Could not write to file: " + path.resolve(_file));
|
|
55
|
+
}
|
|
56
|
+
resolve(_file);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function writeTextToFileSync(_file, _text) {
|
|
61
|
+
try {
|
|
62
|
+
fs.writeFileSync(_file, _text);
|
|
63
|
+
return _file;
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
throw new Error(err + " Could not write to file: " + path.resolve(_file));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function createDirectorySync(directory) {
|
|
70
|
+
try {
|
|
71
|
+
mkdirSyncRecursive(directory);
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function mkdirSyncRecursive(directory) {
|
|
79
|
+
let pathParts = directory.split(path.sep);
|
|
80
|
+
for (var i = 1; i <= pathParts.length; i++) {
|
|
81
|
+
var segment = pathParts.slice(0, i).join(path.sep);
|
|
82
|
+
if (segment.length > 0) {
|
|
83
|
+
!fs.existsSync(segment) ? fs.mkdirSync(segment) : null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function deleteDirectory(dir) {
|
|
88
|
+
return new Promise(function (resolve, reject) {
|
|
89
|
+
fs.access(dir, function (err) {
|
|
90
|
+
if (err) {
|
|
91
|
+
return reject(err);
|
|
92
|
+
}
|
|
93
|
+
fs.readdir(dir, function (err, files) {
|
|
94
|
+
if (err) {
|
|
95
|
+
return reject(err);
|
|
96
|
+
}
|
|
97
|
+
Promise.all(files.map(function (file) {
|
|
98
|
+
return deleteFile(path.join(dir, file));
|
|
99
|
+
})).then(function () {
|
|
100
|
+
fs.rmdir(dir, function (err) {
|
|
101
|
+
if (err) {
|
|
102
|
+
return reject(err);
|
|
103
|
+
}
|
|
104
|
+
resolve();
|
|
105
|
+
});
|
|
106
|
+
}).catch(reject);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
function deleteDirectorySync(dir) {
|
|
112
|
+
fs.accessSync(dir);
|
|
113
|
+
let files = fs.readdirSync(dir);
|
|
114
|
+
files.map(function (file) {
|
|
115
|
+
return deleteFileSync(path.join(dir, file));
|
|
116
|
+
});
|
|
117
|
+
fs.rmdirSync(dir);
|
|
118
|
+
}
|
|
119
|
+
function deleteFile(filePath) {
|
|
120
|
+
return new Promise(function (resolve, reject) {
|
|
121
|
+
fs.lstat(filePath, function (err, stats) {
|
|
122
|
+
if (err) {
|
|
123
|
+
return reject(err);
|
|
124
|
+
}
|
|
125
|
+
if (stats.isDirectory()) {
|
|
126
|
+
resolve(deleteDirectory(filePath));
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
fs.unlink(filePath, function (err) {
|
|
130
|
+
if (err) {
|
|
131
|
+
return reject(err);
|
|
132
|
+
}
|
|
133
|
+
resolve();
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
function deleteFileSync(filePath) {
|
|
140
|
+
let stats = fs.lstatSync(filePath);
|
|
141
|
+
if (stats.isDirectory()) {
|
|
142
|
+
deleteDirectorySync(filePath);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
fs.unlinkSync(filePath);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function renameFile(fileOld, fileNew) {
|
|
149
|
+
return new Promise(function (resolve, reject) {
|
|
150
|
+
fs.rename(fileOld, fileNew, (err) => {
|
|
151
|
+
if (err) {
|
|
152
|
+
reject(err);
|
|
153
|
+
}
|
|
154
|
+
resolve();
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
function renameFileSync(fileOld, fileNew) {
|
|
159
|
+
fs.renameSync(fileOld, fileNew);
|
|
160
|
+
}
|
|
161
|
+
function copyFile(filePath, destPath) {
|
|
162
|
+
return new Promise(function (resolve, reject) {
|
|
163
|
+
fs.copyFile(filePath, destPath, (err) => {
|
|
164
|
+
if (err) {
|
|
165
|
+
reject(err);
|
|
166
|
+
}
|
|
167
|
+
resolve();
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
function copyFileSync(filePath, destPath) {
|
|
172
|
+
fs.copyFileSync(filePath, destPath);
|
|
173
|
+
}
|
|
174
|
+
function copyDirectory(from, to) {
|
|
175
|
+
fs.mkdirSync(to);
|
|
176
|
+
fs.readdirSync(from).forEach(element => {
|
|
177
|
+
if (fs.lstatSync(path.join(from, element)).isFile()) {
|
|
178
|
+
fs.copyFileSync(path.join(from, element), path.join(to, element));
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
copyDirectory(path.join(from, element), path.join(to, element));
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
4
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
5
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
6
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
7
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
8
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
9
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
const logger_1 = require("./logger");
|
|
14
|
+
const fileOperationHelper_1 = require("./fileOperationHelper");
|
|
15
|
+
const pathsConstants_1 = require("./pathsConstants");
|
|
16
|
+
const config = require("./config");
|
|
17
|
+
const nodePath = require("path");
|
|
18
|
+
module.exports = (function () {
|
|
19
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
20
|
+
yield modifyPackageJson();
|
|
21
|
+
yield config.checkConfiguration();
|
|
22
|
+
});
|
|
23
|
+
}());
|
|
24
|
+
function modifyPackageJson() {
|
|
25
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
try {
|
|
27
|
+
let pathToPackageJson = pathsConstants_1.default.getPackageJsonFile();
|
|
28
|
+
let packageJson = yield fileOperationHelper_1.default.readTextFromFile(pathToPackageJson);
|
|
29
|
+
let packageJsonParsed = JSON.parse(packageJson);
|
|
30
|
+
let instrumentDynatraceValue = "node " + nodePath.relative(pathsConstants_1.default.getApplicationPath(), nodePath.join(__dirname, "instrument.js"));
|
|
31
|
+
if (packageJsonParsed.scripts == undefined) {
|
|
32
|
+
packageJsonParsed.scripts = {};
|
|
33
|
+
}
|
|
34
|
+
if (packageJsonParsed.scripts.instrumentDynatrace === instrumentDynatraceValue) {
|
|
35
|
+
logger_1.default.logMessageSync("No need to modify the package.json as it already includes the instrumentDynatrace script!", logger_1.default.INFO);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
packageJsonParsed.scripts.instrumentDynatrace = instrumentDynatraceValue;
|
|
39
|
+
yield fileOperationHelper_1.default.writeTextToFile(pathToPackageJson, JSON.stringify(packageJsonParsed, null, "\t"));
|
|
40
|
+
logger_1.default.logMessageSync("Modified package.json - You are now able to call npm run instrumentDynatrace!", logger_1.default.INFO);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch (e) {
|
|
44
|
+
logger_1.default.logMessageSync("Could not find package.json - please add instrumentDynatrace script manually!", logger_1.default.WARNING);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
package/scripts/ios.js
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const logger_1 = require("./logger");
|
|
5
|
+
const fileOperationHelper_1 = require("./fileOperationHelper");
|
|
6
|
+
const pathsConstants_1 = require("./pathsConstants");
|
|
7
|
+
const plist = require("plist");
|
|
8
|
+
const nodePath = require("path");
|
|
9
|
+
exports.default = {
|
|
10
|
+
modifyPListFile: modifyPListFile,
|
|
11
|
+
findPListFile: findPListFile
|
|
12
|
+
};
|
|
13
|
+
function modifyPListFile(pathToPList, iosConfig, removeOnly) {
|
|
14
|
+
if (pathToPList === undefined) {
|
|
15
|
+
pathToPList = findPListFile();
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
if (!pathToPList.endsWith(".plist")) {
|
|
19
|
+
throw new Error("Can't find .plist file. plist path must also include the plist file!");
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
fileOperationHelper_1.default.checkIfFileExistsSync(pathToPList);
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
throw new Error("Could not read plist file: " + pathToPList);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
let parsedPList = parsePList(pathToPList);
|
|
29
|
+
let configProps = iosConfig === null || iosConfig === void 0 ? void 0 : iosConfig.config;
|
|
30
|
+
if (removeOnly) {
|
|
31
|
+
removePListConfig(pathToPList);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
if (iosConfig && configProps) {
|
|
35
|
+
if (hasDuplicateProperties(configProps)) {
|
|
36
|
+
throw new Error("Duplicate properties found! Please remove duplicates and try again.");
|
|
37
|
+
}
|
|
38
|
+
if (isAutoStartEnabled(configProps)) {
|
|
39
|
+
if (checkForBeaconUrlAndAppId(configProps)) {
|
|
40
|
+
createNewPListIfRequired(parsedPList, configProps, pathToPList);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
throw new Error("The dynatrace.config.js file does not contain DTXBeaconURL or DTXApplicationID properties. If you want to auto-start the iOS agent, please add these two properties at minimum as they are required. If you are using a manual startup of the iOS agent, please add just the DTXAutoStart property (no other properties are needed and none will be considered) with the value set to false.");
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
if (checkForBeaconUrlAndAppId(configProps)) {
|
|
48
|
+
throw new Error("The dynatrace.config.js file contains DTXBeaconURL and or DTXApplicationID properties while DTXAutoStart is set to false. Any properties that you add to the dynatrace.config.js file will not be used if DTXAutoStart is set to false. If you want to manually start the iOS agent, please only add the DTXAutoStart property and set the value to false.");
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
createNewPListIfRequired(parsedPList, configProps, pathToPList);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
throw new Error("Can't write configuration of iOS agent because it is missing!");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function removePListConfig(file) {
|
|
61
|
+
let pListContent = fileOperationHelper_1.default.readTextFromFileSync(file);
|
|
62
|
+
let pListObj = plist.parse(pListContent);
|
|
63
|
+
let pListObjCopy = Object.assign({}, pListObj);
|
|
64
|
+
for (let property in pListObj) {
|
|
65
|
+
if (property.startsWith("DTX")) {
|
|
66
|
+
delete pListObjCopy[property];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
fileOperationHelper_1.default.writeTextToFileSync(file, plist.build(pListObjCopy));
|
|
70
|
+
logger_1.default.logMessageSync("Removed old configuration in plist file: " + file, logger_1.default.INFO);
|
|
71
|
+
}
|
|
72
|
+
function addAgentConfigToPListFile(file, config) {
|
|
73
|
+
let pListContent = fileOperationHelper_1.default.readTextFromFileSync(file);
|
|
74
|
+
let newPListContent = `<plist><dict>${config}</dict></plist>`;
|
|
75
|
+
fileOperationHelper_1.default.writeTextToFileSync(file, plist.build(Object.assign(Object.assign({}, plist.parse(pListContent)), plist.parse(newPListContent))));
|
|
76
|
+
logger_1.default.logMessageSync("Updated configuration in plist file: " + file, logger_1.default.INFO);
|
|
77
|
+
}
|
|
78
|
+
function findPListFile() {
|
|
79
|
+
let appJson = fileOperationHelper_1.default.readTextFromFileSync(pathsConstants_1.default.getAppJsonFile());
|
|
80
|
+
let appJsonObj = JSON.parse(appJson);
|
|
81
|
+
let appName;
|
|
82
|
+
if (appJsonObj.expo !== undefined) {
|
|
83
|
+
appName = appJsonObj.expo.name;
|
|
84
|
+
}
|
|
85
|
+
else if (appJsonObj.name !== undefined) {
|
|
86
|
+
appName = appJsonObj.name;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
throw new Error("Name of the application is unknown. Check your app.json file!");
|
|
90
|
+
}
|
|
91
|
+
let pListPaths = [];
|
|
92
|
+
pListPaths.push(nodePath.join(pathsConstants_1.default.getIOSFolder(), appName, "Info.plist"));
|
|
93
|
+
pListPaths.push(nodePath.join(pathsConstants_1.default.getIOSFolder(), appName, "Supporting", "Info.plist"));
|
|
94
|
+
for (let i = 0; i < pListPaths.length; i++) {
|
|
95
|
+
try {
|
|
96
|
+
fileOperationHelper_1.default.checkIfFileExistsSync(pListPaths[i]);
|
|
97
|
+
return pListPaths[i];
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
throw new Error("Can't find .plist file in iOS Folder! Try to use plist= custom argument. See documentation for help!");
|
|
103
|
+
}
|
|
104
|
+
function parsePList(file) {
|
|
105
|
+
let pListContent = fileOperationHelper_1.default.readTextFromFileSync(file);
|
|
106
|
+
let pListObj = plist.parse(pListContent);
|
|
107
|
+
return pListObj = Object.assign({}, pListObj);
|
|
108
|
+
}
|
|
109
|
+
function isAutoStartEnabled(config) {
|
|
110
|
+
if (config && config.indexOf("<key>DTXAutoStart</key>") === -1) {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
let configObj = "<plist><dict>" + config + "</dict></plist>";
|
|
114
|
+
let configObjCopy = plist.parse(configObj);
|
|
115
|
+
let configKeys = Object.keys(configObjCopy);
|
|
116
|
+
let configValues = Object.values(configObjCopy);
|
|
117
|
+
for (let key in configKeys) {
|
|
118
|
+
if (configKeys[key] === "DTXAutoStart" && configValues[key]) {
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
function checkForBeaconUrlAndAppId(config) {
|
|
125
|
+
return config != null && config.indexOf("DTXApplicationID") >= 0 && config.indexOf("DTXBeaconURL") >= 0;
|
|
126
|
+
}
|
|
127
|
+
function isPropertyCountEqual(parsedPList, config) {
|
|
128
|
+
let configObj = "<plist><dict>" + config + "</dict></plist>";
|
|
129
|
+
let configObjCopy = plist.parse(configObj);
|
|
130
|
+
return Object.keys(parsedPList).filter(pListDtxKeys => pListDtxKeys.startsWith("DTX")).length === Object.keys(configObjCopy).filter(configDtxKeys => configDtxKeys.startsWith("DTX")).length;
|
|
131
|
+
}
|
|
132
|
+
function areConfigsEqual(parsedPList, configObj) {
|
|
133
|
+
let pListKeys = Object.keys(parsedPList);
|
|
134
|
+
for (let property of pListKeys) {
|
|
135
|
+
let plistProperty = parsedPList[property];
|
|
136
|
+
let configProperty = configObj[property];
|
|
137
|
+
let objectProperties = isPropertyAnObject(plistProperty) && isPropertyAnObject(configProperty);
|
|
138
|
+
if (objectProperties && !areConfigsEqual(plistProperty, configProperty) ||
|
|
139
|
+
!objectProperties && plistProperty !== configProperty) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
function comparePListAndConfig(pListObj, config) {
|
|
146
|
+
let configObj = "<plist><dict>" + config + "</dict></plist>";
|
|
147
|
+
let configObjCopy = plist.parse(configObj);
|
|
148
|
+
removeNonDTXProperties(pListObj);
|
|
149
|
+
removeNonDTXProperties(configObjCopy);
|
|
150
|
+
return areConfigsEqual(pListObj, configObjCopy);
|
|
151
|
+
}
|
|
152
|
+
function isPropertyAnObject(propertyObject) {
|
|
153
|
+
return propertyObject != null && typeof propertyObject === 'object';
|
|
154
|
+
}
|
|
155
|
+
function removeNonDTXProperties(propertiesObject) {
|
|
156
|
+
let updatedObject = propertiesObject;
|
|
157
|
+
for (let property in propertiesObject) {
|
|
158
|
+
if (!property.startsWith("DTX")) {
|
|
159
|
+
delete updatedObject[property];
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return updatedObject;
|
|
163
|
+
}
|
|
164
|
+
function hasDuplicateProperties(config) {
|
|
165
|
+
let configArr = config.split("\n");
|
|
166
|
+
let newConfigArr = configArr.filter(configDtxKeys => configDtxKeys.startsWith("<key>DTX"));
|
|
167
|
+
return !newConfigArr.every(property => newConfigArr.indexOf(property) === newConfigArr.lastIndexOf(property));
|
|
168
|
+
}
|
|
169
|
+
function createNewPListIfRequired(parsedPList, configProps, pathToPList) {
|
|
170
|
+
let configIncludingFlavor = configProps + "<key>DTXFlavor</key>\n<string>react_native</string>";
|
|
171
|
+
if (isPropertyCountEqual(parsedPList, configIncludingFlavor) && comparePListAndConfig(parsedPList, configIncludingFlavor)) {
|
|
172
|
+
logger_1.default.logMessageSync("Not generating a new plist as the current plist and dynatrace.config.js iOS properties are identical!", logger_1.default.INFO);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
logger_1.default.logMessageSync("Generating a new plist as the current plist and dynatrace.config.js iOS properties do not match!", logger_1.default.INFO);
|
|
176
|
+
removePListConfig(pathToPList);
|
|
177
|
+
addAgentConfigToPListFile(pathToPList, configIncludingFlavor);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const fileOperationHelper_1 = require("./fileOperationHelper");
|
|
5
|
+
const pathsConstants_1 = require("./pathsConstants");
|
|
6
|
+
const config_1 = require("./config");
|
|
7
|
+
const fs = require("fs");
|
|
8
|
+
const nodePath = require("path");
|
|
9
|
+
const ERROR = 0;
|
|
10
|
+
const INFO = 1;
|
|
11
|
+
const WARNING = 2;
|
|
12
|
+
exports.default = {
|
|
13
|
+
ERROR: ERROR,
|
|
14
|
+
INFO: INFO,
|
|
15
|
+
WARNING: WARNING,
|
|
16
|
+
closeLogFile: closeLogFile,
|
|
17
|
+
logMessageSync: logMessageSync,
|
|
18
|
+
logErrorSync: logErrorSync
|
|
19
|
+
};
|
|
20
|
+
function closeLogFile() {
|
|
21
|
+
if (process.env.SILENT == "true") {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
return fileOperationHelper_1.default.checkIfFileExists(pathsConstants_1.default.getCurrentLogPath())
|
|
25
|
+
.then((_file) => {
|
|
26
|
+
return new Promise(function (resolve, reject) {
|
|
27
|
+
let logFileName = currentDate().split(":").join("-") + ".txt";
|
|
28
|
+
fs.rename(_file, nodePath.join(pathsConstants_1.default.getLogPath(), logFileName), (err) => {
|
|
29
|
+
if (err) {
|
|
30
|
+
reject("Renaming of the log file failed!");
|
|
31
|
+
}
|
|
32
|
+
resolve(nodePath.join(pathsConstants_1.default.getLogPath(), logFileName));
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
})
|
|
36
|
+
.catch(errorHandling);
|
|
37
|
+
}
|
|
38
|
+
function logErrorSync(_message) {
|
|
39
|
+
let config = config_1.readConfig(pathsConstants_1.default.getConfigFilePath());
|
|
40
|
+
if (config.react !== undefined && config.react.debug) {
|
|
41
|
+
logMessageSync(_message, ERROR, true);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function logMessageSync(_message, _logLevel, _onlyConsole = false) {
|
|
45
|
+
if (process.env.SILENT == "true") {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
fs.mkdirSync(pathsConstants_1.default.getLogPath());
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
}
|
|
53
|
+
let logString;
|
|
54
|
+
if (_logLevel == INFO) {
|
|
55
|
+
logString = "#INFO ";
|
|
56
|
+
}
|
|
57
|
+
else if (_logLevel == WARNING) {
|
|
58
|
+
logString = "#WARN ";
|
|
59
|
+
}
|
|
60
|
+
else if (_logLevel == ERROR) {
|
|
61
|
+
logString = "#ERROR ";
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
logString = "#NONE ";
|
|
65
|
+
}
|
|
66
|
+
let outputString = logString + "[" + currentDate() + "]: " + _message;
|
|
67
|
+
console.log(outputString);
|
|
68
|
+
if (!_onlyConsole) {
|
|
69
|
+
fs.appendFileSync(pathsConstants_1.default.getCurrentLogPath(), outputString + "\r\n");
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function errorHandling(_message) {
|
|
73
|
+
console.log(_message);
|
|
74
|
+
}
|
|
75
|
+
function currentDate() {
|
|
76
|
+
let tzoffset = (new Date()).getTimezoneOffset() * 60000;
|
|
77
|
+
let localISOTime = (new Date(Date.now() - tzoffset)).toISOString().slice(0, -5);
|
|
78
|
+
return localISOTime.replace("T", " ");
|
|
79
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const nodePath = require("path");
|
|
5
|
+
const PATH_FILES = "files";
|
|
6
|
+
const PATH_LOGS = "logs";
|
|
7
|
+
var rootPath = __dirname;
|
|
8
|
+
exports.default = {
|
|
9
|
+
setRoot: function (newRoot) {
|
|
10
|
+
rootPath = nodePath.resolve(newRoot);
|
|
11
|
+
},
|
|
12
|
+
getApplicationPath: function () {
|
|
13
|
+
return nodePath.join(getPluginPath(), "..", "..", "..");
|
|
14
|
+
},
|
|
15
|
+
getAppJsonFile: function () {
|
|
16
|
+
return nodePath.join(this.getApplicationPath(), "app.json");
|
|
17
|
+
},
|
|
18
|
+
getPackageJsonFile: function () {
|
|
19
|
+
return nodePath.join(this.getApplicationPath(), "package.json");
|
|
20
|
+
},
|
|
21
|
+
getMetroSouceMapPath: function () {
|
|
22
|
+
return nodePath.join(this.getApplicationPath(), "node_modules", "metro", "src", "DeltaBundler", "Serializers", "helpers");
|
|
23
|
+
},
|
|
24
|
+
getOurSourceMapFile: function () {
|
|
25
|
+
return nodePath.join(getPluginPath(), "lib", "metro", "getSourceMapInfo.js");
|
|
26
|
+
},
|
|
27
|
+
getInternalPackageJsonFile: function () {
|
|
28
|
+
return nodePath.join(getPluginPath(), "package.json");
|
|
29
|
+
},
|
|
30
|
+
getDefaultConfig: function () {
|
|
31
|
+
return nodePath.join(getPluginPath(), PATH_FILES, "default.config.js");
|
|
32
|
+
},
|
|
33
|
+
getBuildPath: function () {
|
|
34
|
+
return nodePath.join(getPluginPath(), "build");
|
|
35
|
+
},
|
|
36
|
+
getConfigFilePath: function () {
|
|
37
|
+
return nodePath.join(this.getApplicationPath(), "dynatrace.config.js");
|
|
38
|
+
},
|
|
39
|
+
getAndroidFolder: function () {
|
|
40
|
+
return nodePath.join(this.getApplicationPath(), "android");
|
|
41
|
+
},
|
|
42
|
+
getAndroidGradleFile: function (androidFolder) {
|
|
43
|
+
return nodePath.join(androidFolder, "build.gradle");
|
|
44
|
+
},
|
|
45
|
+
getIOSFolder: function () {
|
|
46
|
+
return nodePath.join(this.getApplicationPath(), "ios");
|
|
47
|
+
},
|
|
48
|
+
getDynatraceGradleFile: function () {
|
|
49
|
+
return nodePath.join(getPluginPath(), PATH_FILES, "dynatrace.gradle");
|
|
50
|
+
},
|
|
51
|
+
getCurrentLogPath: function () {
|
|
52
|
+
return nodePath.join(getPluginPath(), PATH_LOGS, "currentLog.txt");
|
|
53
|
+
},
|
|
54
|
+
getLogPath: function () {
|
|
55
|
+
return nodePath.join(getPluginPath(), PATH_LOGS);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
function getPluginPath() {
|
|
59
|
+
return nodePath.join(rootPath, "..");
|
|
60
|
+
}
|