feat: add more auth features and remove auth module
Some checks failed
Build, Lint & Test Lib / Build, Lint and Test Library (push) Has been cancelled
Some checks failed
Build, Lint & Test Lib / Build, Lint and Test Library (push) Has been cancelled
This commit is contained in:
parent
c8c4fc847d
commit
fe10ed2850
@ -26,7 +26,7 @@ pnpm add oidc-client-rx @outposts/injection-js @abraham/reflection
|
||||
```typescript
|
||||
import '@abraham/reflection'; // or 'reflect-metadata' | 'core-js/es7/reflect'
|
||||
import { type Injector, ReflectiveInjector } from '@outposts/injection-js';
|
||||
import { LogLevel, OidcSecurityService, provideAuth } from 'oidc-client-rx';
|
||||
import { LogLevel, OidcSecurityService, provideAuth, withDefaultFeatures } from 'oidc-client-rx';
|
||||
|
||||
const injector = ReflectiveInjector.resolveAndCreate(
|
||||
provideAuth(
|
||||
@ -43,7 +43,8 @@ const injector = ReflectiveInjector.resolveAndCreate(
|
||||
logLevel: LogLevel.Debug,
|
||||
...
|
||||
},
|
||||
}
|
||||
},
|
||||
withDefaultFeatures()
|
||||
)
|
||||
) as Injector;
|
||||
|
||||
|
@ -1,7 +1,12 @@
|
||||
import '@abraham/reflection'; // or 'reflect-metadata' | 'core-js/es7/reflect'
|
||||
import { type Injector, ReflectiveInjector } from '@outposts/injection-js';
|
||||
import { RouterProvider, createRouter } from '@tanstack/react-router';
|
||||
import { LogLevel, OidcSecurityService, provideAuth } from 'oidc-client-rx';
|
||||
import {
|
||||
LogLevel,
|
||||
OidcSecurityService,
|
||||
provideAuth,
|
||||
withDefaultFeatures,
|
||||
} from 'oidc-client-rx';
|
||||
import {
|
||||
InjectorContextVoidInjector,
|
||||
InjectorProvider,
|
||||
@ -51,6 +56,11 @@ const injector = ReflectiveInjector.resolveAndCreate(
|
||||
},
|
||||
},
|
||||
},
|
||||
withDefaultFeatures(
|
||||
// the after feature will replace the before same type feature
|
||||
// so the following line can be ignored
|
||||
{ router: { enabled: false } }
|
||||
),
|
||||
withTanstackRouter(router)
|
||||
)
|
||||
) as Injector;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { InjectionToken, inject } from '@outposts/injection-js';
|
||||
import type { Router } from '@tanstack/react-router';
|
||||
import { AbstractRouter } from 'src/router';
|
||||
import type { AuthFeature } from '../../provide-auth';
|
||||
import type { AuthFeature } from '../../features';
|
||||
import { AbstractRouter } from '../../router';
|
||||
|
||||
export type TanStackRouter = Router<any, any, any, any, any, any>;
|
||||
|
||||
|
@ -1,17 +1,17 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import {
|
||||
type DefaultHttpTestingController,
|
||||
HTTP_CLIENT_TEST_CONTROLLER,
|
||||
provideHttpClientTesting,
|
||||
} from '@/testing/http';
|
||||
import { HttpHeaders } from '@ngify/http';
|
||||
import type { HttpTestingController } from '@ngify/http/testing';
|
||||
import { ReplaySubject, firstValueFrom, share } from 'rxjs';
|
||||
import { DataService } from './data.service';
|
||||
import { HttpBaseService } from './http-base.service';
|
||||
|
||||
describe('Data Service', () => {
|
||||
let dataService: DataService;
|
||||
let httpMock: HttpTestingController;
|
||||
let httpMock: DefaultHttpTestingController;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
|
@ -1,11 +1,10 @@
|
||||
import { HttpClient, type HttpHeaders } from '@ngify/http';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import type { Observable } from 'rxjs';
|
||||
import type { HttpParams } from '../http';
|
||||
import { HTTP_CLIENT, type HttpHeaders, type HttpParams } from '../http';
|
||||
|
||||
@Injectable()
|
||||
export class HttpBaseService {
|
||||
private readonly http = inject(HttpClient);
|
||||
private readonly http = inject(HTTP_CLIENT);
|
||||
|
||||
get<T>(
|
||||
url: string,
|
||||
@ -22,7 +21,7 @@ export class HttpBaseService {
|
||||
body: unknown,
|
||||
options: { headers?: HttpHeaders; params?: HttpParams } = {}
|
||||
): Observable<T> {
|
||||
return this.http.post<T>(url, body, {
|
||||
return this.http.post<T>(url, body as any, {
|
||||
...options,
|
||||
params: options.params?.toNgify(),
|
||||
});
|
||||
|
@ -1,66 +0,0 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { PASSED_CONFIG } from './auth-config';
|
||||
import { AuthModule } from './auth.module';
|
||||
import { ConfigurationService } from './config/config.service';
|
||||
import {
|
||||
StsConfigHttpLoader,
|
||||
StsConfigLoader,
|
||||
StsConfigStaticLoader,
|
||||
} from './config/loader/config-loader';
|
||||
import { mockProvider } from './testing/mock';
|
||||
|
||||
describe('AuthModule', () => {
|
||||
describe('APP_CONFIG', () => {
|
||||
let authModule: AuthModule;
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [AuthModule.forRoot({ config: { authority: 'something' } })],
|
||||
providers: [mockProvider(ConfigurationService)],
|
||||
}).compileComponents();
|
||||
authModule = TestBed.getImportByType(AuthModule);
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(AuthModule).toBeDefined();
|
||||
expect(authModule).toBeDefined();
|
||||
});
|
||||
|
||||
it('should provide config', () => {
|
||||
const config = authModule.get(PASSED_CONFIG);
|
||||
|
||||
expect(config).toEqual({ config: { authority: 'something' } });
|
||||
});
|
||||
|
||||
it('should create StsConfigStaticLoader if config is passed', () => {
|
||||
const configLoader = authModule.get(StsConfigLoader);
|
||||
|
||||
expect(configLoader instanceof StsConfigStaticLoader).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('StsConfigHttpLoader', () => {
|
||||
let authModule: AuthModule;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [
|
||||
AuthModule.forRoot({
|
||||
loader: {
|
||||
provide: StsConfigLoader,
|
||||
useFactory: () => new StsConfigHttpLoader(of({})),
|
||||
},
|
||||
}),
|
||||
],
|
||||
providers: [mockProvider(ConfigurationService)],
|
||||
}).compileComponents();
|
||||
authModule = TestBed.getImportByType(AuthModule);
|
||||
});
|
||||
|
||||
it('should create StsConfigStaticLoader if config is passed', () => {
|
||||
const configLoader = authModule.get(StsConfigLoader);
|
||||
|
||||
expect(configLoader instanceof StsConfigHttpLoader).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
@ -1,41 +0,0 @@
|
||||
import {
|
||||
type InjectionToken,
|
||||
Injector,
|
||||
ReflectiveInjector,
|
||||
type Type,
|
||||
} from '@outposts/injection-js';
|
||||
import type { PassedInitialConfig } from './auth-config';
|
||||
import type { Module } from './injection';
|
||||
import { _provideAuth } from './provide-auth';
|
||||
|
||||
export interface AuthModuleOptions {
|
||||
passedConfig: PassedInitialConfig;
|
||||
parentInjector?: ReflectiveInjector;
|
||||
}
|
||||
|
||||
export class AuthModule extends Injector {
|
||||
passedConfig: PassedInitialConfig;
|
||||
injector: ReflectiveInjector;
|
||||
parentInjector?: Injector;
|
||||
|
||||
constructor(passedConfig?: PassedInitialConfig, parentInjector?: Injector) {
|
||||
super();
|
||||
this.passedConfig = passedConfig ?? {};
|
||||
this.parentInjector = parentInjector;
|
||||
this.injector = ReflectiveInjector.resolveAndCreate(
|
||||
[..._provideAuth(this.passedConfig)],
|
||||
this.parentInjector
|
||||
);
|
||||
}
|
||||
|
||||
static forRoot(passedConfig?: PassedInitialConfig): Module {
|
||||
return (parentInjector?: Injector) =>
|
||||
new AuthModule(passedConfig, parentInjector);
|
||||
}
|
||||
|
||||
get<T>(token: Type<T> | InjectionToken<T>, notFoundValue?: T): T;
|
||||
get(token: any, notFoundValue?: any): any;
|
||||
get(token: unknown, notFoundValue?: unknown): any {
|
||||
return this.injector.get(token, notFoundValue);
|
||||
}
|
||||
}
|
131
src/features.ts
Normal file
131
src/features.ts
Normal file
@ -0,0 +1,131 @@
|
||||
import type { HttpFeature } from '@ngify/http';
|
||||
import type { Provider } from '@outposts/injection-js';
|
||||
import { DOCUMENT } from './dom';
|
||||
import { provideHttpClient } from './http';
|
||||
import {
|
||||
AbstractRouter,
|
||||
VanillaHistoryRouter,
|
||||
VanillaLocationRouter,
|
||||
} from './router';
|
||||
import { AbstractSecurityStorage } from './storage/abstract-security-storage';
|
||||
import { DefaultLocalStorageService } from './storage/default-localstorage.service';
|
||||
import { DefaultSessionStorageService } from './storage/default-sessionstorage.service';
|
||||
import { PLATFORM_ID } from './utils/platform-provider/platform.provider';
|
||||
|
||||
/**
|
||||
* A feature to be used with `provideAuth`.
|
||||
*/
|
||||
export interface AuthFeature {
|
||||
ɵproviders: Provider[];
|
||||
}
|
||||
|
||||
export interface BrowserPlatformFeatureOptions {
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
export function withBrowserPlatform({
|
||||
enabled = true,
|
||||
}: BrowserPlatformFeatureOptions = {}): AuthFeature {
|
||||
return {
|
||||
ɵproviders: enabled
|
||||
? [
|
||||
{
|
||||
provide: DOCUMENT,
|
||||
useFactory: () => document,
|
||||
},
|
||||
{
|
||||
provide: PLATFORM_ID,
|
||||
useValue: 'browser',
|
||||
},
|
||||
]
|
||||
: [],
|
||||
};
|
||||
}
|
||||
|
||||
export interface HttpClientFeatureOptions {
|
||||
enabled?: boolean;
|
||||
features?: HttpFeature[];
|
||||
}
|
||||
|
||||
export function withHttpClient({
|
||||
features,
|
||||
enabled = true,
|
||||
}: HttpClientFeatureOptions = {}): AuthFeature {
|
||||
return {
|
||||
ɵproviders: enabled ? provideHttpClient(features) : [],
|
||||
};
|
||||
}
|
||||
|
||||
export type SecurityStorageType = 'session-storage' | 'local-storage';
|
||||
|
||||
export interface SecurityStorageFeatureOptions {
|
||||
enabled?: boolean;
|
||||
type?: SecurityStorageType;
|
||||
}
|
||||
|
||||
export function withSecurityStorage({
|
||||
enabled = true,
|
||||
type = 'session-storage',
|
||||
}: SecurityStorageFeatureOptions = {}): AuthFeature {
|
||||
return {
|
||||
ɵproviders: enabled
|
||||
? [
|
||||
type === 'session-storage'
|
||||
? {
|
||||
provide: AbstractSecurityStorage,
|
||||
useClass: DefaultLocalStorageService,
|
||||
}
|
||||
: {
|
||||
provide: AbstractSecurityStorage,
|
||||
useClass: DefaultSessionStorageService,
|
||||
},
|
||||
]
|
||||
: [],
|
||||
};
|
||||
}
|
||||
|
||||
export type VanillaRouterType = 'location' | 'history';
|
||||
|
||||
export interface VanillaRouterFeatureOptions {
|
||||
enabled?: boolean;
|
||||
type?: VanillaRouterType;
|
||||
}
|
||||
|
||||
export function withVanillaRouter({
|
||||
enabled = true,
|
||||
type = 'history',
|
||||
}: VanillaRouterFeatureOptions = {}): AuthFeature {
|
||||
return {
|
||||
ɵproviders: enabled
|
||||
? [
|
||||
type === 'location'
|
||||
? {
|
||||
provide: AbstractRouter,
|
||||
useClass: VanillaLocationRouter,
|
||||
}
|
||||
: {
|
||||
provide: AbstractRouter,
|
||||
useClass: VanillaHistoryRouter,
|
||||
},
|
||||
]
|
||||
: [],
|
||||
};
|
||||
}
|
||||
|
||||
export interface DefaultFeaturesOptions {
|
||||
browserPlatform?: BrowserPlatformFeatureOptions;
|
||||
securityStorage?: SecurityStorageFeatureOptions;
|
||||
router?: VanillaRouterFeatureOptions;
|
||||
httpClient?: HttpClientFeatureOptions;
|
||||
}
|
||||
|
||||
export function withDefaultFeatures(
|
||||
options: DefaultFeaturesOptions = {}
|
||||
): AuthFeature[] {
|
||||
return [
|
||||
withBrowserPlatform(options.browserPlatform),
|
||||
withSecurityStorage(options.securityStorage),
|
||||
withHttpClient(options.httpClient),
|
||||
withVanillaRouter(options.router),
|
||||
].filter(Boolean) as AuthFeature[];
|
||||
}
|
@ -1,10 +1,15 @@
|
||||
import {
|
||||
// biome-ignore lint/nursery/noExportedImports: <explanation>
|
||||
HttpClient as DefaultHttpClient,
|
||||
type HttpBackend,
|
||||
HttpClient,
|
||||
type HttpFeature,
|
||||
HttpFeatureKind,
|
||||
// biome-ignore lint/nursery/noExportedImports: <explanation>
|
||||
HttpHeaders,
|
||||
type HttpInterceptor,
|
||||
type HttpInterceptorFn,
|
||||
type HttpRequest,
|
||||
type HttpParams as NgifyHttpParams,
|
||||
withInterceptors,
|
||||
withLegacyInterceptors,
|
||||
} from '@ngify/http';
|
||||
@ -13,8 +18,12 @@ import {
|
||||
Optional,
|
||||
type Provider,
|
||||
} from '@outposts/injection-js';
|
||||
import type { Observable } from 'rxjs';
|
||||
import type { ArrayOrNullableOne } from '../utils/types';
|
||||
export { HttpParams, type HttpParamsOptions } from './params';
|
||||
// biome-ignore lint/nursery/noExportedImports: <explanation>
|
||||
import { HttpParams, type HttpParamsOptions } from './params';
|
||||
|
||||
export { HttpParams, HttpHeaders, type HttpParamsOptions, DefaultHttpClient };
|
||||
|
||||
export const HTTP_FEATURES = new InjectionToken<HttpFeature[]>('HTTP_FEATURES');
|
||||
|
||||
@ -112,14 +121,29 @@ export function provideHttpClient(features: HttpFeature[] = []): Provider[] {
|
||||
multi: true,
|
||||
},
|
||||
{
|
||||
provide: HttpClient,
|
||||
provide: HTTP_CLIENT,
|
||||
useFactory: (features: ArrayOrNullableOne<HttpFeature>[]) => {
|
||||
const normalizedFeatures = [features]
|
||||
.flat(Number.MAX_SAFE_INTEGER)
|
||||
.filter(Boolean) as HttpFeature[];
|
||||
return new HttpClient(...normalizedFeatures);
|
||||
return new DefaultHttpClient(...normalizedFeatures);
|
||||
},
|
||||
deps: [HTTP_FEATURES],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export type HttpClient = {
|
||||
get<T>(
|
||||
url: string,
|
||||
options?: { headers?: HttpHeaders; params?: NgifyHttpParams }
|
||||
): Observable<T>;
|
||||
|
||||
post<T>(
|
||||
url: string,
|
||||
body?: HttpRequest<any>['body'],
|
||||
options?: { headers?: HttpHeaders; params?: NgifyHttpParams }
|
||||
): Observable<T>;
|
||||
};
|
||||
|
||||
export const HTTP_CLIENT = new InjectionToken<HttpClient>('HTTP_CLIENT');
|
||||
|
@ -4,7 +4,6 @@ export type { PassedInitialConfig } from './auth-config';
|
||||
export * from './auth-options';
|
||||
export * from './auth-state/auth-result';
|
||||
export * from './auth-state/auth-state';
|
||||
export * from './auth.module';
|
||||
export * from './auto-login/auto-login-partial-routes.guard';
|
||||
export * from './config/auth-well-known/auth-well-known-endpoints';
|
||||
export * from './config/config.service';
|
||||
@ -31,3 +30,4 @@ export * from './validation/validation-result';
|
||||
export * from './injection';
|
||||
export * from './router';
|
||||
export * from './http';
|
||||
export * from './features';
|
||||
|
@ -1,11 +1,15 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import {
|
||||
type DefaultHttpTestingController,
|
||||
HTTP_CLIENT_TEST_CONTROLLER,
|
||||
TestBed,
|
||||
provideHttpClientTesting,
|
||||
} from '@/testing';
|
||||
import { HttpClient } from '@ngify/http';
|
||||
import type { HttpTestingController } from '@ngify/http/testing';
|
||||
import { HTTP_INTERCEPTOR_FNS, HTTP_LEGACY_INTERCEPTORS } from 'oidc-client-rx';
|
||||
import {
|
||||
type DefaultHttpClient,
|
||||
HTTP_CLIENT,
|
||||
HTTP_INTERCEPTOR_FNS,
|
||||
HTTP_LEGACY_INTERCEPTORS,
|
||||
} from 'oidc-client-rx';
|
||||
import { ReplaySubject, firstValueFrom, share } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
@ -16,9 +20,9 @@ import { AuthInterceptor, authInterceptor } from './auth.interceptor';
|
||||
import { ClosestMatchingRouteService } from './closest-matching-route.service';
|
||||
|
||||
describe('AuthHttpInterceptor', () => {
|
||||
let httpTestingController: HttpTestingController;
|
||||
let httpTestingController: DefaultHttpTestingController;
|
||||
let configurationService: ConfigurationService;
|
||||
let httpClient: HttpClient;
|
||||
let httpClient: DefaultHttpClient;
|
||||
let authStateService: AuthStateService;
|
||||
let closestMatchingRouteService: ClosestMatchingRouteService;
|
||||
|
||||
@ -40,7 +44,7 @@ describe('AuthHttpInterceptor', () => {
|
||||
],
|
||||
});
|
||||
|
||||
httpClient = TestBed.inject(HttpClient);
|
||||
httpClient = TestBed.inject(HTTP_CLIENT) as DefaultHttpClient;
|
||||
httpTestingController = TestBed.inject(HTTP_CLIENT_TEST_CONTROLLER);
|
||||
configurationService = TestBed.inject(ConfigurationService);
|
||||
authStateService = TestBed.inject(AuthStateService);
|
||||
@ -72,7 +76,7 @@ describe('AuthHttpInterceptor', () => {
|
||||
],
|
||||
});
|
||||
|
||||
httpClient = TestBed.inject(HttpClient);
|
||||
httpClient = TestBed.inject(HTTP_CLIENT) as DefaultHttpClient;
|
||||
httpTestingController = TestBed.inject(HTTP_CLIENT_TEST_CONTROLLER);
|
||||
configurationService = TestBed.inject(ConfigurationService);
|
||||
authStateService = TestBed.inject(AuthStateService);
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { HttpClient } from '@ngify/http';
|
||||
import type { Provider } from '@outposts/injection-js';
|
||||
import { DataService } from './api/data.service';
|
||||
import { HttpBaseService } from './api/http-base.service';
|
||||
@ -24,6 +23,7 @@ import { StsConfigLoader } from './config/loader/config-loader';
|
||||
import { ConfigValidationService } from './config/validation/config-validation.service';
|
||||
import { DOCUMENT } from './dom';
|
||||
import { JwkExtractor } from './extractors/jwk.extractor';
|
||||
import type { AuthFeature } from './features';
|
||||
import { CodeFlowCallbackHandlerService } from './flows/callback-handling/code-flow-callback-handler.service';
|
||||
import { HistoryJwtKeysCallbackHandlerService } from './flows/callback-handling/history-jwt-keys-callback-handler.service';
|
||||
import { ImplicitFlowCallbackHandlerService } from './flows/callback-handling/implicit-flow-callback-handler.service';
|
||||
@ -62,10 +62,7 @@ import { UserService } from './user-data/user.service';
|
||||
import { CryptoService } from './utils/crypto/crypto.service';
|
||||
import { EqualityService } from './utils/equality/equality.service';
|
||||
import { FlowHelper } from './utils/flowHelper/flow-helper.service';
|
||||
import {
|
||||
PLATFORM_ID,
|
||||
PlatformProvider,
|
||||
} from './utils/platform-provider/platform.provider';
|
||||
import { PlatformProvider } from './utils/platform-provider/platform.provider';
|
||||
import { RedirectService } from './utils/redirect/redirect.service';
|
||||
import { TokenHelperService } from './utils/tokenHelper/token-helper.service';
|
||||
import { CurrentUrlService } from './utils/url/current-url.service';
|
||||
@ -75,20 +72,17 @@ import { JwtWindowCryptoService } from './validation/jwt-window-crypto.service';
|
||||
import { StateValidationService } from './validation/state-validation.service';
|
||||
import { TokenValidationService } from './validation/token-validation.service';
|
||||
|
||||
/**
|
||||
* A feature to be used with `provideAuth`.
|
||||
*/
|
||||
export interface AuthFeature {
|
||||
ɵproviders: Provider[];
|
||||
}
|
||||
|
||||
export function provideAuth(
|
||||
passedConfig: PassedInitialConfig,
|
||||
...features: AuthFeature[]
|
||||
...features: (AuthFeature | AuthFeature[])[]
|
||||
): Provider[] {
|
||||
const providers = _provideAuth(passedConfig);
|
||||
|
||||
for (const feature of features) {
|
||||
const normailizedFeatures = features
|
||||
.flat(Number.MAX_SAFE_INTEGER)
|
||||
.filter(Boolean) as AuthFeature[];
|
||||
|
||||
for (const feature of normailizedFeatures) {
|
||||
providers.push(...feature.ɵproviders);
|
||||
}
|
||||
|
||||
@ -97,15 +91,6 @@ export function provideAuth(
|
||||
|
||||
export function _provideAuth(passedConfig: PassedInitialConfig): Provider[] {
|
||||
return [
|
||||
{
|
||||
provide: DOCUMENT,
|
||||
useFactory: () => document,
|
||||
},
|
||||
HttpClient,
|
||||
{
|
||||
provide: PLATFORM_ID,
|
||||
useValue: 'browser',
|
||||
},
|
||||
// Make the PASSED_CONFIG available through injection
|
||||
{ provide: PASSED_CONFIG, useValue: passedConfig },
|
||||
// Create the loader: Either the one getting passed or a static one
|
||||
|
@ -1,3 +1,6 @@
|
||||
import { inject } from '@outposts/injection-js';
|
||||
import { DOCUMENT } from 'src/dom';
|
||||
|
||||
export type RouteData = {
|
||||
[key: string | symbol]: any;
|
||||
};
|
||||
@ -26,3 +29,55 @@ export abstract class AbstractRouter<
|
||||
|
||||
abstract getCurrentNavigation(): NAVIGATION;
|
||||
}
|
||||
|
||||
export class VanillaLocationRouter extends AbstractRouter {
|
||||
private document = inject(DOCUMENT);
|
||||
|
||||
private get location(): Location {
|
||||
const location = this.document.defaultView?.window?.location;
|
||||
if (!location) {
|
||||
throw new Error('current document do not support Location API');
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
navigateByUrl(url: string): void {
|
||||
this.location.href = url;
|
||||
}
|
||||
|
||||
getCurrentNavigation() {
|
||||
return {
|
||||
extractedUrl: `${this.location.pathname}${this.location.search}${this.location.hash}`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class VanillaHistoryRouter extends AbstractRouter<string> {
|
||||
private document = inject(DOCUMENT);
|
||||
|
||||
private get history(): History {
|
||||
const history = this.document.defaultView?.window?.history;
|
||||
if (!history) {
|
||||
throw new Error('current document do not support History API');
|
||||
}
|
||||
return history;
|
||||
}
|
||||
|
||||
private get location(): Location {
|
||||
const location = this.document.defaultView?.window?.location;
|
||||
if (!location) {
|
||||
throw new Error('current document do not support Location API');
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
navigateByUrl(url: string): void {
|
||||
this.history.pushState({}, '', url);
|
||||
}
|
||||
|
||||
getCurrentNavigation() {
|
||||
return {
|
||||
extractedUrl: `${this.location.pathname}${this.location.search}${this.location.hash}`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ import { HttpClientTestingBackend } from '@ngify/http/testing';
|
||||
import { InjectionToken, type Provider } from '@outposts/injection-js';
|
||||
import { HTTP_BACKEND, provideHttpClient } from 'oidc-client-rx';
|
||||
|
||||
export { HttpTestingController as DefaultHttpTestingController } from '@ngify/http/testing';
|
||||
|
||||
export const HTTP_CLIENT_TEST_CONTROLLER =
|
||||
new InjectionToken<HttpClientTestingBackend>('HTTP_CLIENT_TEST_CONTROLLER');
|
||||
|
||||
|
@ -6,4 +6,8 @@ export {
|
||||
} from './spy';
|
||||
export { createRetriableStream } from './create-retriable-stream.helper';
|
||||
export { MockRouter, mockRouterProvider } from './router';
|
||||
export { provideHttpClientTesting, HTTP_CLIENT_TEST_CONTROLLER } from './http';
|
||||
export {
|
||||
provideHttpClientTesting,
|
||||
HTTP_CLIENT_TEST_CONTROLLER,
|
||||
DefaultHttpTestingController,
|
||||
} from './http';
|
||||
|
Loading…
Reference in New Issue
Block a user