1+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
2+ /* eslint-disable @typescript-eslint/no-var-requires */
13/* eslint-disable @typescript-eslint/no-explicit-any */
2- // import { version as nextVersion } from './node_modules/next/package.json';
34import { getSentryRelease } from '@sentry/node' ;
45import { logger } from '@sentry/utils' ;
56import defaultWebpackPlugin , { SentryCliPluginOptions } from '@sentry/webpack-plugin' ;
67import * as SentryWebpackPlugin from '@sentry/webpack-plugin' ;
78import * as fs from 'fs' ;
9+ import * as path from 'path' ;
10+
11+ /**
12+ * Starting at `startPath`, move up one directory at a time, searching for `searchFile`.
13+ *
14+ * @param startPath The location from which to start the search.
15+ * @param searchFile The file to search for
16+ * @returns The absolute path of the file, if it's found, or undefined if it's not
17+ */
18+ function findUp ( startPath : string , searchFile : string ) : string | undefined {
19+ if ( ! fs . existsSync ( startPath ) ) {
20+ throw new Error ( `The given \`startPath\` value (${ startPath } ) does not exist.` ) ;
21+ }
22+
23+ // if the last segment of `startPath` is a file, trim it off so that we start looking in its parent directory
24+ let currentDir = fs . statSync ( startPath ) . isFile ( ) ? path . dirname ( startPath ) : startPath ;
25+ // eslint-disable-next-line no-constant-condition
26+ while ( true ) {
27+ const possiblePath = path . join ( currentDir , searchFile ) ;
28+ if ( fs . existsSync ( possiblePath ) ) {
29+ return possiblePath ;
30+ }
31+
32+ const parentDir = path . resolve ( currentDir , '..' ) ;
33+ // this means we've gotten to the root
34+ if ( currentDir === parentDir ) {
35+ break ;
36+ }
37+ currentDir = parentDir ;
38+ }
39+
40+ return undefined ;
41+ }
842
943/**
1044 * Next requires that plugins be tagged with the same version number as the currently-running `next.js` package, so
@@ -14,27 +48,39 @@ export function syncPluginVersionWithNextVersion(): void {
1448 // TODO Once we get at least to TS 2.9, we can use `"resolveJsonModule": true` in our `compilerOptions` and we'll be
1549 // able to do:
1650 // import { version as nextVersion } from './node_modules/next/package.json';
51+ let nextVersion ;
1752
18- // eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-member-access
19- const nextVersion = ( require ( '../../../../next/package.json' ) as any ) . version ;
20- if ( ! nextVersion ) {
21- logger . error ( '[next-plugin-sentry] Cannot read next.js version. Plug-in will not work.' ) ;
53+ try {
54+ // `require.resolve` returns the location of the packages `"main"` entry point, as specified in its `package.json`
55+ const nextResolvedMain = require . resolve ( 'next' ) ;
56+ // since we don't know where in the package's directory that entry point is, search upward until we find a folder
57+ // containing `package.json`
58+ const nextPackageJsonPath = findUp ( nextResolvedMain , 'package.json' ) ;
59+ nextVersion = nextPackageJsonPath && ( require ( nextPackageJsonPath ) as { version : string } ) . version ;
60+ } catch ( err ) {
61+ // eslint-disable-next-line no-console
62+ console . error ( `[next-plugin-sentry] Cannot read next.js version. Plug-in will not work.\nReceived error: ${ err } ` ) ;
2263 return ;
2364 }
2465
25- const pluginPackageDotJsonPath = `../../../next-plugin-sentry/package.json` ;
26- // eslint-disable-next-line @typescript-eslint/no-var-requires
27- const pluginPackageDotJson = require ( pluginPackageDotJsonPath ) ; // see TODO above
28- if ( ! pluginPackageDotJson ) {
29- logger . error ( `[next-plugin-sentry] Cannot read ${ pluginPackageDotJsonPath } . Plug-in will not work.` ) ;
66+ let pluginPackageJsonPath , pluginPackageJson ;
67+
68+ try {
69+ const pluginResolvedMain = require . resolve ( '@sentry/next-plugin-sentry' ) ;
70+ // see notes above about why we need to call `findUp`
71+ pluginPackageJsonPath = findUp ( pluginResolvedMain , 'package.json' ) ;
72+ pluginPackageJson = pluginPackageJsonPath && require ( pluginPackageJsonPath ) ;
73+ } catch ( err ) {
74+ // eslint-disable-next-line no-console
75+ console . error (
76+ `[next-plugin-sentry] Cannot find \`@sentry/next-plugin-sentry\`. Plug-in will not work. ` +
77+ `Please try reinstalling \`@sentry/nextjs\`.\nReceived error: ${ err } ` ,
78+ ) ;
3079 return ;
3180 }
3281
33- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
34- ( pluginPackageDotJson as any ) . version = nextVersion ;
35- // interestingly, the `require` calls above seem to resolve from a different starting point than `fs` does here, which
36- // is why we can't just use `pluginPackageDotJsonPath` again
37- fs . writeFileSync ( './node_modules/@sentry/next-plugin-sentry/package.json' , JSON . stringify ( pluginPackageDotJson ) ) ;
82+ ( pluginPackageJson as { version : string } ) . version = nextVersion ! ;
83+ fs . writeFileSync ( pluginPackageJsonPath ! , JSON . stringify ( pluginPackageJson ) ) ;
3884}
3985
4086type WebpackConfig = { devtool : string ; plugins : Array < { [ key : string ] : any } > } ;
0 commit comments