Skip to content

Commit

Permalink
feat(surrealFetch & surrealRPC): new server utils
Browse files Browse the repository at this point in the history
  • Loading branch information
sandros94 committed May 31, 2024
1 parent ad99533 commit e577733
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 1 deletion.
8 changes: 8 additions & 0 deletions playground/server/api/products.get.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default eventHandler(async (event) => {
return surrealRPC(event, {
method: 'select',
params: ['products'],
}, {
database: 'staging',
})
})
3 changes: 2 additions & 1 deletion src/module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { defineNuxtModule, addPlugin, addImportsDir, createResolver } from '@nuxt/kit'
import { defineNuxtModule, addPlugin, addImportsDir, addServerImportsDir, createResolver } from '@nuxt/kit'
import { defu } from 'defu'

import type { DatabasePreset } from './runtime/types'
Expand Down Expand Up @@ -38,5 +38,6 @@ export default defineNuxtModule<ModuleOptions>({

addPlugin(resolve('./runtime', 'plugin'))
addImportsDir(resolve('./runtime', 'composables'))
addServerImportsDir(resolve('./runtime', 'server', 'utils'))
},
})
148 changes: 148 additions & 0 deletions src/runtime/server/utils/use-surreal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import type { FetchOptions, ResponseType } from 'ofetch'
import type { NitroFetchRequest } from 'nitropack'
import { textToBase64 } from 'undio'
import type { H3Event } from 'h3'
import { getCookie } from 'h3'

import type { DatabasePreset, Overrides, RpcRequest, RpcResponse } from '../../types'
import { useRuntimeConfig } from '#imports'

type Methods = 'get' | 'post' | 'put' | 'patch' | 'delete'

function authTokenFn(dbAuth: DatabasePreset['auth']) {
if (!dbAuth) return undefined
if (typeof dbAuth === 'string') {
if (dbAuth.startsWith('Bearer ')) {
return dbAuth
}
else {
const [user, pass] = dbAuth.split(':')
if (user && pass) {
return `Basic ${textToBase64(`${user}:${pass}`, { dataURL: false })}`
}
}
}
else {
return `Basic ${textToBase64(`${dbAuth.user}:${dbAuth.pass}`, { dataURL: false })}`
}
}

export function surrealFetch<
T = any,
R extends NitroFetchRequest = NitroFetchRequest,
O extends ResponseType = ResponseType,
>(
event: H3Event,
req: R,
options: Omit<FetchOptions<O>, 'method'> & { method: Uppercase<Methods> | Methods },
) {
const { databases, tokenCookieName } = useRuntimeConfig(event).public.surrealdb
const authToken = authTokenFn(databases.default.auth)
const userAuth = getCookie(event, tokenCookieName)

const surrealFetch = $fetch.create({
baseURL: databases.default.host,
onRequest({ options }) {
options.headers = options.headers || {}

// @ts-expect-error NS header type missing
if (databases.default.NS && options.headers.NS === undefined) {
// @ts-expect-error NS header type missing
options.headers.NS = databases.default.NS
}
// @ts-expect-error DB header type missing
if (databases.default.DB && options.headers.DB === undefined) {
// @ts-expect-error DB header type missing
options.headers.DB = databases.default.DB
}
// @ts-expect-error Authorization header type missing
if (authToken && !userAuth && !options.headers.Authorization) {
// @ts-expect-error Authorization header type missing
options.headers.Authorization = authToken
}
// @ts-expect-error Authorization header type missing
else if (userAuth && !options.headers.Authorization) {
// @ts-expect-error Authorization header type missing
options.headers.Authorization = `Bearer ${userAuth}`
}
},
})

return surrealFetch<T>(req, options)
}

export function surrealFetchOptionsOverride<
R extends ResponseType = ResponseType,
>(
event: H3Event,
overrides: Overrides = {},
defaults?: Pick<FetchOptions<R>, 'headers'>,
) {
const {
database,
token,
} = overrides
const { databases, tokenCookieName } = useRuntimeConfig(event).public.surrealdb
const authToken = authTokenFn(databases.default.auth)
const userAuth = getCookie(event, tokenCookieName)

const headers = defaults?.headers as Record<string, string> || {}
let db: DatabasePreset | undefined = undefined
let baseURL: string | undefined = undefined
let dbAuth: string | undefined = undefined

if (database !== undefined) {
if (typeof database !== 'string' && typeof database !== 'number' && typeof database !== 'symbol') {
db = database
}
else {
db = databases[database]
}
if (db.host) {
baseURL = db.host
}
if (db.NS) {
headers.NS = db.NS
}
if (db.DB) {
headers.DB = db.DB
}
if (db.auth) {
dbAuth = authTokenFn(db.auth)
}
}

if (token !== false) {
const _token = authTokenFn(token)
if (_token || userAuth || dbAuth || authToken) {
headers.Authorization
= _token
?? userAuth
? `Bearer ${userAuth}`
: dbAuth
?? authToken as string
}
}

return {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
...headers,
},
...(baseURL !== undefined && { baseURL }),
}
}

export function surrealRPC<T = any>(event: H3Event, req: RpcRequest<T>, ovr?: Overrides) {
let id = 0

return surrealFetch<RpcResponse<T>>(event, 'rpc', {
...surrealFetchOptionsOverride(event, ovr),
method: 'POST',
body: {
id: id++,
...req,
},
})
}

0 comments on commit e577733

Please sign in to comment.