This commit is contained in:
hansputera
2022-02-07 10:25:58 +07:00
parent 1e4043279e
commit 02ccf06298
36 changed files with 565 additions and 130 deletions

3
.gitignore vendored
View File

@@ -1,4 +1,5 @@
.vercel
node_modules/
.env.local
.env
package-lock.json
.turbo

1
apps/web/.eslintrc.js Normal file
View File

@@ -0,0 +1 @@
module.exports = require('tiktok-dl-config/eslint.js');

1
apps/web/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.next

2
apps/web/lib/index.ts Normal file
View File

@@ -0,0 +1,2 @@
export * from './redis';
export * from './rotator';

3
apps/web/lib/redis.ts Normal file
View File

@@ -0,0 +1,3 @@
import Redis from 'ioredis';
export const client = new Redis(process.env.REDIS_URL);

50
apps/web/lib/rotator.ts Normal file
View File

@@ -0,0 +1,50 @@
import {providerCache} from '../config';
import {BaseProvider, ExtractedInfo, getRandomProvider} from 'tiktok-dl-core';
import {client as redisClient} from './redis';
/**
* Rotate provider.
* @param {BaseProvider} provider Provider instance
* @param {string} url Video TikTok URL
* @param {boolean?} skipOnError Rotate when error
* @return {Promise<ExtractedInfo>}
*/
export const rotateProvider = async (
provider: BaseProvider, url: string,
skipOnError: boolean = true):
Promise<ExtractedInfo & { provider: string; }> => {
// await redisClient.del(url);
// console.log(provider.resourceName());
if (provider.maintenance) {
return await rotateProvider(getRandomProvider(), url, skipOnError);
}
const cachedData = await redisClient.get(url);
if (!cachedData) {
try {
const data = await provider.fetch(url);
if (data.error) {
// switching to other provider
return await rotateProvider(getRandomProvider(), url);
} else if (data.video && !data.video.urls.length) {
return await rotateProvider(getRandomProvider(), url);
} else {
redisClient.set(url,
JSON.stringify(
{...data, provider: provider.resourceName()}), 'ex',
providerCache);
return {...data, provider: provider.resourceName()};
}
} catch (e) {
if (skipOnError) {
return await rotateProvider(getRandomProvider(), url);
} else {
return {
error: (e as Error).message,
provider: provider.resourceName(),
};
}
}
} else {
return JSON.parse(cachedData);
}
};

View File

@@ -0,0 +1,25 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import {rateLimitConfig} from '../config';
import {client} from '../lib';
export const ratelimitMiddleware = async (req: NextApiRequest, res: NextApiResponse) => {
const ip = req.headers['x-real-ip'] ||
req.headers['x-forwarded-for'];
if (!rateLimitConfig.enable) return true;
else if (!ip) {
return res.status(401).send('Couldn\'t find your real ip address!')
}
client.get('rate-' + ip, (_, result) => {
if (result) {
if (parseInt(result) > rateLimitConfig.maxRatelimitPerXSeconds) {
return res.status(429).send(
'Please try again, you are getting ratelimit!');
}
client.incr('rate-' + ip);
return true;
} else {
client.set('rate-' + ip, '1', 'ex', rateLimitConfig.ratelimitTime);
return true;
}
});
};

5
apps/web/next-env.d.ts vendored Normal file
View File

@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

5
apps/web/next.config.js Normal file
View File

@@ -0,0 +1,5 @@
const withTM = require('next-transpile-modules')(['tiktok-dl-core']);
module.exports = withTM({
reactStrictMode: true,
});

View File

@@ -5,9 +5,20 @@
"license": "MIT",
"dependencies": {
"ioredis": "^4.28.0",
"ow": "^0.28.1"
"next": "^12.0.10",
"ow": "^0.28.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"tiktok-dl-core": "*"
},
"scripts": {
"build": "echo build"
"build": "next build",
"dev": "next dev"
},
"devDependencies": {
"@types/react": "^17.0.39",
"next-transpile-modules": "^9.0.0",
"tiktok-dl-config": "*",
"typescript": "latest"
}
}

View File

@@ -0,0 +1,49 @@
import type {NextApiRequest, NextApiResponse} from 'next';
import ow from 'ow';
import {getProvider, Providers, BaseProvider} from 'tiktok-dl-core';
import {rotateProvider} from '../../lib/rotator';
import {ratelimitMiddleware} from '../../middleware/ratelimit';
export default async (req: NextApiRequest, res: NextApiResponse) => {
try {
await ratelimitMiddleware(req,res);
const providersType = Providers.map((p) => p.resourceName());
ow(req.body || req.query, ow.object.partialShape({
'url': ow.string.url.validate((v) => ({
'validator': /^http(s?)(:\/\/)([a-z]+\.)*tiktok\.com\/(.*)$/gi
.test(v),
'message': 'Expected (.*).tiktok.com',
})),
'type': ow.optional.string.validate((v) => ({
'validator': typeof v === 'string' &&
providersType.includes(v.toLowerCase()),
'message': 'Invalid Provider, available provider is: ' +
Providers.map((x) => x.resourceName()).join(', '),
})),
'nocache': req.method === 'POST' ?
ow.optional.boolean : ow.optional.string,
'rotateOnError': req.method === 'POST' ?
ow.optional.boolean : ow.optional.string,
}));
const provider = getProvider((req.query && req.query.type ||
req.body && req.body.type) ?? 'random');
if (!provider) {
return res.status(400).json({
'error': 'Invalid provider',
'providers': providersType,
});
}
const result = await rotateProvider(
provider as BaseProvider, (req.query && req.query.url ||
req.body && req.body.url), req.method === 'POST' ?
req.body.rotateOnError :
!!req.query.rotateOnError);
return res.status(200).json(result);
} catch (e) {
return res.status(500).json({
'error': (e as Error).message,
});
}
};

View File

@@ -0,0 +1,8 @@
import type {
NextApiRequest,
NextApiResponse
} from 'next';
export default function IndexApi(_: NextApiRequest, res: NextApiResponse) {
res.send('Hello world.');
}

View File

@@ -0,0 +1,14 @@
import type {NextApiRequest, NextApiResponse} from 'next';
import {Providers} from 'tiktok-dl-core';
import {ratelimitMiddleware} from '../../middleware/ratelimit';
export default async (req: NextApiRequest, res: NextApiResponse) => {
await ratelimitMiddleware(req,res);
const providers = Providers.map((p) => ({
'name': p.resourceName(),
'url': p.client.defaults.options.prefixUrl,
'maintenance': p.maintenance,
}));
return res.send(providers);
};

View File

@@ -0,0 +1,14 @@
import type {
NextApiRequest,
NextApiResponse
} from 'next';
import {client} from '../../lib';
import {ratelimitMiddleware} from '../../middleware/ratelimit';
import {matchLink} from 'tiktok-dl-core';
export default async function StoredLinks(req: NextApiRequest, res: NextApiResponse) {
await ratelimitMiddleware(req, res);
const keys = await client.keys('*');
res.status(200).json(keys.filter((x) => matchLink(x)));
}

7
apps/web/pages/index.tsx Normal file
View File

@@ -0,0 +1,7 @@
export default function Index() {
return (
<div>
<p>Hello world</p>
</div>
);
}

View File

@@ -1,19 +1,37 @@
{
"compilerOptions": {
"allowJs": true,
"noEmit": true,
"strict": true,
"strictBindCallApply": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"outDir": "dist",
"target": "ES2016",
"module": "CommonJS",
"removeComments": true,
"esModuleInterop": true,
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"exclude": ["node_modules", "dist"]
"compilerOptions": {
"allowJs": true,
"noEmit": true,
"strict": true,
"strictBindCallApply": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"outDir": "dist",
"target": "ES2016",
"module": "CommonJS",
"removeComments": true,
"esModuleInterop": true,
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"forceConsistentCasingInFileNames": true,
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"incremental": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
},
"exclude": [
"node_modules",
"dist"
],
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx"
]
}

View File

@@ -2,31 +2,20 @@
"name": "tktk",
"version": "1.4.2",
"main": "index.js",
"private": true,
"license": "MIT",
"dependencies": {
"got": "^11.8.2",
"ioredis": "^4.28.0",
"ow": "^0.28.1",
"vm2": "^3.9.5"
},
"devDependencies": {
"@types/ioredis": "^4.28.1",
"@typescript-eslint/eslint-plugin": "^5.3.0",
"@typescript-eslint/parser": "^5.3.0",
"@vercel/node": "^1.12.1",
"eslint": "^8.2.0",
"eslint-config-google": "^0.14.0",
"husky": "^7.0.4",
"turbo": "^1.1.2",
"typescript": "^4.4.4"
},
"scripts": {
"build": "echo build",
"lint": "eslint \"+(lib|api|middleware)/**/*.ts\" --fix",
"prepare": "husky install"
"turbo": "^1.1.2"
},
"workspaces": [
"packages/*"
"apps/*"
]
"packages/*",
"apps/*"
],
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev --parallel",
"lint": "turbo run lint"
},
"packageManager": "yarn@1.22.17"
}

View File

@@ -1,2 +1,3 @@
export * from './src';
export * from './fetch';
export * from './src/utils';

View File

@@ -1,4 +1,4 @@
import {getFetch} from '..';
import {getFetch} from '../fetch';
import {BaseProvider, ExtractedInfo} from './base';
/**

View File

@@ -1,5 +1,5 @@
import {BaseProvider, ExtractedInfo} from './base';
import {getFetch} from '..';
import {getFetch} from '../fetch';
import {matchLink} from './utils';
/**

View File

@@ -1,5 +1,5 @@
import {BaseProvider, ExtractedInfo} from './base';
import {getFetch} from '..';
import {getFetch} from '../fetch';
import {matchCustomDownload} from './utils';
/**

View File

@@ -1,5 +1,5 @@
import {BaseProvider, ExtractedInfo} from './base';
import {getFetch} from '..';
import {getFetch} from '../fetch';
/**
* @class DownloadOne

View File

@@ -1,5 +1,5 @@
import {BaseProvider, ExtractedInfo} from './base';
import {getFetch} from '..';
import {getFetch} from '../fetch';
/**
* @class LoveTikProvider

View File

@@ -1,4 +1,4 @@
import {getFetch} from '..';
import {getFetch} from '../fetch';
import {BaseProvider, ExtractedInfo} from './base';
/**

View File

@@ -1,4 +1,4 @@
import {getFetch} from '..';
import {getFetch} from '../fetch';
import {BaseProvider, ExtractedInfo} from './base';
import {deObfuscateSaveFromScript} from './utils';

View File

@@ -1,5 +1,5 @@
import {BaseProvider, ExtractedInfo} from './base';
import {getFetch} from '..';
import {getFetch} from '../fetch';
import {matchCustomDownload} from './utils';
/**

View File

@@ -1,4 +1,4 @@
import {getFetch} from '..';
import {getFetch} from '../fetch';
import {BaseProvider, ExtractedInfo} from './base';
import {deObfuscate, matchLink} from './utils';

View File

@@ -1,5 +1,5 @@
import {BaseProvider, ExtractedInfo} from './base';
import {getFetch} from '..';
import {getFetch} from '../fetch';
import {matchLink} from './utils';
/**

View File

@@ -1,4 +1,4 @@
import {getFetch} from '..';
import {getFetch} from '../fetch';
import {BaseProvider, ExtractedInfo} from './base';
import {deObfuscate, matchCustomDownload} from './utils';

View File

@@ -1,5 +1,5 @@
import {BaseProvider, ExtractedInfo} from './base';
import {getFetch} from '..';
import {getFetch} from '../fetch';
/**
* @class TokupProvider

View File

@@ -0,0 +1,60 @@
import {getFetch} from '../fetch';
import {BaseProvider, ExtractedInfo} from './base';
import {matchLink} from './utils';
/**
* @class TTDownloader
*/
export class TTDownloader extends BaseProvider {
/**
* @return {string}
*/
public resourceName(): string {
return 'ttdownloader';
}
public client = getFetch('https://ttdownloader.com');
public maintenance = undefined;
/**
*
* @param {string} url - Video TikTok URL
* @return {Promise<ExtractedInfo>}
*/
public async fetch(url: string): Promise<ExtractedInfo> {
// getting token and cookies
const firstResponse = await this.client('./');
const token = (firstResponse.body
.match(/name="token" value="(.*)?"/) as string[])[1];
const videoResponse = await this.client.post('./req', {
form: {
'token': token,
'format': '',
'url': url,
},
headers: {
'Origin': 'https://ttdownloader.com',
'Referer': 'https://ttdownloader.com',
'Cookie': firstResponse.headers['set-cookie']?.toString(),
},
});
return this.extract(videoResponse.body);
}
/**
*
* @param {string} html - HTML Raw
* @return {ExtractedInfo}
*/
extract(html: string): ExtractedInfo {
const urls = matchLink(html);
urls?.pop(); // remove 'https://snaptik.fans'
return {
'video': {
'urls': urls as string[],
},
};
}
};

View File

@@ -1,4 +1,4 @@
import {getFetch} from '..';
import {getFetch} from '../fetch';
import {BaseProvider, ExtractedInfo} from './base';
import {keyGeneratorTTSave, matchLink} from './utils';

View File

@@ -70,4 +70,4 @@ export const deObfuscateSaveFromScript = (scriptContent: string): string => {
});
const result = vm.run(safeScript, 'savefrom.js');
return result;
};r
};

View File

@@ -0,0 +1,19 @@
{
"compilerOptions": {
"allowJs": true,
"noEmit": true,
"strict": true,
"strictBindCallApply": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"outDir": "dist",
"target": "ES2016",
"module": "CommonJS",
"removeComments": true,
"esModuleInterop": true,
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"exclude": ["node_modules", "dist"]
}

View File

@@ -4,6 +4,7 @@
"build": {
"dependsOn": ["^build"]
},
"lint": {}
"lint": {},
"dev": {}
}
}

297
yarn.lock
View File

@@ -31,6 +31,66 @@
resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz"
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
"@next/env@12.0.10":
version "12.0.10"
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.0.10.tgz#561640fd62279218ccd2798ae907bae8d94a7730"
integrity sha512-mQVj0K6wQ5WEk/sL9SZ+mJXJUaG7el8CpZ6io1uFe9GgNTSC7EgUyNGqM6IQovIFc5ukF4O/hqsdh3S/DCgT2g==
"@next/swc-android-arm64@12.0.10":
version "12.0.10"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.0.10.tgz#fd9d716433cc9d361021b0052f8b002bcaff948d"
integrity sha512-xYwXGkNhzZZsM5MD7KRwF5ZNiC8OLPtVMUiagpPnwENg8Hb0GSQo/NbYWXM8YrawEwp9LaZ7OXiuRKPh2JyBdA==
"@next/swc-darwin-arm64@12.0.10":
version "12.0.10"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.0.10.tgz#34b2d0dc62eb89efb9176af111e3820a11fdb3f0"
integrity sha512-f2zngulkpIJKWHckhRi7X8GZ+J/tNgFF7lYIh7Qx15JH0OTBsjkqxORlkzy+VZyHJ5sWTCaI6HYYd3ow6qkEEg==
"@next/swc-darwin-x64@12.0.10":
version "12.0.10"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.0.10.tgz#a4306795159293c7d4d58a2c88ce1710ff0a8baa"
integrity sha512-Qykcu/gVC5oTvOQoRBhyuS5GYm5SbcgrFTsaLFkGBmEkg9eMQRiaCswk4IafpDXVzITkVFurzSM28q3tLW2qUw==
"@next/swc-linux-arm-gnueabihf@12.0.10":
version "12.0.10"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.0.10.tgz#1ad15af3d5fca2fef57894d61e16f73aee61ec2e"
integrity sha512-EhqrTFsIXAXN9B/fiiW/QKUK/lSLCXRsLalkUp58KDfMqVLLlj1ORbESAcswiNQOChLuHQSldGEEtOBPQZcd9A==
"@next/swc-linux-arm64-gnu@12.0.10":
version "12.0.10"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.0.10.tgz#a84a92d0e1a179c4346c9ed8f22e26f708101ad6"
integrity sha512-kqGtC72g3+JYXZbY2ca6digXR5U6AQ6Dzv4eAxYluMePLHjI/Xye1mf9dwVsgmeXfrD/IRDp5K/3A6UNvBm4oQ==
"@next/swc-linux-arm64-musl@12.0.10":
version "12.0.10"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.0.10.tgz#973ec96c77f845bd0a6eecbf1892caa1ee4defaf"
integrity sha512-bG9zTSNwnSgc1Un/7oz1ZVN4UeXsTWrsQhAGWU78lLLCn4Zj9HQoUCRCGLt0OVs2DBZ+WC8CzzFliQ1SKipVbg==
"@next/swc-linux-x64-gnu@12.0.10":
version "12.0.10"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.0.10.tgz#efcc7f8252ea8225834760eaf09350f1bead73f7"
integrity sha512-c79PcfWtyThiYRa1+3KVfDq0zXaI8o1d6dQWNVqDrtLz5HKM/rbjLdvoNuxDwUeZhxI/d9CtyH6GbuKPw5l/5A==
"@next/swc-linux-x64-musl@12.0.10":
version "12.0.10"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.0.10.tgz#c2a73d939dfd310acc1892a0a132762500dd5757"
integrity sha512-g/scgn+21/MLfizOCZOZt+MxNj2/8Tdlwjvy+QZcSUPZRUI2Y5o3HwBvI1f/bSci+NGRU+bUAO0NFtRJ9MzH5w==
"@next/swc-win32-arm64-msvc@12.0.10":
version "12.0.10"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.0.10.tgz#2316af5f612cde1691abdf2571ff40ec32ea3429"
integrity sha512-gl6B/ravwMeY5Nv4Il2/ARYJQ6u+KPRwGMjS1ZrNudIKlNn4YBeXh5A4cIVm+dHaff6/O/lGOa5/SUYDMZpkww==
"@next/swc-win32-ia32-msvc@12.0.10":
version "12.0.10"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.0.10.tgz#98a4f74d164871cfaccb0df6efddf2b7bcbaa54b"
integrity sha512-7RVpZ3tSThC6j+iZB0CUYmFiA3kXmN+pE7QcfyAxFaflKlaZoWNMKHIEZDuxSJc6YmQ6kyxsjqxVay2F5+/YCg==
"@next/swc-win32-x64-msvc@12.0.10":
version "12.0.10"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.0.10.tgz#5c0ba98b695c4be44d8793aff42971a0dac65c2d"
integrity sha512-oUIWRKd24jFLRWUYO1CZmML5+32BcpVfqhimGaaZIXcOkfQW+iqiAzdqsv688zaGtyKGeB9ZtiK3NDf+Q0v+Vw==
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz"
@@ -79,13 +139,6 @@
resolved "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz"
integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==
"@types/ioredis@^4.28.1":
version "4.28.1"
resolved "https://registry.yarnpkg.com/@types/ioredis/-/ioredis-4.28.1.tgz#27d66f4c0540145826d984b6d0a5b54bbb88c32a"
integrity sha512-raYHPqRWrfnEoym94BY28mG1+tcZqh3dsp2q7x5IyMAAEvIdu+H0X8diASMpncIm+oHyH9dalOeOnGOL/YnuOA==
dependencies:
"@types/node" "*"
"@types/json-schema@^7.0.9":
version "7.0.9"
resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz"
@@ -103,6 +156,20 @@
resolved "https://registry.npmjs.org/@types/node/-/node-16.11.6.tgz"
integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w==
"@types/prop-types@*":
version "15.7.4"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11"
integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==
"@types/react@^17.0.39":
version "17.0.39"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.39.tgz#d0f4cde092502a6db00a1cded6e6bf2abb7633ce"
integrity sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "*"
csstype "^3.0.2"
"@types/responselike@*", "@types/responselike@^1.0.0":
version "1.0.0"
resolved "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz"
@@ -110,6 +177,11 @@
dependencies:
"@types/node" "*"
"@types/scheduler@*":
version "0.16.2"
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
"@typescript-eslint/eslint-plugin@^5.3.0":
version "5.3.0"
resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.3.0.tgz"
@@ -180,15 +252,6 @@
"@typescript-eslint/types" "5.3.0"
eslint-visitor-keys "^3.0.0"
"@vercel/node@^1.12.1":
version "1.12.1"
resolved "https://registry.npmjs.org/@vercel/node/-/node-1.12.1.tgz"
integrity sha512-NcawIY05BvVkWlsowaxF2hl/hJg475U8JvT2FnGykFPMx31q1/FtqyTw/awSrKfOSRXR0InrbEIDIelmS9NzPA==
dependencies:
"@types/node" "*"
ts-node "8.9.1"
typescript "4.3.4"
acorn-jsx@^5.3.1:
version "5.3.2"
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
@@ -226,11 +289,6 @@ ansi-styles@^4.1.0:
dependencies:
color-convert "^2.0.1"
arg@^4.1.0:
version "4.1.3"
resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz"
integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
argparse@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz"
@@ -261,11 +319,6 @@ braces@^3.0.1:
dependencies:
fill-range "^7.0.1"
buffer-from@^1.0.0:
version "1.1.2"
resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz"
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
cacheable-lookup@^5.0.3:
version "5.0.4"
resolved "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz"
@@ -289,6 +342,11 @@ callsites@^3.0.0, callsites@^3.1.0:
resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz"
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
caniuse-lite@^1.0.30001283:
version "1.0.30001307"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001307.tgz#27a67f13ebc4aa9c977e6b8256a11d5eafb30f27"
integrity sha512-+MXEMczJ4FuxJAUp0jvAl6Df0NI/OfW1RWEE61eSmzS7hw6lz4IKutbhbXendwq8BljfFuHtu26VWsg4afQ7Ng==
chalk@^4.0.0:
version "4.1.2"
resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
@@ -335,6 +393,11 @@ cross-spawn@^7.0.2:
shebang-command "^2.0.0"
which "^2.0.1"
csstype@^3.0.2:
version "3.0.10"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.10.tgz#2ad3a7bed70f35b965707c092e5f30b327c290e5"
integrity sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==
debug@^4.1.1, debug@^4.3.1, debug@^4.3.2:
version "4.3.2"
resolved "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz"
@@ -364,11 +427,6 @@ denque@^1.1.0:
resolved "https://registry.yarnpkg.com/denque/-/denque-1.5.1.tgz#07f670e29c9a78f8faecb2566a1e2c11929c5cbf"
integrity sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==
diff@^4.0.1:
version "4.0.2"
resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz"
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
dir-glob@^3.0.1:
version "3.0.1"
resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz"
@@ -397,6 +455,14 @@ end-of-stream@^1.1.0:
dependencies:
once "^1.4.0"
enhanced-resolve@^5.7.0:
version "5.8.3"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz#6d552d465cce0423f5b3d718511ea53826a7b2f0"
integrity sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA==
dependencies:
graceful-fs "^4.2.4"
tapable "^2.2.0"
enquirer@^2.3.5:
version "2.3.6"
resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz"
@@ -404,6 +470,11 @@ enquirer@^2.3.5:
dependencies:
ansi-colors "^4.1.1"
escalade@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
escape-string-regexp@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz"
@@ -668,6 +739,11 @@ got@^11.8.2:
p-cancelable "^2.0.0"
responselike "^2.0.0"
graceful-fs@^4.2.4:
version "4.2.9"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96"
integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==
has-flag@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz"
@@ -771,6 +847,11 @@ isexe@^2.0.0:
resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz"
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
"js-tokens@^3.0.0 || ^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
js-yaml@^4.1.0:
version "4.1.0"
resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz"
@@ -833,6 +914,13 @@ lodash.merge@^4.6.2:
resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz"
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
loose-envify@^1.1.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
lowercase-keys@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz"
@@ -845,11 +933,6 @@ lru-cache@^6.0.0:
dependencies:
yallist "^4.0.0"
make-error@^1.1.1:
version "1.3.6"
resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz"
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
merge2@^1.3.0:
version "1.4.1"
resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz"
@@ -885,16 +968,57 @@ ms@2.1.2:
resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
nanoid@^3.1.30:
version "3.2.0"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c"
integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==
natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz"
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
next-transpile-modules@^9.0.0:
version "9.0.0"
resolved "https://registry.yarnpkg.com/next-transpile-modules/-/next-transpile-modules-9.0.0.tgz#133b1742af082e61cc76b02a0f12ffd40ce2bf90"
integrity sha512-VCNFOazIAnXn1hvgYYSTYMnoWgKgwlYh4lm1pKbSfiB3kj5ZYLcKVhfh3jkPOg1cnd9DP+pte9yCUocdPEUBTQ==
dependencies:
enhanced-resolve "^5.7.0"
escalade "^3.1.1"
next@^12.0.10:
version "12.0.10"
resolved "https://registry.yarnpkg.com/next/-/next-12.0.10.tgz#fcc4584177418bd777ce157f3165b7ba5e7708f7"
integrity sha512-1y3PpGzpb/EZzz1jgne+JfZXKAVJUjYXwxzrADf/LWN+8yi9o79vMLXpW3mevvCHkEF2sBnIdjzNn16TJrINUw==
dependencies:
"@next/env" "12.0.10"
caniuse-lite "^1.0.30001283"
postcss "8.4.5"
styled-jsx "5.0.0"
use-subscription "1.5.1"
optionalDependencies:
"@next/swc-android-arm64" "12.0.10"
"@next/swc-darwin-arm64" "12.0.10"
"@next/swc-darwin-x64" "12.0.10"
"@next/swc-linux-arm-gnueabihf" "12.0.10"
"@next/swc-linux-arm64-gnu" "12.0.10"
"@next/swc-linux-arm64-musl" "12.0.10"
"@next/swc-linux-x64-gnu" "12.0.10"
"@next/swc-linux-x64-musl" "12.0.10"
"@next/swc-win32-arm64-msvc" "12.0.10"
"@next/swc-win32-ia32-msvc" "12.0.10"
"@next/swc-win32-x64-msvc" "12.0.10"
normalize-url@^6.0.1:
version "6.1.0"
resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz"
integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==
object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
once@^1.3.0, once@^1.3.1, once@^1.4.0:
version "1.4.0"
resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz"
@@ -958,11 +1082,25 @@ path-type@^4.0.0:
resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz"
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
picocolors@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
picomatch@^2.2.3:
version "2.3.0"
resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz"
integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
postcss@8.4.5:
version "8.4.5"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95"
integrity sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==
dependencies:
nanoid "^3.1.30"
picocolors "^1.0.0"
source-map-js "^1.0.1"
prelude-ls@^1.2.1:
version "1.2.1"
resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz"
@@ -996,6 +1134,23 @@ quick-lru@^5.1.1:
resolved "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz"
integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
react-dom@^17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
scheduler "^0.20.2"
react@^17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
redis-commands@1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.7.0.tgz#15a6fea2d58281e27b1cd1acfb4b293e278c3a89"
@@ -1054,6 +1209,14 @@ run-parallel@^1.1.9:
dependencies:
queue-microtask "^1.2.2"
scheduler@^0.20.2:
version "0.20.2"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
semver@^7.2.1, semver@^7.3.5:
version "7.3.5"
resolved "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz"
@@ -1078,18 +1241,10 @@ slash@^3.0.0:
resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz"
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
source-map-support@^0.5.17:
version "0.5.20"
resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz"
integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==
dependencies:
buffer-from "^1.0.0"
source-map "^0.6.0"
source-map@^0.6.0:
version "0.6.1"
resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
source-map-js@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
standard-as-callback@^2.1.0:
version "2.1.0"
@@ -1108,6 +1263,11 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
styled-jsx@5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.0.tgz#816b4b92e07b1786c6b7111821750e0ba4d26e77"
integrity sha512-qUqsWoBquEdERe10EW8vLp3jT25s/ssG1/qX5gZ4wu15OZpmSMFI2v+fWlRhLfykA5rFtlJ1ME8A8pm/peV4WA==
supports-color@^7.1.0:
version "7.2.0"
resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz"
@@ -1115,6 +1275,11 @@ supports-color@^7.1.0:
dependencies:
has-flag "^4.0.0"
tapable@^2.2.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
text-table@^0.2.0:
version "0.2.0"
resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz"
@@ -1127,17 +1292,6 @@ to-regex-range@^5.0.1:
dependencies:
is-number "^7.0.0"
ts-node@8.9.1:
version "8.9.1"
resolved "https://registry.npmjs.org/ts-node/-/ts-node-8.9.1.tgz"
integrity sha512-yrq6ODsxEFTLz0R3BX2myf0WBCSQh9A+py8PBo1dCzWIOcvisbyH6akNKqDHMgXePF2kir5mm5JXJTH3OUJYOQ==
dependencies:
arg "^4.1.0"
diff "^4.0.1"
make-error "^1.1.1"
source-map-support "^0.5.17"
yn "3.1.1"
tslib@^1.8.1:
version "1.14.1"
resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz"
@@ -1245,15 +1399,10 @@ type-fest@^2.3.4:
resolved "https://registry.npmjs.org/type-fest/-/type-fest-2.5.2.tgz"
integrity sha512-WMbytmAs5PUTqwGJRE+WoRrD2S0bYFtHX8k4Y/1l18CG5kqA3keJud9pPQ/r30FE9n8XRFCXF9BbccHIZzRYJw==
typescript@4.3.4:
version "4.3.4"
resolved "https://registry.npmjs.org/typescript/-/typescript-4.3.4.tgz"
integrity sha512-uauPG7XZn9F/mo+7MrsRjyvbxFpzemRjKEZXS4AK83oP2KKOJPvb+9cO/gmnv8arWZvhnjVOXz7B49m1l0e9Ew==
typescript@^4.4.4:
version "4.4.4"
resolved "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz"
integrity sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==
typescript@latest:
version "4.5.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3"
integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==
uri-js@^4.2.2:
version "4.4.1"
@@ -1262,6 +1411,13 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
use-subscription@1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.5.1.tgz#73501107f02fad84c6dd57965beb0b75c68c42d1"
integrity sha512-Xv2a1P/yReAjAbhylMfFplFKj9GssgTwN7RlcTxBujFQcloStWNDQdc4g4NRWH9xS4i/FDk04vQBptAXoF3VcA==
dependencies:
object-assign "^4.1.1"
v8-compile-cache@^2.0.3:
version "2.3.0"
resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz"
@@ -1298,8 +1454,3 @@ yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
yn@3.1.1:
version "3.1.1"
resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz"
integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==