Skip to content
Closed
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
7 changes: 4 additions & 3 deletions src/api/actor.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,23 @@ import {green, red, yellow} from 'kleur';
import {getToken} from '../configs/cli.config';
import {readEmulatorConfig} from '../configs/emulator.config';
import {ENV} from '../env';
import {EnvToken} from '../env.token';
import {noConfigFile} from '../utils/cli.config.utils';
import {getProcessToken, isHeadless} from '../utils/process.utils';
import {isNotHeadless} from '../utils/process.utils';
import {initAgent} from './agent.api';

export const actorParameters = async (): Promise<
Omit<ActorParameters, 'agent'> & Required<Pick<ActorParameters, 'agent'>>
> => {
const configNotFound = !isHeadless() && noConfigFile();
const configNotFound = (await isNotHeadless()) && noConfigFile();

if (configNotFound) {
await missingConfigInfo({errorType: 'not-configured'});

process.exit(1);
}

const token = getProcessToken() ?? (await getToken());
const token = (await EnvToken.getInstance()).token ?? (await getToken());

if (isNullish(token)) {
await missingConfigInfo({errorType: 'not-logged-in'});
Expand Down
53 changes: 53 additions & 0 deletions src/env.token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {nonNullish} from '@dfinity/utils';
import type {JsonnableEd25519KeyIdentity} from '@icp-sdk/core/identity';

export class EnvToken {
static #instance: EnvToken | undefined;

readonly #token: JsonnableEd25519KeyIdentity | undefined;

private constructor(readonly keyIdentity: JsonnableEd25519KeyIdentity | undefined) {
this.#token = keyIdentity;
}

static async getInstance(): Promise<EnvToken> {
if (EnvToken.#instance === undefined) {
// eslint-disable-next-line require-atomic-updates
EnvToken.#instance = await EnvToken.#init();
}

return EnvToken.#instance;
}

// eslint-disable-next-line @typescript-eslint/require-await
static async #init(): Promise<EnvToken> {
const envToken = process.env.JUNO_TOKEN;

if (envToken !== undefined) {
const token = this.#parseToken({envToken});
return new EnvToken(token);
}

return new EnvToken(undefined);
}

static #parseToken({envToken}: {envToken: string}): JsonnableEd25519KeyIdentity | undefined {
try {
const {token} = JSON.parse(atob(envToken));
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return token;
} catch (err: unknown) {
throw new Error('Cannot parse token provided as an environment variable.', {
cause: err
});
}
}

get token(): JsonnableEd25519KeyIdentity | undefined {
return this.#token;
}

isDefined = (): boolean => {
return nonNullish(this.#token);
};
}
2 changes: 1 addition & 1 deletion src/services/assert.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const assertSatelliteMemorySize = async () => {
heap
)} MB, which exceeds the asserted limit of ${formatNumber(maxMemorySize)} MB.`;

if (isHeadless()) {
if (await isHeadless()) {
console.log(yellow(errorText));
process.exit(1);
}
Expand Down
2 changes: 1 addition & 1 deletion src/services/config/apply.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ const prepareConfig = async ({
return filterIdenticalConfig(extendWithVersions());
}

if (isHeadless()) {
if (await isHeadless()) {
console.log(
yellow('Non-interactive mode detected. Re-run with --force to overwrite without checks.')
);
Expand Down
4 changes: 2 additions & 2 deletions src/services/emulator/_runner.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ const startEmulator = async ({config: extendedConfig}: {config: CliEmulatorConfi
// -i: Keep STDIN open even if not attached. Equivalent to `--interactive`.
await execute({
command: runner,
args: ['start', '-a', ...(isHeadless() ? [] : ['-i']), containerName]
args: ['start', '-a', ...((await isHeadless()) ? [] : ['-i']), containerName]
});
return;
}
Expand Down Expand Up @@ -219,7 +219,7 @@ const startEmulator = async ({config: extendedConfig}: {config: CliEmulatorConfi
command: runner,
args: [
'run',
...(isHeadless() ? [] : ['-it']),
...((await isHeadless()) ? [] : ['-it']),
'--name',
containerName,
'-p',
Expand Down
2 changes: 1 addition & 1 deletion src/services/links.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const links = async () => {
// If a developer is using a JUNO_TOKEN to execute command(s), the custom domain will not be queried or printed.
// This is particularly useful in CI environments where access keys might be limited,
// and only ADMIN keys can list custom domains.
const domains = isHeadless() ? [] : await listCustomDomains({satellite});
const domains = (await isHeadless()) ? [] : await listCustomDomains({satellite});

console.log(`\n🛠️ ${terminalLink(adminUrl)}`);

Expand Down
2 changes: 1 addition & 1 deletion src/services/modules/upgrade/upgrade-assert.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const assertSatelliteBuildType = async ({

const warning = satelliteType === 'extended' && (wasmType === 'stock' || isNullish(wasmType));

if (isHeadless() && warning) {
if ((await isHeadless()) && warning) {
throw new Error(
'Your satellite uses serverless functions. Reverting to the stock version would remove your custom features! '
);
Expand Down
2 changes: 1 addition & 1 deletion src/services/modules/upgrade/upgrade.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const executeUpgradeWasm = async ({
}: {assetKey: AssetKey; moduleId: string} & UpgradeWasm) => {
await assert?.({wasmModule: wasm});

if (isNotHeadless()) {
if (await isNotHeadless()) {
await assertUpgradeHash({hash, reset, assetKey, moduleId});
}

Expand Down
2 changes: 1 addition & 1 deletion src/stores/settings.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class SettingsConfigStore {
static async init(): Promise<SettingsConfigStore> {
const store = new SettingsConfigStore(getSettingsConfig());

if (isHeadless()) {
if (await isHeadless()) {
return store;
}

Expand Down
28 changes: 5 additions & 23 deletions src/utils/process.utils.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,15 @@
import type {JsonnableEd25519KeyIdentity} from '@icp-sdk/core/identity';
import {hasArgs} from '@junobuild/cli-tools';
import {EnvToken} from '../env.token';

export const getProcessToken = (): JsonnableEd25519KeyIdentity | undefined => {
const envToken = process.env.JUNO_TOKEN;
export const isHeadless = async (): Promise<boolean> => {
const {isDefined} = await EnvToken.getInstance();

if (envToken === undefined) {
return undefined;
}

try {
const {token} = JSON.parse(atob(envToken));
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return token;
} catch (err: unknown) {
throw new Error('Cannot parse token provided as an environment variable.', {
cause: err
});
}
};

const isProcessToken = (): boolean => getProcessToken() !== undefined;

export const isHeadless = (): boolean => {
if (isProcessToken()) {
if (isDefined()) {
return true;
}

const [_, ...args] = process.argv.slice(2);
return hasArgs({args, options: ['--headless']});
};

export const isNotHeadless = (): boolean => !isHeadless();
export const isNotHeadless = async (): Promise<boolean> => !(await isHeadless());
2 changes: 1 addition & 1 deletion src/utils/prompt.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export const confirmAndExit = async (message: string) => {
};

export const confirmAndExitUnlessHeadlessAndDev = async (message: string) => {
if (isHeadless() && DEV) {
if ((await isHeadless()) && DEV) {
return;
}

Expand Down