import { Either, type IEither } from "@emprespresso/pengueno"; export const isArgKey = (k: string): k is K => k.startsWith("--"); export const getArg = ( arg: K, args: Array, ): IEither => { const result = args.findIndex((_arg) => _arg.startsWith(arg)); if (result < 0) return Either.left(new Error("no argument found for " + arg)); const [resultArg, next]: Array = [ args[result], args.at(result + 1), ]; if (resultArg && resultArg.includes("=")) { return Either.right(resultArg.split("=")[1] as V); } if (typeof next === "undefined") return Either.left(new Error("no value specified for " + arg)); if (isArgKey(next)) return Either.left( new Error("next value for arg " + arg + " is another arg " + next), ); return Either.right(next as V); }; type ObjectFromList, V = string> = { [K in T extends ReadonlyArray ? U : never]: V; }; export const argv = ( args: ReadonlyArray, defaultArgs?: Partial>, argv = Deno.args, ) => { return args .map((arg) => [arg, getArg(arg, argv)] as [K, IEither]) .map(([arg, specified]): [K, IEither] => [ arg, specified.fold(({ isLeft, isRight, value}): IEither => { if (isRight) { return Either.right(value); } const hasDefaultVal = isLeft && defaultArgs && arg in defaultArgs; if (hasDefaultVal) { return Either.right(defaultArgs[arg]!); } return Either.left(value); }), ]) .reduce( ( acc: IEither>, x: [K, IEither], ): IEither> => { const [arg, eitherVal] = x; return acc.flatMap((args) => { return eitherVal.mapRight((envValue) => ({ ...args, [arg]: envValue, })); }); }, Either.right({} as ObjectFromList), ); };