From 5f75aa34e6bd946623d2212cdb68a78238be3db8 Mon Sep 17 00:00:00 2001 From: Carlos Scheidegger Date: Tue, 3 Dec 2024 09:51:34 -0700 Subject: [PATCH] allow 'info' to not error in quarto check --- src/command/check/check.ts | 24 +++++++++++++++--------- src/command/check/cmd.ts | 18 ++++-------------- src/typing/dynamic.ts | 27 +++++++++++++++++++++++++++ tests/unit/typing/dynamic.test.ts | 19 +++++++++++++++++++ 4 files changed, 65 insertions(+), 23 deletions(-) create mode 100644 src/typing/dynamic.ts create mode 100644 tests/unit/typing/dynamic.test.ts diff --git a/src/command/check/check.ts b/src/command/check/check.ts index 65571392bf..9cc4085b83 100644 --- a/src/command/check/check.ts +++ b/src/command/check/check.ts @@ -47,16 +47,20 @@ import { notebookContext } from "../../render/notebook/notebook-context.ts"; import { typstBinaryPath } from "../../core/typst.ts"; import { quartoCacheDir } from "../../core/appdirs.ts"; import { isWindows } from "../../deno_ral/platform.ts"; +import { checkStringEnum } from "../../typing/dynamic.ts"; -const kIndent = " "; +export const kTargets = [ + "install", + "info", + "jupyter", + "knitr", + "versions", + "all", +] as const; +export type Target = typeof kTargets[number]; +export const checkTargetType = checkStringEnum(...kTargets); -export type Target = - | "install" - | "jupyter" - | "knitr" - | "versions" - | "info" - | "all"; +const kIndent = " "; export async function check(target: Target): Promise { const services = renderServices(notebookContext()); @@ -82,7 +86,9 @@ export async function check(target: Target): Promise { } } -// Currently this doesn't check anything, but +// Currently this doesn't check anything +// but it's a placeholder for future checks +// and the message is useful for troubleshooting async function checkInfo(_services: RenderServices) { const cacheDir = quartoCacheDir(); completeMessage("Checking environment information..."); diff --git a/src/command/check/cmd.ts b/src/command/check/cmd.ts index 0c8fdb06ae..66061bbffb 100644 --- a/src/command/check/cmd.ts +++ b/src/command/check/cmd.ts @@ -4,12 +4,8 @@ * Copyright (C) 2021-2022 Posit Software, PBC */ -import { error } from "../../deno_ral/log.ts"; - import { Command } from "cliffy/command/mod.ts"; -import { check, Target } from "./check.ts"; - -const kTargets = ["install", "jupyter", "knitr", "versions", "all"]; +import { check, checkTargetType } from "./check.ts"; export const checkCommand = new Command() .name("check") @@ -22,13 +18,7 @@ export const checkCommand = new Command() .example("Check Jupyter engine", "quarto check jupyter") .example("Check Knitr engine", "quarto check knitr") .example("Check installation and all engines", "quarto check all") - .action(async (_options: unknown, target?: string) => { - target = target || "all"; - if (!kTargets.includes(target)) { - error( - "Invalid target '" + target + "' (valid targets are " + - kTargets.join(", ") + ").", - ); - } - await check(target as Target); + .action(async (_options: unknown, targetStr?: string) => { + targetStr = targetStr || "all"; + await check(checkTargetType(targetStr)); }); diff --git a/src/typing/dynamic.ts b/src/typing/dynamic.ts new file mode 100644 index 0000000000..7d7ee22411 --- /dev/null +++ b/src/typing/dynamic.ts @@ -0,0 +1,27 @@ +/* + * dynamic.ts + * + * Tools for managing the interface between dynamic and static typing + * in Quarto. + * + * Ideally, every usage of `any` or `as` would appear in this file. + * + * Copyright (C) 2024 Posit Software, PBC + */ + +import { DynamicTypeCheckError } from "../core/lib/error.ts"; + +export const checkStringEnum = ( + ...values: T[] +): (value: string) => T => { + const valueSet: Set = new Set(values); + return (value: string): T => { + if (!valueSet.has(value)) { + throw new DynamicTypeCheckError( + "Invalid value '" + value + "' (valid values are " + + values.join(", ") + ").", + ); + } + return value as unknown as T; + }; +}; diff --git a/tests/unit/typing/dynamic.test.ts b/tests/unit/typing/dynamic.test.ts new file mode 100644 index 0000000000..1b8422dcba --- /dev/null +++ b/tests/unit/typing/dynamic.test.ts @@ -0,0 +1,19 @@ +/* +* dynamic.test.ts +* +* Copyright (C) 2024 Posit Software, PBC +* +*/ + +import { checkStringEnum } from "../../../src/typing/dynamic.ts"; +import { unitTest } from "../../test.ts"; +import { assert, assertThrows } from "testing/asserts"; + +// deno-lint-ignore require-await +unitTest("checkStringEnum", async () => { + const check = checkStringEnum("a", "b", "c"); + assert(check("a") === "a"); + assert(check("b") === "b"); + assert(check("c") === "c"); + assertThrows(() => check("d"), Error, "Invalid value 'd' (valid values are a, b, c)."); +}); \ No newline at end of file