Reduce authentication SoT
Clear and concise description of the problem
Today we define authentication in swagger:
detail: {
summary: 'Create Article',
security: [
{
tokenAuth: [],
},
],
},
and runtime:
beforeHandle: app.store.authService.requireLogin,
This is done for each endpoint individually.
Suggested solution
What if there was a way to reduce the SoTs and lean on ElysiaJS Grouping ? Or at the very least, create a utility to provide both the detail and the beforeHandle to the plugin hook at the same time.
Alternative
No response
Additional context
Continued from here: https://github.com/agnyz/bedstack/pull/145#issuecomment-2744979002
Validations
- [x] Read the Contributing Guide.
- [x] Read the
README.md. - [x] Check that there isn't already an issue that requests the same feature.
@coderabbitai how would you tackle this?
[!TIP] For best results, initiate chat on the files or code changes.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Fetch the title and body of GitHub issue #147 to understand what “this” refers to
curl -s https://api.github.com/repos/agnyz/bedstack/issues/147 | jq '{title: .title, body: .body}'
Length of output: 1197
🏁 Script executed:
#!/bin/bash
# Search occurrences of authService.requireLogin and swagger `tokenAuth` in the repo to understand current pattern
rg --line-number "authService.requireLogin" || true
rg --line-number "tokenAuth" || true
Length of output: 2067
🏁 Script executed:
#!/bin/bash
# Show some snippets around one endpoint in articles.plugin.ts to illustrate duplication
sed -n '40,90p' src/articles/articles.plugin.ts
Length of output: 1383
@yamcodes here’s the direction I would take:
-
Encapsulate “protected endpoint” concerns in one helper
• Create a small utility, e.g.withAuth(meta?: RouteMeta)that returns the options object you currently repeat:export const withAuth = (meta: Partial<RouteMeta> = {}) => ({ beforeHandle: app.store.authService.requireLogin, detail: { security: [{ tokenAuth: [] }], ...meta.detail, }, ...meta, });Wherever you define a route you then write:
.post('/', createHandler, withAuth({ body: InsertArticleSchema, response: ReturnedArticleResponseSchema, detail:{ summary:'Create Article'} })) -
Leverage Elysia’s grouping to remove boilerplate at the plugin level
Each feature plugin already callsnew Elysia(). Wrap the protected routes inside:.group('/articles', (app) => app .use(authPlugin) // ① adds beforeHandle to every descendant .detail({ security:[{tokenAuth:[]}] }) // ② adds swagger security once // descendant routes here )A trivial
authPlugincould be:const authPlugin = new Elysia().onBeforeHandle(app.store.authService.requireLogin); -
Reduce swagger duplication globally (optional)
If every authenticated route shares the same security scheme you can declare a reusable component in OpenAPI and reference it via$ref; Elysia will merge it for every route.
Which option?
• If only a handful of endpoints stay public, grouping (#2) gives the cleanest diff—public routes just sit outside the group.
• If you still need to mix public/protected routes in the same group, the helper (#1) is simpler and keeps intent explicit per call site.
I’d start with #1 (quick refactor, small surface-area) and graduate to grouping once the route structure stabilises.
Let me know if you’d like me to sketch the helper in a PR or open a follow-up issue for the refactor.
Using macros like in https://github.com/bedtime-coders/bedstack-stripped, and grouping together routes based on auth, can help a little. It's not a perfect solution though because I still haven't found a way to apply "detail" to a route externally or at once.