mirror of
https://github.com/withastro/astro.git
synced 2025-03-10 23:01:26 -05:00
feat(actions): getActionPath()
This commit is contained in:
parent
ccc5ad1676
commit
4fa0dc61eb
5 changed files with 65 additions and 6 deletions
20
.changeset/wise-boxes-develop.md
Normal file
20
.changeset/wise-boxes-develop.md
Normal file
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
'astro': minor
|
||||
---
|
||||
|
||||
Exports a new `getActionPath()` helper from `astro:actions`
|
||||
|
||||
In most cases, calling an action as `actions.like()` is enough. But sometimes it's not enough, for example:
|
||||
|
||||
- You want to pass custom headers
|
||||
- You want to call the actions endpoint without `fetch`, eg. using the `navigator.sendBeacon` API
|
||||
|
||||
That's why you can now use the `getActionPath()` helper. Pass an action to it to get the pathname (prefixed by your `based` configuration) to the action:
|
||||
|
||||
```ts
|
||||
import { actions, getActionPath } from 'astro:actions'
|
||||
|
||||
const path = getActionPath(actions.like) // '/_actions/like'
|
||||
```
|
||||
|
||||
If you intent to use this server side, remember to supply a hostname (eg. using `Astro.site`).
|
|
@ -9,6 +9,7 @@ import type {
|
|||
MaybePromise,
|
||||
ActionAPIContext as _ActionAPIContext,
|
||||
} from '../utils.js';
|
||||
import type { ActionClient } from './server.js';
|
||||
|
||||
export type ActionAPIContext = _ActionAPIContext;
|
||||
export const ACTION_QUERY_PARAMS = _ACTION_QUERY_PARAMS;
|
||||
|
@ -180,6 +181,10 @@ export function getActionQueryString(name: string) {
|
|||
return `?${searchParams.toString()}`;
|
||||
}
|
||||
|
||||
export function getActionPath(action: ActionClient<any, any, any>) {
|
||||
return `${import.meta.env.BASE_URL.replace(/\/$/, '')}/_actions/${new URLSearchParams(action.toString()).get(ACTION_QUERY_PARAMS.actionName)}`;
|
||||
}
|
||||
|
||||
export type SerializedActionResult =
|
||||
| {
|
||||
type: 'data';
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
import { ActionError, deserializeActionResult, getActionQueryString } from 'astro:actions';
|
||||
import {
|
||||
ActionError,
|
||||
deserializeActionResult,
|
||||
getActionQueryString,
|
||||
getActionPath,
|
||||
} from 'astro:actions';
|
||||
|
||||
const ENCODED_DOT = '%2E';
|
||||
|
||||
|
@ -83,11 +88,18 @@ async function handleAction(param, path, context) {
|
|||
headers.set('Content-Length', '0');
|
||||
}
|
||||
}
|
||||
const rawResult = await fetch(`${import.meta.env.BASE_URL.replace(/\/$/, '')}/_actions/${path}`, {
|
||||
method: 'POST',
|
||||
body,
|
||||
headers,
|
||||
});
|
||||
const rawResult = await fetch(
|
||||
getActionPath({
|
||||
toString() {
|
||||
return path;
|
||||
},
|
||||
}),
|
||||
{
|
||||
method: 'POST',
|
||||
body,
|
||||
headers,
|
||||
},
|
||||
);
|
||||
if (rawResult.status === 204) {
|
||||
return deserializeActionResult({ type: 'empty', status: 204 });
|
||||
}
|
||||
|
|
|
@ -564,6 +564,22 @@ it('Base path should be used', async () => {
|
|||
await devServer.stop();
|
||||
});
|
||||
|
||||
it('getActionPath() should return the right path', async () => {
|
||||
const fixture = await loadFixture({
|
||||
root: './fixtures/actions/',
|
||||
adapter: testAdapter(),
|
||||
base: '/base',
|
||||
});
|
||||
const devServer = await fixture.startDevServer();
|
||||
const res = await fixture.fetch('/base/get-action-path');
|
||||
|
||||
assert.equal(res.ok, true);
|
||||
const html = await res.text();
|
||||
let $ = cheerio.load(html);
|
||||
assert.equal($('[data-path]').text(), '/base/_actions/transformFormInput');
|
||||
await devServer.stop();
|
||||
});
|
||||
|
||||
/**
|
||||
* Follow an expected redirect response.
|
||||
*
|
||||
|
|
6
packages/astro/test/fixtures/actions/src/pages/get-action-path.astro
vendored
Normal file
6
packages/astro/test/fixtures/actions/src/pages/get-action-path.astro
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
import { actions, getActionPath } from "astro:actions"
|
||||
|
||||
const path = getActionPath(actions.transformFormInput)
|
||||
---
|
||||
<p data-path>{path}</p>
|
Loading…
Add table
Reference in a new issue