Skip to content
This repository has been archived by the owner on Mar 23, 2024. It is now read-only.

Commit

Permalink
feat: function to modify cookies / headers
Browse files Browse the repository at this point in the history
  • Loading branch information
OrJDev committed Mar 3, 2023
1 parent 7e96dcd commit c204ade
Show file tree
Hide file tree
Showing 10 changed files with 109 additions and 16 deletions.
5 changes: 5 additions & 0 deletions .changeset/polite-grapes-poke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@prpc/solid': patch
---

feat: `replyWith` function to modify cookies / headers
4 changes: 4 additions & 0 deletions docs/src/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ export const SIDEBAR: Sidebar = {
API: [
{ text: 'query$', link: 'query' },
{ text: 'mutation$', link: 'mutation' },
{
text: 'replyWith',
link: 'reply-with',
},
{
text: 'QueryProvider',
link: 'query-provider',
Expand Down
2 changes: 2 additions & 0 deletions docs/src/content/docs/mutation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ description: 'API for the mutation$ function'

Converts the function to be a `server$` function and will add in zod validation if there is a zod object in the 2nd argument. Returns a `createMutation` is from `@adeora/solid-query`.

If you want to modify the response headers / cookies, make sure to check out the [`replyWith`](/reply-with) docs.

## Examples

```ts
Expand Down
24 changes: 24 additions & 0 deletions docs/src/content/docs/query.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,30 @@ description: 'API for the query$ function'

Converts the function to be a `server$` function and will add in zod validation if there is a zod object in the 2nd argument. Return object has `useQuery` method on it from `@adeora/solid-query`.

If you want to modify the response headers / cookies, make sure to check out the [`replyWith`](/reply-with) docs.

```ts
import { query$, replyWith } from '@prpc/solid'
import { z } from 'zod'

export const add = query$(
({ payload, request$ }) => {
const result = payload.a + payload.b
console.log(request$.headers.get('user-agent'))
return replyWith(result, {
headers: {
'set-cookie': 'solid-testing=1',
},
})
},
'add',
z.object({
a: z.number(),
b: z.number(),
})
)
```

## Examples

```ts
Expand Down
34 changes: 34 additions & 0 deletions docs/src/content/docs/reply-with.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
title: 'replyWith'
description: 'API for the replyWith function'
---

**API for the replyWith function**

This function is used to modify the response headers / cookies without affecting the return type of the function.

## Usage

```ts
import { query$, replyWith } from '@prpc/solid'
import { z } from 'zod'

export const add = query$(
({ payload, request$ }) => {
const result = payload.a + payload.b
console.log(request$.headers.get('user-agent'))
return replyWith(result, {
headers: {
'set-cookie': 'solid-testing=1',
},
})
},
'add',
z.object({
a: z.number(),
b: z.number(),
})
)
```

The return type of this function is still `number`, but the response headers / cookies are modified.
4 changes: 3 additions & 1 deletion examples/solidstart/src/routes/query.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ const Query: VoidComponent = () => {
}),
() => ({
placeholderData: (prev) => prev,
retry: false,
onSettled(data, error) {
console.log({ data, error })
},
})
)

Expand Down
8 changes: 6 additions & 2 deletions examples/solidstart/src/server/queries.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { query$ } from '@prpc/solid'
import { query$, replyWith } from '@prpc/solid'
import { isServer } from 'solid-js/web'
import { z } from 'zod'

Expand All @@ -8,7 +8,11 @@ export const add = query$(
console.log(isServer /* true */)
console.log('add', result)
console.log(request$.headers.get('user-agent'))
return result
return replyWith(result, {
headers: {
'set-cookie': 'solid-testing=1',
},
})
},
'add',
z.object({
Expand Down
8 changes: 2 additions & 6 deletions packages/solid/src/mutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {
InferReturnType,
AsParam,
} from './types'
import { genQueryKey, unwrapValue } from './utils'
import { genQueryKey, tryAndWrap } from './utils'

export function mutation$<
ZObj extends ZodObject<any> | undefined,
Expand All @@ -23,11 +23,7 @@ export function mutation$<
) =>
createMutation(() => ({
mutationKey: genQueryKey(key, undefined, true),
mutationFn: (input: InferReturnType<Fn>) =>
queryFn({
payload: unwrapValue(input) as any,
request$: {} as unknown as Request, // babel will handle this
}),
mutationFn: (input: AsParam<Fn, false>) => tryAndWrap(queryFn, input),
...((mutationOpts?.() || {}) as any),
})) as CreateMutationResult<InferReturnType<Fn>, Error, AsParam<Fn, false>>
}
8 changes: 2 additions & 6 deletions packages/solid/src/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {
InferReturnType,
AsParam,
} from './types'
import { genQueryKey, unwrapValue } from './utils'
import { genQueryKey, tryAndWrap, unwrapValue } from './utils'

export function query$<
ZObj extends ZodObject<any> | undefined,
Expand All @@ -20,11 +20,7 @@ export function query$<
) => {
return createQuery(() => ({
queryKey: genQueryKey(key, unwrapValue(input)),
queryFn: () =>
queryFn({
payload: unwrapValue(input) as any,
request$: {} as unknown as Request, // babel will handle this
}),
queryFn: () => tryAndWrap(queryFn, input),
...((queryOpts?.() || {}) as any),
})) as CreateQueryResult<InferReturnType<Fn>>
}
Expand Down
28 changes: 27 additions & 1 deletion packages/solid/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import type { ValueOrAccessor } from './types'
import type { ValueOrAccessor, ExpectedFn, AsParam } from './types'

export const unwrapValue = <V extends ValueOrAccessor<any>>(
value: V
Expand All @@ -19,3 +19,29 @@ export const genQueryKey = (key: string, input?: any, isMutation = false) => {
}
return ['prpc.query', input].filter(Boolean)
}

export async function tryAndWrap<Fn extends ExpectedFn>(
queryFn: Fn,
input: AsParam<Fn, false | true>
) {
const response = await queryFn({
payload: unwrapValue(input) as any,
request$: {} as unknown as Request, // babel will handle this
})
if (response instanceof Response) {
const text = await response.text()
try {
return JSON.parse(text)
} catch {
return text
}
}
return response
}

export const replyWith = <T>(value: T, init?: ResponseInit): T => {
return new Response(
typeof value === 'string' ? value : JSON.stringify(value),
init
) as unknown as T
}

0 comments on commit c204ade

Please sign in to comment.