refactor: use new Astro internals (#8254)

* refactor: use new Astro internals

* chore: update tests

---------

Co-authored-by: Matthew Phillips <matthew@skypack.dev>
This commit is contained in:
Emanuele Stoppa 2023-08-28 17:19:04 +01:00 committed by GitHub
parent 52f0837bde
commit c7921e9e1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 34 additions and 68 deletions

View file

@ -24,6 +24,8 @@ import type { AstroIntegrationLogger, Logger, LoggerLevel } from '../core/logger
import type { AstroComponentFactory, AstroComponentInstance } from '../runtime/server'; import type { AstroComponentFactory, AstroComponentInstance } from '../runtime/server';
import type { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from './../core/constants.js'; import type { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from './../core/constants.js';
export { type AstroIntegrationLogger };
export type { export type {
MarkdownHeading, MarkdownHeading,
MarkdownMetadata, MarkdownMetadata,
@ -2203,6 +2205,7 @@ export interface PreviewServerParams {
host: string | undefined; host: string | undefined;
port: number; port: number;
base: string; base: string;
logger: AstroIntegrationLogger;
} }
export type CreatePreviewServer = ( export type CreatePreviewServer = (

View file

@ -27,6 +27,7 @@ import { matchRoute } from '../routing/match.js';
import { EndpointNotFoundError, SSRRoutePipeline } from './ssrPipeline.js'; import { EndpointNotFoundError, SSRRoutePipeline } from './ssrPipeline.js';
import type { RouteInfo } from './types'; import type { RouteInfo } from './types';
export { deserializeManifest } from './common.js'; export { deserializeManifest } from './common.js';
import { AstroIntegrationLogger } from '../logger/core.js';
const clientLocalsSymbol = Symbol.for('astro.locals'); const clientLocalsSymbol = Symbol.for('astro.locals');
@ -58,6 +59,7 @@ export class App {
#pipeline: SSRRoutePipeline; #pipeline: SSRRoutePipeline;
#onRequest: MiddlewareEndpointHandler | undefined; #onRequest: MiddlewareEndpointHandler | undefined;
#middlewareLoaded: boolean; #middlewareLoaded: boolean;
#adapterLogger: AstroIntegrationLogger;
constructor(manifest: SSRManifest, streaming = true) { constructor(manifest: SSRManifest, streaming = true) {
this.#manifest = manifest; this.#manifest = manifest;
@ -68,10 +70,14 @@ export class App {
this.#baseWithoutTrailingSlash = removeTrailingForwardSlash(this.#manifest.base); this.#baseWithoutTrailingSlash = removeTrailingForwardSlash(this.#manifest.base);
this.#pipeline = new SSRRoutePipeline(this.#createEnvironment(streaming)); this.#pipeline = new SSRRoutePipeline(this.#createEnvironment(streaming));
this.#middlewareLoaded = false; this.#middlewareLoaded = false;
this.#adapterLogger = new AstroIntegrationLogger(
this.#logger.options,
this.#manifest.adapterName
);
} }
set setManifest(newManifest: SSRManifest) { getAdapterLogger(): AstroIntegrationLogger {
this.#manifest = newManifest; return this.#adapterLogger;
} }
/** /**

View file

@ -9,6 +9,7 @@ import { createNodeLogger } from '../config/logging.js';
import { createSettings } from '../config/settings.js'; import { createSettings } from '../config/settings.js';
import createStaticPreviewServer from './static-preview-server.js'; import createStaticPreviewServer from './static-preview-server.js';
import { getResolvedHostForHttpServer } from './util.js'; import { getResolvedHostForHttpServer } from './util.js';
import { AstroIntegrationLogger } from '../../core/logger/core.js';
/** /**
* Starts a local server to serve your static dist/ directory. This command is useful for previewing * Starts a local server to serve your static dist/ directory. This command is useful for previewing
@ -62,6 +63,7 @@ export default async function preview(inlineConfig: AstroInlineConfig): Promise<
host: getResolvedHostForHttpServer(settings.config.server.host), host: getResolvedHostForHttpServer(settings.config.server.host),
port: settings.config.server.port, port: settings.config.server.port,
base: settings.config.base, base: settings.config.base,
logger: new AstroIntegrationLogger(logger.options, settings.adapter.name),
}); });
return server; return server;

View file

@ -1,45 +0,0 @@
// TODO: remove `getRuntime()` in Astro 3.0
import type { Cache, CacheStorage, IncomingRequestCfProperties } from '@cloudflare/workers-types';
export type WorkerRuntime<T = unknown> = {
name: 'cloudflare';
env: T;
waitUntil(promise: Promise<any>): void;
passThroughOnException(): void;
caches?: CacheStorage & { default: Cache };
cf?: IncomingRequestCfProperties;
};
export type PagesRuntime<T = unknown, U = unknown> = {
name: 'cloudflare';
env: T;
functionPath: string;
params: Record<string, string>;
data: U;
waitUntil(promise: Promise<any>): void;
next(request: Request): void;
caches?: CacheStorage & { default: Cache };
cf?: IncomingRequestCfProperties;
};
/**
* @deprecated since version 6.8.0
* The `getRuntime` utility has been deprecated and should be updated to the new [`Astro.locals`](https://docs.astro.build/en/guides/middleware/#locals) API.
* ```diff
* - import { getRuntime } from '@astrojs/cloudflare/runtime';
* - getRuntime(Astro.request);
*
* + const runtime = Astro.locals.runtime;
* ```
*/
export function getRuntime<T = unknown, U = unknown>(
request: Request
): WorkerRuntime<T> | PagesRuntime<T, U> {
if (!!request) {
return Reflect.get(request, Symbol.for('runtime'));
} else {
throw new Error(
'To retrieve the current cloudflare runtime you need to pass in the Astro request object'
);
}
}

View file

@ -1,6 +1,5 @@
--- ---
import { getRuntime } from '@astrojs/cloudflare/runtime'; const runtime = Astro.locals.runtime;
const runtime = getRuntime(Astro.request);
--- ---
<html> <html>
<head> <head>

View file

@ -1,6 +1,6 @@
import type { AstroAdapter, AstroIntegration } from 'astro'; import type { AstroAdapter, AstroIntegration } from 'astro';
import type { Options, UserOptions } from './types'; import type { Options, UserOptions } from './types';
import { AstroError } from 'astro/errors';
export function getAdapter(options: Options): AstroAdapter { export function getAdapter(options: Options): AstroAdapter {
return { return {
name: '@astrojs/node', name: '@astrojs/node',
@ -23,7 +23,7 @@ export function getAdapter(options: Options): AstroAdapter {
export default function createIntegration(userOptions: UserOptions): AstroIntegration { export default function createIntegration(userOptions: UserOptions): AstroIntegration {
if (!userOptions?.mode) { if (!userOptions?.mode) {
throw new Error(`[@astrojs/node] Setting the 'mode' option is required.`); throw new AstroError(`Setting the 'mode' option is required.`);
} }
let _options: Options; let _options: Options;

View file

@ -4,6 +4,7 @@ import { fileURLToPath } from 'node:url';
import { getNetworkAddress } from './get-network-address.js'; import { getNetworkAddress } from './get-network-address.js';
import { createServer } from './http-server.js'; import { createServer } from './http-server.js';
import type { createExports } from './server'; import type { createExports } from './server';
import { AstroError } from 'astro/errors';
const preview: CreatePreviewServer = async function ({ const preview: CreatePreviewServer = async function ({
client, client,
@ -11,6 +12,7 @@ const preview: CreatePreviewServer = async function ({
host, host,
port, port,
base, base,
logger,
}) { }) {
type ServerModule = ReturnType<typeof createExports>; type ServerModule = ReturnType<typeof createExports>;
type MaybeServerModule = Partial<ServerModule>; type MaybeServerModule = Partial<ServerModule>;
@ -21,13 +23,13 @@ const preview: CreatePreviewServer = async function ({
if (typeof ssrModule.handler === 'function') { if (typeof ssrModule.handler === 'function') {
ssrHandler = ssrModule.handler; ssrHandler = ssrModule.handler;
} else { } else {
throw new Error( throw new AstroError(
`The server entrypoint doesn't have a handler. Are you sure this is the right file?` `The server entrypoint doesn't have a handler. Are you sure this is the right file?`
); );
} }
} catch (err) { } catch (err) {
if ((err as any).code === 'ERR_MODULE_NOT_FOUND') { if ((err as any).code === 'ERR_MODULE_NOT_FOUND') {
throw new Error( throw new AstroError(
`The server entrypoint ${fileURLToPath( `The server entrypoint ${fileURLToPath(
serverEntrypoint serverEntrypoint
)} does not exist. Have you ran a build yet?` )} does not exist. Have you ran a build yet?`
@ -63,13 +65,11 @@ const preview: CreatePreviewServer = async function ({
const address = getNetworkAddress('http', host, port); const address = getNetworkAddress('http', host, port);
if (host === undefined) { if (host === undefined) {
// eslint-disable-next-line no-console logger.info(
console.log(
`Preview server listening on \n local: ${address.local[0]} \t\n network: ${address.network[0]}\n` `Preview server listening on \n local: ${address.local[0]} \t\n network: ${address.network[0]}\n`
); );
} else { } else {
// eslint-disable-next-line no-console logger.info(`Preview server listening on ${address.local[0]}`);
console.log(`Preview server listening on ${address.local[0]}`);
} }
return server; return server;

View file

@ -6,6 +6,7 @@
import type { ReadableStreamDefaultReadResult } from 'node:stream/web'; import type { ReadableStreamDefaultReadResult } from 'node:stream/web';
import { Readable as NodeReadableStream } from 'stream'; import { Readable as NodeReadableStream } from 'stream';
import { AstroError } from 'astro/errors';
interface NodeStreamIterator<T> { interface NodeStreamIterator<T> {
next(): Promise<IteratorResult<T, boolean | undefined>>; next(): Promise<IteratorResult<T, boolean | undefined>>;
@ -221,5 +222,7 @@ export function responseIterator<T>(response: Response | Buffer): AsyncIterableI
if (isNodeReadableStream(body)) return nodeStreamIterator<T>(body); if (isNodeReadableStream(body)) return nodeStreamIterator<T>(body);
throw new Error('Unknown body type for responseIterator. Please pass a streamable response.'); throw new AstroError(
'Unknown body type for responseIterator. Please pass a streamable response.'
);
} }

View file

@ -37,6 +37,7 @@ export function getResolvedHostForHttpServer(host: string | boolean) {
} }
export default function startServer(app: NodeApp, options: Options) { export default function startServer(app: NodeApp, options: Options) {
const logger = app.getAdapterLogger();
const port = process.env.PORT ? Number(process.env.PORT) : options.port ?? 8080; const port = process.env.PORT ? Number(process.env.PORT) : options.port ?? 8080;
const { client } = resolvePaths(options); const { client } = resolvePaths(options);
const handler = middleware(app, options.mode); const handler = middleware(app, options.mode);
@ -59,13 +60,11 @@ export default function startServer(app: NodeApp, options: Options) {
const address = getNetworkAddress(protocol, host, port); const address = getNetworkAddress(protocol, host, port);
if (host === undefined) { if (host === undefined) {
// eslint-disable-next-line no-console logger.info(
console.log( `Server listening on \n local: ${address.local[0]} \t\n network: ${address.network[0]}\n`
`Preview server listening on \n local: ${address.local[0]} \t\n network: ${address.network[0]}\n`
); );
} else { } else {
// eslint-disable-next-line no-console logger.info(`Server listening on ${address.local[0]}`);
console.log(`Preview server listening on ${address.local[0]}`);
} }
return { return {

View file

@ -1,5 +1,5 @@
import type { AstroAdapter, AstroConfig, AstroIntegration, RouteData } from 'astro'; import type { AstroAdapter, AstroConfig, AstroIntegration, RouteData } from 'astro';
import { AstroError } from 'astro/errors';
import glob from 'fast-glob'; import glob from 'fast-glob';
import { basename } from 'node:path'; import { basename } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url'; import { fileURLToPath, pathToFileURL } from 'node:url';
@ -136,10 +136,9 @@ export default function vercelServerless({
serverEntry = config.build.serverEntry; serverEntry = config.build.serverEntry;
if (config.output === 'static') { if (config.output === 'static') {
throw new Error(` throw new AstroError(
[@astrojs/vercel] \`output: "server"\` or \`output: "hybrid"\` is required to use the serverless adapter. '`output: "server"` or `output: "hybrid"` is required to use the serverless adapter.'
);
`);
} }
}, },