diff --git a/src/cards/wakatime-card.ts b/src/cards/wakatime-card.ts index e8713216..440c2b8e 100644 --- a/src/cards/wakatime-card.ts +++ b/src/cards/wakatime-card.ts @@ -11,16 +11,7 @@ import { import { getStyles } from "../getStyles"; import { wakatimeCardLocales } from "../translations"; -/** Import language colors. - * - * @description Here we use the workaround found in - * https://stackoverflow.com/questions/66726365/how-should-i-import-json-in-node - * since vercel is using v16.14.0 which does not yet support json imports without the - * --experimental-json-modules flag. - */ -import { createRequire } from "module"; -const require = createRequire(import.meta.url); -const languageColors = require("../common/languageColorson"); // now works +import languageColors from "../common/languageColors.json"; /** * @param {{color: string, text: string}} param0 diff --git a/src/common/Card.ts b/src/common/Card.ts index b78a5a4c..43a40d89 100644 --- a/src/common/Card.ts +++ b/src/common/Card.ts @@ -1,7 +1,78 @@ import { getAnimations } from "../getStyles"; import { encodeHTML, flexLayout } from "./utils"; -class Card { +/** Card colors. */ +export interface CardColors { + /** Title color. */ + titleColor: string; + /** Text color. */ + textColor: string; + /** Icon color. */ + iconColor: string; + /** Background color. */ + bgColor: string; + /** Border color. */ + borderColor: string; +} + +/** Accessibility label. */ +interface AccessibilityLabel { + /** The label to display. */ + title: string; + /** The value to display. */ + desc: string; +} + +/** Card properties. */ +interface CardProps { + /** Card width. */ + width: number; + /** Card height. */ + height: number; + /** Card border radius. */ + border_radius: number; + /** Card colors. */ + colors: CardColors | {}; + /** Card title. */ + customTitle?: string; + /** Card default title. */ + defaultTitle?: string; + /** Card title prefix icon. */ + titlePrefixIcon?: string; +} + +/** + * Card class. + */ +export class Card { + /** Card width. */ + width: number; + /** Card height. */ + height: number; + /** Whether the card border is hidden. */ + hideBorder: boolean; + /** Whether the card title is hidden. */ + hideTitle: boolean; + /** Border radius. */ + border_radius: number; + /** Card colors. */ + colors: CardColors | {}; + /** Card title. */ + title: string; + /** Card css. */ + css: string; + /** Card x padding. */ + paddingX: number; + /** Card y padding. */ + paddingY: number; + /** Card title prefix icon. */ + titlePrefixIcon?: string; + /** Whether the card is animated. */ + animations: boolean; + /** Accessibility label title. */ + a11yTitle: string; + /** Accessibility label description. */ + a11yDesc: string; /** * @param {object} args * @param {number?=} args.width @@ -20,7 +91,7 @@ class Card { customTitle, defaultTitle = "", titlePrefixIcon, - }) { + }: CardProps) { this.width = width; this.height = height; @@ -53,7 +124,7 @@ class Card { /** * @param {{title: string, desc: string}} prop */ - setAccessibilityLabel({ title, desc }) { + setAccessibilityLabel({ title, desc }: AccessibilityLabel) { this.a11yTitle = title; this.a11yDesc = desc; } @@ -61,21 +132,21 @@ class Card { /** * @param {string} value */ - setCSS(value) { + setCSS(value: string) { this.css = value; } /** * @param {boolean} value */ - setHideBorder(value) { + setHideBorder(value: boolean) { this.hideBorder = value; } /** * @param {boolean} value */ - setHideTitle(value) { + setHideTitle(value: boolean) { this.hideTitle = value; if (value) { this.height -= 30; @@ -85,7 +156,7 @@ class Card { /** * @param {string} text */ - setTitle(text) { + setTitle(text: string) { this.title = text; } @@ -137,7 +208,7 @@ class Card { gradientTransform="rotate(${this.colors.bgColor[0]})" gradientUnits="userSpaceOnUse" > - ${gradients.map((grad, index) => { + ${gradients.map((grad: string, index: number) => { let offset = (index * 100) / (gradients.length - 1); return ``; })} @@ -150,7 +221,7 @@ class Card { /** * @param {string} body */ - render(body) { + render(body: string) { return ` >; + +/** + * I18n translation class. + */ +export class I18n { + /** The language locale. */ + locale?: string; + /** The translations object. */ + translations: Translations; + /** The fallback language locale. */ + fallbackLocale: string; + + constructor({ + locale, + translations, + }: { + locale?: string; + translations: Translations; + }) { this.locale = locale; this.translations = translations; this.fallbackLocale = "en"; } - t(str) { + t(str: string) { if (!this.translations[str]) { throw new Error(`${str} Translation string not found`); } @@ -17,6 +35,3 @@ class I18n { return this.translations[str][this.locale || this.fallbackLocale]; } } - -export { I18n }; -export default I18n; diff --git a/src/common/blacklist.ts b/src/common/blacklist.ts index 752ef943..5752af03 100644 --- a/src/common/blacklist.ts +++ b/src/common/blacklist.ts @@ -1,4 +1,2 @@ -const blacklist = ["renovate-bot", "technote-space", "sw-yx"]; - -export { blacklist }; -export default blacklist; +/** User blacklist. */ +export const blacklist = ["renovate-bot", "technote-space", "sw-yx"]; diff --git a/src/common/createProgressNode.ts b/src/common/createProgressNode.ts index edfc7b14..23b3dddd 100644 --- a/src/common/createProgressNode.ts +++ b/src/common/createProgressNode.ts @@ -1,11 +1,19 @@ import { clampValue } from "./utils"; -interface IcreateProgressNode { + +/** CreateProgressNode properties. */ +interface CreateProgressNodeProps { + /** Progress bar item x position. */ x: number; + /** Progress bar item y position.. */ y: number; + /** Progress bar item width. */ width: number; + /** Progress bar item color. */ color: string; + /** Progress value. */ progress: number; + /** Progress bar item background color. */ progressBarBackgroundColor: string; } @@ -16,7 +24,7 @@ const createProgressNode = ({ color, progress, progressBarBackgroundColor, -}: IcreateProgressNode) => { +}: CreateProgressNodeProps) => { const progressPercentage = clampValue(progress, 2, 100); return ` diff --git a/src/common/icons.ts b/src/common/icons.ts index 5282a93e..6eca62a3 100644 --- a/src/common/icons.ts +++ b/src/common/icons.ts @@ -1,4 +1,7 @@ -const icons = { + +export type Icons = {[key: string]: string}; + +const icons: Icons = { star: ``, commits: ``, prs: ``, diff --git a/src/common/retryer.ts b/src/common/retryer.ts index 13b7021a..dee5933e 100644 --- a/src/common/retryer.ts +++ b/src/common/retryer.ts @@ -1,5 +1,22 @@ +import axios, { + AxiosError, + AxiosPromise, + AxiosRequestHeaders, + AxiosResponse, +} from "axios"; import { CustomError, logger } from "./utils"; + +/** Data fetcher. */ +type Fetcher = ( + /** Fetcher variables. */ + variables: AxiosRequestHeaders, + /** Authentication token. */ + token: string, + /** The number of retries. */ + retries?: number, +) => AxiosPromise + /** * Try to execute the fetcher function until it succeeds or the max number of retries is reached. * @@ -9,7 +26,11 @@ import { CustomError, logger } from "./utils"; * @param {number} retryerParams.retries How many times to retry. * @returns Promise */ -const retryer = async (fetcher, variables, retries = 0) => { +export const retryer = async ( + fetcher: Fetcher, + variables: AxiosRequestHeaders, + retries = 0, +): Promise => { if (retries > 7) { throw new CustomError("Maximum retries exceeded", CustomError.MAX_RETRY); } @@ -17,7 +38,7 @@ const retryer = async (fetcher, variables, retries = 0) => { // try to fetch with the first token since RETRIES is 0 index i'm adding +1 let response = await fetcher( variables, - process.env[`PAT_${retries + 1}`], + process.env[`PAT_${retries + 1}`] as string, retries, ); @@ -36,18 +57,17 @@ const retryer = async (fetcher, variables, retries = 0) => { // finally return the response return response; } catch (err) { - // prettier-ignore - // also checking for bad credentials if any tokens gets invalidated - const isBadCredential = err.response.data && err.response.data.message === "Bad credentials"; + if (axios.isAxiosError(err)) { + // prettier-ignore + // also checking for bad credentials if any tokens gets invalidated + const isBadCredential = err?.response?.data && err.response.data.message === "Bad credentials"; - if (isBadCredential) { - logger.log(`PAT_${retries + 1} Failed`); - retries++; - // directly return from the function - return retryer(fetcher, variables, retries); + if (isBadCredential) { + logger.log(`PAT_${retries + 1} Failed`); + retries++; + // directly return from the function + return retryer(fetcher, variables, retries); + } } } }; - -export { retryer }; -export default retryer; diff --git a/src/common/utils.ts b/src/common/utils.ts index 99b1eeca..32495970 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -1,15 +1,16 @@ // @ts-check -import axios from "axios"; +import axios, { AxiosRequestConfig, AxiosRequestHeaders } from "axios"; import toEmoji from "emoji-name-map"; import wrap from "word-wrap"; import { themes } from "../../themes/index"; +import type { ThemeEnum } from "../../themes/index"; /** * @param {string} message * @param {string} secondaryMessage * @returns {string} */ -const renderError = (message, secondaryMessage = "") => { +const renderError = (message: string, secondaryMessage = "") => { return `