Files
AstralRinth/packages/api-client/src/features/auth.ts
Calum H. 70e2138248 feat: base api-client impl (#4694)
* feat: base api-client impl

* fix: doc

* feat: start work on module stuff

* feat: migrate v2/v3 projects into module system

* fix: lint & README.md contributing

* refactor: remove utils old api client prototype

* fix: lint

* fix: api url issues

* fix: baseurl in error.vue

* fix: readme

* fix typo in readme

* Update apps/frontend/src/providers/api-client.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Calum H. <hendersoncal117@gmail.com>

* Update packages/api-client/src/features/verbose-logging.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Calum H. <hendersoncal117@gmail.com>

* Update packages/api-client/src/features/retry.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Calum H. <hendersoncal117@gmail.com>

---------

Signed-off-by: Calum H. <hendersoncal117@gmail.com>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-12 20:29:12 +00:00

90 lines
2.0 KiB
TypeScript

import { AbstractFeature, type FeatureConfig } from '../core/abstract-feature'
import type { RequestContext } from '../types/request'
/**
* Authentication feature configuration
*/
export interface AuthConfig extends FeatureConfig {
/**
* Authentication token
* - string: static token
* - function: async function that returns token (useful for dynamic tokens)
*/
token: string | (() => Promise<string | undefined>)
/**
* Token prefix (e.g., 'Bearer', 'Token')
* @default 'Bearer'
*/
tokenPrefix?: string
/**
* Custom header name for the token
* @default 'Authorization'
*/
headerName?: string
}
/**
* Authentication feature
*
* Automatically injects authentication tokens into request headers.
* Supports both static tokens and dynamic token providers.
*
* @example
* ```typescript
* // Static token
* const auth = new AuthFeature({
* token: 'mrp_...'
* })
*
* // Dynamic token (e.g., from auth state)
* const auth = new AuthFeature({
* token: async () => await getAuthToken()
* })
* ```
*/
export class AuthFeature extends AbstractFeature {
protected declare config: AuthConfig
async execute<T>(next: () => Promise<T>, context: RequestContext): Promise<T> {
const token = await this.getToken()
if (token) {
const headerName = this.config.headerName ?? 'Authorization'
const tokenPrefix = this.config.tokenPrefix ?? 'Bearer'
const headerValue = tokenPrefix ? `${tokenPrefix} ${token}` : token
context.options.headers = {
...context.options.headers,
[headerName]: headerValue,
}
}
return next()
}
shouldApply(context: RequestContext): boolean {
if (context.options.skipAuth) {
return false
}
return super.shouldApply(context)
}
/**
* Get the authentication token
*
* Handles both static tokens and async token providers
*/
private async getToken(): Promise<string | undefined> {
const { token } = this.config
if (typeof token === 'function') {
return await token()
}
return token
}
}