{"id":27992854,"url":"https://github.com/vdolek/angular-runtime-config","last_synced_at":"2025-05-08T18:43:19.950Z","repository":{"id":46981384,"uuid":"407883122","full_name":"vdolek/angular-runtime-config","owner":"vdolek","description":"Angular support for one deployment package for different environments with specific configurations","archived":false,"fork":false,"pushed_at":"2023-12-07T11:57:22.000Z","size":565,"stargazers_count":3,"open_issues_count":1,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-19T10:24:12.173Z","etag":null,"topics":["angular","config","configuration","configuration-management","deploy","deployment","environment","package","runtime","runtime-config","runtime-configuration"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vdolek.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-09-18T14:30:49.000Z","updated_at":"2024-11-10T12:55:41.000Z","dependencies_parsed_at":"2022-09-09T17:12:03.149Z","dependency_job_id":null,"html_url":"https://github.com/vdolek/angular-runtime-config","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vdolek%2Fangular-runtime-config","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vdolek%2Fangular-runtime-config/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vdolek%2Fangular-runtime-config/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vdolek%2Fangular-runtime-config/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vdolek","download_url":"https://codeload.github.com/vdolek/angular-runtime-config/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253131886,"owners_count":21859089,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","config","configuration","configuration-management","deploy","deployment","environment","package","runtime","runtime-config","runtime-configuration"],"created_at":"2025-05-08T18:43:19.482Z","updated_at":"2025-05-08T18:43:19.939Z","avatar_url":"https://github.com/vdolek.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Angular Runtime Configuration\n\n[![github version](https://img.shields.io/github/package-json/v/vdolek/angular-runtime-config/master?label=github)](https://github.com/vdolek/angular-runtime-config)\n[![npm version](https://img.shields.io/npm/v/angular-runtime-config)](https://www.npmjs.com/package/angular-runtime-config)\n[![CI](https://github.com/vdolek/angular-runtime-config/actions/workflows/ci.yml/badge.svg)](https://github.com/vdolek/angular-runtime-config/actions/workflows/ci.yml)\n\nTL;DR, Angular support for one deployment package for different environments with specific configurations.\n\nAngular framework lacks support for runtime configuration management. Build-in environments structure is compiled\nwith the deployment package, so you have to build the application for every environment. It doesn't allow you\nto build one package which could be deployed to different environments.\n\nThis library brings support for loading configuration in runtime. It also allows you to\nload multiple configuration files and merge them into one configuration object.\n\n## Playground\n\n[StackBlitz playground](https://stackblitz.com/edit/angular-runtime-config-playground)\n\n[Playground project](https://github.com/vdolek/angular-runtime-config/tree/master/playground)\n\n## How does it work?\n\nAt the initialisation phase of Angular app request for JSON configuration file is made. The content of the file\nis saved into configuration object that is resolvable by dependency injection.\n\nBy default, it looks for `config.json` file at the app root. But it can be changed to look for any other file,\nor even for multiple files that will be merged into one configuration object. This way you can have some configuration\nparameters shared between all environments and override only the specific parameters.\n\nIt can be as simple as:\n\n```typescript\n@Injectable({...})\nexport class SomeService {\n  constructor(\n    private readonly config: Configuration, // \u003c-- look here\n    private readonly http: HttpClient\n  ) {}\n  \n  async getData(): Promise\u003cany\u003e {\n    const baseUrl = this.config.apiUrl; // \u003c-- look here\n    var data = await this.http.get(apiUrl + '/data').toPromise();\n    return data;\n  }\n}\n```\n\n## Basic usage\n\n1. Install `angular-runtime-config` library.\n   ```shell\n   $ npm install angular-runtime-config\n   ```\n\n1. Create configuration class definition with your configuration parameters.\n   \n    ```typescript\n    export class Configuration {\n      readonly apiUrl!: string; // only example\n      readonly apiKey?: string; // only example\n      // add some other configuration parameters\n    }\n    ```\n\n1. Import `AngularRuntimeConfigModule` in your `AppModule`. You have to specify configuration class from previous step \n   as a parameter for `forRoot()` method. \n\n    ```typescript\n    import { AngularRuntimeConfigModule } from 'angular-runtime-config';\n    \n    @NgModule({\n      declarations: [\n        AppComponent\n      ],\n      imports: [\n        ...,\n    \n        // specify AngularRuntimeConfigModule as an import\n        AngularRuntimeConfigModule.forRoot(Configuration)\n      ],\n      providers: [],\n      bootstrap: [ AppComponent ]\n    })\n    export class AppModule { }\n    ```\n\n1. Create `config.json` file at the root of your app.\n\n   ```javascript\n   {\n     \"apiUrl\": \"some url\",\n     \"apiKey\": \"some key\"\n   }\n   ```\n   \n1. Add `config.json` file to assets in `angular.json`\n\n   ```javascript\n   ...\n   \"assets\": [\n     \"src/favicon.ico\",\n     \"src/assets\",\n     \"src/config.json\" // \u003c-- this line\n   ],\n   ...\n   ```\n\n1. Request your configuration class in any injection context.\n\n   ```typescript\n   @Injectable({...})\n   export class SomeService {\n     constructor(private readonly config: Configuration) {}\n   }\n   ```\n   \nWith this basic usage it is the responsibility of deployment to change `config.json` appropriately.\n\nIf you want to make your deployment simple you can make the decision what configuration file to\nload in runtime based on some information (for example current app URL or a query string).\nFor that look at the code examples next.\n\n## Specifying which configuration file/files to load\n\n### Load specific configuration file\n\nConfiguration file URL can be absolute or relative to app root url.\n\n```typescript\nAngularRuntimeConfigModule.forRoot(Configuration, {\n  urlFactory: () =\u003e 'config/config.json'\n})\n```\n\n### Load multiple configuration files\n\nWhen using multiple configuration files, files are merged in returned array order.\n\n```typescript\nAngularRuntimeConfigModule.forRoot(Configuration, {\n  urlFactory: () =\u003e [ 'config/config.common.json', 'config/config.DEV.json' ]\n})\n```\n\nDon't forget to add all configuration files to assets in `angular.json`. You can also add whole folder.\n\n```javascript\n...\n\"assets\": [\n  \"src/favicon.ico\",\n  \"src/assets\",\n  \"src/config\" // \u003c-- adds whole folder\n],\n...\n```\n\n### Load multiple configuration files based on environment\n\n```typescript\nAngularRuntimeConfigModule.forRoot(Configuration, {\n  urlFactory: () =\u003e {\n    const env = getEnvironment(); // your defined method that provides current environment name\n    return ['/config/config.common.json', `/config/config.${env}.json`]\n  }\n})\n```\n\nExample of `getEnvironment()` function: (it can be implemented in any way)\n\n```typescript\nfunction getEnvironment(): string {\n  switch (location.origin) {\n    case 'http://localhost': return 'LOCAL';\n    case 'https://dev.example.com': return 'DEV';\n    case 'https://int.example.com': return 'INT';\n    case 'https://www.example.com': return 'PROD';\n    default: throw Error('Unexpected base URL');\n  }\n}\n```\n\n### Load multiple configuration files based on environment using injector\n\nIf you need to resolve some dependencies in order to determine url of configuration files, you can use Angular Injector.\n\n```typescript\nAngularRuntimeConfigModule.forRoot(Configuration, {\n  urlFactory: (injector: Injector) =\u003e {\n    const env = getEnvironment(injector); // your defined method that provides current environment name\n    return ['/config/config.common.json', `/config/config.${env}.json`]\n  }\n})\n```\n\n### Async load multiple configuration files based on environment using injector\n\nIt is even possible to implement make `urlFactory` asynchronous.\n\n```typescript\nAngularRuntimeConfigModule.forRoot(Configuration, {\n  urlFactory: async (injector: Injector) =\u003e {\n    const env = await getEnvironment(injector); // your defined method that provides current environment name\n    return ['/config/config.common.json', `/config/config.${env}.json`]\n  }\n})\n```\n\n## Problems and solutions\n\n1. Injection of `Configuration` class does not work in `APP_INITIALIZERS` (error: `Configuration hasn't been initialized`).\n   - This is because configuration is also loaded within `APP_INITIALIZERS` so other `APP_INITIALIZERS` cannot\n     depend on `Configuration` class. The solution is to replace `APP_INITIALIZERS` with `CONFIGURATION_APP_INITIALIZERS`\n     for initializers that depend (even transitively) on `Configuration` class.\n     \n     ```typescript\n     {\n       provide: CONFIGURATION_APP_INITIALIZER,\n       useFactory: (config: Configuration) =\u003e () =\u003e ...,\n       deps: [Configuration],\n       multi: true\n     }\n     ```\n\n## License\n\nMIT © [Martin Volek](mailto:martin@vdolek.cz)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvdolek%2Fangular-runtime-config","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvdolek%2Fangular-runtime-config","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvdolek%2Fangular-runtime-config/lists"}