├── .gitignore ├── LICENSE.md ├── README.md ├── assets └── earth.mp4 ├── output └── dummy.txt ├── package.json ├── src ├── index.ts ├── interfaces │ └── splitter-job.ts ├── producer.ts ├── types │ └── index.ts ├── util │ └── ffmpeg.ts └── workers │ ├── concat.ts │ ├── splitter.ts │ ├── transcoder.ts │ └── worker.factory.ts ├── tsconfig.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright © 2022 Taskforce.sh 5 | 6 | Permission is hereby granted, free of charge, to any person 7 | obtaining a copy of this software and associated documentation 8 | files (the “Software”), to deal in the Software without 9 | restriction, including without limitation the rights to use, 10 | copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the 12 | Software is furnished to do so, subject to the following 13 | conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | OTHER DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BullMQ Video Transcoding 2 | 3 | This repo includes example source code for how to split a lengthy job into smaller chunks that can be processed in parallel, specifically for video transcoding, but the the same concept can be used for any other lengthy operation. 4 | 5 | In order to test it, just build the source code with ```yarn build```. You can then add an example video to the "splitter" queue with ```node dist/producer.js``` and then 6 | run the workers in order to process the video ```yarn start```. The results and temporary files will be placed in the output directory. 7 | 8 | Please check this blog post for more information: https://blog.taskforce.sh/splitting-heavy-jobs-using-bullmq-flows/ 9 | -------------------------------------------------------------------------------- /assets/earth.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taskforcesh/bullmq-video-transcoder/2ee8058895387ce19916a980ac6d7a29ce1267e0/assets/earth.mp4 -------------------------------------------------------------------------------- /output/dummy.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taskforcesh/bullmq-video-transcoder/2ee8058895387ce19916a980ac6d7a29ce1267e0/output/dummy.txt -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bullmq-typescript", 3 | "version": "1.0.0", 4 | "description": "BullMQ Example for Typescript", 5 | "license": "MIT", 6 | "bin": "src/index.ts", 7 | "scripts": { 8 | "build": "tsc", 9 | "start": "node './dist/index.js'", 10 | "dev": "tsc-watch --onSuccess \"node ./dist/index.js\" | pino-pretty", 11 | "test": "ts-mocha ./tests/**/*.test.ts" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/taskforcesh/bullmq-typescript.git" 16 | }, 17 | "keywords": [ 18 | "bullmq" 19 | ], 20 | "author": "Manuel Astudillo", 21 | "dependencies": { 22 | "any-shell-escape": "^0.1.1", 23 | "bullmq": "^1.85.3", 24 | "ffmpeg-static": "^5.0.0" 25 | }, 26 | "devDependencies": { 27 | "@types/node": "^17.0.41", 28 | "tsc-watch": "^5.0.3", 29 | "typescript": "^4.7.3" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | concatQueueName, 3 | splitterQueueName, 4 | transcoderQueueName, 5 | } from "./types"; 6 | import splitterProcessor from "./workers/splitter"; 7 | import transcoderProcessor from "./workers/transcoder"; 8 | import concatProcessor from "./workers/concat"; 9 | import { createWorker } from "./workers/worker.factory"; 10 | 11 | const connection = { 12 | host: "localhost", 13 | port: 6379, 14 | }; 15 | 16 | const { worker: splitterWorker, scheduler: splitterScheduler } = createWorker( 17 | splitterQueueName, 18 | splitterProcessor, 19 | connection 20 | ); 21 | 22 | const { worker: transcoderWorker, scheduler: transcoderScheduler } = 23 | createWorker(transcoderQueueName, transcoderProcessor, connection, 8); 24 | 25 | const { worker: concatWorker, scheduler: concatScheduler } = createWorker( 26 | concatQueueName, 27 | concatProcessor, 28 | connection 29 | ); 30 | 31 | process.on("SIGTERM", async () => { 32 | console.info("SIGTERM signal received: closing queues"); 33 | 34 | await splitterWorker.close(); 35 | await splitterScheduler.close(); 36 | await transcoderWorker.close(); 37 | await transcoderScheduler.close(); 38 | await concatWorker.close(); 39 | await concatScheduler.close(); 40 | 41 | console.info("All closed"); 42 | }); 43 | -------------------------------------------------------------------------------- /src/interfaces/splitter-job.ts: -------------------------------------------------------------------------------- 1 | export interface SplitterJob { 2 | videoFile: string; 3 | } 4 | -------------------------------------------------------------------------------- /src/producer.ts: -------------------------------------------------------------------------------- 1 | import { Queue } from "bullmq"; 2 | import { splitterQueueName } from "./types"; 3 | import { SplitterJob } from "./interfaces/splitter-job"; 4 | import path from "path"; 5 | 6 | const connection = { 7 | host: "localhost", 8 | port: 6379, 9 | }; 10 | 11 | const splitterQueue = new Queue(splitterQueueName, { connection }); 12 | 13 | async function addJobs() { 14 | console.log("Adding jobs..."); 15 | await splitterQueue.add("split", { 16 | videoFile: path.join(__dirname, "../assets/earth.mp4"), 17 | }); 18 | console.log("Done"); 19 | await splitterQueue.close(); 20 | } 21 | 22 | addJobs(); 23 | -------------------------------------------------------------------------------- /src/types/index.ts: -------------------------------------------------------------------------------- 1 | export const splitterQueueName = "splitter"; 2 | export const transcoderQueueName = "transcoder"; 3 | export const concatQueueName = "concat"; 4 | -------------------------------------------------------------------------------- /src/util/ffmpeg.ts: -------------------------------------------------------------------------------- 1 | import pathToFfmpeg from "ffmpeg-static"; 2 | import shell from "any-shell-escape"; 3 | const { exec } = require("child_process"); 4 | 5 | const ffmpeg = (input: string | null, flags: string, output: string) => { 6 | const args = `${pathToFfmpeg} ${ 7 | input ? "-i " + input : "" 8 | } ${flags} ${output}`; 9 | 10 | const transcode = shell(args.split(" ")); 11 | 12 | return new Promise((resolve, reject) => { 13 | exec(transcode, (err, stderr, stdout) => { 14 | if (err) { 15 | reject(err); 16 | } else { 17 | resolve(stdout); 18 | } 19 | }); 20 | }); 21 | }; 22 | 23 | export default ffmpeg; 24 | -------------------------------------------------------------------------------- /src/workers/concat.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from "path"; 2 | import { writeFile } from "fs"; 3 | 4 | import { Job } from "bullmq"; 5 | 6 | import { SplitterJob } from "../interfaces/splitter-job"; 7 | import ffmpeg from "../util/ffmpeg"; 8 | 9 | /** 10 | * Transcoder Worker 11 | * 12 | * This worker concatenate the video chunks into a single video. 13 | * 14 | */ 15 | export default async function (job: Job) { 16 | const transcodedChunks = await job.getChildrenValues(); 17 | const files = Object.values(transcodedChunks).sort(); 18 | 19 | console.log("Start concatenating files", files); 20 | 21 | await concat( 22 | job.id, 23 | files, 24 | resolve(process.cwd(), `output/merged-${job.id}.mp4`) 25 | ); 26 | } 27 | 28 | // https://stackoverflow.com/questions/7333232/how-to-concatenate-two-mp4-files-using-ffmpeg 29 | async function concat(jobId: string, files: string[], output: string) { 30 | const listFile = resolve(process.cwd(), `output/${jobId}.txt`); 31 | await new Promise((resolve, reject) => { 32 | writeFile( 33 | listFile, 34 | files.map((file) => `file '${file}'`).join("\n"), 35 | (err) => { 36 | if (err) { 37 | reject(err); 38 | } else { 39 | resolve(); 40 | } 41 | } 42 | ); 43 | }); 44 | 45 | await ffmpeg(null, `-f concat -safe 0 -i ${listFile} -c copy`, output); 46 | return output; 47 | } 48 | -------------------------------------------------------------------------------- /src/workers/splitter.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from "path"; 2 | 3 | import { Job, FlowProducer } from "bullmq"; 4 | import pathToFfmpeg from "ffmpeg-static"; 5 | 6 | import { SplitterJob } from "../interfaces/splitter-job"; 7 | import { concatQueueName, transcoderQueueName } from "../types"; 8 | 9 | import ffmpeg from "../util/ffmpeg"; 10 | 11 | /** 12 | * Splitter Worker 13 | * 14 | * This worker splits the video input into chunks and queues them for processing. 15 | * 16 | */ 17 | export default async function (job: Job) { 18 | const { videoFile } = job.data; 19 | 20 | console.log( 21 | `Start splitting video ${videoFile} using ${pathToFfmpeg}`, 22 | job.id, 23 | job.data 24 | ); 25 | 26 | // Split the video into chunks 27 | const chunks = await splitVideo(videoFile, job.id!); 28 | await addChunksToQueue(chunks); 29 | } 30 | 31 | async function splitVideo(videoFile: string, jobId: string) { 32 | // Split the video into chunks 33 | // around 20 seconds chunks 34 | const stdout = await ffmpeg( 35 | resolve(process.cwd(), videoFile), 36 | "-c copy -map 0 -segment_time 00:00:20 -f segment", 37 | resolve(process.cwd(), `output/${jobId}-part%03d.mp4`) 38 | ); 39 | 40 | return getChunks(stdout); 41 | } 42 | 43 | function getChunks(s: string) { 44 | const lines = s.split(/\n|\r/); 45 | const chunks = lines 46 | .filter((line) => line.startsWith("[segment @")) 47 | .map((line) => line.match("'(.*)'")[1]); 48 | 49 | return chunks; 50 | } 51 | 52 | async function addChunksToQueue(chunks: string[]) { 53 | const flowProducer = new FlowProducer(); 54 | 55 | return flowProducer.add({ 56 | name: "transcode", 57 | queueName: concatQueueName, 58 | children: chunks.map((chunk) => ({ 59 | name: "transcode-chunk", 60 | queueName: transcoderQueueName, 61 | data: { videoFile: chunk } as SplitterJob, 62 | })), 63 | }); 64 | } 65 | -------------------------------------------------------------------------------- /src/workers/transcoder.ts: -------------------------------------------------------------------------------- 1 | import { resolve, basename } from "path"; 2 | import { Job } from "bullmq"; 3 | 4 | import { SplitterJob } from "../interfaces/splitter-job"; 5 | import ffmpeg from "../util/ffmpeg"; 6 | 7 | /** 8 | * Transcoder Worker 9 | * 10 | * This worker transcodes the video input into a different format. 11 | * 12 | */ 13 | export default async function (job: Job) { 14 | const { videoFile } = job.data; 15 | console.log(`Start transcoding video ${videoFile}`); 16 | 17 | // Transcode video 18 | return transcodeVideo(videoFile, job.id!); 19 | } 20 | 21 | async function transcodeVideo(videoFile: string, jobId: string) { 22 | const srcName = basename(videoFile); 23 | const output = resolve(process.cwd(), `output/transcoded-${srcName}`); 24 | 25 | await ffmpeg( 26 | resolve(process.cwd(), videoFile), 27 | "-c:v libx264 -preset slow -crf 20 -c:a aac -b:a 16k -vf scale=320:240", 28 | output 29 | ); 30 | 31 | return output; 32 | } 33 | -------------------------------------------------------------------------------- /src/workers/worker.factory.ts: -------------------------------------------------------------------------------- 1 | import { Worker, QueueScheduler, Processor, ConnectionOptions } from "bullmq"; 2 | 3 | export function createWorker( 4 | name: string, 5 | processor: Processor, 6 | connection: ConnectionOptions, 7 | concurrency = 1 8 | ) { 9 | const worker = new Worker(name, processor, { 10 | connection, 11 | concurrency, 12 | }); 13 | 14 | worker.on("completed", (job, err) => { 15 | console.log(`Completed job on queue ${name}`); 16 | }); 17 | 18 | worker.on("failed", (job, err) => { 19 | console.log(`Faille job on queue ${name}`, err); 20 | }); 21 | 22 | const scheduler = new QueueScheduler(name, { 23 | connection, 24 | }); 25 | 26 | return { worker, scheduler }; 27 | } 28 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "dist", 4 | "target": "es6", 5 | "esModuleInterop": true, 6 | "moduleResolution": "node", 7 | "module": "commonjs" 8 | }, 9 | "include": ["./src/**/*"] 10 | } 11 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@derhuerst/http-basic@^8.2.0": 6 | version "8.2.2" 7 | resolved "https://registry.yarnpkg.com/@derhuerst/http-basic/-/http-basic-8.2.2.tgz#48c88e66c4d47db3b20dd906693f897b22444a27" 8 | integrity sha512-ek065nW95mleLHo8vZ+ob7QTQPNOwDEjCe27BX2flme/UTu9z2mD1uRRPko38u7al4tTZADMtozpll8PQHAZgg== 9 | dependencies: 10 | caseless "^0.12.0" 11 | concat-stream "^1.6.2" 12 | http-response-object "^3.0.1" 13 | parse-cache-control "^1.0.1" 14 | 15 | "@msgpackr-extract/msgpackr-extract-darwin-arm64@2.0.2": 16 | version "2.0.2" 17 | resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-2.0.2.tgz#01e3669b8b2dc01f6353f2c87e1ec94faf52c587" 18 | integrity sha512-FMX5i7a+ojIguHpWbzh5MCsCouJkwf4z4ejdUY/fsgB9Vkdak4ZnoIEskOyOUMMB4lctiZFGszFQJXUeFL8tRg== 19 | 20 | "@msgpackr-extract/msgpackr-extract-darwin-x64@2.0.2": 21 | version "2.0.2" 22 | resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-2.0.2.tgz#5ca32f16e6f1b7854001a1a2345b61d4e26a0931" 23 | integrity sha512-DznYtF3lHuZDSRaIOYeif4JgO0NtO2Xf8DsngAugMx/bUdTFbg86jDTmkVJBNmV+cxszz6OjGvinnS8AbJ342g== 24 | 25 | "@msgpackr-extract/msgpackr-extract-linux-arm64@2.0.2": 26 | version "2.0.2" 27 | resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-2.0.2.tgz#ff629f94379981bf476dffb1439a7c1d3dba2d72" 28 | integrity sha512-b0jMEo566YdM2K+BurSed7bswjo3a6bcdw5ETqoIfSuxKuRLPfAiOjVbZyZBgx3J/TAM/QrvEQ/VN89A0ZAxSg== 29 | 30 | "@msgpackr-extract/msgpackr-extract-linux-arm@2.0.2": 31 | version "2.0.2" 32 | resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-2.0.2.tgz#5f6fd30d266c4a90cf989049c7f2e50e5d4fcd4c" 33 | integrity sha512-Gy9+c3Wj+rUlD3YvCZTi92gs+cRX7ZQogtwq0IhRenloTTlsbpezNgk6OCkt59V4ATEWSic9rbU92H/l7XsRvA== 34 | 35 | "@msgpackr-extract/msgpackr-extract-linux-x64@2.0.2": 36 | version "2.0.2" 37 | resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-2.0.2.tgz#167faa553b9dbffac8b03bf27de9b6f846f0e1bc" 38 | integrity sha512-zrBHaePwcv4cQXxzYgNj0+A8I1uVN97E7/3LmkRocYZ+rMwUsnPpp4RuTAHSRoKlTQV3nSdCQW4Qdt4MXw/iHw== 39 | 40 | "@msgpackr-extract/msgpackr-extract-win32-x64@2.0.2": 41 | version "2.0.2" 42 | resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-2.0.2.tgz#baea7764b1adf201ce4a792fe971fd7211dad2e4" 43 | integrity sha512-fpnI00dt+yO1cKx9qBXelKhPBdEgvc8ZPav1+0r09j0woYQU2N79w/jcGawSY5UGlgQ3vjaJsFHnGbGvvqdLzg== 44 | 45 | "@types/node@^10.0.3": 46 | version "10.17.60" 47 | resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b" 48 | integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== 49 | 50 | "@types/node@^17.0.41": 51 | version "17.0.41" 52 | resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.41.tgz#1607b2fd3da014ae5d4d1b31bc792a39348dfb9b" 53 | integrity sha512-xA6drNNeqb5YyV5fO3OAEsnXLfO7uF0whiOfPTz5AeDo8KeZFmODKnvwPymMNO8qE/an8pVY/O50tig2SQCrGw== 54 | 55 | agent-base@6: 56 | version "6.0.2" 57 | resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" 58 | integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== 59 | dependencies: 60 | debug "4" 61 | 62 | ansi-regex@^5.0.1: 63 | version "5.0.1" 64 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 65 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 66 | 67 | any-shell-escape@^0.1.1: 68 | version "0.1.1" 69 | resolved "https://registry.yarnpkg.com/any-shell-escape/-/any-shell-escape-0.1.1.tgz#d55ab972244c71a9a5e1ab0879f30bf110806959" 70 | integrity sha512-36j4l5HVkboyRhIWgtMh1I9i8LTdFqVwDEHy1cp+QioJyKgAUG40X0W8s7jakWRta/Sjvm8mUG1fU6Tj8mWagQ== 71 | 72 | balanced-match@^1.0.0: 73 | version "1.0.2" 74 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 75 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 76 | 77 | brace-expansion@^1.1.7: 78 | version "1.1.11" 79 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 80 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 81 | dependencies: 82 | balanced-match "^1.0.0" 83 | concat-map "0.0.1" 84 | 85 | buffer-from@^1.0.0: 86 | version "1.1.2" 87 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" 88 | integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== 89 | 90 | bullmq@^1.85.3: 91 | version "1.85.4" 92 | resolved "https://registry.yarnpkg.com/bullmq/-/bullmq-1.85.4.tgz#196569ed549280f55f961d1b91efdb97e9083f49" 93 | integrity sha512-sFeWGJLPDXzYtYmWqyS5aqVL5zv53U1sNaqBL1z/Dt8ib7icy33uzl0uUh1u5AsKcvQJjOaegD0eHwYhnzo9fQ== 94 | dependencies: 95 | cron-parser "^4.2.1" 96 | get-port "^5.1.1" 97 | glob "^7.2.0" 98 | ioredis "^4.28.5" 99 | lodash "^4.17.21" 100 | msgpackr "^1.4.6" 101 | semver "^7.3.7" 102 | tslib "^1.14.1" 103 | uuid "^8.3.2" 104 | 105 | caseless@^0.12.0: 106 | version "0.12.0" 107 | resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" 108 | integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== 109 | 110 | cluster-key-slot@^1.1.0: 111 | version "1.1.0" 112 | resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz#30474b2a981fb12172695833052bc0d01336d10d" 113 | integrity sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw== 114 | 115 | concat-map@0.0.1: 116 | version "0.0.1" 117 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 118 | integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== 119 | 120 | concat-stream@^1.6.2: 121 | version "1.6.2" 122 | resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" 123 | integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== 124 | dependencies: 125 | buffer-from "^1.0.0" 126 | inherits "^2.0.3" 127 | readable-stream "^2.2.2" 128 | typedarray "^0.0.6" 129 | 130 | core-util-is@~1.0.0: 131 | version "1.0.3" 132 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" 133 | integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== 134 | 135 | cron-parser@^4.2.1: 136 | version "4.4.0" 137 | resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-4.4.0.tgz#829d67f9e68eb52fa051e62de0418909f05db983" 138 | integrity sha512-TrE5Un4rtJaKgmzPewh67yrER5uKM0qI9hGLDBfWb8GGRe9pn/SDkhVrdHa4z7h0SeyeNxnQnogws/H+AQANQA== 139 | dependencies: 140 | luxon "^1.28.0" 141 | 142 | cross-spawn@^7.0.3: 143 | version "7.0.3" 144 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" 145 | integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== 146 | dependencies: 147 | path-key "^3.1.0" 148 | shebang-command "^2.0.0" 149 | which "^2.0.1" 150 | 151 | debug@4, debug@^4.3.1: 152 | version "4.3.4" 153 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" 154 | integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== 155 | dependencies: 156 | ms "2.1.2" 157 | 158 | denque@^1.1.0: 159 | version "1.5.1" 160 | resolved "https://registry.yarnpkg.com/denque/-/denque-1.5.1.tgz#07f670e29c9a78f8faecb2566a1e2c11929c5cbf" 161 | integrity sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw== 162 | 163 | duplexer@~0.1.1: 164 | version "0.1.2" 165 | resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" 166 | integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== 167 | 168 | env-paths@^2.2.0: 169 | version "2.2.1" 170 | resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" 171 | integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== 172 | 173 | event-stream@=3.3.4: 174 | version "3.3.4" 175 | resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" 176 | integrity sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g== 177 | dependencies: 178 | duplexer "~0.1.1" 179 | from "~0" 180 | map-stream "~0.1.0" 181 | pause-stream "0.0.11" 182 | split "0.3" 183 | stream-combiner "~0.0.4" 184 | through "~2.3.1" 185 | 186 | ffmpeg-static@^5.0.0: 187 | version "5.0.0" 188 | resolved "https://registry.yarnpkg.com/ffmpeg-static/-/ffmpeg-static-5.0.0.tgz#adb2d083c5160e034c1053164d214953e061e368" 189 | integrity sha512-z96jGVa8uCVMnyrTvbDZe0d5zbvIVQnfBN+vKDZoVK+ssYpfUJGEmo2DkuY43CA9Ytlsk+5ZVTFTqzvKw1gSaA== 190 | dependencies: 191 | "@derhuerst/http-basic" "^8.2.0" 192 | env-paths "^2.2.0" 193 | https-proxy-agent "^5.0.0" 194 | progress "^2.0.3" 195 | 196 | from@~0: 197 | version "0.1.7" 198 | resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" 199 | integrity sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g== 200 | 201 | fs.realpath@^1.0.0: 202 | version "1.0.0" 203 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 204 | integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== 205 | 206 | get-port@^5.1.1: 207 | version "5.1.1" 208 | resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" 209 | integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ== 210 | 211 | glob@^7.2.0: 212 | version "7.2.3" 213 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" 214 | integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== 215 | dependencies: 216 | fs.realpath "^1.0.0" 217 | inflight "^1.0.4" 218 | inherits "2" 219 | minimatch "^3.1.1" 220 | once "^1.3.0" 221 | path-is-absolute "^1.0.0" 222 | 223 | http-response-object@^3.0.1: 224 | version "3.0.2" 225 | resolved "https://registry.yarnpkg.com/http-response-object/-/http-response-object-3.0.2.tgz#7f435bb210454e4360d074ef1f989d5ea8aa9810" 226 | integrity sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA== 227 | dependencies: 228 | "@types/node" "^10.0.3" 229 | 230 | https-proxy-agent@^5.0.0: 231 | version "5.0.1" 232 | resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" 233 | integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== 234 | dependencies: 235 | agent-base "6" 236 | debug "4" 237 | 238 | inflight@^1.0.4: 239 | version "1.0.6" 240 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 241 | integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== 242 | dependencies: 243 | once "^1.3.0" 244 | wrappy "1" 245 | 246 | inherits@2, inherits@^2.0.3, inherits@~2.0.3: 247 | version "2.0.4" 248 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 249 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 250 | 251 | ioredis@^4.28.5: 252 | version "4.28.5" 253 | resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.28.5.tgz#5c149e6a8d76a7f8fa8a504ffc85b7d5b6797f9f" 254 | integrity sha512-3GYo0GJtLqgNXj4YhrisLaNNvWSNwSS2wS4OELGfGxH8I69+XfNdnmV1AyN+ZqMh0i7eX+SWjrwFKDBDgfBC1A== 255 | dependencies: 256 | cluster-key-slot "^1.1.0" 257 | debug "^4.3.1" 258 | denque "^1.1.0" 259 | lodash.defaults "^4.2.0" 260 | lodash.flatten "^4.4.0" 261 | lodash.isarguments "^3.1.0" 262 | p-map "^2.1.0" 263 | redis-commands "1.7.0" 264 | redis-errors "^1.2.0" 265 | redis-parser "^3.0.0" 266 | standard-as-callback "^2.1.0" 267 | 268 | isarray@~1.0.0: 269 | version "1.0.0" 270 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 271 | integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== 272 | 273 | isexe@^2.0.0: 274 | version "2.0.0" 275 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 276 | integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== 277 | 278 | lodash.defaults@^4.2.0: 279 | version "4.2.0" 280 | resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" 281 | integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== 282 | 283 | lodash.flatten@^4.4.0: 284 | version "4.4.0" 285 | resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" 286 | integrity sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g== 287 | 288 | lodash.isarguments@^3.1.0: 289 | version "3.1.0" 290 | resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" 291 | integrity sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg== 292 | 293 | lodash@^4.17.21: 294 | version "4.17.21" 295 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 296 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 297 | 298 | lru-cache@^6.0.0: 299 | version "6.0.0" 300 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" 301 | integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== 302 | dependencies: 303 | yallist "^4.0.0" 304 | 305 | luxon@^1.28.0: 306 | version "1.28.0" 307 | resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.28.0.tgz#e7f96daad3938c06a62de0fb027115d251251fbf" 308 | integrity sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ== 309 | 310 | map-stream@~0.1.0: 311 | version "0.1.0" 312 | resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" 313 | integrity sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g== 314 | 315 | minimatch@^3.1.1: 316 | version "3.1.2" 317 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" 318 | integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== 319 | dependencies: 320 | brace-expansion "^1.1.7" 321 | 322 | ms@2.1.2: 323 | version "2.1.2" 324 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 325 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 326 | 327 | msgpackr-extract@^2.0.2: 328 | version "2.0.2" 329 | resolved "https://registry.yarnpkg.com/msgpackr-extract/-/msgpackr-extract-2.0.2.tgz#201a8d7ade47e99b3ba277c45736b00e195d4670" 330 | integrity sha512-coskCeJG2KDny23zWeu+6tNy7BLnAiOGgiwzlgdm4oeSsTpqEJJPguHIuKZcCdB7tzhZbXNYSg6jZAXkZErkJA== 331 | dependencies: 332 | node-gyp-build-optional-packages "5.0.2" 333 | optionalDependencies: 334 | "@msgpackr-extract/msgpackr-extract-darwin-arm64" "2.0.2" 335 | "@msgpackr-extract/msgpackr-extract-darwin-x64" "2.0.2" 336 | "@msgpackr-extract/msgpackr-extract-linux-arm" "2.0.2" 337 | "@msgpackr-extract/msgpackr-extract-linux-arm64" "2.0.2" 338 | "@msgpackr-extract/msgpackr-extract-linux-x64" "2.0.2" 339 | "@msgpackr-extract/msgpackr-extract-win32-x64" "2.0.2" 340 | 341 | msgpackr@^1.4.6: 342 | version "1.6.1" 343 | resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.6.1.tgz#4f3c94d6a5b819b838ffc736eddaf60eba436d20" 344 | integrity sha512-Je+xBEfdjtvA4bKaOv8iRhjC8qX2oJwpYH4f7JrG4uMVJVmnmkAT4pjKdbztKprGj3iwjcxPzb5umVZ02Qq3tA== 345 | optionalDependencies: 346 | msgpackr-extract "^2.0.2" 347 | 348 | node-cleanup@^2.1.2: 349 | version "2.1.2" 350 | resolved "https://registry.yarnpkg.com/node-cleanup/-/node-cleanup-2.1.2.tgz#7ac19abd297e09a7f72a71545d951b517e4dde2c" 351 | integrity sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw== 352 | 353 | node-gyp-build-optional-packages@5.0.2: 354 | version "5.0.2" 355 | resolved "https://registry.yarnpkg.com/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.2.tgz#3de7d30bd1f9057b5dfbaeab4a4442b7fe9c5901" 356 | integrity sha512-PiN4NWmlQPqvbEFcH/omQsswWQbe5Z9YK/zdB23irp5j2XibaA2IrGvpSWmVVG4qMZdmPdwPctSy4a86rOMn6g== 357 | 358 | once@^1.3.0: 359 | version "1.4.0" 360 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 361 | integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== 362 | dependencies: 363 | wrappy "1" 364 | 365 | p-map@^2.1.0: 366 | version "2.1.0" 367 | resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" 368 | integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== 369 | 370 | parse-cache-control@^1.0.1: 371 | version "1.0.1" 372 | resolved "https://registry.yarnpkg.com/parse-cache-control/-/parse-cache-control-1.0.1.tgz#8eeab3e54fa56920fe16ba38f77fa21aacc2d74e" 373 | integrity sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg== 374 | 375 | path-is-absolute@^1.0.0: 376 | version "1.0.1" 377 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 378 | integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== 379 | 380 | path-key@^3.1.0: 381 | version "3.1.1" 382 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" 383 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 384 | 385 | pause-stream@0.0.11: 386 | version "0.0.11" 387 | resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" 388 | integrity sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A== 389 | dependencies: 390 | through "~2.3" 391 | 392 | process-nextick-args@~2.0.0: 393 | version "2.0.1" 394 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" 395 | integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== 396 | 397 | progress@^2.0.3: 398 | version "2.0.3" 399 | resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" 400 | integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== 401 | 402 | ps-tree@^1.2.0: 403 | version "1.2.0" 404 | resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd" 405 | integrity sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA== 406 | dependencies: 407 | event-stream "=3.3.4" 408 | 409 | readable-stream@^2.2.2: 410 | version "2.3.7" 411 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" 412 | integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== 413 | dependencies: 414 | core-util-is "~1.0.0" 415 | inherits "~2.0.3" 416 | isarray "~1.0.0" 417 | process-nextick-args "~2.0.0" 418 | safe-buffer "~5.1.1" 419 | string_decoder "~1.1.1" 420 | util-deprecate "~1.0.1" 421 | 422 | redis-commands@1.7.0: 423 | version "1.7.0" 424 | resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.7.0.tgz#15a6fea2d58281e27b1cd1acfb4b293e278c3a89" 425 | integrity sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ== 426 | 427 | redis-errors@^1.0.0, redis-errors@^1.2.0: 428 | version "1.2.0" 429 | resolved "https://registry.yarnpkg.com/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad" 430 | integrity sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w== 431 | 432 | redis-parser@^3.0.0: 433 | version "3.0.0" 434 | resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-3.0.0.tgz#b66d828cdcafe6b4b8a428a7def4c6bcac31c8b4" 435 | integrity sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A== 436 | dependencies: 437 | redis-errors "^1.0.0" 438 | 439 | safe-buffer@~5.1.0, safe-buffer@~5.1.1: 440 | version "5.1.2" 441 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 442 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 443 | 444 | semver@^7.3.7: 445 | version "7.3.7" 446 | resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" 447 | integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== 448 | dependencies: 449 | lru-cache "^6.0.0" 450 | 451 | shebang-command@^2.0.0: 452 | version "2.0.0" 453 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" 454 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 455 | dependencies: 456 | shebang-regex "^3.0.0" 457 | 458 | shebang-regex@^3.0.0: 459 | version "3.0.0" 460 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" 461 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 462 | 463 | split@0.3: 464 | version "0.3.3" 465 | resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" 466 | integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8= 467 | dependencies: 468 | through "2" 469 | 470 | standard-as-callback@^2.1.0: 471 | version "2.1.0" 472 | resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" 473 | integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A== 474 | 475 | stream-combiner@~0.0.4: 476 | version "0.0.4" 477 | resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" 478 | integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ= 479 | dependencies: 480 | duplexer "~0.1.1" 481 | 482 | string-argv@^0.1.1: 483 | version "0.1.2" 484 | resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.1.2.tgz#c5b7bc03fb2b11983ba3a72333dd0559e77e4738" 485 | integrity sha512-mBqPGEOMNJKXRo7z0keX0wlAhbBAjilUdPW13nN0PecVryZxdHIeM7TqbsSUA7VYuS00HGC6mojP7DlQzfa9ZA== 486 | 487 | string_decoder@~1.1.1: 488 | version "1.1.1" 489 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" 490 | integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== 491 | dependencies: 492 | safe-buffer "~5.1.0" 493 | 494 | strip-ansi@^6.0.0: 495 | version "6.0.1" 496 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 497 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 498 | dependencies: 499 | ansi-regex "^5.0.1" 500 | 501 | through@2, through@~2.3, through@~2.3.1: 502 | version "2.3.8" 503 | resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" 504 | integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= 505 | 506 | tsc-watch@^5.0.3: 507 | version "5.0.3" 508 | resolved "https://registry.yarnpkg.com/tsc-watch/-/tsc-watch-5.0.3.tgz#4d0b2bda8f2677c8f9ed36e001c1a86c31701145" 509 | integrity sha512-Hz2UawwELMSLOf0xHvAFc7anLeMw62cMVXr1flYmhRuOhOyOljwmb1l/O60ZwRyy1k7N1iC1mrn1QYM2zITfuw== 510 | dependencies: 511 | cross-spawn "^7.0.3" 512 | node-cleanup "^2.1.2" 513 | ps-tree "^1.2.0" 514 | string-argv "^0.1.1" 515 | strip-ansi "^6.0.0" 516 | 517 | tslib@^1.14.1: 518 | version "1.14.1" 519 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" 520 | integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== 521 | 522 | typedarray@^0.0.6: 523 | version "0.0.6" 524 | resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" 525 | integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= 526 | 527 | typescript@^4.7.3: 528 | version "4.7.3" 529 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.3.tgz#8364b502d5257b540f9de4c40be84c98e23a129d" 530 | integrity sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA== 531 | 532 | util-deprecate@~1.0.1: 533 | version "1.0.2" 534 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 535 | integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= 536 | 537 | uuid@^8.3.2: 538 | version "8.3.2" 539 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" 540 | integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== 541 | 542 | which@^2.0.1: 543 | version "2.0.2" 544 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 545 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 546 | dependencies: 547 | isexe "^2.0.0" 548 | 549 | wrappy@1: 550 | version "1.0.2" 551 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 552 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 553 | 554 | yallist@^4.0.0: 555 | version "4.0.0" 556 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" 557 | integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== 558 | --------------------------------------------------------------------------------