-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
[feat] install adapters on demand #7462
Changes from 1 commit
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,39 @@ 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 { | ||
execSync( | ||
`echo "Installing ${candidate.module}" && npm install ${candidate.module} --no-save --no-package-lock`, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TIL Should we add a message along the lines of 'you should add this to your package.json for faster build times in future?' There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That'd only help people who look at the build logs, right? I wonder how many people that is. Also, is there a reason for the If we get rid of that, can we do something with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the advantage to that? The current approach forwards the output to the main shell, so it could help in case something goes wrong. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
a small number, but larger than zero
We'd still pipe Also There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. tried switching to it, can't switch because windows can't execute npm without the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we have |
||
{ stdio: 'inherit', cwd: dirname(fileURLToPath(import.meta.url)) } | ||
); | ||
module = await import(candidate.module); | ||
} catch (e) { | ||
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.` | ||
); | ||
} | ||
} | ||
|
||
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; | ||
} | ||
} | ||
|
||
|
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-auto
is installed in the workspace root whileadapter-foo
is installed inside the appThere 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.module
just contain the name of the package, and the resolution algorithm should start at theadapter-auto
directory 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-auto
directory by runningnpm install
inside 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.resolve
is 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
x
can 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 allowingx
to directly import all indirect dependencies