Skip to content
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
230 changes: 7 additions & 223 deletions src/commands/init.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,11 @@
import {isNullish, nonNullish} from '@dfinity/utils';
import {assertAnswerCtrlC, hasArgs} from '@junobuild/cli-tools';
import type {PartialConfigFile} from '@junobuild/config-loader';
import {cyan, yellow} from 'kleur';
import {unlink} from 'node:fs/promises';
import {basename} from 'node:path';
import prompts from 'prompts';
import {getCliOrbiters, getCliSatellites, getToken} from '../configs/cli.config';
import {
detectJunoConfigType,
junoConfigExist,
junoConfigFile,
writeJunoConfig,
writeJunoConfigPlaceholder
} from '../configs/juno.config';
import {promptConfigType} from '../services/init.services';
import {isNullish} from '@dfinity/utils';
import {hasArgs} from '@junobuild/cli-tools';
import {cyan} from 'kleur';
import {getToken} from '../configs/cli.config';
import {junoConfigExist} from '../configs/juno.config';
import {initConfigInteractive, initConfigNoneInteractive} from '../services/init.services';
import {login as consoleLogin} from '../services/login.services';
import type {CliOrbiterConfig, CliSatelliteConfig} from '../types/cli.config';
import type {PackageManager} from '../types/pm';
import {detectPackageManager} from '../utils/pm.utils';
import {NEW_CMD_LINE, confirm, confirmAndExit} from '../utils/prompt.utils';
import {confirm, confirmAndExit} from '../utils/prompt.utils';

export const init = async (args?: string[]) => {
if (hasArgs({args, options: ['-m', '--minimal']})) {
Expand Down Expand Up @@ -62,206 +49,3 @@ const assertOverwrite = async () => {
);
}
};

const initConfigNoneInteractive = async () => {
const writeFn = async ({source, ...rest}: InitConfigParams) => {
await writeJunoConfigPlaceholder({
...rest,
config: {
satellite: {source}
}
});
};

await initConfig({
writeFn
});
};

const initConfigInteractive = async () => {
const satelliteId = await initSatelliteConfig();
const orbiterId = await initOrbiterConfig();

const writeFn = async ({source, ...rest}: InitConfigParams) => {
await writeJunoConfig({
...rest,
config: {
satellite: {id: satelliteId, source},
...(nonNullish(orbiterId) && {orbiter: {id: orbiterId}})
}
});
};

await initConfig({
writeFn
});
};

type InitConfigParams = PartialConfigFile & {pm: PackageManager | undefined} & {source: string};

const initConfig = async ({writeFn}: {writeFn: (params: InitConfigParams) => Promise<void>}) => {
const pm = detectPackageManager();

const source = await promptSource({pm});

const {configType, configPath: originalConfigPath} = await initConfigType();

await writeFn({
configType,
configPath: originalConfigPath,
pm,
source
});

// We delete the deprecated juno.json, which is now replaced with juno.config.json|ts|js, as just created above.
// The developer was prompted about overwriting the configuration previously.
if (nonNullish(originalConfigPath) && basename(originalConfigPath) === 'juno.json') {
await unlink(originalConfigPath);
}

if (configType === 'json') {
return;
}

showConfigTips({pm});
};

const showConfigTips = ({pm}: {pm: PackageManager | undefined}) => {
const cmd = `${pm ?? 'npm'} ${isNullish(pm) || pm === 'npm' ? 'i' : 'add'} @junobuild/config -D`;

console.log(
`${NEW_CMD_LINE}💡 You can leverage your IDE's intellisense by installing the library: ${yellow(cmd)}${NEW_CMD_LINE}`
);
};

const initSatelliteConfig = async (): Promise<string> => {
const satellites = await getCliSatellites();

const satellite = await (satellites.length > 0
? promptSatellites(satellites)
: promptSatellite());

if (satellite === '_manual_') {
return await promptSatellite();
}

return satellite;
};

const initOrbiterConfig = async (): Promise<string | undefined> => {
const authOrbiters = await getCliOrbiters();

if (authOrbiters === undefined || authOrbiters.length === 0) {
return undefined;
}

const orbiter = await promptOrbiters(authOrbiters);

if (orbiter === '_none_') {
return undefined;
}

return orbiter;
};

const promptSatellites = async (satellites: CliSatelliteConfig[]): Promise<string> => {
const {satellite}: {satellite: string} = await prompts({
type: 'select',
name: 'satellite',
message: 'Which satellite should be linked with this dapp?',
choices: [
...satellites.map(({p, n}) => ({title: n, value: p})),
{title: '<not listed, manual entry>', value: '_manual_'}
],
initial: 0
});

// In case of control+c
assertAnswerCtrlC(satellite);

return satellite;
};

const initConfigType = async (): Promise<PartialConfigFile> => {
if (!(await junoConfigExist())) {
// We try to automatically detect if we should create a TypeScript or JavaScript (mjs) configuration.
const detectedConfig = detectJunoConfigType();

if (nonNullish(detectedConfig)) {
return detectedConfig;
}

const configType = await promptConfigType();
return {configType};
}

return junoConfigFile();
};

const promptSatellite = async (): Promise<string> => {
const {satellite}: {satellite: string} = await prompts([
{
type: 'text',
name: 'satellite',
message: `What's the ${cyan('id')} of your satellite?`
}
]);

assertAnswerCtrlC(satellite, 'The satellite ID is mandatory');

return satellite;
};

const promptSource = async ({pm}: {pm: PackageManager | undefined}): Promise<string> => {
const cmd = `${pm ?? 'npm'}${isNullish(pm) || pm === 'npm' ? ' run' : ''} build`;

const {output}: {output: string} = await prompts({
type: 'select',
name: 'output',
message: `What is the output folder of your \`${cmd}\` command?`,
choices: [
{title: 'build', value: 'build'},
{title: 'dist', value: 'dist'},
{title: 'out', value: 'out'},
{title: '<not listed, manual entry>', value: '_manual_'}
],
initial: 0
});

// In case of control+c
assertAnswerCtrlC(output);

if (output !== '_manual_') {
return output;
}

const {source}: {source: string} = await prompts([
{
type: 'text',
name: 'source',
message: 'Please enter the name of your output folder'
}
]);

assertAnswerCtrlC(source);

return source;
};

const promptOrbiters = async (orbiters: CliOrbiterConfig[]): Promise<string> => {
const {orbiter}: {orbiter: string} = await prompts({
type: 'select',
name: 'orbiter',
message: 'Which orbiter do you use for the analytics in this dapp?',
choices: [
...orbiters.map(({p, n}) => ({title: n ?? p, value: p})),
{title: '<none>', value: '_none_'}
],
initial: 0
});

// In case of control+c
assertAnswerCtrlC(orbiter);

return orbiter;
};
2 changes: 1 addition & 1 deletion src/configs/juno.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export const writeJunoConfig = async ({
});

const content = template
.replace('<SATELLITE_ID>', id)
.replace('<PROD_SATELLITE_ID>', id)
.replace('<SOURCE>', source ?? DEPLOY_DEFAULT_SOURCE)
.replace('<COMMAND>', pm === 'npm' ? 'npm run' : (pm ?? ''))
.replace('<ORBITER_ID>', orbiter?.id ?? '');
Expand Down
Loading