Справочник API Actions
Добавлено в: astro@4.15.0
Actions (Действия) помогают создавать типобезопасный бэкенд, который можно вызывать из клиентского кода и HTML-форм. Все утилиты для определения и вызова действий доступны в модуле astro:actions. Примеры и инструкции по использованию смотрите в руководстве по Actions.
Импорт из astro:actions
Заголовок раздела «Импорт из astro:actions»import { ACTION_QUERY_PARAMS, ActionError, actions, defineAction, getActionContext, getActionPath, isActionError, isInputError, } from 'astro:actions';defineAction()
Заголовок раздела «defineAction()»Тип: ({ accept, input, handler }) => ActionClient
Утилита для определения новых действий в файле src/actions/index.ts. Принимает функцию handler(), содержащую серверную логику для запуска, и необязательное свойство input для валидации входных параметров во время выполнения.
import { defineAction } from 'astro:actions';import { z } from 'astro/zod';
export const server = { getGreeting: defineAction({ input: z.object({ name: z.string(), }), handler: async (input, context) => { return `Привет, ${input.name}!` } })}Свойство handler()
Заголовок раздела «Свойство handler()»Тип: (input: TInputSchema, context: ActionAPIContext) => TOutput | Promise<TOutput>
Обязательная функция, содержащая серверную логику, которая выполняется при вызове действия. Данные, возвращаемые из handler(), автоматически сериализуются и отправляются вызывающей стороне.
handler() вызывается с пользовательским вводом в качестве первого аргумента. Если установлен валидатор input, пользовательский ввод будет проверен перед передачей в обработчик. Второй аргумент — это подмножество объекта context Astro.
Возвращаемые значения парсятся с использованием библиотеки devalue. Она поддерживает значения JSON и экземпляры Date(), Map(), Set() и URL().
Валидатор input
Заголовок раздела «Валидатор input»Тип: ZodType | undefined
Необязательное свойство, которое принимает валидатор Zod (например, объект Zod, дискриминируемое объединение Zod) для проверки входных данных обработчика во время выполнения. Если действие не проходит валидацию, возвращается ошибка BAD_REQUEST, и handler не вызывается.
Если input опущен, handler получит ввод типа unknown для запросов JSON и типа FormData для запросов формы.
Свойство accept
Заголовок раздела «Свойство accept»Тип: "form" | "json"
По умолчанию: json
Определяет формат, ожидаемый действием:
- Используйте
form, когда ваше действие принимаетFormData. - Используйте
json(по умолчанию) для всех остальных случаев.
Когда ваше действие принимает ввод формы, валидатор z.object() автоматически распарсит FormData в типизированный объект. Для валидации ввода поддерживаются все валидаторы Zod.
actions
Заголовок раздела «actions»Тип: Record<string, ActionClient>
Объект, содержащий все ваши действия, где имя действия является ключом, связанным с функцией для вызова этого действия.
------
<script>import { actions } from 'astro:actions';
async () => { const { data, error } = await actions.myAction({ /* ... */ });}</script>Чтобы Astro распознал это свойство, вам может потребоваться перезапустить сервер разработки или запустить команду astro sync (s + enter).
isInputError()
Заголовок раздела «isInputError()»Тип: (error?: unknown) => boolean
Утилита, используемая для проверки, является ли ActionError ошибкой валидации ввода. Когда валидатор input представляет собой z.object(), ошибки ввода включают объект fields с сообщениями об ошибках, сгруппированными по имени.
isInputError(). isActionError()
Заголовок раздела «isActionError()»Тип: (error?: unknown) => boolean
Утилита для проверки, вызвало ли ваше действие ActionError внутри свойства handler. Это полезно при сужении типа общей ошибки.
------
<script>import { isActionError, actions } from 'astro:actions';
async () => { const { data, error } = await actions.myAction({ /* ... */ }); if (isActionError(error)) { // Обработка ошибок, специфичных для действия console.log(error.code); }}</script>ActionError
Заголовок раздела «ActionError»Конструктор ActionError() используется для создания ошибок, выбрасываемых handler действия. Он принимает свойство code, описывающее возникшую ошибку (например: "UNAUTHORIZED"), и необязательное свойство message с дополнительными деталями.
Следующий пример создает новую ActionError, когда пользователь не вошел в систему:
import { defineAction, ActionError } from "astro:actions";
export const server = { getUserOrThrow: defineAction({ accept: 'form', handler: async (_, { locals }) => { if (locals.user?.name !== 'florian') { throw new ActionError({ code: 'UNAUTHORIZED', message: 'Пользователь не авторизован', }); } return locals.user; }, }),}Вы также можете использовать ActionError для сужения типа ошибки при обработке результатов действия:
------
<script>import { ActionError, actions } from 'astro:actions';
async () => { const { data, error } = await actions.myAction({ /* ... */ }); if (error instanceof ActionError) { // Обработка ошибок, специфичных для действия console.log(error.code); }}</script>Тип: ActionErrorCode
Определяет человекочитаемую версию кода состояния HTTP.
message
Заголовок раздела «message»Тип: string
Необязательное свойство для описания ошибки (например, «Пользователь должен войти в систему.»).
Тип: string
Необязательное свойство для передачи трассировки стека.
getActionContext()
Заголовок раздела «getActionContext()»Тип: (context: APIContext) => AstroActionContext
astro@5.0.0
Функция, вызываемая из вашего обработчика middleware для получения информации о входящих запросах действий. Она возвращает объект action с информацией о запросе, метод deserializeActionResult(), а также функции setActionResult() и serializeActionResult() для программной установки значения, возвращаемого Astro.getActionResult().
getActionContext() позволяет программно получать и устанавливать результаты действий с помощью middleware, позволяя сохранять результаты действий из HTML-форм, ограничивать запросы действий дополнительными проверками безопасности и многое другое.
import { defineMiddleware } from 'astro:middleware';import { getActionContext } from 'astro:actions';
export const onRequest = defineMiddleware(async (context, next) => { const { action, setActionResult, serializeActionResult } = getActionContext(context); if (action?.calledFrom === 'form') { const result = await action.handler(); setActionResult(action.name, serializeActionResult(result)); } return next();});Тип: { calledFrom: “rpc” | “form”; name: string; handler: () => Promise<SafeResult>; } | undefined
Объект, содержащий информацию о входящем запросе действия. Он доступен из getActionContext() и предоставляет name действия, handler и информацию о том, было ли действие вызвано из клиентской функции RPC (например, actions.newsletter()) или действия HTML-формы.
import { defineMiddleware } from 'astro:middleware';import { getActionContext } from 'astro:actions';
export const onRequest = defineMiddleware(async (context, next) => { const { action, setActionResult, serializeActionResult } = getActionContext(context); if (action?.calledFrom === 'rpc' && action.name.startsWith('private')) { // Проверка на валидный токен сессии } // ...});calledFrom
Заголовок раздела «calledFrom»Тип: "rpc" | "form"
Было ли действие вызвано с использованием функции RPC или действия HTML-формы.
Тип: string
Имя действия. Полезно для отслеживания источника результата действия во время перенаправления.
handler()
Заголовок раздела «handler()»Тип: () => Promise<SafeResult>
Метод для программного вызова действия для получения результата.
setActionResult()
Заголовок раздела «setActionResult()»Тип: (actionName: string, actionResult: SerializedActionResult) => void
Функция для программной установки значения, возвращаемого Astro.getActionResult() в middleware. Ей передается имя действия и результат действия, сериализованный с помощью serializeActionResult(). Вызов этой функции из middleware отключит собственную обработку результатов действий Astro.
Это полезно при вызове действий из HTML-формы для сохранения и загрузки результатов из сессии.
import { defineMiddleware } from 'astro:middleware';import { getActionContext } from 'astro:actions';export const onRequest = defineMiddleware(async (context, next) => { const { action, setActionResult, serializeActionResult } = getActionContext(context); if (action?.calledFrom === 'form') { const result = await action.handler(); // ... обработка результата действия setActionResult(action.name, serializeActionResult(result)); } return next();});serializeActionResult()
Заголовок раздела «serializeActionResult()»Тип: (res: SafeResult) => SerializedActionResult
Сериализует результат действия в JSON для сохранения. Это необходимо для правильной обработки значений, не являющихся JSON, таких как Map или Date, а также объекта ActionError.
Вызывайте эту функцию при сериализации результата действия для передачи в setActionResult():
import { defineMiddleware } from 'astro:middleware';import { getActionContext } from 'astro:actions';
export const onRequest = defineMiddleware(async (context, next) => { const { action, setActionResult, serializeActionResult } = getActionContext(context); if (action) { const result = await action.handler(); setActionResult(action.name, serializeActionResult(result)); } // ...});deserializeActionResult()
Заголовок раздела «deserializeActionResult()»Тип: (res: SerializedActionResult) => SafeResult
Отменяет эффект serializeActionResult() и возвращает результат действия в исходное состояние. Это полезно для доступа к объектам data и error в сериализованном результате действия.
getActionPath()
Заголовок раздела «getActionPath()»Тип: (action: ActionClient) => string
astro@5.1.0
Утилита, которая принимает действие и возвращает URL-путь, чтобы вы могли выполнить вызов действия как операцию fetch() напрямую. Это позволяет предоставлять такие детали, как пользовательские заголовки, при вызове вашего действия. Затем вы можете обрабатывать возвращаемые данные в пользовательском формате по мере необходимости, как если бы вы вызвали действие напрямую.
Этот пример показывает, как вызвать определенное действие like, передав заголовок Authorization и опцию keepalive:
<script>import { actions, getActionPath } from 'astro:actions'
await fetch(getActionPath(actions.like), { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: 'Bearer YOUR_TOKEN' }, body: JSON.stringify({ id: 'YOUR_ID' }), keepalive: true})</script>Этот пример показывает, как вызвать то же действие like с помощью API sendBeacon:
<script>import { actions, getActionPath } from 'astro:actions'
navigator.sendBeacon( getActionPath(actions.like), new Blob([JSON.stringify({ id: 'YOUR_ID' })], { type: 'application/json' }))</script>ACTION_QUERY_PARAMS
Заголовок раздела «ACTION_QUERY_PARAMS»Тип: { actionName: string, actionPayload: string }
Объект, содержащий имена параметров запроса, используемых Astro внутренне при обработке отправки действий формы.
Когда вы отправляете форму с использованием действия, следующие параметры запроса добавляются к URL для отслеживания вызова действия:
actionName— Параметр запроса, содержащий имя вызываемого действияactionPayload— Параметр запроса, содержащий сериализованные данные формы
Эта константа может быть полезна, когда вам нужно очистить URL после отправки формы. Например, вы можете захотеть удалить параметры запроса, связанные с действием, во время перенаправления:
import type { APIRoute } from "astro";import { ACTION_QUERY_PARAMS } from 'astro:actions'
export const GET: APIRoute = ({ params, request }) => { const link = request.url.searchParams; link.delete(ACTION_QUERY_PARAMS.actionName); link.delete(ACTION_QUERY_PARAMS.actionPayload);
return redirect(link, 303);};Типы astro:actions
Заголовок раздела «Типы astro:actions»import type { ActionAPIContext, ActionClient, ActionErrorCode, ActionInputSchema, ActionReturnType, SafeResult, } from 'astro:actions';ActionAPIContext
Заголовок раздела «ActionAPIContext»Подмножество объекта контекста Astro. Следующие свойства недоступны: callAction, getActionResult, props и redirect.
ActionClient
Заголовок раздела «ActionClient»Типы:
-
(input?: any) => Promise<SafeResult> { queryString?: string; orThrow: (input?: any) => Promise<Awaited<TOutput>>; }
Представляет действие, которое будет вызвано на клиенте. Вы можете использовать его как функцию, которая принимает входные данные и возвращает Promise с объектом SafeResult, содержащим результат действия или ошибки валидации.
Следующий пример показывает, как можно обеспечить обработку ошибок с помощью оператора if, когда увеличение количества лайков не удается:
------
<!-- ваш шаблон -->
<script>import { actions } from 'astro:actions';
const post = document.querySelector('article');const button = document.querySelector('button');button?.addEventListener('click', async () => { const { data: updatedLikes, error } = await actions.likePost({ postId: post?.id }); if (error) { /* обработка ошибок */ }})</script>В качестве альтернативы вы можете использовать его как объект, дающий доступ к queryString и альтернативному методу orThrow().
Свойство queryString
Заголовок раздела «Свойство queryString»Тип: string
Строковое представление действия, которое можно использовать для создания URL-адресов действий формы. Это может быть полезно, когда ваш компонент формы используется в нескольких местах, но вам нужно перенаправить на другой URL при отправке.
Следующий пример использует queryString для создания URL, который будет передан в атрибут action формы через пользовательский проп:
---import { actions } from 'astro:actions';import FeedbackForm from "../components/FeedbackForm.astro";
const feedbackUrl = new URL('/feedback', Astro.url);feedbackUrl.search = actions.myAction.queryString;---<FeedbackForm sendTo={feedbackUrl.pathname} />Свойство orThrow()
Заголовок раздела «Свойство orThrow()»Тип: (input?: any) => Promise<Awaited<TOutput>>
Метод, который выбрасывает ошибку при неудаче вместо возврата объекта с ошибками. Это полезно, когда вы предпочитаете исключения, а не обработку ошибок через проверку объекта.
Следующий пример использует orThrow(), чтобы пропустить обработку ошибок, когда увеличение количества лайков не удается:
------
<!-- ваш шаблон -->
<script>import { actions } from 'astro:actions';
const post = document.querySelector('article');const button = document.querySelector('button');button?.addEventListener('click', async () => { const updatedLikes = await actions.likePost.orThrow({ postId: post?.id });})</script>ActionErrorCode
Заголовок раздела «ActionErrorCode»Тип: string
Тип объединения стандартных кодов состояния HTTP, определенных IANA, использующих человекочитаемые версии в виде строк в верхнем регистре, разделенных подчеркиванием (например, BAD_REQUEST или PAYLOAD_TOO_LARGE).
ActionInputSchema
Заголовок раздела «ActionInputSchema»Тип: ZodType
astro@5.16.0
Вспомогательный тип, который автоматически выводит тип TypeScript ввода действия на основе его схемы Zod. Это может быть полезно для ссылки на тип валидатора input действия как на объект в ваших собственных определениях типов.
Возвращает never, когда валидатор input опущен.
Следующий пример использует ActionInputSchema для действия с именем contact, чтобы:
- Получить тип схемы Zod для ввода действия.
- Получить ожидаемый тип ввода валидатора действия.
---import { actions, ActionInputSchema } from 'astro:actions';import { z } from 'astro/zod';
type ContactSchema = ActionInputSchema<typeof actions.contact>;type ContactInput = z.input<ContactSchema>;---ActionReturnType
Заголовок раздела «ActionReturnType»Тип: Awaited<ReturnType<ActionHandler>>
Вспомогательный тип, который извлекает тип вывода из обработчика действия. Он разворачивает как Promise (если обработчик асинхронный), так и ReturnType, чтобы дать вам фактический тип вывода. Это может быть полезно, если вам нужно ссылаться на тип вывода действия в ваших собственных определениях типов.
Следующий пример использует ActionReturnType для получения ожидаемого типа вывода для действия с именем contact:
---import { actions, ActionReturnType } from 'astro:actions';
type ContactResult = ActionReturnType<typeof actions.contact>;---SafeResult
Заголовок раздела «SafeResult»Тип: { data: TOutput, error: undefined } | { data: undefined, error: ActionError }
Представляет результат вызова действия:
- при успехе
dataсодержит вывод действия, аerror—undefined. - при неудаче
errorсодержитActionErrorс ошибками валидации или ошибками времени выполнения, аdata—undefined.