From 0621116d85dfc55b1ee8a9b86472436e2b367bea Mon Sep 17 00:00:00 2001 From: bholmesdev Date: Fri, 26 Apr 2024 11:30:20 -0400 Subject: [PATCH] feat: add explicit `accept` property --- packages/astro/src/actions/runtime/virtual/server.ts | 12 +++++++----- packages/astro/src/actions/runtime/virtual/shared.ts | 1 + .../test/fixtures/actions-blog/src/actions/index.ts | 2 ++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/astro/src/actions/runtime/virtual/server.ts b/packages/astro/src/actions/runtime/virtual/server.ts index e8ec5142cd02..1eebb2a8cd25 100644 --- a/packages/astro/src/actions/runtime/virtual/server.ts +++ b/packages/astro/src/actions/runtime/virtual/server.ts @@ -9,10 +9,12 @@ export * from './shared.js'; export { z } from '../../../../zod.mjs'; export function defineAction({ + accept, input: inputSchema, handler, }: { input?: TInputSchema; + accept: 'json' | 'form' | 'all'; handler: (input: z.infer, context: APIContext) => MaybePromise; }): (input: z.input | FormData) => Promise> { return async (unparsedInput): Promise> => { @@ -21,14 +23,14 @@ export function defineAction({ if (!inputSchema) return await handler(unparsedInput, context); if (unparsedInput instanceof FormData) { - if (!(inputSchema instanceof z.ZodObject)) { + if (accept === 'json') { throw new ActionError({ - status: 'INTERNAL_SERVER_ERROR', - message: - '`input` must use a Zod object schema with z.object() when accepting form data.', + status: 'UNSUPPORTED_MEDIA_TYPE', + message: 'This action only accepts JSON input. To accept form data, set the `accept` option to either `form` or `all`.' }); } - unparsedInput = upgradeFormData(unparsedInput, inputSchema); + // TODO: form input schema narrowing + unparsedInput = upgradeFormData(unparsedInput, inputSchema as any); } const parsed = inputSchema.safeParse(unparsedInput); diff --git a/packages/astro/src/actions/runtime/virtual/shared.ts b/packages/astro/src/actions/runtime/virtual/shared.ts index fdd98438d31a..9358526fb9d2 100644 --- a/packages/astro/src/actions/runtime/virtual/shared.ts +++ b/packages/astro/src/actions/runtime/virtual/shared.ts @@ -6,6 +6,7 @@ type ActionErrorStatus = | 'UNAUTHORIZED' | 'FORBIDDEN' | 'NOT_FOUND' + | 'UNSUPPORTED_MEDIA_TYPE' | 'INTERNAL_SERVER_ERROR'; export class ActionError extends Error { diff --git a/packages/astro/test/fixtures/actions-blog/src/actions/index.ts b/packages/astro/test/fixtures/actions-blog/src/actions/index.ts index e162f6b7a214..9cf6c1b91662 100644 --- a/packages/astro/test/fixtures/actions-blog/src/actions/index.ts +++ b/packages/astro/test/fixtures/actions-blog/src/actions/index.ts @@ -6,6 +6,7 @@ export default { blog: { like: defineAction({ input: z.object({ postId: z.string() }), + accept: 'json', handler: async ({ postId }, context) => { await new Promise((r) => setTimeout(r, 200)); @@ -23,6 +24,7 @@ export default { }), comment: defineAction({ + accept: 'all', input: z.object({ postId: z.string(), author: z.string(),