From 66dfb8e8f5a2b4f6ec9686f5c8f8bb4546cbd198 Mon Sep 17 00:00:00 2001 From: Adam Matthiesen Date: Thu, 14 Mar 2024 02:41:12 -0700 Subject: [PATCH] Some upgrades to the way octokit and logs are handled --- package/README.md | 4 +- .../ExpressiveCode/components/page-data.ts | 2 + package/src/ExpressiveCode/index.ts | 2 + package/src/components/GetGist.astro | 3 + package/src/components/GetGistGroup.astro | 4 + package/src/index.ts | 6 +- package/src/integration.ts | 130 ++++++++++++++++-- package/src/lib/index.ts | 2 +- package/src/lib/octokit.ts | 79 ++++++++--- 9 files changed, 195 insertions(+), 37 deletions(-) diff --git a/package/README.md b/package/README.md index 6ab3500..f7b9c5a 100644 --- a/package/README.md +++ b/package/README.md @@ -56,7 +56,9 @@ import { defineConfig } from "astro/config"; export default defineConfig({ + integrations: [astroGist({ // Allows you to set the default theme - theme: ['catppuccin-macchiato'] + theme: ['catppuccin-macchiato'], + // Allows you to enable verbose logging + verbose: false, + })] }); ``` diff --git a/package/src/ExpressiveCode/components/page-data.ts b/package/src/ExpressiveCode/components/page-data.ts index f332b3f..8c7ca4f 100644 --- a/package/src/ExpressiveCode/components/page-data.ts +++ b/package/src/ExpressiveCode/components/page-data.ts @@ -3,8 +3,10 @@ export type PageData = { blockGroupIndex: number } +// Map of request to page data const pageDataMap = new Map() +// Get the page data for a request export function getPageData(request: Request): PageData { let data = pageDataMap.get(request) if (!data) { diff --git a/package/src/ExpressiveCode/index.ts b/package/src/ExpressiveCode/index.ts index cb0b267..3db5bd9 100644 --- a/package/src/ExpressiveCode/index.ts +++ b/package/src/ExpressiveCode/index.ts @@ -2,8 +2,10 @@ import { pluginLineNumbers } from '@expressive-code/plugin-line-numbers' import { ExpressiveCode, loadShikiTheme, type BundledShikiTheme } from 'expressive-code' import config from "virtual:astro-gists/config"; +// Export defined components export { default as Code } from './components/Code.astro' +// Create a custom instance of ExpressiveCode export const engine = new ExpressiveCode({ themes: [ config.theme ? diff --git a/package/src/components/GetGist.astro b/package/src/components/GetGist.astro index 4778481..aeb6f9f 100644 --- a/package/src/components/GetGist.astro +++ b/package/src/components/GetGist.astro @@ -17,11 +17,14 @@ export interface Props { wrap?: boolean; } +// Extracting the Props const { gistId, filename, wrap, showLineNumbers } = Astro.props as Props; +// Setting the Defaults const WRAP = wrap ? wrap : wrap === undefined ? true : false; const SLN = showLineNumbers ? showLineNumbers : showLineNumbers === undefined ? true : false; +// Fetching the Gist const Gist = await getGistFile( gistId, filename); --- diff --git a/package/src/components/GetGistGroup.astro b/package/src/components/GetGistGroup.astro index 5d1f060..c36e6b4 100644 --- a/package/src/components/GetGistGroup.astro +++ b/package/src/components/GetGistGroup.astro @@ -15,13 +15,17 @@ export interface Props { wrap?: boolean; } +// extract the props const { gistId, wrap, showLineNumbers } = Astro.props as Props; +// set the defaults const WRAP = wrap ? wrap : wrap === undefined ? true : false; const SLN = showLineNumbers ? showLineNumbers : showLineNumbers === undefined ? true : false; +// get the Gist const Gist = await getGistGroup(gistId); +// extract the files const files = Gist.files; --- { Gist && ( diff --git a/package/src/index.ts b/package/src/index.ts index 45cb777..609ba83 100644 --- a/package/src/index.ts +++ b/package/src/index.ts @@ -14,6 +14,10 @@ export const optionsSchema = z.object({ * All available themes are listed in the [Shiki documentation](https://shiki.matsu.io/docs/themes). */ theme: z.custom().optional(), -}); + /** + * Optional: Allows the user to enable verbose logging. + */ + verbose: z.boolean().optional(), +}).optional().default({}); export type astroGistsUserConfig = z.infer \ No newline at end of file diff --git a/package/src/integration.ts b/package/src/integration.ts index 921c1f3..7bab769 100644 --- a/package/src/integration.ts +++ b/package/src/integration.ts @@ -1,9 +1,24 @@ import { defineIntegration, createResolver } from "astro-integration-kit" import { corePlugins } from "astro-integration-kit/plugins" -import { isThereAToken, TOKEN_MISSING_ERROR } from "./lib" import { optionsSchema } from "./index" import { readFileSync } from "node:fs"; +import type { AstroIntegrationLogger } from "astro"; +import { loadEnv } from "vite"; +// Load environment variables +const { GITHUB_PERSONAL_TOKEN } = loadEnv("all", process.cwd(), "GITHUB_"); + +// Check if there is a GitHub Personal Token +export const isThereAToken = () => { + if (!GITHUB_PERSONAL_TOKEN) { + return false; + } + return true; + } + +// Error message if the token is missing +export const TOKEN_MISSING_ERROR = "GITHUB_PERSONAL_TOKEN not found. Please add it to your .env file. Without it, you will be limited to 60 requests per hour."; + /** * Astro-Gist - An Astro.js integration for embedding GitHub Gists in your Astro.js project. */ @@ -12,27 +27,81 @@ export default defineIntegration({ optionsSchema, plugins: [...corePlugins], setup({ options }) { - const { resolve } = createResolver(import.meta.url) + // Create resolve helper + const { resolve } = createResolver(import.meta.url); + + // Check if verbose logging is enabled + const isVerbose = options.verbose; + + // Create Gist Logger interface + const gistLogger = async ( + logger: AstroIntegrationLogger, + type: "info"|"warn"|"error", + message: string, + checkVerbose: boolean, + ) => { + // if checkVerbose is true and isVerbose is true, log the message + if (checkVerbose && isVerbose) { + if (type === "info") { + logger.info(message); + } else if (type === "warn") { + logger.warn(message); + } else if (type === "error") { + logger.error(message); + } + } + // if checkVerbose is false, force log the message + if (!checkVerbose) { + if (type === "info") { + logger.info(message); + } else if (type === "warn") { + logger.warn(message); + } else if (type === "error") { + logger.error(message); + } + } }; return { "astro:config:setup": ({ watchIntegration, addVirtualImports, logger, addDts }) => { - logger.info("Setting up Astro Gists Integration.") - const configSetup = logger.fork("astro-gists/config:setup") - + + // Create a logger for the setup events + const configLogger = logger.fork("astro-gists : setup"); + + // Create a verbose logger + const verboseLogger = ( + type: "info"|"warn"|"error", + message:string + ) => gistLogger(configLogger, type, message, true); + + // Create a logger that ignores the verbose check + const ignoreVerboseLoggerCheck = ( + type: "info"|"warn"|"error", + message:string + ) => gistLogger(configLogger, type, message, false); + + ignoreVerboseLoggerCheck("info", "Setting up Astro Gists Integration."); + + verboseLogger("warn","Verbose logging is enabled.") + // WATCH INTEGRATION FOR CHANGES watchIntegration(resolve()) // Check for GITHUB_PERSONAL_TOKEN - if (!isThereAToken) {configSetup.warn(TOKEN_MISSING_ERROR)} + if (!isThereAToken()) { + ignoreVerboseLoggerCheck("warn",TOKEN_MISSING_ERROR) + } // Add virtual imports + verboseLogger("info", "Adding virtual imports."); addVirtualImports({ "virtual:astro-gists/config": `export default ${JSON.stringify(options)}`, "astro-gists:components": `export * from "@matthiesenxyz/astro-gists/components";` }); + // Add .d.ts file + verboseLogger("info", "Injecting astro-gists.d.ts file."); addDts({ name: "astro-gists", content: readFileSync(resolve("./stubs/astro-gists.d.ts"), "utf-8") @@ -40,20 +109,53 @@ export default defineIntegration({ }, "astro:config:done": ({ logger }) => { - const configDone = logger.fork("astro-gists/config:done") - configDone.info("Astro Gists Integration Loaded.") + // Create a logger for the config done event + const configDone = logger.fork("astro-gists : setup-done") + + // Log that the configuration is complete + gistLogger( + configDone, + "info", + "Configuration for Astro Gists Integration is complete.", + false + ); + }, "astro:server:setup": ({ logger }) => { - const serverSetup = logger.fork("astro-gists/server:setup") - serverSetup.info("Setting up Astro Gists Integration for Development.") + // Create a logger for the server setup event + const serverSetup = logger.fork("astro-gists : dev") + + // Log that the server is being set up + gistLogger( + serverSetup, + "info", + "Setting up Astro Gists Integration for development.", + true + ); }, "astro:build:start": ({ logger }) => { - const buildStart = logger.fork("astro-gists/build:start") - buildStart.info("Building Astro Gists Integration.") + // Create a logger for the build start event + const buildStart = logger.fork("astro-gists : build") + + // Log that the build is starting + gistLogger( + buildStart, + "info", + "Starting Build for Astro Gists Integration.", + true + ); }, "astro:build:done": ({ logger }) => { - const buildDone = logger.fork("astro-gists/build:done") - buildDone.info("Astro Gists Integration Built.") + // Create a logger for the build done event + const buildDone = logger.fork("astro-gists : done") + + // Log that the build is complete + gistLogger( + buildDone, + "info", + "Build for Astro Gists Integration is complete.", + true + ); } } } diff --git a/package/src/lib/index.ts b/package/src/lib/index.ts index 3ded18b..8a420de 100644 --- a/package/src/lib/index.ts +++ b/package/src/lib/index.ts @@ -1 +1 @@ -export * from "./octokit"; \ No newline at end of file +export * from "./octokit"; diff --git a/package/src/lib/octokit.ts b/package/src/lib/octokit.ts index 7269f8d..b991b77 100644 --- a/package/src/lib/octokit.ts +++ b/package/src/lib/octokit.ts @@ -2,21 +2,43 @@ import { Octokit } from "octokit"; import type { OctokitResponse } from "@octokit/types"; import { loadEnv } from "vite"; import pRretry from 'p-retry'; +import config from "virtual:astro-gists/config"; + +// Load config options to check if verbose logging is enabled +const isVerbose = config.verbose; + +// Create Gist Logger interface +const gistLogger = async ( + type: "info"|"warn"|"error", + message: string, + VerboseCheck: boolean + ) => { + // if checkVerbose is true and isVerbose is true, log the message + if (VerboseCheck && isVerbose) { + if (type === "info") { + console.log(`[astro-gists : octokit] ${message}`); + } else if (type === "warn") { + console.log(`[WARN] [astro-gists : octokit] ${message}`); + } else if (type === "error") { + console.log(`[ERROR] [astro-gists : octokit] ${message}`); + } + } + + if (!VerboseCheck) { + if (type === "info") { + console.log(`[astro-gists : octokit]" ${message}`); + } else if (type === "warn") { + console.log(`[WARN] [astro-gists : octokit] ${message}`); + } else if (type === "error") { + console.log(`[ERROR] [astro-gists : octokit] ${message}`); + } + } + + }; // Load environment variables const { GITHUB_PERSONAL_TOKEN } = loadEnv("all", process.cwd(), "GITHUB_"); -// Check if there is a GitHub Personal Token -export const isThereAToken = () => { - if (!GITHUB_PERSONAL_TOKEN) { - return false; - } - return true; -} - -// Error message if the token is missing -export const TOKEN_MISSING_ERROR = "GITHUB_PERSONAL_TOKEN not found. Please add it to your .env file. Without it, you will be limited to 60 requests per hour."; - // Create an Octokit instance const octokit = new Octokit({ auth: GITHUB_PERSONAL_TOKEN }); @@ -24,9 +46,9 @@ const octokit = new Octokit({ auth: GITHUB_PERSONAL_TOKEN }); const retry: typeof pRretry = (fn, opts) => pRretry(fn, { onFailedAttempt: (e) => - console.log(`[Astro-Gists] Attempt ${e.attemptNumber} failed. There are ${e.retriesLeft} retries left.\n `, - e.message - ), + gistLogger("warn", + `Attempt ${e.attemptNumber} failed. There are ${e.retriesLeft} retries left.\n ${e.message}`, + false), retries: 3, ...opts, }); @@ -38,20 +60,37 @@ function handleResponse(response: OctokitResponse) { case 200: return response.data; case 404: - return "Gist not found."; + return "E404"; case 403: - return "You have exceeded the rate limit for requests to the GitHub API. Please try again later."; + return "E403"; case 500: - return "An internal server error occurred. Please try again later."; + return "E500"; default: - return "An error occurred. Please try again later."; + return "E000"; } } - // Gist Grabber const gistGrabber = async (gistId: string) => { const response = await retry(() => octokit.request('GET /gists/{gist_id}', { gist_id: gistId })); - + if (handleResponse(response) === "E404") { + gistLogger("error", `Gist ${gistId} not found.`, false); + return null; + } + if (handleResponse(response) === "E403") { + gistLogger("error", "Rate limit exceeded. Please try again later.", false); + return null; + } + if (handleResponse(response) === "E500") { + gistLogger("error", "Internal server error. Please try again later.", false); + return null; + } + if (handleResponse(response) === "E000") { + gistLogger("error", "An unknown error occurred. Please try again later.", false); + return null; + } + if (handleResponse(response) === response.data) { + gistLogger("info", `Gist ${gistId} found.`, true); + } return handleResponse(response); }