@dynatrace/react-native-plugin
Version:
This plugin gives you the ability to use the Dynatrace Mobile agent in your react native application.
124 lines (123 loc) âĸ 6.58 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.LineOffsetAnalyzer = void 0;
const fs = require("fs/promises");
const path_1 = require("path");
const diff_1 = require("diff");
const Logger_1 = require("../Logger");
const InstrumentUtil_1 = require("../util/InstrumentUtil");
const FileOperationHelper_1 = require("../../scripts/FileOperationHelper");
class LineOffsetAnalyzer {
constructor(rootPath, instrumentedPath, appBundleInfo) {
this.rootDir = (0, path_1.resolve)(rootPath);
this.instrumentedDir = (0, path_1.resolve)(instrumentedPath);
this.outputFile = (0, path_1.resolve)(this.instrumentedDir, 'line-offsets.json');
this.logFile = (0, path_1.resolve)(this.instrumentedDir, 'debug.log');
this.appBundleInfo = appBundleInfo;
}
run() {
return __awaiter(this, void 0, void 0, function* () {
try {
yield fs.writeFile(this.logFile, '');
const buildExists = yield FileOperationHelper_1.default.checkIfFileExists(this.instrumentedDir);
if (!buildExists) {
yield this.log(`â Build directory not found at: ${this.instrumentedDir}`);
yield this.log('đ ī¸ Please run the instrumentation step first!');
console.error('đĢ Build directory missing. Make and instrument the project first.');
process.exit(1);
}
const instrumentedFiles = (yield FileOperationHelper_1.default.getAllFiles(this.log, this.instrumentedDir))
.filter((filePath) => filePath.endsWith(InstrumentUtil_1.INSTRUMENTED_FILE_EXTENSION));
const mappings = {};
yield this.log(`đ Found ${instrumentedFiles.length} instrumented files`);
for (const instrRelPath of instrumentedFiles) {
const baseRelPath = instrRelPath.slice(0, -InstrumentUtil_1.INSTRUMENTED_FILE_EXTENSION.length);
const origPath = (0, path_1.join)(this.rootDir, baseRelPath);
const instrPath = (0, path_1.join)(this.instrumentedDir, instrRelPath);
const origExists = yield FileOperationHelper_1.default.checkIfFileExists(origPath);
if (!origExists) {
yield this.log(`â ī¸ Original file not found for: ${baseRelPath}`);
continue;
}
yield this.log(`đ Comparing: ${baseRelPath}`);
const [originalContent, instrumentedContent] = yield Promise.all([
FileOperationHelper_1.default.readTextFromFile(origPath),
FileOperationHelper_1.default.readTextFromFile(instrPath),
]);
const offsets = this.computeLineOffsets(originalContent, instrumentedContent);
if (offsets.length > 0) {
mappings[baseRelPath] = offsets;
yield this.log(`â
Offsets found for ${baseRelPath}: ${offsets.length} entries`);
}
else {
yield this.log(`âšī¸ No offsets needed for ${baseRelPath}`);
}
}
const finalOutput = {
generationTime: new Date().toISOString(),
appVersion: this.appBundleInfo ? this.appBundleInfo.version : 'application version not defined',
pluginVersion: this.appBundleInfo ? this.appBundleInfo.pluginVersion : 'plugin version not defined',
mappings: {
[this.appBundleInfo ? this.appBundleInfo.name : 'app name not defined']: mappings,
},
};
yield fs.writeFile(this.outputFile, JSON.stringify(finalOutput, null, 2));
yield this.log(`â
Line offsets written to ${this.outputFile}`);
}
catch (err) {
console.error('â Unexpected error:', err);
}
});
}
log(msg) {
return __awaiter(this, void 0, void 0, function* () {
Logger_1.default.logMessageSync(msg, Logger_1.default.INFO);
yield fs.appendFile(this.logFile, msg + '\n');
});
}
computeLineOffsets(originalContent, instrumentedContent) {
const diffs = (0, diff_1.diffLines)(originalContent, instrumentedContent);
let origLine = 0;
let instrLine = 0;
let offset = 0;
let lastRecordedOffset = null;
const offsets = [];
this.log('đ Diff result:');
for (const part of diffs) {
const lines = part.value.split('\n').slice(0, -1);
if (part.added) {
this.log(`â Added ${lines.length} lines at instrumented line ${instrLine + 1}`);
lines.forEach((line, i) => this.log(` + ${instrLine + 1 + i}: ${line}`));
instrLine += lines.length;
offset -= lines.length;
}
else if (part.removed) {
this.log(`â Removed ${lines.length} lines at original line ${origLine + 1}`);
lines.forEach((line, i) => this.log(` - ${origLine + 1 + i}: ${line}`));
origLine += lines.length;
offset += lines.length;
}
else {
for (let i = 0; i < lines.length; i++) {
instrLine++;
origLine++;
if (offset !== 0 && offset !== lastRecordedOffset) {
offsets.push({ [instrLine]: offset });
lastRecordedOffset = offset;
}
}
}
}
return offsets;
}
}
exports.LineOffsetAnalyzer = LineOffsetAnalyzer;