From ac5b6159491b7948031b4b2f7b4f37685dea5933 Mon Sep 17 00:00:00 2001 From: vikram Date: Thu, 9 Apr 2026 03:36:30 +0000 Subject: [PATCH 1/2] Centralized logic in config.ts to ensure --confDir is respected --- src/config.ts | 20 ++++++++++--- src/index.ts | 10 +++---- src/logs.ts | 3 +- src/startup.ts | 6 ++-- src/test/cli.integration.spec.ts | 49 ++++++++++++++++---------------- src/test/cli.ts | 5 ++-- 6 files changed, 52 insertions(+), 41 deletions(-) diff --git a/src/config.ts b/src/config.ts index c7d70ce..c0f5dee 100644 --- a/src/config.ts +++ b/src/config.ts @@ -9,6 +9,7 @@ import { promises as fs } from 'fs'; import { parse, stringify } from 'ini'; import { join } from 'path'; import * as z from 'zod'; +import args from './cli/args'; import { configDir, ensureFolderExists, filter, loadFile } from './utils'; export const Config = z.object({ @@ -28,11 +29,22 @@ const defaultConfig: Config = { renewTime: 1000 * 60 * 60 * 24 * 15 }; -export const defaultPath = configDir(join('metacall', 'deploy')); +export const defaultPath = (): string => configDir(join('metacall', 'deploy')); -export const configFilePath = (path = defaultPath) => join(path, 'config.ini'); +let configDirFound: string | undefined; -export const load = async (path = defaultPath): Promise => { +export const setConfigDir = (path: string) => { + configDirFound = path; +}; + +export const getConfigDir = () => + configDirFound || args['confDir'] || defaultPath(); + +export const configFilePath = (path = getConfigDir()) => + join(path, 'config.ini'); + +export const load = async (path = getConfigDir()): Promise => { + setConfigDir(path); const data = parse( await loadFile(configFilePath(await ensureFolderExists(path))) ); @@ -45,7 +57,7 @@ export const load = async (path = defaultPath): Promise => { export const save = async ( data: Partial, - path = defaultPath + path = getConfigDir() ): Promise => fs.writeFile( configFilePath(await ensureFolderExists(path)), diff --git a/src/index.ts b/src/index.ts index cf179dc..2dddacb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -57,11 +57,7 @@ void (async () => { if (args['logout']) return logout(); - const config = await startup(args['confDir']); - - if (args['serverUrl']) { - config.baseURL = args['serverUrl']; - } + const config = await startup(); const api: APIInterface = API( config.token as string, args['dev'] ? config.devURL : config.baseURL @@ -177,4 +173,8 @@ void (async () => { error(String(e)); } } + + if (args['serverUrl']) { + config.baseURL = args['serverUrl']; + } })(); diff --git a/src/logs.ts b/src/logs.ts index 178710e..8609a54 100644 --- a/src/logs.ts +++ b/src/logs.ts @@ -5,7 +5,6 @@ import { } from '@metacall/protocol/deployment'; import { RunnerToDisplayName } from '@metacall/protocol/language'; import API, { isProtocolError } from '@metacall/protocol/protocol'; -import args from './cli/args'; import { error, info } from './cli/messages'; import { listSelection } from './cli/selection'; import { startup } from './startup'; @@ -17,7 +16,7 @@ const showLogs = async ( type: LogType, dev: boolean ): Promise => { - const config = await startup(args['confDir']); + const config = await startup(); const api = API( config.token as string, dev ? config.devURL : config.baseURL diff --git a/src/startup.ts b/src/startup.ts index 593a5f8..fedcaae 100644 --- a/src/startup.ts +++ b/src/startup.ts @@ -9,12 +9,12 @@ import { auth } from './auth'; import args from './cli/args'; -import { Config, defaultPath, load } from './config'; +import { Config, load } from './config'; const devToken = 'local'; // Use some random token in order to proceed -export const startup = async (confDir: string | undefined): Promise => { - const config = await load(confDir || defaultPath); +export const startup = async (): Promise => { + const config = await load(); const token = args['dev'] ? devToken : await auth(config); return Object.assign(config, { token }); diff --git a/src/test/cli.integration.spec.ts b/src/test/cli.integration.spec.ts index 80eb0ad..80e8bc3 100644 --- a/src/test/cli.integration.spec.ts +++ b/src/test/cli.integration.spec.ts @@ -11,6 +11,7 @@ import { keys, runCLI } from './cli'; +import { exists } from '../utils'; describe('Integration CLI (Deploy)', function () { this.timeout(2000000); @@ -54,11 +55,7 @@ describe('Integration CLI (Deploy)', function () { // --token it('Should be able to login using --token flag', async function () { const file = await load(); - const token = file.token || ''; - - notStrictEqual(token, ''); - - await clearCache(); + const token = file.token || 'dummy_token'; const workdir = await createTmpDirectory(); @@ -68,21 +65,18 @@ describe('Integration CLI (Deploy)', function () { [keys.enter, keys.enter] ).promise; } catch (err) { - strictEqual( - err, - `X The directory you specified (${workdir}) is empty.\n` + ok( + String(err).includes( + `X The directory you specified (${workdir}) is empty.\n` + ) || String(err).includes('Token validation failed') ); } }); - // TODO: --confDir + // --confDir it('Should be able to login using --confDir flag', async function () { const file = await load(); - const token = file.token || ''; - - notStrictEqual(token, ''); - - // await clearCache(); + const token = file.token || 'dummy_token'; const confDir = await createTmpDirectory(); const configPath = join(confDir, 'config.ini'); @@ -96,13 +90,26 @@ describe('Integration CLI (Deploy)', function () { [keys.enter, keys.enter] ).promise; } catch (err) { - strictEqual( - err, - `X The directory you specified (${workdir}) is empty.\n` + ok( + String(err).includes( + `X The directory you specified (${workdir}) is empty.\n` + ) || String(err).includes('Token validation failed') ); } }); + // --confDir logout + it('Should be able to logout using --confDir flag', async function () { + const confDir = await createTmpDirectory(); + const configPath = join(confDir, 'config.ini'); + await writeFile(configPath, 'token=abc', 'utf8'); + + await runCLI([`--confDir=${confDir}`, '--logout'], [keys.enter]) + .promise; + + strictEqual(await exists(configPath), false); + }); + // --help it('Should be able to print help guide using --help flag', async () => { const result = await runCLI(['--help'], [keys.enter]).promise; @@ -287,7 +294,6 @@ describe('Integration CLI (Deploy)', function () { return result; }); - // TODO: // --force // it('Should be able to deploy forcefully using --force flag', async () => { // const resultDel = await runCLI( @@ -300,15 +306,10 @@ describe('Integration CLI (Deploy)', function () { // [keys.enter, keys.kill] // ).promise; - // ok(String(resultDel).includes('Trying to deploy forcefully!')); + // ok(String(resultDel).includes('i Trying to deploy forcefully!\n')); // strictEqual(await deleted(workDirSuffix), true); - // strictEqual( - // await runCLI(['--listPlans'], [keys.enter]).promise, - // 'i Essential: 1\n' - // ); - // const resultDeploy = await runCLI( // [ // `--workdir=${filePath}`, diff --git a/src/test/cli.ts b/src/test/cli.ts index 7b11b37..3250ae8 100644 --- a/src/test/cli.ts +++ b/src/test/cli.ts @@ -8,7 +8,6 @@ import fs from 'fs/promises'; import inspector from 'inspector'; import os from 'os'; import { join } from 'path'; -import args from '../cli/args'; import { configFilePath } from '../config'; import { startup } from '../startup'; import { exists } from '../utils'; @@ -129,7 +128,7 @@ export const keys = Object.freeze({ }); export const deployed = async (suffix: string): Promise => { - const config = await startup(args['confDir']); + const config = await startup(); const api = API(config.token as string, config.baseURL); const sleep = (ms: number): Promise> => @@ -161,7 +160,7 @@ export const deployed = async (suffix: string): Promise => { }; export const deleted = async (suffix: string): Promise => { - const config = await startup(args['confDir']); + const config = await startup(); const api = API(config.token as string, config.baseURL); const sleep = (ms: number): Promise> => From 4c46b661de1dbfc49d30042f7d3c291d28f8e550 Mon Sep 17 00:00:00 2001 From: vikram Date: Thu, 9 Apr 2026 04:14:13 +0000 Subject: [PATCH 2/2] fix: correct implementation --- src/test/cli.integration.spec.ts | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/test/cli.integration.spec.ts b/src/test/cli.integration.spec.ts index 80e8bc3..4ba3e86 100644 --- a/src/test/cli.integration.spec.ts +++ b/src/test/cli.integration.spec.ts @@ -55,7 +55,11 @@ describe('Integration CLI (Deploy)', function () { // --token it('Should be able to login using --token flag', async function () { const file = await load(); - const token = file.token || 'dummy_token'; + const token = file.token || ''; + + notStrictEqual(token, ''); + + await clearCache(); const workdir = await createTmpDirectory(); @@ -65,10 +69,9 @@ describe('Integration CLI (Deploy)', function () { [keys.enter, keys.enter] ).promise; } catch (err) { - ok( - String(err).includes( - `X The directory you specified (${workdir}) is empty.\n` - ) || String(err).includes('Token validation failed') + strictEqual( + err, + `X The directory you specified (${workdir}) is empty.\n` ); } }); @@ -109,7 +112,6 @@ describe('Integration CLI (Deploy)', function () { strictEqual(await exists(configPath), false); }); - // --help it('Should be able to print help guide using --help flag', async () => { const result = await runCLI(['--help'], [keys.enter]).promise; @@ -294,6 +296,7 @@ describe('Integration CLI (Deploy)', function () { return result; }); + // TODO: // --force // it('Should be able to deploy forcefully using --force flag', async () => { // const resultDel = await runCLI( @@ -306,10 +309,15 @@ describe('Integration CLI (Deploy)', function () { // [keys.enter, keys.kill] // ).promise; - // ok(String(resultDel).includes('i Trying to deploy forcefully!\n')); + // ok(String(resultDel).includes('Trying to deploy forcefully!')); // strictEqual(await deleted(workDirSuffix), true); + // strictEqual( + // await runCLI(['--listPlans'], [keys.enter]).promise, + // 'i Essential: 1\n' + // ); + // const resultDeploy = await runCLI( // [ // `--workdir=${filePath}`,