Skip to content

Commit c2a2235

Browse files
committed
feat: add API endpoints config and feature flags for endpoints
1 parent 3fb0cc3 commit c2a2235

File tree

8 files changed

+103
-8
lines changed

8 files changed

+103
-8
lines changed

src/app/app.module.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import { ProductsModule } from './products/products.module';
1414
import { HttpClientModule } from '@angular/common/http';
1515
import { MatBadgeModule } from '@angular/material/badge';
1616
import { CartModule } from './cart/cart.module';
17+
import { CONFIG_TOKEN } from './core/injection-tokens/config.token';
18+
import { environment } from '../environments/environment';
1719

1820
@NgModule({
1921
declarations: [AppComponent, HeaderComponent],
@@ -31,7 +33,12 @@ import { CartModule } from './cart/cart.module';
3133
HttpClientModule,
3234
MatBadgeModule,
3335
],
34-
providers: [],
36+
providers: [
37+
{
38+
provide: CONFIG_TOKEN,
39+
useValue: environment,
40+
},
41+
],
3542
bootstrap: [AppComponent],
3643
})
3744
export class AppModule {}

src/app/core/api.service.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { TestBed } from '@angular/core/testing';
2+
3+
import { ApiService } from './api.service';
4+
5+
describe('ApiService', () => {
6+
let service: ApiService;
7+
8+
beforeEach(() => {
9+
TestBed.configureTestingModule({});
10+
service = TestBed.inject(ApiService);
11+
});
12+
13+
it('should be created', () => {
14+
expect(service).toBeTruthy();
15+
});
16+
});

src/app/core/api.service.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { Injectable, Injector } from '@angular/core';
2+
import { ApiEndpoint, Config } from '../../environments/config.interface';
3+
import { CONFIG_TOKEN } from './injection-tokens/config.token';
4+
import { Location } from '@angular/common';
5+
import { HttpClient } from '@angular/common/http';
6+
7+
/** Base class for services working with APIs */
8+
@Injectable()
9+
export abstract class ApiService {
10+
protected readonly config: Config;
11+
protected readonly http: HttpClient;
12+
13+
protected constructor(protected readonly injector: Injector) {
14+
this.config = injector.get(CONFIG_TOKEN);
15+
this.http = injector.get(HttpClient);
16+
}
17+
18+
endpointEnabled(api: ApiEndpoint): boolean {
19+
return this.config.apiEndpointsEnabled[api];
20+
}
21+
22+
/** Combines API endpoint and path into a single URL */
23+
protected getUrl(api: ApiEndpoint, path: string): string {
24+
return Location.joinWithSlash(this.config.apiEndpoints[api], path);
25+
}
26+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { InjectionToken } from '@angular/core';
2+
import { Config } from '../../../environments/config.interface';
3+
4+
export const CONFIG_TOKEN = new InjectionToken<Config>('CONFIG_TOKEN');

src/app/products/products.service.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
import { Injectable } from '@angular/core';
2-
import { HttpClient } from '@angular/common/http';
32
import { Observable, of } from 'rxjs';
43
import { Product } from './product.interface';
54
import { map } from 'rxjs/operators';
5+
import { ApiService } from '../core/api.service';
66

77
@Injectable({
88
providedIn: 'root',
99
})
10-
export class ProductsService {
11-
constructor(private readonly http: HttpClient) {}
12-
10+
export class ProductsService extends ApiService {
1311
getProducts(): Observable<Product[]> {
14-
return this.http.get<Product[]>('/assets/products.json');
12+
if (!this.endpointEnabled('bff')) {
13+
return this.http.get<Product[]>('/assets/products.json');
14+
}
15+
16+
const url = this.getUrl('bff', 'products');
17+
return this.http.get<Product[]>(url);
1518
}
1619

1720
getProductsForCheckout(ids: string[]): Observable<Product[]> {

src/environments/config.interface.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export type ApiEndpoint = 'product' | 'order' | 'import' | 'bff' | 'cart';
2+
3+
export interface Config {
4+
production: boolean;
5+
apiEndpoints: Record<ApiEndpoint, string>;
6+
apiEndpointsEnabled: Record<ApiEndpoint, boolean>;
7+
}

src/environments/environment.prod.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1-
export const environment = {
1+
import { Config } from './config.interface';
2+
3+
export const environment: Config = {
24
production: true,
5+
apiEndpoints: {
6+
product: 'https://.execute-api.eu-west-1.amazonaws.com/dev',
7+
order: 'https://.execute-api.eu-west-1.amazonaws.com/dev',
8+
import: 'https://.execute-api.eu-west-1.amazonaws.com/dev',
9+
bff: 'https://.execute-api.eu-west-1.amazonaws.com/dev',
10+
cart: 'https://.execute-api.eu-west-1.amazonaws.com/dev',
11+
},
12+
apiEndpointsEnabled: {
13+
product: false,
14+
order: false,
15+
import: false,
16+
bff: false,
17+
cart: false,
18+
},
319
};

src/environments/environment.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,24 @@
22
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
33
// The list of file replacements can be found in `angular.json`.
44

5-
export const environment = {
5+
import { Config } from './config.interface';
6+
7+
export const environment: Config = {
68
production: false,
9+
apiEndpoints: {
10+
product: 'https://.execute-api.eu-west-1.amazonaws.com/dev',
11+
order: 'https://.execute-api.eu-west-1.amazonaws.com/dev',
12+
import: 'https://.execute-api.eu-west-1.amazonaws.com/dev',
13+
bff: 'https://.execute-api.eu-west-1.amazonaws.com/dev',
14+
cart: 'https://.execute-api.eu-west-1.amazonaws.com/dev',
15+
},
16+
apiEndpointsEnabled: {
17+
product: false,
18+
order: false,
19+
import: false,
20+
bff: false,
21+
cart: false,
22+
},
723
};
824

925
/*

0 commit comments

Comments
 (0)