@holochain/hc-spin
Version:
CLI to run Holochain apps during development.
109 lines (101 loc) • 3.36 kB
text/typescript
import fs from 'fs';
import path from 'path';
import { UISource } from './windows';
export type CliOpts = {
appId?: string;
holochainPath?: string;
numAgents?: number;
networkSeed?: string;
targetArcFactor?: number;
uiPath?: string;
uiPort?: number;
relayUrl?: string;
bootstrapUrl?: string;
openDevtools?: boolean;
};
export type CliOptsValidated = {
appId: string;
holochainPath: string | undefined;
numAgents: number;
networkSeed: string | undefined;
targetArcFactor: number | undefined;
uiSource: UISource;
relayUrl: string | undefined;
bootstrapUrl: string | undefined;
happOrWebhappPath: HappOrWebhappPath;
openDevtools: boolean;
};
export type HappOrWebhappPath = {
type: 'happ' | 'webhapp';
path: string;
};
export function validateCliArgs(
cliArgs: string[],
cliOpts: CliOpts,
appDataRootDir: string,
): CliOptsValidated {
if (cliArgs.length !== 1) {
throw new Error(
`hc spin takes exactly one argument (the path to the .happ or .webhapp file) but got ${cliArgs.length} arguments: ${cliArgs}`,
);
}
const happOrWebhappPath = cliArgs[0];
if (!happOrWebhappPath.endsWith('.happ') && !happOrWebhappPath.endsWith('.webhapp')) {
throw new Error(
`The path passed to hc spin must either be a .happ or a .webhapp file but got path '${happOrWebhappPath}'`,
);
}
if (!fs.existsSync(happOrWebhappPath)) {
throw new Error(
`Path to .happ or .webhapp file passed as argument does not exist: ${happOrWebhappPath}`,
);
}
if (
cliOpts.numAgents !== undefined &&
(typeof cliOpts.numAgents !== 'number' || Number.isNaN(cliOpts.numAgents))
) {
throw new Error(
`The --num-agents (-n) option must be of type number but got: ${cliOpts.numAgents}`,
);
}
if (
cliOpts.targetArcFactor !== undefined &&
(typeof cliOpts.targetArcFactor !== 'number' || Number.isNaN(cliOpts.targetArcFactor))
) {
throw new Error(
`The --target-arc-factor (-t) option must be a valid number but got: ${cliOpts.targetArcFactor}`,
);
}
const isHapp = happOrWebhappPath.endsWith('.happ');
if (isHapp && !cliOpts.uiPath && !cliOpts.uiPort) {
throw new Error(
'If you pass a .happ file as argument, you must also provide either the --ui-port or the --ui-path option pointing to the UI assets.',
);
}
if (cliOpts.uiPath && cliOpts.uiPort) {
throw new Error(
'Only one of --ui-port and --ui-path is allowed at the same time but got values for both.',
);
}
const appId = cliOpts.appId ? cliOpts.appId : path.parse(path.basename(cliArgs[0])).name;
const holochainPath = cliOpts.holochainPath;
const numAgents = cliOpts.numAgents ? cliOpts.numAgents : 2;
return {
appId,
holochainPath,
numAgents,
networkSeed: cliOpts.networkSeed,
targetArcFactor: cliOpts.targetArcFactor,
uiSource: cliOpts.uiPath
? { type: 'path', path: cliOpts.uiPath }
: cliOpts.uiPort
? { type: 'port', port: cliOpts.uiPort }
: { type: 'path', path: path.join(appDataRootDir, 'apps', appId, 'ui') },
relayUrl: cliOpts.relayUrl,
bootstrapUrl: cliOpts.bootstrapUrl,
happOrWebhappPath: isHapp
? { type: 'happ', path: happOrWebhappPath }
: { type: 'webhapp', path: happOrWebhappPath },
openDevtools: cliOpts.openDevtools ? true : false,
};
}