Skip to content

Commit 79ca864

Browse files
committed
use require.resolve() plus upward search to find relevant files
1 parent 01b3f3a commit 79ca864

File tree

1 file changed

+54
-15
lines changed

1 file changed

+54
-15
lines changed

packages/nextjs/src/utils/config.ts

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,37 @@
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';
34
import { getSentryRelease } from '@sentry/node';
45
import { logger } from '@sentry/utils';
56
import defaultWebpackPlugin, { SentryCliPluginOptions } from '@sentry/webpack-plugin';
67
import * as SentryWebpackPlugin from '@sentry/webpack-plugin';
78
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+
let currentDir = fs.statSync(startPath).isFile() ? path.dirname(startPath) : startPath;
24+
while (currentDir !== '/') {
25+
const possiblePath = path.join(currentDir, searchFile);
26+
if (fs.existsSync(possiblePath)) {
27+
return possiblePath;
28+
}
29+
30+
currentDir = path.join(currentDir, '..');
31+
}
32+
33+
return undefined;
34+
}
835

936
/**
1037
* Next requires that plugins be tagged with the same version number as the currently-running `next.js` package, so
@@ -14,27 +41,39 @@ export function syncPluginVersionWithNextVersion(): void {
1441
// TODO Once we get at least to TS 2.9, we can use `"resolveJsonModule": true` in our `compilerOptions` and we'll be
1542
// able to do:
1643
// import { version as nextVersion } from './node_modules/next/package.json';
44+
let nextVersion;
1745

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.');
46+
try {
47+
// `require.resolve` returns the location of the packages `"main"` entry point, as specified in its `package.json`
48+
const nextResolvedMain = require.resolve('next');
49+
// since we don't know where in the package's directory that entry point is, search upward until we find a folder
50+
// containing `package.json`
51+
const nextPackageJsonPath = findUp(nextResolvedMain, 'package.json');
52+
nextVersion = nextPackageJsonPath && (require(nextPackageJsonPath) as { version: string }).version;
53+
} catch (err) {
54+
// eslint-disable-next-line no-console
55+
console.error(`[next-plugin-sentry] Cannot read next.js version. Plug-in will not work.\nReceived error: ${err}`);
2256
return;
2357
}
2458

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.`);
59+
let pluginPackageJsonPath, pluginPackageJson;
60+
61+
try {
62+
const pluginResolvedMain = require.resolve('@sentry/next-plugin-sentry');
63+
// see notes above about why we need to call `findUp`
64+
pluginPackageJsonPath = findUp(pluginResolvedMain, 'package.json');
65+
pluginPackageJson = pluginPackageJsonPath && require(pluginPackageJsonPath);
66+
} catch (err) {
67+
// eslint-disable-next-line no-console
68+
console.error(
69+
`[next-plugin-sentry] Cannot find \`@sentry/next-plugin-sentry\`. Plug-in will not work. ` +
70+
`Please try reinstalling \`@sentry/nextjs\`.\nReceived error: ${err}`,
71+
);
3072
return;
3173
}
3274

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));
75+
(pluginPackageJson as { version: string }).version = nextVersion!;
76+
fs.writeFileSync(pluginPackageJsonPath!, JSON.stringify(pluginPackageJson));
3877
}
3978

4079
type WebpackConfig = { devtool: string; plugins: Array<{ [key: string]: any }> };

0 commit comments

Comments
 (0)