From 269ae9b9dfc75a62cd32c65453b5c61e407928ee Mon Sep 17 00:00:00 2001 From: MAHDTech Date: Mon, 16 Mar 2026 12:48:49 +1100 Subject: [PATCH 1/2] feat: Add optional Docker extraHosts - uses tuple method - includes matching junobuild/config dep - run tsc check - run prettier --- package-lock.json | 14 +++++++------- package.json | 2 +- src/configs/emulator.config.ts | 6 +++++- src/services/emulator/_runner.services.ts | 3 ++- src/types/emulator.ts | 21 +++++++++++++++++++++ src/utils/emulator.utils.ts | 18 ++++++++++++++++++ 6 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 src/utils/emulator.utils.ts diff --git a/package-lock.json b/package-lock.json index 55dae4d5..3d1bb8cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@junobuild/admin": "^4.2.1", "@junobuild/cdn": "^2.3.1", "@junobuild/cli-tools": "^0.12.3", - "@junobuild/config": "^2.14.2", + "@junobuild/config": "^2.15.0", "@junobuild/config-loader": "^0.4.9", "@junobuild/core": "^5.2.2", "@junobuild/functions-tools": "^0.5.3", @@ -1779,9 +1779,9 @@ } }, "node_modules/@junobuild/config": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/@junobuild/config/-/config-2.14.2.tgz", - "integrity": "sha512-7rbb23eRQ4QkVtztIhMEwLZY9kawgLvk9ZTPr8EcGhNc3D2IxU16LYVgwOd2khArZoq1K9efu+nCNuDFmsTVCA==", + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/@junobuild/config/-/config-2.15.0.tgz", + "integrity": "sha512-4SiFDmayi6GxGFdr0BG/sOSk6iinW0ijv7mD3Xp8ufvVEhzfOsT8Ta6GS+HD2Eb0lRpnvXaAtw6xzdB5ub56cg==", "license": "MIT", "peerDependencies": { "@junobuild/schema": "^1.1", @@ -7906,9 +7906,9 @@ } }, "@junobuild/config": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/@junobuild/config/-/config-2.14.2.tgz", - "integrity": "sha512-7rbb23eRQ4QkVtztIhMEwLZY9kawgLvk9ZTPr8EcGhNc3D2IxU16LYVgwOd2khArZoq1K9efu+nCNuDFmsTVCA==", + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/@junobuild/config/-/config-2.15.0.tgz", + "integrity": "sha512-4SiFDmayi6GxGFdr0BG/sOSk6iinW0ijv7mD3Xp8ufvVEhzfOsT8Ta6GS+HD2Eb0lRpnvXaAtw6xzdB5ub56cg==", "requires": {} }, "@junobuild/config-loader": { diff --git a/package.json b/package.json index 2f008f58..4e7f386c 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "@junobuild/admin": "^4.2.1", "@junobuild/cdn": "^2.3.1", "@junobuild/cli-tools": "^0.12.3", - "@junobuild/config": "^2.14.2", + "@junobuild/config": "^2.15.0", "@junobuild/config-loader": "^0.4.9", "@junobuild/core": "^5.2.2", "@junobuild/functions-tools": "^0.5.3", diff --git a/src/configs/emulator.config.ts b/src/configs/emulator.config.ts index 7c7d77dc..6f7759e1 100644 --- a/src/configs/emulator.config.ts +++ b/src/configs/emulator.config.ts @@ -5,6 +5,7 @@ import {DEPLOY_LOCAL_REPLICA_PATH} from '../constants/dev.constants'; import {EMULATOR_SKYLAB} from '../constants/emulator.constants'; import {ENV} from '../env'; import type {CliEmulatorConfig} from '../types/emulator'; +import {mapExtraHosts} from '../utils/emulator.utils'; import {readPackageJson} from '../utils/pkg.utils'; import {junoConfigExist, readJunoConfig} from './juno.config'; @@ -40,6 +41,8 @@ export const readEmulatorConfig = async (): Promise< const targetDeploy = config.runner?.target ?? DEPLOY_LOCAL_REPLICA_PATH; + const extraHosts = mapExtraHosts(config.runner?.extraHosts); + return { success: true, config: { @@ -48,7 +51,8 @@ export const readEmulatorConfig = async (): Promise< containerName, emulatorType, runner, - targetDeploy + targetDeploy, + extraHosts } } }; diff --git a/src/services/emulator/_runner.services.ts b/src/services/emulator/_runner.services.ts index 002c046e..1ae67a56 100644 --- a/src/services/emulator/_runner.services.ts +++ b/src/services/emulator/_runner.services.ts @@ -151,7 +151,7 @@ const initConfigFile = async () => { const startEmulator = async ({config: extendedConfig}: {config: CliEmulatorConfig}) => { const { config, - derivedConfig: {emulatorType, containerName, runner, targetDeploy} + derivedConfig: {emulatorType, containerName, runner, targetDeploy, extraHosts} } = extendedConfig; const {running} = await assertContainerRunning({containerName, runner}); @@ -249,6 +249,7 @@ const startEmulator = async ({config: extendedConfig}: {config: CliEmulatorConfi '-v', `${targetDeploy}:/juno/target/deploy`, ...(nonNullish(platform) ? [`--platform=${platform}`] : []), + ...extraHosts.flatMap((host) => ['--add-host', host]), image ] }); diff --git a/src/types/emulator.ts b/src/types/emulator.ts index 18963ffc..7f2d7423 100644 --- a/src/types/emulator.ts +++ b/src/types/emulator.ts @@ -11,6 +11,27 @@ export interface CliEmulatorDerivedConfig { runner: EmulatorRunnerType; emulatorType: EmulatorType; targetDeploy: string; + /** + * Additional host-to-IP mappings injected into the container via `--add-host`. + * Each entry is a `"hostname:destination"` string, derived by joining the + * `[hostname, destination]` tuples from the emulator config. + * + * This is useful for making host-machine services (e.g. a local Ethereum RPC node) + * reachable from within the container under a stable DNS name such as + * `host.docker.internal`. + * + * @example + * ```ts + * // juno.config.ts + * runner: { + * extraHosts: [['host.docker.internal', 'host-gateway']] + * } + * // Produces: ['host.docker.internal:host-gateway'] + * ``` + * + * @see https://docs.docker.com/reference/cli/docker/container/run/#add-host + */ + extraHosts: string[]; } export interface CliEmulatorConfig { diff --git a/src/utils/emulator.utils.ts b/src/utils/emulator.utils.ts new file mode 100644 index 00000000..0a375468 --- /dev/null +++ b/src/utils/emulator.utils.ts @@ -0,0 +1,18 @@ +/** + * Joins a `[hostname, destination]` tuple into the `"hostname:destination"` string + * expected by Docker's `--add-host` flag. + * + * @example + * joinExtraHost(['host.docker.internal', 'host-gateway']) + * // => 'host.docker.internal:host-gateway' + */ +export const joinExtraHost = ([hostname, destination]: [string, string]): string => + `${hostname}:${destination}`; + +/** + * Maps an array of `[hostname, destination]` tuples (from the emulator config's + * `extraHosts` field) into `"hostname:destination"` strings for use with Docker's + * `--add-host` flag. + */ +export const mapExtraHosts = (extraHosts: Array<[string, string]> | undefined): string[] => + (extraHosts ?? []).map(joinExtraHost); From 5975ff1232ae9aa0e0a0c1fd7ef58a384d5ed4e2 Mon Sep 17 00:00:00 2001 From: MAHDTech Date: Tue, 17 Mar 2026 00:10:48 +1100 Subject: [PATCH 2/2] fix: remove comments - cleanup comments - remove the utils - import and use the proper type. --- src/configs/emulator.config.ts | 8 +++++--- src/types/emulator.ts | 20 -------------------- src/utils/emulator.utils.ts | 18 ------------------ 3 files changed, 5 insertions(+), 41 deletions(-) delete mode 100644 src/utils/emulator.utils.ts diff --git a/src/configs/emulator.config.ts b/src/configs/emulator.config.ts index 6f7759e1..13f3c6c3 100644 --- a/src/configs/emulator.config.ts +++ b/src/configs/emulator.config.ts @@ -1,11 +1,10 @@ -import {type EmulatorConfig, EmulatorConfigSchema} from '@junobuild/config'; +import {type EmulatorConfig, type EmulatorRunner, EmulatorConfigSchema} from '@junobuild/config'; import {red} from 'kleur'; import * as z from 'zod'; import {DEPLOY_LOCAL_REPLICA_PATH} from '../constants/dev.constants'; import {EMULATOR_SKYLAB} from '../constants/emulator.constants'; import {ENV} from '../env'; import type {CliEmulatorConfig} from '../types/emulator'; -import {mapExtraHosts} from '../utils/emulator.utils'; import {readPackageJson} from '../utils/pkg.utils'; import {junoConfigExist, readJunoConfig} from './juno.config'; @@ -41,7 +40,10 @@ export const readEmulatorConfig = async (): Promise< const targetDeploy = config.runner?.target ?? DEPLOY_LOCAL_REPLICA_PATH; - const extraHosts = mapExtraHosts(config.runner?.extraHosts); + const extraHosts = (config.runner?.extraHosts ?? []).map( + ([hostname, destination]: NonNullable[number]) => + `${hostname}:${destination}` + ); return { success: true, diff --git a/src/types/emulator.ts b/src/types/emulator.ts index 7f2d7423..00741d5e 100644 --- a/src/types/emulator.ts +++ b/src/types/emulator.ts @@ -11,26 +11,6 @@ export interface CliEmulatorDerivedConfig { runner: EmulatorRunnerType; emulatorType: EmulatorType; targetDeploy: string; - /** - * Additional host-to-IP mappings injected into the container via `--add-host`. - * Each entry is a `"hostname:destination"` string, derived by joining the - * `[hostname, destination]` tuples from the emulator config. - * - * This is useful for making host-machine services (e.g. a local Ethereum RPC node) - * reachable from within the container under a stable DNS name such as - * `host.docker.internal`. - * - * @example - * ```ts - * // juno.config.ts - * runner: { - * extraHosts: [['host.docker.internal', 'host-gateway']] - * } - * // Produces: ['host.docker.internal:host-gateway'] - * ``` - * - * @see https://docs.docker.com/reference/cli/docker/container/run/#add-host - */ extraHosts: string[]; } diff --git a/src/utils/emulator.utils.ts b/src/utils/emulator.utils.ts deleted file mode 100644 index 0a375468..00000000 --- a/src/utils/emulator.utils.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Joins a `[hostname, destination]` tuple into the `"hostname:destination"` string - * expected by Docker's `--add-host` flag. - * - * @example - * joinExtraHost(['host.docker.internal', 'host-gateway']) - * // => 'host.docker.internal:host-gateway' - */ -export const joinExtraHost = ([hostname, destination]: [string, string]): string => - `${hostname}:${destination}`; - -/** - * Maps an array of `[hostname, destination]` tuples (from the emulator config's - * `extraHosts` field) into `"hostname:destination"` strings for use with Docker's - * `--add-host` flag. - */ -export const mapExtraHosts = (extraHosts: Array<[string, string]> | undefined): string[] => - (extraHosts ?? []).map(joinExtraHost);