-
-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(angular): Add Sentry setup in
main.ts
(#768)
- Adds Sentry initialization on main.ts with feature selection - Also adds Prettier run
- Loading branch information
1 parent
56fd0f5
commit 6bfaedc
Showing
3 changed files
with
217 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */ | ||
import type { Program } from '@babel/types'; | ||
|
||
// @ts-expect-error - magicast is ESM and TS complains about that. It works though | ||
import { builders, generateCode, type ProxifiedModule } from 'magicast'; | ||
|
||
export function updateAppEntryMod( | ||
originalAppModuleMod: ProxifiedModule<any>, | ||
dsn: string, | ||
selectedFeatures: { | ||
performance: boolean; | ||
replay: boolean; | ||
}, | ||
): ProxifiedModule<any> { | ||
originalAppModuleMod.imports.$add({ | ||
from: '@sentry/angular', | ||
imported: '*', | ||
local: 'Sentry', | ||
}); | ||
|
||
insertInitCall(originalAppModuleMod, dsn, selectedFeatures); | ||
|
||
return originalAppModuleMod; | ||
} | ||
|
||
export function insertInitCall( | ||
originalAppModuleMod: ProxifiedModule<any>, | ||
dsn: string, | ||
selectedFeatures: { | ||
performance: boolean; | ||
replay: boolean; | ||
}, | ||
): void { | ||
const initCallArgs = getInitCallArgs(dsn, selectedFeatures); | ||
const initCall = builders.functionCall('Sentry.init', initCallArgs); | ||
const originalAppModuleModAst = originalAppModuleMod.$ast as Program; | ||
|
||
const initCallInsertionIndex = getAfterImportsInsertionIndex( | ||
originalAppModuleModAst, | ||
); | ||
|
||
originalAppModuleModAst.body.splice( | ||
initCallInsertionIndex, | ||
0, | ||
// @ts-expect-error - string works here because the AST is proxified by magicast | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument | ||
generateCode(initCall).code, | ||
); | ||
} | ||
|
||
export function getInitCallArgs( | ||
dsn: string, | ||
selectedFeatures: { | ||
performance: boolean; | ||
replay: boolean; | ||
}, | ||
): Record<string, unknown> { | ||
const initCallArgs = { | ||
dsn, | ||
} as Record<string, unknown>; | ||
|
||
if (selectedFeatures.replay || selectedFeatures.performance) { | ||
initCallArgs.integrations = []; | ||
|
||
if (selectedFeatures.performance) { | ||
// @ts-expect-error - Adding Proxified AST node to the array | ||
initCallArgs.integrations.push( | ||
builders.functionCall('Sentry.browserTracingIntegration'), | ||
); | ||
initCallArgs.tracesSampleRate = 1.0; | ||
} | ||
|
||
if (selectedFeatures.replay) { | ||
// @ts-expect-error - Adding Proxified AST node to the array | ||
initCallArgs.integrations.push( | ||
builders.functionCall('Sentry.replayIntegration'), | ||
); | ||
|
||
initCallArgs.replaysSessionSampleRate = 0.1; | ||
initCallArgs.replaysOnErrorSampleRate = 1.0; | ||
} | ||
} | ||
|
||
return initCallArgs; | ||
} | ||
|
||
/** | ||
* We want to insert the handleError function just after all imports | ||
*/ | ||
export function getAfterImportsInsertionIndex( | ||
originalEntryServerModAST: Program, | ||
): number { | ||
for (let x = originalEntryServerModAST.body.length - 1; x >= 0; x--) { | ||
if (originalEntryServerModAST.body[x].type === 'ImportDeclaration') { | ||
return x + 1; | ||
} | ||
} | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */ | ||
|
||
// @ts-expect-error - magicast is ESM and TS complains about that. It works though | ||
import { loadFile, writeFile } from 'magicast'; | ||
|
||
import * as path from 'path'; | ||
|
||
// @ts-expect-error - clack is ESM and TS complains about that. It works though | ||
import clack from '@clack/prompts'; | ||
import chalk from 'chalk'; | ||
import { updateAppEntryMod } from './codemods/main'; | ||
import { hasSentryContent } from '../utils/ast-utils'; | ||
import type { namedTypes as t } from 'ast-types'; | ||
|
||
export async function initalizeSentryOnApplicationEntry( | ||
dsn: string, | ||
selectedFeatures: { | ||
performance: boolean; | ||
replay: boolean; | ||
}, | ||
): Promise<void> { | ||
const appEntryFilename = 'main.ts'; | ||
const appEntryPath = path.join(process.cwd(), 'src', appEntryFilename); | ||
|
||
const originalAppEntry = await loadFile(appEntryPath); | ||
|
||
if (hasSentryContent(originalAppEntry.$ast as t.Program)) { | ||
clack.log.warn( | ||
`File ${chalk.cyan(appEntryFilename)} already contains Sentry. | ||
Skipping adding Sentry functionality to ${chalk.cyan(appEntryFilename)}.`, | ||
); | ||
|
||
return; | ||
} | ||
|
||
try { | ||
const updatedAppEntryMod = updateAppEntryMod( | ||
originalAppEntry, | ||
dsn, | ||
selectedFeatures, | ||
); | ||
|
||
await writeFile(updatedAppEntryMod.$ast, appEntryPath); | ||
} catch (error: unknown) { | ||
clack.log.error( | ||
`Error while adding Sentry to ${chalk.cyan(appEntryFilename)}`, | ||
); | ||
|
||
clack.log.info( | ||
chalk.dim( | ||
typeof error === 'object' && error != null && 'toString' in error | ||
? error.toString() | ||
: typeof error === 'string' | ||
? error | ||
: '', | ||
), | ||
); | ||
|
||
clack.log.warn( | ||
`Please refer to the documentation for manual setup: | ||
${chalk.underline( | ||
'https://docs.sentry.io/platforms/javascript/guides/angular/#configure', | ||
)}`, | ||
); | ||
|
||
return; | ||
} | ||
|
||
clack.log.success( | ||
`Successfully initialized Sentry on ${chalk.cyan(appEntryFilename)}`, | ||
); | ||
} |