From 7c012b64f486010c4aab37e86439e4137010698b Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Mon, 22 Apr 2024 09:49:50 -0400 Subject: [PATCH 1/6] Prevent getCollection from breaking in vitest --- .changeset/sweet-coins-shop.md | 5 +++++ packages/astro/src/assets/utils/emitAsset.ts | 5 +++-- packages/astro/src/assets/vite-plugin-assets.ts | 6 +++++- packages/astro/src/content/runtime-assets.ts | 5 +++-- packages/astro/src/content/utils.ts | 3 ++- .../astro/src/content/vite-plugin-content-imports.ts | 11 ++++++++++- 6 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 .changeset/sweet-coins-shop.md diff --git a/.changeset/sweet-coins-shop.md b/.changeset/sweet-coins-shop.md new file mode 100644 index 000000000000..02d69af15c6e --- /dev/null +++ b/.changeset/sweet-coins-shop.md @@ -0,0 +1,5 @@ +--- +"astro": patch +--- + +Prevent getCollection breaking in vitest diff --git a/packages/astro/src/assets/utils/emitAsset.ts b/packages/astro/src/assets/utils/emitAsset.ts index 545299605c7f..d049e065d042 100644 --- a/packages/astro/src/assets/utils/emitAsset.ts +++ b/packages/astro/src/assets/utils/emitAsset.ts @@ -8,7 +8,8 @@ import { imageMetadata } from './metadata.js'; export async function emitESMImage( id: string | undefined, watchMode: boolean, - fileEmitter: any + fileEmitter: any, + viteMode: string = '', ): Promise { if (!id) { return undefined; @@ -37,7 +38,7 @@ export async function emitESMImage( }); // Build - if (!watchMode) { + if (!watchMode && viteMode !== 'test') { const pathname = decodeURI(url.pathname); const filename = path.basename(pathname, path.extname(pathname) + `.${fileMetadata.format}`); diff --git a/packages/astro/src/assets/vite-plugin-assets.ts b/packages/astro/src/assets/vite-plugin-assets.ts index 03a9bef29fad..48870212ff21 100644 --- a/packages/astro/src/assets/vite-plugin-assets.ts +++ b/packages/astro/src/assets/vite-plugin-assets.ts @@ -95,6 +95,7 @@ export default function assets({ mode, }: AstroPluginOptions & { mode: string }): vite.Plugin[] { let resolvedConfig: vite.ResolvedConfig; + let viteMode: string; globalThis.astroAsset = { referencedImages: new Set(), @@ -194,6 +195,9 @@ export default function assets({ { name: 'astro:assets:esm', enforce: 'pre', + config(config, { mode }) { + viteMode = mode; + }, configResolved(viteConfig) { resolvedConfig = viteConfig; }, @@ -214,7 +218,7 @@ export default function assets({ return; } - const imageMetadata = await emitESMImage(id, this.meta.watchMode, this.emitFile); + const imageMetadata = await emitESMImage(id, this.meta.watchMode, this.emitFile, viteMode); if (!imageMetadata) { throw new AstroError({ diff --git a/packages/astro/src/content/runtime-assets.ts b/packages/astro/src/content/runtime-assets.ts index a34d71bab738..afb8e5e21deb 100644 --- a/packages/astro/src/content/runtime-assets.ts +++ b/packages/astro/src/content/runtime-assets.ts @@ -2,14 +2,15 @@ import type { PluginContext } from 'rollup'; import { z } from 'zod'; import { emitESMImage } from '../assets/utils/emitAsset.js'; -export function createImage(pluginContext: PluginContext, entryFilePath: string) { +export function createImage(pluginContext: PluginContext, viteMode: string, entryFilePath: string) { return () => { return z.string().transform(async (imagePath, ctx) => { const resolvedFilePath = (await pluginContext.resolve(imagePath, entryFilePath))?.id; const metadata = await emitESMImage( resolvedFilePath, pluginContext.meta.watchMode, - pluginContext.emitFile + pluginContext.emitFile, + viteMode, ); if (!metadata) { diff --git a/packages/astro/src/content/utils.ts b/packages/astro/src/content/utils.ts index f40de3ff9874..fd131a089d93 100644 --- a/packages/astro/src/content/utils.ts +++ b/packages/astro/src/content/utils.ts @@ -92,6 +92,7 @@ export async function getEntryData( _internal: EntryInternal; }, collectionConfig: CollectionConfig, + viteMode: string, pluginContext: PluginContext ) { let data; @@ -105,7 +106,7 @@ export async function getEntryData( let schema = collectionConfig.schema; if (typeof schema === 'function') { schema = schema({ - image: createImage(pluginContext, entry._internal.filePath), + image: createImage(pluginContext, viteMode, entry._internal.filePath), }); } diff --git a/packages/astro/src/content/vite-plugin-content-imports.ts b/packages/astro/src/content/vite-plugin-content-imports.ts index be232eb07cf6..31adb6e92bb4 100644 --- a/packages/astro/src/content/vite-plugin-content-imports.ts +++ b/packages/astro/src/content/vite-plugin-content-imports.ts @@ -74,10 +74,14 @@ export function astroContentImportPlugin({ const contentEntryConfigByExt = getEntryConfigByExtMap(settings.contentEntryTypes); const dataEntryConfigByExt = getEntryConfigByExtMap(settings.dataEntryTypes); const { contentDir } = contentPaths; + let viteMode: string; const plugins: Plugin[] = [ { name: 'astro:content-imports', + config(config, env) { + viteMode = env.mode; + }, async transform(_, viteId) { if (hasContentFlag(viteId, DATA_FLAG)) { const fileId = viteId.split('?')[0] ?? viteId; @@ -90,6 +94,7 @@ export function astroContentImportPlugin({ config: settings.config, fs, pluginContext: this, + viteMode, }); const code = ` @@ -112,6 +117,7 @@ export const _internal = { config: settings.config, fs, pluginContext: this, + viteMode, }); const code = ` @@ -190,6 +196,7 @@ type GetEntryModuleParams = pluginContext: PluginContext; entryConfigByExt: Map; config: AstroConfig; + viteMode: string; }; async function getContentEntryModule( @@ -222,6 +229,7 @@ async function getContentEntryModule( ? await getEntryData( { id, collection, _internal, unvalidatedData }, collectionConfig, + params.viteMode, pluginContext ) : unvalidatedData; @@ -256,7 +264,8 @@ async function getDataEntryModule( ? await getEntryData( { id, collection, _internal, unvalidatedData }, collectionConfig, - pluginContext + params.viteMode, + pluginContext, ) : unvalidatedData; From fc0157f02318664140ec943e4ceeb8fe8f694def Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Mon, 22 Apr 2024 10:11:47 -0400 Subject: [PATCH 2/6] Linting --- packages/astro/src/assets/utils/emitAsset.ts | 2 +- packages/astro/src/assets/vite-plugin-assets.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/astro/src/assets/utils/emitAsset.ts b/packages/astro/src/assets/utils/emitAsset.ts index d049e065d042..2c881ea3751d 100644 --- a/packages/astro/src/assets/utils/emitAsset.ts +++ b/packages/astro/src/assets/utils/emitAsset.ts @@ -9,7 +9,7 @@ export async function emitESMImage( id: string | undefined, watchMode: boolean, fileEmitter: any, - viteMode: string = '', + viteMode = '', ): Promise { if (!id) { return undefined; diff --git a/packages/astro/src/assets/vite-plugin-assets.ts b/packages/astro/src/assets/vite-plugin-assets.ts index 48870212ff21..9dea94b844d0 100644 --- a/packages/astro/src/assets/vite-plugin-assets.ts +++ b/packages/astro/src/assets/vite-plugin-assets.ts @@ -195,8 +195,8 @@ export default function assets({ { name: 'astro:assets:esm', enforce: 'pre', - config(config, { mode }) { - viteMode = mode; + config(_, env) { + viteMode = env.mode; }, configResolved(viteConfig) { resolvedConfig = viteConfig; From 93218400a83ce13ae24e463c77ca803fa426b1b7 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Mon, 22 Apr 2024 13:43:30 -0400 Subject: [PATCH 3/6] Another way --- packages/astro/src/assets/utils/emitAsset.ts | 11 +++++++---- packages/astro/src/assets/vite-plugin-assets.ts | 7 ++++--- packages/astro/src/content/runtime-assets.ts | 5 ++--- packages/astro/src/content/utils.ts | 4 ++-- .../src/content/vite-plugin-content-imports.ts | 16 ++++++++-------- 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/packages/astro/src/assets/utils/emitAsset.ts b/packages/astro/src/assets/utils/emitAsset.ts index 2c881ea3751d..71a1870cd5df 100644 --- a/packages/astro/src/assets/utils/emitAsset.ts +++ b/packages/astro/src/assets/utils/emitAsset.ts @@ -3,13 +3,16 @@ import path from 'node:path'; import { fileURLToPath, pathToFileURL } from 'node:url'; import { prependForwardSlash, slash } from '../../core/path.js'; import type { ImageMetadata } from '../types.js'; +import type * as vite from 'vite'; import { imageMetadata } from './metadata.js'; +type FileEmitter = vite.Rollup.EmitFile; + export async function emitESMImage( id: string | undefined, - watchMode: boolean, - fileEmitter: any, - viteMode = '', + /** @deprecated */ + _watchMode: boolean, + fileEmitter?: FileEmitter, ): Promise { if (!id) { return undefined; @@ -38,7 +41,7 @@ export async function emitESMImage( }); // Build - if (!watchMode && viteMode !== 'test') { + if (typeof fileEmitter === 'function') { const pathname = decodeURI(url.pathname); const filename = path.basename(pathname, path.extname(pathname) + `.${fileMetadata.format}`); diff --git a/packages/astro/src/assets/vite-plugin-assets.ts b/packages/astro/src/assets/vite-plugin-assets.ts index 9dea94b844d0..8721e5ced677 100644 --- a/packages/astro/src/assets/vite-plugin-assets.ts +++ b/packages/astro/src/assets/vite-plugin-assets.ts @@ -95,7 +95,7 @@ export default function assets({ mode, }: AstroPluginOptions & { mode: string }): vite.Plugin[] { let resolvedConfig: vite.ResolvedConfig; - let viteMode: string; + let viteCommand: vite.ConfigEnv['command']; globalThis.astroAsset = { referencedImages: new Set(), @@ -196,7 +196,7 @@ export default function assets({ name: 'astro:assets:esm', enforce: 'pre', config(_, env) { - viteMode = env.mode; + env.command; }, configResolved(viteConfig) { resolvedConfig = viteConfig; @@ -218,7 +218,8 @@ export default function assets({ return; } - const imageMetadata = await emitESMImage(id, this.meta.watchMode, this.emitFile, viteMode); + const emitFile = viteCommand === 'build' ? this.emitFile : undefined; + const imageMetadata = await emitESMImage(id, this.meta.watchMode, emitFile); if (!imageMetadata) { throw new AstroError({ diff --git a/packages/astro/src/content/runtime-assets.ts b/packages/astro/src/content/runtime-assets.ts index afb8e5e21deb..30f25ee9c16e 100644 --- a/packages/astro/src/content/runtime-assets.ts +++ b/packages/astro/src/content/runtime-assets.ts @@ -2,15 +2,14 @@ import type { PluginContext } from 'rollup'; import { z } from 'zod'; import { emitESMImage } from '../assets/utils/emitAsset.js'; -export function createImage(pluginContext: PluginContext, viteMode: string, entryFilePath: string) { +export function createImage(pluginContext: PluginContext, shouldEmitFile: boolean, entryFilePath: string) { return () => { return z.string().transform(async (imagePath, ctx) => { const resolvedFilePath = (await pluginContext.resolve(imagePath, entryFilePath))?.id; const metadata = await emitESMImage( resolvedFilePath, pluginContext.meta.watchMode, - pluginContext.emitFile, - viteMode, + shouldEmitFile ? pluginContext.emitFile : undefined, ); if (!metadata) { diff --git a/packages/astro/src/content/utils.ts b/packages/astro/src/content/utils.ts index fd131a089d93..9cd0b9f5f091 100644 --- a/packages/astro/src/content/utils.ts +++ b/packages/astro/src/content/utils.ts @@ -92,7 +92,7 @@ export async function getEntryData( _internal: EntryInternal; }, collectionConfig: CollectionConfig, - viteMode: string, + shouldEmitFile: boolean, pluginContext: PluginContext ) { let data; @@ -106,7 +106,7 @@ export async function getEntryData( let schema = collectionConfig.schema; if (typeof schema === 'function') { schema = schema({ - image: createImage(pluginContext, viteMode, entry._internal.filePath), + image: createImage(pluginContext, shouldEmitFile, entry._internal.filePath), }); } diff --git a/packages/astro/src/content/vite-plugin-content-imports.ts b/packages/astro/src/content/vite-plugin-content-imports.ts index 31adb6e92bb4..654235971d76 100644 --- a/packages/astro/src/content/vite-plugin-content-imports.ts +++ b/packages/astro/src/content/vite-plugin-content-imports.ts @@ -74,13 +74,13 @@ export function astroContentImportPlugin({ const contentEntryConfigByExt = getEntryConfigByExtMap(settings.contentEntryTypes); const dataEntryConfigByExt = getEntryConfigByExtMap(settings.dataEntryTypes); const { contentDir } = contentPaths; - let viteMode: string; + let shouldEmitFile = false; const plugins: Plugin[] = [ { name: 'astro:content-imports', - config(config, env) { - viteMode = env.mode; + config(_config, env) { + shouldEmitFile = env.command === 'build'; }, async transform(_, viteId) { if (hasContentFlag(viteId, DATA_FLAG)) { @@ -94,7 +94,7 @@ export function astroContentImportPlugin({ config: settings.config, fs, pluginContext: this, - viteMode, + shouldEmitFile, }); const code = ` @@ -117,7 +117,7 @@ export const _internal = { config: settings.config, fs, pluginContext: this, - viteMode, + shouldEmitFile, }); const code = ` @@ -196,7 +196,7 @@ type GetEntryModuleParams = pluginContext: PluginContext; entryConfigByExt: Map; config: AstroConfig; - viteMode: string; + shouldEmitFile: boolean; }; async function getContentEntryModule( @@ -229,7 +229,7 @@ async function getContentEntryModule( ? await getEntryData( { id, collection, _internal, unvalidatedData }, collectionConfig, - params.viteMode, + params.shouldEmitFile, pluginContext ) : unvalidatedData; @@ -264,7 +264,7 @@ async function getDataEntryModule( ? await getEntryData( { id, collection, _internal, unvalidatedData }, collectionConfig, - params.viteMode, + params.shouldEmitFile, pluginContext, ) : unvalidatedData; From b1700553d1af50b640e6292e44058bebc89f9cb7 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Mon, 22 Apr 2024 13:52:37 -0400 Subject: [PATCH 4/6] Make backwards compat --- packages/astro/src/assets/utils/emitAsset.ts | 26 ++++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/packages/astro/src/assets/utils/emitAsset.ts b/packages/astro/src/assets/utils/emitAsset.ts index 71a1870cd5df..b6fc14efa791 100644 --- a/packages/astro/src/assets/utils/emitAsset.ts +++ b/packages/astro/src/assets/utils/emitAsset.ts @@ -12,6 +12,8 @@ export async function emitESMImage( id: string | undefined, /** @deprecated */ _watchMode: boolean, + // FIX: in Astro 5, this function should not be passed in dev mode at all. + // Or rethink the API so that a function that throws isn't passed through. fileEmitter?: FileEmitter, ): Promise { if (!id) { @@ -41,18 +43,26 @@ export async function emitESMImage( }); // Build - if (typeof fileEmitter === 'function') { + let isBuild = typeof fileEmitter === 'function'; + if(isBuild) { const pathname = decodeURI(url.pathname); const filename = path.basename(pathname, path.extname(pathname) + `.${fileMetadata.format}`); - const handle = fileEmitter({ - name: filename, - source: await fs.readFile(url), - type: 'asset', - }); + try { + // fileEmitter throws in dev + const handle = fileEmitter!({ + name: filename, + source: await fs.readFile(url), + type: 'asset', + }); - emittedImage.src = `__ASTRO_ASSET_IMAGE__${handle}__`; - } else { + emittedImage.src = `__ASTRO_ASSET_IMAGE__${handle}__`; + } catch { + isBuild = false; + } + } + + if(!isBuild) { // Pass the original file information through query params so we don't have to load the file twice url.searchParams.append('origWidth', fileMetadata.width.toString()); url.searchParams.append('origHeight', fileMetadata.height.toString()); From 87b9c99c7f9c9620459af698e9eb83be5f5c7814 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Mon, 22 Apr 2024 14:09:34 -0400 Subject: [PATCH 5/6] Oops --- packages/astro/src/assets/vite-plugin-assets.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/astro/src/assets/vite-plugin-assets.ts b/packages/astro/src/assets/vite-plugin-assets.ts index 8721e5ced677..6114e7bf9bdc 100644 --- a/packages/astro/src/assets/vite-plugin-assets.ts +++ b/packages/astro/src/assets/vite-plugin-assets.ts @@ -95,7 +95,7 @@ export default function assets({ mode, }: AstroPluginOptions & { mode: string }): vite.Plugin[] { let resolvedConfig: vite.ResolvedConfig; - let viteCommand: vite.ConfigEnv['command']; + let shouldEmitFile = false; globalThis.astroAsset = { referencedImages: new Set(), @@ -196,7 +196,7 @@ export default function assets({ name: 'astro:assets:esm', enforce: 'pre', config(_, env) { - env.command; + shouldEmitFile = env.command === 'build'; }, configResolved(viteConfig) { resolvedConfig = viteConfig; @@ -218,7 +218,7 @@ export default function assets({ return; } - const emitFile = viteCommand === 'build' ? this.emitFile : undefined; + const emitFile = shouldEmitFile ? this.emitFile : undefined; const imageMetadata = await emitESMImage(id, this.meta.watchMode, emitFile); if (!imageMetadata) { From 1d8996664813ea3ea51fc7e0f644d75ab5c9ee90 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Mon, 22 Apr 2024 16:15:06 -0400 Subject: [PATCH 6/6] runHookConfigSetup creates a new settings --- packages/astro/src/config/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/astro/src/config/index.ts b/packages/astro/src/config/index.ts index fc45ae983476..f48bf4b153b2 100644 --- a/packages/astro/src/config/index.ts +++ b/packages/astro/src/config/index.ts @@ -35,8 +35,8 @@ export function getViteConfig(inlineConfig: UserConfig) { level: 'info', }); const { astroConfig: config } = await resolveConfig({}, cmd); - const settings = await createSettings(config, inlineConfig.root); - await runHookConfigSetup({ settings, command: cmd, logger }); + let settings = await createSettings(config, inlineConfig.root); + settings = await runHookConfigSetup({ settings, command: cmd, logger }); const viteConfig = await createVite( { mode,