aboutsummaryrefslogtreecommitdiff
path: root/src/args.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/args.ts')
-rw-r--r--src/args.ts97
1 files changed, 93 insertions, 4 deletions
diff --git a/src/args.ts b/src/args.ts
index 31fa2ee..d233c18 100644
--- a/src/args.ts
+++ b/src/args.ts
@@ -1,9 +1,98 @@
+import * as E from "fp-ts/lib/Either";
+import * as O from "fp-ts/lib/Option";
+import * as R from "fp-ts/lib/ReadonlyArray";
+import { pipe } from "fp-ts/lib/function";
+import { parseTestType, type TestType } from "./canary";
+
export interface Args {
- testFile: string;
+ readonly testsFile: string;
+ readonly testName: O.Option<string>;
+ readonly testType: O.Option<TestType>;
+}
+
+interface ArgsBuilder {
+ readonly testsFile: O.Option<string>;
+ readonly testName: O.Option<string>;
+ readonly testType: O.Option<string>;
}
-export const parseArgs = (argv: string[]): Args => {
- const useful = argv.slice(2); // skip bun path and script path
+type ArgsBuilderField = (arg: string) => (builder: ArgsBuilder) => ArgsBuilder;
+
+const createArgsBuilder = (): ArgsBuilder => ({
+ testsFile: O.none,
+ testName: O.none,
+ testType: O.none,
+});
+
+const withTestsFile: ArgsBuilderField = (testsFile) => (builder) => ({
+ ...builder,
+ testsFile: O.some(testsFile),
+});
+
+const withTestName: ArgsBuilderField = (testName) => (builder) => ({
+ ...builder,
+ testName: O.some(testName),
+});
+
+const withTestType: ArgsBuilderField = (testType) => (builder) => ({
+ ...builder,
+ testType: O.some(testType),
+});
+
+const flagBuilders: Record<string, ArgsBuilderField> = {
+ "--tests-file": withTestsFile,
+ "--test-name": withTestName,
+ "--test-type": withTestType,
+};
+
+const buildArgs = (builder: ArgsBuilder): E.Either<string, Args> => {
+ if (O.isNone(builder.testsFile)) {
+ return E.left("please specify a test file");
+ }
+
+ const testType = pipe(builder.testType, O.flatMap(parseTestType));
+ if (O.isSome(builder.testType) && !O.isSome(testType)) {
+ return E.left("bad test type " + builder.testType.value);
+ }
+
+ return E.right({
+ testsFile: builder.testsFile.value,
+ testName: builder.testName,
+ testType,
+ });
+};
+
+const isArg = (arg: string) => arg.startsWith("--") && arg in flagBuilders;
+
+export const parseArgs = (argv: string[]): E.Either<string, Args> => {
+ if (argv.length < 2) return E.left("bad argv");
+
+ const useful = argv.slice(2);
+ const argApplicators = pipe(
+ useful,
+ R.mapWithIndex((i, arg) => (isArg(arg) ? O.some({ arg, i }) : O.none)),
+ R.compact,
+ R.map(({ arg, i }) =>
+ pipe(
+ O.fromNullable(flagBuilders[arg]),
+ O.bindTo("argApplicator"),
+ O.bind("val", () =>
+ pipe(
+ O.fromNullable(useful.at(i + 1)),
+ O.flatMap((argValue) =>
+ isArg(argValue) ? O.none : O.some(argValue),
+ ),
+ ),
+ ),
+ O.map(({ val, argApplicator }) => argApplicator(val)),
+ ),
+ ),
+ );
- const flags = useful.map((x, i) => x.startsWith("--") && i);
+ return pipe(
+ argApplicators,
+ R.compact,
+ R.reduce(createArgsBuilder(), (builder, applyArgTo) => applyArgTo(builder)),
+ buildArgs,
+ );
};