From 879d4de542038d5e9910de149307fb8434a04cd1 Mon Sep 17 00:00:00 2001 From: Clay Tercek <30105080+claytercek@users.noreply.github.com> Date: Tue, 26 Nov 2024 15:51:20 -0500 Subject: [PATCH] more verbose error logging --- .changeset/chilled-badgers-confess.md | 6 +++ packages/cli/src/utils/command-utils.ts | 26 +++++------- .../content/src/sources/contentful-source.ts | 42 ++++++++++++------- packages/content/src/sources/strapi-source.ts | 36 ++++++++++------ 4 files changed, 67 insertions(+), 43 deletions(-) create mode 100644 .changeset/chilled-badgers-confess.md diff --git a/.changeset/chilled-badgers-confess.md b/.changeset/chilled-badgers-confess.md new file mode 100644 index 00000000..24e86c34 --- /dev/null +++ b/.changeset/chilled-badgers-confess.md @@ -0,0 +1,6 @@ +--- +"@bluecadet/launchpad-content": patch +"@bluecadet/launchpad-cli": patch +--- + +More verbose error logging, plus better messages on source configs with unions diff --git a/packages/cli/src/utils/command-utils.ts b/packages/cli/src/utils/command-utils.ts index ad579820..95d4721a 100644 --- a/packages/cli/src/utils/command-utils.ts +++ b/packages/cli/src/utils/command-utils.ts @@ -1,5 +1,5 @@ import path from "node:path"; -import { LogManager, type Logger, TTY_FIXED_END } from "@bluecadet/launchpad-utils"; +import { LogManager, type Logger, NO_TTY, TTY_FIXED_END } from "@bluecadet/launchpad-utils"; import chalk from "chalk"; import { ResultAsync, err, errAsync, ok } from "neverthrow"; import { ZodError } from "zod"; @@ -74,26 +74,20 @@ function logFullErrorChain(logger: Logger | Console, error: Error) { `${chalk.red("┌─")} ${chalk.red.bold(currentError.name)}: ${chalk.red(getPrettyMessage(currentError))}`, ); const callstack = currentError.stack; - // logger.error(`${chalk.red(callstack ? '│' : '└')} `); + if (callstack) { + logger.error(`${chalk.red("│")}`); + const lines = callstack.split("\n").slice(1); - // log up to 3 lines of the callstack - let loggedLines = 0; + for (const line of lines) { - const isLastLine = loggedLines === lines.length - 1 || loggedLines > 2; - logger.error( - `${chalk.red("│")} ${chalk.red.dim(isLastLine && lines.length > 3 ? "..." : line.trim())}`, - ); - if (isLastLine) { - logger.error(`${chalk.red("└──────────────────")}`); - } - loggedLines++; - - if (loggedLines > 3) { - break; - } + logger.error(`${chalk.red("│")} ${chalk.red.dim(line)}`); } + + logger.error(`${chalk.red("│")}`); + logger.error(`${chalk.red("└──────────────────")}`); } + if (currentError.cause && currentError.cause instanceof Error) { currentError = currentError.cause; logger.error(` ${chalk.red.dim("│")} ${chalk.red.dim("Caused by:")}`); diff --git a/packages/content/src/sources/contentful-source.ts b/packages/content/src/sources/contentful-source.ts index 8007fc75..4d853686 100644 --- a/packages/content/src/sources/contentful-source.ts +++ b/packages/content/src/sources/contentful-source.ts @@ -4,21 +4,33 @@ import { fetchPaginated } from "../utils/fetch-paginated.js"; import { defineSource } from "./source.js"; // If deliveryToken is provided, then previewToken is optional. -const contentfulCredentialsSchema = z.union([ - z.object({ - /** Content delivery token (all published content). */ - deliveryToken: z.string().describe("Content delivery token (all published content)."), - /** Content preview token (only unpublished/draft content). */ - previewToken: z - .string() - .optional() - .describe("Content preview token (only unpublished/draft content)."), - }), - z.object({ - /** Content preview token (only unpublished/draft content). */ - previewToken: z.string().describe("Content preview token (only unpublished/draft content)."), - }), -]); +const contentfulCredentialsSchema = z.union( + [ + z.object({ + /** Content delivery token (all published content). */ + deliveryToken: z.string().describe("Content delivery token (all published content)."), + /** Content preview token (only unpublished/draft content). */ + previewToken: z + .string() + .optional() + .describe("Content preview token (only unpublished/draft content)."), + }), + z.object({ + /** Content preview token (only unpublished/draft content). */ + previewToken: z.string().describe("Content preview token (only unpublished/draft content)."), + }), + ], + { + errorMap: (error) => { + if (error.code === "invalid_union") + return { + message: "You must provide either a `deliveryToken` or a `previewToken`.", + }; + + return { message: error.message ?? "" }; + }, + }, +); const contentfulSourceSchema = z .object({ diff --git a/packages/content/src/sources/strapi-source.ts b/packages/content/src/sources/strapi-source.ts index c83263b6..97ec493a 100644 --- a/packages/content/src/sources/strapi-source.ts +++ b/packages/content/src/sources/strapi-source.ts @@ -5,18 +5,30 @@ import { z } from "zod"; import { fetchPaginated } from "../utils/fetch-paginated.js"; import { defineSource } from "./source.js"; -const strapiCredentialsSchema = z.union([ - z.object({ - /** Username or email. Should be configured via `./.env.local` */ - identifier: z.string().describe("Username or email. Should be configured via `./.env.local`"), - /** Password. Should be configured via `./.env.local` */ - password: z.string().describe("Password. Should be configured via `./.env.local`"), - }), - z.object({ - /** A previously generated JWT token. */ - token: z.string().describe("A previously generated JWT token."), - }), -]); +const strapiCredentialsSchema = z.union( + [ + z.object({ + /** Username or email. Should be configured via `./.env.local` */ + identifier: z.string().describe("Username or email. Should be configured via `./.env.local`"), + /** Password. Should be configured via `./.env.local` */ + password: z.string().describe("Password. Should be configured via `./.env.local`"), + }), + z.object({ + /** A previously generated JWT token. */ + token: z.string().describe("A previously generated JWT token."), + }), + ], + { + errorMap: (error) => { + if (error.code === "invalid_union") + return { + message: "Either `identifier` and `password` OR a `token` must be provided.", + }; + + return { message: error.message ?? "" }; + }, + }, +); const strapiSourceSchema = z .object({