[ci] format
This commit is contained in:
parent
c77a6cbe34
commit
63a3282f81
29 changed files with 241 additions and 240 deletions
|
@ -5,8 +5,8 @@
|
|||
*/
|
||||
|
||||
export type EventMap = {
|
||||
[key: string]: (...args: any[]) => void
|
||||
}
|
||||
[key: string]: (...args: any[]) => void;
|
||||
};
|
||||
|
||||
/**
|
||||
* Type-safe event emitter.
|
||||
|
@ -25,25 +25,25 @@ export type EventMap = {
|
|||
* ```
|
||||
*/
|
||||
interface TypedEventEmitter<Events extends EventMap> {
|
||||
addListener<E extends keyof Events> (event: E, listener: Events[E]): this
|
||||
on<E extends keyof Events> (event: E, listener: Events[E]): this
|
||||
once<E extends keyof Events> (event: E, listener: Events[E]): this
|
||||
prependListener<E extends keyof Events> (event: E, listener: Events[E]): this
|
||||
prependOnceListener<E extends keyof Events> (event: E, listener: Events[E]): this
|
||||
addListener<E extends keyof Events>(event: E, listener: Events[E]): this;
|
||||
on<E extends keyof Events>(event: E, listener: Events[E]): this;
|
||||
once<E extends keyof Events>(event: E, listener: Events[E]): this;
|
||||
prependListener<E extends keyof Events>(event: E, listener: Events[E]): this;
|
||||
prependOnceListener<E extends keyof Events>(event: E, listener: Events[E]): this;
|
||||
|
||||
off<E extends keyof Events>(event: E, listener: Events[E]): this
|
||||
removeAllListeners<E extends keyof Events> (event?: E): this
|
||||
removeListener<E extends keyof Events> (event: E, listener: Events[E]): this
|
||||
off<E extends keyof Events>(event: E, listener: Events[E]): this;
|
||||
removeAllListeners<E extends keyof Events>(event?: E): this;
|
||||
removeListener<E extends keyof Events>(event: E, listener: Events[E]): this;
|
||||
|
||||
emit<E extends keyof Events> (event: E, ...args: Parameters<Events[E]>): boolean
|
||||
// The sloppy `eventNames()` return type is to mitigate type incompatibilities - see #5
|
||||
eventNames (): (keyof Events | string | symbol)[]
|
||||
rawListeners<E extends keyof Events> (event: E): Events[E][]
|
||||
listeners<E extends keyof Events> (event: E): Events[E][]
|
||||
listenerCount<E extends keyof Events> (event: E): number
|
||||
emit<E extends keyof Events>(event: E, ...args: Parameters<Events[E]>): boolean;
|
||||
// The sloppy `eventNames()` return type is to mitigate type incompatibilities - see #5
|
||||
eventNames(): (keyof Events | string | symbol)[];
|
||||
rawListeners<E extends keyof Events>(event: E): Events[E][];
|
||||
listeners<E extends keyof Events>(event: E): Events[E][];
|
||||
listenerCount<E extends keyof Events>(event: E): number;
|
||||
|
||||
getMaxListeners (): number
|
||||
setMaxListeners (maxListeners: number): this
|
||||
getMaxListeners(): number;
|
||||
setMaxListeners(maxListeners: number): this;
|
||||
}
|
||||
|
||||
export default TypedEventEmitter
|
||||
export default TypedEventEmitter;
|
||||
|
|
|
@ -190,12 +190,7 @@ export async function openConfig(configOptions: LoadConfigOptions): Promise<Open
|
|||
if (config) {
|
||||
userConfig = config.value;
|
||||
}
|
||||
const astroConfig = await resolveConfig(
|
||||
userConfig,
|
||||
root,
|
||||
flags,
|
||||
configOptions.cmd
|
||||
);
|
||||
const astroConfig = await resolveConfig(userConfig, root, flags, configOptions.cmd);
|
||||
|
||||
return {
|
||||
astroConfig,
|
||||
|
@ -318,7 +313,7 @@ export async function resolveConfig(
|
|||
|
||||
export function createDefaultDevConfig(
|
||||
userConfig: AstroUserConfig = {},
|
||||
root: string = process.cwd(),
|
||||
root: string = process.cwd()
|
||||
) {
|
||||
return resolveConfig(userConfig, root, undefined, 'dev');
|
||||
}
|
||||
|
|
|
@ -7,5 +7,5 @@ export {
|
|||
validateConfig,
|
||||
} from './config.js';
|
||||
export type { AstroConfigSchema } from './schema';
|
||||
export { createSettings, createDefaultDevSettings } from './settings.js';
|
||||
export { createDefaultDevSettings, createSettings } from './settings.js';
|
||||
export { loadTSConfig, updateTSConfigForFramework } from './tsconfig.js';
|
||||
|
|
|
@ -2,8 +2,8 @@ import type { AstroConfig, AstroSettings, AstroUserConfig } from '../../@types/a
|
|||
import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from './../constants.js';
|
||||
|
||||
import { fileURLToPath } from 'url';
|
||||
import { createDefaultDevConfig } from './config.js';
|
||||
import jsxRenderer from '../../jsx/renderer.js';
|
||||
import { createDefaultDevConfig } from './config.js';
|
||||
import { loadTSConfig } from './tsconfig.js';
|
||||
|
||||
export function createBaseSettings(config: AstroConfig): AstroSettings {
|
||||
|
@ -34,10 +34,9 @@ export async function createDefaultDevSettings(
|
|||
userConfig: AstroUserConfig = {},
|
||||
root?: string | URL
|
||||
): Promise<AstroSettings> {
|
||||
if(root && typeof root !== 'string') {
|
||||
if (root && typeof root !== 'string') {
|
||||
root = fileURLToPath(root);
|
||||
}
|
||||
const config = await createDefaultDevConfig(userConfig, root);
|
||||
return createBaseSettings(config);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,12 +13,12 @@ import envVitePlugin from '../vite-plugin-env/index.js';
|
|||
import htmlVitePlugin from '../vite-plugin-html/index.js';
|
||||
import astroIntegrationsContainerPlugin from '../vite-plugin-integrations-container/index.js';
|
||||
import jsxVitePlugin from '../vite-plugin-jsx/index.js';
|
||||
import astroLoadFallbackPlugin from '../vite-plugin-load-fallback/index.js';
|
||||
import legacyMarkdownVitePlugin from '../vite-plugin-markdown-legacy/index.js';
|
||||
import markdownVitePlugin from '../vite-plugin-markdown/index.js';
|
||||
import astroScriptsPlugin from '../vite-plugin-scripts/index.js';
|
||||
import astroScriptsPageSSRPlugin from '../vite-plugin-scripts/page-ssr.js';
|
||||
import { createCustomViteLogger } from './errors/dev/index.js';
|
||||
import astroLoadFallbackPlugin from '../vite-plugin-load-fallback/index.js';
|
||||
import { resolveDependency } from './util.js';
|
||||
|
||||
interface CreateViteOptions {
|
||||
|
@ -110,7 +110,7 @@ export async function createVite(
|
|||
astroPostprocessVitePlugin({ settings }),
|
||||
astroIntegrationsContainerPlugin({ settings, logging }),
|
||||
astroScriptsPageSSRPlugin({ settings }),
|
||||
astroLoadFallbackPlugin({ fs })
|
||||
astroLoadFallbackPlugin({ fs }),
|
||||
],
|
||||
publicDir: fileURLToPath(settings.config.publicDir),
|
||||
root: fileURLToPath(settings.config.root),
|
||||
|
|
|
@ -1,23 +1,21 @@
|
|||
|
||||
import * as http from 'http';
|
||||
import type { AddressInfo } from 'net';
|
||||
import type { AstroSettings, AstroUserConfig } from '../../@types/astro';
|
||||
import * as http from 'http';
|
||||
|
||||
import nodeFs from 'fs';
|
||||
import * as vite from 'vite';
|
||||
import {
|
||||
runHookConfigDone,
|
||||
runHookConfigSetup,
|
||||
runHookServerSetup,
|
||||
runHookServerStart,
|
||||
} from '../../integrations/index.js';
|
||||
import { createVite } from '../create-vite.js';
|
||||
import { LogOptions } from '../logger/core.js';
|
||||
import { nodeLogDestination } from '../logger/node.js';
|
||||
import nodeFs from 'fs';
|
||||
import * as vite from 'vite';
|
||||
import { createDefaultDevSettings } from '../config/index.js';
|
||||
import { createVite } from '../create-vite.js';
|
||||
import { LogOptions } from '../logger/core.js';
|
||||
import { nodeLogDestination } from '../logger/node.js';
|
||||
import { apply as applyPolyfill } from '../polyfill.js';
|
||||
|
||||
|
||||
const defaultLogging: LogOptions = {
|
||||
dest: nodeLogDestination,
|
||||
level: 'error',
|
||||
|
@ -47,7 +45,7 @@ export async function createContainer(params: CreateContainerParams = {}): Promi
|
|||
isRestart = false,
|
||||
logging = defaultLogging,
|
||||
settings = await createDefaultDevSettings(params.userConfig, params.root),
|
||||
fs = nodeFs
|
||||
fs = nodeFs,
|
||||
} = params;
|
||||
|
||||
// Initialize
|
||||
|
@ -97,11 +95,15 @@ export async function createContainer(params: CreateContainerParams = {}): Promi
|
|||
},
|
||||
close() {
|
||||
return viteServer.close();
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export async function startContainer({ settings, viteServer, logging }: Container): Promise<AddressInfo> {
|
||||
export async function startContainer({
|
||||
settings,
|
||||
viteServer,
|
||||
logging,
|
||||
}: Container): Promise<AddressInfo> {
|
||||
const { port } = settings.config.server;
|
||||
await viteServer.listen(port);
|
||||
const devServerAddressInfo = viteServer.httpServer!.address() as AddressInfo;
|
||||
|
@ -114,7 +116,10 @@ export async function startContainer({ settings, viteServer, logging }: Containe
|
|||
return devServerAddressInfo;
|
||||
}
|
||||
|
||||
export async function runInContainer(params: CreateContainerParams, callback: (container: Container) => Promise<void> | void) {
|
||||
export async function runInContainer(
|
||||
params: CreateContainerParams,
|
||||
callback: (container: Container) => Promise<void> | void
|
||||
) {
|
||||
const container = await createContainer(params);
|
||||
try {
|
||||
await callback(container);
|
||||
|
|
|
@ -1,9 +1,2 @@
|
|||
export {
|
||||
createContainer,
|
||||
startContainer,
|
||||
runInContainer
|
||||
} from './container.js';
|
||||
|
||||
export {
|
||||
default
|
||||
} from './dev.js';
|
||||
export { createContainer, runInContainer, startContainer } from './container.js';
|
||||
export { default } from './dev.js';
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
import type { ModuleLoader } from '../../module-loader/index.js';
|
||||
import * as fs from 'fs';
|
||||
import { fileURLToPath } from 'url';
|
||||
import {
|
||||
createLogger,
|
||||
type ErrorPayload,
|
||||
type Logger,
|
||||
type LogLevel,
|
||||
} from 'vite';
|
||||
import { createLogger, type ErrorPayload, type Logger, type LogLevel } from 'vite';
|
||||
import type { ModuleLoader } from '../../module-loader/index.js';
|
||||
import { AstroErrorCodes } from '../codes.js';
|
||||
import { AstroError, type ErrorWithMetadata } from '../errors.js';
|
||||
import { incompatPackageExp } from './utils.js';
|
||||
|
@ -30,7 +25,7 @@ export function createCustomViteLogger(logLevel: LogLevel): Logger {
|
|||
export function enhanceViteSSRError(
|
||||
error: Error,
|
||||
filePath?: URL,
|
||||
loader?: ModuleLoader,
|
||||
loader?: ModuleLoader
|
||||
): AstroError {
|
||||
// Vite will give you better stacktraces, using sourcemaps.
|
||||
if (loader) {
|
||||
|
|
|
@ -1,14 +1,3 @@
|
|||
export type {
|
||||
ModuleInfo,
|
||||
ModuleLoader,
|
||||
ModuleNode,
|
||||
LoaderEvents
|
||||
} from './loader.js';
|
||||
|
||||
export {
|
||||
createLoader
|
||||
} from './loader.js';
|
||||
|
||||
export {
|
||||
createViteLoader
|
||||
} from './vite.js';
|
||||
export { createLoader } from './loader.js';
|
||||
export type { LoaderEvents, ModuleInfo, ModuleLoader, ModuleNode } from './loader.js';
|
||||
export { createViteLoader } from './vite.js';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type TypedEmitter from '../../@types/typed-emitter';
|
||||
import type * as fs from 'fs';
|
||||
import { EventEmitter } from 'events';
|
||||
import type * as fs from 'fs';
|
||||
import type TypedEmitter from '../../@types/typed-emitter';
|
||||
|
||||
// This is a generic interface for a module loader. In the astro cli this is
|
||||
// fulfilled by Vite, see vite.ts
|
||||
|
@ -10,10 +10,10 @@ export type LoaderEvents = {
|
|||
'file-change': (msg: [path: string, stats?: fs.Stats | undefined]) => void;
|
||||
'file-unlink': (msg: [path: string, stats?: fs.Stats | undefined]) => void;
|
||||
'hmr-error': (msg: {
|
||||
type: 'error',
|
||||
type: 'error';
|
||||
err: {
|
||||
message: string;
|
||||
stack: string
|
||||
stack: string;
|
||||
};
|
||||
}) => void;
|
||||
};
|
||||
|
@ -53,19 +53,33 @@ export interface ModuleInfo {
|
|||
|
||||
export function createLoader(overrides: Partial<ModuleLoader>): ModuleLoader {
|
||||
return {
|
||||
import() { throw new Error(`Not implemented`); },
|
||||
resolveId(id) { return Promise.resolve(id); },
|
||||
getModuleById() {return undefined },
|
||||
getModulesByFile() { return undefined },
|
||||
getModuleInfo() { return null; },
|
||||
eachModule() { throw new Error(`Not implemented`); },
|
||||
import() {
|
||||
throw new Error(`Not implemented`);
|
||||
},
|
||||
resolveId(id) {
|
||||
return Promise.resolve(id);
|
||||
},
|
||||
getModuleById() {
|
||||
return undefined;
|
||||
},
|
||||
getModulesByFile() {
|
||||
return undefined;
|
||||
},
|
||||
getModuleInfo() {
|
||||
return null;
|
||||
},
|
||||
eachModule() {
|
||||
throw new Error(`Not implemented`);
|
||||
},
|
||||
invalidateModule() {},
|
||||
fixStacktrace() {},
|
||||
clientReload() {},
|
||||
webSocketSend() {},
|
||||
isHttps() { return true; },
|
||||
isHttps() {
|
||||
return true;
|
||||
},
|
||||
events: new EventEmitter() as ModuleLoaderEventEmitter,
|
||||
|
||||
...overrides
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { EventEmitter } from 'events';
|
||||
import type * as vite from 'vite';
|
||||
import type { ModuleLoader, ModuleLoaderEventEmitter } from './loader';
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
export function createViteLoader(viteServer: vite.ViteDevServer): ModuleLoader {
|
||||
const events = new EventEmitter() as ModuleLoaderEventEmitter;
|
||||
|
@ -9,8 +9,8 @@ export function createViteLoader(viteServer: vite.ViteDevServer): ModuleLoader {
|
|||
viteServer.watcher.on('unlink', (...args) => events.emit('file-unlink', args));
|
||||
viteServer.watcher.on('change', (...args) => events.emit('file-change', args));
|
||||
|
||||
wrapMethod(viteServer.ws, 'send', msg => {
|
||||
if(msg?.type === 'error') {
|
||||
wrapMethod(viteServer.ws, 'send', (msg) => {
|
||||
if (msg?.type === 'error') {
|
||||
events.emit('hmr-error', msg);
|
||||
}
|
||||
});
|
||||
|
@ -33,18 +33,18 @@ export function createViteLoader(viteServer: vite.ViteDevServer): ModuleLoader {
|
|||
return viteServer.pluginContainer.getModuleInfo(id);
|
||||
},
|
||||
eachModule(cb) {
|
||||
return viteServer.moduleGraph.idToModuleMap.forEach(cb);
|
||||
},
|
||||
invalidateModule(mod) {
|
||||
viteServer.moduleGraph.invalidateModule(mod as vite.ModuleNode);
|
||||
},
|
||||
return viteServer.moduleGraph.idToModuleMap.forEach(cb);
|
||||
},
|
||||
invalidateModule(mod) {
|
||||
viteServer.moduleGraph.invalidateModule(mod as vite.ModuleNode);
|
||||
},
|
||||
fixStacktrace(err) {
|
||||
return viteServer.ssrFixStacktrace(err);
|
||||
},
|
||||
clientReload() {
|
||||
viteServer.ws.send({
|
||||
type: 'full-reload',
|
||||
path: '*'
|
||||
path: '*',
|
||||
});
|
||||
},
|
||||
webSocketSend(msg) {
|
||||
|
@ -53,14 +53,13 @@ export function createViteLoader(viteServer: vite.ViteDevServer): ModuleLoader {
|
|||
isHttps() {
|
||||
return !!viteServer.config.server.https;
|
||||
},
|
||||
events
|
||||
events,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function wrapMethod(object: any, method: string, newFn: (...args: any[]) => void) {
|
||||
const orig = object[method];
|
||||
object[method] = function(...args: any[]) {
|
||||
object[method] = function (...args: any[]) {
|
||||
newFn.apply(this, args);
|
||||
return orig.apply(this, args);
|
||||
};
|
||||
|
|
|
@ -19,8 +19,7 @@ export async function getStylesForURL(
|
|||
const ext = path.extname(importedModule.url).toLowerCase();
|
||||
if (STYLE_EXTENSIONS.has(ext)) {
|
||||
// The SSR module is possibly not loaded. Load it if it's null.
|
||||
const ssrModule =
|
||||
importedModule.ssrModule ?? (await loader.import(importedModule.url));
|
||||
const ssrModule = importedModule.ssrModule ?? (await loader.import(importedModule.url));
|
||||
if (
|
||||
mode === 'development' && // only inline in development
|
||||
typeof ssrModule?.default === 'string' // ignore JS module styles
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import type { ViteDevServer } from 'vite';
|
||||
import type { AstroSettings, RuntimeMode } from '../../../@types/astro';
|
||||
import type { LogOptions } from '../../logger/core.js';
|
||||
import type { Environment } from '../index';
|
||||
import type { ModuleLoader } from '../../module-loader/index';
|
||||
import type { Environment } from '../index';
|
||||
|
||||
import { createEnvironment } from '../index.js';
|
||||
import { RouteCache } from '../route-cache.js';
|
||||
|
|
|
@ -7,11 +7,11 @@ import type {
|
|||
SSRElement,
|
||||
SSRLoadedRenderer,
|
||||
} from '../../../@types/astro';
|
||||
import type { ModuleLoader } from '../../module-loader/index';
|
||||
import { PAGE_SCRIPT_ID } from '../../../vite-plugin-scripts/index.js';
|
||||
import { enhanceViteSSRError } from '../../errors/dev/index.js';
|
||||
import { AggregateError, CSSError, MarkdownError } from '../../errors/index.js';
|
||||
import { LogOptions } from '../../logger/core.js';
|
||||
import type { ModuleLoader } from '../../module-loader/index';
|
||||
import { isPage, resolveIdToUrl } from '../../util.js';
|
||||
import { createRenderContext, renderPage as coreRenderPage } from '../index.js';
|
||||
import { filterFoundRenderers, loadRenderer } from '../renderer.js';
|
||||
|
|
|
@ -224,7 +224,12 @@ export function createRouteManifest(
|
|||
const validEndpointExtensions: Set<string> = new Set(['.js', '.ts']);
|
||||
const localFs = fsMod ?? nodeFs;
|
||||
|
||||
function walk(fs: typeof nodeFs, dir: string, parentSegments: RoutePart[][], parentParams: string[]) {
|
||||
function walk(
|
||||
fs: typeof nodeFs,
|
||||
dir: string,
|
||||
parentSegments: RoutePart[][],
|
||||
parentParams: string[]
|
||||
) {
|
||||
let items: Item[] = [];
|
||||
fs.readdirSync(dir).forEach((basename) => {
|
||||
const resolved = path.join(dir, basename);
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import type { ModuleLoader } from './module-loader';
|
||||
import eol from 'eol';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import resolve from 'resolve';
|
||||
|
@ -8,6 +6,7 @@ import { fileURLToPath, pathToFileURL } from 'url';
|
|||
import { normalizePath } from 'vite';
|
||||
import type { AstroConfig, AstroSettings, RouteType } from '../@types/astro';
|
||||
import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from './constants.js';
|
||||
import type { ModuleLoader } from './module-loader';
|
||||
import { prependForwardSlash, removeTrailingForwardSlash } from './path.js';
|
||||
|
||||
/** Returns true if argument is an object of any prototype/class (but not null). */
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
import type { ServerState } from './server-state';
|
||||
import type { LoaderEvents, ModuleLoader } from '../core/module-loader/index';
|
||||
import type { ServerState } from './server-state';
|
||||
|
||||
import { createServerState, setRouteError, setServerError, clearRouteError } from './server-state.js';
|
||||
import {
|
||||
clearRouteError,
|
||||
createServerState,
|
||||
setRouteError,
|
||||
setServerError,
|
||||
} from './server-state.js';
|
||||
|
||||
type ReloadFn = () => void;
|
||||
|
||||
|
@ -11,14 +16,16 @@ export interface DevServerController {
|
|||
onHMRError: LoaderEvents['hmr-error'];
|
||||
}
|
||||
|
||||
export type CreateControllerParams = {
|
||||
loader: ModuleLoader;
|
||||
} | {
|
||||
reload: ReloadFn;
|
||||
};
|
||||
export type CreateControllerParams =
|
||||
| {
|
||||
loader: ModuleLoader;
|
||||
}
|
||||
| {
|
||||
reload: ReloadFn;
|
||||
};
|
||||
|
||||
export function createController(params: CreateControllerParams): DevServerController {
|
||||
if('loader' in params) {
|
||||
if ('loader' in params) {
|
||||
return createLoaderController(params.loader);
|
||||
} else {
|
||||
return createBaseController(params);
|
||||
|
@ -29,7 +36,7 @@ export function createBaseController({ reload }: { reload: ReloadFn }): DevServe
|
|||
const serverState = createServerState();
|
||||
|
||||
const onFileChange: LoaderEvents['file-change'] = () => {
|
||||
if(serverState.state === 'error') {
|
||||
if (serverState.state === 'error') {
|
||||
reload();
|
||||
}
|
||||
};
|
||||
|
@ -39,7 +46,7 @@ export function createBaseController({ reload }: { reload: ReloadFn }): DevServe
|
|||
let stack = payload?.err?.stack ?? 'Unknown stack';
|
||||
let error = new Error(msg);
|
||||
Object.defineProperty(error, 'stack', {
|
||||
value: stack
|
||||
value: stack,
|
||||
});
|
||||
setServerError(serverState, error);
|
||||
};
|
||||
|
@ -47,7 +54,7 @@ export function createBaseController({ reload }: { reload: ReloadFn }): DevServe
|
|||
return {
|
||||
state: serverState,
|
||||
onFileChange,
|
||||
onHMRError
|
||||
onHMRError,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -55,21 +62,21 @@ export function createLoaderController(loader: ModuleLoader): DevServerControlle
|
|||
const controller = createBaseController({
|
||||
reload() {
|
||||
loader.clientReload();
|
||||
}
|
||||
},
|
||||
});
|
||||
const baseOnFileChange = controller.onFileChange;
|
||||
controller.onFileChange = (...args) => {
|
||||
if(controller.state.state === 'error') {
|
||||
if (controller.state.state === 'error') {
|
||||
// If we are in an error state, check if there are any modules with errors
|
||||
// and if so invalidate them so that they will be updated on refresh.
|
||||
loader.eachModule(mod => {
|
||||
if(mod.ssrError) {
|
||||
loader.eachModule((mod) => {
|
||||
if (mod.ssrError) {
|
||||
loader.invalidateModule(mod);
|
||||
}
|
||||
});
|
||||
}
|
||||
baseOnFileChange(...args);
|
||||
}
|
||||
};
|
||||
|
||||
loader.events.on('file-change', controller.onFileChange);
|
||||
loader.events.on('hmr-error', controller.onHMRError);
|
||||
|
@ -88,12 +95,12 @@ export async function runWithErrorHandling({
|
|||
controller: { state },
|
||||
pathname,
|
||||
run,
|
||||
onError
|
||||
onError,
|
||||
}: RunWithErrorHandlingParams) {
|
||||
try {
|
||||
await run();
|
||||
clearRouteError(state, pathname);
|
||||
} catch(err) {
|
||||
} catch (err) {
|
||||
const error = onError(err);
|
||||
setRouteError(state, pathname, error);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,3 @@
|
|||
export {
|
||||
createController,
|
||||
runWithErrorHandling
|
||||
} from './controller.js';
|
||||
export {
|
||||
default as vitePluginAstroServer
|
||||
} from './plugin.js';
|
||||
export {
|
||||
handleRequest
|
||||
} from './request.js';
|
||||
export { createController, runWithErrorHandling } from './controller.js';
|
||||
export { default as vitePluginAstroServer } from './plugin.js';
|
||||
export { handleRequest } from './request.js';
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
|
||||
import type * as vite from 'vite';
|
||||
import type { AstroSettings, ManifestData } from '../@types/astro';
|
||||
|
||||
import type fs from 'fs';
|
||||
import { LogOptions } from '../core/logger/core.js';
|
||||
import { createViteLoader } from '../core/module-loader/index.js';
|
||||
import { createDevelopmentEnvironment } from '../core/render/dev/index.js';
|
||||
import { createRouteManifest } from '../core/routing/index.js';
|
||||
import { createViteLoader } from '../core/module-loader/index.js';
|
||||
import { baseMiddleware } from './base.js';
|
||||
import { handleRequest } from './request.js';
|
||||
import { createController } from './controller.js';
|
||||
import type fs from 'fs';
|
||||
import { handleRequest } from './request.js';
|
||||
|
||||
export interface AstroPluginOptions {
|
||||
settings: AstroSettings;
|
||||
|
@ -17,7 +16,11 @@ export interface AstroPluginOptions {
|
|||
fs: typeof fs;
|
||||
}
|
||||
|
||||
export default function createVitePluginAstroServer({ settings, logging, fs: fsMod }: AstroPluginOptions): vite.Plugin {
|
||||
export default function createVitePluginAstroServer({
|
||||
settings,
|
||||
logging,
|
||||
fs: fsMod,
|
||||
}: AstroPluginOptions): vite.Plugin {
|
||||
return {
|
||||
name: 'astro:server',
|
||||
configureServer(viteServer) {
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import type http from 'http';
|
||||
import type { ManifestData, RouteData } from '../@types/astro';
|
||||
import type { DevServerController } from './controller';
|
||||
import type { ManifestData } from '../@types/astro';
|
||||
import type { DevelopmentEnvironment } from '../core/render/dev/index';
|
||||
import type { DevServerController } from './controller';
|
||||
|
||||
import { collectErrorMetadata } from '../core/errors/dev/index.js';
|
||||
import { createSafeError } from '../core/errors/index.js';
|
||||
import { error } from '../core/logger/core.js';
|
||||
import * as msg from '../core/messages.js';
|
||||
import { handleRoute, matchRoute } from './route.js';
|
||||
import { handle500Response } from './response.js';
|
||||
import { runWithErrorHandling } from './controller.js';
|
||||
import { createSafeError } from '../core/errors/index.js';
|
||||
import { handle500Response } from './response.js';
|
||||
import { handleRoute, matchRoute } from './route.js';
|
||||
|
||||
/** The main logic to route dev server requests to pages in Astro. */
|
||||
export async function handleRequest(
|
||||
|
@ -60,7 +60,7 @@ export async function handleRequest(
|
|||
pathname,
|
||||
async run() {
|
||||
const matchedRoute = await matchRoute(pathname, env, manifest);
|
||||
|
||||
|
||||
return await handleRoute(matchedRoute, url, pathname, body, origin, env, manifest, req, res);
|
||||
},
|
||||
onError(_err) {
|
||||
|
@ -73,6 +73,6 @@ export async function handleRequest(
|
|||
handle500Response(moduleLoader, res, errorWithMetadata);
|
||||
|
||||
return err;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import type http from 'http';
|
||||
import type { ModuleLoader } from '../core/module-loader/index';
|
||||
import type { ErrorWithMetadata } from '../core/errors/index.js';
|
||||
import type { ModuleLoader } from '../core/module-loader/index';
|
||||
|
||||
import { Readable } from 'stream';
|
||||
import { getSetCookiesFromResponse } from '../core/cookies/index.js';
|
||||
import { getViteErrorPayload } from '../core/errors/dev/index.js';
|
||||
import notFoundTemplate from '../template/4xx.js';
|
||||
|
||||
|
||||
export async function handle404Response(
|
||||
origin: string,
|
||||
req: http.IncomingMessage,
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import type http from 'http';
|
||||
import mime from 'mime';
|
||||
import type { AstroConfig, AstroSettings, ManifestData } from '../@types/astro';
|
||||
import type { AstroSettings, ManifestData } from '../@types/astro';
|
||||
import { DevelopmentEnvironment, SSROptions } from '../core/render/dev/index';
|
||||
|
||||
import { attachToResponse } from '../core/cookies/index.js';
|
||||
import { call as callEndpoint } from '../core/endpoint/dev/index.js';
|
||||
import { throwIfRedirectNotAllowed } from '../core/endpoint/index.js';
|
||||
import { warn } from '../core/logger/core.js';
|
||||
import { appendForwardSlash } from '../core/path.js';
|
||||
import { preload, renderPage } from '../core/render/dev/index.js';
|
||||
|
@ -13,8 +14,7 @@ import { createRequest } from '../core/request.js';
|
|||
import { matchAllRoutes } from '../core/routing/index.js';
|
||||
import { resolvePages } from '../core/util.js';
|
||||
import { log404 } from './common.js';
|
||||
import { handle404Response, writeWebResponse, writeSSRResult } from './response.js';
|
||||
import { throwIfRedirectNotAllowed } from '../core/endpoint/index.js';
|
||||
import { handle404Response, writeSSRResult, writeWebResponse } from './response.js';
|
||||
|
||||
type AsyncReturnType<T extends (...args: any) => Promise<any>> = T extends (
|
||||
...args: any
|
||||
|
@ -29,7 +29,11 @@ function getCustom404Route({ config }: AstroSettings, manifest: ManifestData) {
|
|||
return manifest.routes.find((r) => r.component.match(pattern));
|
||||
}
|
||||
|
||||
export async function matchRoute(pathname: string, env: DevelopmentEnvironment, manifest: ManifestData) {
|
||||
export async function matchRoute(
|
||||
pathname: string,
|
||||
env: DevelopmentEnvironment,
|
||||
manifest: ManifestData
|
||||
) {
|
||||
const { logging, settings, routeCache } = env;
|
||||
const matches = matchAllRoutes(pathname, manifest);
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ export interface ServerState {
|
|||
export function createServerState(): ServerState {
|
||||
return {
|
||||
routes: new Map(),
|
||||
state: 'fresh'
|
||||
state: 'fresh',
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -23,14 +23,14 @@ export function hasAnyFailureState(serverState: ServerState) {
|
|||
}
|
||||
|
||||
export function setRouteError(serverState: ServerState, pathname: string, error: Error) {
|
||||
if(serverState.routes.has(pathname)) {
|
||||
if (serverState.routes.has(pathname)) {
|
||||
const routeState = serverState.routes.get(pathname)!;
|
||||
routeState.state = 'error';
|
||||
routeState.error = error;
|
||||
} else {
|
||||
const routeState: RouteState = {
|
||||
state: 'error',
|
||||
error: error
|
||||
error: error,
|
||||
};
|
||||
serverState.routes.set(pathname, routeState);
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ export function setServerError(serverState: ServerState, error: Error) {
|
|||
}
|
||||
|
||||
export function clearRouteError(serverState: ServerState, pathname: string) {
|
||||
if(serverState.routes.has(pathname)) {
|
||||
if (serverState.routes.has(pathname)) {
|
||||
serverState.routes.delete(pathname);
|
||||
}
|
||||
serverState.state = 'fresh';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type * as vite from 'vite';
|
||||
import nodeFs from 'fs';
|
||||
import type * as vite from 'vite';
|
||||
|
||||
type NodeFileSystemModule = typeof nodeFs;
|
||||
|
||||
|
@ -9,30 +9,29 @@ export interface LoadFallbackPluginParams {
|
|||
|
||||
export default function loadFallbackPlugin({ fs }: LoadFallbackPluginParams): vite.Plugin | false {
|
||||
// Only add this plugin if a custom fs implementation is provided.
|
||||
if(!fs || fs === nodeFs) {
|
||||
if (!fs || fs === nodeFs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'astro:load-fallback',
|
||||
enforce: 'post',
|
||||
async load(id) {
|
||||
try {
|
||||
// await is necessary for the catch
|
||||
return await fs.promises.readFile(cleanUrl(id), 'utf-8')
|
||||
} catch (e) {
|
||||
try {
|
||||
return await fs.promises.readFile(id, 'utf-8');
|
||||
} catch(e2) {
|
||||
// Let fall through to the next
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
name: 'astro:load-fallback',
|
||||
enforce: 'post',
|
||||
async load(id) {
|
||||
try {
|
||||
// await is necessary for the catch
|
||||
return await fs.promises.readFile(cleanUrl(id), 'utf-8');
|
||||
} catch (e) {
|
||||
try {
|
||||
return await fs.promises.readFile(id, 'utf-8');
|
||||
} catch (e2) {
|
||||
// Let fall through to the next
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const queryRE = /\?.*$/s;
|
||||
const hashRE = /#.*$/s;
|
||||
|
||||
const cleanUrl = (url: string): string =>
|
||||
url.replace(hashRE, '').replace(queryRE, '');
|
||||
const cleanUrl = (url: string): string => url.replace(hashRE, '').replace(queryRE, '');
|
||||
|
|
|
@ -25,8 +25,8 @@ function removeTrailingSeparator(str) {
|
|||
}
|
||||
|
||||
function isSeparator(str, i) {
|
||||
let char = str[i];
|
||||
return i > 0 && (char === '/' || (isWin && char === '\\'));
|
||||
let char = str[i];
|
||||
return i > 0 && (char === '/' || (isWin && char === '\\'));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -37,34 +37,34 @@ function isSeparator(str, i) {
|
|||
* Released under the MIT License.
|
||||
*/
|
||||
function normalizePath(str, stripTrailing) {
|
||||
if (typeof str !== 'string') {
|
||||
throw new TypeError('expected a string');
|
||||
}
|
||||
str = str.replace(/[\\\/]+/g, '/');
|
||||
if (stripTrailing !== false) {
|
||||
str = removeTrailingSeparator(str);
|
||||
}
|
||||
return str;
|
||||
if (typeof str !== 'string') {
|
||||
throw new TypeError('expected a string');
|
||||
}
|
||||
str = str.replace(/[\\\/]+/g, '/');
|
||||
if (stripTrailing !== false) {
|
||||
str = removeTrailingSeparator(str);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/*!
|
||||
* unixify <https://github.com/jonschlinkert/unixify>
|
||||
*
|
||||
*
|
||||
* Inlined from:
|
||||
* Copyright (c) 2014, 2017, Jon Schlinkert.
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
export function unixify(filepath, stripTrailing = true) {
|
||||
if(isWin) {
|
||||
filepath = normalizePath(filepath, stripTrailing);
|
||||
return filepath.replace(/^([a-zA-Z]+:|\.\/)/, '');
|
||||
}
|
||||
return filepath;
|
||||
if (isWin) {
|
||||
filepath = normalizePath(filepath, stripTrailing);
|
||||
return filepath.replace(/^([a-zA-Z]+:|\.\/)/, '');
|
||||
}
|
||||
return filepath;
|
||||
}
|
||||
|
||||
/*
|
||||
* Corrects a windows path to unix format (including \\?\c:...)
|
||||
*/
|
||||
* Corrects a windows path to unix format (including \\?\c:...)
|
||||
*/
|
||||
export function correctPath(filepath) {
|
||||
return unixify(filepath.replace(/^\\\\\?\\.:\\/,'\\'));
|
||||
}
|
||||
return unixify(filepath.replace(/^\\\\\?\\.:\\/, '\\'));
|
||||
}
|
||||
|
|
|
@ -8,9 +8,9 @@ const root = new URL('../../fixtures/alias/', import.meta.url);
|
|||
|
||||
describe('dev container', () => {
|
||||
it('can render requests', async () => {
|
||||
|
||||
const fs = createFs({
|
||||
'/src/pages/index.astro': `
|
||||
const fs = createFs(
|
||||
{
|
||||
'/src/pages/index.astro': `
|
||||
---
|
||||
const name = 'Testing';
|
||||
---
|
||||
|
@ -20,13 +20,15 @@ describe('dev container', () => {
|
|||
<h1>{name}</h1>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
}, root);
|
||||
`,
|
||||
},
|
||||
root
|
||||
);
|
||||
|
||||
await runInContainer({ fs, root }, async container => {
|
||||
await runInContainer({ fs, root }, async (container) => {
|
||||
const { req, res, text } = createRequestAndResponse({
|
||||
method: 'GET',
|
||||
url: '/'
|
||||
url: '/',
|
||||
});
|
||||
container.handle(req, res);
|
||||
const html = await text();
|
||||
|
|
|
@ -7,7 +7,7 @@ import { unixify } from './correct-path.js';
|
|||
|
||||
class MyVolume extends Volume {
|
||||
existsSync(p) {
|
||||
if(p instanceof URL) {
|
||||
if (p instanceof URL) {
|
||||
p = fileURLToPath(p);
|
||||
}
|
||||
return super.existsSync(p);
|
||||
|
@ -15,12 +15,12 @@ class MyVolume extends Volume {
|
|||
}
|
||||
|
||||
export function createFs(json, root) {
|
||||
if(typeof root !== 'string') {
|
||||
if (typeof root !== 'string') {
|
||||
root = unixify(fileURLToPath(root));
|
||||
}
|
||||
|
||||
const structure = {};
|
||||
for(const [key, value] of Object.entries(json)) {
|
||||
for (const [key, value] of Object.entries(json)) {
|
||||
const fullpath = npath.posix.join(root, key);
|
||||
structure[fullpath] = value;
|
||||
}
|
||||
|
@ -61,8 +61,8 @@ export function toPromise(res) {
|
|||
// node-mocks-http doesn't correctly handle non-Buffer typed arrays,
|
||||
// so override the write method to fix it.
|
||||
const write = res.write;
|
||||
res.write = function(data, encoding) {
|
||||
if(ArrayBuffer.isView(data) && !Buffer.isBuffer(data)) {
|
||||
res.write = function (data, encoding) {
|
||||
if (ArrayBuffer.isView(data) && !Buffer.isBuffer(data)) {
|
||||
data = Buffer.from(data);
|
||||
}
|
||||
return write.call(this, data, encoding);
|
||||
|
@ -77,7 +77,7 @@ export function toPromise(res) {
|
|||
export function buffersToString(buffers) {
|
||||
let decoder = new TextDecoder();
|
||||
let str = '';
|
||||
for(const buffer of buffers) {
|
||||
for (const buffer of buffers) {
|
||||
str += decoder.decode(buffer);
|
||||
}
|
||||
return str;
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import { expect } from 'chai';
|
||||
import { createLoader } from '../../../dist/core/module-loader/index.js';
|
||||
import { createController, runWithErrorHandling } from '../../../dist/vite-plugin-astro-server/index.js';
|
||||
import {
|
||||
createController,
|
||||
runWithErrorHandling,
|
||||
} from '../../../dist/vite-plugin-astro-server/index.js';
|
||||
|
||||
describe('vite-plugin-astro-server', () => {
|
||||
describe('controller', () => {
|
||||
|
@ -15,7 +18,7 @@ describe('vite-plugin-astro-server', () => {
|
|||
},
|
||||
onError(err) {
|
||||
error = err;
|
||||
}
|
||||
},
|
||||
});
|
||||
expect(error).to.not.be.an('undefined');
|
||||
expect(error).to.be.an.instanceOf(Error);
|
||||
|
@ -29,7 +32,7 @@ describe('vite-plugin-astro-server', () => {
|
|||
run() {
|
||||
throw new Error('oh no');
|
||||
},
|
||||
onError(){}
|
||||
onError() {},
|
||||
});
|
||||
expect(controller.state.state).to.equal('error');
|
||||
});
|
||||
|
@ -40,7 +43,7 @@ describe('vite-plugin-astro-server', () => {
|
|||
eachModule() {},
|
||||
clientReload() {
|
||||
reloads++;
|
||||
}
|
||||
},
|
||||
});
|
||||
const controller = createController({ loader });
|
||||
loader.events.emit('file-change');
|
||||
|
@ -51,7 +54,7 @@ describe('vite-plugin-astro-server', () => {
|
|||
run() {
|
||||
throw new Error('oh no');
|
||||
},
|
||||
onError(){}
|
||||
onError() {},
|
||||
});
|
||||
expect(reloads).to.equal(0);
|
||||
loader.events.emit('file-change');
|
||||
|
@ -64,7 +67,7 @@ describe('vite-plugin-astro-server', () => {
|
|||
eachModule() {},
|
||||
clientReload() {
|
||||
reloads++;
|
||||
}
|
||||
},
|
||||
});
|
||||
const controller = createController({ loader });
|
||||
loader.events.emit('file-change');
|
||||
|
@ -75,7 +78,7 @@ describe('vite-plugin-astro-server', () => {
|
|||
run() {
|
||||
throw new Error('oh no');
|
||||
},
|
||||
onError(){}
|
||||
onError() {},
|
||||
});
|
||||
expect(reloads).to.equal(0);
|
||||
loader.events.emit('file-change');
|
||||
|
@ -87,7 +90,7 @@ describe('vite-plugin-astro-server', () => {
|
|||
controller,
|
||||
pathname: '/',
|
||||
// No error here
|
||||
run() {}
|
||||
run() {},
|
||||
});
|
||||
loader.events.emit('file-change');
|
||||
expect(reloads).to.equal(2);
|
||||
|
@ -106,7 +109,7 @@ describe('vite-plugin-astro-server', () => {
|
|||
},
|
||||
invalidateModule(mod) {
|
||||
mod.ssrError = null;
|
||||
}
|
||||
},
|
||||
});
|
||||
const controller = createController({ loader });
|
||||
|
||||
|
@ -116,9 +119,9 @@ describe('vite-plugin-astro-server', () => {
|
|||
run() {
|
||||
throw new Error('oh no');
|
||||
},
|
||||
onError(){}
|
||||
onError() {},
|
||||
});
|
||||
|
||||
|
||||
loader.events.emit('file-change');
|
||||
|
||||
expect(mods).to.deep.equal([
|
||||
|
|
|
@ -12,7 +12,7 @@ import { createRequestAndResponse, createFs, createAstroModule } from '../test-u
|
|||
async function createDevEnvironment(overrides = {}) {
|
||||
const env = createBasicEnvironment({
|
||||
logging,
|
||||
renderers: []
|
||||
renderers: [],
|
||||
});
|
||||
env.settings = await createDefaultDevSettings({}, '/');
|
||||
env.settings.renderers = [];
|
||||
|
@ -31,31 +31,31 @@ describe('vite-plugin-astro-server', () => {
|
|||
return render`<div id="test">testing</div>`;
|
||||
});
|
||||
return createAstroModule(Page);
|
||||
}
|
||||
})
|
||||
},
|
||||
}),
|
||||
});
|
||||
const controller = createController({ loader: env.loader });
|
||||
const { req, res, text } = createRequestAndResponse();
|
||||
const fs = createFs({
|
||||
// Note that the content doesn't matter here because we are using a custom loader.
|
||||
'/src/pages/index.astro': ''
|
||||
}, '/');
|
||||
const manifest = createRouteManifest({
|
||||
fsMod: fs,
|
||||
settings: env.settings
|
||||
}, logging);
|
||||
const fs = createFs(
|
||||
{
|
||||
// Note that the content doesn't matter here because we are using a custom loader.
|
||||
'/src/pages/index.astro': '',
|
||||
},
|
||||
'/'
|
||||
);
|
||||
const manifest = createRouteManifest(
|
||||
{
|
||||
fsMod: fs,
|
||||
settings: env.settings,
|
||||
},
|
||||
logging
|
||||
);
|
||||
|
||||
try {
|
||||
await handleRequest(
|
||||
env,
|
||||
manifest,
|
||||
controller,
|
||||
req,
|
||||
res
|
||||
);
|
||||
await handleRequest(env, manifest, controller, req, res);
|
||||
const html = await text();
|
||||
expect(html).to.include('<div id="test">');
|
||||
} catch(err) {
|
||||
} catch (err) {
|
||||
expect(err).to.be.undefined();
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue