@v4fire/client
Version:
V4Fire client core library
139 lines (108 loc) • 2.93 kB
text/typescript
/*!
* V4Fire Client Core
* https://github.com/V4Fire/Client
*
* Released under the MIT license
* https://github.com/V4Fire/Client/blob/master/LICENSE
*/
import Provider, {
provider,
Middlewares,
MiddlewareParams,
RequestFunctionResponse,
Response,
RequestPromise
} from 'core/data';
import * as s from 'core/session';
export * from 'core/data';
@provider
export default class Session extends Provider {
/**
* Authorization scheme prefix
*/
readonly authPrfx: string = 'Bearer ';
/**
* Authorization header name
*/
readonly authHeader: string = 'Authorization';
/**
* Authorization refresh header name
*/
readonly authRefreshHeader: string = 'X-JWT-TOKEN';
/**
* CSRF header name
*/
readonly csrfHeader: string = 'X-XSRF-TOKEN';
/**
* If true, then after clearing the session (in case of answer 401) will be an additional query
*/
readonly requestAfterClear: boolean = true;
static override readonly middlewares: Middlewares = {
...Provider.middlewares,
async addSession(this: Session, {opts}: MiddlewareParams): Promise<void> {
if (opts.api) {
const h = await this.getAuthParams();
Object.mixin({traits: true}, opts.headers, h);
}
}
};
override async getAuthParams(): Promise<Dictionary> {
const
session = await s.get();
if (Object.isString(session.auth)) {
return {
[]: this.authPrfx + session.auth,
[]: session.params?.csrf
};
}
return {};
}
protected override updateRequest<T = unknown>(url: string, factory: RequestFunctionResponse<T>): RequestPromise<T>;
protected override updateRequest<T = unknown>(
url: string,
event: string,
factory: RequestFunctionResponse<T>
): RequestPromise<T>;
protected override updateRequest(
url: string,
event: string | RequestFunctionResponse,
factory?: RequestFunctionResponse
): RequestPromise {
const
req = super.updateRequest(url, Object.cast(event), Object.cast<RequestFunctionResponse>(factory)),
session = s.get();
const update = async (res) => {
const
info = <Response>res.response,
refreshHeader = info.getHeader(this.authRefreshHeader);
try {
if (refreshHeader != null) {
await s.set(refreshHeader, {csrf: info.getHeader(this.csrfHeader)});
}
} catch {}
};
req
.then(update)
.catch(stderr);
return Provider.borrowRequestPromiseAPI(req, req.catch(async (err) => {
const
response = Object.get<Response>(err, 'details.response'),
{auth, params} = await session;
if (response) {
const
r = () => this.updateRequest(url, Object.cast(event), <RequestFunctionResponse>factory);
if (response.status === 401) {
if (!await s.match(auth, params)) {
return r();
}
await s.clear();
if (Object.isTruly(auth) && this.requestAfterClear) {
return r();
}
}
await update({response});
}
throw err;
}));
}
}