0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-02-17 22:44:24 -05:00

fix: use virtual import for storage drivers (#12520)

* fix: use virtual import for storage drivers

* Don't try to resolve anythign in build

* Fix test

* Polyfill node:url

* Handle custom drivers directly

* No need for path

* Update packages/astro/src/core/session.ts

Co-authored-by: Emanuele Stoppa <my.burning@gmail.com>

---------

Co-authored-by: Emanuele Stoppa <my.burning@gmail.com>
This commit is contained in:
Matt Kane 2024-11-25 13:59:03 +00:00 committed by GitHub
parent 82551aeef5
commit 763489842b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 63 additions and 9 deletions

View file

@ -33,6 +33,7 @@ import markdownVitePlugin from '../vite-plugin-markdown/index.js';
import astroScannerPlugin from '../vite-plugin-scanner/index.js';
import astroScriptsPlugin from '../vite-plugin-scripts/index.js';
import astroScriptsPageSSRPlugin from '../vite-plugin-scripts/page-ssr.js';
import vitePluginSessions from '../vite-plugin-sessions/index.js';
import { vitePluginSSRManifest } from '../vite-plugin-ssr-manifest/index.js';
import type { SSRManifest } from './app/types.js';
import type { Logger } from './logger/core.js';
@ -143,6 +144,7 @@ export async function createVite(
astroLoadFallbackPlugin({ fs, root: settings.config.root }),
astroVitePlugin({ settings, logger }),
astroScriptsPlugin({ settings }),
vitePluginSessions({ settings }),
// The server plugin is for dev only and having it run during the build causes
// the build to run very slow as the filewatcher is triggered often.
command === 'dev' && vitePluginAstroServer({ settings, logger, fs, manifest, ssrManifest }), // ssrManifest is only required in dev mode, where it gets created before a Vite instance is created, and get passed to this function

View file

@ -344,7 +344,7 @@ export class AstroSession<TDriver extends SessionDriverName = any> {
* Ensures the storage is initialized.
* This is called automatically when a storage operation is needed.
*/
async #ensureStorage():Promise<Storage> {
async #ensureStorage(): Promise<Storage> {
if (this.#storage) {
return this.#storage;
}
@ -363,13 +363,22 @@ export class AstroSession<TDriver extends SessionDriverName = any> {
}
let driver: ((config: SessionConfig<TDriver>['options']) => Driver) | null = null;
const entry =
builtinDrivers[this.#config.driver as keyof typeof builtinDrivers] || this.#config.driver;
try {
const isBuiltin = this.#config.driver in builtinDrivers;
// Try to load the driver from the built-in unstorage drivers.
// Otherwise, assume it's a custom driver and load by name.
const driverPackage: string = isBuiltin
? builtinDrivers[this.#config.driver as keyof typeof builtinDrivers]
: this.#config.driver;
driver = await import(entry).then((r) => r.default || r);
try {
// If driver is not a builtin, or in development or test, load the driver directly.
if (!isBuiltin || process.env.NODE_ENV === 'development' || process.env.NODE_TEST_CONTEXT) {
driver = await import(/* @vite-ignore */ driverPackage).then((r) => r.default || r);
} else {
// In production, load via the virtual module as it will be bundled by Vite
// @ts-expect-error - virtual module
driver = await import('@astro-session-driver').then((r) => r.default || r);
}
} catch (err: any) {
// If the driver failed to load, throw an error.
if (err.code === 'ERR_MODULE_NOT_FOUND') {
@ -377,7 +386,7 @@ export class AstroSession<TDriver extends SessionDriverName = any> {
{
...SessionStorageInitError,
message: SessionStorageInitError.message(
err.message.includes(`Cannot find package '${entry}'`)
err.message.includes(`Cannot find package '${driverPackage}'`)
? 'The driver module could not be found.'
: err.message,
this.#config.driver,

View file

@ -0,0 +1,43 @@
import { fileURLToPath } from 'node:url';
import { builtinDrivers } from 'unstorage';
import type { Plugin as VitePlugin } from 'vite';
import type { AstroSettings } from '../types/astro.js';
const SESSION_DRIVER_ID = '@astro-session-driver';
const RESOLVED_SESSION_DRIVER_ID = `\0${SESSION_DRIVER_ID}`;
export default function vitePluginSessions({ settings }: { settings: AstroSettings }): VitePlugin {
return {
name: 'astro:vite-plugin-sessions',
enforce: 'pre',
async resolveId(source) {
if (source === SESSION_DRIVER_ID) {
return RESOLVED_SESSION_DRIVER_ID;
}
// Resolve the driver entrypoint so that we bundle it
if (source.startsWith('unstorage/drivers/')) {
return fileURLToPath(import.meta.resolve(source));
}
},
async load(id) {
if (id === RESOLVED_SESSION_DRIVER_ID) {
let driver = settings.config.experimental?.session?.driver;
if (driver && driver in builtinDrivers) {
if (driver === 'fs') {
// fs tries to bundle chokidar (and therefore fsevents), which is a binary
driver = 'fsLite';
}
driver = builtinDrivers[driver as keyof typeof builtinDrivers];
}
if (!driver) {
return `export default function driver() { return null }`;
}
const resolved = await this.resolve(driver, undefined, { skipSelf: false });
if (!resolved) {
throw new Error(`Could not resolve session driver ${driver}`);
}
return `export { default } from ${JSON.stringify(resolved?.id)};`;
}
},
};
}

View file

@ -9,7 +9,7 @@ export default defineConfig({
output: 'server',
experimental: {
session: {
driver: 'fs',
driver: 'fsLite',
options: {
base: join(tmpdir(), 'sessions'),
},