Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(sveltekit): Auto-detect SvelteKit adapters (#8193)
First step for Vercel support: Detecting the used SvelteKit adapter. (This currently does nothing other than detecting the adapter; next step is to configure the source maps plugin correctly for the respective adapters) ref #8085
- Loading branch information
Showing
5 changed files
with
172 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import type { Package } from '@sentry/types'; | ||
import * as fs from 'fs'; | ||
import * as path from 'path'; | ||
|
||
/** | ||
* Supported @sveltejs/adapters-[adapter] SvelteKit adapters | ||
*/ | ||
export type SupportedSvelteKitAdapters = 'node' | 'auto' | 'vercel' | 'other'; | ||
|
||
/** | ||
* Tries to detect the used adapter for SvelteKit by looking at the dependencies. | ||
* returns the name of the adapter or 'other' if no supported adapter was found. | ||
*/ | ||
export async function detectAdapter(debug?: boolean): Promise<SupportedSvelteKitAdapters> { | ||
const pkgJson = await loadPackageJson(); | ||
|
||
const allDependencies = pkgJson ? { ...pkgJson.dependencies, ...pkgJson.devDependencies } : {}; | ||
|
||
let adapter: SupportedSvelteKitAdapters = 'other'; | ||
if (allDependencies['@sveltejs/adapter-vercel']) { | ||
adapter = 'vercel'; | ||
} else if (allDependencies['@sveltejs/adapter-node']) { | ||
adapter = 'node'; | ||
} else if (allDependencies['@sveltejs/adapter-auto']) { | ||
adapter = 'auto'; | ||
} | ||
|
||
if (debug) { | ||
if (adapter === 'other') { | ||
// eslint-disable-next-line no-console | ||
console.warn( | ||
"[Sentry SvelteKit Plugin] Couldn't detect SvelteKit adapter. Please set the 'adapter' option manually.", | ||
); | ||
} else { | ||
// eslint-disable-next-line no-console | ||
console.log(`[Sentry SvelteKit Plugin] Detected SvelteKit ${adapter} adapter`); | ||
} | ||
} | ||
|
||
return adapter; | ||
} | ||
|
||
/** | ||
* Imports the pacakge.json file and returns the parsed JSON object. | ||
*/ | ||
async function loadPackageJson(): Promise<Package | undefined> { | ||
const pkgFile = path.join(process.cwd(), 'package.json'); | ||
|
||
try { | ||
if (!fs.existsSync(pkgFile)) { | ||
throw new Error(`File ${pkgFile} doesn't exist}`); | ||
} | ||
|
||
const pkgJsonContent = (await fs.promises.readFile(pkgFile, 'utf-8')).toString(); | ||
|
||
return JSON.parse(pkgJsonContent); | ||
} catch (e) { | ||
// eslint-disable-next-line no-console | ||
console.warn("[Sentry SvelteKit Plugin] Couldn't load package.json:", e); | ||
return 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
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,79 @@ | ||
import { vi } from 'vitest'; | ||
|
||
import { detectAdapter } from '../../src/vite/detectAdapter'; | ||
|
||
let existsFile = true; | ||
const pkgJson = { | ||
dependencies: {}, | ||
}; | ||
describe('detectAdapter', () => { | ||
beforeEach(() => { | ||
existsFile = true; | ||
vi.clearAllMocks(); | ||
pkgJson.dependencies = {}; | ||
}); | ||
|
||
vi.mock('fs', () => { | ||
return { | ||
existsSync: () => existsFile, | ||
promises: { | ||
readFile: () => { | ||
return Promise.resolve(JSON.stringify(pkgJson)); | ||
}, | ||
}, | ||
}; | ||
}); | ||
|
||
const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); | ||
const consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); | ||
|
||
it.each(['auto', 'vercel', 'node'])( | ||
'returns the adapter name (adapter %s) and logs it to the console', | ||
async adapter => { | ||
pkgJson.dependencies[`@sveltejs/adapter-${adapter}`] = '1.0.0'; | ||
const detectedAdapter = await detectAdapter(true); | ||
expect(detectedAdapter).toEqual(adapter); | ||
expect(consoleLogSpy).toHaveBeenCalledTimes(1); | ||
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining(`Detected SvelteKit ${adapter} adapter`)); | ||
}, | ||
); | ||
|
||
it('returns "other" if no supported adapter was found', async () => { | ||
pkgJson.dependencies['@sveltejs/adapter-netlify'] = '1.0.0'; | ||
const detectedAdapter = await detectAdapter(); | ||
expect(detectedAdapter).toEqual('other'); | ||
}); | ||
|
||
it('logs a warning if in debug mode and no supported adapter was found', async () => { | ||
pkgJson.dependencies['@sveltejs/adapter-netlify'] = '1.0.0'; | ||
const detectedAdapter = await detectAdapter(true); | ||
expect(detectedAdapter).toEqual('other'); | ||
expect(consoleWarnSpy).toHaveBeenCalledTimes(1); | ||
expect(consoleWarnSpy).toHaveBeenCalledWith(expect.stringContaining("Couldn't detect SvelteKit adapter")); | ||
}); | ||
|
||
it('returns "other" if package.json isnt available and emits a warning log', async () => { | ||
existsFile = false; | ||
const detectedAdapter = await detectAdapter(); | ||
expect(detectedAdapter).toEqual('other'); | ||
|
||
expect(consoleWarnSpy).toHaveBeenCalledTimes(1); | ||
expect(consoleWarnSpy).toHaveBeenCalledWith( | ||
expect.stringContaining("Couldn't load package.json"), | ||
expect.any(Error), | ||
); | ||
}); | ||
|
||
it('prefers all other adapters over adapter auto', async () => { | ||
pkgJson.dependencies['@sveltejs/adapter-auto'] = '1.0.0'; | ||
pkgJson.dependencies['@sveltejs/adapter-vercel'] = '1.0.0'; | ||
pkgJson.dependencies['@sveltejs/adapter-node'] = '1.0.0'; | ||
|
||
const detectedAdapter = await detectAdapter(); | ||
expect(detectedAdapter).toEqual('vercel'); | ||
|
||
delete pkgJson.dependencies['@sveltejs/adapter-vercel']; | ||
const detectedAdapter2 = await detectAdapter(); | ||
expect(detectedAdapter2).toEqual('node'); | ||
}); | ||
}); |
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