Release 2025-05-19
This commit is contained in:
184
web/src/lib/callActionWithUrlParams.ts
Normal file
184
web/src/lib/callActionWithUrlParams.ts
Normal file
@@ -0,0 +1,184 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user