UNPKG

ohayolibs

Version:

Ohayo is a set of essential modules for ohayojp.

102 lines (86 loc) 2.99 kB
import { inject, Inject, Injectable, OnDestroy } from '@angular/core'; import { OhayoAuthConfig, OhayoConfigService } from '@ohayo/util'; import { BehaviorSubject, interval, Observable, Subject, Subscription } from 'rxjs'; import { filter, map, share } from 'rxjs/operators'; import { mergeConfig } from '../auth.config'; import { DA_STORE_TOKEN, IStore } from '../store/interface'; import { AuthReferrer, ITokenModel, ITokenService } from './interface'; export function DA_SERVICE_TOKEN_FACTORY(): ITokenService { return new TokenService(inject(OhayoConfigService), inject(DA_STORE_TOKEN)); } /** * 维护Token信息服务,[在线文档](https://ohayojp.com/auth) */ @Injectable() export class TokenService implements ITokenService, OnDestroy { private refresh$ = new Subject<ITokenModel>(); private change$ = new BehaviorSubject<ITokenModel | null>(null); private interval$: Subscription; private _referrer: AuthReferrer = {}; private _options: OhayoAuthConfig; constructor(configSrv: OhayoConfigService, @Inject(DA_STORE_TOKEN) private store: IStore) { this._options = mergeConfig(configSrv); } get refresh(): Observable<ITokenModel> { this.builderRefresh(); return this.refresh$.pipe(share()); } get login_url(): string | undefined { return this._options.login_url; } get referrer(): AuthReferrer { return this._referrer; } get options(): OhayoAuthConfig { return this._options; } set(data: ITokenModel): boolean { this.change$.next(data); return this.store.set(this._options.store_key!, data); } get(type?: any): any; get<T extends ITokenModel>(type?: new () => T): T { const data = this.store.get(this._options.store_key!); return type ? (Object.assign(new type(), data) as T) : (data as T); } clear(options: { onlyToken: boolean } = { onlyToken: false }): void { let data: ITokenModel | null = null; if (options.onlyToken === true) { data = this.get() as ITokenModel; data.token = ``; this.set(data); } else { this.store.remove(this._options.store_key!); } this.change$.next(data); } change(): Observable<ITokenModel | null> { return this.change$.pipe(share()); } private builderRefresh(): void { const { refreshTime, refreshOffset } = this._options; this.cleanRefresh(); this.interval$ = interval(refreshTime) .pipe( map(() => { const item = this.get() as ITokenModel; const expired = item.expired || 0; if (expired <= 0) { return null; } const curTime = new Date().valueOf() + refreshOffset!; return expired <= curTime ? item : null; }), filter(v => v != null), ) .subscribe(res => this.refresh$.next(res!)); } private cleanRefresh(): void { if (this.interval$ && !this.interval$.closed) { this.interval$.unsubscribe(); } } ngOnDestroy(): void { this.cleanRefresh(); } }