Skip to content

Commit 2634967

Browse files
committed
feat(edgedb): refactor dsn management; improve runtimeConfig
1 parent d6140a4 commit 2634967

14 files changed

Lines changed: 185 additions & 99 deletions

File tree

playground/server/api/blogpost.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export default defineEventHandler(async (req) => {
2626
return blogpost as BlogPost
2727
}
2828

29-
const count = await useEdgeDb().query('select count(BlogPost);').then(([count]) => count)
29+
const count = await useEdgeDb().query('select count(BlogPost);').then(count => count?.[0] || 0)
3030

3131
return count ? await allBlogPosts() : []
3232
}

playground/server/plugins/auth.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
export default defineNitroPlugin((app) => {
2-
app.hooks.hook('edgedb:auth:callback', (_) => {
3-
// console.log(_)
4-
})
2+
app.hooks.hook(
3+
'edgedb:auth:callback' as any,
4+
() => {
5+
console.log('auth callback!')
6+
},
7+
)
58
})

src/module.ts

Lines changed: 141 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { existsSync } from 'node:fs'
2+
import type { NuxtModule } from 'nuxt/schema'
23
import { addComponentsDir, addImports, addPlugin, addServerHandler, addServerImports, addServerPlugin, createResolver, defineNuxtModule } from '@nuxt/kit'
34
import { createConsola } from 'consola'
45
import { join } from 'pathe'
@@ -44,7 +45,7 @@ const activePrompts = {
4445
schemaPrompt: undefined as any,
4546
}
4647

47-
export default defineNuxtModule<ModuleOptions>({
48+
const nuxtModule = defineNuxtModule<ModuleOptions>({
4849
meta: {
4950
name: 'nuxt-edgedb-module',
5051
configKey: 'edgeDb',
@@ -84,11 +85,105 @@ export default defineNuxtModule<ModuleOptions>({
8485
nuxt.options.build.transpile ??= []
8586
nuxt.options.build.transpile.push('edgedb')
8687

87-
// Set user model if `auth` is set.
88-
;(nuxt.options.runtimeConfig as any).edgeDb ??= {}
89-
;(nuxt.options.runtimeConfig.app as any).edgeDb ??= {
90-
auth: options.auth,
91-
identityModel: options.identityModel,
88+
// Inject env credentials from `edgedb instance credentials`
89+
if (options.injectDbCredentials) {
90+
// http://localhost:10702/db/edgedb/ext/auth/
91+
let dbCredentials: any | undefined
92+
try {
93+
dbCredentials = await execa.execaCommand(`edgedb instance credentials --json`, { cwd: resolveProject() })
94+
}
95+
catch (e) {
96+
// Silently fail, the EdgeDB instance credentials command failed.
97+
}
98+
if (dbCredentials) {
99+
const { host, port, database, user, password, tls_ca, tls_security } = JSON.parse(dbCredentials.stdout)
100+
101+
if (!process.env.NUXT_EDGEDB_HOST)
102+
process.env.NUXT_EDGEDB_HOST = host
103+
if (!process.env.NUXT_EDGEDB_PORT)
104+
process.env.NUXT_EDGEDB_PORT = port
105+
if (!process.env.NUXT_EDGEDB_DATABASE)
106+
process.env.NUXT_EDGEDB_DATABASE = database
107+
if (!process.env.NUXT_EDGEDB_USER)
108+
process.env.NUXT_EDGEDB_USER = user
109+
if (!process.env.NUXT_EDGEDB_PASS)
110+
process.env.NUXT_EDGEDB_PASS = password
111+
if (!process.env.NUXT_EDGEDB_TLS_CA)
112+
process.env.NUXT_EDGEDB_TLS_CA = tls_ca
113+
if (!process.env.NUXT_EDGEDB_TLS_SECURITY)
114+
process.env.NUXT_EDGEDB_TLS_SECURITY = tls_security
115+
if (!process.env.NUXT_EDGEDB_AUTH_BASE_URL)
116+
process.env.NUXT_EDGEDB_AUTH_BASE_URL = `http://${host}:${port}/db/${database}/ext/auth/`
117+
}
118+
}
119+
120+
const envAppUrl = process.env.APP_URL || process.env.NUXT_EDGEDB_APP_URL
121+
122+
// Create dev app url
123+
const devAppUrl = [
124+
nuxt.options.devServer.https ? `https://` : `http://`,
125+
nuxt.options.devServer.host ? nuxt.options.devServer.host : 'localhost',
126+
nuxt.options.devServer.port ? `:${nuxt.options.devServer.port}` : '',
127+
].join('')
128+
129+
const appUrl = envAppUrl || devAppUrl
130+
131+
const {
132+
// EdgeDB DSN settings
133+
NUXT_EDGEDB_HOST: host,
134+
NUXT_EDGEDB_PORT: port,
135+
NUXT_EDGEDB_USER: user,
136+
NUXT_EDGEDB_PASS: pass,
137+
NUXT_EDGEDB_DATABASE: database,
138+
NUXT_EDGEDB_TLS_CA: tlsCA,
139+
NUXT_EDGEDB_TLS_SECURITY: tlsSecurity,
140+
141+
// EdgeDB Auth settings
142+
NUXT_EDGEDB_IDENTITY_MODEL: identityModel = options.identityModel || 'User',
143+
144+
// EdgeDB Auth URls
145+
NUXT_EDGEDB_AUTH_BASE_URL: authBaseUrl = `http://${host}:${port}/db/${database}/ext/auth/`,
146+
NUXT_EDGEDB_OAUTH_CALLBACK: oAuthCallbackUrl = `http://${host}:${port}/db/${database}/ext/auth/callback`,
147+
148+
// EdgeDB Nuxt Auth URLs
149+
NUXT_EDGEDB_AUTH_VERIFY_REDIRECT_URL: verifyRedirectUrl = `${appUrl}/auth/verify`,
150+
NUXT_EDGEDB_AUTH_RESET_PASSWORD_URL: resetPasswordUrl = `${appUrl}/auth/reset-password`,
151+
NUXT_EDGEDB_OAUTH_REDIRECT_URL: oAuthRedirectUrl = `${appUrl}/auth/callback`,
152+
} = process.env
153+
154+
const dsn = {
155+
host,
156+
port,
157+
user,
158+
pass,
159+
database,
160+
tlsCA,
161+
tlsSecurity: tlsSecurity as 'insecure' | 'no_host_verification' | 'strict' | 'default' | undefined,
162+
full: `edgedb://${user}:${pass}@${host}:${port}/${database}`,
163+
}
164+
165+
const urls = {
166+
// EdgeDB Nuxt Auth URLs
167+
appUrl: appUrl || devAppUrl,
168+
resetPasswordUrl,
169+
verifyRedirectUrl,
170+
oAuthRedirectUrl,
171+
172+
// EdgeDB Auth URls
173+
authBaseUrl,
174+
oAuthCallbackUrl,
175+
}
176+
177+
const auth = {
178+
enabled: options.auth,
179+
oauth: options.oauth,
180+
identityModel,
181+
}
182+
183+
nuxt.options.runtimeConfig.edgeDb ??= {
184+
auth,
185+
dsn,
186+
urls,
92187
}
93188

94189
async function piped$(
@@ -543,28 +638,6 @@ export default defineNuxtModule<ModuleOptions>({
543638
}
544639

545640
if (options.auth) {
546-
if (options.injectDbCredentials) {
547-
// http://localhost:10702/db/edgedb/ext/auth/
548-
let dbCredentials: any | undefined
549-
try {
550-
dbCredentials = await execa.execaCommand(`edgedb instance credentials --json`, { cwd: resolveProject() })
551-
}
552-
catch (e) {
553-
//
554-
}
555-
if (dbCredentials) {
556-
const { host, port, database, user, password, tls_ca, tls_security } = JSON.parse(dbCredentials.stdout)
557-
process.env.NUXT_EDGEDB_HOST = host
558-
process.env.NUXT_EDGEDB_PORT = port
559-
process.env.NUXT_EDGEDB_DATABASE = database
560-
process.env.NUXT_EDGEDB_USER = user
561-
process.env.NUXT_EDGEDB_PASS = password
562-
process.env.NUXT_EDGEDB_TLS_CA = tls_ca
563-
process.env.NUXT_EDGEDB_TLS_SECURITY = tls_security
564-
process.env.NUXT_EDGEDB_AUTH_BASE_URL = `http://${host}:${port}/db/${database}/ext/auth/`
565-
}
566-
}
567-
568641
// Runtime
569642
addPlugin({
570643
src: resolveLocal('./runtime/plugins/edgedb-auth'),
@@ -661,3 +734,43 @@ function useLogger() {
661734
},
662735
)
663736
}
737+
738+
export default nuxtModule
739+
740+
declare module 'nuxt/schema' {
741+
interface NuxtConfig {
742+
['edgeDb']?: typeof nuxtModule extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
743+
}
744+
745+
interface RuntimeConfig {
746+
edgeDb: {
747+
auth: {
748+
enabled: boolean
749+
oauth: boolean
750+
identityModel: string
751+
}
752+
identityModel?: string
753+
urls: {
754+
appUrl?: string
755+
authBaseUrl?: string
756+
resetPasswordUrl?: string
757+
verifyRedirectUrl?: string
758+
oAuthCallbackUrl?: string
759+
oAuthRedirectUrl?: string
760+
}
761+
dsn: {
762+
host?: string
763+
port?: string
764+
user?: string
765+
pass?: string
766+
database?: string
767+
tlsCA?: string
768+
tlsSecurity?: 'insecure' | 'no_host_verification' | 'strict' | 'default' | undefined
769+
}
770+
}
771+
}
772+
773+
interface PublicRuntimeConfig {
774+
775+
}
776+
}

src/runtime/api/auth/authorize.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { H3Error, defineEventHandler, getRequestURL, sendError } from 'h3'
1+
import { H3Error, defineEventHandler, getRequestURL, sendError, setHeaders } from 'h3'
22
import { useEdgeDbEnv, useEdgeDbPKCE } from '../../server'
33

44
/**
@@ -9,7 +9,8 @@ import { useEdgeDbEnv, useEdgeDbPKCE } from '../../server'
99
* @param {Request} req
1010
*/
1111
export default defineEventHandler(async (req) => {
12-
const { authBaseUrl, oAuthRedirectUrl } = useEdgeDbEnv()
12+
const { urls } = useEdgeDbEnv()
13+
const { authBaseUrl, oAuthRedirectUrl } = urls
1314
const requestUrl = getRequestURL(req)
1415
const provider = requestUrl.searchParams.get('provider')
1516

@@ -23,11 +24,14 @@ export default defineEventHandler(async (req) => {
2324
const redirectUrl = new URL('authorize', authBaseUrl)
2425
redirectUrl.searchParams.set('provider', provider)
2526
redirectUrl.searchParams.set('challenge', pkce.challenge)
26-
redirectUrl.searchParams.set('redirect_to', oAuthRedirectUrl)
27+
redirectUrl.searchParams.set('redirect_to', oAuthRedirectUrl!)
2728

28-
setHeaders(req, {
29-
'Set-Cookie': `edgedb-pkce-verifier=${pkce.verifier}; HttpOnly; Path=/; Secure; SameSite=Strict`,
30-
})
29+
setHeaders(
30+
req,
31+
{
32+
'Set-Cookie': `edgedb-pkce-verifier=${pkce.verifier}; HttpOnly; Path=/; Secure; SameSite=Strict`,
33+
},
34+
)
3135

3236
return {
3337
redirect: redirectUrl,

src/runtime/api/auth/callback.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import { useEdgeDbEnv } from '../../server'
88
* @param {Request} req
99
*/
1010
export default defineEventHandler(async (req) => {
11-
const { authBaseUrl } = useEdgeDbEnv()
11+
const { urls } = useEdgeDbEnv()
12+
const { authBaseUrl } = urls
1213

1314
const requestUrl = getRequestURL(req)
1415
const code = requestUrl.searchParams.get('code')

src/runtime/api/auth/identity.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { defineEventHandler, deleteCookie, getCookie, setCookie } from 'h3'
22
import { useEdgeDb, useEdgeDbEnv } from '../../server'
33

44
export default defineEventHandler(async (event) => {
5-
const { identityModel } = useEdgeDbEnv()
5+
const { auth } = useEdgeDbEnv()
66

77
const token = getCookie(event, 'edgedb-auth-token')
88

@@ -18,7 +18,7 @@ export default defineEventHandler(async (event) => {
1818

1919
if (!identityTarget && token) {
2020
identityTarget = await client.query(`
21-
insert ${identityModel} {
21+
insert ${auth.identityModel} {
2222
name := '',
2323
identity := global ext::auth::ClientTokenIdentity
2424
}

src/runtime/api/auth/login.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { useEdgeDbEnv, useEdgeDbPKCE } from '../../server'
33

44
export default defineEventHandler(async (req) => {
55
const pkce = useEdgeDbPKCE()
6-
const { authBaseUrl } = useEdgeDbEnv()
6+
const { urls } = useEdgeDbEnv()
7+
const { authBaseUrl } = urls
78

89
const { email, password, provider } = await readBody(req)
910

src/runtime/api/auth/reset-password-ui.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import { useEdgeDbEnv } from '../../server'
77
* @param {Request} req
88
*/
99
export default defineEventHandler((req) => {
10-
const { authBaseUrl } = useEdgeDbEnv()
10+
const { urls } = useEdgeDbEnv()
11+
const { authBaseUrl } = urls
1112
const { reset_token } = getQuery(req)
1213

1314
return {

src/runtime/api/auth/reset-password.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import { useEdgeDbEnv } from '../../server'
77
* @param {Request} req
88
*/
99
export default defineEventHandler(async (req) => {
10-
const { authBaseUrl } = useEdgeDbEnv()
10+
const { urls } = useEdgeDbEnv()
11+
const { authBaseUrl } = urls
1112
const { reset_token, password } = await readBody(req)
1213

1314
if (!reset_token || !password) {

src/runtime/api/auth/send-password-reset-email.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import { useEdgeDbEnv, useEdgeDbPKCE } from '../../server'
88
*/
99
export default defineEventHandler(async (req) => {
1010
const pkce = useEdgeDbPKCE()
11-
const { authBaseUrl, resetPasswordUrl: reset_url } = useEdgeDbEnv()
11+
const { urls } = useEdgeDbEnv()
12+
const { authBaseUrl, resetPasswordUrl: reset_url } = urls
1213

1314
const { email } = await readBody(req)
1415
const provider = 'builtin::local_emailpassword'
@@ -41,9 +42,12 @@ export default defineEventHandler(async (req) => {
4142

4243
const { email_sent } = await sendResetResponse.json()
4344

44-
setHeaders(req, {
45-
'Set-Cookie': `edgedb-pkce-verifier=${pkce.verifier}; HttpOnly; Path=/; Secure; SameSite=Strict`,
46-
})
45+
setHeaders(
46+
req,
47+
{
48+
'Set-Cookie': `edgedb-pkce-verifier=${pkce.verifier}; HttpOnly; Path=/; Secure; SameSite=Strict`,
49+
},
50+
)
4751

4852
return {
4953
message: `Reset email sent to '${email_sent}'.`,

0 commit comments

Comments
 (0)