Skip to content

feat: custom satellite id in development #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 61 additions & 21 deletions plugins/plugin-tools/src/config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand Down Expand Up @@ -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
);
});
});
});

Expand Down Expand Up @@ -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
});
});
});
Expand Down
20 changes: 18 additions & 2 deletions plugins/plugin-tools/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const useDockerContainer = ({params, mode}: ConfigArgs): boolean =>

export const satelliteId = async (args: ConfigArgs): Promise<string> => {
if (useDockerContainer(args)) {
return DOCKER_SATELLITE_ID;
return await containerSatelliteId(args);
}

return await junoConfigSatelliteId(args);
Expand All @@ -46,6 +46,20 @@ const junoConfigSatelliteId = async ({mode}: ConfigArgs): Promise<string> => {
return satelliteId;
};

const containerSatelliteId = async ({mode}: ConfigArgs): Promise<string> => {
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<string | undefined> => {
if (useDockerContainer(args)) {
return undefined;
Expand Down Expand Up @@ -95,11 +109,13 @@ const readJunoConfig = async ({mode}: ConfigArgs): Promise<JunoConfig> => {
};

export const assertJunoConfig = async () => {
const exist = await junoConfigExistTools(JUNO_CONFIG_FILE);
const exist = await junoConfigExist();

if (!exist) {
throw new JunoPluginError(
`No Juno configuration found. Run "juno init" to configure your dapp.`
);
}
};

const junoConfigExist = (): Promise<boolean> => junoConfigExistTools(JUNO_CONFIG_FILE);
118 changes: 79 additions & 39 deletions plugins/plugin-tools/src/init.spec.ts
Original file line number Diff line number Diff line change
@@ -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';

Expand Down Expand Up @@ -36,23 +43,25 @@ describe('init', () => {
});

it('returns config for development', async () => {
vi.spyOn(configLoader, 'junoConfigExist').mockResolvedValue(false);

const result = await initConfig({
params: {},
mode: 'development'
});

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();
});

Expand All @@ -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
});
Expand All @@ -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 () => {
Expand All @@ -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
});
Expand All @@ -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 () => {
Expand Down