diff --git a/src/Exceptionless.Web/ClientApp.angular/app/project/configure-controller.js b/src/Exceptionless.Web/ClientApp.angular/app/project/configure-controller.js index b10b60fe1b..b47ede9ae9 100644 --- a/src/Exceptionless.Web/ClientApp.angular/app/project/configure-controller.js +++ b/src/Exceptionless.Web/ClientApp.angular/app/project/configure-controller.js @@ -141,6 +141,8 @@ platform: "JavaScript", }, { key: "Exceptionless.Node", name: "Node.js", platform: "JavaScript" }, + { key: "Exceptionless.ReactNative", name: "React Native", platform: "JavaScript" }, + { key: "Exceptionless.Expo", name: "Expo", platform: "JavaScript" }, ]; } @@ -160,6 +162,14 @@ return vm.currentProjectType.key === "Exceptionless.Node"; } + function isReactNative() { + return vm.currentProjectType.key === "Exceptionless.ReactNative"; + } + + function isExpo() { + return vm.currentProjectType.key === "Exceptionless.Expo"; + } + function isBashShell() { return vm.currentProjectType.key === "Bash Shell"; } @@ -207,9 +217,11 @@ vm.isBashShell = isBashShell; vm.isCommandLine = isCommandLine; vm.isDotNet = isDotNet; + vm.isExpo = isExpo; vm.isGeneratingSampleData = false; vm.isJavaScript = isJavaScript; vm.isNode = isNode; + vm.isReactNative = isReactNative; vm.navigateToDashboard = navigateToDashboard; vm.onCopyError = onCopyError; vm.project = {}; diff --git a/src/Exceptionless.Web/ClientApp.angular/app/project/configure.tpl.html b/src/Exceptionless.Web/ClientApp.angular/app/project/configure.tpl.html index c9fb2d6373..38c2c786d5 100644 --- a/src/Exceptionless.Web/ClientApp.angular/app/project/configure.tpl.html +++ b/src/Exceptionless.Web/ClientApp.angular/app/project/configure.tpl.html @@ -51,7 +51,7 @@
curl "{{::vm.serverUrl}}/api/v2/events" \
--request POST \
- --header "Authorization: Bearer {{::vm.apiKey}}" \
+ --header "Authorization: Bearer {{vm.apiKey}}" \
--header "Content-Type: application/json" \
--data-binary '[{"type":"log","message":"Hello World!"}]'
@@ -61,7 +61,7 @@
} | ConvertTo-Json
$header = @{
- "Authorization"="Bearer {{::vm.apiKey}}"
+ "Authorization"="Bearer {{vm.apiKey}}"
"Content-Type"="application/json"
}
@@ -77,7 +77,7 @@
Install-Package {{vm.currentProjectType.key}}
-
+
npm install @exceptionless/browser --save
@@ -86,22 +86,42 @@
npm install @exceptionless/node --save
+
+ Install Exceptionless using the Node Package Manager. Install AsyncStorage with the client. It is a peer dependency used for persistent event queue storage.
+ npm install @exceptionless/react-native @react-native-async-storage/async-storage
+
+
+ Install Exceptionless using the Node Package Manager. Install AsyncStorage with the client. It is a peer dependency used for persistent event queue storage.
+ npx expo install @exceptionless/react-native @react-native-async-storage/async-storage
+
-
+
{{::'Configure the ExceptionlessClient with your Exceptionless API key:' |
translate}}
- import { Exceptionless } from "@exceptionless/browser";
await Exceptionless.startup(c => {
c.apiKey = "{{::vm.apiKey}}";
});
+ import { Exceptionless } from "@exceptionless/browser";
await Exceptionless.startup(c => {
c.apiKey = "{{vm.apiKey}}";
});
{{::'Configure the ExceptionlessClient with your Exceptionless API key:' |
translate}}
- import { Exceptionless } from "@exceptionless/node";
await Exceptionless.startup(c => {
c.apiKey = "{{::vm.apiKey}}";
});
+ import { Exceptionless } from "@exceptionless/node";
await Exceptionless.startup(c => {
c.apiKey = "{{vm.apiKey}}";
});
+
+
+ Add the Exceptionless config plugin to app.json when using development or standalone builds:
+ {
"expo": {
"plugins": ["@exceptionless/react-native/expo-plugin"]
}
}
+ Native iOS crash reporting requires an Expo development build or standalone build. JavaScript error reporting works in Expo Go.
+
+
+
+ {{::'Configure the ExceptionlessClient with your Exceptionless API key:' |
+ translate}}
+
+ import { Exceptionless } from "@exceptionless/react-native";
await Exceptionless.startup(c => {
c.apiKey = "{{vm.apiKey}}";
});
diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/configure/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/configure/+page.svelte
index 30045ae22c..f6dfbff2d4 100644
--- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/configure/+page.svelte
+++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/configure/+page.svelte
@@ -95,6 +95,23 @@
platform: string;
}
+ type CodeBlockLanguage = 'csharp' | 'javascript' | 'json' | 'powershell' | 'shellscript' | 'xml';
+
+ interface JavaScriptConfigurationStep {
+ code: string;
+ description: string;
+ language: CodeBlockLanguage;
+ note?: string;
+ }
+
+ interface JavaScriptClientConfiguration {
+ extraSteps?: JavaScriptConfigurationStep[];
+ installCommand: string;
+ installNote?: string;
+ packageName: string;
+ startupCode: string;
+ }
+
const projectTypes: ProjectType[] = [
{ id: 'bash', label: 'Bash Shell', platform: 'Command Line' },
{ id: 'powershell', label: 'PowerShell', platform: 'Command Line' },
@@ -106,6 +123,8 @@
{ id: 'javascript-browser', label: 'Browser applications', package: 'Exceptionless.JavaScript', platform: 'JavaScript' },
{ id: 'javascript-nodejs', label: 'Node.js', package: 'Exceptionless.Node', platform: 'JavaScript' },
+ { id: 'javascript-react-native', label: 'React Native', package: '@exceptionless/react-native', platform: 'JavaScript' },
+ { id: 'javascript-expo', label: 'Expo', package: '@exceptionless/react-native', platform: 'JavaScript' },
{ id: 'dotnet-legacy-console', label: 'Console and Service applications', package: 'Exceptionless', platform: '.NET Legacy' },
{ config: 'web.config', id: 'dotnet-legacy-mvc', label: 'ASP.NET MVC', package: 'Exceptionless.Mvc', platform: '.NET Legacy' },
@@ -148,13 +167,16 @@
const isDotNet = $derived(selectedProjectType?.platform === '.NET');
const isDotNetLegacy = $derived(selectedProjectType?.platform === '.NET Legacy');
const isJavaScript = $derived(selectedProjectType?.platform === 'JavaScript');
- const isNode = $derived(selectedProjectType?.package === 'Exceptionless.Node');
const isBashShell = $derived(selectedProjectType?.id === 'bash');
const clientDocumentationUrl = $derived.by(() => {
if (isDotNet || isDotNetLegacy) {
return 'https://exceptionless.com/docs/clients/dotnet/';
}
+ if (selectedProjectType?.id === 'javascript-react-native' || selectedProjectType?.id === 'javascript-expo') {
+ return 'https://github.com/exceptionless/Exceptionless.JavaScript/tree/main/packages/react-native';
+ }
+
if (isJavaScript) {
return 'https://exceptionless.com/docs/clients/javascript/';
}
@@ -207,6 +229,18 @@ $header = @{
Invoke-RestMethod -Uri "${serverUrl}/api/v2/events" -Method "Post" -Body $body -Headers $header`,
+ reactNativeExpoPlugin: `{
+ "expo": {
+ "plugins": ["@exceptionless/react-native/expo-plugin"]
+ }
+}`,
+
+ reactNativeJs: `import { Exceptionless } from "@exceptionless/react-native";
+
+await Exceptionless.startup(c => {
+ c.apiKey = "${apiKey}";
+});`,
+
webApi: `public static void Register(HttpConfiguration config) {
config.AddExceptionless("${apiKey}");
}`,
@@ -250,6 +284,47 @@ public partial class App : Application {
}`
});
+ const javascriptClientConfiguration = $derived.by((): JavaScriptClientConfiguration | null => {
+ switch (selectedProjectType?.id) {
+ case 'javascript-browser':
+ return {
+ installCommand: 'npm install @exceptionless/browser --save',
+ packageName: '@exceptionless/browser',
+ startupCode: codeSamples.browserJs
+ };
+ case 'javascript-expo':
+ return {
+ extraSteps: [
+ {
+ code: codeSamples.reactNativeExpoPlugin,
+ description: 'Add the Exceptionless config plugin to app.json when using development or standalone builds.',
+ language: 'json',
+ note: 'Native iOS crash reporting requires an Expo development build or standalone build. JavaScript error reporting works in Expo Go.'
+ }
+ ],
+ installCommand: 'npx expo install @exceptionless/react-native @react-native-async-storage/async-storage',
+ installNote: 'The AsyncStorage package is a peer dependency used for persistent event queue storage, so install it alongside the client.',
+ packageName: '@exceptionless/react-native',
+ startupCode: codeSamples.reactNativeJs
+ };
+ case 'javascript-nodejs':
+ return {
+ installCommand: 'npm install @exceptionless/node --save',
+ packageName: '@exceptionless/node',
+ startupCode: codeSamples.nodeJs
+ };
+ case 'javascript-react-native':
+ return {
+ installCommand: 'npm install @exceptionless/react-native @react-native-async-storage/async-storage',
+ installNote: 'The AsyncStorage package is a peer dependency used for persistent event queue storage, so install it alongside the client.',
+ packageName: '@exceptionless/react-native',
+ startupCode: codeSamples.reactNativeJs
+ };
+ default:
+ return null;
+ }
+ });
+
useEventListener(document, 'PersistentEventChanged', async (event) => {
const message = (event as CustomEvent>).detail;
@@ -563,40 +638,40 @@ public partial class App : Application {
{/if}
{/if}
- {#if isJavaScript}
+ {#if isJavaScript && javascriptClientConfiguration}
Install the {selectedProjectType.package} npm package in your JavaScript project by running this command in the project
- directory.
Install the {javascriptClientConfiguration.packageName} npm package in your JavaScript project by running this command
+ in the project directory. {javascriptClientConfiguration.installNote ?? ''}
- {#if isNode}
-
-
-
-
- {:else}
-
+
+
+
+
+
+
+ {#each javascriptClientConfiguration.extraSteps ?? [] as step (step.description)}
+
+ {step.description}
+
+
-
+
+
+ {#if step.note}
+ {step.note}
{/if}
-
-
+
+ {/each}
Configure the ExceptionlessClient with your Exceptionless API key.
- {#if !isNode}
-
-
-
-
- {:else}
-
-
-
-
- {/if}
+
+
+
+
{/if}