Skip to content

Commit

Permalink
Actions: restore api context param (#11112)
Browse files Browse the repository at this point in the history
* feat: expose APIContext from the second handler param

* refactor: use second param from test

* chore: changeset

* edit: minor -> patch

* edit: apiContext -> context

Co-authored-by: Florian Lefebvre <[email protected]>

* refactor: apiContext -> context

Co-authored-by: Florian Lefebvre <[email protected]>

* refactor: apiContext -> context

Co-authored-by: Florian Lefebvre <[email protected]>

---------

Co-authored-by: Florian Lefebvre <[email protected]>
  • Loading branch information
bholmesdev and florian-lefebvre authored May 22, 2024
1 parent b15949f commit 29a8650
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 13 deletions.
24 changes: 24 additions & 0 deletions .changeset/six-icons-pump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
"astro": patch
---

Deprecate the `getApiContext()` function. API Context can now be accessed from the second parameter to your Action `handler()`:

```diff
// src/actions/index.ts
import {
defineAction,
z,
- getApiContext,
} from 'astro:actions';

export const server = {
login: defineAction({
input: z.object({ id: z.string }),
+ handler(input, context) {
const user = context.locals.auth(input.id);
return user;
}
}),
}
```
17 changes: 9 additions & 8 deletions packages/astro/src/actions/runtime/virtual/server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { z } from 'zod';
import { getApiContext } from '../store.js';
import { getApiContext as _getApiContext, type ActionAPIContext } from '../store.js';
import { type MaybePromise, hasContentType } from '../utils.js';
import {
ActionError,
Expand All @@ -13,16 +13,17 @@ export * from './shared.js';

export { z } from 'zod';

export { getApiContext } from '../store.js';
/** @deprecated Access context from the second `handler()` parameter. */
export const getApiContext = _getApiContext;

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

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

export type ActionClient<
TOutput,
Expand Down Expand Up @@ -88,13 +89,13 @@ function getFormServerHandler<TOutput, TInputSchema extends InputSchema<'form'>>
});
}

if (!(inputSchema instanceof z.ZodObject)) return await handler(unparsedInput);
if (!(inputSchema instanceof z.ZodObject)) return await handler(unparsedInput, getApiContext());

const parsed = await inputSchema.safeParseAsync(formDataToObject(unparsedInput, inputSchema));
if (!parsed.success) {
throw new ActionInputError(parsed.error.issues);
}
return await handler(parsed.data);
return await handler(parsed.data, getApiContext());
};
}

Expand All @@ -112,12 +113,12 @@ function getJsonServerHandler<TOutput, TInputSchema extends InputSchema<'json'>>
});
}

if (!inputSchema) return await handler(unparsedInput);
if (!inputSchema) return await handler(unparsedInput, getApiContext());
const parsed = await inputSchema.safeParseAsync(unparsedInput);
if (!parsed.success) {
throw new ActionInputError(parsed.error.issues);
}
return await handler(parsed.data);
return await handler(parsed.data, getApiContext());
};
}

Expand Down
8 changes: 3 additions & 5 deletions packages/astro/test/fixtures/actions/src/actions/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { defineAction, getApiContext, ActionError, z } from 'astro:actions';
import { defineAction, ActionError, z } from 'astro:actions';

export const server = {
subscribe: defineAction({
Expand Down Expand Up @@ -31,15 +31,13 @@ export const server = {
}),
getUser: defineAction({
accept: 'form',
handler: async () => {
const { locals } = getApiContext();
handler: async (_, { locals }) => {
return locals.user;
}
}),
getUserOrThrow: defineAction({
accept: 'form',
handler: async () => {
const { locals } = getApiContext();
handler: async (_, { locals }) => {
if (locals.user?.name !== 'admin') {
// Expected to throw
throw new ActionError({
Expand Down

0 comments on commit 29a8650

Please sign in to comment.