From 8c240ec1d75420d5d66533cd2e3ea44a49c5a589 Mon Sep 17 00:00:00 2001 From: cv5ch <176032962+cv5ch@users.noreply.github.com> Date: Wed, 10 Sep 2025 09:45:18 +0200 Subject: [PATCH] Rework ConfigService to load backend url from config.json only for production and for development from environment.ts --- .devcontainer/devcontainer.json | 1 - .../core/_services/shared/config.service.ts | 89 +++++++++++++------ 2 files changed, 61 insertions(+), 29 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 74b1b0ac4..dc13e4791 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -34,7 +34,6 @@ "remoteEnv": { "NODE_OPTIONS": "--use-openssl-ca", - "HASHTOPOLIS_BACKEND_URL": "http://localhost:8080" }, "overrideCommand": false, "remoteUser": "node" diff --git a/src/app/core/_services/shared/config.service.ts b/src/app/core/_services/shared/config.service.ts index a0eef6328..7f31b2ea0 100644 --- a/src/app/core/_services/shared/config.service.ts +++ b/src/app/core/_services/shared/config.service.ts @@ -1,53 +1,86 @@ +import { Observable, of } from 'rxjs'; +import { environment } from 'src/environments/environment'; + import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import { environment } from 'src/environments/environment'; + +/** + * Interface for the expected shape of `assets/config.json`. + */ +interface AppConfig { + hashtopolis_backend_url?: string; +} @Injectable({ providedIn: 'root' }) export class ConfigService { private configUrl = 'assets/config.json'; - constructor(private http: HttpClient) { } - private getConfigOnce(): Observable { + constructor(private http: HttpClient) {} + + /** + * Retrieves the configuration file once from the assets folder. + * + * - In **production**, this fetches `assets/config.json` (created at container startup). + * - In **development**, this bypasses the HTTP request and just returns `null`, + * because dev uses `environment.ts` instead of `config.json`. + * + * @returns An observable of the parsed JSON config (prod) or `null` (dev). + */ + private getConfigOnce(): Observable { + if (!environment.production) { + return of(null); + } return this.http.get(this.configUrl); } - public refreshEndpoint(){ - let ApiEndPoint = ""; - this.getConfigOnce().subscribe(config => { - // Assuming the JSON contains a property named 'backendUrl' - if (config && config.hashtopolis_backend_url) { - // If we get a config from the backend, we set the config property - ApiEndPoint = config.hashtopolis_backend_url; - // Remove trailing slash, because this causing invalid URLs - if (ApiEndPoint.endsWith('/')) { - ApiEndPoint = ApiEndPoint.slice(0, -1); + /** + * Refreshes the API endpoint configuration. + * + * - In **production**, it tries to read `hashtopolis_backend_url` from `config.json`. + * If found, it is saved to `localStorage`. + * If missing or invalid, falls back to `environment.config.prodApiEndpoint`. + * + * - In **development**, it always uses `environment.config.prodApiEndpoint` + * and stores it in `localStorage`. + */ + public refreshEndpoint(): void { + let ApiEndPoint = ''; + this.getConfigOnce().subscribe({ + next: (config) => { + if (config && config.hashtopolis_backend_url) { + ApiEndPoint = config.hashtopolis_backend_url; + if (ApiEndPoint.endsWith('/')) { + ApiEndPoint = ApiEndPoint.slice(0, -1); + } + } else { + ApiEndPoint = environment.config.prodApiEndpoint; } localStorage.setItem('prodApiEndpoint', ApiEndPoint); - } else if (config && !config.hashtopolis_backend_url) { - console.error('Invalid configuration file. Please check your config.json. Using defaults.'); - ApiEndPoint = environment.config.prodApiEndpoint; - localStorage.setItem('prodApiEndpoint', ApiEndPoint); - } else { + }, + error: () => { ApiEndPoint = environment.config.prodApiEndpoint; localStorage.setItem('prodApiEndpoint', ApiEndPoint); } - }, - error => { - ApiEndPoint = environment.config.prodApiEndpoint; - localStorage.setItem('prodApiEndpoint', ApiEndPoint); - } - ); + }); } - public getEndpoint(){ + /** + * Retrieves the currently configured API endpoint. + * + * - If an endpoint is already stored in `localStorage`, returns it. + * - If not, it triggers `refreshEndpoint()` to initialize it and then returns + * either the stored value or falls back to `environment.config.prodApiEndpoint`. + * + * @returns The active API endpoint as a string. + */ + public getEndpoint(): string { let ApiEndPoint = localStorage.getItem('prodApiEndpoint'); if (!ApiEndPoint) { this.refreshEndpoint(); + ApiEndPoint = localStorage.getItem('prodApiEndpoint'); } - ApiEndPoint = localStorage.getItem('prodApiEndpoint'); - return ApiEndPoint; + return ApiEndPoint ?? environment.config.prodApiEndpoint; } }