@flareapp/react-native-sourcemaps 2.6.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/dist/bin.mjs ADDED
@@ -0,0 +1,252 @@
1
+ #!/usr/bin/env node
2
+ import { t as uploadSourcemaps } from "./uploadSourcemaps-C2EGBxe1.mjs";
3
+ import { r as LOG_PREFIX, t as resolveAutoVersion } from "./version-DnFqflPl.mjs";
4
+ import { readFileSync } from "node:fs";
5
+ import { dirname, join } from "node:path";
6
+
7
+ //#region src/banner.ts
8
+ const BORDER = "=".repeat(60);
9
+ /**
10
+ * Mask an API key for display in a build log, which CI commonly archives. A key
11
+ * long enough to stay unguessable keeps a short head/tail so the user can still
12
+ * recognise WHICH key it was; a short key is fully masked. Never returns the key
13
+ * in full, so the secret cannot leak through the failure banner.
14
+ */
15
+ function maskApiKey(apiKey) {
16
+ if (apiKey.length <= 12) return "*".repeat(apiKey.length);
17
+ return `${apiKey.slice(0, 4)}${"*".repeat(8)}${apiKey.slice(-4)}`;
18
+ }
19
+ /**
20
+ * The deliberately large failure banner. A one-line "failed to upload" is too easy
21
+ * to miss in a long native-build log, so this is a bordered block surrounded by
22
+ * blank lines. Resolved values are interpolated into the re-run command so the
23
+ * user can copy-paste it; unknown values show a labelled placeholder (in the
24
+ * version-unset case `version` stays a placeholder — it is the value to supply).
25
+ * The API key is the one exception: it is MASKED, never printed in full, because
26
+ * this banner lands in the native build log.
27
+ */
28
+ function formatFailureBanner(info) {
29
+ const sourcemap = info.sourcemap ?? "<path-to-map>";
30
+ const bundleFilename = info.bundleFilename ?? "<bundle-filename>";
31
+ const version = info.version && info.version.length > 0 ? info.version : "<flare-sourcemap-version>";
32
+ const hasApiKey = !!(info.apiKey && info.apiKey.length > 0);
33
+ const apiKey = hasApiKey ? maskApiKey(info.apiKey) : "<your-flare-api-key>";
34
+ const endpointFlag = info.apiEndpoint ? ` --api-endpoint ${info.apiEndpoint}` : "";
35
+ const lines = [
36
+ "",
37
+ BORDER,
38
+ " FLARE SOURCEMAP UPLOAD FAILED",
39
+ ` Reason: ${info.reason}`,
40
+ " Your release will report minified stack traces until the",
41
+ " sourcemap is uploaded. Re-run manually:",
42
+ ` npx flare-rn-sourcemaps upload --sourcemap ${sourcemap} \\`,
43
+ ` --bundle-filename ${bundleFilename} --version ${version} --api-key ${apiKey}${endpointFlag}`
44
+ ];
45
+ if (hasApiKey) lines.push(" (the --api-key above is masked; pass your full Flare key, or set FLARE_API_KEY, when re-running)");
46
+ lines.push(BORDER, "");
47
+ return lines.join("\n");
48
+ }
49
+ function printFailureBanner(info) {
50
+ console.error(formatFailureBanner(info));
51
+ }
52
+
53
+ //#endregion
54
+ //#region src/config.ts
55
+ /**
56
+ * Read flare.json from an EXPLICIT path. The hooks run from android/ or ios/, so
57
+ * resolving relative to process.cwd() would read the wrong file — callers always
58
+ * pass --config. Missing or malformed file → empty config, so resolution falls
59
+ * through to env, then to the no-key skip-with-banner. Any `version` key is
60
+ * deliberately ignored: in the auto path the version flows only through
61
+ * FLARE_SOURCEMAP_VERSION (see resolveAutoVersion / the design doc).
62
+ */
63
+ function readFlareConfig(configPath) {
64
+ if (!configPath) return {};
65
+ try {
66
+ const raw = JSON.parse(readFileSync(configPath, "utf8"));
67
+ const config = {};
68
+ const apiKey = asString(raw.apiKey);
69
+ const apiEndpoint = asString(raw.apiEndpoint);
70
+ if (apiKey !== void 0) config.apiKey = apiKey;
71
+ if (apiEndpoint !== void 0) config.apiEndpoint = apiEndpoint;
72
+ return config;
73
+ } catch {
74
+ return {};
75
+ }
76
+ }
77
+ function asString(value) {
78
+ return typeof value === "string" && value.length > 0 ? value : void 0;
79
+ }
80
+
81
+ //#endregion
82
+ //#region src/env.ts
83
+ const ENV_FILES = [".env.local", ".env"];
84
+ /**
85
+ * Load FLARE_* variables from .env.local / .env in `rootDir` into process.env,
86
+ * without overwriting anything already set.
87
+ *
88
+ * The native build hooks run in a fresh process whose environment often does NOT
89
+ * carry the upload key: the app's .env files are loaded by Metro at JS runtime, not
90
+ * at native build time, and a build launched from an IDE — or served by a reused
91
+ * Gradle daemon with a stale environment — won't see a key you exported in your
92
+ * shell. Reading the key from the FILE here makes "drop FLARE_API_KEY in .env.local"
93
+ * work the way developers expect, on both platforms, without re-exporting it per
94
+ * build.
95
+ *
96
+ * Only FLARE_-prefixed keys are read, so this never pulls unrelated secrets from the
97
+ * file into the process. Minimal parser (no dependency): `KEY=value`, an optional
98
+ * `export ` prefix, surrounding single/double quotes stripped, blank and `#` comment
99
+ * lines ignored. Inline comments are NOT stripped (a `#` is treated as part of the
100
+ * value), which is fine for the alphanumeric keys Flare issues.
101
+ */
102
+ function loadEnvFiles(rootDir) {
103
+ for (const file of ENV_FILES) {
104
+ let raw;
105
+ try {
106
+ raw = readFileSync(join(rootDir, file), "utf8");
107
+ } catch {
108
+ continue;
109
+ }
110
+ for (const [key, value] of parseFlareEnv(raw)) if (process.env[key] === void 0) process.env[key] = value;
111
+ }
112
+ }
113
+ function parseFlareEnv(raw) {
114
+ const out = [];
115
+ for (const line of raw.split(/\r?\n/)) {
116
+ const trimmed = line.trim();
117
+ if (trimmed === "" || trimmed.startsWith("#")) continue;
118
+ const body = trimmed.startsWith("export ") ? trimmed.slice(7).trim() : trimmed;
119
+ const eq = body.indexOf("=");
120
+ if (eq === -1) continue;
121
+ const key = body.slice(0, eq).trim();
122
+ if (!key.startsWith("FLARE_")) continue;
123
+ let value = body.slice(eq + 1).trim();
124
+ if ((value.startsWith("\"") && value.endsWith("\"") || value.startsWith("'") && value.endsWith("'")) && value.length >= 2) value = value.slice(1, -1);
125
+ out.push([key, value]);
126
+ }
127
+ return out;
128
+ }
129
+
130
+ //#endregion
131
+ //#region src/cli.ts
132
+ const USAGE = "Usage: flare-rn-sourcemaps upload --sourcemap <path> [--api-key <key>] [--bundle-filename <name>] [--version <v>] [--api-endpoint <url>] [--config <flare.json>] [--auto]";
133
+ /** Minimal `--flag value` / `--flag` parser. No external dependency. */
134
+ function parseArgs(argv) {
135
+ const [command, ...rest] = argv;
136
+ const flags = {};
137
+ for (let i = 0; i < rest.length; i++) {
138
+ const arg = rest[i];
139
+ if (!arg.startsWith("--")) continue;
140
+ const body = arg.slice(2);
141
+ const eq = body.indexOf("=");
142
+ if (eq !== -1) {
143
+ flags[body.slice(0, eq)] = body.slice(eq + 1);
144
+ continue;
145
+ }
146
+ const key = body;
147
+ const next = rest[i + 1];
148
+ if (next !== void 0 && !next.startsWith("--")) {
149
+ flags[key] = next;
150
+ i++;
151
+ } else flags[key] = "true";
152
+ }
153
+ return {
154
+ command,
155
+ flags
156
+ };
157
+ }
158
+ async function runCli(argv) {
159
+ const { command, flags } = parseArgs(argv);
160
+ if (command !== "upload") {
161
+ console.error(`${LOG_PREFIX}: Unknown command "${command ?? ""}".\n${USAGE}`);
162
+ process.exitCode = 1;
163
+ return;
164
+ }
165
+ const sourcemap = flags.sourcemap;
166
+ if (!sourcemap) {
167
+ console.error(`${LOG_PREFIX}: --sourcemap is required.\n${USAGE}`);
168
+ process.exitCode = 1;
169
+ return;
170
+ }
171
+ if (flags.auto === "true") loadEnvFiles(flags.config ? dirname(flags.config) : process.cwd());
172
+ const config = readFlareConfig(flags.config);
173
+ const apiKey = flags["api-key"] ?? process.env.FLARE_API_KEY ?? config.apiKey ?? "";
174
+ const apiEndpoint = flags["api-endpoint"] ?? process.env.FLARE_API_ENDPOINT ?? config.apiEndpoint;
175
+ const bundleFilename = flags["bundle-filename"];
176
+ if (flags.auto === "true") {
177
+ await runAutoUpload({
178
+ apiKey,
179
+ sourcemap,
180
+ bundleFilename,
181
+ apiEndpoint,
182
+ version: flags.version
183
+ });
184
+ return;
185
+ }
186
+ await uploadSourcemaps({
187
+ apiKey,
188
+ sourcemap,
189
+ bundleFilename,
190
+ version: flags.version,
191
+ apiEndpoint
192
+ });
193
+ }
194
+ /**
195
+ * The build-hook upload path. It NEVER throws and NEVER sets a non-zero exit code
196
+ * (a Gradle doLast / Xcode run-script phase would abort the build on a non-zero
197
+ * child). Every failure mode — no key, unresolved version, upload error — prints the
198
+ * loud banner and returns, leaving the build green. Only arg misuse (handled in
199
+ * runCli before we get here) exits non-zero.
200
+ */
201
+ async function runAutoUpload(options) {
202
+ const { apiKey, sourcemap, bundleFilename, apiEndpoint } = options;
203
+ if (!apiKey) {
204
+ printFailureBanner({
205
+ reason: "No Flare API key. Set FLARE_API_KEY (shell, .env.local, or .env) or add \"apiKey\" to flare.json.",
206
+ sourcemap,
207
+ bundleFilename,
208
+ apiKey,
209
+ apiEndpoint
210
+ });
211
+ return;
212
+ }
213
+ const version = resolveAutoVersion(options.version);
214
+ if (!version) {
215
+ printFailureBanner({
216
+ reason: "FLARE_SOURCEMAP_VERSION is not set (required for the automatic upload).",
217
+ sourcemap,
218
+ bundleFilename,
219
+ apiKey,
220
+ apiEndpoint
221
+ });
222
+ return;
223
+ }
224
+ try {
225
+ await uploadSourcemaps({
226
+ apiKey,
227
+ sourcemap,
228
+ bundleFilename,
229
+ version,
230
+ apiEndpoint
231
+ });
232
+ } catch (error) {
233
+ printFailureBanner({
234
+ reason: error instanceof Error ? error.message : String(error),
235
+ sourcemap,
236
+ bundleFilename,
237
+ version,
238
+ apiKey,
239
+ apiEndpoint
240
+ });
241
+ }
242
+ }
243
+
244
+ //#endregion
245
+ //#region src/bin.ts
246
+ runCli(process.argv.slice(2)).catch((error) => {
247
+ console.error(error);
248
+ process.exitCode = 1;
249
+ });
250
+
251
+ //#endregion
252
+ export { };
package/dist/expo.cjs ADDED
@@ -0,0 +1,254 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
3
+
4
+ //#endregion
5
+ let node_fs = require("node:fs");
6
+ let node_path = require("node:path");
7
+ let _expo_config_plugins = require("@expo/config-plugins");
8
+
9
+ //#region src/expoTransforms.ts
10
+ const FLARE_GRADLE_MARKER = "@flareapp/react-native-sourcemaps Expo config plugin";
11
+ const SOURCEMAP_FILE_LINE = "export SOURCEMAP_FILE=\"$TARGET_TEMP_DIR/main.jsbundle.map\"";
12
+ const GITIGNORE_ENTRY = "flare.json";
13
+ /** Serialise the plugin props into the flare.json the native hooks read. Absent
14
+ * props are omitted so the CLI applies its own defaults (endpoint) and env fallback
15
+ * (FLARE_API_KEY). No `version` key — version flows only through FLARE_SOURCEMAP_VERSION. */
16
+ function flareJsonContents(props) {
17
+ const config = {};
18
+ if (props.apiKey) config.apiKey = props.apiKey;
19
+ if (props.apiEndpoint) config.apiEndpoint = props.apiEndpoint;
20
+ return `${JSON.stringify(config, null, 4)}\n`;
21
+ }
22
+ /** Append `apply from: "<path>"` to android/app/build.gradle. Idempotent via a marker
23
+ * comment, so a re-prebuild without --clean does not duplicate it. */
24
+ function addFlareGradleApply(buildGradle, applyFromPath) {
25
+ if (buildGradle.includes(FLARE_GRADLE_MARKER)) return buildGradle;
26
+ return `${buildGradle.endsWith("\n") ? buildGradle : `${buildGradle}\n`}\n// ${FLARE_GRADLE_MARKER}\napply from: ${JSON.stringify(applyFromPath)}\n`;
27
+ }
28
+ /** Ensure ios/.xcode.env exports SOURCEMAP_FILE so the stock bundle phase emits the
29
+ * composed map. Idempotent, and treats a missing file (empty string) as valid input.
30
+ * The guard is line-based and ignores comments, so a commented-out `# SOURCEMAP_FILE=`
31
+ * does not suppress injection while a real `export SOURCEMAP_FILE=`/`SOURCEMAP_FILE=`
32
+ * (a user's custom map path) is left untouched. */
33
+ function addSourcemapFileEnv(xcodeEnv) {
34
+ if (xcodeEnv.split("\n").some((line) => {
35
+ const trimmed = line.trim();
36
+ return !trimmed.startsWith("#") && /^(export\s+)?SOURCEMAP_FILE=/.test(trimmed);
37
+ })) return xcodeEnv;
38
+ return `${xcodeEnv.length === 0 || xcodeEnv.endsWith("\n") ? xcodeEnv : `${xcodeEnv}\n`}# Flare: emit the composed Hermes sourcemap so the upload phase can find it\n${SOURCEMAP_FILE_LINE}\n`;
39
+ }
40
+ /** Append `flare.json` to .gitignore once (the file is generated from app.json props). */
41
+ function ensureGitignored(gitignore, entry = GITIGNORE_ENTRY) {
42
+ if (gitignore.split("\n").some((line) => line.trim() === entry)) return gitignore;
43
+ return `${gitignore.length === 0 || gitignore.endsWith("\n") ? gitignore : `${gitignore}\n`}${entry}\n`;
44
+ }
45
+ /** The shell body of the iOS "Upload Flare sourcemaps" phase: source RN's
46
+ * with-environment.sh (so SOURCEMAP_FILE/FLARE_* are present), then run flare-xcode.sh. */
47
+ function flareXcodeShellScript(withEnvironmentPath, flareXcodePath) {
48
+ return [
49
+ "set -e",
50
+ `WITH_ENVIRONMENT="${withEnvironmentPath}"`,
51
+ `FLARE_XCODE="${flareXcodePath}"`,
52
+ "/bin/sh \"$WITH_ENVIRONMENT\" \"$FLARE_XCODE\"",
53
+ ""
54
+ ].join("\n");
55
+ }
56
+ /** path.relative, normalised to forward slashes (Gradle/Xcode script paths are posix
57
+ * even when prebuild runs on Windows). */
58
+ function toPosixRelative(fromDir, target) {
59
+ return (0, node_path.relative)(fromDir, target).split(node_path.sep).join("/");
60
+ }
61
+
62
+ //#endregion
63
+ //#region src/expoXcode.ts
64
+ const FLARE_PHASE_NAME = "Upload Flare sourcemaps";
65
+ const ALWAYS_OUT_OF_DATE = 1;
66
+ /**
67
+ * Append an "Upload Flare sourcemaps" shell-script phase to the app target. The phase
68
+ * is APPENDED (so it always runs after the JS bundle phase, whatever that phase is
69
+ * named or wherever it sits across Expo SDKs). Idempotency guard: skip if a phase with
70
+ * our name already exists. Note this mutates `project` in place (the `xcode` lib's
71
+ * contract) and returns the same instance for convenience.
72
+ */
73
+ function addUploadBuildPhase(project, shellScript) {
74
+ const internal = project;
75
+ const phases = internal.hash.project.objects.PBXShellScriptBuildPhase ?? {};
76
+ if (Object.values(phases).some((phase) => typeof phase === "object" && phase !== null && typeof phase.name === "string" && phase.name.replace(/^"|"$/g, "") === FLARE_PHASE_NAME)) return project;
77
+ const { buildPhase } = internal.addBuildPhase([], "PBXShellScriptBuildPhase", FLARE_PHASE_NAME, null, {
78
+ shellPath: "/bin/sh",
79
+ shellScript
80
+ });
81
+ buildPhase.alwaysOutOfDate = ALWAYS_OUT_OF_DATE;
82
+ return project;
83
+ }
84
+
85
+ //#endregion
86
+ //#region package.json
87
+ var require_package = /* @__PURE__ */ __commonJSMin(((exports, module) => {
88
+ module.exports = {
89
+ "name": "@flareapp/react-native-sourcemaps",
90
+ "version": "2.6.0",
91
+ "description": "Upload React Native (Metro) sourcemaps to Flare",
92
+ "homepage": "https://flareapp.io",
93
+ "bugs": "https://github.com/spatie/flare-client-js/issues",
94
+ "repository": {
95
+ "type": "git",
96
+ "url": "git+https://github.com/spatie/flare-client-js.git"
97
+ },
98
+ "license": "MIT",
99
+ "author": {
100
+ "name": "Spatie",
101
+ "email": "info@spatie.be"
102
+ },
103
+ "files": [
104
+ "dist",
105
+ "flare.gradle",
106
+ "scripts"
107
+ ],
108
+ "main": "./dist/index.cjs",
109
+ "module": "./dist/index.mjs",
110
+ "types": "./dist/index.d.cts",
111
+ "bin": { "flare-rn-sourcemaps": "./dist/bin.cjs" },
112
+ "exports": {
113
+ ".": {
114
+ "import": {
115
+ "types": "./dist/index.d.mts",
116
+ "default": "./dist/index.mjs"
117
+ },
118
+ "require": {
119
+ "types": "./dist/index.d.cts",
120
+ "default": "./dist/index.cjs"
121
+ }
122
+ },
123
+ "./babel": {
124
+ "import": {
125
+ "types": "./dist/babel.d.mts",
126
+ "default": "./dist/babel.mjs"
127
+ },
128
+ "require": {
129
+ "types": "./dist/babel.d.cts",
130
+ "default": "./dist/babel.cjs"
131
+ }
132
+ },
133
+ "./runtime": {
134
+ "import": {
135
+ "types": "./dist/runtime.d.mts",
136
+ "default": "./dist/runtime.mjs"
137
+ },
138
+ "require": {
139
+ "types": "./dist/runtime.d.cts",
140
+ "default": "./dist/runtime.cjs"
141
+ }
142
+ },
143
+ "./expo": {
144
+ "types": "./dist/expo.d.cts",
145
+ "require": "./dist/expo.cjs",
146
+ "default": "./dist/expo.cjs"
147
+ },
148
+ "./package.json": "./package.json"
149
+ },
150
+ "engines": { "node": ">=18" },
151
+ "scripts": {
152
+ "prepublishOnly": "npm run build",
153
+ "build": "tsdown",
154
+ "test": "vitest run",
155
+ "typescript": "tsc --noEmit",
156
+ "release": "release-it"
157
+ },
158
+ "devDependencies": {
159
+ "@babel/core": "^7.0.0",
160
+ "@expo/config-plugins": "^56.0.9",
161
+ "@flareapp/flare-api": "*",
162
+ "@types/babel__core": "^7.0.0",
163
+ "tsdown": "^0.20.3",
164
+ "typescript": "^5.7.0",
165
+ "vitest": "^4.0.0",
166
+ "xcode": "^3.0.1"
167
+ },
168
+ "peerDependencies": {
169
+ "@babel/core": ">=7.0.0",
170
+ "@expo/config-plugins": ">=7.0.0"
171
+ },
172
+ "peerDependenciesMeta": {
173
+ "@babel/core": { "optional": true },
174
+ "@expo/config-plugins": { "optional": true }
175
+ },
176
+ "publishConfig": { "access": "public" }
177
+ };
178
+ }));
179
+
180
+ //#endregion
181
+ //#region src/expo.ts
182
+ function packageDir() {
183
+ return (0, node_path.dirname)(require.resolve("@flareapp/react-native-sourcemaps/package.json"));
184
+ }
185
+ function flareGradlePath() {
186
+ return (0, node_path.join)(packageDir(), "flare.gradle");
187
+ }
188
+ function flareXcodeScriptPath() {
189
+ return (0, node_path.join)(packageDir(), "scripts", "flare-xcode.sh");
190
+ }
191
+ function withEnvironmentScriptPath() {
192
+ return (0, node_path.join)((0, node_path.dirname)(require.resolve("react-native/package.json")), "scripts", "xcode", "with-environment.sh");
193
+ }
194
+ async function writeFlareConfigFiles(projectRoot, props) {
195
+ await node_fs.promises.writeFile((0, node_path.join)(projectRoot, "flare.json"), flareJsonContents(props), "utf8");
196
+ const gitignorePath = (0, node_path.join)(projectRoot, ".gitignore");
197
+ let gitignore = "";
198
+ try {
199
+ gitignore = await node_fs.promises.readFile(gitignorePath, "utf8");
200
+ } catch {
201
+ gitignore = "";
202
+ }
203
+ await node_fs.promises.writeFile(gitignorePath, ensureGitignored(gitignore), "utf8");
204
+ }
205
+ const withFlareConfigFiles = (config, props) => {
206
+ for (const platform of ["ios", "android"]) config = (0, _expo_config_plugins.withDangerousMod)(config, [platform, async (cfg) => {
207
+ await writeFlareConfigFiles(cfg.modRequest.projectRoot, props);
208
+ return cfg;
209
+ }]);
210
+ return config;
211
+ };
212
+ const withFlareAndroidGradle = (config) => (0, _expo_config_plugins.withAppBuildGradle)(config, (cfg) => {
213
+ const appDir = (0, node_path.join)(cfg.modRequest.platformProjectRoot, "app");
214
+ cfg.modResults.contents = addFlareGradleApply(cfg.modResults.contents, toPosixRelative(appDir, flareGradlePath()));
215
+ return cfg;
216
+ });
217
+ const withFlareXcodeEnv = (config) => (0, _expo_config_plugins.withDangerousMod)(config, ["ios", async (cfg) => {
218
+ const xcodeEnvPath = (0, node_path.join)(cfg.modRequest.platformProjectRoot, ".xcode.env");
219
+ let contents = "";
220
+ try {
221
+ contents = await node_fs.promises.readFile(xcodeEnvPath, "utf8");
222
+ } catch {
223
+ contents = "";
224
+ }
225
+ await node_fs.promises.writeFile(xcodeEnvPath, addSourcemapFileEnv(contents), "utf8");
226
+ return cfg;
227
+ }]);
228
+ const withFlareIosBuildPhase = (config) => (0, _expo_config_plugins.withXcodeProject)(config, (cfg) => {
229
+ const iosRoot = cfg.modRequest.platformProjectRoot;
230
+ const shellScript = flareXcodeShellScript(toPosixRelative(iosRoot, withEnvironmentScriptPath()), toPosixRelative(iosRoot, flareXcodeScriptPath()));
231
+ cfg.modResults = addUploadBuildPhase(cfg.modResults, shellScript);
232
+ return cfg;
233
+ });
234
+ const withFlareSourcemaps = (config, props) => {
235
+ config = withFlareConfigFiles(config, props ?? {});
236
+ config = withFlareAndroidGradle(config);
237
+ config = withFlareXcodeEnv(config);
238
+ config = withFlareIosBuildPhase(config);
239
+ return config;
240
+ };
241
+ const pkg = (() => {
242
+ try {
243
+ return require_package();
244
+ } catch {
245
+ return {
246
+ name: "@flareapp/react-native-sourcemaps",
247
+ version: "0.0.0"
248
+ };
249
+ }
250
+ })();
251
+ var expo_default = (0, _expo_config_plugins.createRunOncePlugin)(withFlareSourcemaps, pkg.name, pkg.version);
252
+
253
+ //#endregion
254
+ module.exports = expo_default;
@@ -0,0 +1,11 @@
1
+ import { ConfigPlugin } from "@expo/config-plugins";
2
+
3
+ //#region src/expoTransforms.d.ts
4
+ type FlarePluginProps = {
5
+ apiKey?: string;
6
+ apiEndpoint?: string;
7
+ };
8
+ //#endregion
9
+ //#region src/expo.d.ts
10
+ declare const _default: ConfigPlugin<FlarePluginProps | undefined>;
11
+ export = _default;