Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/itchy-peaches-peel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@example/erp": patch
"@kivotos/core": minor
"@kivotos/next": minor
---

[[DRIZZ-39] Server Function RPC](https://app.plane.so/softnetics/browse/DRIZZ-39/)
4 changes: 2 additions & 2 deletions examples/erp/drizzlify/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const serverConfig = baseConfig.toServerConfig({
},
({ query }) => {
return {
status: 200,
status: 200 as const,
body: {
message: `Hello ${query.name ?? 'World'}`,
},
Expand All @@ -45,7 +45,7 @@ export const serverConfig = baseConfig.toServerConfig({
},
({ query }) => {
return {
status: 200,
status: 200 as const,
body: {
message: `Hello2 ${query.name ?? 'World'}`,
},
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/auth/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export type AuthContext<TConfig extends AuthConfig = AuthConfig> = {
authConfig: TConfig
internalHandlers: InternalHandlers

requiredAuthenticated: (headers: Headers) => Promise<InferTableType<AnyUserTable>>
requiredAuthenticated: (headers: Record<string, string>) => Promise<InferTableType<AnyUserTable>>
}

export function createAuthContext<TAuthConfig extends AuthConfig, TContext extends MinimalContext>(
Expand All @@ -39,7 +39,7 @@ export function createAuthContext<TAuthConfig extends AuthConfig, TContext exten
authConfig: authConfig,
internalHandlers: internalHandlers,

requiredAuthenticated: async (headers: Headers) => {
requiredAuthenticated: async (headers: Record<string, string>) => {
const sessionId = getSessionCookie(headers)
if (!sessionId) throw new Error('Unauthorized')
const session = await internalHandlers.session.findUserBySessionId(sessionId)
Expand Down
21 changes: 8 additions & 13 deletions packages/core/src/auth/handlers/forgot-password.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import z from 'zod'

import { ApiRoute, ApiRouteHandler, ApiRouteSchema } from '~/core/endpoint'

import { ApiRouteHandler, ApiRouteSchema, createEndpoint } from '../../endpoint'
import { AuthContext } from '../context'
import { WithPrefix } from '../types'

Expand All @@ -14,18 +13,17 @@ export function forgotPasswordEmail<const TOptions extends InternalRouteOptions>
) {
const schema = {
method: 'POST',
path: (options.prefix ? `${options.prefix}/forgot-password` : '/forgot-password') as WithPrefix<
TOptions['prefix'],
'/forgot-password'
>,
body: z.interface({
path: (options.prefix
? `${options.prefix}/auth/forgot-password`
: '/auth/forgot-password') as WithPrefix<TOptions['prefix'], '/auth/forgot-password'>,
body: z.object({
email: z.string(),
}),
responses: {
200: z.interface({
200: z.object({
status: z.string(),
}),
400: z.interface({
400: z.object({
status: z.string(),
}),
},
Expand Down Expand Up @@ -63,8 +61,5 @@ export function forgotPasswordEmail<const TOptions extends InternalRouteOptions>
}
}

return {
...schema,
handler,
} satisfies ApiRoute
return createEndpoint(schema, handler)
}
22 changes: 10 additions & 12 deletions packages/core/src/auth/handlers/me.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import z from 'zod'

import { ApiRoute, ApiRouteHandler, ApiRouteSchema } from '~/core/endpoint'

import { ApiRouteHandler, ApiRouteSchema, createEndpoint } from '../../endpoint'
import { AuthContext } from '../context'
import { WithPrefix } from '../types'

interface InternalRouteOptions {
prefix?: string
Expand All @@ -11,17 +11,18 @@ interface InternalRouteOptions {
export function me<const TOptions extends InternalRouteOptions>(options: TOptions) {
const schema = {
method: 'GET',
path: (options.prefix ? `${options.prefix}/me` : '/me') as TOptions['prefix'] extends string
? `${TOptions['prefix']}/me`
: '/me',
path: (options.prefix ? `${options.prefix}/auth/me` : '/auth/me') as WithPrefix<
TOptions['prefix'],
'/auth/me'
>,
responses: {
200: z.interface({
200: z.object({
id: z.string(),
name: z.string(),
email: z.string(),
'image?': z.string().nullable(),
image: z.string().nullable().optional(),
}),
401: z.interface({
401: z.object({
status: z.string(),
}),
},
Expand All @@ -36,8 +37,5 @@ export function me<const TOptions extends InternalRouteOptions>(options: TOption
}
}

return {
...schema,
handler,
} satisfies ApiRoute
return createEndpoint(schema, handler)
}
28 changes: 12 additions & 16 deletions packages/core/src/auth/handlers/reset-password.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import z from 'zod'

import { ApiRoute, ApiRouteHandler, ApiRouteSchema } from '~/core/endpoint'

import { ApiRouteHandler, ApiRouteSchema, createEndpoint } from '../../endpoint'
import { AuthContext } from '../context'
import { WithPrefix } from '../types'

interface InternalRouteOptions {
prefix?: string
Expand All @@ -12,21 +12,19 @@ export function resetPasswordEmail<const TOptions extends InternalRouteOptions>(
const schema = {
method: 'POST',
path: (options.prefix
? `${options.prefix}/reset-password`
: '/reset-password') as TOptions['prefix'] extends string
? `${TOptions['prefix']}/reset-password`
: '/reset-password',
query: z.interface({
? `${options.prefix}/auth/reset-password`
: '/auth/reset-password') as WithPrefix<TOptions['prefix'], '/auth/reset-password'>,
query: z.object({
token: z.string(),
}),
body: z.interface({
body: z.object({
password: z.string(),
}),
responses: {
200: z.interface({
200: z.object({
status: z.string(),
}),
400: z.interface({
400: z.object({
status: z.string(),
}),
},
Expand Down Expand Up @@ -59,8 +57,9 @@ export function resetPasswordEmail<const TOptions extends InternalRouteOptions>(

const redirectTo = `${args.context.authConfig.resetPassword?.redirectTo ?? '/auth/login'}`

const responseHeaders = new Headers()
responseHeaders.set('Location', redirectTo)
const responseHeaders = {
Location: redirectTo,
}

return {
status: 200,
Expand All @@ -69,8 +68,5 @@ export function resetPasswordEmail<const TOptions extends InternalRouteOptions>(
}
}

return {
...schema,
handler,
} satisfies ApiRoute
return createEndpoint(schema, handler)
}
25 changes: 10 additions & 15 deletions packages/core/src/auth/handlers/sign-in-email.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import z from 'zod'

import { ApiRoute, ApiRouteHandler, ApiRouteSchema } from '~/core/endpoint'

import { ApiRouteHandler, ApiRouteSchema, createEndpoint } from '../../endpoint'
import { AccountProvider } from '../constant'
import { AuthContext } from '../context'
import { WithPrefix } from '../types'
Expand All @@ -14,23 +13,22 @@ interface InternalRouteOptions {
export function signInEmail<const TOptions extends InternalRouteOptions>(options: TOptions) {
const schema = {
method: 'POST',
path: (options.prefix ? `${options.prefix}/sign-in/email` : '/sign-in/email') as WithPrefix<
TOptions['prefix'],
'/sign-in/email'
>,
path: (options.prefix
? `${options.prefix}/auth/sign-in/email`
: '/auth/sign-in/email') as WithPrefix<TOptions['prefix'], '/auth/sign-in/email'>,

body: z.interface({
body: z.object({
email: z.string(),
password: z.string(),
}),
responses: {
200: z.interface({
200: z.object({
token: z.string().nullable(),
user: z.interface({
user: z.object({
id: z.string(),
name: z.string(),
email: z.string(),
'image?': z.string().nullable(),
image: z.string().nullable().optional(),
}),
}),
},
Expand All @@ -54,7 +52,7 @@ export function signInEmail<const TOptions extends InternalRouteOptions>(options
expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24),
})

const responseHeaders = new Headers()
const responseHeaders = {}
setSessionCookie(responseHeaders, session.token)

return {
Expand All @@ -67,8 +65,5 @@ export function signInEmail<const TOptions extends InternalRouteOptions>(options
}
}

return {
...schema,
handler,
} satisfies ApiRoute
return createEndpoint(schema, handler)
}
12 changes: 4 additions & 8 deletions packages/core/src/auth/handlers/sign-out.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import z from 'zod'

import { ApiRoute, ApiRouteHandler, ApiRouteSchema } from '~/core/endpoint'

import { ApiRouteHandler, ApiRouteSchema, createEndpoint } from '../../endpoint'
import { AuthContext } from '../context'
import { WithPrefix } from '../types'
import { deleteSessionCookie, getSessionCookie } from '../utils'
Expand All @@ -13,13 +12,13 @@ interface InternalRouteOptions {
export function signOut<const TOptions extends InternalRouteOptions>(options: TOptions) {
const schema = {
method: 'POST',
path: (options.prefix ? `${options.prefix}/sign-out` : '/sign-out') as WithPrefix<
path: (options.prefix ? `${options.prefix}/auth/sign-out` : '/auth/sign-out') as WithPrefix<
TOptions['prefix'],
'/sign-out'
>,
body: undefined,
responses: {
200: z.interface({
200: z.object({
status: z.string(),
}),
},
Expand All @@ -45,8 +44,5 @@ export function signOut<const TOptions extends InternalRouteOptions>(options: TO
}
}

return {
...schema,
handler,
} satisfies ApiRoute
return createEndpoint(schema, handler)
}
18 changes: 7 additions & 11 deletions packages/core/src/auth/handlers/sign-up.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import z from 'zod'

import { ApiRoute, ApiRouteHandler, ApiRouteSchema } from '~/core/endpoint'

import { ApiRouteHandler, ApiRouteSchema, createEndpoint } from '../../endpoint'
import { AccountProvider } from '../constant'
import { AuthContext } from '../context'
import { WithPrefix } from '../types'
Expand All @@ -13,22 +12,22 @@ interface InternalRouteOptions {
export function signUp<const TOptions extends InternalRouteOptions>(options: TOptions) {
const schema = {
method: 'POST',
path: (options.prefix ? `${options.prefix}/sign-up` : '/sign-up') as WithPrefix<
path: (options.prefix ? `${options.prefix}/auth/sign-up` : '/auth/sign-up') as WithPrefix<
TOptions['prefix'],
'/sign-up'
'/auth/sign-up'
>,
body: z
.interface({
.object({
name: z.string(),
email: z.string(),
password: z.string(),
callbackURL: z.string().optional(),
})
.and(z.record(z.string(), z.any())),
responses: {
200: z.interface({
200: z.object({
token: z.string().nullable(),
user: z.interface({
user: z.object({
id: z.string(),
name: z.string(),
email: z.string(),
Expand Down Expand Up @@ -73,8 +72,5 @@ export function signUp<const TOptions extends InternalRouteOptions>(options: TOp
}
}

return {
...schema,
handler,
} satisfies ApiRoute
return createEndpoint(schema, handler)
}
4 changes: 2 additions & 2 deletions packages/core/src/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ type ChangeAuthHandlerContextToMinimalContext<
any,
infer TApiRouteSchema
>
? TApiRouteSchema & { handler: ApiRouteHandler<TContext, TApiRouteSchema> }
? { schema: TApiRouteSchema; handler: ApiRouteHandler<TContext, TApiRouteSchema> }
: never
}

Expand Down Expand Up @@ -140,7 +140,7 @@ export function createAuth<TContext extends MinimalContext = MinimalContext>(
const handler: ApiRouteHandler<TContext, any> = (args) => {
return h.handler({ ...args, context: authContext } as any) as any
}
return { ...h, handler }
return { schema: h.schema, handler }
}) as ChangeAuthHandlerContextToMinimalContext<
TContext,
ReturnType<typeof createAuthHandlers>['handlers']
Expand Down
18 changes: 9 additions & 9 deletions packages/core/src/auth/utils.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
function setCookie(headers: Headers, name: string, value: string) {
headers.append('Set-Cookie', `${name}=${value}; Path=/; HttpOnly; SameSite=Strict`)
function setCookie(headers: Record<string, string>, name: string, value: string) {
headers['Set-Cookie'] = `${name}=${value}; Path=/; HttpOnly; SameSite=Strict`
}

function getCookie(headers: Headers, name: string) {
const cookie = headers.get('Cookie')
function getCookie(headers: Record<string, string>, name: string) {
const cookie = headers[name]
if (!cookie) return null
const cookies = cookie.split('; ')
for (const c of cookies) {
Expand All @@ -13,20 +13,20 @@ function getCookie(headers: Headers, name: string) {
return null
}

function deleteCookie(headers: Headers, name: string) {
headers.append('Set-Cookie', `${name}=; Path=/; HttpOnly; SameSite=Strict; Max-Age=0`)
function deleteCookie(headers: Record<string, string>, name: string) {
headers['Set-Cookie'] = `${name}=; Path=/; HttpOnly; SameSite=Strict; Max-Age=0`
}

const SESSION_COOKIE_NAME = 'SESSION_ID'

export function getSessionCookie(headers: Headers) {
export function getSessionCookie(headers: Record<string, string>) {
return getCookie(headers, SESSION_COOKIE_NAME)
}

export function setSessionCookie(headers: Headers, value: string) {
export function setSessionCookie(headers: Record<string, string>, value: string) {
setCookie(headers, SESSION_COOKIE_NAME, value)
}

export function deleteSessionCookie(headers: Headers) {
export function deleteSessionCookie(headers: Record<string, string>) {
deleteCookie(headers, SESSION_COOKIE_NAME)
}
Loading
Loading