Skip to content

Commit

Permalink
feat: app to support realtime environment config (#78)
Browse files Browse the repository at this point in the history
# What ❔

Adjust app so it supports realtime environment config

## Why ❔

We need this feature to set different app configs from the CLI

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [X] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [X] Tests for the changes have been added / updated.
  • Loading branch information
vasyl-ivanchuk committed Nov 3, 2023
1 parent 09ccc29 commit 6d2a403
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 17 deletions.
14 changes: 10 additions & 4 deletions packages/app/src/composables/useEnvironmentConfig.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
import { computed, ref } from "vue";

import type { EnvironmentConfig, NetworkConfig } from "@/configs";
import type { EnvironmentConfig, NetworkConfig, RuntimeConfig } from "@/configs";

const config = ref<EnvironmentConfig | null>(null);

const HYPERCHAIN_CONFIG_NAME = "hyperchain";
const DEVELOPMENT_CONFIG_NAME = "dev";

export async function loadEnvironmentConfig(appEnvironment: string): Promise<void> {
export async function loadEnvironmentConfig(runtimeConfig: RuntimeConfig): Promise<void> {
// runtime environment config takes precedence over hard coded config
if (runtimeConfig.environmentConfig) {
config.value = runtimeConfig.environmentConfig;
return;
}

let envConfig: EnvironmentConfig;
if (appEnvironment === "default") {
if (runtimeConfig.appEnvironment === "default") {
try {
envConfig = (await import(`../configs/${HYPERCHAIN_CONFIG_NAME}.config.json`)).default;
} catch {
envConfig = (await import(`../configs/${DEVELOPMENT_CONFIG_NAME}.config.json`)).default;
}
} else {
envConfig = (await import(`../configs/${appEnvironment}.config.json`)).default;
envConfig = (await import(`../configs/${runtimeConfig.appEnvironment}.config.json`)).default;
}
config.value = envConfig;
}
Expand Down
9 changes: 3 additions & 6 deletions packages/app/src/composables/useRuntimeConfig.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { NetworkConfig } from "@/configs";
import type { NetworkConfig, RuntimeConfig } from "@/configs";

export const DEFAULT_NETWORK: NetworkConfig = {
apiUrl: "https://block-explorer-api.testnets.zksync.dev",
Expand All @@ -17,11 +17,7 @@ export const DEFAULT_NETWORK: NetworkConfig = {
rpcUrl: "https://testnet.era.zksync.dev",
};

export default (): {
version: string;
sentryDSN: string;
appEnvironment: string;
} => {
export default (): RuntimeConfig => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const runtimeConfig = window && window["##runtimeConfig"];
Expand All @@ -30,5 +26,6 @@ export default (): {
version: import.meta.env?.VITE_VERSION || "localhost",
sentryDSN: runtimeConfig?.sentryDSN || import.meta.env?.VITE_SENTRY_DSN,
appEnvironment: runtimeConfig?.appEnvironment || import.meta.env?.VITE_APP_ENVIRONMENT || "default",
environmentConfig: runtimeConfig?.environmentConfig,
};
};
7 changes: 7 additions & 0 deletions packages/app/src/configs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,10 @@ export type NetworkConfig = {
export type EnvironmentConfig = {
networks: NetworkConfig[];
};

export type RuntimeConfig = {
version: string;
sentryDSN: string;
appEnvironment: string;
environmentConfig?: EnvironmentConfig;
};
8 changes: 4 additions & 4 deletions packages/app/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const i18n = createI18n<[MessageSchema], "en">({
app.use(router);
app.use(i18n);
app.use(testId);
const config = useRuntimeConfig();
const runtimeConfig = useRuntimeConfig();

const context = useContext();

Expand All @@ -50,11 +50,11 @@ const { initialize: initializeWallet } = useWallet({
});
initializeWallet();

if (config.sentryDSN?.length) {
useSentry(app, config.sentryDSN, config.appEnvironment, config.version, router);
if (runtimeConfig.sentryDSN?.length) {
useSentry(app, runtimeConfig.sentryDSN, runtimeConfig.appEnvironment, runtimeConfig.version, router);
}

(process.env.NODE_ENV === "test" ? Promise.resolve() : loadEnvironmentConfig(config.appEnvironment))
(process.env.NODE_ENV === "test" ? Promise.resolve() : loadEnvironmentConfig(runtimeConfig))
.catch(() => null)
.then(context.identifyNetwork);

Expand Down
30 changes: 27 additions & 3 deletions packages/app/tests/composables/useEnvironmentConfig.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { GOERLI_BETA_NETWORK, GOERLI_NETWORK } from "../mocks";

import useEnvironmentConfig, { loadEnvironmentConfig } from "@/composables/useEnvironmentConfig";

import type { RuntimeConfig } from "@/configs";

vi.mock("../../src/configs/local.config", () => {
return {
default: {
Expand Down Expand Up @@ -39,20 +41,42 @@ describe("useEnvironmentConfig:", () => {
describe("loadEnvironmentConfig", () => {
it("sets networks data to config", async () => {
const { networks } = useEnvironmentConfig();
await loadEnvironmentConfig("local");
await loadEnvironmentConfig({ appEnvironment: "local" } as RuntimeConfig);
expect(networks.value).toEqual([GOERLI_BETA_NETWORK, GOERLI_NETWORK]);
});

it("sets networks to values from runtime config if specified", async () => {
const runtimeConfig = {
environmentConfig: {
networks: [
{
name: "runtime network",
published: true,
},
],
},
appEnvironment: "local",
} as RuntimeConfig;
const { networks } = useEnvironmentConfig();
await loadEnvironmentConfig(runtimeConfig);
expect(networks.value).toEqual([
{
name: "runtime network",
published: true,
},
]);
});
});

describe("networks", () => {
it("returns empty array when networks are not defined", async () => {
const { networks } = useEnvironmentConfig();
await loadEnvironmentConfig("production");
await loadEnvironmentConfig({ appEnvironment: "production" } as RuntimeConfig);
expect(networks.value).toEqual([]);
});
it("returns only published network configs", async () => {
const { networks } = useEnvironmentConfig();
await loadEnvironmentConfig("staging");
await loadEnvironmentConfig({ appEnvironment: "staging" } as RuntimeConfig);
expect(networks.value).toEqual([GOERLI_BETA_NETWORK]);
});
});
Expand Down

0 comments on commit 6d2a403

Please sign in to comment.