-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdev.ts
More file actions
83 lines (80 loc) · 2.77 KB
/
dev.ts
File metadata and controls
83 lines (80 loc) · 2.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import { APP_ENV, DEVTOOL_ACCESS_TOKEN } from '@01edu/api/env'
import { respond } from '@01edu/api/response'
import type { RequestContext } from '@01edu/types/context'
import { route } from '@01edu/api/router'
import { ARR, OBJ, optional, STR } from '@01edu/api/validator'
import type { Sql } from '@01edu/db'
/**
* Authorizes access to developer routes.
* Checks for `DEVTOOL_ACCESS_TOKEN` in the Authorization header.
* In non-prod environments, access is allowed if no token is configured.
*
* @param ctx - The request context.
* @throws {respond.UnauthorizedError} If access is denied.
*/
export const authorizeDevAccess = ({ req }: RequestContext) => {
if (APP_ENV !== 'prod') return // always open for dev env
const auth = req.headers.get('Authorization') || ''
const bearer = auth.toLowerCase().startsWith('bearer ')
? auth.slice(7).trim()
: ''
if (bearer && bearer === DEVTOOL_ACCESS_TOKEN) return
throw new respond.UnauthorizedError({ message: 'Unauthorized access' })
}
/**
* Creates a route handler for executing arbitrary SQL queries.
* Useful for debugging and development tools.
*
* @param sql - The SQL tag function to use for execution.
* @returns A route handler configuration.
*/
export const createSqlDevRoute = (sql?: Sql) => {
return route({
authorize: authorizeDevAccess,
fn: (_, { query, params }) => {
try {
if (!sql) {
return respond.NotImplemented({
message: 'Database not configured',
})
}
return sql`${query}`.all(params)
} catch (error) {
throw new respond.BadRequestError({
message: error instanceof Error ? error.message : 'Unexpected Error',
})
}
},
input: OBJ({
query: STR('The SQL query to execute'),
params: optional(OBJ({}, 'The parameters to bind to the query')),
}),
output: ARR(
optional(OBJ({}, 'A single result row')),
'List of results',
),
description: 'Execute an SQL query',
})
}
/**
* Creates a route handler for receiving the DevTools logging token.
* This allows the local app to send logs to the connected DevTools instance.
*/
export const createDevToolsHandshakeRoute = () => {
return route({
fn: (_, { token }) => {
// @ts-ignore: Call hidden method
const setToken = globalThis.__DEVTOOLS_SET_TOKEN__
if (typeof setToken === 'function') {
setToken(token)
return { success: true }
}
return respond.NotImplemented({ message: 'Logger not configured for dynamic updates' })
},
input: OBJ({
token: STR('The logging token from DevTools'),
}),
output: OBJ({}, 'Success response'),
description: 'Receive DevTools logging token',
})
}