diff --git a/.eslintrc.js b/.eslintrc.js index c452bf23..d7ac74ba 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -226,7 +226,7 @@ module.exports = { }, }, { - files: ['**/scripts/**', '*.spec.ts'], + files: ['**/scripts/**', '*.spec.ts', 'packages/create-*/**'], rules: { 'no-console': 'off', 'no-restricted-imports': 'off', diff --git a/packages/create-bot/README.md b/packages/create-bot/README.md new file mode 100644 index 00000000..7a7106e3 --- /dev/null +++ b/packages/create-bot/README.md @@ -0,0 +1,9 @@ +# @mtcute/create-bot + +Starter kit for creating bots using `@mtcute/node`. + +## Usage + +```bash +pnpm create @mtcute/bot +``` diff --git a/packages/create-bot/package.json b/packages/create-bot/package.json new file mode 100644 index 00000000..35b48d81 --- /dev/null +++ b/packages/create-bot/package.json @@ -0,0 +1,26 @@ +{ + "name": "@mtcute/create-bot", + "private": true, + "version": "1.0.0", + "description": "Bot starter kit for mtcute", + "author": "Alina Sireneva ", + "license": "MIT", + "type": "module", + "scripts": { + "build": "pnpm run -w build-package node", + "run": "ts-node-esm src/main.ts" + }, + "bin": { + "create-bot": "./dist/main.js" + }, + "dependencies": { + "chalk": "^5.3.0", + "glob": "10.2.6", + "handlebars": "^4.7.8", + "inquirer": "9.2.11", + "open": "9.1.0" + }, + "devDependencies": { + "@types/inquirer": "^9.0.6" + } +} diff --git a/packages/create-bot/src/cli.ts b/packages/create-bot/src/cli.ts new file mode 100644 index 00000000..78e548d3 --- /dev/null +++ b/packages/create-bot/src/cli.ts @@ -0,0 +1,135 @@ +import chalk from 'chalk' +import inquirer from 'inquirer' +import open from 'open' + +import { readConfig, UserConfigPersisted, writeConfig } from './config.js' +import { TELEGRAM_APPS_PAGE } from './constants.js' +import { getFeatureChoices } from './features/cli.js' +import { MtcuteFeature } from './features/types.js' + +interface UserConfigAnswers { + reuse?: boolean + apiId?: string + apiHash?: string + botToken?: string + features: MtcuteFeature[] +} + +export interface UserConfig extends UserConfigPersisted { + name: string + botToken?: string + features: MtcuteFeature[] +} + +export async function askForConfigPersisted(): Promise { + const existing = await readConfig() + + if (existing) { + const { reuse } = await inquirer.prompt([ + { + type: 'confirm', + name: 'reuse', + message: 'Found existing config, do you want to reuse it?', + default: true, + }, + ]) + + if (reuse) return existing + } + + const answers = await inquirer.prompt([ + { + type: 'input', + name: 'apiId', + message: 'API ID (press Enter to obtain one):', + validate: (v: string) => { + if (!v) { + setTimeout(() => void open(TELEGRAM_APPS_PAGE), 1000) + + return [ + chalk.italic(`Opening ${chalk.blue(TELEGRAM_APPS_PAGE)}...`), + `๐Ÿ”’ Log in with your ${chalk.blueBright('Telegram')} account`, + '๐Ÿ“ Fill out the form:', + ` - ${chalk.bold('App title, short name')}: anything you want, can be changed later`, + ` - ${chalk.bold('Platform')}: doesn't matter`, + ` - ${chalk.bold('URL')}: can be left blank`, + `๐Ÿš€ Click ${chalk.bold('Create application')}`, + `${chalk.bold.red('โ— DO NOT')} share your API hash with anyone, as it can't be revoked`, + ].join('\n') + } + if (!/^\d+$/.test(v)) return 'API ID must be a number' + + return true + }, + }, + { + type: 'input', + name: 'apiHash', + message: 'API hash:', + validate: (v: string) => { + if (!v) return 'API hash is required' + if (!v.match(/^[a-f0-9]{32}$/i)) return 'API hash must be 32 hex characters' + + return true + }, + }, + { + type: 'confirm', + name: 'reuse', + message: 'Do you want to save these credentials for later use?', + default: true, + }, + ]) + + const config: UserConfigPersisted = { + apiId: Number(answers.apiId), + apiHash: answers.apiHash!, + } + + if (answers.reuse) { + await writeConfig(config) + } + + return config +} + +export async function askForConfig(): Promise { + const persisted = await askForConfigPersisted() + + let allowEmptyBotToken = false + const { botToken, features } = await inquirer.prompt([ + { + type: 'input', + name: 'botToken', + message: 'Bot token (optional):', + validate: (v: string) => { + if (!v) { + if (allowEmptyBotToken) return true + + allowEmptyBotToken = true + + return [ + `You most likely need a bot token. You can obtain one from ${chalk.blue('@BotFather')}`, + ` Press ${chalk.bold('Enter')} again if you want to create a ${chalk.magenta('userbot')}`, + ].join('\n') + } + if (!v.match(/^(\d+):[a-z0-9-_]{16,50}$/i)) return 'Invalid bot token' + + return true + }, + }, + { + type: 'checkbox', + choices: getFeatureChoices(), + name: 'features', + message: 'Select features:', + }, + ]) + + return { + ...persisted, + name: '', // will be filled later + botToken: botToken || undefined, + features, + } +} diff --git a/packages/create-bot/src/config.ts b/packages/create-bot/src/config.ts new file mode 100644 index 00000000..8fc289e8 --- /dev/null +++ b/packages/create-bot/src/config.ts @@ -0,0 +1,42 @@ +import { promises as fs } from 'fs' +import { homedir } from 'os' +import * as path from 'path' + +export interface UserConfigPersisted { + apiId: number + apiHash: string +} + +export function getConfigFilePath() { + switch (process.platform) { + case 'linux': + return path.join(homedir(), '.local', 'share', 'mtcute-create.json') + case 'darwin': + return path.join(homedir(), 'Library', 'Application Support', 'mtcute-create.json') + case 'win32': + return path.join(process.env.APPDATA!, 'mtcute-create.json') + } + + throw new Error(`Unsupported platform: ${process.platform}`) +} + +export async function readConfig(): Promise { + const filePath = getConfigFilePath() + + try { + const data = await fs.readFile(filePath, 'utf8') + + return JSON.parse(data) as UserConfigPersisted + } catch (e) { + if (e && typeof e === 'object' && 'code' in e && e.code === 'ENOENT') return null + + throw e + } +} + +export async function writeConfig(config: UserConfigPersisted) { + const filePath = getConfigFilePath() + + await fs.mkdir(path.dirname(filePath), { recursive: true }) + await fs.writeFile(filePath, JSON.stringify(config, null, 2)) +} diff --git a/packages/create-bot/src/constants.ts b/packages/create-bot/src/constants.ts new file mode 100644 index 00000000..e7e902d6 --- /dev/null +++ b/packages/create-bot/src/constants.ts @@ -0,0 +1 @@ +export const TELEGRAM_APPS_PAGE = 'https://my.telegram.org/apps' diff --git a/packages/create-bot/src/dependencies.ts b/packages/create-bot/src/dependencies.ts new file mode 100644 index 00000000..079b1f3d --- /dev/null +++ b/packages/create-bot/src/dependencies.ts @@ -0,0 +1,56 @@ +import { UserConfig } from './cli.js' +import { MtcuteFeature } from './features/types.js' +import { exec } from './utils.js' + +export function buildDependenciesList(config: UserConfig) { + const dependencies = ['@mtcute/node'] + const devDepdenencies = ['dotenv-cli'] + + if (config.features.includes(MtcuteFeature.Dispatcher)) { + dependencies.push('@mtcute/dispatcher') + } + + if (config.features.includes(MtcuteFeature.I18n)) { + dependencies.push('@mtcute/i18n') + } + + if (config.features.includes(MtcuteFeature.NativeAddon)) { + dependencies.push('@mtcute/crypto-node') + } + + if (config.features.includes(MtcuteFeature.TypeScript)) { + devDepdenencies.push('typescript', '@types/node') + } + + if (config.features.includes(MtcuteFeature.Linters)) { + devDepdenencies.push( + 'husky', + 'lint-staged', + 'eslint', + 'eslint-config-prettier', + 'eslint-plugin-ascii', + 'eslint-plugin-import', + 'eslint-plugin-simple-import-sort', + ) + + if (config.features.includes(MtcuteFeature.TypeScript)) { + devDepdenencies.push( + 'eslint-import-resolver-typescript', + '@typescript-eslint/eslint-plugin', + '@typescript-eslint/parser', + ) + } + } + + return { + dependencies, + devDepdenencies, + } +} + +export async function installDependencies(cwd: string, config: UserConfig) { + const { dependencies, devDepdenencies } = buildDependenciesList(config) + + await exec(cwd, 'pnpm', 'add', ...dependencies) + await exec(cwd, 'pnpm', 'add', '--save-dev', ...devDepdenencies) +} diff --git a/packages/create-bot/src/features/cli.ts b/packages/create-bot/src/features/cli.ts new file mode 100644 index 00000000..c1f7a463 --- /dev/null +++ b/packages/create-bot/src/features/cli.ts @@ -0,0 +1,43 @@ +import { CheckboxChoiceOptions } from 'inquirer' + +import { MtcuteFeature } from './types.js' + +export function getFeatureChoices(): CheckboxChoiceOptions[] { + return [ + { + name: ' ๐Ÿš€ Native addon (better performance)', + short: 'Native addon', + value: MtcuteFeature.NativeAddon, + checked: true, + }, + { + name: ' ๐ŸŒ Internationalization', + short: 'i18n', + value: MtcuteFeature.I18n, + }, + { + name: ' ๐Ÿ“จ Event dispatcher', + short: 'Dispatcher', + value: MtcuteFeature.Dispatcher, + checked: true, + }, + { + name: ' ๐Ÿณ Generate Dockerfile', + short: 'Dockerfile', + value: MtcuteFeature.Docker, + checked: true, + }, + { + name: ' โœจ Use TypeScript', + short: 'TypeScript', + value: MtcuteFeature.TypeScript, + checked: true, + }, + { + name: ' ๐Ÿฅฐ Setup Prettier & ESLint', + short: 'Linters', + value: MtcuteFeature.Linters, + checked: true, + }, + ] +} diff --git a/packages/create-bot/src/features/types.ts b/packages/create-bot/src/features/types.ts new file mode 100644 index 00000000..71e8f419 --- /dev/null +++ b/packages/create-bot/src/features/types.ts @@ -0,0 +1,8 @@ +export enum MtcuteFeature { + NativeAddon = 'native_addon', + I18n = 'i18n', + Dispatcher = 'dispatcher', + Docker = 'docker', + TypeScript = 'typescript', + Linters = 'linters', +} diff --git a/packages/create-bot/src/main.ts b/packages/create-bot/src/main.ts new file mode 100644 index 00000000..9f88446d --- /dev/null +++ b/packages/create-bot/src/main.ts @@ -0,0 +1,23 @@ +import { join } from 'node:path' + +import { askForConfig } from './cli.js' +import { installDependencies } from './dependencies.js' +import { runTemplater } from './templater.js' + +const config = await askForConfig() + +const projectName = process.argv[2] + +if (!projectName) { + console.error('Usage: create-mtcute-bot ') + process.exit(1) +} + +config.name = projectName +const outDir = process.env.TARGET_DIR || join(process.cwd(), projectName) + +const __dirname = new URL('.', import.meta.url).pathname + +await runTemplater(join(__dirname, '../template'), outDir, config) + +await installDependencies(outDir, config) diff --git a/packages/create-bot/src/templater.ts b/packages/create-bot/src/templater.ts new file mode 100644 index 00000000..fbcd12e3 --- /dev/null +++ b/packages/create-bot/src/templater.ts @@ -0,0 +1,74 @@ +import * as glob from 'glob' +import Handlebars from 'handlebars' +import { promises as fs } from 'node:fs' +import * as path from 'node:path' + +import type { UserConfig } from './cli.js' +import { MtcuteFeature } from './features/types.js' + +const templater = Handlebars.create() + +const NOEMIT_HEADER = '/* DO NOT EMIT */' +templater.registerHelper({ + emit_if: (cond) => (cond ? '' : NOEMIT_HEADER), + emit_unless: (cond) => (cond ? NOEMIT_HEADER : ''), + eq: (v1, v2) => v1 === v2, + ne: (v1, v2) => v1 !== v2, + lt: (v1, v2) => v1 < v2, + gt: (v1, v2) => v1 > v2, + lte: (v1, v2) => v1 <= v2, + gte: (v1, v2) => v1 >= v2, + not: (v) => !v, + and(...args) { + return Array.prototype.every.call(args, Boolean) + }, + or(...args) { + return Array.prototype.slice.call(args, 0, -1).some(Boolean) + }, +}) + +export async function runTemplaterForFile(file: string, config: UserConfig): Promise { + const content = await fs.readFile(file, 'utf-8') + + const execute = templater.compile(content, { + strict: true, + noEscape: true, + }) + + const result = execute({ + ...config, + features: config.features.reduce>( + (acc, f) => { + acc[f] = true + + return acc + }, + {}, + ), + }) + + if (result.startsWith(NOEMIT_HEADER)) return null + + return result +} + +export async function runTemplater(templateDir: string, outDir: string, config: UserConfig): Promise { + for await (const file of glob.globIterate('**/*', { cwd: templateDir, nodir: true, dot: true })) { + const sourceFile = path.join(templateDir, file) + const destFile = path.join(outDir, file.replace(/\.hbs$/, '')) + + const isTemplate = path.extname(file) === '.hbs' + + if (!isTemplate) { + await fs.mkdir(path.dirname(destFile), { recursive: true }) + await fs.copyFile(sourceFile, destFile) + continue + } + + const result = await runTemplaterForFile(sourceFile, config) + if (result === null) continue + + await fs.mkdir(path.dirname(destFile), { recursive: true }) + await fs.writeFile(destFile, result.trimStart()) + } +} diff --git a/packages/create-bot/src/utils.ts b/packages/create-bot/src/utils.ts new file mode 100644 index 00000000..3820a0d8 --- /dev/null +++ b/packages/create-bot/src/utils.ts @@ -0,0 +1,21 @@ +import chalk from 'chalk' +import * as cp from 'child_process' + +export function exec(cwd: string, ...cmd: string[]) { + return new Promise((resolve, reject) => { + console.log(`${chalk.blue('$')} ${cmd.join(' ')}`) + + const proc = cp.spawn(cmd[0], cmd.slice(1), { + stdio: 'inherit', + cwd, + }) + + proc.on('close', (code) => { + if (code === 0) { + resolve() + } else { + reject(new Error(`Process exited with code ${code}`)) + } + }) + }) +} diff --git a/packages/create-bot/template/.env.example.hbs b/packages/create-bot/template/.env.example.hbs new file mode 100644 index 00000000..f03b3711 --- /dev/null +++ b/packages/create-bot/template/.env.example.hbs @@ -0,0 +1,5 @@ +API_ID= +API_HASH= +{{#if botToken}} +BOT_TOKEN= +{{/if}} \ No newline at end of file diff --git a/packages/create-bot/template/.env.hbs b/packages/create-bot/template/.env.hbs new file mode 100644 index 00000000..89c4aa7d --- /dev/null +++ b/packages/create-bot/template/.env.hbs @@ -0,0 +1,5 @@ +API_ID={{apiId}} +API_HASH={{apiHash}} +{{#if botToken}} +BOT_TOKEN={{botToken}} +{{/if}} \ No newline at end of file diff --git a/packages/create-bot/template/.eslintignore b/packages/create-bot/template/.eslintignore new file mode 100644 index 00000000..b75090a2 --- /dev/null +++ b/packages/create-bot/template/.eslintignore @@ -0,0 +1,7 @@ +node_modules/ +.husky/ +.idea/ + +dist/ + +*.json diff --git a/packages/create-bot/template/.eslintrc.cjs.hbs b/packages/create-bot/template/.eslintrc.cjs.hbs new file mode 100644 index 00000000..6c1905fd --- /dev/null +++ b/packages/create-bot/template/.eslintrc.cjs.hbs @@ -0,0 +1,208 @@ +{{emit_if features.linters}} +module.exports = { + env: { + browser: true, + es2021: true, + node: true, + }, + extends: ['eslint:recommended', 'plugin:import/recommended', 'prettier'], + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + }, + plugins: ['ascii', 'import', 'simple-import-sort'], + reportUnusedDisableDirectives: true, + rules: { + // see https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb-base/rules/style.js#L122 + indent: [ + 2, + 4, + { + SwitchCase: 1, + VariableDeclarator: 1, + outerIIFEBody: 1, + // MemberExpression: null, + FunctionDeclaration: { + parameters: 1, + body: 1, + }, + FunctionExpression: { + parameters: 1, + body: 1, + }, + CallExpression: { + arguments: 1, + }, + ArrayExpression: 1, + ObjectExpression: 1, + ImportDeclaration: 1, + flatTernaryExpressions: false, + // list derived from https://github.com/benjamn/ast-types/blob/HEAD/def/jsx.js + ignoredNodes: [ + 'JSXElement', + 'JSXElement > *', + 'JSXAttribute', + 'JSXIdentifier', + 'JSXNamespacedName', + 'JSXMemberExpression', + 'JSXSpreadAttribute', + 'JSXExpressionContainer', + 'JSXOpeningElement', + 'JSXClosingElement', + 'JSXText', + 'JSXEmptyExpression', + 'JSXSpreadChild', + ], + ignoreComments: false, + }, + ], + + semi: [2, 'never', { beforeStatementContinuationChars: 'never' }], + 'semi-spacing': [2, { before: false, after: true }], + 'wrap-iife': [2, 'inside'], + 'no-caller': 2, + 'no-cond-assign': [2, 'except-parens'], + 'no-constant-condition': 0, + 'no-debugger': 2, + 'no-dupe-args': 2, + 'no-dupe-keys': 2, + 'no-duplicate-case': 2, + 'no-empty': [2, { allowEmptyCatch: true }], + 'no-empty-function': 'off', + 'no-extra-boolean-cast': 2, + 'no-extra-semi': 2, + 'no-func-assign': 2, + 'no-new': 2, + 'no-sparse-arrays': 2, + 'no-unexpected-multiline': 2, + 'no-unreachable': 2, + + 'max-params': [1, 5], + 'max-depth': [1, 4], + 'no-eq-null': 0, + 'no-unused-expressions': 0, + 'dot-notation': 2, + 'use-isnan': 2, + + // Best practices + 'block-scoped-var': 2, + complexity: [0, 11], + curly: [2, 'multi-line'], + eqeqeq: [2, 'always', { null: 'ignore' }], + 'no-else-return': 2, + 'no-extra-bind': 2, + 'no-implicit-coercion': 2, + 'no-return-assign': 0, + 'no-sequences': 2, + yoda: 2, + + // Variables + 'no-restricted-globals': ['error'], + 'no-var': 1, + + // Codestyle + 'arrow-parens': [2, 'always'], + 'array-bracket-spacing': [2, 'never'], + 'brace-style': [2, '1tbs', { allowSingleLine: true }], + camelcase: [2, { properties: 'never' }], + 'comma-dangle': ['warn', 'always-multiline'], + 'comma-spacing': [2, { before: false, after: true }], + 'eol-last': 2, + 'func-call-spacing': [2, 'never'], + 'block-spacing': 2, + 'keyword-spacing': [2, { before: true, after: true }], + 'max-len': [ + 2, + { + code: 120, + ignoreUrls: true, + ignoreComments: false, + ignoreRegExpLiterals: true, + ignoreStrings: true, + ignoreTemplateLiterals: true, + ignorePattern: 'require', + }, + ], + 'no-lonely-if': 2, + 'no-mixed-spaces-and-tabs': 2, + 'no-multi-spaces': 2, + 'no-multiple-empty-lines': [2, { max: 1, maxBOF: 0, maxEOF: 0 }], + 'no-trailing-spaces': 2, + 'ascii/valid-name': 2, + 'no-unneeded-ternary': 2, + 'no-nested-ternary': 2, + 'object-curly-spacing': [2, 'always'], + 'one-var-declaration-per-line': [2, 'initializations'], + 'one-var': [2, { let: 'never', const: 'never' }], + 'operator-linebreak': [2, 'after'], + 'padded-blocks': [2, 'never'], + 'quote-props': [2, 'as-needed', { numbers: true }], + quotes: [2, 'single', { avoidEscape: true }], + 'space-before-blocks': [2, 'always'], + 'space-before-function-paren': [ + 2, + { + named: 'never', + anonymous: 'always', + }, + ], + 'space-in-parens': 2, + 'key-spacing': [2, { beforeColon: false, afterColon: true, mode: 'strict' }], + 'space-infix-ops': 2, + 'padding-line-between-statements': [ + 'error', + { blankLine: 'always', prev: '*', next: 'return' }, + { blankLine: 'always', prev: '*', next: 'block-like' }, + { blankLine: 'any', prev: 'block-like', next: 'block-like' }, + { blankLine: 'any', prev: 'case', next: 'case' }, + ], + + 'simple-import-sort/imports': [ + 'error', + { + groups: [['^@mtcute'], ['^[a-z]'], ['^#']], + }, + ], + 'simple-import-sort/exports': 'error', + 'import/no-relative-packages': 'error', + 'import/no-mutable-exports': 'error', + 'import/no-default-export': 'error', + }, + {{#if features.typescript}} + overrides: [ + { + files: ['**/*.ts'], + env: { browser: true, es6: true, node: true }, + extends: ['plugin:@typescript-eslint/recommended'], + globals: { Atomics: 'readonly', SharedArrayBuffer: 'readonly' }, + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint'], + rules: { + '@typescript-eslint/consistent-type-assertions': 2, + '@typescript-eslint/no-explicit-any': 2, + '@typescript-eslint/no-unused-vars': [ + 2, + { + args: 'after-used', + argsIgnorePattern: '^_', + ignoreRestSiblings: true, + vars: 'all', + varsIgnorePattern: '^_', + }, + ], + }, + settings: { + 'import/resolver': { + node: true, + typescript: true, + }, + }, + }, + ], + {{/if}} + settings: { + 'import/resolver': { + node: true, + }, + }, +} diff --git a/packages/create-bot/template/.gitignore.hbs b/packages/create-bot/template/.gitignore.hbs new file mode 100644 index 00000000..b08e3c0a --- /dev/null +++ b/packages/create-bot/template/.gitignore.hbs @@ -0,0 +1,9 @@ +node_modules/ +dist/ +private/ +.nyc_output/ +**/.DS_Store +.idea +.vscode +*.log +*.tsbuildinfo \ No newline at end of file diff --git a/packages/create-bot/template/.husky/pre-commit.hbs b/packages/create-bot/template/.husky/pre-commit.hbs new file mode 100644 index 00000000..9fd01df4 --- /dev/null +++ b/packages/create-bot/template/.husky/pre-commit.hbs @@ -0,0 +1,5 @@ +{{emit_if features.linters}} +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +pnpm exec lint-staged \ No newline at end of file diff --git a/packages/create-bot/template/.lintstagedrc.cjs.hbs b/packages/create-bot/template/.lintstagedrc.cjs.hbs new file mode 100644 index 00000000..e21e3dd7 --- /dev/null +++ b/packages/create-bot/template/.lintstagedrc.cjs.hbs @@ -0,0 +1,7 @@ +{{emit_if features.linters}} +module.exports = { + '*.{js,jsx,ts,tsx}': [ + `prettier --write`, + `eslint --fix`, + ] +} diff --git a/packages/create-bot/template/.npmrc b/packages/create-bot/template/.npmrc new file mode 100644 index 00000000..68335980 --- /dev/null +++ b/packages/create-bot/template/.npmrc @@ -0,0 +1 @@ +@mtcute:registry=https://npm.tei.su \ No newline at end of file diff --git a/packages/create-bot/template/.prettierrc.hbs b/packages/create-bot/template/.prettierrc.hbs new file mode 100644 index 00000000..1395d786 --- /dev/null +++ b/packages/create-bot/template/.prettierrc.hbs @@ -0,0 +1,20 @@ +{{emit_if features.linters}} +{ + "arrowParens": "always", + "bracketSpacing": true, + "embeddedLanguageFormatting": "auto", + "htmlWhitespaceSensitivity": "css", + "insertPragma": false, + "jsxBracketSameLine": false, + "jsxSingleQuote": false, + "printWidth": 80, + "proseWrap": "preserve", + "quoteProps": "as-needed", + "requirePragma": false, + "semi": false, + "singleQuote": true, + "tabWidth": 4, + "trailingComma": "es5", + "useTabs": false, + "vueIndentScriptAndStyle": false +} \ No newline at end of file diff --git a/packages/create-bot/template/Dockerfile.hbs b/packages/create-bot/template/Dockerfile.hbs new file mode 100644 index 00000000..4c86728c --- /dev/null +++ b/packages/create-bot/template/Dockerfile.hbs @@ -0,0 +1,15 @@ +{{emit_if features.docker}} +FROM node:20-alpine +WORKDIR /app + +RUN apk add python3 make g++ && \ + corepack enable && \ + corepack prepare pnpm@8.7.1 --activate + +COPY package*.json pnpm*.yaml tsconfig.json .npmrc ./ +RUN pnpm install --frozen-lockfile + +COPY src /app/src +RUN pnpm run build + +CMD [ "node", "/app/dist/index.js" ] \ No newline at end of file diff --git a/packages/create-bot/template/README.md.hbs b/packages/create-bot/template/README.md.hbs new file mode 100644 index 00000000..fbc90424 --- /dev/null +++ b/packages/create-bot/template/README.md.hbs @@ -0,0 +1,14 @@ +# {{name}} + +MTCute powered Telegram bot + +## Development + +```bash +pnpm install --frozen-lockfile +cp .env.example .env +# edit .env +pnpm run run +``` + +*generated with @mtcute/create-bot* \ No newline at end of file diff --git a/packages/create-bot/template/bot-data/.gitignore.hbs b/packages/create-bot/template/bot-data/.gitignore.hbs new file mode 100644 index 00000000..c96a04f0 --- /dev/null +++ b/packages/create-bot/template/bot-data/.gitignore.hbs @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/packages/create-bot/template/docker-compose.yaml.hbs b/packages/create-bot/template/docker-compose.yaml.hbs new file mode 100644 index 00000000..5062eb53 --- /dev/null +++ b/packages/create-bot/template/docker-compose.yaml.hbs @@ -0,0 +1,11 @@ +{{emit_if features.docker}} +version: "3.9" +services: + bot: + build: + context: . + restart: always + env_file: + - .env + volumes: + - ./bot-data:/app/bot-data \ No newline at end of file diff --git a/packages/create-bot/template/package.json.hbs b/packages/create-bot/template/package.json.hbs new file mode 100644 index 00000000..94e32a67 --- /dev/null +++ b/packages/create-bot/template/package.json.hbs @@ -0,0 +1,25 @@ +{ + "name": "{{ name }}", + "license": "MIT", + "version": "1.0.0", + {{#if features.typescript}} + "main": "dist/index.js", + {{else}} + "main": "src/index.js", + {{/if}} + "type": "module", + "scripts": { + {{#if features.linters}} + "prepare": "husky install", + "lint": "eslint .", + "lint:fix": "eslint --fix .", + "format": "prettier --write \"src/**/*.ts\"", + {{/if}} + {{#if features.typescript}} + "run": "tsc && dotenv node ./dist/index.js", + "build": "tsc" + {{else}} + "run": "dotenv node ./src/index.js" + {{/if}} + } +} \ No newline at end of file diff --git a/packages/create-bot/template/src/env.ts.hbs b/packages/create-bot/template/src/env.ts.hbs new file mode 100644 index 00000000..addfad52 --- /dev/null +++ b/packages/create-bot/template/src/env.ts.hbs @@ -0,0 +1,12 @@ +{{emit_if features.typescript}} +const API_ID = parseInt(process.env.API_ID!) +const API_HASH = process.env.API_HASH! +{{#if botToken}} +const BOT_TOKEN = process.env.BOT_TOKEN! +{{/if}} + +if (isNaN(API_ID) || !API_HASH) { + throw new Error('API_ID or API_HASH not set!') +} + +export { API_HASH, API_ID{{#if botToken}}, BOT_TOKEN{{/if}} } diff --git a/packages/create-bot/template/src/i18n/en.js.hbs b/packages/create-bot/template/src/i18n/en.js.hbs new file mode 100644 index 00000000..a2a98c89 --- /dev/null +++ b/packages/create-bot/template/src/i18n/en.js.hbs @@ -0,0 +1,4 @@ +{{emit_if (and (not features.typescript) features.i18n)}} +export const en = { + helloWorld: 'Hello, world!', +} \ No newline at end of file diff --git a/packages/create-bot/template/src/i18n/en.ts.hbs b/packages/create-bot/template/src/i18n/en.ts.hbs new file mode 100644 index 00000000..1dcd521b --- /dev/null +++ b/packages/create-bot/template/src/i18n/en.ts.hbs @@ -0,0 +1,4 @@ +{{emit_if (and features.typescript features.i18n)}} +export const en = { + helloWorld: 'Hello, world!', +} as const \ No newline at end of file diff --git a/packages/create-bot/template/src/i18n/index.js.hbs b/packages/create-bot/template/src/i18n/index.js.hbs new file mode 100644 index 00000000..1bb46608 --- /dev/null +++ b/packages/create-bot/template/src/i18n/index.js.hbs @@ -0,0 +1,13 @@ +{{emit_if (and (not features.typescript) features.i18n)}} + +import { createMtcuteI18n } from '@mtcute/i18n' +import { en } from './en.js' +import { ru } from './ru.js' + +export const tr = createMtcuteI18n({ + primaryLanguage: { + name: 'en', + strings: en, + }, + otherLanguages: { ru } +}) \ No newline at end of file diff --git a/packages/create-bot/template/src/i18n/index.ts.hbs b/packages/create-bot/template/src/i18n/index.ts.hbs new file mode 100644 index 00000000..be96dce9 --- /dev/null +++ b/packages/create-bot/template/src/i18n/index.ts.hbs @@ -0,0 +1,12 @@ +{{emit_if (and features.typescript features.i18n)}} +import { createMtcuteI18n } from '@mtcute/i18n' +import { en } from './en.js' +import { ru } from './ru.js' + +export const tr = createMtcuteI18n({ + primaryLanguage: { + name: 'en', + strings: en, + }, + otherLanguages: { ru } +}) \ No newline at end of file diff --git a/packages/create-bot/template/src/i18n/ru.js.hbs b/packages/create-bot/template/src/i18n/ru.js.hbs new file mode 100644 index 00000000..712a2f74 --- /dev/null +++ b/packages/create-bot/template/src/i18n/ru.js.hbs @@ -0,0 +1,4 @@ +{{emit_if (and (not features.typescript) features.i18n)}} +export const ru = { + helloWorld: 'ะŸั€ะธะฒะตั‚, ะผะธั€!', +} \ No newline at end of file diff --git a/packages/create-bot/template/src/i18n/ru.ts.hbs b/packages/create-bot/template/src/i18n/ru.ts.hbs new file mode 100644 index 00000000..dad57d13 --- /dev/null +++ b/packages/create-bot/template/src/i18n/ru.ts.hbs @@ -0,0 +1,8 @@ +{{emit_if (and features.typescript features.i18n)}} +import type { OtherLanguageWrap } from '@mtcute/i18n' + +import type { en } from './en.js' + +export const ru = { + helloWorld: 'ะŸั€ะธะฒะตั‚, ะผะธั€!', +} satisfies OtherLanguageWrap \ No newline at end of file diff --git a/packages/create-bot/template/src/index.js.hbs b/packages/create-bot/template/src/index.js.hbs new file mode 100644 index 00000000..85b9ad61 --- /dev/null +++ b/packages/create-bot/template/src/index.js.hbs @@ -0,0 +1,39 @@ +{{emit_if (not features.typescript)}} +{{#if features.dispatcher}} +import { Dispatcher, filters } from '@mtcute/dispatcher' +{{/if}} +import { NodeTelegramClient } from '@mtcute/node' + +import * as env from './env.js' +{{#if features.i18n}} +import { tr } from './i18n/index.js' +{{/if}} + +const tg = new NodeTelegramClient({ + apiId: env.API_ID, + apiHash: env.API_HASH, + storage: 'bot-data/session', +}) + +{{#if features.dispatcher}} +const dp = new Dispatcher(tg) + +dp.onNewMessage(filters.start, async (msg) => { + {{#if features.i18n}} + await msg.answerText(tr(msg, 'helloWorld')) + {{else}} + await msg.answerText('Hello, world!') + {{/if}} +}) +{{/if}} + +tg.run( + {{#if botToken}} + { botToken: env.BOT_TOKEN }, + {{else}} + {}, + {{/if}} + (user) => { + console.log('Logged in as', user.username) + }, +) \ No newline at end of file diff --git a/packages/create-bot/template/src/index.ts.hbs b/packages/create-bot/template/src/index.ts.hbs new file mode 100644 index 00000000..dca25cba --- /dev/null +++ b/packages/create-bot/template/src/index.ts.hbs @@ -0,0 +1,39 @@ +{{emit_if features.typescript}} +{{#if features.dispatcher}} +import { Dispatcher, filters } from '@mtcute/dispatcher' +{{/if}} +import { NodeTelegramClient } from '@mtcute/node' + +import * as env from './env.js' +{{#if features.i18n}} +import { tr } from './i18n/index.js' +{{/if}} + +const tg = new NodeTelegramClient({ + apiId: env.API_ID, + apiHash: env.API_HASH, + storage: 'bot-data/session', +}) + +{{#if features.dispatcher}} +const dp = new Dispatcher(tg) + +dp.onNewMessage(filters.start, async (msg) => { + {{#if features.i18n}} + await msg.answerText(tr(msg, 'helloWorld')) + {{else}} + await msg.answerText('Hello, world!') + {{/if}} +}) +{{/if}} + +tg.run( + {{#if botToken}} + { botToken: env.BOT_TOKEN }, + {{else}} + {}, + {{/if}} + (user) => { + console.log('Logged in as', user.username) + }, +) diff --git a/packages/create-bot/template/tsconfig.json.hbs b/packages/create-bot/template/tsconfig.json.hbs new file mode 100644 index 00000000..ff21c4a9 --- /dev/null +++ b/packages/create-bot/template/tsconfig.json.hbs @@ -0,0 +1,29 @@ +{{emit_if features.typescript}} +{ + "compilerOptions": { + "outDir": "./dist", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "target": "es2020", + "allowJs": true, + "sourceMap": true, + "inlineSources": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "noImplicitAny": true, + "noImplicitThis": true, + "incremental": true, + "skipLibCheck": true, + }, + "include": [ + "./src" + ], + "ts-node": { + "esm": true, + "experimentalSpecifierResolution": "node" + }, + "exclude": [ + "**/node_modules", + ] +} diff --git a/packages/create-bot/tsconfig.json b/packages/create-bot/tsconfig.json new file mode 100644 index 00000000..04e9fb30 --- /dev/null +++ b/packages/create-bot/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist" + }, + "include": [ + "./src" + ] +} diff --git a/packages/i18n/tests/types.ts b/packages/i18n/tests/types.ts index 0d85ba0f..41a35d32 100644 --- a/packages/i18n/tests/types.ts +++ b/packages/i18n/tests/types.ts @@ -3,7 +3,7 @@ // This file is never executed, only compiled import { Message } from '@mtcute/client' -import { createMtcuteI18n, OtherLanguageWrapExhaustive, OtherLanguageWrap } from '../src' +import { createMtcuteI18n, OtherLanguageWrap } from '../src/index.js' const en = { basic: { diff --git a/packages/node/index.ts b/packages/node/index.ts index b21de908..a3cac4a1 100644 --- a/packages/node/index.ts +++ b/packages/node/index.ts @@ -7,7 +7,6 @@ import { MarkdownMessageEntityParser } from '@mtcute/markdown-parser' import { SqliteStorage } from '@mtcute/sqlite' export * from '@mtcute/client' -export * from '@mtcute/dispatcher' export * from '@mtcute/html-parser' export * from '@mtcute/markdown-parser' export { SqliteStorage } diff --git a/packages/node/package.json b/packages/node/package.json index e75d4940..ad682fd2 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -23,7 +23,6 @@ "@mtcute/client": "workspace:^1.0.0", "@mtcute/sqlite": "workspace:^1.0.0", "@mtcute/markdown-parser": "workspace:^1.0.0", - "@mtcute/html-parser": "workspace:^1.0.0", - "@mtcute/dispatcher": "workspace:^1.0.0" + "@mtcute/html-parser": "workspace:^1.0.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 967f8804..cad6f992 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -164,6 +164,28 @@ importers: specifier: 8.13.0 version: 8.13.0 + packages/create-bot: + dependencies: + chalk: + specifier: ^5.3.0 + version: 5.3.0 + glob: + specifier: 10.2.6 + version: 10.2.6 + handlebars: + specifier: ^4.7.8 + version: 4.7.8 + inquirer: + specifier: 9.2.11 + version: 9.2.11 + open: + specifier: 9.1.0 + version: 9.1.0 + devDependencies: + '@types/inquirer': + specifier: ^9.0.6 + version: 9.0.6 + packages/crypto: {} packages/crypto-node: @@ -245,9 +267,6 @@ importers: '@mtcute/client': specifier: workspace:^1.0.0 version: link:../client - '@mtcute/dispatcher': - specifier: workspace:^1.0.0 - version: link:../dispatcher '@mtcute/html-parser': specifier: workspace:^1.0.0 version: link:../html-parser @@ -792,7 +811,6 @@ packages: strip-ansi-cjs: /strip-ansi@6.0.1 wrap-ansi: 8.1.0 wrap-ansi-cjs: /wrap-ansi@7.0.0 - dev: true /@istanbuljs/load-nyc-config@1.1.0: resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} @@ -836,6 +854,13 @@ packages: '@jridgewell/resolve-uri': 3.0.6 '@jridgewell/sourcemap-codec': 1.4.11 + /@ljharb/through@2.3.11: + resolution: {integrity: sha512-ccfcIDlogiXNq5KcbAwbaO7lMh3Tm1i3khMPYpxlK8hH/W53zN81KM9coerRLOnTGu3nfXIniAmQbRI9OxbC0w==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + dev: false + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -878,7 +903,6 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} requiresBuild: true - dev: true optional: true /@tokenizer/token@0.3.0: @@ -922,6 +946,13 @@ packages: resolution: {integrity: sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==} dev: false + /@types/inquirer@9.0.6: + resolution: {integrity: sha512-1Go1AAP/yOy3Pth5Xf1DC3nfZ03cJLCPx6E2YnSN/5I3w1jHBVH4170DkZ+JxfmA7c9kL9+bf9z3FRGa4kNAqg==} + dependencies: + '@types/through': 0.0.32 + rxjs: 7.8.1 + dev: true + /@types/js-yaml@4.0.5: resolution: {integrity: sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==} dev: true @@ -963,6 +994,12 @@ packages: resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} dev: true + /@types/through@0.0.32: + resolution: {integrity: sha512-7XsfXIsjdfJM2wFDRAtEWp3zb2aVPk5QeyZxGlVK57q4u26DczMHhJmlhr0Jqv0THwxam/L8REXkj8M2I/lcvw==} + dependencies: + '@types/node': 18.16.0 + dev: true + /@types/ws@8.5.4: resolution: {integrity: sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==} dependencies: @@ -1184,7 +1221,6 @@ packages: engines: {node: '>=8'} dependencies: type-fest: 0.21.3 - dev: true /ansi-regex@2.1.1: resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} @@ -1198,7 +1234,6 @@ packages: /ansi-regex@6.0.1: resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} engines: {node: '>=12'} - dev: true /ansi-sequence-parser@1.1.0: resolution: {integrity: sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==} @@ -1216,12 +1251,10 @@ packages: engines: {node: '>=8'} dependencies: color-convert: 2.0.1 - dev: true /ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} - dev: true /anymatch@3.1.2: resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} @@ -1396,6 +1429,13 @@ packages: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} dev: true + /bplist-parser@0.2.0: + resolution: {integrity: sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==} + engines: {node: '>= 5.10.0'} + dependencies: + big-integer: 1.6.51 + dev: false + /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: @@ -1436,6 +1476,13 @@ packages: base64-js: 1.5.1 ieee754: 1.2.1 + /bundle-name@3.0.0: + resolution: {integrity: sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==} + engines: {node: '>=12'} + dependencies: + run-applescript: 5.0.0 + dev: false + /cacache@16.0.7: resolution: {integrity: sha512-a4zfQpp5vm4Ipdvbj+ZrPonikRhm6WBEd4zT1Yc1DXsmAxrPgDwWBLF/u/wTVXSFPIgOJ1U3ghSa2Xm4s3h28w==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -1477,7 +1524,6 @@ packages: dependencies: function-bind: 1.1.1 get-intrinsic: 1.2.1 - dev: true /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} @@ -1544,13 +1590,21 @@ packages: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - dev: true /chalk@5.2.0: resolution: {integrity: sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} dev: true + /chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: false + + /chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + dev: false + /check-error@1.0.2: resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} dev: true @@ -1612,12 +1666,10 @@ packages: engines: {node: '>=8'} dependencies: restore-cursor: 3.1.0 - dev: true /cli-spinners@2.9.1: resolution: {integrity: sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==} engines: {node: '>=6'} - dev: true /cli-truncate@2.1.0: resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} @@ -1635,6 +1687,11 @@ packages: string-width: 5.1.2 dev: true + /cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + dev: false + /cliui@6.0.0: resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} dependencies: @@ -1663,7 +1720,6 @@ packages: /clone@1.0.4: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} - dev: true /code-point-at@1.1.0: resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==} @@ -1681,7 +1737,6 @@ packages: engines: {node: '>=7.0.0'} dependencies: color-name: 1.1.4 - dev: true /color-name@1.1.3: resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} @@ -1689,7 +1744,6 @@ packages: /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true /color-support@1.1.3: resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} @@ -1807,7 +1861,6 @@ packages: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - dev: true /css-select@5.1.0: resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} @@ -1897,6 +1950,24 @@ packages: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true + /default-browser-id@3.0.0: + resolution: {integrity: sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==} + engines: {node: '>=12'} + dependencies: + bplist-parser: 0.2.0 + untildify: 4.0.0 + dev: false + + /default-browser@4.0.0: + resolution: {integrity: sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==} + engines: {node: '>=14.16'} + dependencies: + bundle-name: 3.0.0 + default-browser-id: 3.0.0 + execa: 7.1.1 + titleize: 3.0.0 + dev: false + /default-require-extensions@3.0.0: resolution: {integrity: sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==} engines: {node: '>=8'} @@ -1908,7 +1979,11 @@ packages: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} dependencies: clone: 1.0.4 - dev: true + + /define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + dev: false /define-properties@1.2.0: resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} @@ -2045,7 +2120,6 @@ packages: /eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: true /electron-to-chromium@1.4.124: resolution: {integrity: sha512-VhaE9VUYU6d2eIb+4xf83CATD+T+3bTzvxvlADkQE+c2hisiw3sZmvEDtsW704+Zky9WZGhBuQXijDVqSriQLA==} @@ -2056,7 +2130,6 @@ packages: /emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: true /encoding@0.1.13: resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} @@ -2187,6 +2260,11 @@ packages: engines: {node: '>=10'} dev: true + /escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + dev: false + /eslint-config-prettier@8.8.0(eslint@8.47.0): resolution: {integrity: sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==} hasBin: true @@ -2428,7 +2506,6 @@ packages: onetime: 5.1.2 signal-exit: 3.0.7 strip-final-newline: 2.0.0 - dev: true /execa@7.1.1: resolution: {integrity: sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==} @@ -2443,7 +2520,6 @@ packages: onetime: 6.0.0 signal-exit: 3.0.7 strip-final-newline: 3.0.0 - dev: true /exit-on-epipe@1.0.1: resolution: {integrity: sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==} @@ -2455,6 +2531,15 @@ packages: engines: {node: '>=6'} dev: false + /external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + dev: false + /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: true @@ -2495,6 +2580,14 @@ packages: reusify: 1.0.4 dev: true + /figures@5.0.0: + resolution: {integrity: sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==} + engines: {node: '>=14'} + dependencies: + escape-string-regexp: 5.0.0 + is-unicode-supported: 1.3.0 + dev: false + /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -2584,7 +2677,6 @@ packages: dependencies: cross-spawn: 7.0.3 signal-exit: 4.0.2 - dev: true /fromentries@1.3.2: resolution: {integrity: sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==} @@ -2623,7 +2715,6 @@ packages: /function-bind@1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - dev: true /function.prototype.name@1.1.5: resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} @@ -2687,7 +2778,6 @@ packages: has: 1.0.3 has-proto: 1.0.1 has-symbols: 1.0.3 - dev: true /get-package-type@0.1.0: resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} @@ -2697,7 +2787,6 @@ packages: /get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} - dev: true /get-symbol-description@1.0.0: resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} @@ -2749,11 +2838,10 @@ packages: hasBin: true dependencies: foreground-child: 3.1.1 - jackspeak: 2.2.1 + jackspeak: 2.3.6 minimatch: 9.0.1 minipass: 6.0.2 - path-scurry: 1.9.2 - dev: true + path-scurry: 1.10.1 /glob@10.3.10: resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} @@ -2840,6 +2928,19 @@ packages: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} dev: true + /handlebars@4.7.8: + resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + engines: {node: '>=0.4.7'} + hasBin: true + dependencies: + minimist: 1.2.6 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.17.4 + dev: false + /hard-rejection@2.1.0: resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} engines: {node: '>=6'} @@ -2867,12 +2968,10 @@ packages: /has-proto@1.0.1: resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} engines: {node: '>= 0.4'} - dev: true /has-symbols@1.0.3: resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} engines: {node: '>= 0.4'} - dev: true /has-tostringtag@1.0.0: resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} @@ -2890,7 +2989,6 @@ packages: engines: {node: '>= 0.4.0'} dependencies: function-bind: 1.1.1 - dev: true /hasha@5.2.2: resolution: {integrity: sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==} @@ -2966,12 +3064,10 @@ packages: /human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} - dev: true /human-signals@4.3.1: resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} engines: {node: '>=14.18.0'} - dev: true /humanize-ms@1.2.1: resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} @@ -2985,6 +3081,13 @@ packages: hasBin: true dev: true + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + /iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -3039,6 +3142,27 @@ packages: /ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + /inquirer@9.2.11: + resolution: {integrity: sha512-B2LafrnnhbRzCWfAdOXisUzL89Kg8cVJlYmhqoi3flSiV/TveO+nsXwgKr9h9PIo+J1hz7nBSk6gegRIMBBf7g==} + engines: {node: '>=14.18.0'} + dependencies: + '@ljharb/through': 2.3.11 + ansi-escapes: 4.3.2 + chalk: 5.3.0 + cli-cursor: 3.1.0 + cli-width: 4.1.0 + external-editor: 3.1.0 + figures: 5.0.0 + lodash: 4.17.21 + mute-stream: 1.0.0 + ora: 5.4.1 + run-async: 3.0.0 + rxjs: 7.8.1 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + dev: false + /internal-slot@1.0.5: resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} engines: {node: '>= 0.4'} @@ -3114,6 +3238,18 @@ packages: has-tostringtag: 1.0.0 dev: true + /is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + dev: false + + /is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + dev: false + /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -3142,10 +3278,17 @@ packages: is-extglob: 2.1.1 dev: true + /is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + dependencies: + is-docker: 3.0.0 + dev: false + /is-interactive@1.0.0: resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} engines: {node: '>=8'} - dev: true /is-lambda@1.0.1: resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} @@ -3205,12 +3348,10 @@ packages: /is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} - dev: true /is-stream@3.0.0: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true /is-string@1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} @@ -3251,7 +3392,11 @@ packages: /is-unicode-supported@0.1.0: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} - dev: true + + /is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + dev: false /is-weakref@1.0.2: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} @@ -3264,6 +3409,13 @@ packages: engines: {node: '>=0.10.0'} dev: true + /is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + dependencies: + is-docker: 2.2.1 + dev: false + /isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} dev: false @@ -3336,15 +3488,6 @@ packages: istanbul-lib-report: 3.0.0 dev: true - /jackspeak@2.2.1: - resolution: {integrity: sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==} - engines: {node: '>=14'} - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - dev: true - /jackspeak@2.3.6: resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} engines: {node: '>=14'} @@ -3352,7 +3495,6 @@ packages: '@isaacs/cliui': 8.0.2 optionalDependencies: '@pkgjs/parseargs': 0.11.0 - dev: true /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -3549,7 +3691,6 @@ packages: /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true /log-symbols@4.1.0: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} @@ -3557,7 +3698,6 @@ packages: dependencies: chalk: 4.1.2 is-unicode-supported: 0.1.0 - dev: true /log-update@4.0.0: resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} @@ -3593,7 +3733,6 @@ packages: /lru-cache@9.1.2: resolution: {integrity: sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==} engines: {node: 14 || >=16.14} - dev: true /lunr@2.3.9: resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} @@ -3669,7 +3808,6 @@ packages: /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true /merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} @@ -3687,12 +3825,10 @@ packages: /mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} - dev: true /mimic-fn@4.0.0: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} - dev: true /mimic-response@3.1.0: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} @@ -3728,7 +3864,6 @@ packages: engines: {node: '>=16 || 14 >=14.17'} dependencies: brace-expansion: 2.0.1 - dev: true /minimist-options@4.1.0: resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} @@ -3791,7 +3926,6 @@ packages: /minipass@6.0.2: resolution: {integrity: sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==} engines: {node: '>=16 || 14 >=14.17'} - dev: true /minizlib@2.1.2: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} @@ -3845,6 +3979,11 @@ packages: /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + /mute-stream@1.0.0: + resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: false + /nanoid@3.3.3: resolution: {integrity: sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -3864,6 +4003,10 @@ packages: engines: {node: '>= 0.6'} dev: false + /neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + dev: false + /node-abi@3.15.0: resolution: {integrity: sha512-Ic6z/j6I9RLm4ov7npo1I48UQr2BEyFCqh6p7S1dhEx9jPO0GPGq/e2Rb7x7DroQrmiVMz/Bw1vJm9sPAl2nxA==} engines: {node: '>=10'} @@ -3944,14 +4087,12 @@ packages: engines: {node: '>=8'} dependencies: path-key: 3.1.1 - dev: true /npm-run-path@5.1.0: resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: path-key: 4.0.0 - dev: true /npmlog@4.1.2: resolution: {integrity: sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==} @@ -4080,14 +4221,22 @@ packages: engines: {node: '>=6'} dependencies: mimic-fn: 2.1.0 - dev: true /onetime@6.0.0: resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} engines: {node: '>=12'} dependencies: mimic-fn: 4.0.0 - dev: true + + /open@9.1.0: + resolution: {integrity: sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==} + engines: {node: '>=14.16'} + dependencies: + default-browser: 4.0.0 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + is-wsl: 2.2.0 + dev: false /optionator@0.9.3: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} @@ -4114,7 +4263,11 @@ packages: log-symbols: 4.1.0 strip-ansi: 6.0.1 wcwidth: 1.0.1 - dev: true + + /os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + dev: false /p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} @@ -4218,12 +4371,10 @@ packages: /path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - dev: true /path-key@4.0.0: resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} engines: {node: '>=12'} - dev: true /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} @@ -4235,15 +4386,6 @@ packages: dependencies: lru-cache: 9.1.2 minipass: 6.0.2 - dev: true - - /path-scurry@1.9.2: - resolution: {integrity: sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - lru-cache: 9.1.2 - minipass: 6.0.2 - dev: true /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} @@ -4524,7 +4666,6 @@ packages: dependencies: onetime: 5.1.2 signal-exit: 3.0.7 - dev: true /retry@0.12.0: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} @@ -4554,6 +4695,18 @@ packages: glob: 10.2.6 dev: true + /run-applescript@5.0.0: + resolution: {integrity: sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==} + engines: {node: '>=12'} + dependencies: + execa: 5.1.1 + dev: false + + /run-async@3.0.0: + resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} + engines: {node: '>=0.12.0'} + dev: false + /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: @@ -4563,8 +4716,7 @@ packages: /rxjs@7.8.1: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} dependencies: - tslib: 2.5.3 - dev: true + tslib: 2.6.2 /safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} @@ -4584,7 +4736,6 @@ packages: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} requiresBuild: true dev: false - optional: true /semver@5.7.1: resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} @@ -4638,12 +4789,10 @@ packages: engines: {node: '>=8'} dependencies: shebang-regex: 3.0.0 - dev: true /shebang-regex@3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - dev: true /shiki@0.14.2: resolution: {integrity: sha512-ltSZlSLOuSY0M0Y75KA+ieRaZ0Trf5Wl3gutE7jzLuIcWxLp5i/uEnLoQWNvgKXQ5OMpGkJnVMRLAuzjc0LJ2A==} @@ -4668,7 +4817,6 @@ packages: /signal-exit@4.0.2: resolution: {integrity: sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==} engines: {node: '>=14'} - dev: true /simple-concat@1.0.1: resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} @@ -4745,7 +4893,6 @@ packages: /source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} - dev: true /spawn-wrap@2.0.0: resolution: {integrity: sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==} @@ -4827,7 +4974,6 @@ packages: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 strip-ansi: 7.1.0 - dev: true /string.prototype.trim@1.2.7: resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} @@ -4883,7 +5029,6 @@ packages: engines: {node: '>=12'} dependencies: ansi-regex: 6.0.1 - dev: true /strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} @@ -4898,12 +5043,10 @@ packages: /strip-final-newline@2.0.0: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} - dev: true /strip-final-newline@3.0.0: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} - dev: true /strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} @@ -4942,7 +5085,6 @@ packages: engines: {node: '>=8'} dependencies: has-flag: 4.0.0 - dev: true /supports-color@8.1.1: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} @@ -5020,6 +5162,18 @@ packages: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} dev: true + /titleize@3.0.0: + resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==} + engines: {node: '>=12'} + dev: false + + /tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + dependencies: + os-tmpdir: 1.0.2 + dev: false + /to-fast-properties@2.0.0: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} @@ -5102,13 +5256,8 @@ packages: strip-bom: 3.0.0 dev: true - /tslib@2.5.3: - resolution: {integrity: sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==} - dev: true - /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - dev: true /tunnel-agent@0.6.0: resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} @@ -5141,7 +5290,6 @@ packages: /type-fest@0.21.3: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} - dev: true /type-fest@0.6.0: resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} @@ -5192,6 +5340,14 @@ packages: hasBin: true dev: true + /uglify-js@3.17.4: + resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} + engines: {node: '>=0.8.0'} + hasBin: true + requiresBuild: true + dev: false + optional: true + /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} dependencies: @@ -5218,6 +5374,11 @@ packages: engines: {node: '>= 10.0.0'} dev: true + /untildify@4.0.0: + resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} + engines: {node: '>=8'} + dev: false + /uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: @@ -5255,7 +5416,6 @@ packages: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} dependencies: defaults: 1.0.4 - dev: true /which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} @@ -5296,6 +5456,10 @@ packages: string-width: 4.2.3 dev: false + /wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + dev: false + /workerpool@6.2.1: resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==} dev: true @@ -5307,7 +5471,6 @@ packages: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true /wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} @@ -5316,7 +5479,6 @@ packages: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true /wrap-ansi@8.1.0: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} @@ -5325,7 +5487,6 @@ packages: ansi-styles: 6.2.1 string-width: 5.1.2 strip-ansi: 7.1.0 - dev: true /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}