Skip to content

Commit

Permalink
Actions: expose utility types (#11438)
Browse files Browse the repository at this point in the history
* feat: expose ACTION_ERROR_CODES util

* feat: expose ActionHandler util type

* chore: changeset
  • Loading branch information
bholmesdev authored Jul 10, 2024
1 parent 0d6f356 commit 619f07d
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 29 deletions.
5 changes: 5 additions & 0 deletions .changeset/plenty-socks-talk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Exposes utility types from `astro:actions` for the `defineAction` handler (`ActionHandler`) and the `ActionError` code (`ActionErrorCode`).
10 changes: 7 additions & 3 deletions packages/astro/src/@types/astro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import type {
import type * as babel from '@babel/core';
import type * as rollup from 'rollup';
import type * as vite from 'vite';
import type { Accept, ActionClient, InputSchema } from '../actions/runtime/virtual/server.js';
import type {
ActionAccept,
ActionClient,
ActionInputSchema,
} from '../actions/runtime/virtual/server.js';
import type { RemotePattern } from '../assets/utils/remotePattern.js';
import type { AssetsPrefix, SerializedSSRManifest } from '../core/app/types.js';
import type { PageBuildData } from '../core/build/types.js';
Expand Down Expand Up @@ -2764,8 +2768,8 @@ interface AstroSharedContext<
* Get action result on the server when using a form POST.
*/
getActionResult: <
TAccept extends Accept,
TInputSchema extends InputSchema<TAccept>,
TAccept extends ActionAccept,
TInputSchema extends ActionInputSchema<TAccept>,
TAction extends ActionClient<unknown, TAccept, TInputSchema>,
>(
action: TAction
Expand Down
24 changes: 12 additions & 12 deletions packages/astro/src/actions/runtime/virtual/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,21 @@ export { z } from 'zod';
/** @deprecated Access context from the second `handler()` parameter. */
export const getApiContext = _getApiContext;

export type Accept = 'form' | 'json';
export type InputSchema<T extends Accept | undefined> = T extends 'form'
export type ActionAccept = 'form' | 'json';
export type ActionInputSchema<T extends ActionAccept | undefined> = T extends 'form'
? z.AnyZodObject | z.ZodType<FormData>
: z.ZodType;

type Handler<TInputSchema, TOutput> = TInputSchema extends z.ZodType
export type ActionHandler<TInputSchema, TOutput> = TInputSchema extends z.ZodType
? (input: z.infer<TInputSchema>, context: ActionAPIContext) => MaybePromise<TOutput>
: (input: any, context: ActionAPIContext) => MaybePromise<TOutput>;

export type ActionReturnType<T extends Handler<any, any>> = Awaited<ReturnType<T>>;

export type ActionClient<
TOutput,
TAccept extends Accept | undefined,
TInputSchema extends InputSchema<TAccept> | undefined,
TAccept extends ActionAccept | undefined,
TInputSchema extends ActionInputSchema<TAccept> | undefined,
> = TInputSchema extends z.ZodType
? ((
input: TAccept extends 'form' ? FormData : z.input<TInputSchema>
Expand All @@ -46,8 +46,8 @@ export type ActionClient<

export function defineAction<
TOutput,
TAccept extends Accept | undefined = undefined,
TInputSchema extends InputSchema<Accept> | undefined = TAccept extends 'form'
TAccept extends ActionAccept | undefined = undefined,
TInputSchema extends ActionInputSchema<ActionAccept> | undefined = TAccept extends 'form'
? // If `input` is omitted, default to `FormData` for forms and `any` for JSON.
z.ZodType<FormData>
: undefined,
Expand All @@ -58,7 +58,7 @@ export function defineAction<
}: {
input?: TInputSchema;
accept?: TAccept;
handler: Handler<TInputSchema, TOutput>;
handler: ActionHandler<TInputSchema, TOutput>;
}): ActionClient<TOutput, TAccept, TInputSchema> {
const serverHandler =
accept === 'form'
Expand All @@ -73,8 +73,8 @@ export function defineAction<
return serverHandler as ActionClient<TOutput, TAccept, TInputSchema>;
}

function getFormServerHandler<TOutput, TInputSchema extends InputSchema<'form'>>(
handler: Handler<TInputSchema, TOutput>,
function getFormServerHandler<TOutput, TInputSchema extends ActionInputSchema<'form'>>(
handler: ActionHandler<TInputSchema, TOutput>,
inputSchema?: TInputSchema
) {
return async (unparsedInput: unknown): Promise<Awaited<TOutput>> => {
Expand All @@ -95,8 +95,8 @@ function getFormServerHandler<TOutput, TInputSchema extends InputSchema<'form'>>
};
}

function getJsonServerHandler<TOutput, TInputSchema extends InputSchema<'json'>>(
handler: Handler<TInputSchema, TOutput>,
function getJsonServerHandler<TOutput, TInputSchema extends ActionInputSchema<'json'>>(
handler: ActionHandler<TInputSchema, TOutput>,
inputSchema?: TInputSchema
) {
return async (unparsedInput: unknown): Promise<Awaited<TOutput>> => {
Expand Down
31 changes: 17 additions & 14 deletions packages/astro/src/actions/runtime/virtual/shared.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import type { z } from 'zod';
import type { ErrorInferenceObject, MaybePromise } from '../utils.js';

type ActionErrorCode =
| 'BAD_REQUEST'
| 'UNAUTHORIZED'
| 'FORBIDDEN'
| 'NOT_FOUND'
| 'TIMEOUT'
| 'CONFLICT'
| 'PRECONDITION_FAILED'
| 'PAYLOAD_TOO_LARGE'
| 'UNSUPPORTED_MEDIA_TYPE'
| 'UNPROCESSABLE_CONTENT'
| 'TOO_MANY_REQUESTS'
| 'CLIENT_CLOSED_REQUEST'
| 'INTERNAL_SERVER_ERROR';
export const ACTION_ERROR_CODES = [
'BAD_REQUEST',
'UNAUTHORIZED',
'FORBIDDEN',
'NOT_FOUND',
'TIMEOUT',
'CONFLICT',
'PRECONDITION_FAILED',
'PAYLOAD_TOO_LARGE',
'UNSUPPORTED_MEDIA_TYPE',
'UNPROCESSABLE_CONTENT',
'TOO_MANY_REQUESTS',
'CLIENT_CLOSED_REQUEST',
'INTERNAL_SERVER_ERROR',
] as const;

export type ActionErrorCode = (typeof ACTION_ERROR_CODES)[number];

const codeToStatusMap: Record<ActionErrorCode, number> = {
// Implemented from tRPC error code table
Expand Down

0 comments on commit 619f07d

Please sign in to comment.