-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(nuxt): Add server config to root folder (#13583)
> This is a draft PR as this approach leads to an error as `hook.mjs` is not included in the `node_modules`. This has been fixed upstream but was not yet released for nuxt. Makes it possible to include a `sentry.server.config.ts` file in the root folder alongside `sentry.client.config.ts`. Currently, it has to be added in the `public` folder which is not 100% ideal.
- Loading branch information
Showing
5 changed files
with
160 additions
and
21 deletions.
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
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,57 @@ | ||
import * as fs from 'fs'; | ||
import * as path from 'path'; | ||
import { createResolver } from '@nuxt/kit'; | ||
import type { Nuxt } from '@nuxt/schema'; | ||
import type { SentryNuxtModuleOptions } from '../common/types'; | ||
|
||
/** | ||
* Adds the `sentry.server.config.ts` file as `sentry.server.config.mjs` to the `.output` directory to be able to reference this file in the node --import option. | ||
* | ||
* 1. Adding the file as a rollup import, so it is included in the build (automatically transpiles the file). | ||
* 2. Copying the file to the `.output` directory after the build process is finished. | ||
*/ | ||
export function addServerConfigToBuild( | ||
moduleOptions: SentryNuxtModuleOptions, | ||
nuxt: Nuxt, | ||
serverConfigFile: string, | ||
): void { | ||
nuxt.hook('vite:extendConfig', async (viteInlineConfig, _env) => { | ||
if ( | ||
typeof viteInlineConfig?.build?.rollupOptions?.input === 'object' && | ||
'server' in viteInlineConfig.build.rollupOptions.input | ||
) { | ||
// Create a rollup entry for the server config to add it as `sentry.server.config.mjs` to the build | ||
(viteInlineConfig.build.rollupOptions.input as { [entryName: string]: string })['sentry.server.config'] = | ||
createResolver(nuxt.options.srcDir).resolve(`/${serverConfigFile}`); | ||
} | ||
|
||
/** | ||
* When the build process is finished, copy the `sentry.server.config` file to the `.output` directory. | ||
* This is necessary because we need to reference this file path in the node --import option. | ||
*/ | ||
nuxt.hook('close', async () => { | ||
const source = path.resolve('.nuxt/dist/server/sentry.server.config.mjs'); | ||
const destination = path.resolve('.output/server/sentry.server.config.mjs'); | ||
|
||
try { | ||
await fs.promises.access(source, fs.constants.F_OK); | ||
await fs.promises.copyFile(source, destination); | ||
|
||
if (moduleOptions.debug) { | ||
// eslint-disable-next-line no-console | ||
console.log( | ||
`[Sentry] Successfully added the content of the \`${serverConfigFile}\` file to \`${destination}\``, | ||
); | ||
} | ||
} catch (error) { | ||
if (moduleOptions.debug) { | ||
// eslint-disable-next-line no-console | ||
console.warn( | ||
`[Sentry] An error occurred when trying to add the \`${serverConfigFile}\` file to the \`.output\` directory`, | ||
error, | ||
); | ||
} | ||
} | ||
}); | ||
}); | ||
} |
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,28 @@ | ||
import * as fs from 'fs'; | ||
import * as path from 'path'; | ||
|
||
/** | ||
* Find the default SDK init file for the given type (client or server). | ||
* The sentry.server.config file is prioritized over the instrument.server file. | ||
*/ | ||
export function findDefaultSdkInitFile(type: 'server' | 'client'): string | undefined { | ||
const possibleFileExtensions = ['ts', 'js', 'mjs', 'cjs', 'mts', 'cts']; | ||
const cwd = process.cwd(); | ||
|
||
const filePaths: string[] = []; | ||
if (type === 'server') { | ||
for (const ext of possibleFileExtensions) { | ||
// order is important here - we want to prioritize the server.config file | ||
filePaths.push(path.join(cwd, `sentry.${type}.config.${ext}`)); | ||
filePaths.push(path.join(cwd, 'public', `instrument.${type}.${ext}`)); | ||
} | ||
} else { | ||
for (const ext of possibleFileExtensions) { | ||
filePaths.push(path.join(cwd, `sentry.${type}.config.${ext}`)); | ||
} | ||
} | ||
|
||
const filePath = filePaths.find(filename => fs.existsSync(filename)); | ||
|
||
return filePath ? path.basename(filePath) : undefined; | ||
} |
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,61 @@ | ||
import * as fs from 'fs'; | ||
import { afterEach, describe, expect, it, vi } from 'vitest'; | ||
import { findDefaultSdkInitFile } from '../../src/vite/utils'; | ||
|
||
vi.mock('fs'); | ||
|
||
describe('findDefaultSdkInitFile', () => { | ||
afterEach(() => { | ||
vi.clearAllMocks(); | ||
}); | ||
|
||
it.each(['ts', 'js', 'mjs', 'cjs', 'mts', 'cts'])( | ||
'should return the server file with .%s extension if it exists', | ||
ext => { | ||
vi.spyOn(fs, 'existsSync').mockImplementation(filePath => { | ||
return !(filePath instanceof URL) && filePath.includes(`sentry.server.config.${ext}`); | ||
}); | ||
|
||
const result = findDefaultSdkInitFile('server'); | ||
expect(result).toBe(`sentry.server.config.${ext}`); | ||
}, | ||
); | ||
|
||
it.each(['ts', 'js', 'mjs', 'cjs', 'mts', 'cts'])( | ||
'should return the client file with .%s extension if it exists', | ||
ext => { | ||
vi.spyOn(fs, 'existsSync').mockImplementation(filePath => { | ||
return !(filePath instanceof URL) && filePath.includes(`sentry.client.config.${ext}`); | ||
}); | ||
|
||
const result = findDefaultSdkInitFile('client'); | ||
expect(result).toBe(`sentry.client.config.${ext}`); | ||
}, | ||
); | ||
|
||
it('should return undefined if no file with specified extensions exists', () => { | ||
vi.spyOn(fs, 'existsSync').mockReturnValue(false); | ||
|
||
const result = findDefaultSdkInitFile('server'); | ||
expect(result).toBeUndefined(); | ||
}); | ||
|
||
it('should return undefined if no file exists', () => { | ||
vi.spyOn(fs, 'existsSync').mockReturnValue(false); | ||
|
||
const result = findDefaultSdkInitFile('server'); | ||
expect(result).toBeUndefined(); | ||
}); | ||
|
||
it('should return the server config file if server.config and instrument exist', () => { | ||
vi.spyOn(fs, 'existsSync').mockImplementation(filePath => { | ||
return ( | ||
!(filePath instanceof URL) && | ||
(filePath.includes('sentry.server.config.js') || filePath.includes('instrument.server.js')) | ||
); | ||
}); | ||
|
||
const result = findDefaultSdkInitFile('server'); | ||
expect(result).toBe('sentry.server.config.js'); | ||
}); | ||
}); |