-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
[feat] install adapters on demand #7462
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
dd410e4
3e1dffc
76fd805
8beb30a
3f5e992
b832a84
28e8576
faadc0e
7a1e06d
123124a
1aeaaa6
c1afb75
5418d8b
5449fd2
bdaf16f
40ac2af
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| '@sveltejs/adapter-auto': patch | ||
| --- | ||
|
|
||
| [feat] install adapters on demand |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,6 @@ | ||
| import { execSync } from 'child_process'; | ||
| import { dirname } from 'path'; | ||
| import { fileURLToPath } from 'url'; | ||
| import { adapters } from './adapters.js'; | ||
|
|
||
| /** @type {import('./index').default} */ | ||
|
|
@@ -10,31 +13,55 @@ for (const candidate of adapters) { | |
|
|
||
| try { | ||
| module = await import(candidate.module); | ||
|
|
||
| fn = () => { | ||
| const adapter = module.default(); | ||
| return { | ||
| ...adapter, | ||
| adapt: (builder) => { | ||
| builder.log.info(`Detected environment: ${candidate.name}. Using ${candidate.module}`); | ||
| return adapter.adapt(builder); | ||
| } | ||
| }; | ||
| }; | ||
|
|
||
| break; | ||
| } catch (error) { | ||
| if ( | ||
| error.code === 'ERR_MODULE_NOT_FOUND' && | ||
| error.message.startsWith(`Cannot find package '${candidate.module}'`) | ||
| ) { | ||
| throw new Error( | ||
| `It looks like ${candidate.module} is not installed. Please install it and try building your project again.` | ||
| ); | ||
| try { | ||
| console.log(`Installing ${candidate.module} on the fly...`); | ||
| execSync( | ||
| `${process.platform === 'win32' ? 'set' : ''} NODE_ENV=ignore_me && npm install ${ | ||
| candidate.module | ||
| } --no-save --omit=dev --no-package-lock`, | ||
| { | ||
| stdio: 'inherit', | ||
| cwd: dirname(fileURLToPath(import.meta.url)) | ||
| } | ||
| ); | ||
|
||
| module = await import(candidate.module); | ||
| console.log( | ||
| `Successfully installed ${candidate.module} on the fly. If you plan on staying on this deployment platform, consider switching out @sveltejs/adapter-auto for ${candidate.module} for faster and more robust installs.` | ||
| ); | ||
| } catch (e) { | ||
| // if ( | ||
| // error.code === 'ERR_MODULE_NOT_FOUND' && | ||
| // error.message.startsWith(`Cannot find package '${candidate.module}'`) | ||
| // ) { | ||
| throw new Error( | ||
| `Could not install ${candidate.module} on the fly. Please install it yourself by adding it to your package.json's devDependencies and try building your project again.` | ||
| ); | ||
| // } | ||
| // ignore other errors, but print them | ||
| console.warn(e); | ||
| } | ||
| } else { | ||
| throw error; | ||
| } | ||
|
|
||
| throw error; | ||
| } | ||
|
|
||
| fn = () => { | ||
| const adapter = module.default(); | ||
| return { | ||
| ...adapter, | ||
| adapt: (builder) => { | ||
| builder.log.info(`Detected environment: ${candidate.name}. Using ${candidate.module}`); | ||
| return adapter.adapt(builder); | ||
| } | ||
| }; | ||
| }; | ||
|
|
||
| break; | ||
| } | ||
| } | ||
|
|
||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
am suddenly wondering if we should actually be importing the module from the app directory rather than the adapter-auto directory. in most cases it should Just Work, but you can imagine a situation where
adapter-autois installed in the workspace root whileadapter-foois installed inside the appUh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't
candidate.modulejust contain the name of the package, and the resolution algorithm should start at theadapter-autodirectory and look for node_modules there, and if it's there, look for that module there? At least I (try to) use this fact by installing the package into theadapter-autodirectory by runningnpm installinside its directory.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the adapter is a dependency of the app (which it would be, if you'd already installed it) then surely resolution should start from there? (Until
import.meta.resolveis stable, this would need import-meta-resolve)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like this overcomplicates things for no good reason. In what world are you using adapter-auto, but have installed a more specific adapter in another place? You either have them in the same place or switched to the one you actually want to use a long time ago.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not so hard to imagine a situation where shared dependencies are installed in the workspace root but someone installs a one-off dependency in a package — this very repo used to work that way, until we decided to move all dependencies into packages. I also wonder if 'dependencies of
xcan import all other dependencies ofx' is guaranteed across all package managers now and in the future. It's a side-effect of the resolution algorithm plus the way package managers populatenode_modules, but it's the sort of thing that feels changeable, the same way pnpm prevents the npm 3+ behaviour of allowingxto directly import all indirect dependencies