-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(app): Convert config to instance so that implementation of behav…
…ior is abstracted (#2508) * feat(app): Convert config to instance so that implementation of behavior is abstracted - create manifest for config validation - create class for transpiling of config - update cli to use the VO type of config NOTE: direct access of endpoints if now deprecated! BREAKING CHANGES: `endpoints` will be deprecate in future, applications should use `getEndpoint` * refactor(app): Refactor AppConfig class to improve endpoint handling
- Loading branch information
Showing
21 changed files
with
406 additions
and
152 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,9 @@ | |
{ | ||
"path": "../modules/bookmark" | ||
}, | ||
{ | ||
"path": "../modules/app" | ||
}, | ||
{ | ||
"path": "../app" | ||
}, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { | ||
jsonSelector, | ||
type ResponseSelector, | ||
} from '@equinor/fusion-framework-module-http/selectors'; | ||
|
||
import { AppConfig } from './AppConfig'; | ||
import { ApiAppConfigSchema } from './schemas'; | ||
|
||
/** | ||
* Asynchronously selects and parses the application configuration from the given response. | ||
* | ||
* @param response - The response object to select and parse the application configuration from. | ||
* @returns A promise that resolves to an instance of `AppConfig` containing the parsed configuration data. | ||
* | ||
* @throws Will throw an error if the response cannot be parsed or does not conform to the expected schema. | ||
*/ | ||
export const AppConfigSelector: ResponseSelector<AppConfig> = async (response) => { | ||
// Select the JSON data from the response | ||
const raw = await jsonSelector(response); | ||
|
||
// Parse the JSON data using the API application configuration schema | ||
const data = ApiAppConfigSchema.parse(raw); | ||
|
||
return new AppConfig(data); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// todo: move to utils | ||
const deepFreeze = <T extends Record<string, unknown>>(obj: T): T => { | ||
Object.keys(obj).forEach((property) => { | ||
if ( | ||
typeof obj[property] === 'object' && | ||
obj[property] !== null && | ||
!Object.isFrozen(obj[property]) | ||
) { | ||
deepFreeze(obj[property] as Record<string, unknown>); | ||
} | ||
}); | ||
return Object.freeze(obj); | ||
}; | ||
|
||
export type ConfigEnvironment = Record<string, unknown>; | ||
|
||
export type ConfigEndPoint = { | ||
url: string; | ||
scopes: string[]; | ||
}; | ||
|
||
/** | ||
* Class representing the application configuration. | ||
* | ||
* @template TEnvironment - The type of the environment configuration, extending `ConfigEnvironment`. | ||
* | ||
* @remarks | ||
* The `AppConfig` class provides a way to manage application configuration, including environment settings and endpoints. | ||
* | ||
* @example | ||
* ```typescript | ||
* const config = new AppConfig({ | ||
* environment: { ... }, | ||
* endpoints: { | ||
* api: { url: 'https://api.example.com' } | ||
* } | ||
* }); | ||
* | ||
* console.log(config.getEndpoint('api')); // { url: 'https://api.example.com' } | ||
* ``` | ||
* | ||
* @param {Object} config - The configuration object. | ||
* @param {TEnvironment} [config.environment] - The environment configuration. | ||
* @param {Record<string, ConfigEndPoint>} [config.endpoints] - The endpoints configuration. | ||
* | ||
* @property {TEnvironment} [environment] - The environment configuration. | ||
* @property {Record<string, string | undefined>} endpoints - The endpoints configuration (deprecated). | ||
* | ||
* @method getEndpoint | ||
* @param {string} key - The key of the endpoint to retrieve. | ||
*/ | ||
export class AppConfig<TEnvironment extends ConfigEnvironment = ConfigEnvironment> { | ||
#endpoints: Record<string, ConfigEndPoint>; | ||
|
||
/** | ||
* The environment configuration for the application. | ||
* This property is read-only and is of type `TEnvironment`. | ||
*/ | ||
public readonly environment: TEnvironment; | ||
|
||
/** | ||
* @deprecated Use `getEndpoint` instead. | ||
* | ||
* Retrieves the endpoints as a record of strings. This method returns a proxy | ||
* that maps the endpoint names to their respective URLs. | ||
* | ||
* @returns {Record<string, string | undefined>} A record where the keys are endpoint names and the values are their URLs. | ||
*/ | ||
public get endpoints(): Record<string, string | undefined> { | ||
console.warn('endpoints is deprecated, use getEndpoint instead'); | ||
return new Proxy(this.#endpoints, { | ||
get(target, prop): string | undefined { | ||
return target[prop as string]?.url; | ||
}, | ||
}) as unknown as Record<string, string>; | ||
} | ||
|
||
constructor(config: { | ||
environment?: TEnvironment | null; | ||
endpoints?: Record<string, ConfigEndPoint>; | ||
}) { | ||
this.environment = deepFreeze(config.environment ?? {}) as TEnvironment; | ||
this.#endpoints = config.endpoints ?? {}; | ||
} | ||
|
||
/** | ||
* Retrieves the configuration endpoint associated with the given key. | ||
* | ||
* @param key - The key corresponding to the desired configuration endpoint. | ||
* @returns The configuration endpoint if found, otherwise `undefined`. | ||
*/ | ||
getEndpoint(key: string): ConfigEndPoint | undefined { | ||
return this.#endpoints[key]; | ||
} | ||
} |
Oops, something went wrong.