full site update

This commit is contained in:
2025-07-24 18:46:24 +02:00
parent bfe2b90d8d
commit 37a6e0ab31
6912 changed files with 540482 additions and 361712 deletions

View File

@@ -1,6 +1,19 @@
import './polyfill.js';
import type { AstroUserConfig, NamedSSRLoadedRendererValue, Props, RouteType, SSRLoadedRenderer, SSRLoadedRendererValue, SSRManifest, SSRResult } from '../@types/astro.js';
import type { AstroComponentFactory } from '../runtime/server/index.js';
import type { Props } from '../types/public/common.js';
import type { AstroUserConfig } from '../types/public/config.js';
import type { NamedSSRLoadedRendererValue, RouteType, SSRLoadedRenderer, SSRLoadedRendererValue, SSRManifest, SSRResult } from '../types/public/internal.js';
/** Public type, used for integrations to define a renderer for the container API */
export type ContainerRenderer = {
/**
* The name of the renderer.
*/
name: string;
/**
* The entrypoint that is used to render a component on the server
*/
serverEntrypoint: string;
};
/**
* Options to be passed when rendering a route
*/
@@ -230,4 +243,15 @@ export declare class experimental_AstroContainer {
* @param {ContainerRenderOptions=} options Possible options to pass when rendering the component.
*/
renderToResponse(component: AstroComponentFactory, options?: ContainerRenderOptions): Promise<Response>;
/**
* It stores an Astro **page** route. The first argument, `route`, gets associated to the `component`.
*
* This function can be useful when you want to render a route via `AstroContainer.renderToString`, where that
* route eventually renders another route via `Astro.rewrite`.
*
* @param {string} route - The URL that will render the component.
* @param {AstroComponentFactory} component - The component factory to be used for rendering the route.
* @param {Record<string, string | undefined>} params - An object containing key-value pairs of route parameters.
*/
insertPageRoute(route: string, component: AstroComponentFactory, params?: Record<string, string | undefined>): void;
}

View File

@@ -1,7 +1,7 @@
import "./polyfill.js";
import { posix } from "node:path";
import { getDefaultClientDirectives } from "../core/client-directive/index.js";
import { ASTRO_CONFIG_DEFAULTS } from "../core/config/schema.js";
import { ASTRO_CONFIG_DEFAULTS } from "../core/config/schemas/index.js";
import { validateConfig } from "../core/config/validate.js";
import { createKey } from "../core/encryption.js";
import { Logger } from "../core/logger/core.js";
@@ -9,8 +9,10 @@ import { nodeLogDestination } from "../core/logger/node.js";
import { NOOP_MIDDLEWARE_FN } from "../core/middleware/noop-middleware.js";
import { removeLeadingForwardSlash } from "../core/path.js";
import { RenderContext } from "../core/render-context.js";
import { getParts, validateSegment } from "../core/routing/manifest/create.js";
import { getParts } from "../core/routing/manifest/parts.js";
import { getPattern } from "../core/routing/manifest/pattern.js";
import { validateSegment } from "../core/routing/manifest/segment.js";
import { SlotString } from "../runtime/server/render/slot.js";
import { ContainerPipeline } from "./pipeline.js";
function createManifest(manifest, renderers, middleware) {
function middlewareInstance() {
@@ -20,6 +22,12 @@ function createManifest(manifest, renderers, middleware) {
}
return {
hrefRoot: import.meta.url,
srcDir: manifest?.srcDir ?? ASTRO_CONFIG_DEFAULTS.srcDir,
buildClientDir: manifest?.buildClientDir ?? ASTRO_CONFIG_DEFAULTS.build.client,
buildServerDir: manifest?.buildServerDir ?? ASTRO_CONFIG_DEFAULTS.build.server,
publicDir: manifest?.publicDir ?? ASTRO_CONFIG_DEFAULTS.publicDir,
outDir: manifest?.outDir ?? ASTRO_CONFIG_DEFAULTS.outDir,
cacheDir: manifest?.cacheDir ?? ASTRO_CONFIG_DEFAULTS.cacheDir,
trailingSlash: manifest?.trailingSlash ?? ASTRO_CONFIG_DEFAULTS.trailingSlash,
buildFormat: manifest?.buildFormat ?? ASTRO_CONFIG_DEFAULTS.build.format,
compressHTML: manifest?.compressHTML ?? ASTRO_CONFIG_DEFAULTS.compressHTML,
@@ -31,13 +39,14 @@ function createManifest(manifest, renderers, middleware) {
clientDirectives: manifest?.clientDirectives ?? getDefaultClientDirectives(),
renderers: renderers ?? manifest?.renderers ?? [],
base: manifest?.base ?? ASTRO_CONFIG_DEFAULTS.base,
userAssetsBase: manifest?.userAssetsBase ?? "",
componentMetadata: manifest?.componentMetadata ?? /* @__PURE__ */ new Map(),
inlinedScripts: manifest?.inlinedScripts ?? /* @__PURE__ */ new Map(),
i18n: manifest?.i18n,
checkOrigin: false,
middleware: manifest?.middleware ?? middlewareInstance,
experimentalEnvGetSecretEnabled: false,
key: createKey()
key: createKey(),
csp: manifest?.csp
};
}
class experimental_AstroContainer {
@@ -47,11 +56,6 @@ class experimental_AstroContainer {
* @private
*/
#withManifest = false;
/**
* Internal function responsible for importing a renderer
* @private
*/
#getRenderer;
constructor({
streaming = false,
manifest,
@@ -179,7 +183,7 @@ class experimental_AstroContainer {
this.#pipeline.manifest.renderers[rendererIndex] = renderer;
}
// NOTE: we keep this private via TS instead via `#` so it's still available on the surface, so we can play with it.
// @ematipico: I plan to use it for a possible integration that could help people
// @ts-expect-error @ematipico: I plan to use it for a possible integration that could help people
static async createFromManifest(manifest) {
const astroConfig = await validateConfig(ASTRO_CONFIG_DEFAULTS, process.cwd(), "container");
const container = new experimental_AstroContainer({
@@ -227,6 +231,9 @@ class experimental_AstroContainer {
* @param {ContainerRenderOptions=} options Possible options to pass when rendering the component.
*/
async renderToString(component, options = {}) {
if (options.slots) {
options.slots = markAllSlotsAsSlotString(options.slots);
}
const response = await this.renderToResponse(component, options);
return await response.text();
}
@@ -267,7 +274,8 @@ class experimental_AstroContainer {
request,
pathname: url.pathname,
locals: options?.locals ?? {},
partial: options?.partial ?? true
partial: options?.partial ?? true,
clientAddress: ""
});
if (options.params) {
renderContext.params = options.params;
@@ -277,6 +285,29 @@ class experimental_AstroContainer {
}
return renderContext.render(componentInstance, slots);
}
/**
* It stores an Astro **page** route. The first argument, `route`, gets associated to the `component`.
*
* This function can be useful when you want to render a route via `AstroContainer.renderToString`, where that
* route eventually renders another route via `Astro.rewrite`.
*
* @param {string} route - The URL that will render the component.
* @param {AstroComponentFactory} component - The component factory to be used for rendering the route.
* @param {Record<string, string | undefined>} params - An object containing key-value pairs of route parameters.
*/
insertPageRoute(route, component, params) {
const url = new URL(route, "https://example.com/");
const routeData = this.#createRoute(url, params ?? {}, "page");
this.#pipeline.manifest.routes.push({
routeData,
file: "",
links: [],
styles: [],
scripts: []
});
const componentInstance = this.#wrapComponent(component, params);
this.#pipeline.insertRoute(routeData, componentInstance);
}
#createRoute(url, params, type) {
const segments = removeLeadingForwardSlash(url.pathname).split(posix.sep).filter(Boolean).map((s) => {
validateSegment(s);
@@ -298,7 +329,8 @@ class experimental_AstroContainer {
segments,
type,
fallbackRoutes: [],
isIndex: false
isIndex: false,
origin: "internal"
};
}
/**
@@ -322,6 +354,13 @@ class experimental_AstroContainer {
function isNamedRenderer(renderer) {
return !!renderer?.name;
}
function markAllSlotsAsSlotString(slots) {
const markedSlots = {};
for (const slotName in slots) {
markedSlots[slotName] = new SlotString(slots[slotName], null);
}
return markedSlots;
}
export {
experimental_AstroContainer
};

View File

@@ -1,5 +1,7 @@
import type { ComponentInstance, RewritePayload, RouteData, SSRResult } from '../@types/astro.js';
import { type HeadElements, Pipeline, type TryRewriteResult } from '../core/base-pipeline.js';
import type { ComponentInstance } from '../types/astro.js';
import type { RewritePayload } from '../types/public/common.js';
import type { RouteData, SSRResult } from '../types/public/internal.js';
export declare class ContainerPipeline extends Pipeline {
#private;
static create({ logger, manifest, renderers, resolve, serverLike, streaming, }: Pick<ContainerPipeline, 'logger' | 'manifest' | 'renderers' | 'resolve' | 'serverLike' | 'streaming'>): ContainerPipeline;
@@ -7,5 +9,5 @@ export declare class ContainerPipeline extends Pipeline {
headElements(routeData: RouteData): Promise<HeadElements> | HeadElements;
tryRewrite(payload: RewritePayload, request: Request): Promise<TryRewriteResult>;
insertRoute(route: RouteData, componentInstance: ComponentInstance): void;
getComponentByRoute(_routeData: RouteData): Promise<ComponentInstance>;
getComponentByRoute(routeData: RouteData): Promise<ComponentInstance>;
}

View File

@@ -56,7 +56,8 @@ class ContainerPipeline extends Pipeline {
routes: this.manifest?.routes.map((r) => r.routeData),
trailingSlash: this.manifest.trailingSlash,
buildFormat: this.manifest.buildFormat,
base: this.manifest.base
base: this.manifest.base,
outDir: this.manifest.outDir
});
const componentInstance = await this.getComponentByRoute(routeData);
return { componentInstance, routeData, newUrl, pathname };
@@ -71,8 +72,12 @@ class ContainerPipeline extends Pipeline {
});
}
// At the moment it's not used by the container via any public API
// @ts-expect-error It needs to be implemented.
async getComponentByRoute(_routeData) {
async getComponentByRoute(routeData) {
const page = this.#componentsInterner.get(routeData);
if (page) {
return page.page();
}
throw new Error("Couldn't find component for route " + routeData.pathname);
}
}
export {