diff --git a/.changeset/famous-points-switch.md b/.changeset/famous-points-switch.md new file mode 100644 index 000000000000..1ea3c3ba3d40 --- /dev/null +++ b/.changeset/famous-points-switch.md @@ -0,0 +1,6 @@ +--- +'@sveltejs/adapter-auto': patch +'@sveltejs/kit': patch +--- + +chore: remove `import-meta-resolve` dependency diff --git a/packages/adapter-auto/index.js b/packages/adapter-auto/index.js index c83ba6246c59..f6b113b49e8a 100644 --- a/packages/adapter-auto/index.js +++ b/packages/adapter-auto/index.js @@ -1,9 +1,7 @@ import { execSync } from 'node:child_process'; -import { pathToFileURL } from 'node:url'; -import { resolve } from 'import-meta-resolve'; import { adapters } from './adapters.js'; -import { dirname, join } from 'node:path'; -import { existsSync } from 'node:fs'; +import path from 'node:path'; +import fs from 'node:fs'; import process from 'node:process'; /** @type {Record string>} */ @@ -17,12 +15,15 @@ const commands = { function detect_lockfile() { let dir = process.cwd(); + /** @param {string} file */ + const exists = (file) => fs.existsSync(path.join(dir, file)); + do { - if (existsSync(join(dir, 'pnpm-lock.yaml'))) return 'pnpm'; - if (existsSync(join(dir, 'yarn.lock'))) return 'yarn'; - if (existsSync(join(dir, 'package-lock.json'))) return 'npm'; - if (existsSync(join(dir, 'bun.lockb')) || existsSync(join(dir, 'bun.lock'))) return 'bun'; - } while (dir !== (dir = dirname(dir))); + if (exists('pnpm-lock.yaml')) return 'pnpm'; + if (exists('yarn.lock')) return 'yarn'; + if (exists('package-lock.json')) return 'npm'; + if (exists('bun.lockb') || exists('bun.lock')) return 'bun'; + } while (dir !== (dir = path.dirname(dir))); return 'npm'; } @@ -38,12 +39,40 @@ function detect_package_manager() { } } -/** @param {string} name */ -function import_from_cwd(name) { - const cwd = pathToFileURL(process.cwd()).href; - const url = resolve(name, cwd + '/x.js'); +/** + * Resolves a peer dependency relative to the current CWD. Duplicated with `packages/kit` + * @param {string} dependency + */ +function resolve_peer(dependency) { + let [name, ...parts] = dependency.split('/'); + if (name[0] === '@') name += `/${parts.shift()}`; + + let dir = process.cwd(); + + while (!fs.existsSync(`${dir}/node_modules/${name}/package.json`)) { + if (dir === (dir = path.dirname(dir))) { + throw new Error( + `Could not resolve peer dependency "${name}" relative to your project — please install it and try again.` + ); + } + } + + const pkg_dir = `${dir}/node_modules/${name}`; + const pkg = JSON.parse(fs.readFileSync(`${pkg_dir}/package.json`, 'utf-8')); + + const subpackage = ['.', ...parts].join('/'); + + let exported = pkg.exports[subpackage]; + + while (typeof exported !== 'string') { + if (!exported) { + throw new Error(`Could not find valid "${subpackage}" export in ${name}/package.json`); + } + + exported = exported['import'] ?? exported['default']; + } - return import(url); + return path.resolve(pkg_dir, exported); } /** @typedef {import('@sveltejs/kit').Adapter} Adapter */ @@ -56,47 +85,43 @@ async function get_adapter() { if (!match) return; - /** @type {{ default: () => Adapter }} */ - let module; + /** @type {string} */ + let resolved; try { - module = await import_from_cwd(match.module); - } catch (error) { - if ( - error.code === 'ERR_MODULE_NOT_FOUND' && - error.message.startsWith(`Cannot find package '${match.module}'`) - ) { - const package_manager = detect_package_manager(); - const command = commands[package_manager](match.module, match.version); - - try { - console.log(`Installing ${match.module}...`); - - execSync(command, { - stdio: 'inherit', - env: { - ...process.env, - NODE_ENV: undefined - } - }); - - module = await import_from_cwd(match.module); - - console.log(`Successfully installed ${match.module}.`); - console.warn( - `\nIf you plan on staying on this deployment platform, consider replacing @sveltejs/adapter-auto with ${match.module}. This will give you faster and more robust installs, and more control over deployment configuration.\n` - ); - } catch (e) { - throw new Error( - `Could not install ${match.module}. Please install it yourself by adding it to your package.json's devDependencies and try building your project again.`, - { cause: e } - ); - } - } else { - throw error; + resolved = resolve_peer(match.module); + } catch { + const package_manager = detect_package_manager(); + const command = commands[package_manager](match.module, match.version); + + try { + console.log(`Installing ${match.module}...`); + + execSync(command, { + stdio: 'inherit', + env: { + ...process.env, + NODE_ENV: undefined + } + }); + + resolved = resolve_peer(match.module); + + console.log(`Successfully installed ${match.module}.`); + console.warn( + `\nIf you plan on staying on this deployment platform, consider replacing @sveltejs/adapter-auto with ${match.module}. This will give you faster and more robust installs, and more control over deployment configuration.\n` + ); + } catch (e) { + throw new Error( + `Could not install ${match.module}. Please install it yourself by adding it to your package.json's devDependencies and try building your project again.`, + { cause: e } + ); } } + /** @type {{ default: () => Adapter }} */ + const module = await import(resolved); + const adapter = module.default(); return { diff --git a/packages/adapter-auto/package.json b/packages/adapter-auto/package.json index f92ae66ecc77..6a7c6209cdc9 100644 --- a/packages/adapter-auto/package.json +++ b/packages/adapter-auto/package.json @@ -46,9 +46,6 @@ "typescript": "^5.3.3", "vitest": "^3.0.1" }, - "dependencies": { - "import-meta-resolve": "^4.1.0" - }, "peerDependencies": { "@sveltejs/kit": "^2.0.0" } diff --git a/packages/kit/package.json b/packages/kit/package.json index 105470b94170..cd3d192eaff1 100644 --- a/packages/kit/package.json +++ b/packages/kit/package.json @@ -22,7 +22,6 @@ "cookie": "^0.6.0", "devalue": "^5.1.0", "esm-env": "^1.2.2", - "import-meta-resolve": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", diff --git a/packages/kit/src/core/sync/utils.js b/packages/kit/src/core/sync/utils.js index 304e9180a77b..be3ecc22b347 100644 --- a/packages/kit/src/core/sync/utils.js +++ b/packages/kit/src/core/sync/utils.js @@ -1,10 +1,10 @@ import fs from 'node:fs'; import path from 'node:path'; import { mkdirp } from '../../utils/filesystem.js'; -import { resolve_peer_dependency } from '../../utils/import.js'; +import { import_peer } from '../../utils/import.js'; /** @type {{ VERSION: string }} */ -const { VERSION } = await resolve_peer_dependency('svelte/compiler'); +const { VERSION } = await import_peer('svelte/compiler'); /** @type {Map} */ const previous_contents = new Map(); diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index bdb37b1f9cff..8eaa0f513aac 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -34,7 +34,7 @@ import { sveltekit_paths, sveltekit_server } from './module_ids.js'; -import { resolve_peer_dependency } from '../../utils/import.js'; +import { import_peer } from '../../utils/import.js'; import { compact } from '../../utils/array.js'; const cwd = process.cwd(); @@ -155,7 +155,7 @@ export async function sveltekit() { ...svelte_config.vitePlugin }; - const { svelte } = await resolve_peer_dependency('@sveltejs/vite-plugin-svelte'); + const { svelte } = await import_peer('@sveltejs/vite-plugin-svelte'); return [...svelte(vite_plugin_svelte_options), ...(await kit({ svelte_config }))]; } @@ -181,7 +181,7 @@ let manifest_data; * @return {Promise} */ async function kit({ svelte_config }) { - const vite = await resolve_peer_dependency('vite'); + const vite = await import_peer('vite'); const { kit } = svelte_config; const out = `${kit.outDir}/output`; diff --git a/packages/kit/src/utils/import.js b/packages/kit/src/utils/import.js index 4a8e92971f16..3ed96fa46484 100644 --- a/packages/kit/src/utils/import.js +++ b/packages/kit/src/utils/import.js @@ -1,25 +1,52 @@ -import * as imr from 'import-meta-resolve'; import process from 'node:process'; -import { pathToFileURL } from 'node:url'; +import fs from 'node:fs'; +import path from 'node:path'; + +/** + * Resolves a peer dependency relative to the current CWD. Duplicated with `packages/adapter-auto` + * @param {string} dependency + */ +function resolve_peer(dependency) { + let [name, ...parts] = dependency.split('/'); + if (name[0] === '@') name += `/${parts.shift()}`; + + let dir = process.cwd(); + + while (!fs.existsSync(`${dir}/node_modules/${name}/package.json`)) { + if (dir === (dir = path.dirname(dir))) { + throw new Error( + `Could not resolve peer dependency "${name}" relative to your project — please install it and try again.` + ); + } + } + + const pkg_dir = `${dir}/node_modules/${name}`; + const pkg = JSON.parse(fs.readFileSync(`${pkg_dir}/package.json`, 'utf-8')); + + const subpackage = ['.', ...parts].join('/'); + + let exported = pkg.exports[subpackage]; + + while (typeof exported !== 'string') { + if (!exported) { + throw new Error(`Could not find valid "${subpackage}" export in ${name}/package.json`); + } + + exported = exported['import'] ?? exported['default']; + } + + return path.resolve(pkg_dir, exported); +} /** * Resolve a dependency relative to the current working directory, * rather than relative to this package (but falls back to trying that, if necessary) * @param {string} dependency */ -export async function resolve_peer_dependency(dependency) { +export async function import_peer(dependency) { try { - // @ts-expect-error the types are wrong - const resolved = imr.resolve(dependency, pathToFileURL(process.cwd() + '/dummy.js')); - return await import(resolved); + return await import(resolve_peer(dependency)); } catch { - try { - // both imr.resolve and await import above can throw, which is why we can't just do import(resolved).catch(...) above - return await import(dependency); - } catch { - throw new Error( - `Could not resolve peer dependency "${dependency}" relative to your project — please install it and try again.` - ); - } + return await import(dependency); } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fb5fae117180..aff37f5116cb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -34,10 +34,6 @@ importers: version: 8.26.0(eslint@9.6.0)(typescript@5.6.3) packages/adapter-auto: - dependencies: - import-meta-resolve: - specifier: ^4.1.0 - version: 4.1.0 devDependencies: '@sveltejs/kit': specifier: workspace:^ @@ -351,9 +347,6 @@ importers: esm-env: specifier: ^1.2.2 version: 1.2.2 - import-meta-resolve: - specifier: ^4.1.0 - version: 4.1.0 kleur: specifier: ^4.1.5 version: 4.1.5 @@ -2560,9 +2553,6 @@ packages: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} - import-meta-resolve@4.1.0: - resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} - imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -4938,8 +4928,6 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 - import-meta-resolve@4.1.0: {} - imurmurhash@0.1.4: {} is-arrayish@0.3.2: {}