From 01623eab2a23ad26e49553f48be9ab80f7aa6563 Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Tue, 28 Oct 2025 15:42:39 +0000 Subject: [PATCH] fix(smartcli): Allow passing argv to startParse and improve getUserArgs Deno/runtime handling; update tests and add license --- changelog.md | 8 ++++++++ test/test.node+deno+bun.ts | 3 ++- ts/00_commitinfo_data.ts | 2 +- ts/smartcli.classes.smartcli.ts | 5 +++-- ts/smartcli.helpers.ts | 10 +++------- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/changelog.md b/changelog.md index 9de0bba..66e068c 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,13 @@ # Changelog +## 2025-10-28 - 4.0.18 - fix(smartcli) +Allow passing argv to startParse and improve getUserArgs Deno/runtime handling; update tests and add license + +- Smartcli.startParse now accepts an optional testArgv parameter to bypass automatic runtime detection (makes testing deterministic). +- getUserArgs logic refined: always prefer Deno.args when available (handles Deno run and compiled executables reliably) and improve execPath fallback and slicing behavior for Node/Bun/other launchers. +- Tests updated: test/test.node+deno+bun.ts now passes process.argv explicitly to startParse to avoid Deno.args interference in test environments. +- Added MIT LICENSE file and a local .claude/settings.local.json for environment/permission settings. + ## 2025-10-28 - 4.0.17 - fix(license) Add MIT license and local Claude settings diff --git a/test/test.node+deno+bun.ts b/test/test.node+deno+bun.ts index 6fa1d60..c9e07e6 100644 --- a/test/test.node+deno+bun.ts +++ b/test/test.node+deno+bun.ts @@ -19,7 +19,8 @@ tap.test('should add an command', async (toolsArg) => { console.log(process.argv); process.argv.splice(2, 0, 'awesome'); console.log(process.argv); - smartCliTestObject.startParse(); + // Pass process.argv explicitly for testing (bypasses Deno.args in Deno environments) + smartCliTestObject.startParse(process.argv); await done.promise; }); diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 884b8a1..60d28e2 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@push.rocks/smartcli', - version: '4.0.17', + version: '4.0.18', description: 'A library that simplifies building reactive command-line applications using observables, with robust support for commands, arguments, options, aliases, and asynchronous operation management.' } diff --git a/ts/smartcli.classes.smartcli.ts b/ts/smartcli.classes.smartcli.ts index 7323b2d..d57f2ab 100644 --- a/ts/smartcli.classes.smartcli.ts +++ b/ts/smartcli.classes.smartcli.ts @@ -123,10 +123,11 @@ export class Smartcli { /** * start the process of evaluating commands + * @param testArgv - Optional argv override for testing (bypasses automatic runtime detection) */ - public startParse(): void { + public startParse(testArgv?: string[]): void { // Get user arguments, properly handling Node.js, Deno (run/compiled), and Bun - const userArgs = getUserArgs(); + const userArgs = testArgv ? getUserArgs(testArgv) : getUserArgs(); const parsedYArgs = plugins.yargsParser(userArgs); const wantedCommand = parsedYArgs._[0]; diff --git a/ts/smartcli.helpers.ts b/ts/smartcli.helpers.ts index 7a68f74..73b3d26 100644 --- a/ts/smartcli.helpers.ts +++ b/ts/smartcli.helpers.ts @@ -13,19 +13,15 @@ export function getUserArgs(argv?: string[]): string[] { // Prefer Deno.args when available and no custom argv provided; // it's the most reliable for Deno run and compiled. + // Deno.args is ALWAYS correct in Deno environments - it handles the internal bundle path automatically. // deno-lint-ignore no-explicit-any const g: any = typeof globalThis !== 'undefined' ? globalThis : {}; - // Check if we should use Deno.args - // Skip Deno.args if process.argv has been manipulated (test scenario detection) - const processArgv = typeof process !== 'undefined' && Array.isArray(process.argv) ? process.argv : []; - const argvLooksManipulated = processArgv.length > 2 && g.Deno && g.Deno.args; - - if (!useProvidedArgv && g.Deno && g.Deno.args && Array.isArray(g.Deno.args) && !argvLooksManipulated) { + if (!useProvidedArgv && g.Deno && g.Deno.args && Array.isArray(g.Deno.args)) { return g.Deno.args.slice(); } - const a = argv ?? processArgv; + const a = argv ?? (typeof process !== 'undefined' && Array.isArray(process.argv) ? process.argv : []); if (!Array.isArray(a) || a.length === 0) return [];