-
Notifications
You must be signed in to change notification settings - Fork 0
Implement Local Log push and SQL Execution Support #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,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) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return sql`${query}`.all(params) | |
| return sql(query).all(params) |
Copilot
AI
Jan 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line has inconsistent indentation (extra leading spaces). The indentation should match the surrounding code.
| 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', | |
| }) | |
| 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', | |
| }) |
Copilot
AI
Jan 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These lines have inconsistent indentation (extra leading spaces). The indentation should match the surrounding code.
| 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', | |
| }) | |
| 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', | |
| }) |
Copilot
AI
Jan 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line has inconsistent indentation (extra leading spaces). The indentation should match the surrounding code.
| 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', | |
| }) | |
| 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', | |
| }) |
Copilot
AI
Jan 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line has inconsistent indentation (extra leading spaces). The indentation should match the surrounding code.
| 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', | |
| }) | |
| 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', | |
| }) |
Copilot
AI
Jan 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These lines have inconsistent indentation (extra leading spaces). The indentation should match the surrounding code.
| 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', | |
| }) | |
| 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', | |
| }) |
Copilot
AI
Jan 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Accessing a hidden global method via globalThis bypasses TypeScript's type system and creates a non-standard coupling between modules. This pattern makes the code harder to maintain and test. Consider using a more explicit dependency injection pattern or returning a reference to the setToken function from the logger initialization.
| */ | |
| 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', | |
| }) | |
| * | |
| * @param setToken - Optional function used to update the logger token. | |
| */ | |
| export const createDevToolsHandshakeRoute = (setToken?: (token: string) => void) => { | |
| return route({ | |
| fn: (_, { 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', | |
| }) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,140 @@ | ||
| import type { Def, DefBase } from '@01edu/types/validator' | ||
| import type { GenericRoutes } from '@01edu/types/router' | ||
| import { route } from '@01edu/api/router' | ||
| import { ARR, BOOL, LIST, OBJ, optional, STR } from '@01edu/api/validator' | ||
|
|
||
| /** | ||
| * Recursive type representing the structure of input/output documentation. | ||
| * It mirrors the structure of the validator definitions but simplified for documentation purposes. | ||
| */ | ||
| export type Documentation = | ||
| & ( | ||
| | { type: Exclude<DefBase['type'], 'object' | 'array' | 'list' | 'union'> } | ||
| | { type: 'object'; properties: Record<string, Documentation> } | ||
| | { type: 'array'; items: Documentation } | ||
| | { type: 'list'; options: (string | number)[] } | ||
| | { type: 'union'; options: Documentation[] } | ||
| ) | ||
| & { description?: string; optional?: boolean } | ||
|
|
||
| /** | ||
| * Represents the documentation for a single API endpoint. | ||
| */ | ||
| export type EndpointDoc = { | ||
| method: string | ||
| path: string | ||
| requiresAuth: boolean | ||
| authFunction: string | ||
| description?: string | ||
| input?: Documentation | ||
| output?: Documentation | ||
| } | ||
|
|
||
| /** | ||
| * Extracts documentation from a validator definition. | ||
| * Recursively processes objects and arrays to build a `Documentation` structure. | ||
| * | ||
| * @param def - The validator definition to extract documentation from. | ||
| * @returns The extracted documentation or undefined if no definition is provided. | ||
| */ | ||
| function extractDocs(def?: Def): Documentation | undefined { | ||
| if (!def) return undefined | ||
| const base = { | ||
| type: def.type, | ||
| description: def.description, | ||
| optional: def.optional, | ||
| } | ||
|
|
||
| switch (def.type) { | ||
| case 'object': { | ||
| const properties: Record<string, Documentation> = {} | ||
| for (const [key, value] of Object.entries(def.properties)) { | ||
| const doc = extractDocs(value) | ||
| if (doc) { | ||
| properties[key] = doc | ||
| } | ||
| } | ||
| return { ...base, properties, type: 'object' } | ||
| } | ||
| case 'array': { | ||
| const items = extractDocs(def.of) as Documentation | ||
| return { ...base, items, type: 'array' } | ||
| } | ||
| case 'list': | ||
| return { ...base, options: def.of as (string | number)[], type: 'list' } | ||
| case 'union': | ||
| return { | ||
| ...base, | ||
| options: def.of.map((d: Def) => extractDocs(d) as Documentation), | ||
| type: 'union', | ||
| } | ||
| case 'boolean': | ||
| return { ...base, type: 'boolean' } | ||
| case 'number': | ||
| return { ...base, type: 'number' } | ||
| case 'string': | ||
| return { ...base, type: 'string' } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Generates API documentation for a set of routes. | ||
| * Iterates through the route definitions and extracts metadata, input, and output documentation. | ||
| * | ||
| * @param defs - The route definitions to generate documentation for. | ||
| * @returns An array of `EndpointDoc` objects describing the API. | ||
| */ | ||
| export const generateApiDocs = (defs: GenericRoutes) => { | ||
| return Object.entries<typeof defs[keyof typeof defs]>(defs).map( | ||
| ([key, handler]) => { | ||
| const slashIndex = key.indexOf('/') | ||
| const method = key.slice(0, slashIndex).toUpperCase() | ||
| const path = key.slice(slashIndex) | ||
| const requiresAuth = handler.authorize ? true : false | ||
|
|
||
| return { | ||
| method, | ||
| path, | ||
| requiresAuth, | ||
| authFunction: handler.authorize?.name || '', | ||
| description: 'description' in handler ? handler.description : undefined, | ||
| input: 'input' in handler ? extractDocs(handler.input) : undefined, | ||
| output: 'output' in handler ? extractDocs(handler.output) : undefined, | ||
| } | ||
| }, | ||
| ) | ||
| } | ||
|
|
||
| const encoder = new TextEncoder() | ||
| const apiDocOutputDef: Def = ARR( | ||
| OBJ({ | ||
| method: LIST(['GET', 'POST', 'PUT', 'DELETE', 'PATCH'], 'HTTP method'), | ||
| path: STR('API endpoint path'), | ||
| requiresAuth: BOOL('whether authentication is required'), | ||
| authFunction: STR('name of the authorization function'), | ||
| description: STR('Endpoint description'), | ||
| input: optional(OBJ({}, 'Input documentation structure')), | ||
| output: optional(OBJ({}, 'Output documentation structure')), | ||
| }, 'API documentation object structure'), | ||
| 'API documentation array', | ||
| ) | ||
|
|
||
| /** | ||
| * Creates a route handler that serves the generated API documentation. | ||
| * The documentation is served as a JSON array of `EndpointDoc` objects. | ||
| * | ||
| * @param defs - The route definitions to generate documentation for. | ||
| * @returns A route handler that serves the API documentation. | ||
| */ | ||
| export const createDocRoute = (defs: GenericRoutes) => { | ||
| const docStr = JSON.stringify(generateApiDocs(defs)) | ||
| const docBuffer = encoder.encode(docStr) | ||
| return route({ | ||
| fn: () => | ||
| new Response(docBuffer, { | ||
| headers: { 'content-type': 'application/json' }, | ||
| }), | ||
| output: apiDocOutputDef, | ||
| description: 'Get the API documentation', | ||
| }) | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -66,14 +66,14 @@ export const CI_COMMIT_SHA: string = ENV('CI_COMMIT_SHA', '') | |||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||
| * @example | ||||||||||||||||||||||||||||||||||||||||||||
| * ```ts | ||||||||||||||||||||||||||||||||||||||||||||
| * import { DEVTOOL_TOKEN } from '@01edu/api/env'; | ||||||||||||||||||||||||||||||||||||||||||||
| * import { DEVTOOL_REPORT_TOKEN } from '@01edu/api/env'; | ||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||
| * const headers = { | ||||||||||||||||||||||||||||||||||||||||||||
| * 'Authorization': `Bearer ${DEVTOOL_TOKEN}`, | ||||||||||||||||||||||||||||||||||||||||||||
| * 'Authorization': `Bearer ${DEVTOOL_REPORT_TOKEN}`, | ||||||||||||||||||||||||||||||||||||||||||||
| * }; | ||||||||||||||||||||||||||||||||||||||||||||
| * ``` | ||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||
| export const DEVTOOL_TOKEN: string = ENV('DEVTOOL_TOKEN', '') | ||||||||||||||||||||||||||||||||||||||||||||
| export const DEVTOOL_REPORT_TOKEN: string = ENV('DEVTOOL_REPORT_TOKEN', '') | ||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||
| * The URL for a developer tool service. | ||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -86,6 +86,20 @@ export const DEVTOOL_TOKEN: string = ENV('DEVTOOL_TOKEN', '') | |||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||
| export const DEVTOOL_URL: string = ENV('DEVTOOL_URL', '') | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||
| * Internal token for dev access in production. | ||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||
| * @example | ||||||||||||||||||||||||||||||||||||||||||||
| * ```ts | ||||||||||||||||||||||||||||||||||||||||||||
| * import { DEVTOOL_ACCESS_TOKEN } from '@01edu/api/env'; | ||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||
| * if (req.headers.get('Authorization') === `Bearer ${DEVTOOL_ACCESS_TOKEN}`) { | ||||||||||||||||||||||||||||||||||||||||||||
| * // Allow access | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+90
to
+97
|
||||||||||||||||||||||||||||||||||||||||||||
| * Internal token for dev access in production. | |
| * | |
| * @example | |
| * ```ts | |
| * import { DEVTOOL_ACCESS_TOKEN } from '@01edu/api/env'; | |
| * | |
| * if (req.headers.get('Authorization') === `Bearer ${DEVTOOL_ACCESS_TOKEN}`) { | |
| * // Allow access | |
| * Authentication token used to protect production-hosted developer tooling | |
| * or diagnostic endpoints (for example, internal dashboards or report hooks). | |
| * | |
| * This token is intended for restricted operational use only and must not be | |
| * used for end-user authentication or as a general backdoor into the | |
| * application. Rotate and store it securely (e.g. via your secret manager). | |
| * | |
| * @example | |
| * ```ts | |
| * import { DEVTOOL_ACCESS_TOKEN } from '@01edu/api/env'; | |
| * | |
| * if (req.headers.get('Authorization') === `Bearer ${DEVTOOL_ACCESS_TOKEN}`) { | |
| * // Allow access to an internal developer tooling endpoint |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The quote style was changed from double quotes to single quotes. While this change is cosmetic, it should be consistent with the project's style guidelines. Ensure this aligns with the project's formatting standards.