Перейти к содержимому

Справочник API Actions

Добавлено в: astro@4.15.0

Actions (Действия) помогают создавать типобезопасный бэкенд, который можно вызывать из клиентского кода и HTML-форм. Все утилиты для определения и вызова действий доступны в модуле astro:actions. Примеры и инструкции по использованию смотрите в руководстве по Actions.

import {
ACTION_QUERY_PARAMS,
ActionError,
actions,
defineAction,
getActionContext,
getActionPath,
isActionError,
isInputError,
} from 'astro:actions';

Тип: ({ accept, input, handler }) => ActionClient

Утилита для определения новых действий в файле src/actions/index.ts. Принимает функцию handler(), содержащую серверную логику для запуска, и необязательное свойство input для валидации входных параметров во время выполнения.

src/actions/index.ts
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}!`
}
})
}

Тип: (input: TInputSchema, context: ActionAPIContext) => TOutput | Promise<TOutput>

Обязательная функция, содержащая серверную логику, которая выполняется при вызове действия. Данные, возвращаемые из handler(), автоматически сериализуются и отправляются вызывающей стороне.

handler() вызывается с пользовательским вводом в качестве первого аргумента. Если установлен валидатор input, пользовательский ввод будет проверен перед передачей в обработчик. Второй аргумент — это подмножество объекта context Astro.

Возвращаемые значения парсятся с использованием библиотеки devalue. Она поддерживает значения JSON и экземпляры Date(), Map(), Set() и URL().

Тип: ZodType | undefined

Необязательное свойство, которое принимает валидатор Zod (например, объект Zod, дискриминируемое объединение Zod) для проверки входных данных обработчика во время выполнения. Если действие не проходит валидацию, возвращается ошибка BAD_REQUEST, и handler не вызывается.

Если input опущен, handler получит ввод типа unknown для запросов JSON и типа FormData для запросов формы.

Тип: "form" | "json"
По умолчанию: json

Определяет формат, ожидаемый действием:

  • Используйте form, когда ваше действие принимает FormData.
  • Используйте json (по умолчанию) для всех остальных случаев.

Когда ваше действие принимает ввод формы, валидатор z.object() автоматически распарсит FormData в типизированный объект. Для валидации ввода поддерживаются все валидаторы Zod.

Узнайте об использовании валидаторов с вводом форм в руководстве по Actions, включая примеры использования и специальную обработку ввода.

Тип: Record<string, ActionClient>

Объект, содержащий все ваши действия, где имя действия является ключом, связанным с функцией для вызова этого действия.

src/pages/index.astro
---
---
<script>
import { actions } from 'astro:actions';
async () => {
const { data, error } = await actions.myAction({ /* ... */ });
}
</script>

Чтобы Astro распознал это свойство, вам может потребоваться перезапустить сервер разработки или запустить команду astro sync (s + enter).

Тип: (error?: unknown) => boolean

Утилита, используемая для проверки, является ли ActionError ошибкой валидации ввода. Когда валидатор input представляет собой z.object(), ошибки ввода включают объект fields с сообщениями об ошибках, сгруппированными по имени.

Смотрите руководство по ошибкам ввода формы для получения дополнительной информации об использовании isInputError().

Тип: (error?: unknown) => boolean

Утилита для проверки, вызвало ли ваше действие ActionError внутри свойства handler. Это полезно при сужении типа общей ошибки.

src/pages/index.astro
---
---
<script>
import { isActionError, actions } from 'astro:actions';
async () => {
const { data, error } = await actions.myAction({ /* ... */ });
if (isActionError(error)) {
// Обработка ошибок, специфичных для действия
console.log(error.code);
}
}
</script>

Конструктор ActionError() используется для создания ошибок, выбрасываемых handler действия. Он принимает свойство code, описывающее возникшую ошибку (например: "UNAUTHORIZED"), и необязательное свойство message с дополнительными деталями.

Следующий пример создает новую ActionError, когда пользователь не вошел в систему:

src/actions/index.ts
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 для сужения типа ошибки при обработке результатов действия:

src/pages/index.astro
---
---
<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.

Тип: string

Необязательное свойство для описания ошибки (например, «Пользователь должен войти в систему.»).

Тип: string

Необязательное свойство для передачи трассировки стека.

Тип: (context: APIContext) => AstroActionContext

Добавлено в: astro@5.0.0

Функция, вызываемая из вашего обработчика middleware для получения информации о входящих запросах действий. Она возвращает объект action с информацией о запросе, метод deserializeActionResult(), а также функции setActionResult() и serializeActionResult() для программной установки значения, возвращаемого Astro.getActionResult().

getActionContext() позволяет программно получать и устанавливать результаты действий с помощью middleware, позволяя сохранять результаты действий из HTML-форм, ограничивать запросы действий дополнительными проверками безопасности и многое другое.

src/middleware.ts
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-формы.

src/middleware.ts
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')) {
// Проверка на валидный токен сессии
}
// ...
});

Тип: "rpc" | "form"

Было ли действие вызвано с использованием функции RPC или действия HTML-формы.

Тип: string

Имя действия. Полезно для отслеживания источника результата действия во время перенаправления.

Тип: () => Promise<SafeResult>

Метод для программного вызова действия для получения результата.

Тип: (actionName: string, actionResult: SerializedActionResult) => void

Функция для программной установки значения, возвращаемого Astro.getActionResult() в middleware. Ей передается имя действия и результат действия, сериализованный с помощью serializeActionResult(). Вызов этой функции из middleware отключит собственную обработку результатов действий Astro.

Это полезно при вызове действий из HTML-формы для сохранения и загрузки результатов из сессии.

src/middleware.ts
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();
});
Смотрите руководство по продвинутым сессиям для примера реализации с использованием Netlify Blob.

Тип: (res: SafeResult) => SerializedActionResult

Сериализует результат действия в JSON для сохранения. Это необходимо для правильной обработки значений, не являющихся JSON, таких как Map или Date, а также объекта ActionError.

Вызывайте эту функцию при сериализации результата действия для передачи в setActionResult():

src/middleware.ts
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));
}
// ...
});

Тип: (res: SerializedActionResult) => SafeResult

Отменяет эффект serializeActionResult() и возвращает результат действия в исходное состояние. Это полезно для доступа к объектам data и error в сериализованном результате действия.

Тип: (action: ActionClient) => string

Добавлено в: astro@5.1.0

Утилита, которая принимает действие и возвращает URL-путь, чтобы вы могли выполнить вызов действия как операцию fetch() напрямую. Это позволяет предоставлять такие детали, как пользовательские заголовки, при вызове вашего действия. Затем вы можете обрабатывать возвращаемые данные в пользовательском формате по мере необходимости, как если бы вы вызвали действие напрямую.

Этот пример показывает, как вызвать определенное действие like, передав заголовок Authorization и опцию keepalive:

src/components/my-component.astro
<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:

src/components/my-component.astro
<script>
import { actions, getActionPath } from 'astro:actions'
navigator.sendBeacon(
getActionPath(actions.like),
new Blob([JSON.stringify({ id: 'YOUR_ID' })], {
type: 'application/json'
})
)
</script>

Тип: { actionName: string, actionPayload: string }

Объект, содержащий имена параметров запроса, используемых Astro внутренне при обработке отправки действий формы.

Когда вы отправляете форму с использованием действия, следующие параметры запроса добавляются к URL для отслеживания вызова действия:

  • actionName — Параметр запроса, содержащий имя вызываемого действия
  • actionPayload — Параметр запроса, содержащий сериализованные данные формы

Эта константа может быть полезна, когда вам нужно очистить URL после отправки формы. Например, вы можете захотеть удалить параметры запроса, связанные с действием, во время перенаправления:

src/pages/api/contact.ts
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);
};
import type {
ActionAPIContext,
ActionClient,
ActionErrorCode,
ActionInputSchema,
ActionReturnType,
SafeResult,
} from 'astro:actions';

Подмножество объекта контекста Astro. Следующие свойства недоступны: callAction, getActionResult, props и redirect.

Типы:

  • (input?: any) => Promise<SafeResult>
  • { queryString?: string; orThrow: (input?: any) => Promise<Awaited<TOutput>>; }

Представляет действие, которое будет вызвано на клиенте. Вы можете использовать его как функцию, которая принимает входные данные и возвращает Promise с объектом SafeResult, содержащим результат действия или ошибки валидации.

Следующий пример показывает, как можно обеспечить обработку ошибок с помощью оператора if, когда увеличение количества лайков не удается:

src/pages/posts/post-1.astro
---
---
<!-- ваш шаблон -->
<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().

Тип: string

Строковое представление действия, которое можно использовать для создания URL-адресов действий формы. Это может быть полезно, когда ваш компонент формы используется в нескольких местах, но вам нужно перенаправить на другой URL при отправке.

Следующий пример использует queryString для создания URL, который будет передан в атрибут action формы через пользовательский проп:

src/pages/postal-service.astro
---
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} />

Тип: (input?: any) => Promise<Awaited<TOutput>>

Метод, который выбрасывает ошибку при неудаче вместо возврата объекта с ошибками. Это полезно, когда вы предпочитаете исключения, а не обработку ошибок через проверку объекта.

Следующий пример использует orThrow(), чтобы пропустить обработку ошибок, когда увеличение количества лайков не удается:

src/pages/posts/post-1.astro
---
---
<!-- ваш шаблон -->
<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>

Тип: string

Тип объединения стандартных кодов состояния HTTP, определенных IANA, использующих человекочитаемые версии в виде строк в верхнем регистре, разделенных подчеркиванием (например, BAD_REQUEST или PAYLOAD_TOO_LARGE).

Тип: ZodType

Добавлено в: astro@5.16.0

Вспомогательный тип, который автоматически выводит тип TypeScript ввода действия на основе его схемы Zod. Это может быть полезно для ссылки на тип валидатора input действия как на объект в ваших собственных определениях типов.

Возвращает never, когда валидатор input опущен.

Следующий пример использует ActionInputSchema для действия с именем contact, чтобы:

  • Получить тип схемы Zod для ввода действия.
  • Получить ожидаемый тип ввода валидатора действия.
src/components/Form.astro
---
import { actions, ActionInputSchema } from 'astro:actions';
import { z } from 'astro/zod';
type ContactSchema = ActionInputSchema<typeof actions.contact>;
type ContactInput = z.input<ContactSchema>;
---

Тип: Awaited<ReturnType<ActionHandler>>

Вспомогательный тип, который извлекает тип вывода из обработчика действия. Он разворачивает как Promise (если обработчик асинхронный), так и ReturnType, чтобы дать вам фактический тип вывода. Это может быть полезно, если вам нужно ссылаться на тип вывода действия в ваших собственных определениях типов.

Следующий пример использует ActionReturnType для получения ожидаемого типа вывода для действия с именем contact:

src/components/Form.astro
---
import { actions, ActionReturnType } from 'astro:actions';
type ContactResult = ActionReturnType<typeof actions.contact>;
---

Тип: { data: TOutput, error: undefined } | { data: undefined, error: ActionError }

Представляет результат вызова действия:

  • при успехе data содержит вывод действия, а errorundefined.
  • при неудаче error содержит ActionError с ошибками валидации или ошибками времени выполнения, а dataundefined.