@sentry/wizard 3.24.0 → 3.25.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/CHANGELOG.md +8 -0
- package/dist/package.json +1 -1
- package/dist/src/nextjs/templates.js +1 -1
- package/dist/src/nextjs/templates.js.map +1 -1
- package/dist/src/react-native/expo-env-file.d.ts +2 -0
- package/dist/src/react-native/expo-env-file.js +127 -0
- package/dist/src/react-native/expo-env-file.js.map +1 -0
- package/dist/src/react-native/expo-metro.d.ts +7 -0
- package/dist/src/react-native/expo-metro.js +236 -0
- package/dist/src/react-native/expo-metro.js.map +1 -0
- package/dist/src/react-native/expo.d.ts +16 -0
- package/dist/src/react-native/expo.js +195 -0
- package/dist/src/react-native/expo.js.map +1 -0
- package/dist/src/react-native/git.d.ts +1 -0
- package/dist/src/react-native/git.js +85 -0
- package/dist/src/react-native/git.js.map +1 -0
- package/dist/src/react-native/javascript.d.ts +3 -0
- package/dist/src/react-native/javascript.js +119 -1
- package/dist/src/react-native/javascript.js.map +1 -1
- package/dist/src/react-native/metro.d.ts +3 -0
- package/dist/src/react-native/metro.js +17 -15
- package/dist/src/react-native/metro.js.map +1 -1
- package/dist/src/react-native/react-native-wizard.d.ts +12 -0
- package/dist/src/react-native/react-native-wizard.js +91 -78
- package/dist/src/react-native/react-native-wizard.js.map +1 -1
- package/dist/src/react-native/xcode.js +14 -3
- package/dist/src/react-native/xcode.js.map +1 -1
- package/dist/src/sourcemaps/sourcemaps-wizard.js +1 -1
- package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
- package/dist/src/utils/clack-utils.d.ts +2 -1
- package/dist/src/utils/clack-utils.js +2 -2
- package/dist/src/utils/clack-utils.js.map +1 -1
- package/dist/test/nextjs/templates.test.js +1 -1
- package/dist/test/nextjs/templates.test.js.map +1 -1
- package/dist/test/react-native/expo-metro.test.d.ts +1 -0
- package/dist/test/react-native/expo-metro.test.js +26 -0
- package/dist/test/react-native/expo-metro.test.js.map +1 -0
- package/dist/test/react-native/expo.test.d.ts +1 -0
- package/dist/test/react-native/expo.test.js +57 -0
- package/dist/test/react-native/expo.test.js.map +1 -0
- package/dist/test/react-native/xcode.test.js +5 -0
- package/dist/test/react-native/xcode.test.js.map +1 -1
- package/package.json +1 -1
- package/src/nextjs/templates.ts +1 -1
- package/src/react-native/expo-env-file.ts +55 -0
- package/src/react-native/expo-metro.ts +212 -0
- package/src/react-native/expo.ts +175 -0
- package/src/react-native/git.ts +25 -0
- package/src/react-native/javascript.ts +68 -1
- package/src/react-native/metro.ts +3 -3
- package/src/react-native/react-native-wizard.ts +72 -76
- package/src/react-native/xcode.ts +21 -5
- package/src/sourcemaps/sourcemaps-wizard.ts +1 -1
- package/src/utils/clack-utils.ts +4 -4
- package/test/nextjs/templates.test.ts +1 -1
- package/test/react-native/expo-metro.test.ts +81 -0
- package/test/react-native/expo.test.ts +86 -0
- package/test/react-native/xcode.test.ts +90 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
35
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
36
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
37
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
38
|
+
function step(op) {
|
|
39
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
40
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
41
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
42
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
43
|
+
switch (op[0]) {
|
|
44
|
+
case 0: case 1: t = op; break;
|
|
45
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
46
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
47
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
48
|
+
default:
|
|
49
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
50
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
51
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
52
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
53
|
+
if (t[2]) _.ops.pop();
|
|
54
|
+
_.trys.pop(); continue;
|
|
55
|
+
}
|
|
56
|
+
op = body.call(thisArg, _);
|
|
57
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
58
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
62
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
63
|
+
};
|
|
64
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
65
|
+
exports.getSentryAppConfigJsonCodeSnippet = exports.addWithSentryToAppConfigJson = exports.patchExpoAppConfig = exports.printSentryExpoMigrationOutro = exports.SENTRY_PLUGIN_FUNCTION_NAME = exports.DEPRECATED_SENTRY_EXPO_PLUGIN_NAME = exports.SENTRY_EXPO_PLUGIN_NAME = void 0;
|
|
66
|
+
// @ts-ignore - clack is ESM and TS complains about that. It works though
|
|
67
|
+
var clack = __importStar(require("@clack/prompts"));
|
|
68
|
+
var chalk_1 = __importDefault(require("chalk"));
|
|
69
|
+
var fs = __importStar(require("fs"));
|
|
70
|
+
var os_1 = require("os");
|
|
71
|
+
var utils_1 = require("@sentry/utils");
|
|
72
|
+
var Sentry = __importStar(require("@sentry/node"));
|
|
73
|
+
var clack_utils_1 = require("../utils/clack-utils");
|
|
74
|
+
var telemetry_1 = require("../telemetry");
|
|
75
|
+
exports.SENTRY_EXPO_PLUGIN_NAME = '@sentry/react-native/expo';
|
|
76
|
+
exports.DEPRECATED_SENTRY_EXPO_PLUGIN_NAME = 'sentry-expo';
|
|
77
|
+
exports.SENTRY_PLUGIN_FUNCTION_NAME = 'withSentry';
|
|
78
|
+
var APP_CONFIG_JSON = "app.json";
|
|
79
|
+
function printSentryExpoMigrationOutro() {
|
|
80
|
+
clack.outro("Deprecated ".concat(chalk_1.default.cyan('sentry-expo'), " package installed in your dependencies. Please follow the migration guide at ").concat(chalk_1.default.cyan('https://docs.sentry.io/platforms/react-native/migration/sentry-expo/')));
|
|
81
|
+
}
|
|
82
|
+
exports.printSentryExpoMigrationOutro = printSentryExpoMigrationOutro;
|
|
83
|
+
/**
|
|
84
|
+
* Finds app.json in the project root and add Sentry Expo `withSentry` plugin.
|
|
85
|
+
*/
|
|
86
|
+
function patchExpoAppConfig(options) {
|
|
87
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
88
|
+
function showInstructions() {
|
|
89
|
+
return (0, clack_utils_1.showCopyPasteInstructions)(APP_CONFIG_JSON, getSentryAppConfigJsonCodeSnippet(options), 'This ensures auto upload of source maps during native app build.');
|
|
90
|
+
}
|
|
91
|
+
var appConfigJsonExists, patched;
|
|
92
|
+
return __generator(this, function (_a) {
|
|
93
|
+
switch (_a.label) {
|
|
94
|
+
case 0:
|
|
95
|
+
appConfigJsonExists = fs.existsSync(APP_CONFIG_JSON);
|
|
96
|
+
Sentry.setTag('app-config-file-status', appConfigJsonExists ? 'found' : 'not-found');
|
|
97
|
+
if (!!appConfigJsonExists) return [3 /*break*/, 2];
|
|
98
|
+
return [4 /*yield*/, showInstructions()];
|
|
99
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
100
|
+
case 2: return [4 /*yield*/, patchAppConfigJson(APP_CONFIG_JSON, options)];
|
|
101
|
+
case 3:
|
|
102
|
+
patched = _a.sent();
|
|
103
|
+
if (!!patched) return [3 /*break*/, 5];
|
|
104
|
+
return [4 /*yield*/, showInstructions()];
|
|
105
|
+
case 4: return [2 /*return*/, _a.sent()];
|
|
106
|
+
case 5: return [2 /*return*/];
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
exports.patchExpoAppConfig = patchExpoAppConfig;
|
|
112
|
+
function patchAppConfigJson(path, options) {
|
|
113
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
114
|
+
var appConfigContent, patchedContent, error_1;
|
|
115
|
+
return __generator(this, function (_a) {
|
|
116
|
+
switch (_a.label) {
|
|
117
|
+
case 0: return [4 /*yield*/, fs.promises.readFile(path, { encoding: 'utf-8' })];
|
|
118
|
+
case 1:
|
|
119
|
+
appConfigContent = (_a.sent()).toString();
|
|
120
|
+
patchedContent = (0, telemetry_1.traceStep)('app-config-json-patch', function () {
|
|
121
|
+
return addWithSentryToAppConfigJson(appConfigContent, options);
|
|
122
|
+
});
|
|
123
|
+
if (patchedContent === null) {
|
|
124
|
+
return [2 /*return*/, false];
|
|
125
|
+
}
|
|
126
|
+
_a.label = 2;
|
|
127
|
+
case 2:
|
|
128
|
+
_a.trys.push([2, 4, , 5]);
|
|
129
|
+
return [4 /*yield*/, fs.promises.writeFile(path, patchedContent)];
|
|
130
|
+
case 3:
|
|
131
|
+
_a.sent();
|
|
132
|
+
return [3 /*break*/, 5];
|
|
133
|
+
case 4:
|
|
134
|
+
error_1 = _a.sent();
|
|
135
|
+
Sentry.setTag('app-config-file-status', 'json-write-error');
|
|
136
|
+
clack.log.error("Unable to write ".concat(chalk_1.default.cyan('app.config.json'), "."));
|
|
137
|
+
return [2 /*return*/, false];
|
|
138
|
+
case 5:
|
|
139
|
+
Sentry.setTag('app-config-file-status', 'json-write-success');
|
|
140
|
+
clack.log.success("Added Sentry Expo plugin to ".concat(chalk_1.default.cyan('app.config.json'), "."));
|
|
141
|
+
return [2 /*return*/, true];
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
function addWithSentryToAppConfigJson(appConfigContent, options) {
|
|
147
|
+
var _a, _b;
|
|
148
|
+
try {
|
|
149
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
150
|
+
var parsedAppConfig = JSON.parse(appConfigContent);
|
|
151
|
+
var includesWithSentry = appConfigContent.includes(exports.SENTRY_EXPO_PLUGIN_NAME) ||
|
|
152
|
+
appConfigContent.includes(exports.DEPRECATED_SENTRY_EXPO_PLUGIN_NAME);
|
|
153
|
+
if (includesWithSentry) {
|
|
154
|
+
Sentry.setTag('app-config-file-status', 'already-patched');
|
|
155
|
+
clack.log.warn("Your ".concat(chalk_1.default.cyan('app.config.json'), " already includes the Sentry Expo plugin."));
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
if (parsedAppConfig.expo !== undefined &&
|
|
159
|
+
!(0, utils_1.isPlainObject)(parsedAppConfig.expo)) {
|
|
160
|
+
Sentry.setTag('app-config-file-status', 'invalid-json');
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
if (parsedAppConfig.expo &&
|
|
164
|
+
parsedAppConfig.expo.plugins !== undefined &&
|
|
165
|
+
!Array.isArray(parsedAppConfig.expo.plugins)) {
|
|
166
|
+
Sentry.setTag('app-config-file-status', 'invalid-json');
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
parsedAppConfig.expo = (_a = parsedAppConfig.expo) !== null && _a !== void 0 ? _a : {};
|
|
170
|
+
parsedAppConfig.expo.plugins = (_b = parsedAppConfig.expo.plugins) !== null && _b !== void 0 ? _b : [];
|
|
171
|
+
parsedAppConfig.expo.plugins.push([
|
|
172
|
+
exports.SENTRY_EXPO_PLUGIN_NAME,
|
|
173
|
+
{
|
|
174
|
+
url: options.url,
|
|
175
|
+
project: options.project,
|
|
176
|
+
organization: options.org,
|
|
177
|
+
},
|
|
178
|
+
]);
|
|
179
|
+
return JSON.stringify(parsedAppConfig, null, 2) + os_1.EOL;
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
Sentry.setTag('app-config-file-status', 'invalid-json');
|
|
183
|
+
clack.log.error("Unable to parse your ".concat(chalk_1.default.cyan('app.config.json'), ". Make sure it has a valid format!"));
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
exports.addWithSentryToAppConfigJson = addWithSentryToAppConfigJson;
|
|
188
|
+
function getSentryAppConfigJsonCodeSnippet(_a) {
|
|
189
|
+
var url = _a.url, project = _a.project, org = _a.org;
|
|
190
|
+
return (0, clack_utils_1.makeCodeSnippet)(true, function (unchanged, plus, _minus) {
|
|
191
|
+
return unchanged("{\n \"name\": \"my app\",\n \"plugins\": [\n ".concat(plus("[\n \"@sentry/react-native/expo\",\n {\n \"url\": \"".concat(url, "\",\n \"project\": \"").concat(project, "\",\n \"organization\": \"").concat(org, "\"\n }\n ]")), "\n ],\n}"));
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
exports.getSentryAppConfigJsonCodeSnippet = getSentryAppConfigJsonCodeSnippet;
|
|
195
|
+
//# sourceMappingURL=expo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expo.js","sourceRoot":"","sources":["../../../src/react-native/expo.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-ignore - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\nimport chalk from 'chalk';\nimport * as fs from 'fs';\nimport { EOL } from 'os';\n\nimport { isPlainObject } from '@sentry/utils';\nimport * as Sentry from '@sentry/node';\nimport {\n makeCodeSnippet,\n showCopyPasteInstructions,\n} from '../utils/clack-utils';\nimport { RNCliSetupConfigContent } from './react-native-wizard';\nimport { traceStep } from '../telemetry';\n\nexport const SENTRY_EXPO_PLUGIN_NAME = '@sentry/react-native/expo';\nexport const DEPRECATED_SENTRY_EXPO_PLUGIN_NAME = 'sentry-expo';\n\nexport const SENTRY_PLUGIN_FUNCTION_NAME = 'withSentry';\n\nconst APP_CONFIG_JSON = `app.json`;\n\nexport interface AppConfigJson {\n expo?: {\n plugins?: Array<[string, undefined | Record<string, unknown>]>;\n };\n}\n\nexport function printSentryExpoMigrationOutro(): void {\n clack.outro(\n `Deprecated ${chalk.cyan(\n 'sentry-expo',\n )} package installed in your dependencies. Please follow the migration guide at ${chalk.cyan(\n 'https://docs.sentry.io/platforms/react-native/migration/sentry-expo/',\n )}`,\n );\n}\n\n/**\n * Finds app.json in the project root and add Sentry Expo `withSentry` plugin.\n */\nexport async function patchExpoAppConfig(options: RNCliSetupConfigContent) {\n function showInstructions() {\n return showCopyPasteInstructions(\n APP_CONFIG_JSON,\n getSentryAppConfigJsonCodeSnippet(options),\n 'This ensures auto upload of source maps during native app build.',\n );\n }\n\n const appConfigJsonExists = fs.existsSync(APP_CONFIG_JSON);\n\n Sentry.setTag(\n 'app-config-file-status',\n appConfigJsonExists ? 'found' : 'not-found',\n );\n if (!appConfigJsonExists) {\n return await showInstructions();\n }\n\n const patched = await patchAppConfigJson(APP_CONFIG_JSON, options);\n if (!patched) {\n return await showInstructions();\n }\n}\n\nasync function patchAppConfigJson(\n path: string,\n options: RNCliSetupConfigContent,\n): Promise<boolean> {\n const appConfigContent = (\n await fs.promises.readFile(path, { encoding: 'utf-8' })\n ).toString();\n const patchedContent = traceStep('app-config-json-patch', () =>\n addWithSentryToAppConfigJson(appConfigContent, options),\n );\n if (patchedContent === null) {\n return false;\n }\n\n try {\n await fs.promises.writeFile(path, patchedContent);\n } catch (error) {\n Sentry.setTag('app-config-file-status', 'json-write-error');\n clack.log.error(`Unable to write ${chalk.cyan('app.config.json')}.`);\n return false;\n }\n Sentry.setTag('app-config-file-status', 'json-write-success');\n clack.log.success(\n `Added Sentry Expo plugin to ${chalk.cyan('app.config.json')}.`,\n );\n return true;\n}\n\nexport function addWithSentryToAppConfigJson(\n appConfigContent: string,\n options: RNCliSetupConfigContent,\n): string | null {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const parsedAppConfig: AppConfigJson = JSON.parse(appConfigContent);\n const includesWithSentry =\n appConfigContent.includes(SENTRY_EXPO_PLUGIN_NAME) ||\n appConfigContent.includes(DEPRECATED_SENTRY_EXPO_PLUGIN_NAME);\n\n if (includesWithSentry) {\n Sentry.setTag('app-config-file-status', 'already-patched');\n clack.log.warn(\n `Your ${chalk.cyan(\n 'app.config.json',\n )} already includes the Sentry Expo plugin.`,\n );\n return null;\n }\n\n if (\n parsedAppConfig.expo !== undefined &&\n !isPlainObject(parsedAppConfig.expo)\n ) {\n Sentry.setTag('app-config-file-status', 'invalid-json');\n return null;\n }\n if (\n parsedAppConfig.expo &&\n parsedAppConfig.expo.plugins !== undefined &&\n !Array.isArray(parsedAppConfig.expo.plugins)\n ) {\n Sentry.setTag('app-config-file-status', 'invalid-json');\n return null;\n }\n\n parsedAppConfig.expo = parsedAppConfig.expo ?? {};\n parsedAppConfig.expo.plugins = parsedAppConfig.expo.plugins ?? [];\n parsedAppConfig.expo.plugins.push([\n SENTRY_EXPO_PLUGIN_NAME,\n {\n url: options.url,\n project: options.project,\n organization: options.org,\n },\n ]);\n\n return JSON.stringify(parsedAppConfig, null, 2) + EOL;\n } catch (error) {\n Sentry.setTag('app-config-file-status', 'invalid-json');\n clack.log.error(\n `Unable to parse your ${chalk.cyan(\n 'app.config.json',\n )}. Make sure it has a valid format!`,\n );\n return null;\n }\n}\n\nexport function getSentryAppConfigJsonCodeSnippet({\n url,\n project,\n org,\n}: Omit<RNCliSetupConfigContent, 'authToken'>) {\n return makeCodeSnippet(true, (unchanged, plus, _minus) => {\n return unchanged(`{\n \"name\": \"my app\",\n \"plugins\": [\n ${plus(`[\n \"@sentry/react-native/expo\",\n {\n \"url\": \"${url}\",\n \"project\": \"${project}\",\n \"organization\": \"${org}\"\n }\n ]`)}\n ],\n}`);\n });\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function addToGitignore(filepath: string): Promise<boolean>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
35
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
36
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
37
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
38
|
+
function step(op) {
|
|
39
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
40
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
41
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
42
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
43
|
+
switch (op[0]) {
|
|
44
|
+
case 0: case 1: t = op; break;
|
|
45
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
46
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
47
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
48
|
+
default:
|
|
49
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
50
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
51
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
52
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
53
|
+
if (t[2]) _.ops.pop();
|
|
54
|
+
_.trys.pop(); continue;
|
|
55
|
+
}
|
|
56
|
+
op = body.call(thisArg, _);
|
|
57
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
58
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
62
|
+
exports.addToGitignore = void 0;
|
|
63
|
+
var fs = __importStar(require("fs"));
|
|
64
|
+
var GITIGNORE_FILENAME = '.gitignore';
|
|
65
|
+
function addToGitignore(filepath) {
|
|
66
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
67
|
+
var _a;
|
|
68
|
+
return __generator(this, function (_b) {
|
|
69
|
+
switch (_b.label) {
|
|
70
|
+
case 0:
|
|
71
|
+
_b.trys.push([0, 2, , 3]);
|
|
72
|
+
return [4 /*yield*/, fs.promises.appendFile(GITIGNORE_FILENAME, "\n".concat(filepath, "\n"))];
|
|
73
|
+
case 1:
|
|
74
|
+
_b.sent();
|
|
75
|
+
return [2 /*return*/, true];
|
|
76
|
+
case 2:
|
|
77
|
+
_a = _b.sent();
|
|
78
|
+
return [2 /*return*/, false];
|
|
79
|
+
case 3: return [2 /*return*/];
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
exports.addToGitignore = addToGitignore;
|
|
85
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../../src/react-native/git.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qCAAyB;AAEzB,IAAM,kBAAkB,GAAG,YAAY,CAAC;AAExC,SAAsB,cAAc,CAAC,QAAgB;;;;;;;oBAejD,qBAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,kBAAkB,EAAE,YAAK,QAAQ,OAAI,CAAC,EAAA;;oBAAnE,SAAmE,CAAC;oBACpE,sBAAO,IAAI,EAAC;;;oBAEZ,sBAAO,KAAK,EAAC;;;;;CAEhB;AApBD,wCAoBC","sourcesContent":["import * as fs from 'fs';\n\nconst GITIGNORE_FILENAME = '.gitignore';\n\nexport async function addToGitignore(filepath: string): Promise<boolean> {\n /**\n * Don't check whether the given file is ignored because:\n * 1. It's tricky to check it without git.\n * 2. Git might not be installed or accessible.\n * 3. It's convenient to use a module to interact with git, but it would\n * increase the size x2 approximately. Docs say to run the Wizard without\n * installing it, and duplicating the size would slow the set-up down.\n * 4. The Wizard is meant to be run once.\n * 5. A message is logged informing users it's been added to the gitignore.\n * 6. It will be added to the gitignore as many times as it runs - not a big\n * deal.\n * 7. It's straightforward to remove it from the gitignore.\n */\n try {\n await fs.promises.appendFile(GITIGNORE_FILENAME, `\\n${filepath}\\n`);\n return true;\n } catch {\n return false;\n }\n}\n"]}
|
|
@@ -1,7 +1,125 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
35
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
36
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
37
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
38
|
+
function step(op) {
|
|
39
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
40
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
41
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
42
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
43
|
+
switch (op[0]) {
|
|
44
|
+
case 0: case 1: t = op; break;
|
|
45
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
46
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
47
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
48
|
+
default:
|
|
49
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
50
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
51
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
52
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
53
|
+
if (t[2]) _.ops.pop();
|
|
54
|
+
_.trys.pop(); continue;
|
|
55
|
+
}
|
|
56
|
+
op = body.call(thisArg, _);
|
|
57
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
58
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
62
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
63
|
+
};
|
|
2
64
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getSentryInitPlainTextSnippet = exports.getSentryInitColoredCodeSnippet = exports.doesJsCodeIncludeSdkSentryImport = exports.addSentryInitWithSdkImport = void 0;
|
|
65
|
+
exports.getSentryInitPlainTextSnippet = exports.getSentryInitColoredCodeSnippet = exports.doesJsCodeIncludeSdkSentryImport = exports.addSentryInitWithSdkImport = exports.addSentryInit = void 0;
|
|
66
|
+
/* eslint-disable max-lines */
|
|
67
|
+
// @ts-ignore - clack is ESM and TS complains about that. It works though
|
|
68
|
+
var prompts_1 = __importDefault(require("@clack/prompts"));
|
|
69
|
+
var chalk_1 = __importDefault(require("chalk"));
|
|
70
|
+
var path = __importStar(require("path"));
|
|
71
|
+
var process = __importStar(require("process"));
|
|
72
|
+
var fs = __importStar(require("fs"));
|
|
73
|
+
var Sentry = __importStar(require("@sentry/node"));
|
|
74
|
+
var telemetry_1 = require("../telemetry");
|
|
4
75
|
var clack_utils_1 = require("../utils/clack-utils");
|
|
76
|
+
var glob_1 = require("./glob");
|
|
77
|
+
var react_native_wizard_1 = require("./react-native-wizard");
|
|
78
|
+
function addSentryInit(_a) {
|
|
79
|
+
var dsn = _a.dsn;
|
|
80
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
81
|
+
var prefixGlob, suffixGlob, universalGlob, jsFileGlob, jsPath, jsRelativePath, js, includesSentry;
|
|
82
|
+
return __generator(this, function (_b) {
|
|
83
|
+
switch (_b.label) {
|
|
84
|
+
case 0:
|
|
85
|
+
prefixGlob = '{.,./src,./app}';
|
|
86
|
+
suffixGlob = '@(j|t|cj|mj)s?(x)';
|
|
87
|
+
universalGlob = "@(App|_layout).".concat(suffixGlob);
|
|
88
|
+
jsFileGlob = "".concat(prefixGlob, "/+(").concat(universalGlob, ")");
|
|
89
|
+
jsPath = (0, telemetry_1.traceStep)('find-app-js-file', function () {
|
|
90
|
+
return (0, glob_1.getFirstMatchedPath)(jsFileGlob);
|
|
91
|
+
});
|
|
92
|
+
Sentry.setTag('app-js-file-status', jsPath ? 'found' : 'not-found');
|
|
93
|
+
if (!!jsPath) return [3 /*break*/, 2];
|
|
94
|
+
prompts_1.default.log.warn("Could not find main App file. Place the following code snippet close to the Apps Root component.");
|
|
95
|
+
return [4 /*yield*/, (0, clack_utils_1.showCopyPasteInstructions)('App.js or _layout.tsx', getSentryInitColoredCodeSnippet(dsn), 'This ensures the Sentry SDK is ready to capture errors.')];
|
|
96
|
+
case 1:
|
|
97
|
+
_b.sent();
|
|
98
|
+
return [2 /*return*/];
|
|
99
|
+
case 2:
|
|
100
|
+
jsRelativePath = path.relative(process.cwd(), jsPath);
|
|
101
|
+
js = fs.readFileSync(jsPath, 'utf-8');
|
|
102
|
+
includesSentry = doesJsCodeIncludeSdkSentryImport(js, {
|
|
103
|
+
sdkPackageName: react_native_wizard_1.RN_SDK_PACKAGE,
|
|
104
|
+
});
|
|
105
|
+
if (includesSentry) {
|
|
106
|
+
Sentry.setTag('app-js-file-status', 'already-includes-sentry');
|
|
107
|
+
prompts_1.default.log.warn("".concat(chalk_1.default.cyan(jsRelativePath), " already includes Sentry. We wont't add it again."));
|
|
108
|
+
return [2 /*return*/];
|
|
109
|
+
}
|
|
110
|
+
(0, telemetry_1.traceStep)('add-sentry-init', function () {
|
|
111
|
+
var newContent = addSentryInitWithSdkImport(js, { dsn: dsn });
|
|
112
|
+
prompts_1.default.log.success("Added ".concat(chalk_1.default.cyan('Sentry.init'), " to ").concat(chalk_1.default.cyan(jsRelativePath), "."));
|
|
113
|
+
fs.writeFileSync(jsPath, newContent, 'utf-8');
|
|
114
|
+
});
|
|
115
|
+
Sentry.setTag('app-js-file-status', 'added-sentry-init');
|
|
116
|
+
prompts_1.default.log.success(chalk_1.default.green("".concat(chalk_1.default.cyan(jsRelativePath), " changes saved.")));
|
|
117
|
+
return [2 /*return*/];
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
exports.addSentryInit = addSentryInit;
|
|
5
123
|
function addSentryInitWithSdkImport(js, _a) {
|
|
6
124
|
var dsn = _a.dsn;
|
|
7
125
|
return js.replace(/^([^]*)(import\s+[^;]*?;$)/m, function (match) { return "".concat(match, "\n").concat(getSentryInitPlainTextSnippet(dsn)); });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"javascript.js","sourceRoot":"","sources":["../../../src/react-native/javascript.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"javascript.js","sourceRoot":"","sources":["../../../src/react-native/javascript.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable max-lines */\n// @ts-ignore - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\nimport chalk from 'chalk';\nimport * as path from 'path';\nimport * as process from 'process';\nimport * as fs from 'fs';\nimport * as Sentry from '@sentry/node';\n\nimport { traceStep } from '../telemetry';\nimport {\n makeCodeSnippet,\n showCopyPasteInstructions,\n} from '../utils/clack-utils';\nimport { getFirstMatchedPath } from './glob';\nimport { RN_SDK_PACKAGE } from './react-native-wizard';\n\nexport async function addSentryInit({ dsn }: { dsn: string }) {\n const prefixGlob = '{.,./src,./app}';\n const suffixGlob = '@(j|t|cj|mj)s?(x)';\n const universalGlob = `@(App|_layout).${suffixGlob}`;\n const jsFileGlob = `${prefixGlob}/+(${universalGlob})`;\n const jsPath = traceStep('find-app-js-file', () =>\n getFirstMatchedPath(jsFileGlob),\n );\n Sentry.setTag('app-js-file-status', jsPath ? 'found' : 'not-found');\n if (!jsPath) {\n clack.log.warn(\n `Could not find main App file. Place the following code snippet close to the Apps Root component.`,\n );\n await showCopyPasteInstructions(\n 'App.js or _layout.tsx',\n getSentryInitColoredCodeSnippet(dsn),\n 'This ensures the Sentry SDK is ready to capture errors.',\n );\n return;\n }\n const jsRelativePath = path.relative(process.cwd(), jsPath);\n\n const js = fs.readFileSync(jsPath, 'utf-8');\n const includesSentry = doesJsCodeIncludeSdkSentryImport(js, {\n sdkPackageName: RN_SDK_PACKAGE,\n });\n if (includesSentry) {\n Sentry.setTag('app-js-file-status', 'already-includes-sentry');\n clack.log.warn(\n `${chalk.cyan(\n jsRelativePath,\n )} already includes Sentry. We wont't add it again.`,\n );\n return;\n }\n\n traceStep('add-sentry-init', () => {\n const newContent = addSentryInitWithSdkImport(js, { dsn });\n\n clack.log.success(\n `Added ${chalk.cyan('Sentry.init')} to ${chalk.cyan(jsRelativePath)}.`,\n );\n\n fs.writeFileSync(jsPath, newContent, 'utf-8');\n });\n\n Sentry.setTag('app-js-file-status', 'added-sentry-init');\n clack.log.success(\n chalk.green(`${chalk.cyan(jsRelativePath)} changes saved.`),\n );\n}\n\nexport function addSentryInitWithSdkImport(\n js: string,\n { dsn }: { dsn: string },\n): string {\n return js.replace(\n /^([^]*)(import\\s+[^;]*?;$)/m,\n (match: string) => `${match}\n${getSentryInitPlainTextSnippet(dsn)}`,\n );\n}\n\nexport function doesJsCodeIncludeSdkSentryImport(\n js: string,\n { sdkPackageName }: { sdkPackageName: string },\n): boolean {\n return !!js.match(sdkPackageName);\n}\n\nexport function getSentryInitColoredCodeSnippet(dsn: string) {\n return makeCodeSnippet(true, (_unchanged, plus, _minus) => {\n return plus(getSentryInitPlainTextSnippet(dsn));\n });\n}\n\nexport function getSentryInitPlainTextSnippet(dsn: string) {\n return `import * as Sentry from '@sentry/react-native';\n\nSentry.init({\n dsn: '${dsn}',\n\n // uncomment the line below to enable Spotlight (https://spotlightjs.com)\n // enableSpotlight: __DEV__,\n});`;\n}\n"]}
|
|
@@ -2,12 +2,15 @@ import { ProxifiedModule } from 'magicast';
|
|
|
2
2
|
import * as recast from 'recast';
|
|
3
3
|
import x = recast.types;
|
|
4
4
|
import t = x.namedTypes;
|
|
5
|
+
export declare const metroConfigPath = "metro.config.js";
|
|
5
6
|
export declare function patchMetroWithSentryConfig(): Promise<void>;
|
|
6
7
|
export declare function patchMetroWithSentryConfigInMemory(mod: ProxifiedModule, showInstructions: () => Promise<void>): Promise<boolean>;
|
|
7
8
|
export declare function patchMetroConfigWithSentrySerializer(): Promise<void>;
|
|
8
9
|
export declare function unPatchMetroConfig(): Promise<void>;
|
|
9
10
|
export declare function removeSentrySerializerFromMetroConfig(program: t.Program): boolean;
|
|
10
11
|
export declare function removeSentryRequire(program: t.Program): boolean;
|
|
12
|
+
export declare function parseMetroConfig(): Promise<ProxifiedModule>;
|
|
13
|
+
export declare function writeMetroConfig(mod: ProxifiedModule): Promise<boolean>;
|
|
11
14
|
export declare function addSentrySerializerToMetroConfig(configObj: t.ObjectExpression): boolean;
|
|
12
15
|
export declare function addSentrySerializerRequireToMetroConfig(program: t.Program): boolean;
|
|
13
16
|
export declare function addSentryMetroRequireToMetroConfig(program: t.Program): boolean;
|
|
@@ -62,7 +62,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
62
62
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
63
63
|
};
|
|
64
64
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
65
|
-
exports.getModuleExportsAssignmentRight = exports.getMetroConfigObject = exports.addSentryMetroRequireToMetroConfig = exports.addSentrySerializerRequireToMetroConfig = exports.addSentrySerializerToMetroConfig = exports.removeSentryRequire = exports.removeSentrySerializerFromMetroConfig = exports.unPatchMetroConfig = exports.patchMetroConfigWithSentrySerializer = exports.patchMetroWithSentryConfigInMemory = exports.patchMetroWithSentryConfig = void 0;
|
|
65
|
+
exports.getModuleExportsAssignmentRight = exports.getMetroConfigObject = exports.addSentryMetroRequireToMetroConfig = exports.addSentrySerializerRequireToMetroConfig = exports.addSentrySerializerToMetroConfig = exports.writeMetroConfig = exports.parseMetroConfig = exports.removeSentryRequire = exports.removeSentrySerializerFromMetroConfig = exports.unPatchMetroConfig = exports.patchMetroConfigWithSentrySerializer = exports.patchMetroWithSentryConfigInMemory = exports.patchMetroWithSentryConfig = exports.metroConfigPath = void 0;
|
|
66
66
|
// @ts-ignore - clack is ESM and TS complains about that. It works though
|
|
67
67
|
var clack = __importStar(require("@clack/prompts"));
|
|
68
68
|
// @ts-ignore - magicast is ESM and TS complains about that. It works though
|
|
@@ -74,7 +74,7 @@ var clack_utils_1 = require("../utils/clack-utils");
|
|
|
74
74
|
var recast = __importStar(require("recast"));
|
|
75
75
|
var chalk_1 = __importDefault(require("chalk"));
|
|
76
76
|
var b = recast.types.builders;
|
|
77
|
-
|
|
77
|
+
exports.metroConfigPath = 'metro.config.js';
|
|
78
78
|
function patchMetroWithSentryConfig() {
|
|
79
79
|
return __awaiter(this, void 0, void 0, function () {
|
|
80
80
|
var mod, showInstructions, success, saved;
|
|
@@ -84,7 +84,7 @@ function patchMetroWithSentryConfig() {
|
|
|
84
84
|
case 1:
|
|
85
85
|
mod = _a.sent();
|
|
86
86
|
showInstructions = function () {
|
|
87
|
-
return (0, clack_utils_1.showCopyPasteInstructions)(metroConfigPath, getMetroWithSentryConfigSnippet(true));
|
|
87
|
+
return (0, clack_utils_1.showCopyPasteInstructions)(exports.metroConfigPath, getMetroWithSentryConfigSnippet(true));
|
|
88
88
|
};
|
|
89
89
|
return [4 /*yield*/, patchMetroWithSentryConfigInMemory(mod, showInstructions)];
|
|
90
90
|
case 2:
|
|
@@ -96,10 +96,10 @@ function patchMetroWithSentryConfig() {
|
|
|
96
96
|
case 3:
|
|
97
97
|
saved = _a.sent();
|
|
98
98
|
if (!saved) return [3 /*break*/, 4];
|
|
99
|
-
clack.log.success(chalk_1.default.green("".concat(chalk_1.default.cyan(metroConfigPath), " changes saved.")));
|
|
99
|
+
clack.log.success(chalk_1.default.green("".concat(chalk_1.default.cyan(exports.metroConfigPath), " changes saved.")));
|
|
100
100
|
return [3 /*break*/, 6];
|
|
101
101
|
case 4:
|
|
102
|
-
clack.log.warn("Could not save changes to ".concat(chalk_1.default.cyan(metroConfigPath), ", please follow the manual steps."));
|
|
102
|
+
clack.log.warn("Could not save changes to ".concat(chalk_1.default.cyan(exports.metroConfigPath), ", please follow the manual steps."));
|
|
103
103
|
return [4 /*yield*/, showInstructions()];
|
|
104
104
|
case 5: return [2 /*return*/, _a.sent()];
|
|
105
105
|
case 6: return [2 /*return*/];
|
|
@@ -149,7 +149,7 @@ function patchMetroWithSentryConfigInMemory(mod, showInstructions) {
|
|
|
149
149
|
_a.sent();
|
|
150
150
|
return [2 /*return*/, false];
|
|
151
151
|
case 9:
|
|
152
|
-
clack.log.success("Added Sentry Metro plugin to ".concat(chalk_1.default.cyan(metroConfigPath), "."));
|
|
152
|
+
clack.log.success("Added Sentry Metro plugin to ".concat(chalk_1.default.cyan(exports.metroConfigPath), "."));
|
|
153
153
|
return [2 /*return*/, true];
|
|
154
154
|
}
|
|
155
155
|
});
|
|
@@ -165,7 +165,7 @@ function patchMetroConfigWithSentrySerializer() {
|
|
|
165
165
|
case 1:
|
|
166
166
|
mod = _a.sent();
|
|
167
167
|
showInstructions = function () {
|
|
168
|
-
return (0, clack_utils_1.showCopyPasteInstructions)(metroConfigPath, getMetroSentrySerializerSnippet(true));
|
|
168
|
+
return (0, clack_utils_1.showCopyPasteInstructions)(exports.metroConfigPath, getMetroSentrySerializerSnippet(true));
|
|
169
169
|
};
|
|
170
170
|
if (!(0, ast_utils_1.hasSentryContent)(mod.$ast)) return [3 /*break*/, 4];
|
|
171
171
|
return [4 /*yield*/, confirmPathMetroConfig()];
|
|
@@ -192,15 +192,15 @@ function patchMetroConfigWithSentrySerializer() {
|
|
|
192
192
|
return [4 /*yield*/, showInstructions()];
|
|
193
193
|
case 7: return [2 /*return*/, _a.sent()];
|
|
194
194
|
case 8:
|
|
195
|
-
clack.log.success("Added Sentry Metro plugin to ".concat(chalk_1.default.cyan(metroConfigPath), "."));
|
|
195
|
+
clack.log.success("Added Sentry Metro plugin to ".concat(chalk_1.default.cyan(exports.metroConfigPath), "."));
|
|
196
196
|
return [4 /*yield*/, writeMetroConfig(mod)];
|
|
197
197
|
case 9:
|
|
198
198
|
saved = _a.sent();
|
|
199
199
|
if (!saved) return [3 /*break*/, 10];
|
|
200
|
-
clack.log.success(chalk_1.default.green("".concat(chalk_1.default.cyan(metroConfigPath), " changes saved.")));
|
|
200
|
+
clack.log.success(chalk_1.default.green("".concat(chalk_1.default.cyan(exports.metroConfigPath), " changes saved.")));
|
|
201
201
|
return [3 /*break*/, 12];
|
|
202
202
|
case 10:
|
|
203
|
-
clack.log.warn("Could not save changes to ".concat(chalk_1.default.cyan(metroConfigPath), ", please follow the manual steps."));
|
|
203
|
+
clack.log.warn("Could not save changes to ".concat(chalk_1.default.cyan(exports.metroConfigPath), ", please follow the manual steps."));
|
|
204
204
|
return [4 /*yield*/, showInstructions()];
|
|
205
205
|
case 11: return [2 /*return*/, _a.sent()];
|
|
206
206
|
case 12: return [2 /*return*/];
|
|
@@ -224,11 +224,11 @@ function unPatchMetroConfig() {
|
|
|
224
224
|
case 2:
|
|
225
225
|
saved = _a.sent();
|
|
226
226
|
if (saved) {
|
|
227
|
-
clack.log.success("Removed Sentry Metro plugin from ".concat(chalk_1.default.cyan(metroConfigPath), "."));
|
|
227
|
+
clack.log.success("Removed Sentry Metro plugin from ".concat(chalk_1.default.cyan(exports.metroConfigPath), "."));
|
|
228
228
|
}
|
|
229
229
|
return [3 /*break*/, 4];
|
|
230
230
|
case 3:
|
|
231
|
-
clack.log.warn("No Sentry Metro plugin found in ".concat(chalk_1.default.cyan(metroConfigPath), "."));
|
|
231
|
+
clack.log.warn("No Sentry Metro plugin found in ".concat(chalk_1.default.cyan(exports.metroConfigPath), "."));
|
|
232
232
|
_a.label = 4;
|
|
233
233
|
case 4: return [2 /*return*/];
|
|
234
234
|
}
|
|
@@ -292,7 +292,7 @@ function parseMetroConfig() {
|
|
|
292
292
|
var metroConfigContent;
|
|
293
293
|
return __generator(this, function (_a) {
|
|
294
294
|
switch (_a.label) {
|
|
295
|
-
case 0: return [4 /*yield*/, fs.promises.readFile(metroConfigPath)];
|
|
295
|
+
case 0: return [4 /*yield*/, fs.promises.readFile(exports.metroConfigPath)];
|
|
296
296
|
case 1:
|
|
297
297
|
metroConfigContent = (_a.sent()).toString();
|
|
298
298
|
return [2 /*return*/, (0, magicast_1.parseModule)(metroConfigContent)];
|
|
@@ -300,6 +300,7 @@ function parseMetroConfig() {
|
|
|
300
300
|
});
|
|
301
301
|
});
|
|
302
302
|
}
|
|
303
|
+
exports.parseMetroConfig = parseMetroConfig;
|
|
303
304
|
function writeMetroConfig(mod) {
|
|
304
305
|
return __awaiter(this, void 0, void 0, function () {
|
|
305
306
|
var e_1;
|
|
@@ -307,19 +308,20 @@ function writeMetroConfig(mod) {
|
|
|
307
308
|
switch (_a.label) {
|
|
308
309
|
case 0:
|
|
309
310
|
_a.trys.push([0, 2, , 3]);
|
|
310
|
-
return [4 /*yield*/, (0, magicast_1.writeFile)(mod.$ast, metroConfigPath)];
|
|
311
|
+
return [4 /*yield*/, (0, magicast_1.writeFile)(mod.$ast, exports.metroConfigPath)];
|
|
311
312
|
case 1:
|
|
312
313
|
_a.sent();
|
|
313
314
|
return [3 /*break*/, 3];
|
|
314
315
|
case 2:
|
|
315
316
|
e_1 = _a.sent();
|
|
316
|
-
clack.log.error("Failed to write to ".concat(chalk_1.default.cyan(metroConfigPath), ": ").concat(JSON.stringify(e_1)));
|
|
317
|
+
clack.log.error("Failed to write to ".concat(chalk_1.default.cyan(exports.metroConfigPath), ": ").concat(JSON.stringify(e_1)));
|
|
317
318
|
return [2 /*return*/, false];
|
|
318
319
|
case 3: return [2 /*return*/, true];
|
|
319
320
|
}
|
|
320
321
|
});
|
|
321
322
|
});
|
|
322
323
|
}
|
|
324
|
+
exports.writeMetroConfig = writeMetroConfig;
|
|
323
325
|
function addSentrySerializerToMetroConfig(configObj) {
|
|
324
326
|
var serializerProp = getSerializerProp(configObj);
|
|
325
327
|
if ('invalid' === serializerProp) {
|