From 17be686c0b9203eaa15e14bf70b255d6cb7705b6 Mon Sep 17 00:00:00 2001 From: David Dal Busco Date: Mon, 20 Apr 2026 10:54:34 +0200 Subject: [PATCH 1/4] feat: juno emulator pull Signed-off-by: David Dal Busco --- src/commands/emulator.ts | 4 +++ src/constants/help.constants.ts | 1 + src/help/emulator.help.ts | 2 ++ src/services/emulator/_runner.services.ts | 43 ++++++++++++++++++++++- src/services/emulator/pull.services.ts | 5 +++ 5 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 src/services/emulator/pull.services.ts diff --git a/src/commands/emulator.ts b/src/commands/emulator.ts index 002dfa3..76c6864 100644 --- a/src/commands/emulator.ts +++ b/src/commands/emulator.ts @@ -6,6 +6,7 @@ import {clear} from '../services/emulator/clear.services'; import {start} from '../services/emulator/start.services'; import {stop} from '../services/emulator/stop.services'; import {wait} from '../services/emulator/wait.services'; +import {pull} from '../services/emulator/pull.services'; export const emulator = async (args?: string[]) => { const [subCommand] = args ?? []; @@ -23,6 +24,9 @@ export const emulator = async (args?: string[]) => { case 'clear': await clear(); break; + case 'pull': + await pull(); + break; default: console.log(red('Unknown subcommand.')); logHelpEmulator(args); diff --git a/src/constants/help.constants.ts b/src/constants/help.constants.ts index 32fc76f..d5e913b 100644 --- a/src/constants/help.constants.ts +++ b/src/constants/help.constants.ts @@ -34,6 +34,7 @@ export const HOSTING_PRUNE_DESCRIPTION = export const EMULATOR_START_DESCRIPTION = 'Start the emulator for local development.'; export const EMULATOR_WAIT_DESCRIPTION = 'Wait until the emulator is ready.'; export const EMULATOR_CLEAR_DESCRIPTION = 'Clear the local emulator state (volume and container).'; +export const EMULATOR_PULL_DESCRIPTION = 'Pull the latest emulator image.'; export const FUNCTIONS_PUBLISH_DESCRIPTION = 'Publish a new version of your serverless functions.'; export const FUNCTIONS_UPGRADE_DESCRIPTION = 'Upgrade your serverless functions.'; diff --git a/src/help/emulator.help.ts b/src/help/emulator.help.ts index a578690..91b940d 100644 --- a/src/help/emulator.help.ts +++ b/src/help/emulator.help.ts @@ -2,6 +2,7 @@ import {cyan, green, magenta, yellow} from 'kleur'; import { EMULATOR_CLEAR_DESCRIPTION, EMULATOR_DESCRIPTION, + EMULATOR_PULL_DESCRIPTION, EMULATOR_START_DESCRIPTION, EMULATOR_WAIT_DESCRIPTION } from '../constants/help.constants'; @@ -12,6 +13,7 @@ const usage = `Usage: ${green('juno')} ${cyan('emulator')} ${magenta(' { await runWithConfig({fn}); }; +export const pullImage = async () => { + const fn: RunWithConfigFn = async (args) => { + await pullEmulator(args); + }; + + await runWithConfig({fn}); +}; + type RunWithConfigFn = (params: {config: CliEmulatorConfig}) => Promise; const runWithConfig = async ({fn}: {fn: RunWithConfigFn}) => { @@ -299,6 +308,38 @@ const clearEmulator = async ({config: {config, derivedConfig}}: {config: CliEmul }); }; +const pullEmulator = async ({config: {config, derivedConfig}}: {config: CliEmulatorConfig}) => { + const {runner, image} = derivedConfig; + + await confirmAndExit( + `Are you sure you want to pull the emulator image "${image}"? You will need to ${yellow('clear')} the emulator afterward to apply the update.` + ); + + const spinner = ora('Pulling...').start(); + + try { + let output = ''; + await spawn({ + command: runner, + args: ['pull', image], + stdout: (o) => (output += o), + silentOut: true + }); + + spinner.stop(); + + console.log('\nDone ✅\n'); + console.log(output); + + console.log( + `Run ${yellow('juno emulator clear')} to reset the state, then ${green('juno emulator start')} to use the updated image.` + ); + } catch (error: unknown) { + spinner.stop(); + throw error; + } +}; + const assertContainerRunning = async ({ containerName, runner diff --git a/src/services/emulator/pull.services.ts b/src/services/emulator/pull.services.ts new file mode 100644 index 0000000..f0b388c --- /dev/null +++ b/src/services/emulator/pull.services.ts @@ -0,0 +1,5 @@ +import {pullImage} from './_runner.services'; + +export const pull = async () => { + await pullImage(); +}; From db0c6e3d2842ffda2bf8e20574d629fa8615b0b4 Mon Sep 17 00:00:00 2001 From: David Dal Busco Date: Mon, 20 Apr 2026 10:59:36 +0200 Subject: [PATCH 2/4] feat: print out Signed-off-by: David Dal Busco --- src/services/emulator/_runner.services.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/services/emulator/_runner.services.ts b/src/services/emulator/_runner.services.ts index c77fe04..9073620 100644 --- a/src/services/emulator/_runner.services.ts +++ b/src/services/emulator/_runner.services.ts @@ -318,18 +318,19 @@ const pullEmulator = async ({config: {config, derivedConfig}}: {config: CliEmula const spinner = ora('Pulling...').start(); try { - let output = ''; await spawn({ command: runner, args: ['pull', image], - stdout: (o) => (output += o), + stdout: (o) => { + // We print out to display some sort of progression + console.log(o); + }, silentOut: true }); spinner.stop(); console.log('\nDone ✅\n'); - console.log(output); console.log( `Run ${yellow('juno emulator clear')} to reset the state, then ${green('juno emulator start')} to use the updated image.` From 86216c282e825cb989109f7f60d1d0c8cb667d3d Mon Sep 17 00:00:00 2001 From: David Dal Busco Date: Mon, 20 Apr 2026 11:04:11 +0200 Subject: [PATCH 3/4] chore: fmt Signed-off-by: David Dal Busco --- src/commands/emulator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/emulator.ts b/src/commands/emulator.ts index 76c6864..8a89260 100644 --- a/src/commands/emulator.ts +++ b/src/commands/emulator.ts @@ -3,10 +3,10 @@ import {logHelpEmulator} from '../help/emulator.help'; import {logHelpEmulatorStart} from '../help/emulator.start.help'; import {logHelpEmulatorWait} from '../help/emulator.wait.help'; import {clear} from '../services/emulator/clear.services'; +import {pull} from '../services/emulator/pull.services'; import {start} from '../services/emulator/start.services'; import {stop} from '../services/emulator/stop.services'; import {wait} from '../services/emulator/wait.services'; -import {pull} from '../services/emulator/pull.services'; export const emulator = async (args?: string[]) => { const [subCommand] = args ?? []; From a9bf397b8a8ad876306828273750de5384dad29f Mon Sep 17 00:00:00 2001 From: David Dal Busco Date: Mon, 20 Apr 2026 11:04:35 +0200 Subject: [PATCH 4/4] chore: lint Signed-off-by: David Dal Busco --- src/services/emulator/_runner.services.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/emulator/_runner.services.ts b/src/services/emulator/_runner.services.ts index 9073620..59c9e6d 100644 --- a/src/services/emulator/_runner.services.ts +++ b/src/services/emulator/_runner.services.ts @@ -308,7 +308,7 @@ const clearEmulator = async ({config: {config, derivedConfig}}: {config: CliEmul }); }; -const pullEmulator = async ({config: {config, derivedConfig}}: {config: CliEmulatorConfig}) => { +const pullEmulator = async ({config: {derivedConfig}}: {config: CliEmulatorConfig}) => { const {runner, image} = derivedConfig; await confirmAndExit(