mirror of
https://github.com/withastro/astro.git
synced 2024-12-23 21:53:55 -05:00
Fix regression with loading .ts in .mjs config (#5431)
* Fix regression with loading .ts in .mjs config * Account for directories
This commit is contained in:
parent
b22ba1c03a
commit
1ab505855f
5 changed files with 80 additions and 19 deletions
5
.changeset/purple-tips-flash.md
Normal file
5
.changeset/purple-tips-flash.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix regression with loading .ts in .mjs config
|
|
@ -3,6 +3,7 @@ import npath from 'path';
|
||||||
import { pathToFileURL } from 'url';
|
import { pathToFileURL } from 'url';
|
||||||
import * as vite from 'vite';
|
import * as vite from 'vite';
|
||||||
import { AstroError, AstroErrorData } from '../errors/index.js';
|
import { AstroError, AstroErrorData } from '../errors/index.js';
|
||||||
|
import loadFallbackPlugin from '../../vite-plugin-load-fallback/index.js';
|
||||||
|
|
||||||
// Fallback for legacy
|
// Fallback for legacy
|
||||||
import load from '@proload/core';
|
import load from '@proload/core';
|
||||||
|
@ -15,7 +16,7 @@ export interface ViteLoader {
|
||||||
viteServer: vite.ViteDevServer;
|
viteServer: vite.ViteDevServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createViteLoader(root: string): Promise<ViteLoader> {
|
async function createViteLoader(root: string, fs: typeof fsType): Promise<ViteLoader> {
|
||||||
const viteServer = await vite.createServer({
|
const viteServer = await vite.createServer({
|
||||||
server: { middlewareMode: true, hmr: false },
|
server: { middlewareMode: true, hmr: false },
|
||||||
optimizeDeps: { entries: [] },
|
optimizeDeps: { entries: [] },
|
||||||
|
@ -27,6 +28,7 @@ async function createViteLoader(root: string): Promise<ViteLoader> {
|
||||||
// avoid `vite.createServer` and use `loadConfigFromFile` instead.
|
// avoid `vite.createServer` and use `loadConfigFromFile` instead.
|
||||||
external: ['@astrojs/tailwind', '@astrojs/mdx', '@astrojs/react'],
|
external: ['@astrojs/tailwind', '@astrojs/mdx', '@astrojs/react'],
|
||||||
},
|
},
|
||||||
|
plugins: [ loadFallbackPlugin({ fs, root: pathToFileURL(root) })]
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -103,17 +105,22 @@ export async function loadConfigWithVite({
|
||||||
|
|
||||||
// Try loading with Node import()
|
// Try loading with Node import()
|
||||||
if (/\.[cm]?js$/.test(file)) {
|
if (/\.[cm]?js$/.test(file)) {
|
||||||
const config = await import(pathToFileURL(file).toString());
|
try {
|
||||||
return {
|
const config = await import(pathToFileURL(file).toString());
|
||||||
value: config.default ?? {},
|
return {
|
||||||
filePath: file,
|
value: config.default ?? {},
|
||||||
};
|
filePath: file,
|
||||||
|
};
|
||||||
|
} catch {
|
||||||
|
// We do not need to keep the error here because with fallback the error will be rethrown
|
||||||
|
// when/if it fails in Proload.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try Loading with Vite
|
// Try Loading with Vite
|
||||||
let loader: ViteLoader | undefined;
|
let loader: ViteLoader | undefined;
|
||||||
try {
|
try {
|
||||||
loader = await createViteLoader(root);
|
loader = await createViteLoader(root, fs);
|
||||||
const mod = await loader.viteServer.ssrLoadModule(file);
|
const mod = await loader.viteServer.ssrLoadModule(file);
|
||||||
return {
|
return {
|
||||||
value: mod.default ?? {},
|
value: mod.default ?? {},
|
||||||
|
|
|
@ -97,7 +97,7 @@ export async function createVite(
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
configAliasVitePlugin({ settings }),
|
configAliasVitePlugin({ settings }),
|
||||||
astroLoadFallbackPlugin({ fs, settings }),
|
astroLoadFallbackPlugin({ fs, root: settings.config.root }),
|
||||||
astroVitePlugin({ settings, logging }),
|
astroVitePlugin({ settings, logging }),
|
||||||
astroScriptsPlugin({ settings }),
|
astroScriptsPlugin({ settings }),
|
||||||
// The server plugin is for dev only and having it run during the build causes
|
// The server plugin is for dev only and having it run during the build causes
|
||||||
|
|
|
@ -8,12 +8,12 @@ type NodeFileSystemModule = typeof nodeFs;
|
||||||
|
|
||||||
export interface LoadFallbackPluginParams {
|
export interface LoadFallbackPluginParams {
|
||||||
fs?: NodeFileSystemModule;
|
fs?: NodeFileSystemModule;
|
||||||
settings: AstroSettings;
|
root: URL;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function loadFallbackPlugin({
|
export default function loadFallbackPlugin({
|
||||||
fs,
|
fs,
|
||||||
settings,
|
root,
|
||||||
}: LoadFallbackPluginParams): vite.Plugin[] | false {
|
}: LoadFallbackPluginParams): vite.Plugin[] | false {
|
||||||
// Only add this plugin if a custom fs implementation is provided.
|
// Only add this plugin if a custom fs implementation is provided.
|
||||||
if (!fs || fs === nodeFs) {
|
if (!fs || fs === nodeFs) {
|
||||||
|
@ -29,7 +29,7 @@ export default function loadFallbackPlugin({
|
||||||
return await fs.promises.readFile(id, 'utf-8');
|
return await fs.promises.readFile(id, 'utf-8');
|
||||||
} catch (e2) {
|
} catch (e2) {
|
||||||
try {
|
try {
|
||||||
const fullpath = new URL('.' + id, settings.config.root);
|
const fullpath = new URL('.' + id, root);
|
||||||
return await fs.promises.readFile(fullpath, 'utf-8');
|
return await fs.promises.readFile(fullpath, 'utf-8');
|
||||||
} catch (e3) {
|
} catch (e3) {
|
||||||
// Let fall through to the next
|
// Let fall through to the next
|
||||||
|
@ -43,15 +43,23 @@ export default function loadFallbackPlugin({
|
||||||
name: 'astro:load-fallback',
|
name: 'astro:load-fallback',
|
||||||
enforce: 'post',
|
enforce: 'post',
|
||||||
async resolveId(id, parent) {
|
async resolveId(id, parent) {
|
||||||
if (id.startsWith('.') && parent && fs.existsSync(parent)) {
|
// See if this can be loaded from our fs
|
||||||
return npath.posix.join(npath.posix.dirname(parent), id);
|
if (parent) {
|
||||||
} else {
|
const candidateId = npath.posix.join(npath.posix.dirname(parent), id);
|
||||||
let resolved = await this.resolve(id, parent, { skipSelf: true });
|
try {
|
||||||
if (resolved) {
|
// Check to see if this file exists and is not a directory.
|
||||||
return resolved.id;
|
const stats = await fs.promises.stat(candidateId);
|
||||||
}
|
if(!stats.isDirectory()) {
|
||||||
return slashify(id);
|
return candidateId;
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let resolved = await this.resolve(id, parent, { skipSelf: true });
|
||||||
|
if (resolved) {
|
||||||
|
return resolved.id;
|
||||||
}
|
}
|
||||||
|
return slashify(id);
|
||||||
},
|
},
|
||||||
async load(id) {
|
async load(id) {
|
||||||
const source = await tryLoadModule(id);
|
const source = await tryLoadModule(id);
|
||||||
|
|
41
packages/astro/test/units/config/format.test.js
Normal file
41
packages/astro/test/units/config/format.test.js
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import { expect } from 'chai';
|
||||||
|
import * as cheerio from 'cheerio';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
|
||||||
|
import {
|
||||||
|
runInContainer,
|
||||||
|
} from '../../../dist/core/dev/index.js';
|
||||||
|
import { openConfig, createSettings } from '../../../dist/core/config/index.js';
|
||||||
|
import { createFs } from '../test-utils.js';
|
||||||
|
import { defaultLogging } from '../../test-utils.js';
|
||||||
|
|
||||||
|
const root = new URL('../../fixtures/tailwindcss-ts/', import.meta.url);
|
||||||
|
|
||||||
|
describe('Astro config formats', () => {
|
||||||
|
it('An mjs config can import TypeScript modules', async () => {
|
||||||
|
const fs = createFs(
|
||||||
|
{
|
||||||
|
'/src/pages/index.astro': ``,
|
||||||
|
'/src/stuff.ts': `export default 'works';`,
|
||||||
|
'/astro.config.mjs': `
|
||||||
|
import stuff from './src/stuff.ts';
|
||||||
|
export default {}
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
root
|
||||||
|
);
|
||||||
|
|
||||||
|
const { astroConfig } = await openConfig({
|
||||||
|
cwd: root,
|
||||||
|
flags: {},
|
||||||
|
cmd: 'dev',
|
||||||
|
logging: defaultLogging,
|
||||||
|
fsMod: fs
|
||||||
|
});
|
||||||
|
const settings = createSettings(astroConfig);
|
||||||
|
|
||||||
|
await runInContainer({ fs, root, settings }, () => {
|
||||||
|
expect(true).to.equal(true, 'We were able to get into the container which means the config loaded.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in a new issue