Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
4328298
chore: Initialize `RNSentryTimeToDisplay` during native module `init`…
krystofwoldrich Jan 14, 2025
27d76de
ref(ios): Extract Cocoa SDK init into standalone file
krystofwoldrich Jan 14, 2025
5a28c03
fix lint
krystofwoldrich Jan 14, 2025
8b67bf1
rename rnsentrysdk to rnsentrystart
krystofwoldrich Jan 14, 2025
05cef29
rename class name also to rnsentrystart, fix tests
krystofwoldrich Jan 14, 2025
778478f
explicitly import only used classes
krystofwoldrich Jan 14, 2025
3d3d0b4
fix call cocoa start not itself
krystofwoldrich Jan 14, 2025
e2e40fa
also extract didBecomeActive notification
krystofwoldrich Jan 14, 2025
83106a7
add explanation comment to native crash handling
krystofwoldrich Jan 14, 2025
742f28c
explain notification purpose
krystofwoldrich Jan 14, 2025
4897aa3
fix sdk name
krystofwoldrich Jan 14, 2025
d37ebdd
fix native sdk not react native package
krystofwoldrich Jan 14, 2025
13a0b89
fix lint sentry start
krystofwoldrich Jan 14, 2025
d7270b1
add changelog
krystofwoldrich Jan 14, 2025
580590b
feat(experimental): Add native `startWithConfigureOptions` for Apple …
krystofwoldrich Jan 14, 2025
2cc92f2
feat: Read `sentry.options.json` during cocoa init
krystofwoldrich Jan 14, 2025
592b903
Update CHANGELOG.md
krystofwoldrich Jan 15, 2025
a2717bd
remove global processor
krystofwoldrich Jan 15, 2025
5ecd6b2
Merge remote-tracking branch 'origin/kw-add-read-ios-options-file' in…
krystofwoldrich Jan 15, 2025
890133a
Update code docs for start methods
krystofwoldrich Jan 15, 2025
2d021e8
Merge branch 'main' into kw-ref-ios-sdk-init
krystofwoldrich Jan 20, 2025
cfc6293
fix lint
krystofwoldrich Jan 20, 2025
f2a041e
remove unused rnSentry
krystofwoldrich Jan 20, 2025
fc4ff7e
fix changelog
krystofwoldrich Jan 20, 2025
879044f
Merge branch 'kw-ref-ios-sdk-init' into kw-add-react-native-ios-manua…
krystofwoldrich Jan 20, 2025
dec9869
wip! add manual init tests
krystofwoldrich Jan 20, 2025
22e88c7
add tests
krystofwoldrich Jan 21, 2025
4ac4896
Merge branch 'kw-add-react-native-ios-manual-init' into kw-add-read-i…
krystofwoldrich Jan 21, 2025
1baac18
add tests
krystofwoldrich Jan 21, 2025
f92edd9
remove unavailable and unused global events processors import
krystofwoldrich Jan 21, 2025
2662dbd
Merge branch 'kw-add-react-native-ios-manual-init' into kw-add-read-i…
krystofwoldrich Jan 21, 2025
7baad41
fix c-format
krystofwoldrich Jan 21, 2025
1a2aca8
feat: Automatically load `sentry.options.json` file
krystofwoldrich Jan 21, 2025
6d81a10
remove old sentry-cocoa init code
krystofwoldrich Jan 22, 2025
92c32e9
Merge remote-tracking branch 'origin/capture-app-start-errors' into k…
krystofwoldrich Jan 22, 2025
dcfdc6c
Merge remote-tracking branch 'origin/kw-add-read-ios-options-file' in…
krystofwoldrich Jan 22, 2025
7eb1786
fix copy options json only if destination set and file exists
krystofwoldrich Jan 22, 2025
dae191b
Merge branch 'kw-add-read-ios-options-file' into kw-add-options-file-…
krystofwoldrich Jan 22, 2025
0909148
fix types, handle errors, add logs, add support for expo projects
krystofwoldrich Jan 23, 2025
82f2a87
add json options for expo project
krystofwoldrich Jan 23, 2025
21d2880
fix bail todo
krystofwoldrich Jan 23, 2025
539892c
fix lint
krystofwoldrich Jan 23, 2025
c4b2bdd
add tests
krystofwoldrich Jan 23, 2025
55ed3fa
Merge branch 'capture-app-start-errors' into kw-add-options-file-init…
krystofwoldrich Jan 24, 2025
2cdcd60
Update CHANGELOG.md
krystofwoldrich Feb 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

## Unreleased

### Features

- Load `optionsFile` into the JS bundle during Metro bundle process ([#4476](https://github.com/getsentry/sentry-react-native/pull/4476))

### Fixes

- Add mechanism field to unhandled rejection errors ([#4457](https://github.com/getsentry/sentry-react-native/pull/4457))
Expand Down
2 changes: 1 addition & 1 deletion packages/core/jest.config.tools.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module.exports = {
collectCoverage: true,
preset: 'ts-jest',
setupFilesAfterEnv: ['<rootDir>/test/mockConsole.ts'],
setupFilesAfterEnv: ['jest-extended/all', '<rootDir>/test/mockConsole.ts'],
globals: {
__DEV__: true,
},
Expand Down
20 changes: 18 additions & 2 deletions packages/core/src/js/tools/metroconfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { createSentryMetroSerializer, unstable_beforeAssetSerializationPlugin }
import type { DefaultConfigOptions } from './vendor/expo/expoconfig';
export * from './sentryMetroSerializer';
import { withSentryMiddleware } from './metroMiddleware';
import { withSentryOptionsFromFile } from './sentryOptionsSerializer';
import type { MetroCustomSerializer } from './utils';

enableLogger();

Expand All @@ -30,6 +32,14 @@ export interface SentryMetroConfigOptions {
* @default true
*/
enableSourceContextInDevelopment?: boolean;
/**
* Load Sentry Options from a file. If `true` it will use the default path.
* If `false` it will not load any options from a file. Only options provided in the code will be used.
* If `string` it will use the provided path.
*
* @default '{projectRoot}/sentry.options.json'
*/
optionsFile?: string | boolean;
}

export interface SentryExpoConfigOptions {
Expand All @@ -51,6 +61,7 @@ export function withSentryConfig(
annotateReactComponents = false,
includeWebReplay = true,
enableSourceContextInDevelopment = true,
optionsFile = true,
}: SentryMetroConfigOptions = {},
): MetroConfig {
setSentryMetroDevServerEnvFlag();
Expand All @@ -68,6 +79,9 @@ export function withSentryConfig(
if (enableSourceContextInDevelopment) {
newConfig = withSentryMiddleware(newConfig);
}
if (optionsFile) {
newConfig = withSentryOptionsFromFile(newConfig, optionsFile);
}

return newConfig;
}
Expand Down Expand Up @@ -103,6 +117,10 @@ export function getSentryExpoConfig(
newConfig = withSentryMiddleware(newConfig);
}

if (options.optionsFile ?? true) {
newConfig = withSentryOptionsFromFile(newConfig, options.optionsFile ?? true);
}

return newConfig;
}

Expand Down Expand Up @@ -155,8 +173,6 @@ export function withSentryBabelTransformer(config: MetroConfig): MetroConfig {
};
}

type MetroCustomSerializer = Required<Required<MetroConfig>['serializer']>['customSerializer'] | undefined;

function withSentryDebugId(config: MetroConfig): MetroConfig {
const customSerializer = createSentryMetroSerializer(
config.serializer?.customSerializer || undefined,
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/js/tools/sentryMetroSerializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export function unstable_beforeAssetSerializationPlugin({
return [...addDebugIdModule(premodules, debugIdModule)];
}

// TODO: deprecate this and afterwards rename to createSentryDebugIdSerializer
/**
* Creates a Metro serializer that adds Debug ID module to the plain bundle.
* The Debug ID module is a virtual module that provides a debug ID in runtime.
Expand Down
104 changes: 104 additions & 0 deletions packages/core/src/js/tools/sentryOptionsSerializer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { logger } from '@sentry/core';
import * as fs from 'fs';
import type { MetroConfig, Module } from 'metro';
// eslint-disable-next-line import/no-extraneous-dependencies
import * as countLines from 'metro/src/lib/countLines';
import * as path from 'path';

import type { MetroCustomSerializer, VirtualJSOutput } from './utils';
import { createSet } from './utils';

const DEFAULT_OPTIONS_FILE_NAME = 'sentry.options.json';

/**
* Loads Sentry options from a file in
*/
export function withSentryOptionsFromFile(config: MetroConfig, optionsFile: string | boolean): MetroConfig {
if (optionsFile === false) {
return config;
}

const { projectRoot } = config;
if (!projectRoot) {
// eslint-disable-next-line no-console
console.error('[@sentry/react-native/metro] Project root is required to load Sentry options from a file');
return config;
}

let optionsPath = path.join(projectRoot, DEFAULT_OPTIONS_FILE_NAME);
if (typeof optionsFile === 'string' && path.isAbsolute(optionsFile)) {
optionsPath = optionsFile;
} else if (typeof optionsFile === 'string') {
optionsPath = path.join(projectRoot, optionsFile);
}

const originalSerializer = config.serializer?.customSerializer;
if (!originalSerializer) {
// It's okay to bail here because we don't expose this for direct usage, but as part of `withSentryConfig`
// If used directly in RN, the user is responsible for providing a custom serializer first, Expo provides serializer in default config
// eslint-disable-next-line no-console
console.error(
'[@sentry/react-native/metro] `config.serializer.customSerializer` is required to load Sentry options from a file',
);
return config;
}

const sentryOptionsSerializer: MetroCustomSerializer = (entryPoint, preModules, graph, options) => {
const sentryOptionsModule = createSentryOptionsModule(optionsPath);
if (sentryOptionsModule) {
(preModules as Module[]).push(sentryOptionsModule);
}
return originalSerializer(entryPoint, preModules, graph, options);
};

return {
...config,
serializer: {
...config.serializer,
customSerializer: sentryOptionsSerializer,
},
};
}

function createSentryOptionsModule(filePath: string): Module<VirtualJSOutput> | null {
let content: string;
try {
content = fs.readFileSync(filePath, 'utf8');
} catch (error) {
if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
logger.debug(`[@sentry/react-native/metro] Sentry options file does not exist at ${filePath}`);
} else {
logger.error(`[@sentry/react-native/metro] Failed to read Sentry options file at ${filePath}`);
}
return null;
}

let parsedContent: Record<string, unknown>;
try {
parsedContent = JSON.parse(content);
} catch (error) {
logger.error(`[@sentry/react-native/metro] Failed to parse Sentry options file at ${filePath}`);
return null;
}

const minifiedContent = JSON.stringify(parsedContent);
const optionsCode = `var __SENTRY_OPTIONS__=${minifiedContent};`;

logger.debug(`[@sentry/react-native/metro] Sentry options added to the bundle from file at ${filePath}`);
return {
dependencies: new Map(),
getSource: () => Buffer.from(optionsCode),
inverseDependencies: createSet(),
path: '__sentry-options__',
output: [
{
type: 'js/script/virtual',
data: {
code: optionsCode,
lineCount: countLines(optionsCode),
map: [],
},
},
],
};
}
4 changes: 3 additions & 1 deletion packages/core/src/js/tools/utils.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import * as crypto from 'crypto';
// eslint-disable-next-line import/no-extraneous-dependencies
import type { Module, ReadOnlyGraph, SerializerOptions } from 'metro';
import type { MetroConfig, Module, ReadOnlyGraph, SerializerOptions } from 'metro';
// eslint-disable-next-line import/no-extraneous-dependencies
import type CountingSet from 'metro/src/lib/CountingSet';

export type MetroCustomSerializer = Required<Required<MetroConfig>['serializer']>['customSerializer'] | undefined;

// Variant of MixedOutput
// https://github.com/facebook/metro/blob/9b85f83c9cc837d8cd897aa7723be7da5b296067/packages/metro/src/DeltaBundler/types.flow.js#L21
export type VirtualJSOutput = {
Expand Down
Loading
Loading