Skip to content

Commit 9f669a8

Browse files
committed
refactor: remove normal context from handler
1 parent c5f25c3 commit 9f669a8

12 files changed

Lines changed: 199 additions & 86 deletions

File tree

packages/core/src/builder.handler.spec.ts

Lines changed: 122 additions & 40 deletions
Large diffs are not rendered by default.

packages/core/src/builder.handler.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import type {
2424
InferFields,
2525
} from './collection'
2626
import type { MinimalContext } from './config'
27+
import type { RequestContext } from './context'
2728
import type { Field, Fields } from './field'
2829
import {
2930
createDrizzleQuery,
@@ -63,7 +64,7 @@ export function createDefaultApiHandlers<
6364
}
6465

6566
const findOne: ApiFindOneHandler<TContext, TFields> = async (args) => {
66-
const db = args.context.db
67+
const db = args.requestContext.db
6768
const query = db.query[tableName as keyof typeof db.query] as RelationalQueryBuilder<any, any>
6869

6970
const result = await query.findFirst({
@@ -86,7 +87,7 @@ export function createDefaultApiHandlers<
8687
}
8788

8889
const findMany: ApiFindManyHandler<TContext, TFields> = async (args) => {
89-
const db = args.context.db
90+
const db = args.requestContext.db
9091
const query = db.query[tableName as keyof typeof db.query] as RelationalQueryBuilder<any, any>
9192

9293
const orderType = args.orderType ?? 'asc'
@@ -118,14 +119,14 @@ export function createDefaultApiHandlers<
118119
}
119120

120121
const create: ApiCreateHandler<TContext, TFields> = async (args) => {
121-
const db = args.context.db
122+
const db = args.requestContext.db
122123
// TODO: Please reuse findOne instead of duplicate logic
123124
const query = db.query[tableName as keyof typeof db.query] as RelationalQueryBuilder<any, any>
124125

125126
const pk = await db.transaction(async (tx) => {
126127
const apiHandler = new ApiHandler(tableTsKey, fields, {
127128
schema,
128-
context: args.context,
129+
requestContext: args.requestContext,
129130
tableRelationalConfigByTableTsName: tables,
130131
tableTsNameByTableDbName: tableNamesMap,
131132
})
@@ -150,14 +151,14 @@ export function createDefaultApiHandlers<
150151
}
151152

152153
const update: ApiUpdateHandler<TContext, TFields> = async (args) => {
153-
const db = args.context.db
154+
const db = args.requestContext.db
154155
// TODO: Please reuse findOne instead of duplicate logic
155156
const query = db.query[tableName as keyof typeof db.query] as RelationalQueryBuilder<any, any>
156157

157158
const result = await db.transaction(async (tx) => {
158159
const apiHandler = new ApiHandler(tableTsKey, fields, {
159160
schema,
160-
context: args.context,
161+
requestContext: args.requestContext,
161162
tableRelationalConfigByTableTsName: tables,
162163
tableTsNameByTableDbName: tableNamesMap,
163164
})
@@ -183,7 +184,7 @@ export function createDefaultApiHandlers<
183184

184185
// why not just delete? why _delete?
185186
const _delete: ApiDeleteHandler<TContext, TFields> = async (args) => {
186-
const db = args.context.db
187+
const db = args.requestContext.db
187188

188189
await db
189190
.delete(tableSchema)
@@ -211,7 +212,7 @@ class ApiHandler {
211212
private readonly fields: Fields<any>,
212213
private readonly config: {
213214
schema: Record<string, unknown>
214-
context: MinimalContext
215+
requestContext: RequestContext<MinimalContext>
215216
tableTsNameByTableDbName: Record<string, string>
216217
tableRelationalConfigByTableTsName: Record<string, TableRelationalConfig>
217218
}

packages/core/src/collection.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { ConditionalExcept, Simplify, UnionToIntersection, ValueOf } from '
33
import z from 'zod'
44

55
import type { MinimalContext } from './config'
6+
import type { RequestContext } from './context'
67
import type {
78
ApiRoute,
89
ApiRouteHandler,
@@ -309,7 +310,7 @@ export type ServerApiHandlerArgs<
309310
> = {
310311
slug: string
311312
fields: TFields
312-
context: TContext
313+
requestContext: RequestContext<TContext>
313314
}
314315

315316
export type ApiArgs<
@@ -718,7 +719,7 @@ export function getAllCollectionEndpoints<
718719
const response = await (fn as ApiCreateHandler<any, any>)({
719720
slug: collection.slug,
720721
fields: collection.fields,
721-
context: args.context,
722+
requestContext: args.requestContext,
722723
data: args.body,
723724
})
724725
return { status: 200, body: response }
@@ -746,7 +747,7 @@ export function getAllCollectionEndpoints<
746747
const response = await (fn as ApiFindOneHandler<any, any>)({
747748
slug: collection.slug,
748749
fields: collection.fields,
749-
context: args.context,
750+
requestContext: args.requestContext,
750751
id: args.pathParams.id,
751752
})
752753
return { status: 200, body: response }
@@ -777,7 +778,7 @@ export function getAllCollectionEndpoints<
777778
const response = await (fn as ApiFindManyHandler<any, any>)({
778779
slug: collection.slug,
779780
fields: collection.fields,
780-
context: args.context,
781+
requestContext: args.requestContext,
781782
limit: args.query.limit,
782783
offset: args.query.offset,
783784
orderBy: args.query.orderBy,
@@ -813,7 +814,7 @@ export function getAllCollectionEndpoints<
813814
const response = await (fn as ApiUpdateHandler<any, any>)({
814815
slug: collection.slug,
815816
fields: collection.fields,
816-
context: args.context,
817+
requestContext: args.requestContext,
817818
id: args.pathParams.id,
818819
data: args.body as any, // TODO: Fix this
819820
})
@@ -840,7 +841,7 @@ export function getAllCollectionEndpoints<
840841
await (fn as ApiDeleteHandler<any, any>)({
841842
slug: collection.slug,
842843
fields: collection.fields,
843-
context: args.context,
844+
requestContext: args.requestContext,
844845
ids: args.body.ids,
845846
})
846847
return { status: 200, body: { message: 'ok' } }

packages/core/src/endpoint.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { z, ZodType } from 'zod'
44
import zodToJsonSchema from 'zod-to-json-schema'
55

66
import type { MaybePromise } from './collection'
7-
import type { Context, RequestContext } from './context'
7+
import type { RequestContext } from './context'
88

99
export type ApiHttpStatus = 200 | 201 | 204 | 301 | 302 | 400 | 401 | 403 | 404 | 409 | 422 | 500
1010

@@ -56,7 +56,6 @@ export type ApiRouteHandlerPayloadWithContext<
5656
TApiRouteSchema extends ApiRouteSchema,
5757
TContext extends Record<string, unknown> = Record<string, unknown>,
5858
> = ApiRouteHandlerPayload<TApiRouteSchema> & {
59-
context: Context<TContext>
6059
requestContext: RequestContext<TContext>
6160
}
6261

packages/core/src/field.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import type { Simplify } from 'type-fest'
1010
import type { ZodObject } from 'zod'
1111
import z from 'zod'
1212

13-
import type { Context } from './context'
13+
import type { RequestContext } from './context'
1414
import {
1515
appendFieldNameToFields,
1616
type GetPrimaryColumn,
@@ -21,7 +21,7 @@ import {
2121
export type OptionCallback<
2222
TType extends string | number,
2323
TContext extends Record<string, unknown> = {},
24-
> = (args: Context<TContext>) => Promise<Array<{ label: string; value: TType }>>
24+
> = (args: RequestContext<TContext>) => Promise<Array<{ label: string; value: TType }>>
2525

2626
export type FieldsWithFieldName<TFields extends Record<string, FieldBase>> = {
2727
[TKey in keyof TFields]: TFields[TKey] & { fieldName: string }

packages/core/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export type { AuthHandlers } from './auth'
1+
export { type AuthHandlers, createAuth } from './auth'
22
export { Builder } from './builder'
33
export type {
44
ApiReturnType,

packages/core/src/spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ export const postCollection = builder.collection('posts', {
151151
}),
152152
},
153153
},
154-
({ context, body }) => {
154+
({ requestContext, body }) => {
155155
const name = body.name
156156
return {
157157
status: 200 as const,
@@ -174,7 +174,7 @@ export const postCollection = builder.collection('posts', {
174174
}),
175175
},
176176
},
177-
({ context, body }) => {
177+
({ requestContext, body }) => {
178178
const name = body.name
179179
return {
180180
status: 200 as const,
@@ -207,7 +207,7 @@ export const serverConfig = defineServerConfig(baseConfig, {
207207
}),
208208
},
209209
},
210-
({ context, body }) => {
210+
({ requestContext, body }) => {
211211
const name = body.name
212212
return {
213213
status: 200 as const,

packages/next/src/components/auto-field.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
import { Context, type Field, type ServerConfig } from '@kivotos/core'
1+
import { headers } from 'next/headers'
2+
3+
import { Context, createAuth, type Field, type ServerConfig } from '@kivotos/core'
24

35
import { Checkbox } from '../intentui/ui/checkbox'
46
import { Select, SelectList, SelectOption, SelectTrigger } from '../intentui/ui/select'
57
import { Switch } from '../intentui/ui/switch'
68
import { TextField } from '../intentui/ui/text-field'
9+
import { getHeadersObject } from '../utils/headers'
710

811
interface AutoFieldProps<TServerConfig extends ServerConfig> {
912
name: string
@@ -15,6 +18,10 @@ export async function AutoField<TServerConfig extends ServerConfig>(
1518
props: AutoFieldProps<TServerConfig>
1619
) {
1720
const { field, name } = props
21+
const headersValue = getHeadersObject(await headers())
22+
const { context } = createAuth(props.serverConfig.auth, props.serverConfig.context)
23+
24+
const requestContext = Context.toRequestContext(context, headersValue)
1825

1926
switch (field.type) {
2027
case 'text':
@@ -36,7 +43,7 @@ export async function AutoField<TServerConfig extends ServerConfig>(
3643
case 'switch':
3744
return <Switch name={name} children={field.label ?? name} />
3845
case 'selectText': {
39-
const options = await field.options(new Context({ db: props.serverConfig.db }))
46+
const options = await field.options(requestContext)
4047
return (
4148
<Select name={name} placeholder={field.placeholder ?? name} label={field.label ?? name}>
4249
<SelectTrigger />
@@ -51,7 +58,7 @@ export async function AutoField<TServerConfig extends ServerConfig>(
5158
)
5259
}
5360
case 'selectNumber': {
54-
const options = await field.options(new Context({ db: props.serverConfig.db }))
61+
const options = await field.options(requestContext)
5562
return (
5663
<Select name={name} placeholder={field.placeholder ?? name} label={field.label ?? name}>
5764
<SelectTrigger />
@@ -66,7 +73,7 @@ export async function AutoField<TServerConfig extends ServerConfig>(
6673
)
6774
}
6875
case 'comboboxText': {
69-
const options = await field.options(new Context({ db: props.serverConfig.db }))
76+
const options = await field.options(requestContext)
7077
return (
7178
<select name={name}>
7279
{options.map((option) => (
@@ -78,7 +85,7 @@ export async function AutoField<TServerConfig extends ServerConfig>(
7885
)
7986
}
8087
case 'comboboxNumber': {
81-
const options = await field.options(new Context({ db: props.serverConfig.db }))
88+
const options = await field.options(requestContext)
8289
return (
8390
<select name={name}>
8491
{options.map((option) => (

packages/next/src/resource.ts

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
import { type NextRequest } from 'next/server'
22
import { createRouter } from 'radix3'
33

4-
import { type ApiRoute, type ApiRouter, Context, type ServerConfig } from '@kivotos/core'
4+
import {
5+
type ApiRoute,
6+
type ApiRouter,
7+
Context,
8+
createAuth,
9+
type ServerConfig,
10+
} from '@kivotos/core'
511

612
function extractHeaders(headers: Headers) {
713
const headersRecord: Record<string, string> = {}
@@ -21,7 +27,7 @@ function extractSearchParams(searchParams: URLSearchParams) {
2127

2228
async function makeApiRoute(
2329
req: NextRequest,
24-
context: Record<string, unknown>,
30+
serverConfig: ServerConfig<any, any, any, ApiRouter<any>>,
2531
route: ApiRoute,
2632
pathParams: Record<string, string> | undefined
2733
) {
@@ -41,11 +47,11 @@ async function makeApiRoute(
4147
// This is useful for file uploads or plain text requests
4248
}
4349

44-
const wrappedContext = new Context(context)
50+
const { context } = createAuth(serverConfig.auth, serverConfig.context)
51+
const requestContext = Context.toRequestContext(context, reqHeaders)
4552

4653
const rawResponse = await route.handler({
47-
context: wrappedContext,
48-
requestContext: Context.toRequestContext(wrappedContext, reqHeaders),
54+
requestContext,
4955
headers: reqHeaders,
5056
pathParams: pathParams,
5157
query: reqSearchParams,
@@ -64,13 +70,13 @@ async function makeApiRoute(
6470
async function lookupRoute(
6571
radixRouter: ReturnType<typeof createRouter>,
6672
req: NextRequest,
67-
context: Record<string, unknown>
73+
serverConfig: ServerConfig<any, any, any, ApiRouter<any>>
6874
) {
6975
const match = radixRouter.lookup(req.nextUrl.pathname)
7076
if (!match) return Response.json({ message: 'Not Found' }, { status: 404 })
7177
const pathParams = match.params
7278
const route = match.route as ApiRoute<any>
73-
return makeApiRoute(req, context, route, pathParams)
79+
return makeApiRoute(req, serverConfig, route, pathParams)
7480
}
7581

7682
export function createApiResourceRouter(serverConfig: ServerConfig<any, any, any, ApiRouter<any>>) {
@@ -136,19 +142,19 @@ export function createApiResourceRouter(serverConfig: ServerConfig<any, any, any
136142

137143
return {
138144
GET: async (req: NextRequest) => {
139-
return lookupRoute(radixGetRouter, req, serverConfig.context)
145+
return lookupRoute(radixGetRouter, req, serverConfig)
140146
},
141147
POST: async (req: NextRequest) => {
142-
return lookupRoute(radixPostRouter, req, serverConfig.context)
148+
return lookupRoute(radixPostRouter, req, serverConfig)
143149
},
144150
PUT: async (req: NextRequest) => {
145-
return lookupRoute(radixPutRouter, req, serverConfig.context)
151+
return lookupRoute(radixPutRouter, req, serverConfig)
146152
},
147153
DELETE: async (req: NextRequest) => {
148-
return lookupRoute(radixDeleteRouter, req, serverConfig.context)
154+
return lookupRoute(radixDeleteRouter, req, serverConfig)
149155
},
150156
PATCH: async (req: NextRequest) => {
151-
return lookupRoute(radixPatchRouter, req, serverConfig.context)
157+
return lookupRoute(radixPatchRouter, req, serverConfig)
152158
},
153159
}
154160
}

packages/next/src/server-function.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
type ApiRouteResponse,
1010
type ApiRouteSchema,
1111
Context,
12+
createAuth,
1213
type ServerConfig,
1314
} from '@kivotos/core'
1415

@@ -46,12 +47,12 @@ export async function handleServerFunction<
4647
if (!apiRoute) {
4748
throw new Error(`No API route found for method: ${args.method as string}`)
4849
}
49-
const context = new Context(serverConfig.context)
50+
const { context } = createAuth(serverConfig.auth, serverConfig.context)
51+
const requestContext = Context.toRequestContext(context, args.headers)
5052

5153
const response = await apiRoute.handler({
5254
...args,
53-
context,
54-
requestContext: Context.toRequestContext(context, args.headers),
55+
requestContext,
5556
})
5657

5758
if (response.headers?.['Set-Cookie']) {

0 commit comments

Comments
 (0)