mirror of
https://github.com/withastro/astro.git
synced 2025-04-07 23:41:43 -05:00
feat: add new method insertPageRoute
to container (#13358)
* feat: add new method `insertPageRoute` to container * chore: add back the correct use * Update .changeset/ninety-cups-decide.md Co-authored-by: Matt Kane <m@mk.gg> --------- Co-authored-by: Matt Kane <m@mk.gg> Co-authored-by: ascorbic <213306+ascorbic@users.noreply.github.com> Co-authored-by: florian-lefebvre <69633530+florian-lefebvre@users.noreply.github.com>
This commit is contained in:
parent
defad33140
commit
8c21663c4a
6 changed files with 98 additions and 3 deletions
22
.changeset/ninety-cups-decide.md
Normal file
22
.changeset/ninety-cups-decide.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Adds a new function called `insertPageRoute` to the Astro Container API.
|
||||
|
||||
The new function is useful when testing routes that, for some business logic, use `Astro.rewrite`.
|
||||
|
||||
For example, if you have a route `/blog/post` and for some business decision there's a rewrite to `/generic-error`, the container API implementation will look like this:
|
||||
|
||||
```js
|
||||
import Post from "../src/pages/Post.astro";
|
||||
import GenericError from "../src/pages/GenericError.astro";
|
||||
import { experimental_AstroContainer as AstroContainer } from "astro/container";
|
||||
|
||||
const container = await AstroContainer.create();
|
||||
container.insertPageRoute("/generic-error", GenericError);
|
||||
const result = await container.renderToString(Post);
|
||||
console.log(result) // this should print the response from GenericError.astro
|
||||
```
|
||||
|
||||
This new method only works for page routes, which means that endpoints aren't supported.
|
|
@ -18,7 +18,7 @@ export function PostComment({
|
|||
<form
|
||||
method="POST"
|
||||
data-testid="client"
|
||||
action={actions.blog.comment}
|
||||
action={actions.blog.comment.toString()}
|
||||
onSubmit={async (e) => {
|
||||
e.preventDefault();
|
||||
const form = e.target as HTMLFormElement;
|
||||
|
|
|
@ -539,6 +539,30 @@ export 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.
|
||||
*/
|
||||
public insertPageRoute(route: string,component: AstroComponentFactory, params?: Record<string, string | undefined>) {
|
||||
const url = new URL(route, 'https://example.com/');
|
||||
const routeData: 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: URL, params: Record<string, string | undefined>, type: RouteType): RouteData {
|
||||
const segments = removeLeadingForwardSlash(url.pathname)
|
||||
.split(posix.sep)
|
||||
|
|
|
@ -89,6 +89,11 @@ export 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: RouteData): Promise<ComponentInstance> {}
|
||||
async getComponentByRoute(routeData: RouteData): Promise<ComponentInstance> {
|
||||
const page = this.#componentsInterner.get(routeData);
|
||||
if (page) {
|
||||
return page.page();
|
||||
}
|
||||
throw new Error("Couldn't find component for route " + routeData.pathname);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
renderHead,
|
||||
renderSlot,
|
||||
renderTemplate,
|
||||
createAstro
|
||||
} from '../dist/runtime/server/index.js';
|
||||
import testAdapter from './test-adapter.js';
|
||||
import { loadFixture } from './test-utils.js';
|
||||
|
@ -59,6 +60,43 @@ describe('Container', () => {
|
|||
assert.match(response, /hello world/);
|
||||
});
|
||||
|
||||
it('Renders a div with hello world text', async () => {
|
||||
const $$Astro = createAstro();
|
||||
const Page = createComponent((result, props, slots) => {
|
||||
const Astro = result.createAstro($$Astro, props, slots);
|
||||
return Astro.rewrite('/example')
|
||||
});
|
||||
|
||||
const Example = createComponent((result) => {
|
||||
return render`${renderComponent(
|
||||
result,
|
||||
'BaseLayout',
|
||||
BaseLayout,
|
||||
{},
|
||||
{
|
||||
default: () => render`${maybeRenderHead(result)}<div>hello world</div>`,
|
||||
head: () => render`
|
||||
${renderComponent(
|
||||
result,
|
||||
'Fragment',
|
||||
Fragment,
|
||||
{ slot: 'head' },
|
||||
{
|
||||
default: () => render`<meta charset="utf-8">`,
|
||||
},
|
||||
)}
|
||||
`,
|
||||
},
|
||||
)}`;
|
||||
});
|
||||
|
||||
const container = await experimental_AstroContainer.create();
|
||||
container.insertPageRoute('/example', Example);
|
||||
const response = await container.renderToString(Page);
|
||||
|
||||
assert.match(response, /hello world/);
|
||||
});
|
||||
|
||||
it('Renders a slot', async () => {
|
||||
const Page = createComponent(
|
||||
(result, _props, slots) => {
|
||||
|
|
6
pnpm-lock.yaml
generated
6
pnpm-lock.yaml
generated
|
@ -2514,6 +2514,12 @@ importers:
|
|||
specifier: workspace:*
|
||||
version: link:../../..
|
||||
|
||||
packages/astro/test/fixtures/container:
|
||||
dependencies:
|
||||
astro:
|
||||
specifier: workspace:*
|
||||
version: link:../../..
|
||||
|
||||
packages/astro/test/fixtures/container-custom-renderers:
|
||||
dependencies:
|
||||
'@astrojs/react':
|
||||
|
|
Loading…
Add table
Reference in a new issue