summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/astro/src/@types/astro.ts72
-rw-r--r--packages/astro/src/core/README.md51
-rw-r--r--packages/astro/src/core/constants.ts43
-rw-r--r--packages/astro/src/core/create-vite.ts2
-rw-r--r--packages/astro/src/core/messages.ts6
-rw-r--r--packages/astro/src/core/polyfill.ts4
-rw-r--r--packages/astro/src/core/render-context.ts4
-rw-r--r--packages/astro/src/core/request.ts7
8 files changed, 150 insertions, 39 deletions
diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts
index df45fa410..01925212f 100644
--- a/packages/astro/src/@types/astro.ts
+++ b/packages/astro/src/@types/astro.ts
@@ -2352,7 +2352,9 @@ interface AstroSharedContext<
RouteParams extends Record<string, string | undefined> = Record<string, string | undefined>,
> {
/**
- * The address (usually IP address) of the user. Used with SSR only.
+ * The address (usually IP address) of the user.
+ *
+ * Throws an error if used within a static site, or within a prerendered page.
*/
clientAddress: string;
/**
@@ -2402,15 +2404,33 @@ interface AstroSharedContext<
currentLocale: string | undefined;
}
+/**
+ * The `APIContext` is the object made available to endpoints and middleware.
+ * It is a subset of the `Astro` global object available in pages.
+ *
+ * [Reference](https://docs.astro.build/en/reference/api-reference/#endpoint-context)
+ */
export interface APIContext<
Props extends Record<string, any> = Record<string, any>,
APIParams extends Record<string, string | undefined> = Record<string, string | undefined>,
> extends AstroSharedContext<Props, Params> {
+ /**
+ * The site provided in the astro config, parsed as an instance of `URL`, without base.
+ * `undefined` if the site is not provided in the config.
+ */
site: URL | undefined;
+ /**
+ * A human-readable string representing the Astro version used to create the project.
+ * For example, `"Astro v1.1.1"`.
+ */
generator: string;
/**
- * A full URL object of the request URL.
- * Equivalent to: `new URL(request.url)`
+ * The url of the current request, parsed as an instance of `URL`.
+ *
+ * Equivalent to:
+ * ```ts
+ * new URL(context.request.url)
+ * ```
*/
url: AstroSharedContext['url'];
/**
@@ -2420,6 +2440,8 @@ export interface APIContext<
*
* Example usage:
* ```ts
+ * import type { APIContext } from "astro"
+ *
* export function getStaticPaths() {
* return [
* { params: { id: '0' }, props: { name: 'Sarah' } },
@@ -2428,14 +2450,12 @@ export interface APIContext<
* ];
* }
*
- * export async function GET({ params }) {
- * return {
- * body: `Hello user ${params.id}!`,
- * }
+ * export async function GET({ params }: APIContext) {
+ * return new Response(`Hello user ${params.id}!`)
* }
* ```
*
- * [context reference](https://docs.astro.build/en/reference/api-reference/#contextparams)
+ * [Reference](https://docs.astro.build/en/reference/api-reference/#contextparams)
*/
params: AstroSharedContext<Props, APIParams>['params'];
/**
@@ -2443,6 +2463,8 @@ export interface APIContext<
*
* Example usage:
* ```ts
+ * import type { APIContext } from "astro"
+ *
* export function getStaticPaths() {
* return [
* { params: { id: '0' }, props: { name: 'Sarah' } },
@@ -2451,19 +2473,17 @@ export interface APIContext<
* ];
* }
*
- * export function GET({ props }) {
- * return {
- * body: `Hello ${props.name}!`,
- * }
+ * export function GET({ props }: APIContext): Response {
+ * return new Response(`Hello ${props.name}!`);
* }
* ```
- *
- * [context reference](https://docs.astro.build/en/guides/api-reference/#contextprops)
+ *
+ * [Reference](https://docs.astro.build/en/guides/api-reference/#contextprops)
*/
props: AstroSharedContext<Props, APIParams>['props'];
/**
- * Redirect to another page. Only available in SSR builds.
- *
+ * Create a response that redirects to another page.
+ *
* Example usage:
* ```ts
* // src/pages/secret.ts
@@ -2472,18 +2492,20 @@ export interface APIContext<
* }
* ```
*
- * [context reference](https://docs.astro.build/en/guides/api-reference/#contextredirect)
+ * [Reference](https://docs.astro.build/en/guides/api-reference/#contextredirect)
*/
redirect: AstroSharedContext['redirect'];
/**
- * Object accessed via Astro middleware.
- *
+ * An object that middlewares can use to store extra information related to the request.
+ *
+ * It will be made available to pages as `Astro.locals`, and to endpoints as `context.locals`.
+ *
* Example usage:
- *
+ *
* ```ts
* // src/middleware.ts
- * import {defineMiddleware} from "astro:middleware";
+ * import { defineMiddleware } from "astro:middleware";
*
* export const onRequest = defineMiddleware((context, next) => {
* context.locals.greeting = "Hello!";
@@ -2498,6 +2520,8 @@ export interface APIContext<
* ---
* <h1>{greeting}</h1>
* ```
+ *
+ * [Reference](https://docs.astro.build/en/reference/api-reference/#contextlocals)
*/
locals: App.Locals;
@@ -2535,12 +2559,6 @@ export interface APIContext<
currentLocale: string | undefined;
}
-// eslint-disable-next-line @typescript-eslint/no-unused-vars
-type Routing = {
- prefixDefaultLocale: boolean;
- strategy: 'pathname';
-};
-
export type APIRoute<
Props extends Record<string, any> = Record<string, any>,
APIParams extends Record<string, string | undefined> = Record<string, string | undefined>,
diff --git a/packages/astro/src/core/README.md b/packages/astro/src/core/README.md
index ef4dd8750..94eff9e05 100644
--- a/packages/astro/src/core/README.md
+++ b/packages/astro/src/core/README.md
@@ -1,20 +1,51 @@
# `core/`
-Code that executes within the top-level Node context. Contains the main Astro logic for the `build`, `dev`, `preview`, and `sync` commands, and also manages the Vite server and SSR.
+Code that executes directly on Node (not processed by vite). Contains the main Astro logic for the `build`, `dev`, `preview`, and `sync` commands, and also manages the lifecycle of the Vite server.
-The `core/index.ts` file is the main entry point for the `astro` package.
+The `core/index.ts` module exports the CLI commands as functions and is the main entrypoint of the `astro` package.
+```ts
+import { dev, build, preview, sync } from 'astro';
+```
[See CONTRIBUTING.md](../../../../CONTRIBUTING.md) for a code overview.
-## Pipeline
+```
+ Pages
+ used by /
+ /
+ creates /
+ App --------- AppPipeline AstroGlobal
+ \ implements /
+ \ creates /
+ creates impl.\ provided to /
+vite-plugin-astro-server --------- DevPipeline ------ Pipeline ------------- RenderContext Middleware
+ / \ used by /
+ / creates \ /
+ creates / implements \ /
+ AstroBuilder --------- BuildPipeline APIContext
+ \
+ \
+ used by \
+ Endpoints
+```
-The pipeline is an internal concept that describes how Astro pages are eventually created and rendered to the user.
+## `App`
-Each pipeline has different requirements, criteria and quirks. Although, each pipeline must use the same underline functions, because
-the core of the pipeline is the same.
+## `vite-plugin-astro-server` (see `../vite-plugin-astro-server/`)
-The core of the pipeline is rendering a generic route (page, endpoint or redirect) and returning a `Response`.
-When rendering a route, a pipeline must pass a `RenderContext` and `ComponentInstance`. The way these two information are
-computed doesn't concern the core of a pipeline. In fact, these types will be computed in different manner based on the type of pipeline.
+## `AstroBuilder`
-Each consumer will decide how to handle a `Response`.
+## `Pipeline`
+
+The pipeline is an interface representing data that stays unchanged throughout the duration of the server or build. For example: the user configuration, the list of pages and endpoints in the project, and environment-specific way of gathering scripts and styles.
+
+There are 3 implementations of the pipeline:
+- `DevPipeline`: in-use during the `astro dev` CLI command. Created and used by `vite-plugin-astro-server`, and then forwarded to other internals.
+- `BuildPipeline`: in-use during the `astro build` command in `"static"` mode, and for prerendering in `"server"` and `"hybrid"` output modes. See `core/build/`.
+- `AppPipeline`: in-use during production server(less) deployments. Created and used by `App` (see `core/app/`), and then forwarded to other internals.
+
+All 3 expose a common, environment-agnostic interface which is used by the rest of the internals, most notably by `RenderContext`.
+
+## `RenderContext`
+
+Each request is rendered using a `RenderContext`. It manages data unique to each request. For example: the parsed `URL`, internationalization data, the `locals` object, and the route that matched the request. It is responsible for executing middleware, calling endpoints, and rendering pages by gathering necessary data from a `Pipeline`.
diff --git a/packages/astro/src/core/constants.ts b/packages/astro/src/core/constants.ts
index aabdcbcab..c7431aa96 100644
--- a/packages/astro/src/core/constants.ts
+++ b/packages/astro/src/core/constants.ts
@@ -1,9 +1,35 @@
// process.env.PACKAGE_VERSION is injected when we build and publish the astro package.
export const ASTRO_VERSION = process.env.PACKAGE_VERSION ?? 'development';
+/**
+ * The name for the header used to help rerouting behavior.
+ * When set to "no", astro will NOT try to reroute an error response to the corresponding error page, which is the default behavior that can sometimes lead to loops.
+ *
+ * ```ts
+ * const response = new Response("keep this content as-is", {
+ * status: 404,
+ * headers: {
+ * // note that using a variable name as the key of an object needs to be wrapped in square brackets in javascript
+ * // without them, the header name will be interpreted as "REROUTE_DIRECTIVE_HEADER" instead of "X-Astro-Reroute"
+ * [REROUTE_DIRECTIVE_HEADER]: 'no',
+ * }
+ * })
+ * ```
+ * Alternatively...
+ * ```ts
+ * response.headers.set(REROUTE_DIRECTIVE_HEADER, 'no');
+ * ```
+ */
export const REROUTE_DIRECTIVE_HEADER = 'X-Astro-Reroute';
+
+/**
+ * The name for the header used to help i18n middleware, which only needs to act on "page" and "fallback" route types.
+ */
export const ROUTE_TYPE_HEADER = 'X-Astro-Route-Type';
+/**
+ * The value of the `component` field of the default 404 page, which is used when there is no user-provided 404.astro page.
+ */
export const DEFAULT_404_COMPONENT = 'astro-default-404';
/**
@@ -12,8 +38,25 @@ export const DEFAULT_404_COMPONENT = 'astro-default-404';
*/
export const REROUTABLE_STATUS_CODES = [404, 500];
+/**
+ * The symbol which is used as a field on the request object to store the client address.
+ * The clientAddresss provided by the adapter (or the dev server) is stored on this field.
+ */
export const clientAddressSymbol = Symbol.for('astro.clientAddress');
+
+/**
+ * The symbol used as a field on the request object to store the object to be made available to Astro APIs as `locals`.
+ * Use judiciously, as locals are now stored within `RenderContext` by default. Tacking it onto request is no longer necessary.
+ */
export const clientLocalsSymbol = Symbol.for('astro.locals');
+
+/**
+ * The symbol used as a field on the response object to keep track of streaming.
+ *
+ * It is set when the `<head>` element has been completely generated, rendered, and the response object has been passed onto the adapter.
+ *
+ * Used to provide helpful errors and warnings when headers or cookies are added during streaming, after the response has already been sent.
+ */
export const responseSentSymbol = Symbol.for('astro.responseSent');
// possible extensions for markdown files
diff --git a/packages/astro/src/core/create-vite.ts b/packages/astro/src/core/create-vite.ts
index 5a4046915..56092bd32 100644
--- a/packages/astro/src/core/create-vite.ts
+++ b/packages/astro/src/core/create-vite.ts
@@ -69,7 +69,7 @@ const ONLY_DEV_EXTERNAL = [
'string-width',
];
-/** Return a common starting point for all Vite actions */
+/** Return a base vite config as a common starting point for all Vite commands. */
export async function createVite(
commandConfig: vite.InlineConfig,
{ settings, logger, mode, command, fs = nodeFs }: CreateViteOptions
diff --git a/packages/astro/src/core/messages.ts b/packages/astro/src/core/messages.ts
index f69b84697..bd2cfab04 100644
--- a/packages/astro/src/core/messages.ts
+++ b/packages/astro/src/core/messages.ts
@@ -25,7 +25,11 @@ import {
} from './errors/index.js';
import { padMultilineString } from './util.js';
-/** Display */
+/**
+ * Prestyled messages for the CLI. Used by astro CLI commands.
+ */
+
+/** Display each request being served with the path and the status code. */
export function req({
url,
method,
diff --git a/packages/astro/src/core/polyfill.ts b/packages/astro/src/core/polyfill.ts
index c183d23f6..7b0280fb7 100644
--- a/packages/astro/src/core/polyfill.ts
+++ b/packages/astro/src/core/polyfill.ts
@@ -1,6 +1,10 @@
import buffer from 'node:buffer';
import crypto from 'node:crypto';
+/**
+ * Astro aims to compatible with web standards as much as possible.
+ * This function adds two objects that are globally-available on most javascript runtimes but not on node 18.
+ */
export function apply() {
// Remove when Node 18 is dropped for Node 20
if (!globalThis.crypto) {
diff --git a/packages/astro/src/core/render-context.ts b/packages/astro/src/core/render-context.ts
index 36a27c6e8..4155de863 100644
--- a/packages/astro/src/core/render-context.ts
+++ b/packages/astro/src/core/render-context.ts
@@ -29,6 +29,10 @@ import { sequence } from './middleware/index.js';
import { renderRedirect } from './redirects/render.js';
import { type Pipeline, Slots, getParams, getProps } from './render/index.js';
+/**
+ * Each request is rendered using a `RenderContext`.
+ * It contains data unique to each request. It is responsible for executing middleware, calling endpoints, and rendering the page by gathering necessary data from a `Pipeline`.
+ */
export class RenderContext {
private constructor(
readonly pipeline: Pipeline,
diff --git a/packages/astro/src/core/request.ts b/packages/astro/src/core/request.ts
index 2e77a89c1..8445792af 100644
--- a/packages/astro/src/core/request.ts
+++ b/packages/astro/src/core/request.ts
@@ -27,6 +27,13 @@ export interface CreateRequestOptions {
const clientAddressSymbol = Symbol.for('astro.clientAddress');
const clientLocalsSymbol = Symbol.for('astro.locals');
+/**
+ * Used by astro internals to create a web standard request object.
+ *
+ * The user of this function may provide the data in a runtime-agnostic way.
+ *
+ * This is used by the static build to create fake requests for prerendering, and by the dev server to convert node requests into the standard request object.
+ */
export function createRequest({
base,
url,