From b20152c3e11db9e15c6e2a18bbde595cfc99bb32 Mon Sep 17 00:00:00 2001 From: nxu Date: Tue, 13 Dec 2022 05:40:41 +0800 Subject: [PATCH] Version 1.0.0 --- .github/workflows/auto-update.yml | 39 +++++++ .gitignore | 6 + changelog.md | 2 + config.json | 4 + package.json | 22 ++++ src/app.ts | 167 +++++++++++++++++++++++++++ src/interface/IConfig.ts | 4 + src/interface/IEmoji.ts | 23 ++++ src/interface/IGithubEmoji.ts | 3 + src/interface/IUnicode.ts | 16 +++ src/utilities.ts | 180 ++++++++++++++++++++++++++++++ tsconfig.json | 18 +++ yarn.lock | 174 +++++++++++++++++++++++++++++ 13 files changed, 658 insertions(+) create mode 100644 .github/workflows/auto-update.yml create mode 100644 .gitignore create mode 100644 changelog.md create mode 100644 config.json create mode 100644 package.json create mode 100644 src/app.ts create mode 100644 src/interface/IConfig.ts create mode 100644 src/interface/IEmoji.ts create mode 100644 src/interface/IGithubEmoji.ts create mode 100644 src/interface/IUnicode.ts create mode 100644 src/utilities.ts create mode 100644 tsconfig.json create mode 100644 yarn.lock diff --git a/.github/workflows/auto-update.yml b/.github/workflows/auto-update.yml new file mode 100644 index 0000000..f32de72 --- /dev/null +++ b/.github/workflows/auto-update.yml @@ -0,0 +1,39 @@ +name: Auto Update +on: + push: + branches: + - main + paths-ignore: + - "README.md" + pull_request: + branches: + - main + schedule: + - cron: "0 0 * * 7" +jobs: + build: + runs-on: ubuntu-latest + env: + AUTO_COMMIT_MESSAGE: Auto Update by GitHub Actions + AUTO_COMMIT_AUTHOR: github-actions[bot] + AUTO_COMMIT_EMAIL: github-actions[bot]@users.noreply.github.com + steps: + - uses: actions/checkout@v3 + + - uses: actions/setup-node@v3 + with: + node-version: '16' + cache: 'yarn' + - name: Install Dependencies + run: yarn --frozen-lockfile + - name: Generate the GitHub Emoji Icon List Markdown + run: yarn start + + # Commit and push the README.md + - name: Update the README.md (Commit and Push) + run: | + git config --global user.name "${{ env.AUTO_COMMIT_AUTHOR }}" + git config --global user.email "${{ env.AUTO_COMMIT_EMAIL }}" + git add README.md + git commit -m "${{ env.AUTO_COMMIT_MESSAGE }}" + git push diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c50c3df --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +# Dependency directories +node_modules/ + +# IDE config +.vscode/ +.idea/ diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..240886c --- /dev/null +++ b/changelog.md @@ -0,0 +1,2 @@ +### Version 1.0.0 +- Initial version diff --git a/config.json b/config.json new file mode 100644 index 0000000..b3367c3 --- /dev/null +++ b/config.json @@ -0,0 +1,4 @@ +{ + "GitHub_Emojis_List": "https://api.github.com/emojis", + "Unicode_Emojis_Data": "https://unicode.org/Public/emoji/15.0/emoji-test.txt" +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..295c9ed --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "github-emoji-icon-list", + "version": "1.0.0", + "description": "Generate GitHub Emoji Icon list in Markdown format.", + "homepage": "https://github.com/jasonfoknxu/github-emoji-icon-list", + "author": "jasonfoknxu (https://nxuweb.net)", + "main": "src/app.ts", + "license": "MIT", + "repository": "github:jasonfoknxu/github-emoji-icon-list", + "private": false, + "scripts": { + "start": "ts-node --files src/app.ts" + }, + "devDependencies": { + "@types/node": "^18.11.12", + "typescript": "^4.9.3" + }, + "dependencies": { + "ts-node": "^10.9.1", + "axios": "^1.2.1" + } +} diff --git a/src/app.ts b/src/app.ts new file mode 100644 index 0000000..0992410 --- /dev/null +++ b/src/app.ts @@ -0,0 +1,167 @@ +/** + * add Generator + * - Version: 1.0.0 + * - Developer: NXU (GitHub: @jasonfoknxu) + * - https://github.com/jasonfoknxu/github-emoji-icon-list + */ + +import * as Utils from './utilities'; + +(async () => { + // Get the config from config file + const config: IConfig = await Utils.getConfig(); + // Get the GitHub Emoji Icon List + const githubEmojisData: IGithubEmoji = await Utils.get(config.GitHub_Emojis_List); + // Get the Unicode Emoji Data + const unicodeEmojisData = await Utils.get(config.Unicode_Emojis_Data); + + // Stop if no GitHub emoji list or Unicode data + if (!githubEmojisData || !unicodeEmojisData) { + Utils.log('Failed to get the GitHub Emoji List or Unicode Emoji Data.', 'e'); + process.exit(1); + } + + // Handle the GitHub emoji from the GitHub Emoji Icon List + let githubEmojis: IGithubEmoji = {}; + for (const [shortcode, url] of Object.entries(githubEmojisData)) { + githubEmojis[shortcode] = Utils.base(url).toUpperCase(); + } + + // Process the Unicode emoji data from the Unicode Emoji Data text + const unicodeEmojiLines = unicodeEmojisData.split(/\r?\n/); + let unicodeEmojis: IUnicodeEmojiData = {}; + let group, subgroup, emojiGroups = [], emojiSubgroups = [], emojiCount = 0; + for (let i = 0; i < unicodeEmojiLines.length; i++) { + const parseResult = Utils.parse(unicodeEmojiLines[i]); + if (!parseResult) { continue; } + if (parseResult.type === 'group') { + group = parseResult.name; + emojiGroups.push(group); + } else if (parseResult.type === 'subgroup') { + subgroup = parseResult.name; + emojiSubgroups.push(subgroup); + } else if (parseResult.type === 'emoji') { + if (!parseResult.unicode) { continue; } + unicodeEmojis[parseResult.unicode] = { + name: parseResult.name, + group: group ?? '', + subgroup: subgroup ?? '', + order: emojiCount++ + }; + } + } + + // Group the GitHub emoji with the Unicode emoji information + let emojis: IEmojiGroup = {}, customGroup: ICustomEmoji[] = []; + for (const [shortcode, unicode] of Object.entries(githubEmojis)) { + const emojiData = unicodeEmojis[unicode]; + if (!emojiData || emojiData.group === '') { + customGroup.push({unicode: unicode, shortcode: shortcode}); + } else if (emojiData.group !== '') { + if (!emojis[emojiData.group]) { + emojis[emojiData.group] = {}; + } + if (emojiData.subgroup !== '') + if (!emojis[emojiData.group][emojiData.subgroup]) { + emojis[emojiData.group][emojiData.subgroup] = []; + } + const emojiToAdd = {unicode: unicode, shortcode: shortcode, name: emojiData.name, order: emojiData.order}; + // Ordering the emoji within the subgroup + const index = emojis[emojiData.group][emojiData.subgroup].findIndex((emoji) => { + return emoji.order > emojiToAdd.order; + }); + if (index > -1) { + emojis[emojiData.group][emojiData.subgroup].splice(index, 0, emojiToAdd); + } else { + emojis[emojiData.group][emojiData.subgroup].splice(emojis[emojiData.group][emojiData.subgroup].length, 0, emojiToAdd); + } + } + } + + // Sort the emoji from group and subgroup + let organizedEmoji: EmojiGroup[] = []; + for (const group in emojis) { + let sortedEmojiSubgroups: EmojiSubgroup[] = []; + for (const subgroup in emojis[group]) { + sortedEmojiSubgroups.push([emojiSubgroups.indexOf(subgroup), subgroup, emojis[group][subgroup]]); + } + sortedEmojiSubgroups = sortedEmojiSubgroups.sort((a, b) => { + return a[0] - b[0]; + }); + organizedEmoji.push([emojiGroups.indexOf(group), group, sortedEmojiSubgroups]); + } + organizedEmoji = organizedEmoji.sort((a, b) => { + return a[0] - b[0]; + }); + + // Create the Markdown + let markdown = '', tableOfContents = '## Table of Contents\n', tocColumns = []; + // Build the Markdown format + for (let i = 0; i < organizedEmoji.length; i++) { + const groupTitle = organizedEmoji[i][1]; + markdown += `## ${groupTitle}\n\n`; + + if (tocColumns.length > 0) { + tableOfContents += `|${tocColumns.join('|')}|\n`; + tocColumns = []; + } + tableOfContents += `\n- ${Utils.anchor(groupTitle)})\n\n`; + tableOfContents += `| | | | | |\n`; + tableOfContents += `|:-----:|:-----:|:-----:|:-----:|:-----:|\n`; + + const subgroups = organizedEmoji[i][2]; + for (let j = 0; j < subgroups.length; j++) { + const subgroupTitle = subgroups[j][1]; + markdown += `### ${Utils.title(subgroupTitle)}\n\n`; + markdown += `|Emoji|Shortcode|Description|\n`; + markdown += `|:---:|:-----:|:---|\n`; + + const emojiInGroup = subgroups[j][2]; + for (let k = 0; k < emojiInGroup.length; k++) { + const emoji = emojiInGroup[k]; + markdown += `|:${emoji.shortcode}:|\`:${emoji.shortcode}:\`|${emoji.name}|\n`; + } + markdown += `\n\n`; + markdown += Utils.anchor(':top: Back to Top', 'github-emoji-icon-list'); + markdown += `\n\n`; + + tocColumns.push(Utils.anchor(`:${emojiInGroup[0].shortcode}: ${Utils.title(subgroupTitle)}`, subgroupTitle)); + if (tocColumns.length > 4) { + tableOfContents += `|${tocColumns.join('|')}|\n`; + tocColumns = []; + } + } + + if (tocColumns.length > 0) { + tableOfContents += `|${tocColumns.join('|')}|\n`; + tocColumns = []; + } + } + + // Add GitHub Custom Emoji + tableOfContents += `\n- ${Utils.anchor('GitHub Custom Emoji')}\n\n`; + + markdown += `### GitHub Custom Emoji\n\n`; + markdown += `|Emoji|Shortcode|\n`; + markdown += `|:---:|:-----:|\n`; + for (let x = 0; x < customGroup.length; x++) { + const emoji = customGroup[x]; + markdown += `|:${emoji.shortcode}:|\`:${emoji.shortcode}:\`|\n`; + } + markdown += `\n\n`; + markdown += Utils.anchor(':top: Back to Top', 'github-emoji-icon-list'); + markdown += `\n`; + + // Add Table of Contents + markdown = tableOfContents + '\n\n' + markdown; + + // Introduction + markdown = `This list includes all the usable Emoji icon shortcodes in GitHub Markdown. The list is automatically generated from [GitHub Emoji API](${config.GitHub_Emojis_List}) with the information from [Unicode Emoji data file](${config.Unicode_Emojis_Data}).\n\nThe first column is the emoji icon, second column is the shortcode for Markdown, third column is the name of the emoji from the Unicode data.\n\n*The emoji may be displayed in different result on various system*\n\n` + markdown; + + // Heading + markdown = `# GitHub Emoji Icon List\n\n` + markdown; + + // Write to file README.md + await Utils.writeFile('README.md', markdown); + +})(); diff --git a/src/interface/IConfig.ts b/src/interface/IConfig.ts new file mode 100644 index 0000000..6e78e8b --- /dev/null +++ b/src/interface/IConfig.ts @@ -0,0 +1,4 @@ +interface IConfig { + GitHub_Emojis_List: string, + Unicode_Emojis_Data: string +} diff --git a/src/interface/IEmoji.ts b/src/interface/IEmoji.ts new file mode 100644 index 0000000..92b1f48 --- /dev/null +++ b/src/interface/IEmoji.ts @@ -0,0 +1,23 @@ +interface IEmoji { + unicode: string, + shortcode?: string, + name: string, + order: number +} + +interface IEmojiGroup { + [groupname: string]: IEmojiSubgroup +} + +interface IEmojiSubgroup { + [subgroupname: string]: IEmoji[] +} + +interface ICustomEmoji { + unicode: string, + shortcode: string +} + +type EmojiSubgroup = [suborder: number, subgroup: string, emoji: IEmoji[]]; + +type EmojiGroup = [order: number, group: string, subgroups: EmojiSubgroup[]]; diff --git a/src/interface/IGithubEmoji.ts b/src/interface/IGithubEmoji.ts new file mode 100644 index 0000000..77b51e0 --- /dev/null +++ b/src/interface/IGithubEmoji.ts @@ -0,0 +1,3 @@ +interface IGithubEmoji { + [shortcode: string]: string +} diff --git a/src/interface/IUnicode.ts b/src/interface/IUnicode.ts new file mode 100644 index 0000000..3be5401 --- /dev/null +++ b/src/interface/IUnicode.ts @@ -0,0 +1,16 @@ +interface IUnicode { + type: string, + name: string, + unicode?: string +} + +interface IUnicodeEmojiData { + [unicode: string]: IUnicodeEmoji +} + +interface IUnicodeEmoji { + name: string, + group: string, + subgroup: string, + order: number +} diff --git a/src/utilities.ts b/src/utilities.ts new file mode 100644 index 0000000..3077c34 --- /dev/null +++ b/src/utilities.ts @@ -0,0 +1,180 @@ +/** + * Utilities of GitHub Emoji Icon List Markdown Generator + */ + +import {promises as fs} from 'fs'; +import axios from 'axios'; +import path from 'path'; + +/** + * Get the config from the config file + * + * @param filename - The file name of the config file (in project root dir) + * @param format - The file extension of the config file (normally is JSON) + * + * @returns The parsed config from the JSON-formatted config file + */ +const getConfig = async (filename: string = 'config', format: string = 'json'): Promise => { + try { + const readConfig: string = await fs.readFile(path.join(__dirname, '../', `${filename}.${format}`), 'utf8'); + return JSON.parse(readConfig); + } catch (err) { + log('Failed to read the config file.', 'e'); + console.log(err); + process.exit(); + } +}; + +/** + * Perform a HTTP/HTTPS get request + * + * @param url - The URL of the request + * + * @returns The responsive result of the request + */ +const get = async (url: string) => { + return (await axios.get(url)).data ?? null; +}; + +/** + * Extract the unicode form the urls in the GitHub emoji icon list + * + * @param url - The URL of a GitHub emoji icon + * @param extension - The extension of the GitHUb emoji icon + * + * @returns The unicode of a GitHub emoji + */ +const base = (url: string, extension: string = '.png'): string => { + if (url.includes('?')) { + url = url.split('?')[0]; + } + return path.basename(url, extension); +}; + +/** + * Parser to extract the data from the Unicode Emojis Data text + * + * @param text - A line of the Unicode Emojis text + * + * @returns The parsed result of the line of Unicode Emoji text + */ +const parse = (text: string): IUnicode | null => { + // Format: {code points}; {status} # {emoji} E{emoji version} {name} + const dataRegex = /^(.+)\s+;.+#.+E[\d.]+\s+(.+)$/i; + const dataMatch = text.match(dataRegex); + if (dataMatch !== null) { + // \u200d is the joiner unicode which is not used in GitHub icon file naming + const unicode = dataMatch[1].trim().replace(/\s200D/g, '').replace(/\s/g, '-').toUpperCase(); + return {type: 'emoji', name: dataMatch[2].trim(), unicode: unicode}; + } + const subgroupRegex = /^#\s+subgroup:\s+(.+)$/i; + const subgroupMatch = text.match(subgroupRegex); + if (subgroupMatch !== null) { + return {type: 'subgroup', name: subgroupMatch[1].trim()}; + } + const groupRegex = /^#\s+group:\s+(.+)$/i; + const groupMatch = text.match(groupRegex); + if (groupMatch !== null) { + return {type: 'group', name: groupMatch[1].trim()}; + } + return null; +}; + +/** + * Formatting a title (Uppercase first character of each word) + * + * @param text - The original text for the title + * + * @returns The formatted title + */ +const title = (text: string): string => { + text = text.replace(/-/g, ' '); + if (text.includes(' ')) { + const words = text.split(' '); + return words.map((word) => { + return word[0].toUpperCase() + word.substring(1); + }).join(' '); + } + return text[0].toUpperCase() + text.substring(1); +}; + +/** + * Convert the unicode to Emoji symbol + * + * @param unicode - The Unicode + * + * @returns The Emoji symbol + */ +const toEmoji = (unicode: string): string => { + if (unicode.includes('-')) { + const codes = unicode.split('-'); + return codes.map((u) => { + return String.fromCodePoint(parseInt(u, 16)); + }).join(''); + } + return String.fromCodePoint(parseInt(unicode, 16)); +}; + +/** + * Create a Markdown Anchor + * + * @param displayText - The text for the anchor + * @param anchorPoint - The named anchor point to be linked + * + * @returns The anchor point Markdown + */ +const anchor = (displayText: string, anchorPoint: string = '') => { + if (anchorPoint === '') { + anchorPoint = displayText; + } + return `[${displayText}](#${anchorPoint.toLowerCase().replace(/\s/g, '-').replace(/&/g, '')})`; +}; + +/** + * Write content to a file + * + * @param filepath - The path of the file (in project root directory) + * @param content - The content to be written to the file + * + */ +const writeFile = async (filepath: string, content: string) => { + await fs.writeFile(path.join(__dirname, '../', `${filepath}`), content); +}; + +/** + * Log for message (Display in the console only) + * + * @param message - The text to be logged + * @param type - The type of the log + * + */ +const log = (message: string, type: string = '') => { + let msgType; + switch (type.toLowerCase()) { + case 'i': + msgType = 'INFO'; + break; + case 'e': + msgType = 'ERROR'; + break; + case 'w': + msgType = 'WARNING'; + break; + default: + msgType = 'MESSAGE'; + } + console.log(`[${msgType}] ${timeNow()} | ${message}`); +}; + +/** + * Get current date time with format YYYY-MM-DD HH:mm:ss + * + * @returns The formatted datetime + */ +const timeNow = (): string => { + const d: Date = new Date(); + return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}`; +}; + + +export {getConfig, get, base, parse, title, toEmoji, anchor, writeFile, log, timeNow}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..65e716f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "es2020", + "module": "commonjs", + "rootDir": "src", + "typeRoots": ["./src/interface"], + "types": ["node"], + "outDir": "dist", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true + }, + "include": [ + "src/*", + "src/*/*" + ] +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..8c5b53a --- /dev/null +++ b/yarn.lock @@ -0,0 +1,174 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" + integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== + +"@types/node@^18.11.12": + version "18.11.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.12.tgz#89e7f8aa8c88abf432f9bd594888144d7dba10aa" + integrity sha512-FgD3NtTAKvyMmD44T07zz2fEf+OKwutgBCEVM8GcvMGVGaDktiLNTDvPwC/LUe3PinMW+X6CuLOF2Ui1mAlSXg== + +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.4.1: + version "8.8.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" + integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +axios@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.2.1.tgz#44cf04a3c9f0c2252ebd85975361c026cb9f864a" + integrity sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +follow-redirects@^1.15.0: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +ts-node@^10.9.1: + version "10.9.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +typescript@^4.9.3: + version "4.9.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.3.tgz#3aea307c1746b8c384435d8ac36b8a2e580d85db" + integrity sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==