1
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
+ /* eslint-disable @typescript-eslint/no-var-requires */
1
3
/* eslint-disable @typescript-eslint/no-explicit-any */
2
- // import { version as nextVersion } from './node_modules/next/package.json';
3
4
import { getSentryRelease } from '@sentry/node' ;
4
5
import { logger } from '@sentry/utils' ;
5
6
import defaultWebpackPlugin , { SentryCliPluginOptions } from '@sentry/webpack-plugin' ;
6
7
import * as SentryWebpackPlugin from '@sentry/webpack-plugin' ;
7
8
import * 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
+ }
8
42
9
43
/**
10
44
* 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 {
14
48
// TODO Once we get at least to TS 2.9, we can use `"resolveJsonModule": true` in our `compilerOptions` and we'll be
15
49
// able to do:
16
50
// import { version as nextVersion } from './node_modules/next/package.json';
51
+ let nextVersion ;
17
52
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 } ` ) ;
22
63
return ;
23
64
}
24
65
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
+ ) ;
30
79
return ;
31
80
}
32
81
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 ) ) ;
38
84
}
39
85
40
86
type WebpackConfig = { devtool : string ; plugins : Array < { [ key : string ] : any } > } ;
0 commit comments