Some upgrades to the way octokit and logs are handled

This commit is contained in:
Adam Matthiesen 2024-03-14 02:41:12 -07:00
parent 9f6c52a45d
commit 66dfb8e8f5
No known key found for this signature in database
GPG Key ID: 3F53281CB3936013
9 changed files with 195 additions and 37 deletions

View File

@ -56,7 +56,9 @@ import { defineConfig } from "astro/config";
export default defineConfig({ export default defineConfig({
+ integrations: [astroGist({ + integrations: [astroGist({
// Allows you to set the default theme // Allows you to set the default theme
theme: ['catppuccin-macchiato'] theme: ['catppuccin-macchiato'],
// Allows you to enable verbose logging
verbose: false,
+ })] + })]
}); });
``` ```

View File

@ -3,8 +3,10 @@ export type PageData = {
blockGroupIndex: number blockGroupIndex: number
} }
// Map of request to page data
const pageDataMap = new Map<Request, PageData>() const pageDataMap = new Map<Request, PageData>()
// Get the page data for a request
export function getPageData(request: Request): PageData { export function getPageData(request: Request): PageData {
let data = pageDataMap.get(request) let data = pageDataMap.get(request)
if (!data) { if (!data) {

View File

@ -2,8 +2,10 @@ import { pluginLineNumbers } from '@expressive-code/plugin-line-numbers'
import { ExpressiveCode, loadShikiTheme, type BundledShikiTheme } from 'expressive-code' import { ExpressiveCode, loadShikiTheme, type BundledShikiTheme } from 'expressive-code'
import config from "virtual:astro-gists/config"; import config from "virtual:astro-gists/config";
// Export defined components
export { default as Code } from './components/Code.astro' export { default as Code } from './components/Code.astro'
// Create a custom instance of ExpressiveCode
export const engine = new ExpressiveCode({ export const engine = new ExpressiveCode({
themes: [ themes: [
config.theme ? config.theme ?

View File

@ -17,11 +17,14 @@ export interface Props {
wrap?: boolean; wrap?: boolean;
} }
// Extracting the Props
const { gistId, filename, wrap, showLineNumbers } = Astro.props as Props; const { gistId, filename, wrap, showLineNumbers } = Astro.props as Props;
// Setting the Defaults
const WRAP = wrap ? wrap : wrap === undefined ? true : false; const WRAP = wrap ? wrap : wrap === undefined ? true : false;
const SLN = showLineNumbers ? showLineNumbers : showLineNumbers === undefined ? true : false; const SLN = showLineNumbers ? showLineNumbers : showLineNumbers === undefined ? true : false;
// Fetching the Gist
const Gist = await getGistFile( gistId, filename); const Gist = await getGistFile( gistId, filename);
--- ---

View File

@ -15,13 +15,17 @@ export interface Props {
wrap?: boolean; wrap?: boolean;
} }
// extract the props
const { gistId, wrap, showLineNumbers } = Astro.props as Props; const { gistId, wrap, showLineNumbers } = Astro.props as Props;
// set the defaults
const WRAP = wrap ? wrap : wrap === undefined ? true : false; const WRAP = wrap ? wrap : wrap === undefined ? true : false;
const SLN = showLineNumbers ? showLineNumbers : showLineNumbers === undefined ? true : false; const SLN = showLineNumbers ? showLineNumbers : showLineNumbers === undefined ? true : false;
// get the Gist
const Gist = await getGistGroup(gistId); const Gist = await getGistGroup(gistId);
// extract the files
const files = Gist.files; const files = Gist.files;
--- ---
{ Gist && ( { Gist && (

View File

@ -14,6 +14,10 @@ export const optionsSchema = z.object({
* All available themes are listed in the [Shiki documentation](https://shiki.matsu.io/docs/themes). * All available themes are listed in the [Shiki documentation](https://shiki.matsu.io/docs/themes).
*/ */
theme: z.custom<BundledShikiTheme>().optional(), theme: z.custom<BundledShikiTheme>().optional(),
}); /**
* Optional: Allows the user to enable verbose logging.
*/
verbose: z.boolean().optional(),
}).optional().default({});
export type astroGistsUserConfig = z.infer<typeof optionsSchema> export type astroGistsUserConfig = z.infer<typeof optionsSchema>

View File

@ -1,8 +1,23 @@
import { defineIntegration, createResolver } from "astro-integration-kit" import { defineIntegration, createResolver } from "astro-integration-kit"
import { corePlugins } from "astro-integration-kit/plugins" import { corePlugins } from "astro-integration-kit/plugins"
import { isThereAToken, TOKEN_MISSING_ERROR } from "./lib"
import { optionsSchema } from "./index" import { optionsSchema } from "./index"
import { readFileSync } from "node:fs"; 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. * Astro-Gist - An Astro.js integration for embedding GitHub Gists in your Astro.js project.
@ -12,27 +27,81 @@ export default defineIntegration({
optionsSchema, optionsSchema,
plugins: [...corePlugins], plugins: [...corePlugins],
setup({ options }) { 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 { return {
"astro:config:setup": ({ "astro:config:setup": ({
watchIntegration, addVirtualImports, logger, addDts 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 // WATCH INTEGRATION FOR CHANGES
watchIntegration(resolve()) watchIntegration(resolve())
// Check for GITHUB_PERSONAL_TOKEN // Check for GITHUB_PERSONAL_TOKEN
if (!isThereAToken) {configSetup.warn(TOKEN_MISSING_ERROR)} if (!isThereAToken()) {
ignoreVerboseLoggerCheck("warn",TOKEN_MISSING_ERROR)
}
// Add virtual imports // Add virtual imports
verboseLogger("info", "Adding virtual imports.");
addVirtualImports({ addVirtualImports({
"virtual:astro-gists/config": `export default ${JSON.stringify(options)}`, "virtual:astro-gists/config": `export default ${JSON.stringify(options)}`,
"astro-gists:components": `export * from "@matthiesenxyz/astro-gists/components";` "astro-gists:components": `export * from "@matthiesenxyz/astro-gists/components";`
}); });
// Add .d.ts file
verboseLogger("info", "Injecting astro-gists.d.ts file.");
addDts({ addDts({
name: "astro-gists", name: "astro-gists",
content: readFileSync(resolve("./stubs/astro-gists.d.ts"), "utf-8") content: readFileSync(resolve("./stubs/astro-gists.d.ts"), "utf-8")
@ -40,20 +109,53 @@ export default defineIntegration({
}, },
"astro:config:done": ({ logger }) => { "astro:config:done": ({ logger }) => {
const configDone = logger.fork("astro-gists/config:done") // Create a logger for the config done event
configDone.info("Astro Gists Integration Loaded.") 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 }) => { "astro:server:setup": ({ logger }) => {
const serverSetup = logger.fork("astro-gists/server:setup") // Create a logger for the server setup event
serverSetup.info("Setting up Astro Gists Integration for Development.") 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 }) => { "astro:build:start": ({ logger }) => {
const buildStart = logger.fork("astro-gists/build:start") // Create a logger for the build start event
buildStart.info("Building Astro Gists Integration.") 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 }) => { "astro:build:done": ({ logger }) => {
const buildDone = logger.fork("astro-gists/build:done") // Create a logger for the build done event
buildDone.info("Astro Gists Integration Built.") const buildDone = logger.fork("astro-gists : done")
// Log that the build is complete
gistLogger(
buildDone,
"info",
"Build for Astro Gists Integration is complete.",
true
);
} }
} }
} }

View File

@ -2,21 +2,43 @@ import { Octokit } from "octokit";
import type { OctokitResponse } from "@octokit/types"; import type { OctokitResponse } from "@octokit/types";
import { loadEnv } from "vite"; import { loadEnv } from "vite";
import pRretry from 'p-retry'; 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 // Load environment variables
const { GITHUB_PERSONAL_TOKEN } = loadEnv("all", process.cwd(), "GITHUB_"); 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 // Create an Octokit instance
const octokit = new Octokit({ auth: GITHUB_PERSONAL_TOKEN }); 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) => const retry: typeof pRretry = (fn, opts) =>
pRretry(fn, { pRretry(fn, {
onFailedAttempt: (e) => onFailedAttempt: (e) =>
console.log(`[Astro-Gists] Attempt ${e.attemptNumber} failed. There are ${e.retriesLeft} retries left.\n `, gistLogger("warn",
e.message `Attempt ${e.attemptNumber} failed. There are ${e.retriesLeft} retries left.\n ${e.message}`,
), false),
retries: 3, retries: 3,
...opts, ...opts,
}); });
@ -38,20 +60,37 @@ function handleResponse(response: OctokitResponse<any>) {
case 200: case 200:
return response.data; return response.data;
case 404: case 404:
return "Gist not found."; return "E404";
case 403: case 403:
return "You have exceeded the rate limit for requests to the GitHub API. Please try again later."; return "E403";
case 500: case 500:
return "An internal server error occurred. Please try again later."; return "E500";
default: default:
return "An error occurred. Please try again later."; return "E000";
} }
} }
// Gist Grabber // Gist Grabber
const gistGrabber = async (gistId: string) => { const gistGrabber = async (gistId: string) => {
const response = await retry(() => octokit.request('GET /gists/{gist_id}', { gist_id: gistId })); 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); return handleResponse(response);
} }