From 9970036d203ba2d0a46b35ba6fad21d49441cdd4 Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Sun, 27 Jul 2025 17:03:10 -0700 Subject: hai --- lib/process/argv.ts | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 lib/process/argv.ts (limited to 'lib/process/argv.ts') diff --git a/lib/process/argv.ts b/lib/process/argv.ts new file mode 100644 index 0000000..396fa96 --- /dev/null +++ b/lib/process/argv.ts @@ -0,0 +1,79 @@ +import { Either, type Mapper, type IEither, Optional } from '@emprespresso/pengueno'; + +export const isArgKey = (k: string): k is K => k.startsWith('--'); + +interface ArgHandler { + absent?: V; + unspecified?: V; + present: Mapper; +} + +export const getArg = ( + arg: K, + argv: Array, + whenValue: ArgHandler, +): IEither => { + const argIndex = Optional.from(argv.findIndex((_argv) => isArgKey(_argv) && _argv.split('=')[0] === arg)).filter( + (index) => index >= 0 && index < argv.length, + ); + if (!argIndex.present()) { + return Optional.from(whenValue.absent) + .map((v) => Either.right(v)) + .orSome(() => + Either.left( + new Error(`arg ${arg} is not present in arguments list and does not have an 'absent' value`), + ), + ) + .get(); + } + + return argIndex + .flatMap((idx) => + Optional.from(argv.at(idx)).map((_argv) => (_argv.includes('=') ? _argv.split('=')[1] : argv.at(idx + 1))), + ) + .filter((next) => !isArgKey(next)) + .map((next) => whenValue.present(next)) + .orSome(() => whenValue.unspecified) + .map((v) => Either.right(v)) + .get(); +}; + +type MappedArgs< + Args extends ReadonlyArray, + Handlers extends Partial>>, +> = { + [K in Args[number]]: K extends keyof Handlers ? (Handlers[K] extends ArgHandler ? T : string) : string; +}; + +export const argv = < + const Args extends ReadonlyArray, + const Handlers extends Partial>>, +>( + args: Args, + handlers?: Handlers, + argv = process.argv.slice(2), +): IEither> => { + type Result = MappedArgs; + + const defaultHandler: ArgHandler = { present: (value: string) => value }; + + const processArg = (arg: Args[number]): IEither => { + const handler = handlers?.[arg] ?? defaultHandler; + return getArg(arg, argv, handler).mapRight((value) => [arg, value] as const); + }; + + const res = args + .map(processArg) + .reduce( + (acc: IEither>, current: IEither) => + acc.flatMap((accValue) => + current.mapRight(([key, value]) => ({ + ...accValue, + [key]: value, + })), + ), + Either.right(>{}), + ) + .mapRight((result) => result); + return res; +}; -- cgit v1.2.3-70-g09d2