From ee414e64e3ceffdd5cca4c46e9a9283706dd9e0c Mon Sep 17 00:00:00 2001 From: David Dal Busco Date: Mon, 7 Apr 2025 08:16:18 +0200 Subject: [PATCH] feat: custom satellite id in development --- plugins/plugin-tools/src/config.spec.ts | 82 +++++++++++----- plugins/plugin-tools/src/config.ts | 20 +++- plugins/plugin-tools/src/init.spec.ts | 118 ++++++++++++++++-------- 3 files changed, 158 insertions(+), 62 deletions(-) diff --git a/plugins/plugin-tools/src/config.spec.ts b/plugins/plugin-tools/src/config.spec.ts index d4fb3b9..9b657a1 100644 --- a/plugins/plugin-tools/src/config.spec.ts +++ b/plugins/plugin-tools/src/config.spec.ts @@ -9,6 +9,7 @@ import { satelliteId, useDockerContainer } from './config'; +import {DOCKER_SATELLITE_ID, ICP_INDEX_ID, ICP_LEDGER_ID, INTERNET_IDENTITY_ID} from './constants'; import {JunoPluginError} from './error'; vi.mock('@junobuild/config-loader', async () => { @@ -115,31 +116,70 @@ describe('config', () => { vi.clearAllMocks(); }); - it('returns docker satellite ID in dev mode with container true', async () => { - const id = await satelliteId({params: {container: true}, mode: 'development'}); - expect(id).toBe('jx5yt-yyaaa-aaaal-abzbq-cai'); - }); + describe('development', () => { + it('returns docker satellite ID in dev mode with container true and no config file', async () => { + vi.spyOn(configLoader, 'junoConfigExist').mockResolvedValue(false); - it('reads config if not using docker', async () => { - vi.spyOn(configLoader, 'junoConfigExist').mockResolvedValue(true); + const id = await satelliteId({params: {container: true}, mode: 'development'}); + expect(id).toBe(DOCKER_SATELLITE_ID); + }); - vi.spyOn(configLoader, 'readJunoConfig').mockResolvedValue({ - satellite: {ids: {production: 'prod-sat-id'}} + it('returns satellite ID from config if it exists', async () => { + vi.spyOn(configLoader, 'junoConfigExist').mockResolvedValue(true); + + vi.spyOn(configLoader, 'readJunoConfig').mockResolvedValue({ + satellite: {ids: {development: 'dev-custom-id'}} + }); + + const id = await satelliteId({params: {container: true}, mode: 'development'}); + expect(id).toBe('dev-custom-id'); }); - const id = await satelliteId({params: {container: false}, mode: 'production'}); - expect(id).toBe('prod-sat-id'); + it('falls back to default docker satellite ID if config exists but development ID is not set', async () => { + vi.spyOn(configLoader, 'junoConfigExist').mockResolvedValue(true); + + vi.spyOn(configLoader, 'readJunoConfig').mockResolvedValue({ + satellite: {ids: {}} + }); + + const id = await satelliteId({params: {container: true}, mode: 'development'}); + expect(id).toBe(DOCKER_SATELLITE_ID); + }); + + it('falls back to default docker satellite ID if config exists but no ids', async () => { + vi.spyOn(configLoader, 'junoConfigExist').mockResolvedValue(true); + + vi.spyOn(configLoader, 'readJunoConfig').mockResolvedValue({ + satellite: {id: 'prod-id'} + }); + + const id = await satelliteId({params: {container: true}, mode: 'development'}); + expect(id).toBe(DOCKER_SATELLITE_ID); + }); }); - it('throws if satellite ID is missing', async () => { - vi.spyOn(configLoader, 'junoConfigExist').mockResolvedValue(true); - vi.spyOn(configLoader, 'readJunoConfig').mockResolvedValue({ - satellite: {} - } as unknown as JunoConfig); + describe('no container', () => { + it('reads config if not using docker', async () => { + vi.spyOn(configLoader, 'junoConfigExist').mockResolvedValue(true); - await expect(() => satelliteId({params: {}, mode: 'production'})).rejects.toThrow( - JunoPluginError - ); + vi.spyOn(configLoader, 'readJunoConfig').mockResolvedValue({ + satellite: {ids: {production: 'prod-sat-id'}} + }); + + const id = await satelliteId({params: {container: false}, mode: 'production'}); + expect(id).toBe('prod-sat-id'); + }); + + it('throws if satellite ID is missing', async () => { + vi.spyOn(configLoader, 'junoConfigExist').mockResolvedValue(true); + vi.spyOn(configLoader, 'readJunoConfig').mockResolvedValue({ + satellite: {} + } as unknown as JunoConfig); + + await expect(() => satelliteId({params: {}, mode: 'production'})).rejects.toThrow( + JunoPluginError + ); + }); }); }); @@ -167,9 +207,9 @@ describe('config', () => { describe('icpIds', () => { it('returns static ICP IDs', () => { expect(icpIds()).toEqual({ - internetIdentityId: 'rdmx6-jaaaa-aaaaa-aaadq-cai', - icpLedgerId: 'ryjl3-tyaaa-aaaaa-aaaba-cai', - icpIndexId: 'qhbym-qaaaa-aaaaa-aaafq-cai' + internetIdentityId: INTERNET_IDENTITY_ID, + icpLedgerId: ICP_LEDGER_ID, + icpIndexId: ICP_INDEX_ID }); }); }); diff --git a/plugins/plugin-tools/src/config.ts b/plugins/plugin-tools/src/config.ts index 5e3cb39..0e674ef 100644 --- a/plugins/plugin-tools/src/config.ts +++ b/plugins/plugin-tools/src/config.ts @@ -22,7 +22,7 @@ export const useDockerContainer = ({params, mode}: ConfigArgs): boolean => export const satelliteId = async (args: ConfigArgs): Promise => { if (useDockerContainer(args)) { - return DOCKER_SATELLITE_ID; + return await containerSatelliteId(args); } return await junoConfigSatelliteId(args); @@ -46,6 +46,20 @@ const junoConfigSatelliteId = async ({mode}: ConfigArgs): Promise => { return satelliteId; }; +const containerSatelliteId = async ({mode}: ConfigArgs): Promise => { + const exist = await junoConfigExist(); + + if (!exist) { + return DOCKER_SATELLITE_ID; + } + + const { + satellite: {ids} + } = await readJunoConfig({mode}); + + return ids?.['development'] ?? DOCKER_SATELLITE_ID; +}; + export const orbiterId = async (args: ConfigArgs): Promise => { if (useDockerContainer(args)) { return undefined; @@ -95,7 +109,7 @@ const readJunoConfig = async ({mode}: ConfigArgs): Promise => { }; export const assertJunoConfig = async () => { - const exist = await junoConfigExistTools(JUNO_CONFIG_FILE); + const exist = await junoConfigExist(); if (!exist) { throw new JunoPluginError( @@ -103,3 +117,5 @@ export const assertJunoConfig = async () => { ); } }; + +const junoConfigExist = (): Promise => junoConfigExistTools(JUNO_CONFIG_FILE); diff --git a/plugins/plugin-tools/src/init.spec.ts b/plugins/plugin-tools/src/init.spec.ts index 7c71c01..564c49f 100644 --- a/plugins/plugin-tools/src/init.spec.ts +++ b/plugins/plugin-tools/src/init.spec.ts @@ -1,6 +1,13 @@ import type {JunoConfig} from '@junobuild/config'; import * as configLoader from '@junobuild/config-loader'; import {beforeEach, describe, expect, it, MockInstance, vi} from 'vitest'; +import { + DOCKER_CONTAINER_URL, + DOCKER_SATELLITE_ID, + ICP_INDEX_ID, + ICP_LEDGER_ID, + INTERNET_IDENTITY_ID +} from './constants'; import {initConfig} from './init'; import type {ConfigArgs} from './types'; @@ -36,6 +43,8 @@ describe('init', () => { }); it('returns config for development', async () => { + vi.spyOn(configLoader, 'junoConfigExist').mockResolvedValue(false); + const result = await initConfig({ params: {}, mode: 'development' @@ -43,16 +52,16 @@ describe('init', () => { expect(result).toEqual({ orbiterId: undefined, - satelliteId: 'jx5yt-yyaaa-aaaal-abzbq-cai', + satelliteId: DOCKER_SATELLITE_ID, icpIds: { - internetIdentityId: 'rdmx6-jaaaa-aaaaa-aaadq-cai', - icpLedgerId: 'ryjl3-tyaaa-aaaaa-aaaba-cai', - icpIndexId: 'qhbym-qaaaa-aaaaa-aaafq-cai' + internetIdentityId: INTERNET_IDENTITY_ID, + icpLedgerId: ICP_LEDGER_ID, + icpIndexId: ICP_INDEX_ID }, - container: 'http://127.0.0.1:5987' + container: DOCKER_CONTAINER_URL }); - expect(spyJunoConfigExist).not.toHaveBeenCalled(); + expect(configLoader.junoConfigExist).toHaveBeenCalled(); expect(spyReadJunoConfig).not.toHaveBeenCalled(); }); @@ -63,9 +72,9 @@ describe('init', () => { satelliteId: 'mock-satellite-id', orbiterId: 'mock-orbiter-id', icpIds: { - internetIdentityId: 'rdmx6-jaaaa-aaaaa-aaadq-cai', - icpLedgerId: 'ryjl3-tyaaa-aaaaa-aaaba-cai', - icpIndexId: 'qhbym-qaaaa-aaaaa-aaafq-cai' + internetIdentityId: INTERNET_IDENTITY_ID, + icpLedgerId: ICP_LEDGER_ID, + icpIndexId: ICP_INDEX_ID }, container: undefined }); @@ -74,24 +83,52 @@ describe('init', () => { expect(spyReadJunoConfig).toHaveBeenCalled(); }); - it('returns config for development when params is not passed', async () => { - const result = await initConfig({ - mode: 'development' - }); + describe('no config', () => { + it('returns default docker satellite ID in development if config does not exist', async () => { + vi.spyOn(configLoader, 'junoConfigExist').mockResolvedValue(false); - expect(result).toEqual({ - satelliteId: 'jx5yt-yyaaa-aaaal-abzbq-cai', - orbiterId: undefined, - icpIds: { - internetIdentityId: 'rdmx6-jaaaa-aaaaa-aaadq-cai', - icpLedgerId: 'ryjl3-tyaaa-aaaaa-aaaba-cai', - icpIndexId: 'qhbym-qaaaa-aaaaa-aaafq-cai' - }, - container: 'http://127.0.0.1:5987' + const result = await initConfig({ + params: {}, + mode: 'development' + }); + + expect(result).toEqual({ + orbiterId: undefined, + satelliteId: DOCKER_SATELLITE_ID, + icpIds: { + internetIdentityId: INTERNET_IDENTITY_ID, + icpLedgerId: ICP_LEDGER_ID, + icpIndexId: ICP_INDEX_ID + }, + container: DOCKER_CONTAINER_URL + }); + + expect(configLoader.junoConfigExist).toHaveBeenCalled(); + expect(spyReadJunoConfig).not.toHaveBeenCalled(); }); - expect(spyJunoConfigExist).not.toHaveBeenCalled(); - expect(spyReadJunoConfig).not.toHaveBeenCalled(); + it('returns fallback Docker satellite ID when using container and config does not exist and container is specified', async () => { + vi.spyOn(configLoader, 'junoConfigExist').mockResolvedValue(false); + + const result = await initConfig({ + params: {container: true}, + mode: 'development' + }); + + expect(result).toEqual({ + satelliteId: DOCKER_SATELLITE_ID, + orbiterId: undefined, + icpIds: { + internetIdentityId: INTERNET_IDENTITY_ID, + icpLedgerId: ICP_LEDGER_ID, + icpIndexId: ICP_INDEX_ID + }, + container: DOCKER_CONTAINER_URL + }); + + expect(configLoader.junoConfigExist).toHaveBeenCalled(); + expect(spyReadJunoConfig).not.toHaveBeenCalled(); + }); }); it('returns config for production when params is not passed', async () => { @@ -103,9 +140,9 @@ describe('init', () => { satelliteId: 'mock-satellite-id', orbiterId: 'mock-orbiter-id', icpIds: { - internetIdentityId: 'rdmx6-jaaaa-aaaaa-aaadq-cai', - icpLedgerId: 'ryjl3-tyaaa-aaaaa-aaaba-cai', - icpIndexId: 'qhbym-qaaaa-aaaaa-aaafq-cai' + internetIdentityId: INTERNET_IDENTITY_ID, + icpLedgerId: ICP_LEDGER_ID, + icpIndexId: ICP_INDEX_ID }, container: undefined }); @@ -114,27 +151,30 @@ describe('init', () => { expect(spyReadJunoConfig).toHaveBeenCalled(); }); - it('skips assertJunoConfig when using Docker container', async () => { - const dockerArgs: ConfigArgs = { + it('returns satellite ID from config when using container and config exists', async () => { + vi.spyOn(configLoader, 'junoConfigExist').mockResolvedValue(true); + vi.spyOn(configLoader, 'readJunoConfig').mockResolvedValue({ + satellite: {ids: {development: 'custom-docker-id'}} + }); + + const result = await initConfig({ params: {container: true}, mode: 'development' - }; - - const result = await initConfig(dockerArgs); + }); expect(result).toEqual({ - satelliteId: 'jx5yt-yyaaa-aaaal-abzbq-cai', // fallback to docker const + satelliteId: 'custom-docker-id', orbiterId: undefined, icpIds: { - internetIdentityId: 'rdmx6-jaaaa-aaaaa-aaadq-cai', - icpLedgerId: 'ryjl3-tyaaa-aaaaa-aaaba-cai', - icpIndexId: 'qhbym-qaaaa-aaaaa-aaafq-cai' + internetIdentityId: INTERNET_IDENTITY_ID, + icpLedgerId: ICP_LEDGER_ID, + icpIndexId: ICP_INDEX_ID }, - container: 'http://127.0.0.1:5987' + container: DOCKER_CONTAINER_URL }); - expect(spyJunoConfigExist).not.toHaveBeenCalled(); - expect(spyReadJunoConfig).not.toHaveBeenCalled(); + expect(configLoader.junoConfigExist).toHaveBeenCalled(); + expect(configLoader.readJunoConfig).toHaveBeenCalled(); }); it('throws if config does not exist and mode is production', async () => {