185 lines
5.6 KiB
TypeScript
185 lines
5.6 KiB
TypeScript
import { serialize } from 'object-to-formdata'
|
|
|
|
import { urlParamsToFormData, urlParamsToObject } from './urls'
|
|
|
|
import type { AstroGlobal } from 'astro'
|
|
import type { ActionAccept, ActionClient, SafeResult } from 'astro:actions'
|
|
import type { z } from 'astro:schema'
|
|
|
|
/**
|
|
* Call an Action directly from an Astro page or API endpoint.
|
|
*
|
|
* The action input is obtained from the URL search params.
|
|
*
|
|
* Returns a Promise with the action result.
|
|
*
|
|
* It uses {@link AstroGlobal.callAction} internally.
|
|
*
|
|
* Example usage:
|
|
*
|
|
* ```typescript
|
|
* import { actions } from 'astro:actions';
|
|
*
|
|
* const result = await callActionWithUrlParamsUnhandledErrors(Astro, actions.getPost, 'form');
|
|
* ```
|
|
*/
|
|
export function callActionWithUrlParamsUnhandledErrors<
|
|
TAccept extends ActionAccept,
|
|
TInputSchema extends z.ZodType,
|
|
TOutput,
|
|
TAction extends
|
|
| ActionClient<TOutput, TAccept, TInputSchema>
|
|
| ActionClient<TOutput, TAccept, TInputSchema>['orThrow'],
|
|
P extends Parameters<TAction>[0],
|
|
>(context: AstroGlobal, action: TAction, accept: P extends FormData ? 'form' : 'json') {
|
|
const input =
|
|
accept === 'form'
|
|
? urlParamsToFormData(context.url.searchParams)
|
|
: urlParamsToObject(context.url.searchParams)
|
|
|
|
return context.callAction(action, input as P)
|
|
}
|
|
|
|
/**
|
|
* Call an Action directly from an Astro page or API endpoint.
|
|
*
|
|
* The action input is obtained from the URL search params.
|
|
*
|
|
* Returns a Promise with the action result's data.
|
|
*
|
|
* It stores the errors in {@link context.locals.banners}
|
|
*
|
|
* It uses {@link AstroGlobal.callAction} internally.
|
|
*
|
|
* Example usage:
|
|
*
|
|
* ```typescript
|
|
* import { actions } from 'astro:actions';
|
|
*
|
|
* const data = await callActionWithUrlParams(Astro, actions.getPost, 'form');
|
|
* ```
|
|
*/
|
|
export async function callActionWithUrlParams<
|
|
TAccept extends ActionAccept,
|
|
TInputSchema extends z.ZodType,
|
|
TOutput,
|
|
TAction extends
|
|
| ActionClient<TOutput, TAccept, TInputSchema>
|
|
| ActionClient<TOutput, TAccept, TInputSchema>['orThrow'],
|
|
P extends Parameters<TAction>[0],
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
TInputSchema2 extends ReturnType<TAction> extends Promise<SafeResult<infer I, any>> ? I : never,
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
TOutput2 extends ReturnType<TAction> extends Promise<SafeResult<any, infer O>> ? O : never,
|
|
>(context: AstroGlobal, action: TAction, accept: P extends FormData ? 'form' : 'json') {
|
|
const input =
|
|
accept === 'form'
|
|
? urlParamsToFormData(context.url.searchParams)
|
|
: urlParamsToObject(context.url.searchParams)
|
|
|
|
const result = (await context.callAction(action, input as P)) as SafeResult<
|
|
TInputSchema2,
|
|
Awaited<TOutput2>
|
|
>
|
|
if (result.error) {
|
|
context.locals.banners.add({
|
|
uiMessage: result.error.message,
|
|
type: 'error',
|
|
origin: 'action',
|
|
error: result.error,
|
|
})
|
|
}
|
|
return result.data
|
|
}
|
|
|
|
/**
|
|
* Call an Action directly from an Astro page or API endpoint.
|
|
*
|
|
* Returns a Promise with the action result.
|
|
*
|
|
* It uses {@link AstroGlobal.callAction} internally.
|
|
*
|
|
* Example usage:
|
|
*
|
|
* ```typescript
|
|
* import { actions } from 'astro:actions';
|
|
*
|
|
* const input = { id: 123 }
|
|
* const result = await callActionWithObjectUnhandledErrors(Astro, actions.getPost, input, 'form');
|
|
* ```
|
|
*/
|
|
export function callActionWithObjectUnhandledErrors<
|
|
TAccept extends ActionAccept,
|
|
TInputSchema extends z.ZodType,
|
|
TOutput,
|
|
TAction extends
|
|
| ActionClient<TOutput, TAccept, TInputSchema>
|
|
| ActionClient<TOutput, TAccept, TInputSchema>['orThrow'],
|
|
P extends Parameters<TAction>[0],
|
|
TInputSchema2 extends ReturnType<TAction> extends Promise<SafeResult<infer I, unknown>> ? I : never,
|
|
>(
|
|
context: AstroGlobal,
|
|
action: TAction,
|
|
input: [TInputSchema2] extends [FormData] | [never] ? undefined : TInputSchema2,
|
|
accept: P extends FormData ? 'form' : 'json'
|
|
) {
|
|
const parsedInput = accept === 'form' ? serialize(input) : input
|
|
|
|
return context.callAction(action, parsedInput as P)
|
|
}
|
|
|
|
/**
|
|
* Call an Action directly from an Astro page or API endpoint.
|
|
*
|
|
* The action input is a plain object.
|
|
*
|
|
* Returns a Promise with the action result's data.
|
|
*
|
|
* It stores the errors in {@link context.locals.banners}
|
|
*
|
|
* It uses {@link AstroGlobal.callAction} internally.
|
|
*
|
|
* Example usage:
|
|
*
|
|
* ```typescript
|
|
* import { actions } from 'astro:actions';
|
|
*
|
|
* const input = { id: 123 }
|
|
* const data = await callActionWithObject(Astro, actions.getPost, input, 'form');
|
|
* ```
|
|
*/
|
|
export async function callActionWithObject<
|
|
TAccept extends ActionAccept,
|
|
TInputSchema extends z.ZodType,
|
|
TOutput,
|
|
TAction extends
|
|
| ActionClient<TOutput, TAccept, TInputSchema>
|
|
| ActionClient<TOutput, TAccept, TInputSchema>['orThrow'],
|
|
P extends Parameters<TAction>[0],
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
TInputSchema2 extends ReturnType<TAction> extends Promise<SafeResult<infer I, any>> ? I : never,
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
TOutput2 extends ReturnType<TAction> extends Promise<SafeResult<any, infer O>> ? O : never,
|
|
>(
|
|
context: AstroGlobal,
|
|
action: TAction,
|
|
input: [TInputSchema2] extends [FormData] | [never] ? undefined : TInputSchema2,
|
|
accept: P extends FormData ? 'form' : 'json'
|
|
) {
|
|
const parsedInput = accept === 'form' ? serialize(input) : input
|
|
|
|
const result = (await context.callAction(action, parsedInput as P)) as SafeResult<
|
|
TInputSchema2,
|
|
Awaited<TOutput2>
|
|
>
|
|
if (result.error) {
|
|
context.locals.banners.add({
|
|
uiMessage: result.error.message,
|
|
type: 'error',
|
|
origin: 'action',
|
|
error: result.error,
|
|
})
|
|
}
|
|
return result.data
|
|
}
|