Skip to content

Local Config Option #60

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,8 @@ testem.log
.DS_Store
Thumbs.db

.nx/cache
.nx/cache

# Local Config
.env
local.config.json
35 changes: 21 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,43 +16,50 @@ imports: [..., RuntimeConfigLoaderModule, ...],

That's it; it's that simple. In the `RuntimeConfigLoaderModule`, the `APP_INITIALIZER` token is used to run a function which loads the configuration from a file or an API endpoint that can be used throughout the application.

If you implement the library exactly as it is above, the configuration file needs to be in the `./assets/config.json` location as mentioned above. If you'd like to load the file from a different location, provide that location in the `.forRoot()` method when importing the `RuntimeConfigLoaderModule`:
If you implement the library exactly as it is above, the configuration file needs to be in the `./assets/config.json` location as mentioned above. If you'd like to load the file from a different location, provide that using an injection token in the app's main providers array:

```ts
imports: [
providers: [
...,
RuntimeConfigLoaderModule.forRoot(
{ configUrl: './path/to/config/config.json' }
{
provide: RUNTIME_CONFIG_LOADER_CONFIG,
useValue: { configUrl: './path/to/config/config.json' }
),
...]
```

If you want to load multiple files, the value of `configUrl` should be an array of strings:

```ts
imports: [
providers: [
...,
RuntimeConfigLoaderModule.forRoot(
{ configUrl: ['./path/to/config/config-1.json', './path/to/config/config-2.json'] }
{
provide: RUNTIME_CONFIG_LOADER_CONFIG,
useValue: { configUrl: ['./path/to/config/config-1.json', './path/to/config/config-2.json'] }
),
...]
```

> Make sure that the path(s) you provide here is accessible by the Angular application, meaning that the file is somewhere the app can load it. In my opinion, the `assets` folder is the easiest place to work from.

## Multiple Config Paths
## Local Config File

One reason you may want to load multiple configuration objects is so that you can set the configuration on your machine without affecting anyone else. For example, you could have a `local.config.json` file that is not included in source control. Some of the values in that file would overwrite the values in a config file that everyone can use. Another use case is that some config values don't change between environments, and some do. The ones that don't change could go in one file, the ones that do change could go in a second file. Each developer/environment can provide the second file with values they want or need.
One reason you may want to load multiple configuration objects is so that you can set the configuration on your machine without affecting anyone else. For example, you could have a `local.config.json` file that is not included in source control. Some of the values in that file would overwrite the values in a config file that everyone can use. There is an improved way of providing the local config file for your app. There are two new attributes on the config object, `localConfigUrl` and `useLocalConfig`. The first, `localConfigUrl`, is the path to the local config file. Again, generally, this file generally won't be checked in to source control. The second is called `userLocalConfig`. The recommendation is to set the value of this to `isDevMode()` from `@angular/core`, but you could set the value of this to true or false based on any other condition you would like.

It's important to know that if an attribute is repeated in two configuration files, the latest value is kept. So, let's say you have `apiUrl` in both files, `config-1.json` and `config-2.json`. Let's assume the files are passed in to the `forRoot` method like this:
The values in the local config file will overwrite all previous values on other config objects that have been loaded. This way you can have a general app config file that everyone uses, but you can overwrite it on your machine without worrying about checking it in and messing up other people's applications.

> Note: If you provide a file URL and tell the service to load that config, it will load it. If the file doesn't exist, it will produce a 404. That's why it's recommended that the `useLocalConfig` value is set to `isDevMode()`, so that you don't have a 404 show up in production when it shouldn't.

```ts
imports: [
...,
RuntimeConfigLoaderModule.forRoot(
{ configUrl: ['./path/to/config/config-1.json', './path/to/config/config-2.json'] }
{
provide: RUNTIME_CONFIG_LOADER_CONFIG,
useValue: {
configUrl: './path/to/config/config.json',
localConfigUrl: './path/to/config/local.config.json',
useLocalConfig: isDevMode()
}
),
...]
```

In this case, the `apiUrl` value from `config-2.json` will override the value from `config-1.json`.
23 changes: 15 additions & 8 deletions apps/runtime-config-loader-demo/src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import { NgModule } from '@angular/core';
import { NgModule, isDevMode } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RuntimeConfigLoaderModule } from 'runtime-config-loader';
import {
RUNTIME_CONFIG_LOADER_CONFIG,
RuntimeConfigLoaderModule,
} from 'runtime-config-loader';

import { AppComponent } from './app.component';

@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
RuntimeConfigLoaderModule.forRoot({
configUrl: './assets/config/config.json',
}),
imports: [BrowserModule, RuntimeConfigLoaderModule],
providers: [
{
provide: RUNTIME_CONFIG_LOADER_CONFIG,
useValue: {
configUrl: './assets/config/config.json',
localConfigUrl: './assets/config/local.config.json',
useLocalConfig: isDevMode(),
},
},
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
{
"testValue": "This is a test"
"unique": "This is a unique value",
"testValue": "This is a test",
"deepMergeExample": {
"attr1": "value 1",
"attr2": "value 2"
}
}
35 changes: 21 additions & 14 deletions libs/runtime-config-loader/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,43 +16,50 @@ imports: [..., RuntimeConfigLoaderModule, ...],

That's it; it's that simple. In the `RuntimeConfigLoaderModule`, the `APP_INITIALIZER` token is used to run a function which loads the configuration from a file or an API endpoint that can be used throughout the application.

If you implement the library exactly as it is above, the configuration file needs to be in the `./assets/config.json` location as mentioned above. If you'd like to load the file from a different location, provide that location in the `.forRoot()` method when importing the `RuntimeConfigLoaderModule`:
If you implement the library exactly as it is above, the configuration file needs to be in the `./assets/config.json` location as mentioned above. If you'd like to load the file from a different location, provide that using an injection token in the app's main providers array:

```ts
imports: [
providers: [
...,
RuntimeConfigLoaderModule.forRoot(
{ configUrl: './path/to/config/config.json' }
{
provide: RUNTIME_CONFIG_LOADER_CONFIG,
useValue: { configUrl: './path/to/config/config.json' }
),
...]
```

If you want to load multiple files, the value of `configUrl` should be an array of strings:

```ts
imports: [
providers: [
...,
RuntimeConfigLoaderModule.forRoot(
{ configUrl: ['./path/to/config/config-1.json', './path/to/config/config-2.json'] }
{
provide: RUNTIME_CONFIG_LOADER_CONFIG,
useValue: { configUrl: ['./path/to/config/config-1.json', './path/to/config/config-2.json'] }
),
...]
```

> Make sure that the path(s) you provide here is accessible by the Angular application, meaning that the file is somewhere the app can load it. In my opinion, the `assets` folder is the easiest place to work from.

## Multiple Config Paths
## Local Config File

One reason you may want to load multiple configuration objects is so that you can set the configuration on your machine without affecting anyone else. For example, you could have a `local.config.json` file that is not included in source control. Some of the values in that file would overwrite the values in a config file that everyone can use. Another use case is that some config values don't change between environments, and some do. The ones that don't change could go in one file, the ones that do change could go in a second file. Each developer/environment can provide the second file with values they want or need.
One reason you may want to load multiple configuration objects is so that you can set the configuration on your machine without affecting anyone else. For example, you could have a `local.config.json` file that is not included in source control. Some of the values in that file would overwrite the values in a config file that everyone can use. There is an improved way of providing the local config file for your app. There are two new attributes on the config object, `localConfigUrl` and `useLocalConfig`. The first, `localConfigUrl`, is the path to the local config file. Again, generally, this file generally won't be checked in to source control. The second is called `userLocalConfig`. The recommendation is to set the value of this to `isDevMode()` from `@angular/core`, but you could set the value of this to true or false based on any other condition you would like.

It's important to know that if an attribute is repeated in two configuration files, the latest value is kept. So, let's say you have `apiUrl` in both files, `config-1.json` and `config-2.json`. Let's assume the files are passed in to the `forRoot` method like this:
The values in the local config file will overwrite all previous values on other config objects that have been loaded. This way you can have a general app config file that everyone uses, but you can overwrite it on your machine without worrying about checking it in and messing up other people's applications.

> Note: If you provide a file URL and tell the service to load that config, it will load it. If the file doesn't exist, it will produce a 404. That's why it's recommended that the `useLocalConfig` value is set to `isDevMode()`, so that you don't have a 404 show up in production when it shouldn't.

```ts
imports: [
...,
RuntimeConfigLoaderModule.forRoot(
{ configUrl: ['./path/to/config/config-1.json', './path/to/config/config-2.json'] }
{
provide: RUNTIME_CONFIG_LOADER_CONFIG,
useValue: {
configUrl: './path/to/config/config.json',
localConfigUrl: './path/to/config/local.config.json',
useLocalConfig: isDevMode()
}
),
...]
```

In this case, the `apiUrl` value from `config-2.json` will override the value from `config-1.json`.
8 changes: 4 additions & 4 deletions libs/runtime-config-loader/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "runtime-config-loader",
"version": "5.0.2",
"version": "6.0.0",
"author": {
"email": "preston.j.lamb@gmail.com",
"name": "Preston Lamb",
Expand All @@ -23,9 +23,9 @@
"config"
],
"peerDependencies": {
"@angular/common": ">=13.0.0",
"@angular/core": ">=13.0.0",
"@angular/platform-browser-dynamic": ">=13.0.0",
"@angular/common": ">=16.0.0",
"@angular/core": ">=16.0.0",
"@angular/platform-browser-dynamic": ">=16.0.0",
"rxjs": ">=6.6.0"
},
"dependencies": {
Expand Down
20 changes: 2 additions & 18 deletions libs/runtime-config-loader/src/lib/runtime-config-loader.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { HttpClientModule } from '@angular/common/http';
import { APP_INITIALIZER, ModuleWithProviders, NgModule } from '@angular/core';
import { RuntimeConfig } from './runtime-config';
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { RuntimeConfigLoaderService } from './runtime-config-loader/runtime-config-loader.service';

export function initConfig(configSvc: RuntimeConfigLoaderService) {
Expand All @@ -19,19 +18,4 @@ export function initConfig(configSvc: RuntimeConfigLoaderService) {
},
],
})
export class RuntimeConfigLoaderModule {
static forRoot(
config: RuntimeConfig
): ModuleWithProviders<RuntimeConfigLoaderModule> {
return {
ngModule: RuntimeConfigLoaderModule,
providers: [
{
provide: RuntimeConfig,
useValue: config,
},
RuntimeConfigLoaderService,
],
};
}
}
export class RuntimeConfigLoaderModule {}
Loading