diff --git a/.gitignore b/.gitignore index 2e03175..fbffcc9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ .env -repositories/ +/repositories repo/ db_backups message.txt diff --git a/config.js b/config.js deleted file mode 100644 index f402c3a..0000000 --- a/config.js +++ /dev/null @@ -1,16 +0,0 @@ -const config = { - CLIENT_ID: null, - CLIENT_SECRET: null, - GITHUB_TOKEN: null, - MAX_FILE_SIZE: 10 * 1024 * 1024, // in b - MAX_REPO_SIZE: 8 * 1024, // in kb - AUTH_CALLBACK: "http://localhost:5000/github/auth", - ANONYMIZATION_MASK: "XXXX", - PORT: 5000, -}; -for (let conf in process.env) { - if (config[conf] !== undefined) { - config[conf] = process.env[conf]; - } -} -module.exports = config; diff --git a/config.ts b/config.ts new file mode 100644 index 0000000..6c545d9 --- /dev/null +++ b/config.ts @@ -0,0 +1,74 @@ +import { resolve } from "path"; + +interface Config { + REDIS_PORT: number; + REDIS_HOSTNAME: string; + CLIENT_ID: string; + CLIENT_SECRET: string; + GITHUB_TOKEN: string; + DEFAULT_QUOTA: number; + MAX_FILE_SIZE: number; + MAX_REPO_SIZE: number; + AUTH_CALLBACK: string; + /** + * Allow to download repository and files + */ + ENABLE_DOWNLOAD: boolean; + ANONYMIZATION_MASK: string; + PORT: number; + HOSTNAME: string; + DB_USERNAME: string; + DB_PASSWORD: string; + DB_HOSTNAME: string; + FOLDER: string; + additionalExtensions: string[]; + S3_BUCKET?: string; + S3_CLIENT_ID?: string; + S3_CLIENT_SECRET?: string; + S3_ENDPOINT?: string; + S3_REGION?: string; + STORAGE: "filesystem" | "s3"; +} +const config: Config = { + CLIENT_ID: "CLIENT_ID", + CLIENT_SECRET: "CLIENT_SECRET", + GITHUB_TOKEN: "", + DEFAULT_QUOTA: 2 * 1024 * 1024 * 1024 * 8, + MAX_FILE_SIZE: 10 * 1024 * 1024, // in b + MAX_REPO_SIZE: 8 * 1024, // in kb + ENABLE_DOWNLOAD: false, + AUTH_CALLBACK: "http://localhost:5000/github/auth", + ANONYMIZATION_MASK: "XXXX", + PORT: 5000, + HOSTNAME: "anonymous.4open.science", + DB_USERNAME: "admin", + DB_PASSWORD: "password", + DB_HOSTNAME: "mongodb", + REDIS_HOSTNAME: "redis", + REDIS_PORT: 6379, + FOLDER: resolve(__dirname, "repositories"), + additionalExtensions: [ + "license", + "dockerfile", + "sbt", + "ipynb", + "gp", + "out", + "sol", + "in", + ], + STORAGE: "filesystem", + S3_BUCKET: null, + S3_CLIENT_ID: null, + S3_CLIENT_SECRET: null, + S3_ENDPOINT: null, + S3_REGION: null, +}; + +for (let conf in process.env) { + if ((config as any)[conf] !== undefined) { + (config as any)[conf] = process.env[conf]; + } +} + +export default config; diff --git a/docker-compose.yml b/docker-compose.yml index dea6c0b..f56d1bb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,6 +9,9 @@ services: container_name: anonymous_github env_file: - ./.env + environment: + - REDIS_HOSTNAME=redis + - DB_HOSTNAME=mongodb volumes: - .:/app # - ./repositories:/app/repositories diff --git a/index.js b/index.js deleted file mode 100644 index 4e5ae6e..0000000 --- a/index.js +++ /dev/null @@ -1,109 +0,0 @@ -const path = require("path"); -const ofs = require("fs"); -const redis = require("redis"); -const RateLimit = require("express-rate-limit"); -const RedisStore = require("rate-limit-redis"); -const express = require("express"); -const compression = require("compression"); -const bodyParser = require("body-parser"); - -const config = require("./config"); -const rediscli = redis.createClient({ - host: "redis", - ttl: 260, -}); - -const connection = require("./routes/connection"); - -const db = require("./utils/database"); -const fileUtils = require("./utils/file"); - -const app = express(); -app.use(bodyParser.json()); -app.use(compression()); -app.set("trust proxy", 1); - -// handle session and connection -app.use(connection.session); -app.use(connection.passport.initialize()); -app.use(connection.passport.session()); - -const rateLimit = new RateLimit({ - store: new RedisStore({ - client: rediscli, - }), - windowMs: 15 * 60 * 1000, // 15 minutes - max: 200, // limit each IP to 100 requests per windowMs - // delayMs: 0, // disable delaying - full speed until the max limit is reached -}); - -app.use("/github", rateLimit, connection.router); - -// app routes -app.use("/api/user", rateLimit, require("./routes/user")); -app.use("/api/repo", rateLimit, require("./routes/file")); -app.use("/api/repo", rateLimit, require("./routes/repository")); - -// wesite view -app.use("/w/", rateLimit, require("./routes/webview")); - -app.get("/api/supportedTypes", async (_, res) => { - res.json( - require("textextensions") - .default.concat(fileUtils.additionalExtensions) - .sort() - ); -}); - -app.get("/api/message", async (_, res) => { - if (ofs.existsSync("./message.txt")) { - return res.sendFile(path.resolve(__dirname, "message.txt")); - } - res.sendStatus(404); -}); - -app.get("/api/stat", async (_, res) => { - const nbRepositories = await db - .get("anonymized_repositories") - .estimatedDocumentCount(); - - const nbUsers = (await db.get("anonymized_repositories").distinct("owner")) - .length; //await db.get("users").estimatedDocumentCount(); - res.json({ nbRepositories, nbUsers }); -}); - -function indexResponse(req, res) { - if ( - req.params.repoId && - req.headers["accept"] && - req.headers["accept"].indexOf("text/html") == -1 - ) { - const repoId = req.path.split("/")[2]; - // if it is not an html request, it assumes that the browser try to load a different type of resource - return res.redirect( - `/api/repo/${repoId}/file/${req.path.substring( - req.path.indexOf(repoId) + repoId.length + 1 - )}` - ); - } - res.sendFile(path.resolve(__dirname, "public", "index.html")); -} - -app - .get("/", indexResponse) - .get("/404", indexResponse) - .get("/anonymize", indexResponse) - .get("/r/:repoId/?*", indexResponse) - .get("/repository/:repoId/?*", indexResponse); - -app.use(express.static(__dirname + "/public")); - -app.get("*", indexResponse); - -db.connect().then((_) => { - app.listen(config.PORT, () => { - console.log( - "Database connected and Server started on port: " + config.PORT - ); - }); -}); diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..462137e --- /dev/null +++ b/index.ts @@ -0,0 +1,6 @@ +require("dotenv").config(); + +import server from "./src/server"; + +// start the server +server(); diff --git a/migrateDB.ts b/migrateDB.ts new file mode 100644 index 0000000..5da9212 --- /dev/null +++ b/migrateDB.ts @@ -0,0 +1,178 @@ +import * as mongoose from "mongoose"; +import config from "./config"; +import * as database from "./src/database/database"; +import RepositoryModel from "./src/database/repositories/repositories.model"; +import AnonymizedRepositoryModel from "./src/database/anonymizedRepositories/anonymizedRepositories.model"; +import UserModel from "./src/database/users/users.model"; +import { IRepositoryDocument } from "./src/database/repositories/repositories.types"; +import { LexRuntime } from "aws-sdk"; + +const MONGO_URL = `mongodb://${config.DB_USERNAME}:${config.DB_PASSWORD}@${config.DB_HOSTNAME}:27017/`; + +async function connect(db) { + const t = new mongoose.Mongoose(); + t.set("useNewUrlParser", true); + t.set("useFindAndModify", true); + t.set("useUnifiedTopology", true); + + const database = t.connection; + + await t.connect(MONGO_URL + db, { + authSource: "admin", + useCreateIndex: true, + useFindAndModify: true, + }); + + return database; +} + +(async () => { + await database.connect(); + const oldDB = await connect("anonymous_github"); + + console.log("Import Users"); + await new Promise(async (resolve) => { + const promises = []; + await oldDB + .collection("users") + .find() + .batchSize(1) + .forEach(async (r) => { + let localResolve = null; + const p = new Promise((r) => (localResolve = r)); + promises.push(p); + + const repositoryModels: Promise[] = []; + const finds = ( + await RepositoryModel.find({ + externalId: { + $in: r.repositories.map((repo) => "gh_" + repo.id), + }, + }).select("externalId") + ).map((m) => m.externalId); + for (const repo of r.repositories.filter( + (f) => finds.indexOf("gh_" + f.id) == -1 + )) { + repositoryModels.push( + new RepositoryModel({ + externalId: "gh_" + repo.id, + name: repo.full_name, + url: repo.html_url, + size: repo.size, + defaultBranch: repo.default_branch, + }).save() + ); + } + const user = await new UserModel({ + accessToken: r.accessToken, + username: r.username, + email: r.profile.emails[0]?.value, + photo: r.profile.photos[0]?.value, + repositories: (await Promise.all(repositoryModels)).map((d) => d._id), + default: { + terms: r.default.terms, + options: r.default.options, + }, + }).save(); + + localResolve(user); + }); + Promise.all(promises).then(resolve); + }); + + console.log("Import Repositories"); + let promises = []; + await oldDB + .collection("repositories") + .find({}) + .batchSize(1) + .forEach(async (r) => { + if (!r.id) return; + let localResolve = null; + const p = new Promise((r) => (localResolve = r)); + promises.push(p); + + let find = await RepositoryModel.findOne({ + externalId: "gh_" + r.id, + }); + // console.log("gh_" + r.id, find != null); + if (find == null) { + find = new RepositoryModel({ + externalId: "gh_" + r.id, + name: r.fullName, + url: r.html_url, + size: r.size, + defaultBranch: r.default_branch, + }); + } + const branches = [...Object.values(r.branches)].map((b: any) => { + const o: any = { name: b.name, commit: b.commit.sha }; + if (b.name == find.defaultBranch) { + o.readme = r.readme; + } + return o; + }); + find.branches = branches; + await find.save(); + localResolve(); + }); + await Promise.all(promises); + console.log("Import Anonymized Repositories"); + promises = []; + await oldDB + .collection("anonymized_repositories") + .find({}) + .forEach(async (r) => { + let localResolve = null; + const p = new Promise((r) => (localResolve = r)); + promises.push(p); + + let repo = await RepositoryModel.findOne({ name: r.fullName }); + if (repo == null) { + const tmp = await oldDB + .collection("repositories") + .findOne({ fullName: r.fullName }); + if (tmp) { + repo = await RepositoryModel.findOne({ externalId: "gh_" + tmp.id }); + } else { + console.error(`Repository ${r.fullName} is not found (renamed)`); + } + } + await new AnonymizedRepositoryModel({ + repoId: r.repoId, + status: r.status, + anonymizeDate: r.anonymizeDate, + lastView: r.lastView, + pageView: r.pageView, + owner: r.owner, + source: { + accessToken: r.token, + type: + r.options.mode == "download" ? "GitHubDownload" : "GitHubStream", + branch: r.branch, + commit: r.commit, + repositoryId: repo?.id, + repositoryName: r.fullName, + }, + options: { + terms: r.terms, + expirationMode: r.options.expirationMode, + expirationDate: r.options.expirationDate + ? new Date(r.options.expirationDate) + : null, + update: r.options.update, + image: r.options.image, + pdf: r.options.pdf, + notebook: r.options.notebook, + loc: r.options.loc, + link: r.options.link, + page: r.options.page, + pageSource: r.options.pageSource, + }, + }).save(); + localResolve(); + }); + await Promise.all(promises); + console.log("Import finished!"); + setTimeout(() => process.exit(), 5000); +})(); diff --git a/package-lock.json b/package-lock.json index 326adc8..69b5d77 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,43 +1,87 @@ { "name": "anonymous_github", - "version": "2.0.0", + "version": "2.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "anonymous_github", - "version": "2.0.0", + "version": "2.1.0", "license": "MIT", "dependencies": { "@octokit/oauth-app": "^3.3.2", "@octokit/rest": "^18.5.3", - "array-equal": "^1.0.0", + "archive-stream-to-s3": "^1.1.3", + "archiver": "^5.3.0", + "aws-sdk": "^2.958.0", "compression": "^1.7.4", - "connect-redis": "^5.1.0", + "connect-redis": "^6.0.0", + "dotenv": "^10.0.0", "express": "^4.17.1", "express-rate-limit": "^5.2.6", "express-session": "^1.17.1", - "extract-zip": "^2.0.1", - "github-linguist": "^2.3.0", - "istextorbinary": "^5.12.0", - "mongodb": "^3.6.6", + "got": "^11.8.2", + "gunzip-maybe": "^1.4.2", + "istextorbinary": "^6.0.0", + "mime-types": "^2.1.30", + "mongoose": "^5.13.5", "parse-github-url": "^1.0.2", "passport": "^0.4.1", "passport-github2": "^0.1.12", "rate-limit-redis": "^2.1.0", "redis": "^3.1.2", - "textextensions": "^5.12.0" + "tar-fs": "^2.1.1", + "textextensions": "^5.12.0", + "xml-flow": "^1.0.4" }, "devDependencies": { + "@types/archiver": "^5.1.1", + "@types/compression": "^1.7.1", + "@types/connect-redis": "^0.0.17", + "@types/express": "^4.17.13", + "@types/express-rate-limit": "^5.1.3", + "@types/express-session": "^1.17.4", + "@types/got": "^9.6.12", + "@types/mime-types": "^2.1.0", + "@types/parse-github-url": "^1.0.0", + "@types/passport": "^1.0.7", + "@types/passport-github2": "^1.2.5", + "@types/rate-limit-redis": "^1.7.2", + "@types/redis": "^2.8.31", + "@types/tar-fs": "^2.0.1", + "@types/xml-flow": "^1.0.1", "chai": "^4.3.4", - "mocha": "^8.3.2", - "nodemon": "^2.0.4" + "mocha": "^9.0.3", + "nodemon": "^2.0.7", + "ts-node": "^10.1.0", + "typescript": "^4.3.5" + } + }, + "node_modules/@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.6.1.tgz", + "integrity": "sha512-DX3Z+T5dt1ockmPdobJS/FAsQPW4V4SrWEhD2iYQT2Cb2tQsiMnYxrcUH9By/Z3B+v0S5LMBkQtV/XOBbpLEOg==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-consumer": "0.8.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/@octokit/auth-oauth-app": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-4.1.2.tgz", - "integrity": "sha512-bdNGNRmuDJjKoHla3mUGtkk/xcxKngnQfBEnyk+7VwMqrABKvQB1wQRSrwSWkPPUX7Lcj2ttkPAPG7+iBkMRnw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-4.3.0.tgz", + "integrity": "sha512-cETmhmOQRHCz6cLP7StThlJROff3A/ln67Q961GuIr9zvyFXZ4lIJy9RE6Uw5O7D8IXWPU3jhDnG47FTSGQr8Q==", "dependencies": { "@octokit/auth-oauth-device": "^3.1.1", "@octokit/auth-oauth-user": "^1.2.1", @@ -49,9 +93,9 @@ } }, "node_modules/@octokit/auth-oauth-device": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-3.1.1.tgz", - "integrity": "sha512-ykDZROilszXZJ6pYdl6SZ15UZniCs0zDcKgwOZpMz3U0QDHPUhFGXjHToBCAIHwbncMu+jLt4/Nw4lq3FwAw/w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-3.1.2.tgz", + "integrity": "sha512-w7Po4Ck6N2aAn2VQyKLuojruiyKROTBv4qs6IwE5rbwF7HhBXXp4A/NKmkpoFIZkiXQtM+N8QtkSck4ApYWdGg==", "dependencies": { "@octokit/oauth-methods": "^1.1.0", "@octokit/request": "^5.4.14", @@ -60,9 +104,9 @@ } }, "node_modules/@octokit/auth-oauth-user": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-1.2.4.tgz", - "integrity": "sha512-efOajupCZBP1veqx5w59Qey0lIud1rDUgxTRjjkQDU3eOBmkAasY1pXemDsQwW0I85jb1P/gn2dMejedVxf9kw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-1.3.0.tgz", + "integrity": "sha512-3QC/TAdk7onnxfyZ24BnJRfZv8TRzQK7SEFUS9vLng4Vv6Hv6I64ujdk/CUkREec8lhrwU764SZ/d+yrjjqhaQ==", "dependencies": { "@octokit/auth-oauth-device": "^3.1.1", "@octokit/oauth-methods": "^1.1.0", @@ -81,22 +125,22 @@ } }, "node_modules/@octokit/auth-unauthenticated": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-2.0.4.tgz", - "integrity": "sha512-jZMwIz2PfQuLcOQRRELY6zb/jIyWQKlPxVV1oEG4sxJNmnANz3Skvnz4kVNvfs1r2jhgKAx9Pb6f+3vXeyh7yg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-2.1.0.tgz", + "integrity": "sha512-+baofLfSL0CAv3CfGQ9rxiZZQEX8VNJMGuuS4PgrMRBUL52Ho5+hQYb63UJQshw7EXYMPDZxbXznc0y33cbPqw==", "dependencies": { - "@octokit/request-error": "^2.0.2", + "@octokit/request-error": "^2.1.0", "@octokit/types": "^6.0.3" } }, "node_modules/@octokit/core": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.4.0.tgz", - "integrity": "sha512-6/vlKPP8NF17cgYXqucdshWqmMZGXkuvtcrWCgU5NOI0Pl2GjlmZyWgBMrU8zJ3v2MJlM6++CiB45VKYmhiWWg==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz", + "integrity": "sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==", "dependencies": { "@octokit/auth-token": "^2.4.4", "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.4.12", + "@octokit/request": "^5.6.0", "@octokit/request-error": "^2.0.5", "@octokit/types": "^6.0.3", "before-after-hook": "^2.2.0", @@ -104,9 +148,9 @@ } }, "node_modules/@octokit/endpoint": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.11.tgz", - "integrity": "sha512-fUIPpx+pZyoLW4GCs3yMnlj2LfoXTWDUVPTC4V3MUEKZm48W+XYpeWSZCv+vYF1ZABUm2CqnDVf1sFtIYrj7KQ==", + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", "dependencies": { "@octokit/types": "^6.0.3", "is-plain-object": "^5.0.0", @@ -114,22 +158,22 @@ } }, "node_modules/@octokit/graphql": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.6.1.tgz", - "integrity": "sha512-2lYlvf4YTDgZCTXTW4+OX+9WTLFtEUc6hGm4qM1nlZjzxj+arizM4aHWzBVBCxY9glh7GIs0WEuiSgbVzv8cmA==", + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.6.4.tgz", + "integrity": "sha512-SWTdXsVheRmlotWNjKzPOb6Js6tjSqA2a8z9+glDJng0Aqjzti8MEWOtuT8ZSu6wHnci7LZNuarE87+WJBG4vg==", "dependencies": { - "@octokit/request": "^5.3.0", + "@octokit/request": "^5.6.0", "@octokit/types": "^6.0.3", "universal-user-agent": "^6.0.0" } }, "node_modules/@octokit/oauth-app": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/@octokit/oauth-app/-/oauth-app-3.3.2.tgz", - "integrity": "sha512-vZPleCS65Sq2fXQYWt1JmTqrNUdsmdvmgr4rmZhxKaX/Fc6xExtNCBmksAbSMY9q3uFBv76BuvNWGKFNpXy5Tw==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@octokit/oauth-app/-/oauth-app-3.5.1.tgz", + "integrity": "sha512-heRM/m5nZfN6b9lsNwfOQ+HnpqLu3ske1CBmKaQ8URuB3HEEkZjKJUaZmnXK2c2Q70sDtPSiiFEDuq4McP40mQ==", "dependencies": { "@octokit/auth-oauth-app": "^4.0.0", - "@octokit/auth-oauth-user": "^1.2.3", + "@octokit/auth-oauth-user": "^1.3.0", "@octokit/auth-unauthenticated": "^2.0.0", "@octokit/core": "^3.3.2", "@octokit/oauth-authorization-url": "^4.2.1", @@ -139,14 +183,14 @@ } }, "node_modules/@octokit/oauth-authorization-url": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@octokit/oauth-authorization-url/-/oauth-authorization-url-4.3.1.tgz", - "integrity": "sha512-sI/SOEAvzRhqdzj+kJl+2ifblRve2XU6ZB36Lq25Su8R31zE3GoKToSLh64nWFnKePNi2RrdcMm94UEIQZslOw==" + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@octokit/oauth-authorization-url/-/oauth-authorization-url-4.3.3.tgz", + "integrity": "sha512-lhP/t0i8EwTmayHG4dqLXgU+uPVys4WD/qUNvC+HfB1S1dyqULm5Yx9uKc1x79aP66U1Cb4OZeW8QU/RA9A4XA==" }, "node_modules/@octokit/oauth-methods": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-1.2.2.tgz", - "integrity": "sha512-CFMUMn9DdPLMcpffhKgkwIIClfv0ZToJM4qcg4O0egCoHMYkVlxl22bBoo9qCnuF1U/xn871KEXuozKIX+bA2w==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-1.2.4.tgz", + "integrity": "sha512-85hen2Dkpnmy2PGfVFe7Ke9rUo//nlqUcHE4GiQBHJ7D95rAm19GcRO49LlH6NOXOMdEFj7i/Ay5GVDRrAk38w==", "dependencies": { "@octokit/oauth-authorization-url": "^4.3.1", "@octokit/request": "^5.4.14", @@ -156,35 +200,35 @@ } }, "node_modules/@octokit/openapi-types": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-6.1.1.tgz", - "integrity": "sha512-ICBhnEb+ahi/TTdNuYb/kTyKVBgAM0VD4k6JPzlhJyzt3Z+Tq/bynwCD+gpkJP7AEcNnzC8YO5R39trmzEo2UA==" + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-9.7.0.tgz", + "integrity": "sha512-TUJ16DJU8mekne6+KVcMV5g6g/rJlrnIKn7aALG9QrNpnEipFc1xjoarh0PKaAWf2Hf+HwthRKYt+9mCm5RsRg==" }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "2.13.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.13.3.tgz", - "integrity": "sha512-46lptzM9lTeSmIBt/sVP/FLSTPGx6DCzAdSX3PfeJ3mTf4h9sGC26WpaQzMEq/Z44cOcmx8VsOhO+uEgE3cjYg==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.15.1.tgz", + "integrity": "sha512-47r52KkhQDkmvUKZqXzA1lKvcyJEfYh3TKAIe5+EzMeyDM3d+/s5v11i2gTk8/n6No6DPi3k5Ind6wtDbo/AEg==", "dependencies": { - "@octokit/types": "^6.11.0" + "@octokit/types": "^6.24.0" }, "peerDependencies": { "@octokit/core": ">=2" } }, "node_modules/@octokit/plugin-request-log": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.3.tgz", - "integrity": "sha512-4RFU4li238jMJAzLgAwkBAw+4Loile5haQMQr+uhFq27BmyJXcXSKvoQKqh0agsZEiUlW6iSv3FAgvmGkur7OQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", "peerDependencies": { "@octokit/core": ">=3" } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.0.1.tgz", - "integrity": "sha512-vvWbPtPqLyIzJ7A4IPdTl+8IeuKAwMJ4LjvmqWOOdfSuqWQYZXq2CEd0hsnkidff2YfKlguzujHs/reBdAx8Sg==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.7.0.tgz", + "integrity": "sha512-G7sgccWRYQMwcHJXkDY/sDxbXeKiZkFQqUtzBCwmrzCNj2GQf3VygQ4T/BFL2crLVpIbenkE/c0ErhYOte2MPw==", "dependencies": { - "@octokit/types": "^6.13.1", + "@octokit/types": "^6.24.0", "deprecation": "^2.3.1" }, "peerDependencies": { @@ -192,22 +236,22 @@ } }, "node_modules/@octokit/request": { - "version": "5.4.15", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.4.15.tgz", - "integrity": "sha512-6UnZfZzLwNhdLRreOtTkT9n57ZwulCve8q3IT/Z477vThu6snfdkBuhxnChpOKNGxcQ71ow561Qoa6uqLdPtag==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.1.tgz", + "integrity": "sha512-Ls2cfs1OfXaOKzkcxnqw5MR6drMA/zWX/LIS/p8Yjdz7QKTPQLMsB3R+OvoxE6XnXeXEE2X7xe4G4l4X0gRiKQ==", "dependencies": { "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.0.0", - "@octokit/types": "^6.7.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", "is-plain-object": "^5.0.0", "node-fetch": "^2.6.1", "universal-user-agent": "^6.0.0" } }, "node_modules/@octokit/request-error": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.5.tgz", - "integrity": "sha512-T/2wcCFyM7SkXzNoyVNWjyVlUwBvW3igM3Btr/eKYiPmucXTtkxt2RBsf6gn3LTzaLSLTQtNmvg+dGsOxQrjZg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", "dependencies": { "@octokit/types": "^6.0.3", "deprecation": "^2.0.0", @@ -215,43 +259,95 @@ } }, "node_modules/@octokit/rest": { - "version": "18.5.3", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.5.3.tgz", - "integrity": "sha512-KPAsUCr1DOdLVbZJgGNuE/QVLWEaVBpFQwDAz/2Cnya6uW2wJ/P5RVGk0itx7yyN1aGa8uXm2pri4umEqG1JBA==", + "version": "18.9.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.9.0.tgz", + "integrity": "sha512-VrmrE8gjpuOoDAGjrQq2j9ZhOE6LxaqxaQg0yMrrEnnQZy2ZcAnr5qbVfKsMF0up/48PRV/VFS/2GSMhA7nTdA==", "dependencies": { - "@octokit/core": "^3.2.3", + "@octokit/core": "^3.5.0", "@octokit/plugin-paginate-rest": "^2.6.2", "@octokit/plugin-request-log": "^1.0.2", - "@octokit/plugin-rest-endpoint-methods": "5.0.1" + "@octokit/plugin-rest-endpoint-methods": "5.7.0" } }, "node_modules/@octokit/types": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.13.2.tgz", - "integrity": "sha512-jN5LImYHvv7W6SZargq1UMJ3EiaqIz5qkpfsv4GAb4b16SGqctxtOU2TQAZxvsKHkOw2A4zxdsi5wR9en1/ezQ==", + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.25.0.tgz", + "integrity": "sha512-bNvyQKfngvAd/08COlYIN54nRgxskmejgywodizQNyiKoXmWRAjKup2/LYwm+T9V0gsKH6tuld1gM0PzmOiB4Q==", "dependencies": { - "@octokit/openapi-types": "^6.1.1" + "@octokit/openapi-types": "^9.5.0" } }, "node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true, + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", + "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==", "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" } }, "node_modules/@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", "dependencies": { - "defer-to-connect": "^1.0.1" + "defer-to-connect": "^2.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "dev": true + }, + "node_modules/@types/archiver": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-5.1.1.tgz", + "integrity": "sha512-heuaCk0YH5m274NOLSi66H1zX6GtZoMsdE6TYFcpFFjBjg0FoU4i4/M/a/kNlgNg26Xk3g364mNOYe1JaiEPOQ==", + "dev": true, + "dependencies": { + "@types/glob": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.1.tgz", + "integrity": "sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bson": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.5.tgz", + "integrity": "sha512-vVLwMUqhYJSQ/WKcE60eFqcyuWse5fGH+NMAXHuKrUAPoryq3ATxk5o4bgYNtg5aOM4APVg7Hnb3ASqUYG0PKg==", + "dependencies": { + "@types/node": "*" } }, "node_modules/@types/btoa-lite": { @@ -259,17 +355,292 @@ "resolved": "https://registry.npmjs.org/@types/btoa-lite/-/btoa-lite-1.0.0.tgz", "integrity": "sha512-wJsiX1tosQ+J5+bY5LrSahHxr2wT+uME5UDwdN1kg4frt40euqA+wzECkmq4t5QbveHiJepfdThgQrPw6KiSlg==" }, + "node_modules/@types/cacheable-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", + "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, + "node_modules/@types/compression": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.7.1.tgz", + "integrity": "sha512-d6K1bU3qIjtfB2u+A1N0WDf62LpewRjrvbqY79qlPwk2otgQ4mWB4+LzPCWTvGmcuVwo+zAroEhsNlJavRcFvg==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-redis": { + "version": "0.0.17", + "resolved": "https://registry.npmjs.org/@types/connect-redis/-/connect-redis-0.0.17.tgz", + "integrity": "sha512-6apVqZFTMspIWwjGPfip7fKP+6Sl3M589DuYuYtzyc+Fzn2fnZqtQQ2o/UfwDlLh6zxq0RAnFbW3Mx1+2Nuh0w==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/express-session": "*", + "@types/ioredis": "*", + "@types/redis": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-rate-limit": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@types/express-rate-limit/-/express-rate-limit-5.1.3.tgz", + "integrity": "sha512-H+TYy3K53uPU2TqPGFYaiWc2xJV6+bIFkDd/Ma2/h67Pa6ARk9kWE0p/K9OH1Okm0et9Sfm66fmXoAxsH2PHXg==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz", + "integrity": "sha512-3UJuW+Qxhzwjq3xhwXm2onQcFHn76frIYVbTu+kn24LFxI+dEhdfISDFovPB8VpEgW8oQCTpRuCe+0zJxB7NEA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "node_modules/@types/express-session": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.17.4.tgz", + "integrity": "sha512-7cNlSI8+oOBUHTfPXMwDxF/Lchx5aJ3ho7+p9jJZYVg9dVDJFh3qdMXmJtRsysnvS+C6x46k9DRYmrmCkE+MVg==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/got": { + "version": "9.6.12", + "resolved": "https://registry.npmjs.org/@types/got/-/got-9.6.12.tgz", + "integrity": "sha512-X4pj/HGHbXVLqTpKjA2ahI4rV/nNBc9mGO2I/0CgAra+F2dKgMXnENv2SRpemScBzBAI4vMelIVYViQxlSE6xA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/tough-cookie": "*", + "form-data": "^2.5.0" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" + }, + "node_modules/@types/ioredis": { + "version": "4.26.7", + "resolved": "https://registry.npmjs.org/@types/ioredis/-/ioredis-4.26.7.tgz", + "integrity": "sha512-TOGRR+e1to00CihjgPNygD7+G7ruVnMi62YdIvGUBRfj11k/aWq+Fv5Ea8St0Oy56NngTBfA8GvLn1uvHvhX6Q==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/keyv": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.2.tgz", + "integrity": "sha512-/FvAK2p4jQOaJ6CGDHJTqZcUtbZe820qIeTg7o0Shg7drB4JHeL+V/dhSaly7NXx6u8eSee+r7coT+yuJEvDLg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true + }, + "node_modules/@types/mime-types": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz", + "integrity": "sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM=", + "dev": true + }, + "node_modules/@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true + }, + "node_modules/@types/mongodb": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.20.tgz", + "integrity": "sha512-WcdpPJCakFzcWWD9juKoZbRtQxKIMYF/JIAM4JrNHrMcnJL6/a2NWjXxW7fo9hxboxxkg+icff8d7+WIEvKgYQ==", + "dependencies": { + "@types/bson": "*", + "@types/node": "*" + } + }, "node_modules/@types/node": { - "version": "14.14.41", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.41.tgz", - "integrity": "sha512-dueRKfaJL4RTtSa7bWeTK1M+VH+Gns73oCgzvYfHZywRCoPSd8EkXBL0mZ9unPTveBn+D9phZBaxuzpwjWkW0g==", - "optional": true + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.6.1.tgz", + "integrity": "sha512-Sr7BhXEAer9xyGuCN3Ek9eg9xPviCF2gfu9kTfuU2HkTVAMYSDeX40fvpmo72n5nansg3nsBjuQBrsS28r+NUw==" }, - "node_modules/@types/yauzl": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz", - "integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==", - "optional": true, + "node_modules/@types/oauth": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@types/oauth/-/oauth-0.9.1.tgz", + "integrity": "sha512-a1iY62/a3yhZ7qH7cNUsxoI3U/0Fe9+RnuFrpTKr+0WVOzbKlSLojShCKe20aOD1Sppv+i8Zlq0pLDuTJnwS4A==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/parse-github-url": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-github-url/-/parse-github-url-1.0.0.tgz", + "integrity": "sha512-YNsYjdFmlfwIUGc47jfkb4BvFH9rdVbw80DxqSIQzQ3QpgaekmH2BcGKmEENzQRkeODoT/GiDrsJeztni+diAQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/passport": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.7.tgz", + "integrity": "sha512-JtswU8N3kxBYgo+n9of7C97YQBT+AYPP2aBfNGTzABqPAZnK/WOAaKfh3XesUYMZRrXFuoPc2Hv0/G/nQFveHw==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/passport-github2": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/passport-github2/-/passport-github2-1.2.5.tgz", + "integrity": "sha512-+WLyrd8JPsCxroK34EjegR0j3FMxp6wqB9cw/sRCFkWT9qic1dymAn021gr336EpyjzdhjUd2KKrqyxvdFSvOA==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-oauth2": "*" + } + }, + "node_modules/@types/passport-oauth2": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@types/passport-oauth2/-/passport-oauth2-1.4.11.tgz", + "integrity": "sha512-KUNwmGhe/3xPbjkzkPwwcPmyFwfyiSgtV1qOrPBLaU4i4q9GSCdAOyCbkFG0gUxAyEmYwqo9OAF/rjPjJ6ImdA==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/oauth": "*", + "@types/passport": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true + }, + "node_modules/@types/rate-limit-redis": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@types/rate-limit-redis/-/rate-limit-redis-1.7.2.tgz", + "integrity": "sha512-6Rl/7pKHpTYCUnj+2WGfpcF5YiZAV1Zn9GDjZI1pnRcY1qZi9MED7YQSKmGnycLHk5E8vorARw2S9llfkhd6xQ==", + "dev": true, + "dependencies": { + "@types/ioredis": "*", + "@types/redis": "*", + "express-rate-limit": ">=3.4.0" + } + }, + "node_modules/@types/redis": { + "version": "2.8.31", + "resolved": "https://registry.npmjs.org/@types/redis/-/redis-2.8.31.tgz", + "integrity": "sha512-daWrrTDYaa5iSDFbgzZ9gOOzyp2AJmYK59OlG/2KGBgYWF3lfs8GDKm1c//tik5Uc93hDD36O+qLPvzDolChbA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", + "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/tar-fs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/tar-fs/-/tar-fs-2.0.1.tgz", + "integrity": "sha512-qlsQyIY9sN7p221xHuXKNoMfUenOcvEBN4zI8dGsYbYCqHtTarXOEXSIgUnK+GcR0fZDse6pAIc5pIrCh9NefQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/tar-stream": "*" + } + }, + "node_modules/@types/tar-stream": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@types/tar-stream/-/tar-stream-2.2.1.tgz", + "integrity": "sha512-zhcfACZ4HavArMutfAB1/ApfSx44kNF2zyytU4mbO1dGCT/y9kL2IZwRDRyYYtBUxW6LRparZpLoX8i67b6IZw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.1.tgz", + "integrity": "sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg==", + "dev": true + }, + "node_modules/@types/xml-flow": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/xml-flow/-/xml-flow-1.0.1.tgz", + "integrity": "sha512-kJpk5awHNvRtOir562ZOKcoev5/XKeXFQs01MQnBJO/SWguD3qePt2JSs2OUFysg8ovMqE/QPPxTP6j58KLM0A==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -298,6 +669,27 @@ "node": ">= 0.6" } }, + "node_modules/acorn": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz", + "integrity": "sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.1.1.tgz", + "integrity": "sha512-FbJdceMlPHEAWJOILDk1fXD8lnTlEIWFkqtfk+MvmL5q/qlHfN7GEHcsFZWt/Tea9jRNPWUZG4G976nqAAmU9w==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/ansi-align": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", @@ -376,14 +768,18 @@ } }, "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/anymatch": { @@ -399,41 +795,145 @@ "node": ">= 8" } }, + "node_modules/archive-stream-to-s3": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/archive-stream-to-s3/-/archive-stream-to-s3-1.1.3.tgz", + "integrity": "sha512-XTUK2fLCAFPrCu9Y0X0u1vLrM5uh/cRbmeBNwUz/X4KeoImcgCexYmOoHAswoGivbm4Eh99eBKOpbIsBa06ZTg==", + "dependencies": { + "aws-sdk": "^2.270.1", + "debug": "^3.1.0", + "gunzip-maybe": "^1.4.1", + "mime-types": "^2.1.18", + "tar-stream": "^1.6.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/archiver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.0.tgz", + "integrity": "sha512-iUw+oDwK0fgNpvveEsdQ0Ase6IIKztBJU2U0E9MzszMfmVVUyv1QJhS2ITW9ZCqx8dktAxVAjWWkKehuZE8OPg==", + "dependencies": { + "archiver-utils": "^2.1.0", + "async": "^3.2.0", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.0.0", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "dependencies": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/archiver-utils/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/archiver-utils/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/archiver/node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/archiver/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/archiver/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/array-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", - "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=" - }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, - "node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dependencies": { - "array-uniq": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -443,11 +943,61 @@ "node": "*" } }, + "node_modules/async": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.1.tgz", + "integrity": "sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "node_modules/aws-sdk": { + "version": "2.967.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.967.0.tgz", + "integrity": "sha512-1IuQZsYZS67AMtywea+hL737sWHzeAzCqX3tEKTieMI+Ip5UoY4rNmQbJlUo8ysY+u8lixoiCFivEQfb/DG1cw==", + "hasInstallScript": true, + "dependencies": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.3.2", + "xml2js": "0.4.19" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/base64url": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", @@ -457,9 +1007,9 @@ } }, "node_modules/before-after-hook": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.1.tgz", - "integrity": "sha512-/6FKxSTWoJdbsLDF8tdIjaRiFXiE6UHsEHE3OPI/cwPURCVi1ukP0gmLn7XWEiFk5TcwQjjY5PWsU+j+tgXgmw==" + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", + "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==" }, "node_modules/binary-extensions": { "version": "2.2.0", @@ -471,9 +1021,9 @@ } }, "node_modules/binaryextensions": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-4.15.0.tgz", - "integrity": "sha512-MkUl3szxXolQ2scI1PM14WOT951KnaTNJ0eMKg7WzOI4kvSxyNo/Cygx4LOBNhwyINhAuSQpJW1rYD9aBSxGaw==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-4.18.0.tgz", + "integrity": "sha512-PQu3Kyv9dM4FnwB7XGj1+HucW+ShvJzJqjuw1JkKVs1mWdwOKVcRjOi+pV9X52A0tNvrPCsPkbFFQb+wE1EAXw==", "engines": { "node": ">=0.8" }, @@ -490,6 +1040,33 @@ "safe-buffer": "^5.1.1" } }, + "node_modules/bl/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/bl/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, "node_modules/body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", @@ -518,6 +1095,19 @@ "node": ">= 0.8" } }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, "node_modules/boxen": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", @@ -540,21 +1130,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/boxen/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/boxen/node_modules/chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -568,33 +1143,6 @@ "node": ">=8" } }, - "node_modules/boxen/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/boxen/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/boxen/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/boxen/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -634,6 +1182,14 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "node_modules/browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dependencies": { + "pako": "~0.2.0" + } + }, "node_modules/bson": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz", @@ -647,6 +1203,30 @@ "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", "integrity": "sha1-M3dm2hWAEhD92VbCLpxokaudAzc=" }, + "node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, "node_modules/buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -655,6 +1235,16 @@ "node": "*" } }, + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, "node_modules/bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", @@ -663,33 +1253,31 @@ "node": ">= 0.8" } }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "engines": { + "node": ">=10.6.0" + } + }, "node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", "dependencies": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", + "keyv": "^4.0.0", "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -717,16 +1305,31 @@ } }, "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/check-error": { @@ -739,27 +1342,31 @@ } }, "node_modules/chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", "dev": true, "dependencies": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "readdirp": "~3.6.0" }, "engines": { "node": ">= 8.10.0" }, "optionalDependencies": { - "fsevents": "~2.3.1" + "fsevents": "~2.3.2" } }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, "node_modules/ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", @@ -801,28 +1408,53 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, "dependencies": { "mimic-response": "^1.0.0" } }, "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "color-name": "1.1.3" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/compress-commons": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", + "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", + "dependencies": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } }, "node_modules/compressible": { "version": "2.0.18", @@ -852,6 +1484,19 @@ "node": ">= 0.8.0" } }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -875,11 +1520,11 @@ } }, "node_modules/connect-redis": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/connect-redis/-/connect-redis-5.1.0.tgz", - "integrity": "sha512-Cosy8gGUdkBPEYG84svgkzIGzspKBb98NUX4Nfc5eTJOF0A++41ZV15rPwWW0n5nU/FusNgNzuMeXhLVEQF80Q==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/connect-redis/-/connect-redis-6.0.0.tgz", + "integrity": "sha512-6eGEAAPHYvcfbRNCMmPzBIjrqRWLw7at9lCUH4G6NQ8gwWDJelaUmFNOqPIhehbw941euVmIuqWsaWiKXfb+5g==", "engines": { - "node": ">=10.0.0" + "node": ">=12" } }, "node_modules/content-disposition": { @@ -919,6 +1564,39 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "node_modules/crc-32": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", + "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", + "dependencies": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + }, + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", + "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, "node_modules/crypto-random-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", @@ -929,11 +1607,11 @@ } }, "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dependencies": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "node_modules/decamelize": { @@ -949,15 +1627,28 @@ } }, "node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "dependencies": { - "mimic-response": "^1.0.0" + "mimic-response": "^3.1.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/deep-eql": { @@ -990,10 +1681,21 @@ } }, "node_modules/defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "engines": { + "node": ">=10" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } }, "node_modules/denque": { "version": "1.5.0", @@ -1042,25 +1744,51 @@ "node": ">=8" } }, + "node_modules/dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "engines": { + "node": ">=10" + } + }, "node_modules/duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, - "node_modules/editions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/editions/-/editions-6.1.0.tgz", - "integrity": "sha512-h6nWEyIocfgho9J3sTSuhU/WoFOu1hTX75rPBebNrbF38Y9QFDjCDizYXdikHTySW7Y3mSxli8bpDz9RAtc7rA==", + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", "dependencies": { - "errlop": "^4.0.0", - "version-range": "^1.0.0" - }, - "engines": { - "node": ">=4" - }, - "funding": { - "url": "https://bevry.me/fund" + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexify/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" } }, "node_modules/ee-first": { @@ -1090,17 +1818,6 @@ "once": "^1.4.0" } }, - "node_modules/errlop": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/errlop/-/errlop-4.1.0.tgz", - "integrity": "sha512-vul6gGBuVt0M2TPi1/WrcL86+Hb3Q2Tpu3TME3sbVhZrYf7J1ZMHCodI25RQKCVurh56qTfvgM0p3w5cT4reSQ==", - "engines": { - "node": ">=4" - }, - "funding": { - "url": "https://bevry.me/fund" - } - }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -1125,11 +1842,15 @@ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, "engines": { - "node": ">=0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/etag": { @@ -1140,6 +1861,22 @@ "node": ">= 0.6" } }, + "node_modules/events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", + "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", @@ -1181,28 +1918,44 @@ } }, "node_modules/express-rate-limit": { - "version": "5.2.6", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.2.6.tgz", - "integrity": "sha512-nE96xaxGfxiS5jP3tD3kIW1Jg9yQgX0rXCs3rCkZtmbWHEGyotwaezkLj7bnB41Z0uaOLM8W4AX6qHao4IZ2YA==" + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.3.0.tgz", + "integrity": "sha512-qJhfEgCnmteSeZAeuOKQ2WEIFTX5ajrzE0xS6gCOBCoRQcU+xEzQmgYQQTpzCcqUAAzTEtu4YEih4pnLfvNtew==" }, "node_modules/express-session": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz", - "integrity": "sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==", + "version": "1.17.2", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", + "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==", "dependencies": { - "cookie": "0.4.0", + "cookie": "0.4.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "~2.0.0", "on-headers": "~1.0.2", "parseurl": "~1.3.3", - "safe-buffer": "5.2.0", + "safe-buffer": "5.2.1", "uid-safe": "~2.1.5" }, "engines": { "node": ">= 0.8.0" } }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-session/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, "node_modules/express-session/node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1211,60 +1964,43 @@ "node": ">= 0.8" } }, - "node_modules/express-session/node_modules/safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" - }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dependencies": { - "@types/yauzl": "^2.9.1", - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } + "node_modules/express-session/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, - "node_modules/extract-zip/node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true + "node_modules/express-session/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } - } - }, - "node_modules/extract-zip/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + ] }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { - "pend": "~1.2.0" + "ms": "2.0.0" } }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -1294,6 +2030,19 @@ "node": ">= 0.8" } }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -1319,10 +2068,24 @@ "flat": "cli.js" } }, + "node_modules/form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, "node_modules/forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "engines": { "node": ">= 0.6" } @@ -1354,15 +2117,10 @@ } ] }, - "node_modules/fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, "node_modules/fs.realpath": { "version": "1.0.0", @@ -1415,26 +2173,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/github-linguist": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/github-linguist/-/github-linguist-2.3.0.tgz", - "integrity": "sha512-pDskxid9R1/VHsgEwbaht8+oxnFjfvFJRg0nemV/kMyDjeh6Z3/s8WAlG1OO59XhmRF4qvOHK9ai8gfIgQ0GUQ==", - "dependencies": { - "chalk": "^2.2.0", - "commander": "^2.11.0", - "fs-extra": "^4.0.3", - "globby": "^6.1.0", - "language-map": "^1.3.0", - "slash2": "^2.0.0" - }, - "bin": { - "loc": "dist/cli.js" - } - }, "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -1477,59 +2219,34 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dependencies": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/got/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" + "version": "11.8.2", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", + "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.1", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" }, "engines": { - "node": ">=6" + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" } }, "node_modules/graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" }, "node_modules/growl": { "version": "1.10.5", @@ -1540,12 +2257,29 @@ "node": ">=4.x" } }, + "node_modules/gunzip-maybe": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz", + "integrity": "sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==", + "dependencies": { + "browserify-zlib": "^0.1.4", + "is-deflate": "^1.0.0", + "is-gzip": "^1.0.0", + "peek-stream": "^1.1.0", + "pumpify": "^1.3.3", + "through2": "^2.0.3" + }, + "bin": { + "gunzip-maybe": "bin.js" + } + }, "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/has-yarn": { @@ -1569,8 +2303,7 @@ "node_modules/http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" }, "node_modules/http-errors": { "version": "1.7.2", @@ -1592,6 +2325,18 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1603,6 +2348,11 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, "node_modules/ignore-by-default": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", @@ -1679,6 +2429,11 @@ "is-ci": "bin.js" } }, + "node_modules/is-deflate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", + "integrity": "sha1-yGKQHDwWH7CdrHzcfnhPgOmPLxQ=" + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -1709,6 +2464,14 @@ "node": ">=0.10.0" } }, + "node_modules/is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha1-bKiwe5nHeZgCWQDlVc7Y7YCHmoM=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-installed-globally": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", @@ -1784,6 +2547,18 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-yarn-global": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", @@ -1802,13 +2577,12 @@ "dev": true }, "node_modules/istextorbinary": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-5.12.0.tgz", - "integrity": "sha512-wLDRWD7qpNTYubk04+q3en1+XZGS4vYWK0+SxNSXJLaITMMEK+J3o/TlOMyULeH1qozVZ9uUkKcyMA8odyxz8w==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-6.0.0.tgz", + "integrity": "sha512-4j3UqQCa06GAf6QHlN3giz2EeFU7qc6Q5uB/aY7Gmb3xmLDLepDOtsZqkb4sCfJgFvTbLUinNw0kHgHs8XOHoQ==", "dependencies": { - "binaryextensions": "^4.15.0", - "editions": "^6.1.0", - "textextensions": "^5.11.0" + "binaryextensions": "^4.18.0", + "textextensions": "^5.14.0" }, "engines": { "node": ">=10" @@ -1817,10 +2591,18 @@ "url": "https://bevry.me/fund" } }, + "node_modules/jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/js-yaml": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", - "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { "argparse": "^2.0.1" @@ -1830,36 +2612,23 @@ } }, "node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dependencies": { - "graceful-fs": "^4.1.6" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } + "node_modules/kareem": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz", + "integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ==" }, "node_modules/keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", + "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", "dependencies": { - "json-buffer": "3.0.0" + "json-buffer": "3.0.1" } }, - "node_modules/language-map": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/language-map/-/language-map-1.4.0.tgz", - "integrity": "sha512-5XHMCqKQ/14VXwJTKZX7MZwsVyTrR0bwCsRBwrBq3nP4w7liMJiR0ixXgI29EF/T1/U6be8cYK2y0ibWW9kx2w==" - }, "node_modules/latest-version": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", @@ -1872,110 +2641,101 @@ "node": ">=8" } }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, + "node_modules/lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", "dependencies": { - "p-locate": "^5.0.0" + "readable-stream": "^2.0.5" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.6.3" } }, - "node_modules/log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", - "dev": true, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dependencies": { - "chalk": "^4.0.0" - }, - "engines": { - "node": ">=10" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "safe-buffer": "~5.1.0" } }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "p-locate": "^5.0.0" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "node_modules/lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=" }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "node_modules/lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true, + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/make-dir": { @@ -2002,6 +2762,12 @@ "semver": "bin/semver.js" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -2041,19 +2807,19 @@ } }, "node_modules/mime-db": { - "version": "1.47.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", - "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz", + "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.30", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", - "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", + "version": "2.1.32", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz", + "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==", "dependencies": { - "mime-db": "1.47.0" + "mime-db": "1.49.0" }, "engines": { "node": ">= 0.6" @@ -2063,7 +2829,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, "engines": { "node": ">=4" } @@ -2085,34 +2850,39 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, "node_modules/mocha": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.2.tgz", - "integrity": "sha512-UdmISwr/5w+uXLPKspgoV7/RXZwKRTiTjJ2/AC5ZiEztIoOYdfKb19+9jNmEInzx5pBsCyJQzarAxqIGBNYJhg==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.0.3.tgz", + "integrity": "sha512-hnYFrSefHxYS2XFGtN01x8un0EwNu2bzKvhpRFhgoybIvMaOkkL60IVPmkb5h6XDmUl4IMSB+rT5cIO4/4bJgg==", "dev": true, "dependencies": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.5.1", + "chokidar": "3.5.2", "debug": "4.3.1", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.1.6", + "glob": "7.1.7", "growl": "1.10.5", "he": "1.2.0", - "js-yaml": "4.0.0", - "log-symbols": "4.0.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", "minimatch": "3.0.4", "ms": "2.1.3", - "nanoid": "3.1.20", - "serialize-javascript": "5.0.1", + "nanoid": "3.1.23", + "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", "wide-align": "1.1.3", - "workerpool": "6.1.0", + "workerpool": "6.1.5", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" @@ -2122,7 +2892,7 @@ "mocha": "bin/mocha" }, "engines": { - "node": ">= 10.12.0" + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", @@ -2152,59 +2922,16 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/mongodb": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.6.tgz", - "integrity": "sha512-WlirMiuV1UPbej5JeCMqE93JRfZ/ZzqE7nJTwP85XzjAF4rRSeq2bGCb1cjfoHLOF06+HxADaPGqT0g3SbVT1w==", + "version": "3.6.11", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.11.tgz", + "integrity": "sha512-4Y4lTFHDHZZdgMaHmojtNAlqkvddX2QQBEN0K//GzxhGwlI9tZ9R0vhbjr1Decw+TF7qK0ZLjQT292XgHRRQgw==", "dependencies": { "bl": "^2.2.1", "bson": "^1.1.4", "denque": "^1.4.1", - "optional-require": "^1.0.2", - "safe-buffer": "^5.1.2", - "saslprep": "^1.0.0" + "optional-require": "^1.0.3", + "safe-buffer": "^5.1.2" }, "engines": { "node": ">=4" @@ -2233,15 +2960,110 @@ } } }, - "node_modules/ms": { + "node_modules/mongoose": { + "version": "5.13.7", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.7.tgz", + "integrity": "sha512-ADIvftZ+KfoTALMZ0n8HvBlezFhcUd73hQaHQDwQ+3X+JZlqE47fUy9yhFZ2SjT+qzmuaCcIXCfhewIc38t2fQ==", + "dependencies": { + "@types/mongodb": "^3.5.27", + "bson": "^1.1.4", + "kareem": "2.3.2", + "mongodb": "3.6.11", + "mongoose-legacy-pluralize": "1.0.2", + "mpath": "0.8.3", + "mquery": "3.2.5", + "ms": "2.1.2", + "optional-require": "1.0.x", + "regexp-clone": "1.0.0", + "safe-buffer": "5.2.1", + "sift": "13.5.2", + "sliced": "1.0.1" + }, + "engines": { + "node": ">=4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose-legacy-pluralize": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", + "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==", + "peerDependencies": { + "mongoose": "*" + } + }, + "node_modules/mongoose/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/mongoose/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/mpath": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.3.tgz", + "integrity": "sha512-eb9rRvhDltXVNL6Fxd2zM9D4vKBxjVVQNLNijlj7uoXUy19zNDsIif5zR+pWmPCWNKwAtqyo4JveQm4nfD5+eA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.5.tgz", + "integrity": "sha512-VjOKHHgU84wij7IUoZzFRU07IAxd5kWJaDmyUzQlbjHjyoeK5TNeeo8ZsFDtTYnSgpW6n/nMNIHvE3u8Lbrf4A==", + "dependencies": { + "bluebird": "3.5.1", + "debug": "3.1.0", + "regexp-clone": "^1.0.0", + "safe-buffer": "5.1.2", + "sliced": "1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/mquery/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/nanoid": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", - "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", "dev": true, "bin": { "nanoid": "bin/nanoid.cjs" @@ -2267,9 +3089,9 @@ } }, "node_modules/nodemon": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.7.tgz", - "integrity": "sha512-XHzK69Awgnec9UzHr1kc8EomQh4sjTQ8oRf8TsGrSmHDx9/UmiGG9E/mM3BuTfNeFwdNBvrqQq/RHL0xIeyFOA==", + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.12.tgz", + "integrity": "sha512-egCTmNZdObdBxUBw6ZNwvZ/xzk24CKRs5K6d+5zbmrMr7rOpPmfPeF6OxM3DDpaRx331CQRFEktn+wrFFfBSOA==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -2295,20 +3117,26 @@ "url": "https://opencollective.com/nodemon" } }, - "node_modules/nodemon/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/nodemon/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true, - "dependencies": { - "ms": "^2.1.1" + "engines": { + "node": ">=4" } }, - "node_modules/nodemon/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "node_modules/nodemon/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } }, "node_modules/nopt": { "version": "1.0.10", @@ -2329,18 +3157,19 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/normalize-url": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", - "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", - "dev": true, + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/oauth": { @@ -2348,14 +3177,6 @@ "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", "integrity": "sha1-vR/vr2hslrdUda7VGWQS/2DPucE=" }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -2392,12 +3213,11 @@ } }, "node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true, + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", "engines": { - "node": ">=6" + "node": ">=8" } }, "node_modules/p-limit": { @@ -2445,6 +3265,157 @@ "node": ">=8" } }, + "node_modules/package-json/node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json/node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json/node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/package-json/node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "node_modules/package-json/node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/package-json/node_modules/got/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json/node_modules/got/node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/package-json/node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "node_modules/package-json/node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/package-json/node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json/node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/package-json/node_modules/responselike/node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/package-json/node_modules/semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -2454,6 +3425,11 @@ "semver": "bin/semver.js" } }, + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=" + }, "node_modules/parse-github-url": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz", @@ -2497,9 +3473,9 @@ } }, "node_modules/passport-oauth2": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.5.0.tgz", - "integrity": "sha512-kqBt6vR/5VlCK8iCx1/KpY42kQ+NEHZwsSyt4Y6STiNjU+wWICG1i8ucc1FapXDGO15C5O5VZz7+7vRzrDPXXQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.6.0.tgz", + "integrity": "sha512-emXPLqLcVEcLFR/QvQXZcwLmfK8e9CqvMgmOFJxcNT3okSFMtUbRRKpY20x5euD+01uHsjjCa07DYboEeLXYiw==", "dependencies": { "base64url": "3.x.x", "oauth": "0.9.x", @@ -2509,6 +3485,10 @@ }, "engines": { "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" } }, "node_modules/passport-strategy": { @@ -2555,15 +3535,20 @@ "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + "node_modules/peek-stream": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", + "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", + "dependencies": { + "buffer-from": "^1.0.0", + "duplexify": "^3.5.0", + "through2": "^2.0.3" + } }, "node_modules/picomatch": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", - "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", "dev": true, "engines": { "node": ">=8.6" @@ -2572,33 +3557,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", @@ -2608,17 +3566,28 @@ "node": ">=4" } }, + "node_modules/printj": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", + "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==", + "bin": { + "printj": "bin/printj.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "node_modules/proxy-addr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "dependencies": { - "forwarded": "~0.1.2", + "forwarded": "0.2.0", "ipaddr.js": "1.9.1" }, "engines": { @@ -2640,6 +3609,30 @@ "once": "^1.3.1" } }, + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/pumpify/node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, "node_modules/pupa": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", @@ -2660,6 +3653,26 @@ "node": ">=0.6" } }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", @@ -2741,23 +3754,30 @@ } }, "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdir-glob": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.1.tgz", + "integrity": "sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA==", + "dependencies": { + "minimatch": "^3.0.4" } }, "node_modules/readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "dependencies": { "picomatch": "^2.2.1" @@ -2808,6 +3828,11 @@ "node": ">=4" } }, + "node_modules/regexp-clone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", + "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" + }, "node_modules/registry-auth-token": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", @@ -2841,13 +3866,17 @@ "node": ">=0.10.0" } }, + "node_modules/resolve-alpn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.0.tgz", + "integrity": "sha512-e4FNQs+9cINYMO5NMFc6kOUCdohjqFPSgMuwuZAOUWqrfWsen+Yjy5qZFkV5K7VO7tFSLKcUL97olkED7sCBHA==" + }, "node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", "dependencies": { - "lowercase-keys": "^1.0.0" + "lowercase-keys": "^2.0.0" } }, "node_modules/safe-buffer": { @@ -2872,6 +3901,11 @@ "node": ">=6" } }, + "node_modules/sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, "node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -2925,15 +3959,28 @@ "node": ">= 0.8.0" } }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, "node_modules/send/node_modules/ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" }, "node_modules/serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "dependencies": { "randombytes": "^2.1.0" @@ -2958,19 +4005,21 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" }, + "node_modules/sift": { + "version": "13.5.2", + "resolved": "https://registry.npmjs.org/sift/-/sift-13.5.2.tgz", + "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA==" + }, "node_modules/signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, - "node_modules/slash2": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash2/-/slash2-2.0.0.tgz", - "integrity": "sha512-7ElvBydJPi3MHU/KEOblFSbO/skl4Z69jKkFCpYIYVOMSIZsKi4gYU43HGeZPmjxCXrHekoDAAewphPQNnsqtA==", - "engines": { - "node": ">=6" - } + "node_modules/sliced": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", + "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" }, "node_modules/sparse-bitfield": { "version": "3.0.3", @@ -2989,14 +4038,38 @@ "node": ">= 0.6" } }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dependencies": { - "safe-buffer": "~5.1.0" + "safe-buffer": "~5.2.0" } }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/string-width": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", @@ -3036,14 +4109,125 @@ } }, "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/tar-fs/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/tar-fs/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "dependencies": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/tar-stream/node_modules/bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "dependencies": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/tar-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" } }, "node_modules/term-size": { @@ -3059,9 +4243,9 @@ } }, "node_modules/textextensions": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-5.12.0.tgz", - "integrity": "sha512-IYogUDaP65IXboCiPPC0jTLLBzYlhhw2Y4b0a2trPgbHNGGGEfuHE6tds+yDcCf4mpNDaGISFzwSSezcXt+d6w==", + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-5.14.0.tgz", + "integrity": "sha512-4cAYwNFNYlIAHBUo7p6zw8POUvWbZor+/R0Tanv+rIhsauEyV9QSrEXL40pI+GfTQxKX8k6Tyw6CmdSDSmASrg==", "engines": { "node": ">=0.8" }, @@ -3069,6 +4253,42 @@ "url": "https://bevry.me/fund" } }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/through2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, "node_modules/to-readable-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", @@ -3110,6 +4330,59 @@ "nodetouch": "bin/nodetouch.js" } }, + "node_modules/ts-node": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.2.0.tgz", + "integrity": "sha512-FstYHtQz6isj8rBtYMN4bZdnXN1vq4HCbqn9vdNQcInRqtB86PePJQIxE6es0PhxKWhj2PHuwbG40H+bxkZPmg==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "0.6.1", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -3149,6 +4422,19 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/typescript": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/uid-safe": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", @@ -3174,6 +4460,21 @@ "debug": "^2.2.0" } }, + "node_modules/undefsafe/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/undefsafe/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, "node_modules/unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -3191,14 +4492,6 @@ "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -3234,21 +4527,6 @@ "url": "https://github.com/yeoman/update-notifier?sponsor=1" } }, - "node_modules/update-notifier/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/update-notifier/node_modules/chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -3262,33 +4540,6 @@ "node": ">=8" } }, - "node_modules/update-notifier/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/update-notifier/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/update-notifier/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/update-notifier/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -3301,6 +4552,15 @@ "node": ">=8" } }, + "node_modules/url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, "node_modules/url-parse-lax": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", @@ -3325,38 +4585,22 @@ "engines": { "node": ">= 0.4.0" } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/version-compare": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/version-compare/-/version-compare-1.1.0.tgz", - "integrity": "sha512-zVKtPOJTC9x23lzS4+4D7J+drq80BXVYAmObnr5zqxxFVH7OffJ1lJlAS7LYsQNV56jx/wtbw0UV7XHLrvd6kQ==", - "engines": { - "node": ">=4" - }, - "funding": { - "url": "https://bevry.me/fund" + }, + "node_modules/uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" } }, - "node_modules/version-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/version-range/-/version-range-1.1.0.tgz", - "integrity": "sha512-R1Ggfg2EXamrnrV3TkZ6yBNgITDbclB3viwSjbZ3+eK0VVNK4ajkYJTnDz5N0bIMYDtK9MUBvXJUnKO5RWWJ6w==", - "dependencies": { - "version-compare": "^1.0.0" - }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", "engines": { - "node": ">=4" - }, - "funding": { - "url": "https://bevry.me/fund" + "node": ">= 0.8" } }, "node_modules/which": { @@ -3439,9 +4683,9 @@ } }, "node_modules/workerpool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", - "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", + "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==", "dev": true }, "node_modules/wrap-ansi": { @@ -3461,39 +4705,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -3520,6 +4731,44 @@ "node": ">=8" } }, + "node_modules/xml-flow": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/xml-flow/-/xml-flow-1.0.4.tgz", + "integrity": "sha512-r19LXKPL7vkVGL6oWHlESoBgwUVom5w/w8opuS53qULh8+K2w+K9K72edTIQa+X/Vxx1R7ugnCabHFSZ1Tv2zA==", + "dependencies": { + "sax": "^1.2.4" + } + }, + "node_modules/xml-flow/node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "node_modules/xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -3583,13 +4832,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" } }, "node_modules/yocto-queue": { @@ -3603,13 +4852,41 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zip-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", + "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", + "dependencies": { + "archiver-utils": "^2.1.0", + "compress-commons": "^4.1.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } } }, "dependencies": { + "@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "dev": true + }, + "@cspotcode/source-map-support": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.6.1.tgz", + "integrity": "sha512-DX3Z+T5dt1ockmPdobJS/FAsQPW4V4SrWEhD2iYQT2Cb2tQsiMnYxrcUH9By/Z3B+v0S5LMBkQtV/XOBbpLEOg==", + "dev": true, + "requires": { + "@cspotcode/source-map-consumer": "0.8.0" + } + }, "@octokit/auth-oauth-app": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-4.1.2.tgz", - "integrity": "sha512-bdNGNRmuDJjKoHla3mUGtkk/xcxKngnQfBEnyk+7VwMqrABKvQB1wQRSrwSWkPPUX7Lcj2ttkPAPG7+iBkMRnw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-4.3.0.tgz", + "integrity": "sha512-cETmhmOQRHCz6cLP7StThlJROff3A/ln67Q961GuIr9zvyFXZ4lIJy9RE6Uw5O7D8IXWPU3jhDnG47FTSGQr8Q==", "requires": { "@octokit/auth-oauth-device": "^3.1.1", "@octokit/auth-oauth-user": "^1.2.1", @@ -3621,9 +4898,9 @@ } }, "@octokit/auth-oauth-device": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-3.1.1.tgz", - "integrity": "sha512-ykDZROilszXZJ6pYdl6SZ15UZniCs0zDcKgwOZpMz3U0QDHPUhFGXjHToBCAIHwbncMu+jLt4/Nw4lq3FwAw/w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-3.1.2.tgz", + "integrity": "sha512-w7Po4Ck6N2aAn2VQyKLuojruiyKROTBv4qs6IwE5rbwF7HhBXXp4A/NKmkpoFIZkiXQtM+N8QtkSck4ApYWdGg==", "requires": { "@octokit/oauth-methods": "^1.1.0", "@octokit/request": "^5.4.14", @@ -3632,9 +4909,9 @@ } }, "@octokit/auth-oauth-user": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-1.2.4.tgz", - "integrity": "sha512-efOajupCZBP1veqx5w59Qey0lIud1rDUgxTRjjkQDU3eOBmkAasY1pXemDsQwW0I85jb1P/gn2dMejedVxf9kw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-1.3.0.tgz", + "integrity": "sha512-3QC/TAdk7onnxfyZ24BnJRfZv8TRzQK7SEFUS9vLng4Vv6Hv6I64ujdk/CUkREec8lhrwU764SZ/d+yrjjqhaQ==", "requires": { "@octokit/auth-oauth-device": "^3.1.1", "@octokit/oauth-methods": "^1.1.0", @@ -3653,22 +4930,22 @@ } }, "@octokit/auth-unauthenticated": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-2.0.4.tgz", - "integrity": "sha512-jZMwIz2PfQuLcOQRRELY6zb/jIyWQKlPxVV1oEG4sxJNmnANz3Skvnz4kVNvfs1r2jhgKAx9Pb6f+3vXeyh7yg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-2.1.0.tgz", + "integrity": "sha512-+baofLfSL0CAv3CfGQ9rxiZZQEX8VNJMGuuS4PgrMRBUL52Ho5+hQYb63UJQshw7EXYMPDZxbXznc0y33cbPqw==", "requires": { - "@octokit/request-error": "^2.0.2", + "@octokit/request-error": "^2.1.0", "@octokit/types": "^6.0.3" } }, "@octokit/core": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.4.0.tgz", - "integrity": "sha512-6/vlKPP8NF17cgYXqucdshWqmMZGXkuvtcrWCgU5NOI0Pl2GjlmZyWgBMrU8zJ3v2MJlM6++CiB45VKYmhiWWg==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz", + "integrity": "sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==", "requires": { "@octokit/auth-token": "^2.4.4", "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.4.12", + "@octokit/request": "^5.6.0", "@octokit/request-error": "^2.0.5", "@octokit/types": "^6.0.3", "before-after-hook": "^2.2.0", @@ -3676,9 +4953,9 @@ } }, "@octokit/endpoint": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.11.tgz", - "integrity": "sha512-fUIPpx+pZyoLW4GCs3yMnlj2LfoXTWDUVPTC4V3MUEKZm48W+XYpeWSZCv+vYF1ZABUm2CqnDVf1sFtIYrj7KQ==", + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", "requires": { "@octokit/types": "^6.0.3", "is-plain-object": "^5.0.0", @@ -3686,22 +4963,22 @@ } }, "@octokit/graphql": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.6.1.tgz", - "integrity": "sha512-2lYlvf4YTDgZCTXTW4+OX+9WTLFtEUc6hGm4qM1nlZjzxj+arizM4aHWzBVBCxY9glh7GIs0WEuiSgbVzv8cmA==", + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.6.4.tgz", + "integrity": "sha512-SWTdXsVheRmlotWNjKzPOb6Js6tjSqA2a8z9+glDJng0Aqjzti8MEWOtuT8ZSu6wHnci7LZNuarE87+WJBG4vg==", "requires": { - "@octokit/request": "^5.3.0", + "@octokit/request": "^5.6.0", "@octokit/types": "^6.0.3", "universal-user-agent": "^6.0.0" } }, "@octokit/oauth-app": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/@octokit/oauth-app/-/oauth-app-3.3.2.tgz", - "integrity": "sha512-vZPleCS65Sq2fXQYWt1JmTqrNUdsmdvmgr4rmZhxKaX/Fc6xExtNCBmksAbSMY9q3uFBv76BuvNWGKFNpXy5Tw==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@octokit/oauth-app/-/oauth-app-3.5.1.tgz", + "integrity": "sha512-heRM/m5nZfN6b9lsNwfOQ+HnpqLu3ske1CBmKaQ8URuB3HEEkZjKJUaZmnXK2c2Q70sDtPSiiFEDuq4McP40mQ==", "requires": { "@octokit/auth-oauth-app": "^4.0.0", - "@octokit/auth-oauth-user": "^1.2.3", + "@octokit/auth-oauth-user": "^1.3.0", "@octokit/auth-unauthenticated": "^2.0.0", "@octokit/core": "^3.3.2", "@octokit/oauth-authorization-url": "^4.2.1", @@ -3711,14 +4988,14 @@ } }, "@octokit/oauth-authorization-url": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@octokit/oauth-authorization-url/-/oauth-authorization-url-4.3.1.tgz", - "integrity": "sha512-sI/SOEAvzRhqdzj+kJl+2ifblRve2XU6ZB36Lq25Su8R31zE3GoKToSLh64nWFnKePNi2RrdcMm94UEIQZslOw==" + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@octokit/oauth-authorization-url/-/oauth-authorization-url-4.3.3.tgz", + "integrity": "sha512-lhP/t0i8EwTmayHG4dqLXgU+uPVys4WD/qUNvC+HfB1S1dyqULm5Yx9uKc1x79aP66U1Cb4OZeW8QU/RA9A4XA==" }, "@octokit/oauth-methods": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-1.2.2.tgz", - "integrity": "sha512-CFMUMn9DdPLMcpffhKgkwIIClfv0ZToJM4qcg4O0egCoHMYkVlxl22bBoo9qCnuF1U/xn871KEXuozKIX+bA2w==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-1.2.4.tgz", + "integrity": "sha512-85hen2Dkpnmy2PGfVFe7Ke9rUo//nlqUcHE4GiQBHJ7D95rAm19GcRO49LlH6NOXOMdEFj7i/Ay5GVDRrAk38w==", "requires": { "@octokit/oauth-authorization-url": "^4.3.1", "@octokit/request": "^5.4.14", @@ -3728,50 +5005,50 @@ } }, "@octokit/openapi-types": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-6.1.1.tgz", - "integrity": "sha512-ICBhnEb+ahi/TTdNuYb/kTyKVBgAM0VD4k6JPzlhJyzt3Z+Tq/bynwCD+gpkJP7AEcNnzC8YO5R39trmzEo2UA==" + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-9.7.0.tgz", + "integrity": "sha512-TUJ16DJU8mekne6+KVcMV5g6g/rJlrnIKn7aALG9QrNpnEipFc1xjoarh0PKaAWf2Hf+HwthRKYt+9mCm5RsRg==" }, "@octokit/plugin-paginate-rest": { - "version": "2.13.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.13.3.tgz", - "integrity": "sha512-46lptzM9lTeSmIBt/sVP/FLSTPGx6DCzAdSX3PfeJ3mTf4h9sGC26WpaQzMEq/Z44cOcmx8VsOhO+uEgE3cjYg==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.15.1.tgz", + "integrity": "sha512-47r52KkhQDkmvUKZqXzA1lKvcyJEfYh3TKAIe5+EzMeyDM3d+/s5v11i2gTk8/n6No6DPi3k5Ind6wtDbo/AEg==", "requires": { - "@octokit/types": "^6.11.0" + "@octokit/types": "^6.24.0" } }, "@octokit/plugin-request-log": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.3.tgz", - "integrity": "sha512-4RFU4li238jMJAzLgAwkBAw+4Loile5haQMQr+uhFq27BmyJXcXSKvoQKqh0agsZEiUlW6iSv3FAgvmGkur7OQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", "requires": {} }, "@octokit/plugin-rest-endpoint-methods": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.0.1.tgz", - "integrity": "sha512-vvWbPtPqLyIzJ7A4IPdTl+8IeuKAwMJ4LjvmqWOOdfSuqWQYZXq2CEd0hsnkidff2YfKlguzujHs/reBdAx8Sg==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.7.0.tgz", + "integrity": "sha512-G7sgccWRYQMwcHJXkDY/sDxbXeKiZkFQqUtzBCwmrzCNj2GQf3VygQ4T/BFL2crLVpIbenkE/c0ErhYOte2MPw==", "requires": { - "@octokit/types": "^6.13.1", + "@octokit/types": "^6.24.0", "deprecation": "^2.3.1" } }, "@octokit/request": { - "version": "5.4.15", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.4.15.tgz", - "integrity": "sha512-6UnZfZzLwNhdLRreOtTkT9n57ZwulCve8q3IT/Z477vThu6snfdkBuhxnChpOKNGxcQ71ow561Qoa6uqLdPtag==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.1.tgz", + "integrity": "sha512-Ls2cfs1OfXaOKzkcxnqw5MR6drMA/zWX/LIS/p8Yjdz7QKTPQLMsB3R+OvoxE6XnXeXEE2X7xe4G4l4X0gRiKQ==", "requires": { "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.0.0", - "@octokit/types": "^6.7.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", "is-plain-object": "^5.0.0", "node-fetch": "^2.6.1", "universal-user-agent": "^6.0.0" } }, "@octokit/request-error": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.5.tgz", - "integrity": "sha512-T/2wcCFyM7SkXzNoyVNWjyVlUwBvW3igM3Btr/eKYiPmucXTtkxt2RBsf6gn3LTzaLSLTQtNmvg+dGsOxQrjZg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", "requires": { "@octokit/types": "^6.0.3", "deprecation": "^2.0.0", @@ -3779,37 +5056,86 @@ } }, "@octokit/rest": { - "version": "18.5.3", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.5.3.tgz", - "integrity": "sha512-KPAsUCr1DOdLVbZJgGNuE/QVLWEaVBpFQwDAz/2Cnya6uW2wJ/P5RVGk0itx7yyN1aGa8uXm2pri4umEqG1JBA==", + "version": "18.9.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.9.0.tgz", + "integrity": "sha512-VrmrE8gjpuOoDAGjrQq2j9ZhOE6LxaqxaQg0yMrrEnnQZy2ZcAnr5qbVfKsMF0up/48PRV/VFS/2GSMhA7nTdA==", "requires": { - "@octokit/core": "^3.2.3", + "@octokit/core": "^3.5.0", "@octokit/plugin-paginate-rest": "^2.6.2", "@octokit/plugin-request-log": "^1.0.2", - "@octokit/plugin-rest-endpoint-methods": "5.0.1" + "@octokit/plugin-rest-endpoint-methods": "5.7.0" } }, "@octokit/types": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.13.2.tgz", - "integrity": "sha512-jN5LImYHvv7W6SZargq1UMJ3EiaqIz5qkpfsv4GAb4b16SGqctxtOU2TQAZxvsKHkOw2A4zxdsi5wR9en1/ezQ==", + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.25.0.tgz", + "integrity": "sha512-bNvyQKfngvAd/08COlYIN54nRgxskmejgywodizQNyiKoXmWRAjKup2/LYwm+T9V0gsKH6tuld1gM0PzmOiB4Q==", "requires": { - "@octokit/openapi-types": "^6.1.1" + "@octokit/openapi-types": "^9.5.0" } }, "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", + "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==" }, "@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "requires": { + "defer-to-connect": "^2.0.0" + } + }, + "@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "dev": true + }, + "@types/archiver": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-5.1.1.tgz", + "integrity": "sha512-heuaCk0YH5m274NOLSi66H1zX6GtZoMsdE6TYFcpFFjBjg0FoU4i4/M/a/kNlgNg26Xk3g364mNOYe1JaiEPOQ==", "dev": true, "requires": { - "defer-to-connect": "^1.0.1" + "@types/glob": "*" + } + }, + "@types/body-parser": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.1.tgz", + "integrity": "sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/bson": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.5.tgz", + "integrity": "sha512-vVLwMUqhYJSQ/WKcE60eFqcyuWse5fGH+NMAXHuKrUAPoryq3ATxk5o4bgYNtg5aOM4APVg7Hnb3ASqUYG0PKg==", + "requires": { + "@types/node": "*" } }, "@types/btoa-lite": { @@ -3817,17 +5143,292 @@ "resolved": "https://registry.npmjs.org/@types/btoa-lite/-/btoa-lite-1.0.0.tgz", "integrity": "sha512-wJsiX1tosQ+J5+bY5LrSahHxr2wT+uME5UDwdN1kg4frt40euqA+wzECkmq4t5QbveHiJepfdThgQrPw6KiSlg==" }, + "@types/cacheable-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", + "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", + "requires": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, + "@types/compression": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.7.1.tgz", + "integrity": "sha512-d6K1bU3qIjtfB2u+A1N0WDf62LpewRjrvbqY79qlPwk2otgQ4mWB4+LzPCWTvGmcuVwo+zAroEhsNlJavRcFvg==", + "dev": true, + "requires": { + "@types/express": "*" + } + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/connect-redis": { + "version": "0.0.17", + "resolved": "https://registry.npmjs.org/@types/connect-redis/-/connect-redis-0.0.17.tgz", + "integrity": "sha512-6apVqZFTMspIWwjGPfip7fKP+6Sl3M589DuYuYtzyc+Fzn2fnZqtQQ2o/UfwDlLh6zxq0RAnFbW3Mx1+2Nuh0w==", + "dev": true, + "requires": { + "@types/express": "*", + "@types/express-session": "*", + "@types/ioredis": "*", + "@types/redis": "*" + } + }, + "@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-rate-limit": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@types/express-rate-limit/-/express-rate-limit-5.1.3.tgz", + "integrity": "sha512-H+TYy3K53uPU2TqPGFYaiWc2xJV6+bIFkDd/Ma2/h67Pa6ARk9kWE0p/K9OH1Okm0et9Sfm66fmXoAxsH2PHXg==", + "dev": true, + "requires": { + "@types/express": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz", + "integrity": "sha512-3UJuW+Qxhzwjq3xhwXm2onQcFHn76frIYVbTu+kn24LFxI+dEhdfISDFovPB8VpEgW8oQCTpRuCe+0zJxB7NEA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "@types/express-session": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.17.4.tgz", + "integrity": "sha512-7cNlSI8+oOBUHTfPXMwDxF/Lchx5aJ3ho7+p9jJZYVg9dVDJFh3qdMXmJtRsysnvS+C6x46k9DRYmrmCkE+MVg==", + "dev": true, + "requires": { + "@types/express": "*" + } + }, + "@types/glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/got": { + "version": "9.6.12", + "resolved": "https://registry.npmjs.org/@types/got/-/got-9.6.12.tgz", + "integrity": "sha512-X4pj/HGHbXVLqTpKjA2ahI4rV/nNBc9mGO2I/0CgAra+F2dKgMXnENv2SRpemScBzBAI4vMelIVYViQxlSE6xA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/tough-cookie": "*", + "form-data": "^2.5.0" + } + }, + "@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" + }, + "@types/ioredis": { + "version": "4.26.7", + "resolved": "https://registry.npmjs.org/@types/ioredis/-/ioredis-4.26.7.tgz", + "integrity": "sha512-TOGRR+e1to00CihjgPNygD7+G7ruVnMi62YdIvGUBRfj11k/aWq+Fv5Ea8St0Oy56NngTBfA8GvLn1uvHvhX6Q==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/keyv": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.2.tgz", + "integrity": "sha512-/FvAK2p4jQOaJ6CGDHJTqZcUtbZe820qIeTg7o0Shg7drB4JHeL+V/dhSaly7NXx6u8eSee+r7coT+yuJEvDLg==", + "requires": { + "@types/node": "*" + } + }, + "@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true + }, + "@types/mime-types": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz", + "integrity": "sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM=", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true + }, + "@types/mongodb": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.20.tgz", + "integrity": "sha512-WcdpPJCakFzcWWD9juKoZbRtQxKIMYF/JIAM4JrNHrMcnJL6/a2NWjXxW7fo9hxboxxkg+icff8d7+WIEvKgYQ==", + "requires": { + "@types/bson": "*", + "@types/node": "*" + } + }, "@types/node": { - "version": "14.14.41", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.41.tgz", - "integrity": "sha512-dueRKfaJL4RTtSa7bWeTK1M+VH+Gns73oCgzvYfHZywRCoPSd8EkXBL0mZ9unPTveBn+D9phZBaxuzpwjWkW0g==", - "optional": true + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.6.1.tgz", + "integrity": "sha512-Sr7BhXEAer9xyGuCN3Ek9eg9xPviCF2gfu9kTfuU2HkTVAMYSDeX40fvpmo72n5nansg3nsBjuQBrsS28r+NUw==" + }, + "@types/oauth": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@types/oauth/-/oauth-0.9.1.tgz", + "integrity": "sha512-a1iY62/a3yhZ7qH7cNUsxoI3U/0Fe9+RnuFrpTKr+0WVOzbKlSLojShCKe20aOD1Sppv+i8Zlq0pLDuTJnwS4A==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/parse-github-url": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-github-url/-/parse-github-url-1.0.0.tgz", + "integrity": "sha512-YNsYjdFmlfwIUGc47jfkb4BvFH9rdVbw80DxqSIQzQ3QpgaekmH2BcGKmEENzQRkeODoT/GiDrsJeztni+diAQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/passport": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.7.tgz", + "integrity": "sha512-JtswU8N3kxBYgo+n9of7C97YQBT+AYPP2aBfNGTzABqPAZnK/WOAaKfh3XesUYMZRrXFuoPc2Hv0/G/nQFveHw==", + "dev": true, + "requires": { + "@types/express": "*" + } + }, + "@types/passport-github2": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/passport-github2/-/passport-github2-1.2.5.tgz", + "integrity": "sha512-+WLyrd8JPsCxroK34EjegR0j3FMxp6wqB9cw/sRCFkWT9qic1dymAn021gr336EpyjzdhjUd2KKrqyxvdFSvOA==", + "dev": true, + "requires": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-oauth2": "*" + } + }, + "@types/passport-oauth2": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@types/passport-oauth2/-/passport-oauth2-1.4.11.tgz", + "integrity": "sha512-KUNwmGhe/3xPbjkzkPwwcPmyFwfyiSgtV1qOrPBLaU4i4q9GSCdAOyCbkFG0gUxAyEmYwqo9OAF/rjPjJ6ImdA==", + "dev": true, + "requires": { + "@types/express": "*", + "@types/oauth": "*", + "@types/passport": "*" + } + }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true + }, + "@types/rate-limit-redis": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@types/rate-limit-redis/-/rate-limit-redis-1.7.2.tgz", + "integrity": "sha512-6Rl/7pKHpTYCUnj+2WGfpcF5YiZAV1Zn9GDjZI1pnRcY1qZi9MED7YQSKmGnycLHk5E8vorARw2S9llfkhd6xQ==", + "dev": true, + "requires": { + "@types/ioredis": "*", + "@types/redis": "*", + "express-rate-limit": ">=3.4.0" + } + }, + "@types/redis": { + "version": "2.8.31", + "resolved": "https://registry.npmjs.org/@types/redis/-/redis-2.8.31.tgz", + "integrity": "sha512-daWrrTDYaa5iSDFbgzZ9gOOzyp2AJmYK59OlG/2KGBgYWF3lfs8GDKm1c//tik5Uc93hDD36O+qLPvzDolChbA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "requires": { + "@types/node": "*" + } + }, + "@types/serve-static": { + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", + "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "dev": true, + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "@types/tar-fs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/tar-fs/-/tar-fs-2.0.1.tgz", + "integrity": "sha512-qlsQyIY9sN7p221xHuXKNoMfUenOcvEBN4zI8dGsYbYCqHtTarXOEXSIgUnK+GcR0fZDse6pAIc5pIrCh9NefQ==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/tar-stream": "*" + } + }, + "@types/tar-stream": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@types/tar-stream/-/tar-stream-2.2.1.tgz", + "integrity": "sha512-zhcfACZ4HavArMutfAB1/ApfSx44kNF2zyytU4mbO1dGCT/y9kL2IZwRDRyYYtBUxW6LRparZpLoX8i67b6IZw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/tough-cookie": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.1.tgz", + "integrity": "sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg==", + "dev": true }, - "@types/yauzl": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz", - "integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==", - "optional": true, + "@types/xml-flow": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/xml-flow/-/xml-flow-1.0.1.tgz", + "integrity": "sha512-kJpk5awHNvRtOir562ZOKcoev5/XKeXFQs01MQnBJO/SWguD3qePt2JSs2OUFysg8ovMqE/QPPxTP6j58KLM0A==", + "dev": true, "requires": { "@types/node": "*" } @@ -3853,6 +5454,18 @@ "negotiator": "0.6.2" } }, + "acorn": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz", + "integrity": "sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==", + "dev": true + }, + "acorn-walk": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.1.1.tgz", + "integrity": "sha512-FbJdceMlPHEAWJOILDk1fXD8lnTlEIWFkqtfk+MvmL5q/qlHfN7GEHcsFZWt/Tea9jRNPWUZG4G976nqAAmU9w==", + "dev": true + }, "ansi-align": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", @@ -3915,11 +5528,12 @@ "dev": true }, "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" } }, "anymatch": { @@ -3932,55 +5546,175 @@ "picomatch": "^2.0.4" } }, + "archive-stream-to-s3": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/archive-stream-to-s3/-/archive-stream-to-s3-1.1.3.tgz", + "integrity": "sha512-XTUK2fLCAFPrCu9Y0X0u1vLrM5uh/cRbmeBNwUz/X4KeoImcgCexYmOoHAswoGivbm4Eh99eBKOpbIsBa06ZTg==", + "requires": { + "aws-sdk": "^2.270.1", + "debug": "^3.1.0", + "gunzip-maybe": "^1.4.1", + "mime-types": "^2.1.18", + "tar-stream": "^1.6.1" + } + }, + "archiver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.0.tgz", + "integrity": "sha512-iUw+oDwK0fgNpvveEsdQ0Ase6IIKztBJU2U0E9MzszMfmVVUyv1QJhS2ITW9ZCqx8dktAxVAjWWkKehuZE8OPg==", + "requires": { + "archiver-utils": "^2.1.0", + "async": "^3.2.0", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.0.0", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "dependencies": { + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + } + } + } + }, + "archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "requires": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "array-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", - "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=" - }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" - }, "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true }, + "async": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.1.tgz", + "integrity": "sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "aws-sdk": { + "version": "2.967.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.967.0.tgz", + "integrity": "sha512-1IuQZsYZS67AMtywea+hL737sWHzeAzCqX3tEKTieMI+Ip5UoY4rNmQbJlUo8ysY+u8lixoiCFivEQfb/DG1cw==", + "requires": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.3.2", + "xml2js": "0.4.19" + } + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, "base64url": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==" }, "before-after-hook": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.1.tgz", - "integrity": "sha512-/6FKxSTWoJdbsLDF8tdIjaRiFXiE6UHsEHE3OPI/cwPURCVi1ukP0gmLn7XWEiFk5TcwQjjY5PWsU+j+tgXgmw==" + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", + "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==" }, "binary-extensions": { "version": "2.2.0", @@ -3989,9 +5723,9 @@ "dev": true }, "binaryextensions": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-4.15.0.tgz", - "integrity": "sha512-MkUl3szxXolQ2scI1PM14WOT951KnaTNJ0eMKg7WzOI4kvSxyNo/Cygx4LOBNhwyINhAuSQpJW1rYD9aBSxGaw==" + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-4.18.0.tgz", + "integrity": "sha512-PQu3Kyv9dM4FnwB7XGj1+HucW+ShvJzJqjuw1JkKVs1mWdwOKVcRjOi+pV9X52A0tNvrPCsPkbFFQb+wE1EAXw==" }, "bl": { "version": "2.2.1", @@ -4000,8 +5734,37 @@ "requires": { "readable-stream": "^2.3.5", "safe-buffer": "^5.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, "body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", @@ -4023,6 +5786,19 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -4042,15 +5818,6 @@ "widest-line": "^3.1.0" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, "chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -4061,27 +5828,6 @@ "supports-color": "^7.1.0" } }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4117,6 +5863,14 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "requires": { + "pako": "~0.2.0" + } + }, "bson": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz", @@ -4127,37 +5881,67 @@ "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", "integrity": "sha1-M3dm2hWAEhD92VbCLpxokaudAzc=" }, + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, + "cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==" + }, "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", "requires": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", + "keyv": "^4.0.0", "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - } + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" } }, "camelcase": { @@ -4181,13 +5965,24 @@ } }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "check-error": { @@ -4197,21 +5992,26 @@ "dev": true }, "chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", "dev": true, "requires": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "readdirp": "~3.6.0" } }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, "ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", @@ -4244,28 +6044,44 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, "requires": { "mimic-response": "^1.0.0" } }, "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "requires": { - "color-name": "1.1.3" + "color-name": "~1.1.4" } }, "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "compress-commons": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", + "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", + "requires": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + } }, "compressible": { "version": "2.0.18", @@ -4287,6 +6103,21 @@ "on-headers": "~1.0.2", "safe-buffer": "5.1.2", "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } } }, "concat-map": { @@ -4309,9 +6140,9 @@ } }, "connect-redis": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/connect-redis/-/connect-redis-5.1.0.tgz", - "integrity": "sha512-Cosy8gGUdkBPEYG84svgkzIGzspKBb98NUX4Nfc5eTJOF0A++41ZV15rPwWW0n5nU/FusNgNzuMeXhLVEQF80Q==" + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/connect-redis/-/connect-redis-6.0.0.tgz", + "integrity": "sha512-6eGEAAPHYvcfbRNCMmPzBIjrqRWLw7at9lCUH4G6NQ8gwWDJelaUmFNOqPIhehbw941euVmIuqWsaWiKXfb+5g==" }, "content-disposition": { "version": "0.5.3", @@ -4341,6 +6172,30 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "crc-32": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", + "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", + "requires": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + } + }, + "crc32-stream": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", + "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", + "requires": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + } + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, "crypto-random-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", @@ -4348,11 +6203,11 @@ "dev": true }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "decamelize": { @@ -4362,12 +6217,18 @@ "dev": true }, "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "requires": { - "mimic-response": "^1.0.0" + "mimic-response": "^3.1.0" + }, + "dependencies": { + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + } } }, "deep-eql": { @@ -4394,9 +6255,14 @@ } }, "defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, "denque": { @@ -4434,19 +6300,50 @@ "is-obj": "^2.0.0" } }, + "dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==" + }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, - "editions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/editions/-/editions-6.1.0.tgz", - "integrity": "sha512-h6nWEyIocfgho9J3sTSuhU/WoFOu1hTX75rPBebNrbF38Y9QFDjCDizYXdikHTySW7Y3mSxli8bpDz9RAtc7rA==", + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", "requires": { - "errlop": "^4.0.0", - "version-range": "^1.0.0" + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "ee-first": { @@ -4473,11 +6370,6 @@ "once": "^1.4.0" } }, - "errlop": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/errlop/-/errlop-4.1.0.tgz", - "integrity": "sha512-vul6gGBuVt0M2TPi1/WrcL86+Hb3Q2Tpu3TME3sbVhZrYf7J1ZMHCodI25RQKCVurh56qTfvgM0p3w5cT4reSQ==" - }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -4496,15 +6388,26 @@ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + }, + "exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", + "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==" + }, "express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", @@ -4540,74 +6443,73 @@ "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } } }, "express-rate-limit": { - "version": "5.2.6", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.2.6.tgz", - "integrity": "sha512-nE96xaxGfxiS5jP3tD3kIW1Jg9yQgX0rXCs3rCkZtmbWHEGyotwaezkLj7bnB41Z0uaOLM8W4AX6qHao4IZ2YA==" + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.3.0.tgz", + "integrity": "sha512-qJhfEgCnmteSeZAeuOKQ2WEIFTX5ajrzE0xS6gCOBCoRQcU+xEzQmgYQQTpzCcqUAAzTEtu4YEih4pnLfvNtew==" }, "express-session": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz", - "integrity": "sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==", + "version": "1.17.2", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", + "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==", "requires": { - "cookie": "0.4.0", + "cookie": "0.4.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "~2.0.0", "on-headers": "~1.0.2", "parseurl": "~1.3.3", - "safe-buffer": "5.2.0", + "safe-buffer": "5.2.1", "uid-safe": "~2.1.5" }, "dependencies": { - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + "cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" }, - "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" - } - } - }, - "extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "requires": { - "@types/yauzl": "^2.9.1", - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "dependencies": { "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { - "ms": "2.1.2" + "ms": "2.0.0" } }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" } } }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "requires": { - "pend": "~1.2.0" - } - }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -4629,6 +6531,21 @@ "parseurl": "~1.3.3", "statuses": "~1.5.0", "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } } }, "find-up": { @@ -4647,10 +6564,21 @@ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true }, + "form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" }, "fresh": { "version": "0.5.2", @@ -4662,15 +6590,10 @@ "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==" }, - "fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, "fs.realpath": { "version": "1.0.0", @@ -4704,23 +6627,10 @@ "pump": "^3.0.0" } }, - "github-linguist": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/github-linguist/-/github-linguist-2.3.0.tgz", - "integrity": "sha512-pDskxid9R1/VHsgEwbaht8+oxnFjfvFJRg0nemV/kMyDjeh6Z3/s8WAlG1OO59XhmRF4qvOHK9ai8gfIgQ0GUQ==", - "requires": { - "chalk": "^2.2.0", - "commander": "^2.11.0", - "fs-extra": "^4.0.3", - "globby": "^6.1.0", - "language-map": "^1.3.0", - "slash2": "^2.0.0" - } - }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -4748,52 +6658,28 @@ "ini": "1.3.7" } }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "dependencies": { - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - } + "version": "11.8.2", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", + "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", + "requires": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.1", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" } }, "graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" }, "growl": { "version": "1.10.5", @@ -4801,10 +6687,24 @@ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, + "gunzip-maybe": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz", + "integrity": "sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==", + "requires": { + "browserify-zlib": "^0.1.4", + "is-deflate": "^1.0.0", + "is-gzip": "^1.0.0", + "peek-stream": "^1.1.0", + "pumpify": "^1.3.3", + "through2": "^2.0.3" + } + }, "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true }, "has-yarn": { "version": "2.1.0", @@ -4821,8 +6721,7 @@ "http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" }, "http-errors": { "version": "1.7.2", @@ -4843,6 +6742,15 @@ } } }, + "http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "requires": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -4851,6 +6759,11 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, "ignore-by-default": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", @@ -4912,6 +6825,11 @@ "ci-info": "^2.0.0" } }, + "is-deflate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", + "integrity": "sha1-yGKQHDwWH7CdrHzcfnhPgOmPLxQ=" + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -4933,6 +6851,11 @@ "is-extglob": "^2.1.1" } }, + "is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha1-bKiwe5nHeZgCWQDlVc7Y7YCHmoM=" + }, "is-installed-globally": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", @@ -4984,6 +6907,12 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, "is-yarn-global": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", @@ -5002,52 +6931,46 @@ "dev": true }, "istextorbinary": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-5.12.0.tgz", - "integrity": "sha512-wLDRWD7qpNTYubk04+q3en1+XZGS4vYWK0+SxNSXJLaITMMEK+J3o/TlOMyULeH1qozVZ9uUkKcyMA8odyxz8w==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-6.0.0.tgz", + "integrity": "sha512-4j3UqQCa06GAf6QHlN3giz2EeFU7qc6Q5uB/aY7Gmb3xmLDLepDOtsZqkb4sCfJgFvTbLUinNw0kHgHs8XOHoQ==", "requires": { - "binaryextensions": "^4.15.0", - "editions": "^6.1.0", - "textextensions": "^5.11.0" + "binaryextensions": "^4.18.0", + "textextensions": "^5.14.0" } }, + "jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" + }, "js-yaml": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", - "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "requires": { "argparse": "^2.0.1" } }, "json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } + "kareem": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz", + "integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ==" }, "keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", + "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", "requires": { - "json-buffer": "3.0.0" + "json-buffer": "3.0.1" } }, - "language-map": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/language-map/-/language-map-1.4.0.tgz", - "integrity": "sha512-5XHMCqKQ/14VXwJTKZX7MZwsVyTrR0bwCsRBwrBq3nP4w7liMJiR0ixXgI29EF/T1/U6be8cYK2y0ibWW9kx2w==" - }, "latest-version": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", @@ -5057,6 +6980,38 @@ "package-json": "^6.3.0" } }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "requires": { + "readable-stream": "^2.0.5" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -5066,71 +7021,45 @@ "p-locate": "^5.0.0" } }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=" + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=" + }, "log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "requires": { - "chalk": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" } }, "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" }, "make-dir": { "version": "3.1.0", @@ -5149,6 +7078,12 @@ } } }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -5176,23 +7111,22 @@ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { - "version": "1.47.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", - "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==" + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz", + "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==" }, "mime-types": { - "version": "2.1.30", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", - "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", + "version": "2.1.32", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz", + "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==", "requires": { - "mime-db": "1.47.0" + "mime-db": "1.49.0" } }, "mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" }, "minimatch": { "version": "3.0.4", @@ -5208,34 +7142,39 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, "mocha": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.2.tgz", - "integrity": "sha512-UdmISwr/5w+uXLPKspgoV7/RXZwKRTiTjJ2/AC5ZiEztIoOYdfKb19+9jNmEInzx5pBsCyJQzarAxqIGBNYJhg==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.0.3.tgz", + "integrity": "sha512-hnYFrSefHxYS2XFGtN01x8un0EwNu2bzKvhpRFhgoybIvMaOkkL60IVPmkb5h6XDmUl4IMSB+rT5cIO4/4bJgg==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.5.1", + "chokidar": "3.5.2", "debug": "4.3.1", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.1.6", + "glob": "7.1.7", "growl": "1.10.5", "he": "1.2.0", - "js-yaml": "4.0.0", - "log-symbols": "4.0.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", "minimatch": "3.0.4", "ms": "2.1.3", - "nanoid": "3.1.20", - "serialize-javascript": "5.0.1", + "nanoid": "3.1.23", + "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", "wide-align": "1.1.3", - "workerpool": "6.1.0", + "workerpool": "6.1.5", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" @@ -5257,58 +7196,101 @@ "dev": true } } - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } } } }, "mongodb": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.6.tgz", - "integrity": "sha512-WlirMiuV1UPbej5JeCMqE93JRfZ/ZzqE7nJTwP85XzjAF4rRSeq2bGCb1cjfoHLOF06+HxADaPGqT0g3SbVT1w==", + "version": "3.6.11", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.11.tgz", + "integrity": "sha512-4Y4lTFHDHZZdgMaHmojtNAlqkvddX2QQBEN0K//GzxhGwlI9tZ9R0vhbjr1Decw+TF7qK0ZLjQT292XgHRRQgw==", "requires": { "bl": "^2.2.1", "bson": "^1.1.4", "denque": "^1.4.1", - "optional-require": "^1.0.2", + "optional-require": "^1.0.3", "safe-buffer": "^5.1.2", "saslprep": "^1.0.0" } }, + "mongoose": { + "version": "5.13.7", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.7.tgz", + "integrity": "sha512-ADIvftZ+KfoTALMZ0n8HvBlezFhcUd73hQaHQDwQ+3X+JZlqE47fUy9yhFZ2SjT+qzmuaCcIXCfhewIc38t2fQ==", + "requires": { + "@types/mongodb": "^3.5.27", + "bson": "^1.1.4", + "kareem": "2.3.2", + "mongodb": "3.6.11", + "mongoose-legacy-pluralize": "1.0.2", + "mpath": "0.8.3", + "mquery": "3.2.5", + "ms": "2.1.2", + "optional-require": "1.0.x", + "regexp-clone": "1.0.0", + "safe-buffer": "5.2.1", + "sift": "13.5.2", + "sliced": "1.0.1" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } + } + }, + "mongoose-legacy-pluralize": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", + "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==", + "requires": {} + }, + "mpath": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.3.tgz", + "integrity": "sha512-eb9rRvhDltXVNL6Fxd2zM9D4vKBxjVVQNLNijlj7uoXUy19zNDsIif5zR+pWmPCWNKwAtqyo4JveQm4nfD5+eA==" + }, + "mquery": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.5.tgz", + "integrity": "sha512-VjOKHHgU84wij7IUoZzFRU07IAxd5kWJaDmyUzQlbjHjyoeK5TNeeo8ZsFDtTYnSgpW6n/nMNIHvE3u8Lbrf4A==", + "requires": { + "bluebird": "3.5.1", + "debug": "3.1.0", + "regexp-clone": "^1.0.0", + "safe-buffer": "5.1.2", + "sliced": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "nanoid": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", - "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", "dev": true }, "negotiator": { @@ -5322,9 +7304,9 @@ "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" }, "nodemon": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.7.tgz", - "integrity": "sha512-XHzK69Awgnec9UzHr1kc8EomQh4sjTQ8oRf8TsGrSmHDx9/UmiGG9E/mM3BuTfNeFwdNBvrqQq/RHL0xIeyFOA==", + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.12.tgz", + "integrity": "sha512-egCTmNZdObdBxUBw6ZNwvZ/xzk24CKRs5K6d+5zbmrMr7rOpPmfPeF6OxM3DDpaRx331CQRFEktn+wrFFfBSOA==", "dev": true, "requires": { "chokidar": "^3.2.2", @@ -5339,20 +7321,20 @@ "update-notifier": "^4.1.0" }, "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { - "ms": "^2.1.1" + "has-flag": "^3.0.0" } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true } } }, @@ -5368,25 +7350,18 @@ "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, "normalize-url": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", - "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", - "dev": true + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" }, "oauth": { "version": "0.9.15", "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", "integrity": "sha1-vR/vr2hslrdUda7VGWQS/2DPucE=" }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -5414,10 +7389,9 @@ "integrity": "sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA==" }, "p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==" }, "p-limit": { "version": "3.1.0", @@ -5449,6 +7423,131 @@ "semver": "^6.2.0" }, "dependencies": { + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "dependencies": { + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + } + } + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + }, + "dependencies": { + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + } + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -5457,6 +7556,11 @@ } } }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=" + }, "parse-github-url": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz", @@ -5485,9 +7589,9 @@ } }, "passport-oauth2": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.5.0.tgz", - "integrity": "sha512-kqBt6vR/5VlCK8iCx1/KpY42kQ+NEHZwsSyt4Y6STiNjU+wWICG1i8ucc1FapXDGO15C5O5VZz7+7vRzrDPXXQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.6.0.tgz", + "integrity": "sha512-emXPLqLcVEcLFR/QvQXZcwLmfK8e9CqvMgmOFJxcNT3okSFMtUbRRKpY20x5euD+01uHsjjCa07DYboEeLXYiw==", "requires": { "base64url": "3.x.x", "oauth": "0.9.x", @@ -5528,34 +7632,21 @@ "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + "peek-stream": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", + "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", + "requires": { + "buffer-from": "^1.0.0", + "duplexify": "^3.5.0", + "through2": "^2.0.3" + } }, "picomatch": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", - "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", - "dev": true - }, - "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "requires": { - "pinkie": "^2.0.0" - } + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true }, "prepend-http": { "version": "2.0.0", @@ -5563,17 +7654,22 @@ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", "dev": true }, + "printj": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", + "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==" + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "proxy-addr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "requires": { - "forwarded": "~0.1.2", + "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, @@ -5592,6 +7688,32 @@ "once": "^1.3.1" } }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, "pupa": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", @@ -5606,6 +7728,16 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==" + }, "random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", @@ -5673,23 +7805,27 @@ } }, "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "readdir-glob": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.1.tgz", + "integrity": "sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA==", + "requires": { + "minimatch": "^3.0.4" } }, "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "requires": { "picomatch": "^2.2.1" @@ -5724,6 +7860,11 @@ "redis-errors": "^1.0.0" } }, + "regexp-clone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", + "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" + }, "registry-auth-token": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", @@ -5748,13 +7889,17 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, + "resolve-alpn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.0.tgz", + "integrity": "sha512-e4FNQs+9cINYMO5NMFc6kOUCdohjqFPSgMuwuZAOUWqrfWsen+Yjy5qZFkV5K7VO7tFSLKcUL97olkED7sCBHA==" + }, "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", "requires": { - "lowercase-keys": "^1.0.0" + "lowercase-keys": "^2.0.0" } }, "safe-buffer": { @@ -5776,6 +7921,11 @@ "sparse-bitfield": "^3.0.3" } }, + "sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -5819,6 +7969,21 @@ "statuses": "~1.5.0" }, "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", @@ -5827,9 +7992,9 @@ } }, "serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "requires": { "randombytes": "^2.1.0" @@ -5851,16 +8016,21 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" }, + "sift": { + "version": "13.5.2", + "resolved": "https://registry.npmjs.org/sift/-/sift-13.5.2.tgz", + "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA==" + }, "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, - "slash2": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash2/-/slash2-2.0.0.tgz", - "integrity": "sha512-7ElvBydJPi3MHU/KEOblFSbO/skl4Z69jKkFCpYIYVOMSIZsKi4gYU43HGeZPmjxCXrHekoDAAewphPQNnsqtA==" + "sliced": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", + "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" }, "sparse-bitfield": { "version": "3.0.3", @@ -5876,12 +8046,24 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } } }, "string-width": { @@ -5911,11 +8093,103 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" + } + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + }, + "dependencies": { + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + } + } + } + }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + }, + "dependencies": { + "bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "term-size": { @@ -5925,9 +8199,47 @@ "dev": true }, "textextensions": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-5.12.0.tgz", - "integrity": "sha512-IYogUDaP65IXboCiPPC0jTLLBzYlhhw2Y4b0a2trPgbHNGGGEfuHE6tds+yDcCf4mpNDaGISFzwSSezcXt+d6w==" + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-5.14.0.tgz", + "integrity": "sha512-4cAYwNFNYlIAHBUo7p6zw8POUvWbZor+/R0Tanv+rIhsauEyV9QSrEXL40pI+GfTQxKX8k6Tyw6CmdSDSmASrg==" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" }, "to-readable-stream": { "version": "1.0.0", @@ -5958,6 +8270,34 @@ "nopt": "~1.0.10" } }, + "ts-node": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.2.0.tgz", + "integrity": "sha512-FstYHtQz6isj8rBtYMN4bZdnXN1vq4HCbqn9vdNQcInRqtB86PePJQIxE6es0PhxKWhj2PHuwbG40H+bxkZPmg==", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "0.6.1", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "yn": "3.1.1" + }, + "dependencies": { + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + } + } + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -5988,6 +8328,12 @@ "is-typedarray": "^1.0.0" } }, + "typescript": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", + "dev": true + }, "uid-safe": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", @@ -6008,6 +8354,23 @@ "dev": true, "requires": { "debug": "^2.2.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "unique-string": { @@ -6024,11 +8387,6 @@ "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -6055,15 +8413,6 @@ "xdg-basedir": "^4.0.0" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, "chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -6074,27 +8423,6 @@ "supports-color": "^7.1.0" } }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -6106,6 +8434,15 @@ } } }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, "url-parse-lax": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", @@ -6125,24 +8462,16 @@ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, - "version-compare": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/version-compare/-/version-compare-1.1.0.tgz", - "integrity": "sha512-zVKtPOJTC9x23lzS4+4D7J+drq80BXVYAmObnr5zqxxFVH7OffJ1lJlAS7LYsQNV56jx/wtbw0UV7XHLrvd6kQ==" - }, - "version-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/version-range/-/version-range-1.1.0.tgz", - "integrity": "sha512-R1Ggfg2EXamrnrV3TkZ6yBNgITDbclB3viwSjbZ3+eK0VVNK4ajkYJTnDz5N0bIMYDtK9MUBvXJUnKO5RWWJ6w==", - "requires": { - "version-compare": "^1.0.0" - } - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -6204,9 +8533,9 @@ } }, "workerpool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", - "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", + "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==", "dev": true }, "wrap-ansi": { @@ -6218,32 +8547,6 @@ "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } } }, "wrappy": { @@ -6269,6 +8572,40 @@ "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true }, + "xml-flow": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/xml-flow/-/xml-flow-1.0.4.tgz", + "integrity": "sha512-r19LXKPL7vkVGL6oWHlESoBgwUVom5w/w8opuS53qULh8+K2w+K9K72edTIQa+X/Vxx1R7ugnCabHFSZ1Tv2zA==", + "requires": { + "sax": "^1.2.4" + }, + "dependencies": { + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + } + } + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -6316,20 +8653,27 @@ } } }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true + }, + "zip-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", + "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", + "requires": { + "archiver-utils": "^2.1.0", + "compress-commons": "^4.1.0", + "readable-stream": "^3.6.0" + } } } } diff --git a/package.json b/package.json index 51776a7..af60853 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,14 @@ { "name": "anonymous_github", - "version": "2.0.0", + "version": "2.1.0", "description": "Anonymise Github repositories for double-anonymous reviews", - "main": "index.js", + "main": "index.ts", "scripts": { "test": "mocha --reporter spec", - "start": "node index.js", - "dev": "nodemon index.js" + "start": "node --inspect=5858 -r ts-node/register ./index.ts", + "dev": "nodemon --transpile-only index.ts", + "migrateDB": "ts-node --transpile-only migrateDB.ts", + "build": "tsc" }, "repository": { "type": "git", @@ -17,31 +19,57 @@ "bugs": { "url": "https://github.com/tdurieux/anonymous_github/issues" }, + "funding": { + "url": "https://github.com/sponsors/tdurieux" + }, "homepage": "https://github.com/tdurieux/anonymous_github#readme", "dependencies": { "@octokit/oauth-app": "^3.3.2", "@octokit/rest": "^18.5.3", - "array-equal": "^1.0.0", + "archive-stream-to-s3": "^1.1.3", + "archiver": "^5.3.0", + "aws-sdk": "^2.958.0", "compression": "^1.7.4", - "connect-redis": "^5.1.0", + "connect-redis": "^6.0.0", + "dotenv": "^10.0.0", "express": "^4.17.1", "express-rate-limit": "^5.2.6", "express-session": "^1.17.1", - "extract-zip": "^2.0.1", - "github-linguist": "^2.3.0", - "istextorbinary": "^5.12.0", - "mongodb": "^3.6.6", + "got": "^11.8.2", + "gunzip-maybe": "^1.4.2", + "istextorbinary": "^6.0.0", + "mime-types": "^2.1.30", + "mongoose": "^5.13.5", "parse-github-url": "^1.0.2", "passport": "^0.4.1", "passport-github2": "^0.1.12", "rate-limit-redis": "^2.1.0", "redis": "^3.1.2", - "textextensions": "^5.12.0" + "tar-fs": "^2.1.1", + "textextensions": "^5.12.0", + "xml-flow": "^1.0.4" }, "devDependencies": { + "@types/archiver": "^5.1.1", + "@types/compression": "^1.7.1", + "@types/connect-redis": "^0.0.17", + "@types/express": "^4.17.13", + "@types/express-rate-limit": "^5.1.3", + "@types/express-session": "^1.17.4", + "@types/got": "^9.6.12", + "@types/mime-types": "^2.1.0", + "@types/parse-github-url": "^1.0.0", + "@types/passport": "^1.0.7", + "@types/passport-github2": "^1.2.5", + "@types/rate-limit-redis": "^1.7.2", + "@types/redis": "^2.8.31", + "@types/tar-fs": "^2.0.1", + "@types/xml-flow": "^1.0.1", "chai": "^4.3.4", - "mocha": "^8.3.2", - "nodemon": "^2.0.4" + "mocha": "^9.0.3", + "nodemon": "^2.0.7", + "ts-node": "^10.1.0", + "typescript": "^4.3.5" }, "nodemonConfig": { "ignore": [ diff --git a/public/css/style.css b/public/css/style.css index 54f92c8..9db9a1d 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -78,8 +78,8 @@ input, button { outline: none; } -*:hover, -*:active { +input:hover, +input:active { box-shadow: none !important; } @@ -326,7 +326,7 @@ a:hover { cursor: default; } -.paths { +.status-bar { background-color: var(--main-bg-color); padding: 8px 6px; margin: 0; @@ -334,6 +334,15 @@ a:hover { border-radius: 0; } +.paths { + padding: 0; + margin: 0; + background-color: initial; + border: none; + border-radius: 0; + align-items: center; +} + .paths a { color: var(--color); } @@ -507,3 +516,4 @@ loc .lang { rgb(23 26 49) 100% ); } + diff --git a/public/partials/anonymize.htm b/public/partials/anonymize.htm index 4d4afab..9b5fc83 100644 --- a/public/partials/anonymize.htm +++ b/public/partials/anonymize.htm @@ -335,8 +335,8 @@

name="mode" ng-model="options.mode" > - - + + How the repository will be anonymized. Stream mode will @@ -367,22 +367,6 @@

https://anonymous.4open.science/w/{{repoId}} -
- - - Display the number of line of code in the - repository -
diff --git a/public/partials/dashboard.htm b/public/partials/dashboard.htm index 0f1be00..fda0c1b 100644 --- a/public/partials/dashboard.htm +++ b/public/partials/dashboard.htm @@ -73,6 +73,8 @@

Status
/> +

Quota
+ {{quota.used | humanFileSize}}/{{quota.total| humanFileSize}}
@@ -95,6 +97,9 @@
Status
Anonymize date + + Size + # Views @@ -113,32 +118,30 @@
Status
{{$index + 1}} - {{repo.repoId}} + {{repo.repoId}} {{repo.fullName}}{{repo.source.fullName}} - {{repo.branch}} + {{repo.source.branch.name}} - {{repo.terms.length}} + {{repo.options.terms.length}} Status {{repo.anonymizeDate | date}} - {{repo.pageView}} + + {{repo.size | humanFileSize}} + + + {{repo.pageView}} + {{repo.lastView | date}} @@ -214,10 +222,7 @@
Status
> Remove - + View Repo
diff --git a/public/script/app.js b/public/script/app.js index 96673e5..406b301 100644 --- a/public/script/app.js +++ b/public/script/app.js @@ -81,6 +81,30 @@ angular $locationProvider.html5Mode(true); }) .run(["Analytics", function (Analytics) {}]) + .filter("humanFileSize", function () { + return function humanFileSize(bytes, si = false, dp = 1) { + const thresh = si ? 1000 : 1024; + + bytes = bytes / 8; + + if (Math.abs(bytes) < thresh) { + return bytes + " B"; + } + + const units = si + ? ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"] + : ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"]; + let u = -1; + const r = 10 ** dp; + + do { + bytes /= thresh; + ++u; + } while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1); + + return bytes.toFixed(dp) + " " + units[u]; + }; + }) .filter("title", function () { return function (str) { if (!str) return str; @@ -370,7 +394,7 @@ angular notebook: true, loc: true, link: true, - mode: "download", + mode: "GitHubDownload", }; function getDefault() { @@ -500,6 +524,13 @@ angular } getRepositories(); + function getQuota() { + $http.get("/api/user/quota").then((res) => { + $scope.quota = res.data; + }, console.error); + } + getQuota(); + $scope.removeRepository = (repo) => { if ( confirm( @@ -551,13 +582,13 @@ angular if ($scope.repo.status == "ready") { $scope.progress = 100; } else if ($scope.repo.status == "queue") { - $scope.progress = 0; + $scope.progress = 10; } else if ($scope.repo.status == "downloaded") { $scope.progress = 50; } else if ($scope.repo.status == "downloading") { $scope.progress = 25; } else if ($scope.repo.status == "preparing") { - $scope.progress = 10; + $scope.progress = 25; } else if ($scope.repo.status == "anonymizing") { $scope.progress = 75; } @@ -596,9 +627,8 @@ angular image: true, pdf: true, notebook: true, - loc: true, link: true, - mode: "download", + mode: "GitHubDownload", }; $scope.options.expirationDate.setDate( $scope.options.expirationDate.getDate() + 90 @@ -630,10 +660,10 @@ angular $scope.repoId = $routeParams.repoId; $http.get("/api/repo/" + $scope.repoId).then( async (res) => { - $scope.repoUrl = "https://github.com/" + res.data.fullName; + $scope.repoUrl = "https://github.com/" + res.data.source.fullName; - $scope.terms = res.data.terms.join("\n"); - $scope.branch = res.data.branch; + $scope.terms = res.data.options.terms.join("\n"); + $scope.branch = res.data.source.branch.name; $scope.options = res.data.options; $scope.conference = res.data.conference; if (res.data.options.expirationDate) { @@ -648,11 +678,11 @@ angular } $scope.details = ( - await $http.get(`/api/repo/${res.data.fullName}/`) + await $http.get(`/api/repo/${res.data.source.fullName}/`) ).data; - await getReadme(); await $scope.getBranches(); + await getReadme(); anonymize(); $scope.$apply(); }, @@ -709,24 +739,32 @@ angular }; $('[data-toggle="tooltip"]').tooltip(); - $scope.$watch("branch", (v) => { - if ($scope.branches && $scope.branches[$scope.branch]) { - $scope.commit = $scope.branches[$scope.branch].commit.sha; - } - if ($scope.details && $scope.details.has_page) { - $scope.anonymize.page.disabled(false); + $scope.$watch("branch", async (v) => { + const selected = $scope.branches.filter( + (f) => f.name == $scope.branch + )[0]; + if ($scope.details && $scope.details.hasPage) { + $scope.anonymize.page.$$element[0].disabled = false; if ($scope.details.pageSource.branch != $scope.branch) { - $scope.anonymize.page.disabled(true); + $scope.anonymize.page.$$element[0].disabled = true; } } + + if (selected) { + $scope.commit = selected.commit; + $scope.readme = selected.readme; + await getReadme(); + anonymize(); + $scope.$apply(); + } }); $scope.$watch("options.mode", (v) => { - if (v == "stream") { - $scope.options.loc = false; - $scope.anonymize.loc.$$element[0].disabled = true; + if (v == "GitHubStream") { + $scope.options.page = false; + $scope.anonymize.page.$$element[0].disabled = true; } else { - $scope.anonymize.loc.$$element[0].disabled = false; + $scope.anonymize.page.$$element[0].disabled = false; } }); @@ -749,10 +787,12 @@ angular ); $scope.branches = branches.data; if (!$scope.branch) { - $scope.branch = $scope.details.default_branch; + $scope.branch = $scope.details.defaultBranch; } - if ($scope.branches[$scope.branch]) { - $scope.commit = $scope.branches[$scope.branch].commit.sha; + const selected = $scope.branches.filter((b) => b.name == $scope.branch); + if (selected.length > 0) { + $scope.commit = selected[0].commit; + $scope.readme = selected[0].readme; } $scope.$apply(); }; @@ -771,12 +811,10 @@ angular const res = await $http.get(`/api/repo/${o.owner}/${o.repo}/`); $scope.details = res.data; if ($scope.details.size > 1024 * 8) { - $scope.options.mode = "stream"; - $scope.options.loc = false; + $scope.options.mode = "GitHubStream"; $scope.anonymize.mode.$$element[0].disabled = true; - $scope.anonymize.loc.$$element[0].disabled = true; } - $scope.repoId = $scope.details.name + "-" + generateRandomId(4); + $scope.repoId = $scope.details.repo + "-" + generateRandomId(4); await $scope.getBranches(); } catch (error) { if (error.data) { @@ -790,13 +828,16 @@ angular } } - async function getReadme() { + async function getReadme(force) { + if ($scope.readme) return $scope.readme; const o = parseGithubUrl($scope.repoUrl); - const res = await $http.get(`/api/repo/${o.owner}/${o.repo}/readme`); + const res = await $http.get(`/api/repo/${o.owner}/${o.repo}/readme`, { + params: { force: force === true ? "1" : "0", branch: $scope.branch }, + }); $scope.readme = res.data; } - async function anonymize() { + function anonymize() { const urlRegex = /?/g; let content = $scope.readme; @@ -890,6 +931,7 @@ angular function getRepo() { const o = parseGithubUrl($scope.repoUrl); + $scope.options.pageSource = $scope.details.pageSource; return { repoId: $scope.repoId, terms: $scope.terms.trim().split("\n"), @@ -966,6 +1008,7 @@ angular txt: "text", py: "python", js: "javascript", + ts: "typescript", }; const textFiles = ["license", "txt"]; const imageFiles = ["png", "jpg", "jpeg", "gif"]; @@ -1200,7 +1243,7 @@ angular getFiles(() => { updateContent(); - if (options.mode == "download") { + if (options.mode == "GitHubDownload") { getStats(); } }); diff --git a/routes/connection.js b/routes/connection.js deleted file mode 100644 index 51e24ec..0000000 --- a/routes/connection.js +++ /dev/null @@ -1,102 +0,0 @@ -const redis = require("redis"); - -const passport = require("passport"); -const session = require("express-session"); -const redisStore = require("connect-redis")(session); -const GitHubStrategy = require("passport-github2").Strategy; - -const express = require("express"); - -const router = express.Router(); - -const db = require("../utils/database"); -const config = require("../config"); - -function ensureAuthenticated(req, res, next) { - if (req.isAuthenticated()) { - return next(); - } - res.status(401).json({ error: "not_connected" }); -} - -passport.serializeUser(function(user, done) { - delete user.profile._json; - done(null, user); -}); - -passport.deserializeUser(function(obj, done) { - done(null, obj); -}); - -passport.use( - new GitHubStrategy( - { - clientID: config.CLIENT_ID, - clientSecret: config.CLIENT_SECRET, - callbackURL: config.AUTH_CALLBACK, - }, - async (accessToken, refreshToken, profile, done) => { - try { - await db - .get() - .collection("users") - .updateOne( - { username: profile.username }, - { - $set: { - username: profile.username, - profile, - accessToken, - refreshToken, - }, - }, - { upsert: true } - ); - } catch (error) { - console.error(error); - } finally { - done(null, { - username: profile.username, - accessToken, - refreshToken, - profile, - }); - } - } - ) -); - -const rediscli = redis.createClient({ - host: "redis", - ttl: 260, -}); - -const appSession = session({ - secret: "keyboard cat", - store: new redisStore({ - client: rediscli, - }), - saveUninitialized: false, - resave: false, -}); - -router.get( - "/login", - passport.authenticate("github", { scope: ["repo"] }), // Note the scope here - function(req, res) { - res.redirect("/"); - } -); - -router.get( - "/auth", - passport.authenticate("github", { failureRedirect: "/" }), - function(req, res) { - res.redirect("/"); - } -); - -module.exports.ensureAuthenticated = ensureAuthenticated; -module.exports.passport = passport; -module.exports.session = appSession; -module.exports.router = router; diff --git a/routes/file.js b/routes/file.js deleted file mode 100644 index fb2d191..0000000 --- a/routes/file.js +++ /dev/null @@ -1,166 +0,0 @@ -const express = require("express"); -const path = require("path"); - -const db = require("../utils/database"); -const fileUtils = require("../utils/file"); -const repoUtils = require("../utils/repository"); -const githubUtils = require("../utils/github"); - -const router = express.Router(); - -async function anonymizeRepository(options) { - let repoConfig = options.repoConfig; - if (!repoConfig) { - repoConfig = await repoUtils.getConfig(options.repoId); - } - - if (repoConfig == null) { - throw "repo_not_found"; - } - if (repoConfig.status == "removed" || repoConfig.status == "expired") { - return; - } - - if (repoConfig.options.expirationMode != "never") { - if (repoConfig.options.expirationDate <= new Date()) { - console.log(repoConfig.repoId, "The repository is expired"); - await repoUtils.updateStatus(repoConfig, "expired"); - await repoUtils.removeRepository(repoConfig); - throw "repository_expired"; - } - } - - const lastView = repoConfig.lastView; - - const yesterday = new Date(); - yesterday.setDate(yesterday.getDate() - 1); - - if (repoConfig.options.update && lastView < yesterday) { - console.log(repoConfig.repoId, "check for updates in the repository."); - try { - } catch (error) { - console.error("Error while updating the repository."); - console.error(repoConfig.repoId, req.path, error); - } - await repoUtils.updateAnonymizedRepository(repoConfig); - } else { - await githubUtils.downloadRepoAndAnonymize(repoConfig); - } -} - -router.get("/:repoId/files", async (req, res) => { - const repoConfig = await repoUtils.getConfig(req.params.repoId); - if (repoConfig == null) { - return res.status(500).json({ error: "repo_not_found" }); - } - - if (repoConfig.status != "ready") { - return res.status(500).json({ error: "repo_not_ready" }); - } - - try { - const files = await fileUtils.getFileList({ repoConfig }); - return res.json(files); - } catch (error) { - console.error(req.path, error); - return res.status(500).json({ error }); - } -}); - -router.get("/:repoId/stats", async (req, res) => { - const repoConfig = await repoUtils.getConfig(req.params.repoId); - - if (repoConfig == null) { - return res.status(500).json({ error: "repo_not_found" }); - } - if (repoConfig.status != "ready") { - return res.status(500).json({ error: "repo_not_ready" }); - } - - if (repoConfig.options.mode == "stream") { - return res.status(500).json({ error: "stream_not_supported" }); - } - - try { - const stats = await fileUtils.getStats({ repoConfig }); - return res.json(stats.languages); - } catch (error) { - console.error(req.path, error); - return res.status(500).json({ error }); - } -}); - -router.get("/:repoId/options", async (req, res) => { - const repoConfig = await repoUtils.getConfig(req.params.repoId); - if (repoConfig == null) { - return res.status(500).json({ error: "repo_not_found" }); - } - try { - try { - await anonymizeRepository({ repoConfig }); - } catch (error) { - console.log("Error during the anonymization of the repository"); - console.error(req.path, error); - } - if (repoConfig.status == "removed") { - throw "repository_expired"; - } - if (repoConfig.status == "expired") { - if (repoConfig.options.expirationMode == "redirect") { - repoConfig.options.url = "https://github.com/" + repoConfig.fullName; - } else { - throw "repository_expired"; - } - } else if (repoConfig.status != "ready") { - throw "repository_not_ready"; - } - - return res.json(repoConfig.options); - } catch (error) { - console.error(req.path, error); - return res.status(500).json({ error }); - } -}); - -router.get("/:repoId/file/:path*", async (req, res) => { - const repoConfig = await repoUtils.getConfig(req.params.repoId); - - if (repoConfig == null) { - return res.status(500).json({ error: "repo_not_found" }); - } - if (repoConfig.status != "ready") { - return res.status(500).json({ error: "repo_not_ready" }); - } - - let requestPath = req.params.path; - if (req.params[0]) { - requestPath += req.params[0]; - } - - try { - const isValid = await fileUtils.isFilePathValid({ - repoConfig, - path: requestPath, - }); - if (isValid) { - await db - .get("anonymized_repositories") - .updateOne( - { repoId: repoConfig.repoId }, - { $set: { lastView: new Date() }, $inc: { pageView: 1 } } - ); - const ppath = path.join( - repoUtils.getAnonymizedPath(repoConfig.repoId), - requestPath - ); - return res.sendFile(ppath, { dotfiles: "allow" }); - } else { - return res.status(404).json({ error: "file_not_found" }); - } - } catch (error) { - console.error(req.path, error); - return res.status(500).send({ error }); - } -}); - -module.exports = router; diff --git a/routes/repository.js b/routes/repository.js deleted file mode 100644 index 950233f..0000000 --- a/routes/repository.js +++ /dev/null @@ -1,366 +0,0 @@ -const ofs = require("fs"); -const fs = require("fs").promises; - -const express = require("express"); -const gh = require("parse-github-url"); -const arrayEquals = require("array-equal"); - -const connection = require("./connection"); -const githubUtils = require("../utils/github"); -const db = require("../utils/database"); -const repoUtils = require("../utils/repository"); -const config = require("../config"); - -const router = express.Router(); - -// user needs to be connected for all user API -router.use(connection.ensureAuthenticated); - -// claim a repository -router.post("/claim", async (req, res) => { - try { - if (!req.body.repoId) { - return res.status(500).json({ error: "repoId_not_defined" }); - } - if (!req.body.repoUrl) { - return res.status(500).json({ error: "repoUrl_not_defined" }); - } - - const repoConfig = await repoUtils.getConfig(req.body.repoId); - if (repoConfig == null) { - return res.status(500).json({ error: "repo_not_found" }); - } - - const repo = gh(req.body.repoUrl); - if (repoConfig.fullName != repo.repository) { - return res.status(500).json({ error: "repo_not_found" }); - } - - console.log(`${req.user.username} claims ${repoConfig.fullName}.`); - - await db - .get("anonymized_repositories") - .updateOne( - { repoId: repoConfig.repoId }, - { $set: { owner: req.user.username } } - ); - return res.send("Ok"); - } catch (error) { - console.error(req.path, error); - return res.status(500).json({ error }); - } -}); - -router.get("/:repoId/", async (req, res) => { - try { - const repository = await repoUtils.getAnonymizedRepoDetails( - req.params.repoId, - req.user - ); - if (repository) { - return res.json(repository); - } - res.status(404).send({error: "repo_not_found"}); - } catch (error) { - console.error(req.path, error); - res.status(500).json({ error }); - } -}); - -// update a repository -router.post("/:repoId/", async (req, res) => { - const repoUpdate = req.body; - - let repoConfig = await repoUtils.getConfig(req.params.repoId); - if (repoConfig == null) { - return res.status(500).json({ error: "repo_not_found" }); - } - if (repoConfig.owner != req.user.username) { - return res.status(401).json({ error: "not_authorized" }); - } - if (!repoUpdate.branch) { - return res.status(500).json({ error: "branch_not_specified" }); - } - if (!repoUpdate.options) { - return res.status(500).json({ error: "options_not_provided" }); - } - if (!Array.isArray(repoUpdate.terms)) { - return res.status(500).send({ error: "invalid_terms_format" }); - } - if (!/^[a-f0-9]+$/.test(repoUpdate.commit)) { - return res.status(500).send({ error: "invalid_commit_format" }); - } - - try { - const details = await repoUtils.getRepoDetails({ - repoConfig, - force: true, - token: req.user.accessToken, - }); - if (repoUpdate.options.mode == "download") { - // details.size is in kilobytes - if (details.size > config.MAX_REPO_SIZE) { - return res.status(500).send({ error: "invalid_mode" }); - } - } - - if (repoUpdate.commit != repoConfig.commit) { - repoUpdate.anonymizeDate = new Date(); - await repoUtils.removeRepository(repoConfig); - } - if ( - !arrayEquals(repoUpdate.terms, repoConfig.terms) || - repoUpdate.options.link != repoConfig.options.link || - repoUpdate.options.image != repoConfig.options.image - ) { - repoUpdate.anonymizeDate = new Date(); - if (ofs.existsSync(repoUtils.getAnonymizedPath(repoConfig.repoId))) { - await fs.rm(repoUtils.getAnonymizedPath(repoConfig.repoId), { - recursive: true, - force: true, - }); - } - } - const data = { - terms: repoUpdate.terms, - branch: repoUpdate.branch, - commit: repoUpdate.commit, - options: { - expirationMode: repoUpdate.options.expirationMode, - expirationDate: repoUpdate.options.expirationDate, - update: repoUpdate.options.update, - image: repoUpdate.options.image, - pdf: repoUpdate.options.pdf, - notebook: repoUpdate.options.notebook, - loc: repoUpdate.options.loc, - link: repoUpdate.options.link, - mode: repoUpdate.options.mode, - page: repoUpdate.options.page, - }, - }; - if (repoUpdate.options.page) { - data.options.pageSource = details.pageSource; - } - await db.get("anonymized_repositories").updateOne( - { - repoId: repoConfig.repoId, - }, - { - $set: data, - } - ); - - repoConfig = await repoUtils.getConfig(repoUpdate.repoId); - await repoUtils.updateStatus(repoConfig, "preparing"); - - res.send("ok"); - } catch (error) { - console.error(req.path, error); - await repoUtils.updateStatus(repoConfig, "error", error); - return res.status(500).json({ error }); - } - try { - await githubUtils.downloadRepoAndAnonymize(repoConfig); - await repoUtils.updateStatus(repoConfig, "ready"); - } catch (error) { - console.error(req.path, error); - await repoUtils.updateStatus(repoConfig, "error", error); - } -}); - -// refresh a repository -router.post("/:repoId/refresh", async (req, res) => { - try { - const repoConfig = await repoUtils.getConfig(req.params.repoId); - if (repoConfig == null) { - return res.status(500).json({ error: "repo_not_found" }); - } - if (repoConfig.owner != req.user.username) { - return res.status(401).json({ error: "not_authorized" }); - } - - await repoUtils.updateAnonymizedRepository(repoConfig); - return res.send("ok"); - } catch (error) { - console.error(req.path, error); - return res.status(500).json({ error }); - } -}); - -// delete a repository -router.delete("/:repoId/", async (req, res) => { - try { - const repoConfig = await repoUtils.getConfig(req.params.repoId); - if (repoConfig == null) { - return res.status(500).json({ error: "repo_not_found" }); - } - if (repoConfig.owner != req.user.username) { - return res.status(401).json({ error: "not_authorized" }); - } - - await repoUtils.updateStatus(repoConfig, "removed"); - await repoUtils.removeRepository(repoConfig); - console.log(`${req.params.repoId} is removed`); - return res.json("ok"); - } catch (error) { - console.error(req.path, error); - return res.status(500).json({ error }); - } -}); - -router.get("/:owner/:repo/", async (req, res) => { - try { - const repository = await repoUtils.getRepoDetails({ - owner: req.params.owner, - repo: req.params.repo, - token: req.user.accessToken, - force: req.query.force === "1", - }); - if (repository) { - return res.json(repository); - } - res.status(404).send({error: "repo_not_found"}); - } catch (error) { - console.error(req.path, error); - res.status(500).json({ error }); - } -}); - -router.get("/:owner/:repo/branches", async (req, res) => { - try { - const repository = await repoUtils.getRepoBranches({ - owner: req.params.owner, - repo: req.params.repo, - token: req.user.accessToken, - force: req.query.force === "1", - }); - if (repository) { - return res.json(repository); - } - res.status(404).send({error: "repo_not_found"}); - } catch (error) { - console.error(req.path, error); - res.status(500).json({ error }); - } -}); - -router.get("/:owner/:repo/readme", async (req, res) => { - try { - const readme = await repoUtils.getRepoReadme({ - owner: req.params.owner, - repo: req.params.repo, - token: req.user.accessToken, - force: req.query.force === "1", - }); - if (readme) { - return res.send(readme); - } - res.status(404).send({error: "repo_not_found"}); - } catch (error) { - res.status(500).json({ error }); - } -}); - -router.post("/", async (req, res) => { - const repoConfig = req.body; - let data = null; - try { - const repository = await repoUtils.getConfig(repoConfig.repoId); - const cacheExist = ofs.existsSync( - repoUtils.getOriginalPath(repoConfig.repoId) - ); - if (repository && cacheExist) { - return res.status(500).send({ error: "repoId_already_used" }); - } - var validCharacters = /^[0-9a-zA-Z\-\_]+$/; - if ( - !repoConfig.repoId.match(validCharacters) || - repoConfig.repoId.length < 3 - ) { - return res.status(500).send({ error: "invalid_repoId" }); - } - if (!repoConfig.branch) { - return res.status(500).json({ error: "branch_not_specified" }); - } - if (!repoConfig.options) { - return res.status(500).json({ error: "options_not_provided" }); - } - if (!Array.isArray(repoConfig.terms)) { - return res.status(500).send({ error: "invalid_terms_format" }); - } - if (!/^[a-f0-9]+$/.test(repoConfig.commit)) { - return res.status(500).send({ error: "invalid_commit_format" }); - } - - await repoUtils.getRepoBranches({ - repoConfig, - token: req.user.accessToken, - }); - const details = await repoUtils.getRepoDetails({ - repoConfig, - token: req.user.accessToken, - }); - if (details.branches[repoConfig.branch] == null) { - return res.status(500).send({ error: "invalid_branch" }); - } - if (repoConfig.options.mode == "download") { - // details.size is in kilobytes - if (details.size > config.MAX_REPO_SIZE) { - return res.status(500).send({ error: "non_supported_mode" }); - } - } - - data = { - repoId: repoConfig.repoId, - fullName: repoConfig.fullName, - status: "preparing", - terms: repoConfig.terms, - owner: req.user.profile.username, - token: req.user.accessToken, - branch: repoConfig.branch, - conference: repoConfig.conference, - commit: repoConfig.commit - ? repoConfig.commit - : details.branches[repoConfig.branch].commit.sha, - anonymizeDate: new Date(), - options: { - expirationMode: repoConfig.options.expirationMode, - expirationDate: repoConfig.options.expirationDate, - update: repoConfig.options.update, - image: repoConfig.options.image, - pdf: repoConfig.options.pdf, - notebook: repoConfig.options.notebook, - loc: repoConfig.options.loc, - link: repoConfig.options.link, - mode: repoConfig.options.mode, - page: repoConfig.options.page, - }, - }; - if (repoConfig.options.page) { - data.options.pageSource = details.pageSource; - } - await db.get("anonymized_repositories").updateOne( - { - repoId: data.repoId, - }, - { - $set: data, - }, - { upsert: true } - ); - res.send("ok"); - } catch(error) { - console.error(req.path, error); - await repoUtils.updateStatus(repoConfig, "error", error); - return res.status(500).json({ error }); - } - try { - await githubUtils.downloadRepoAndAnonymize(data); - await repoUtils.updateStatus(repoConfig, "ready"); - } catch (error) { - console.error(req.path, error); - await repoUtils.updateStatus(repoConfig, "error", "unable_to_anonymize"); - } -}); - -module.exports = router; diff --git a/routes/user.js b/routes/user.js deleted file mode 100644 index 94fd7cb..0000000 --- a/routes/user.js +++ /dev/null @@ -1,134 +0,0 @@ -const express = require("express"); -const { Octokit } = require("@octokit/rest"); - -const connection = require("./connection"); -const db = require("../utils/database"); -const repoUtils = require("../utils/repository"); - -const router = express.Router(); - -// user needs to be connected for all user API -router.use(connection.ensureAuthenticated); - -router.get("/logout", async (req, res) => { - try { - req.logout(); - res.redirect("/"); - } catch (error) { - console.error(req.path, error); - res.status(500).json({ error }); - } -}); - -router.get("/", async (req, res) => { - try { - const photo = req.user.profile.photos.length - ? req.user.profile.photos[0].value - : null; - res.json({ username: req.user.profile.username, photo }); - } catch (error) { - console.error(req.path, error); - res.status(500).json({ error }); - } -}); - -router.get("/default", async (req, res) => { - try { - const d = await db - .get("users") - .findOne({ username: req.user.username }, { projection: { default: 1 } }); - res.json(d.default); - } catch (error) { - console.error(req.path, error); - res.status(500).json({ error }); - } -}); - -router.post("/default", async (req, res) => { - try { - const d = req.body; - await db - .get("users") - .updateOne({ username: req.user.username }, { $set: { default: d } }); - res.send("ok"); - } catch (error) { - console.error(req.path, error); - res.status(500).json({ error }); - } -}); - -router.get("/anonymized_repositories", async (req, res) => { - try { - const repos = await db - .get("anonymized_repositories") - .find( - { - owner: req.user.username, - }, - { projection: { token: 0, files: 0, originalFiles: 0 } } - ) - .toArray(); - for (let repo of repos) { - if (repo.options.expirationDate) { - repo.options.expirationDate = new Date(repo.options.expirationDate); - } - if ( - repo.options.expirationMode != "never" && - repo.options.expirationDate != null && - repo.options.expirationDate < new Date() - ) { - await repoUtils.updateStatus({ repoId: repo.repoId }, "expired"); - repo.status = "expired"; - } - } - res.json(repos); - } catch (error) { - console.error(req.path, error); - res.status(500).json({ error }); - } -}); - -router.get("/all_repositories", async (req, res) => { - try { - const user = await db - .get() - .collection("users") - .findOne( - { username: req.user.username }, - { projection: { repositories: 1 } } - ); - if (!user) { - res.status(401).send({ error: "user_not_found" }); - } - if (user.repositories && req.query.force !== "1") { - return res.json(user.repositories); - } else { - const octokit = new Octokit({ auth: req.user.accessToken }); - const repositories = await octokit.paginate( - octokit.repos.listForAuthenticatedUser, - { - visibility: "all", - sort: "pushed", - per_page: 100, - } - ); - try { - await db - .get() - .collection("users") - .updateOne( - { username: req.user.profile.username }, - { $set: { repositories } } - ); - res.json(repositories); - } catch (error) { - res.status(500).send(error); - } - } - } catch (error) { - console.error(req.path, error); - res.status(500).json({ error }); - } -}); - -module.exports = router; diff --git a/routes/webview.js b/routes/webview.js deleted file mode 100644 index 221c9e7..0000000 --- a/routes/webview.js +++ /dev/null @@ -1,79 +0,0 @@ -const express = require("express"); -const path = require("path"); - -const fileUtils = require("../utils/file"); -const repoUtils = require("../utils/repository"); - -const router = express.Router(); - -async function webView(req, res) { - try { - const repoId = req.params.repoId; - const repoConfig = await repoUtils.getConfig(repoId); - - if (!repoConfig.options.page) { - throw "page_not_activated"; - } - if (!repoConfig.options.pageSource) { - throw "page_not_activated"; - } - - if (repoConfig.status == "expired") { - throw "repository_expired"; - } - if (repoConfig.status == "removed") { - throw "repository_expired"; - } - - if (repoConfig.options.pageSource.branch != repoConfig.branch) { - throw "page_not_supported_on_different_branch"; - } - - let requestPath = req.path.substring( - req.path.indexOf(repoId) + repoId.length - ); - if (requestPath[requestPath.length - 1] == "/") { - requestPath = path.join(requestPath, "index.html"); - } - // TODO: handle website that are not in the docs folder (master, docs, gh-pages) - requestPath = path.join(repoConfig.options.pageSource.path, requestPath); - - if (await fileUtils.isFilePathValid({ repoConfig, path: requestPath })) { - const ppath = path.join( - repoUtils.getAnonymizedPath(repoConfig.repoId), - requestPath - ); - return res.sendFile(ppath, { dotfiles: "allow" }, (err) => { - if (err) { - if (err.path) { - const newPath = path.join( - req.path, - err.path.replace( - path.join( - repoUtils.getAnonymizedPath(repoConfig.repoId), - "docs" - ), - "" - ) - ); - if (newPath != req.path) { - return res.redirect(newPath); - } - } - } - console.log(err); - }); - } - } catch (error) { - console.error(req.path, error); - return res.status(500).send({ error }); - } - return res.status(404).send("file_not_found"); -} - -router.get("/:repoId/*", webView); -router.get("/:repoId", (req, res) => { - res.redirect("/w" + req.url + "/") -}); - -module.exports = router; diff --git a/src/AnonymizedFile.ts b/src/AnonymizedFile.ts new file mode 100644 index 0000000..4bb3dd6 --- /dev/null +++ b/src/AnonymizedFile.ts @@ -0,0 +1,180 @@ +import * as path from "path"; +import * as express from "express"; +import * as stream from "stream"; +import Repository from "./Repository"; +import { Tree, TreeElement, TreeFile } from "./types"; +import storage from "./storage"; +import config from "../config"; +import { anonymizePath, anonymizeStream } from "./anonymize-utils"; + +function tree2sha( + tree: any, + output: { [key: string]: string } = {}, + parent: string = "" +): { [key: string]: string } { + for (let i in tree) { + const sha = tree[i].sha as string; + const size = tree[i].size as number; + if (sha != null && size != null) { + output[sha] = path.join(parent, i); + } else if (tree[i].child) { + tree2sha(tree[i].child as Tree, output, path.join(parent, i)); + } else { + tree2sha(tree[i] as Tree, output, path.join(parent, i)); + } + } + return output; +} + +/** + * Represent a file in a anonymized repository + */ +export default class AnonymizedFile { + private _originalPath: string; + private fileSize?: number; + + repository: Repository; + anonymizedPath: string; + sha?: string; + + constructor(data: { repository: Repository; anonymizedPath: string }) { + this.repository = data.repository; + if (!this.repository.options.terms) throw new Error("terms_not_specified"); + this.anonymizedPath = data.anonymizedPath; + } + + /** + * De-anonymize the path + * + * @returns the origin relative path of the file + */ + async originalPath(): Promise { + // console.log(new Error().stack); + if (this._originalPath) return this._originalPath; + if (!this.anonymizedPath) throw new Error("path_not_specified"); + + const paths = this.anonymizedPath.trim().split("/"); + + let currentAnonymized: TreeElement = await this.repository.anonymizedFiles({ + includeSha: true, + }); + let currentOriginal: TreeElement = await this.repository.files(); + let currentOriginalPath = ""; + let isAmbiguous = false; + for (let i = 0; i < paths.length; i++) { + const fileName = paths[i]; + if (fileName == "") { + continue; + } + if (!currentAnonymized[fileName]) { + throw new Error("file_not_found"); + } + currentAnonymized = currentAnonymized[fileName]; + + if (!isAmbiguous && !currentOriginal[fileName]) { + // anonymize all the file in the folder and check if there is one that match the current filename + const options = []; + for (let originalFileName in currentOriginal) { + if ( + anonymizePath(originalFileName, this.repository.options.terms) == + fileName + ) { + options.push(originalFileName); + } + } + + // if only one option we found the original filename + if (options.length == 1) { + currentOriginalPath = path.join(currentOriginalPath, options[0]); + currentOriginal = currentOriginal[options[0]]; + } else { + isAmbiguous = true; + } + } else if (!isAmbiguous) { + currentOriginalPath = path.join(currentOriginalPath, fileName); + currentOriginal = currentOriginal[fileName]; + } + } + + if ( + currentAnonymized.sha === undefined || + currentAnonymized.size === undefined + ) { + throw new Error("folder_not_supported"); + } + + const file: TreeFile = currentAnonymized as TreeFile; + this.fileSize = file.size; + this.sha = file.sha; + + if (isAmbiguous) { + // it should never happen + const shaTree = tree2sha(currentOriginal); + if (!currentAnonymized.sha || !shaTree[file.sha]) { + throw new Error("file_not_found"); + } + + this._originalPath = path.join(currentOriginalPath, shaTree[file.sha]); + } else { + this._originalPath = currentOriginalPath; + } + + return this._originalPath; + } + + async isFileSupported() { + const filename = path.basename(await this.originalPath()); + const extensions = filename.split(".").reverse(); + const extension = extensions[0].toLowerCase(); + if (!this.repository.options.pdf && extension == "pdf") { + return false; + } + if ( + !this.repository.options.image && + (extension == "png" || + extension == "ico" || + extension == "jpg" || + extension == "jpeg" || + extension == "gif") + ) { + return false; + } + return true; + } + + async content(): Promise { + if (this.fileSize && this.fileSize > config.MAX_FILE_SIZE) { + throw new Error("file_too_big"); + } + if (await storage.exists(this.originalCachePath)) { + return storage.read(this.originalCachePath); + } else { + return await this.repository.source?.getFileContent(this); + } + } + + async anonymizedContent() { + await this.originalPath(); + const rs = await this.content(); + return rs.pipe(anonymizeStream(await this.originalPath(), this.repository)); + } + + get originalCachePath() { + if (!this.originalPath) throw new Error("path_not_defined"); + return path.join(this.repository.originalCachePath, this._originalPath); + } + + async send(res: express.Response): Promise { + try { + const s = await this.anonymizedContent(); + s.on("error", (err) => { + console.log(err); + res.status(500).send({ error: err.message }); + }); + s.pipe(res); + } catch (error) { + console.log("Error during anonymization", error); + res.status(500).send({ error: error.message }); + } + } +} diff --git a/src/Repository.ts b/src/Repository.ts new file mode 100644 index 0000000..e019c16 --- /dev/null +++ b/src/Repository.ts @@ -0,0 +1,285 @@ +import * as path from "path"; +import storage from "./storage"; +import { RepositoryStatus, Source, Tree, TreeElement, TreeFile } from "./types"; +import * as stream from "stream"; +import User from "./User"; +import GitHubStream from "./source/GitHubStream"; +import GitHubDownload from "./source/GitHubDownload"; +import Zip from "./source/Zip"; +import { anonymizePath } from "./anonymize-utils"; +import UserModel from "./database/users/users.model"; +import { IAnonymizedRepositoryDocument } from "./database/anonymizedRepositories/anonymizedRepositories.types"; +import { anonymizeStream } from "./anonymize-utils"; +import GitHubBase from "./source/GitHubBase"; + +export default class Repository { + private _model: IAnonymizedRepositoryDocument; + source: Source; + owner: User; + + constructor(data: IAnonymizedRepositoryDocument) { + this._model = data; + switch (data.source.type) { + case "GitHubDownload": + this.source = new GitHubDownload(data.source, this); + break; + case "GitHubStream": + this.source = new GitHubStream(data.source, this); + break; + case "Zip": + this.source = new Zip(data.source, this); + break; + default: + throw new Error("unsupported_source"); + } + this.owner = new User(new UserModel({ username: data.owner })); + } + + /** + * Get the anonymized file tree + * @param opt force to get an updated list of files + * @returns The anonymized file tree + */ + async anonymizedFiles(opt?: { + /** Force to refresh the file tree */ + force?: boolean; + /** Include the file sha in the response */ + includeSha: boolean; + }): Promise { + const terms = this._model.options.terms || []; + + function anonymizeTreeRecursive(tree: TreeElement): TreeElement { + if (Number.isInteger(tree.size) && tree.sha !== undefined) { + if (opt?.includeSha) return tree as TreeFile; + return { size: tree.size } as TreeFile; + } + const output: Tree = {}; + for (const file in tree) { + const anonymizedPath = anonymizePath(file, terms); + output[anonymizedPath] = anonymizeTreeRecursive(tree[file]); + } + return output; + } + + return anonymizeTreeRecursive(await this.files(opt)) as Tree; + } + + /** + * Get the file tree + * + * @param opt force to get an updated list of files + * @returns The file tree + */ + async files(opt?: { force?: boolean }) { + if ( + this._model.originalFiles && + Object.keys(this._model.originalFiles).length !== 0 && + !opt?.force + ) { + return this._model.originalFiles; + } + const files = await this.source.getFiles(); + this._model.originalFiles = files; + this._model.size = 0; + await this._model.save(); + + this._model.originalFiles = files; + return files; + } + + /** + * Check the status of the repository + */ + check() { + if (this._model.options.expirationMode != "never") { + if (this._model.options.expirationDate > new Date()) { + this.updateStatus("expired"); + } + } + if (this._model.status == "expired") { + throw new Error("repository_expired"); + } + if (this._model.status == "removed") { + throw new Error("repository_expired"); + } + if (this._model.status != "ready") { + throw new Error("repository_not_ready"); + } + } + + /** + * Compress and anonymize the repository + * + * @returns A stream of anonymized repository compressed + */ + zip(): stream.Readable { + return storage.archive(this.originalCachePath, { + format: "zip", + fileTransformer: (filename) => + anonymizeStream(filename, this) as Transformer, + }); + } + + /** + * Update the repository if a new commit exists + * + * @returns void + */ + async updateIfNeeded(): Promise { + const yesterday = new Date(); + yesterday.setDate(yesterday.getDate() - 1); + + if (this._model.options.update && this._model.lastView < yesterday) { + if (this._model.status != "ready") { + throw new Error("repo_not_ready"); + } + + // Only GitHubBase can be update for the moment + if (this.source instanceof GitHubBase) { + const branches = await this.source.githubRepository.branches({ + force: true, + accessToken: await this.source.getToken(), + }); + const branch = this.source.branch; + if ( + branch.commit == + branches.filter((f) => f.name == branch.name)[0].commit + ) { + console.log(`${this._model.repoId} is up to date`); + return; + } + this._model.source.commit = branches.filter( + (f) => f.name == branch.name + )[0].commit; + this._model.anonymizeDate = new Date(); + await this.updateStatus("preparing"); + console.log( + `${this._model.repoId} will be updated to ${this._model.source.commit}` + ); + await this.resetSate(); + await this.anonymize(); + } + } + } + + /** + * Download the require state for the repository to work + * + * @returns void + */ + async anonymize() { + if (this._model.status == "ready") return; + await this.updateStatus("preparing"); + await this.files(); + await this.updateStatus("ready"); + } + + /** + * Update the last view and view count + */ + async countView() { + this._model.lastView = new Date(); + this._model.pageView = (this._model.pageView || 0) + 1; + await this._model.save(); + } + + /** + * Update the status of the repository + * @param status the new status + * @param errorMessage a potential error message to display + */ + async updateStatus(status: RepositoryStatus, errorMessage?: string) { + this._model.status = status; + this._model.errorMessage = errorMessage; + this._model.status = status; + await this._model.save(); + } + + /** + * Expire the repository + */ + async expire() { + await this.updateStatus("expired"); + await this.resetSate(); + } + + /** + * Remove the repository + */ + async remove() { + await this.updateStatus("removed"); + await this.resetSate(); + } + + /** + * Reset/delete the state of the repository + */ + private async resetSate() { + this._model.size = 0; + this._model.originalFiles = null; + await this._model.save(); + await storage.rm(this._model.repoId + "/"); + } + + /** + * Compute the size of the repository in bite. + * + * @returns The size of the repository in bite + */ + async computeSize(): Promise { + if (this._model.status != "ready") return 0; + if (this._model.size) return this._model.size; + function recursiveCount(files) { + let total = 0; + for (const name in files) { + const file = files[name]; + if (file.size) { + total += file.size as number; + } else if (typeof file == "object") { + total += recursiveCount(file); + } + } + return total; + } + + const files = await this.files({ force: false }); + this._model.size = recursiveCount(files); + await this._model.save(); + return this._model.size; + } + + /***** Getters ********/ + + get repoId() { + return this._model.repoId; + } + + get options() { + return this._model.options; + } + + get model() { + return this._model; + } + + get originalCachePath() { + return path.join(this._model.repoId, "original") + "/"; + } + + get status() { + return this._model.status; + } + + toJSON() { + return { + repoId: this._model.repoId, + options: this._model.options, + anonymizeDate: this._model.anonymizeDate, + status: this._model.status, + source: this.source.toJSON(), + lastView: this._model.lastView, + pageView: this._model.pageView, + size: this._model.size, + }; + } +} diff --git a/src/User.ts b/src/User.ts new file mode 100644 index 0000000..357b012 --- /dev/null +++ b/src/User.ts @@ -0,0 +1,138 @@ +import { Octokit } from "@octokit/rest"; +import AnonymizedRepositoryModel from "./database/anonymizedRepositories/anonymizedRepositories.model"; +import RepositoryModel from "./database/repositories/repositories.model"; +import { IUserDocument } from "./database/users/users.types"; +import Repository from "./Repository"; +import { GitHubRepository } from "./source/GitHubRepository"; + +/** + * Model for a user + */ +export default class User { + private _model: IUserDocument; + constructor(model: IUserDocument) { + this._model = model; + } + + get username(): string { + return this._model.username; + } + + get accessToken(): string { + return this._model.accessToken; + } + + get photo(): string { + return this._model.photo; + } + + get default() { + return this._model.default; + } + + set default(d) { + this._model.default = d; + } + + /** + * Get the GitHub repositories of the user + * @param opt options + * @returns the list of github repositories + */ + async getGitHubRepositories(opt?: { + /** + * Get the repository from GitHub + */ + force: boolean; + }): Promise { + if ( + !this._model.repositories || + this._model.repositories.length == 0 || + opt?.force === true + ) { + // get the list of repo from github + const octokit = new Octokit({ auth: this.accessToken }); + const repositories = ( + await octokit.paginate(octokit.repos.listForAuthenticatedUser, { + visibility: "all", + sort: "pushed", + per_page: 100, + }) + ).map((r) => { + return new RepositoryModel({ + externalId: "gh_" + r.id, + name: r.full_name, + url: r.html_url, + size: r.size, + defaultBranch: r.default_branch, + }); + }); + + // find the repositories that are already in the database + const finds = ( + await RepositoryModel.find({ + externalId: { + $in: repositories.map((repo) => repo.externalId), + }, + }).select("externalId") + ).map((m) => m.externalId); + + // save all the new repositories + await Promise.all( + repositories + .filter((r) => finds.indexOf(r.externalId) == -1) + .map((r) => r.save()) + ); + + // save only the if of the repositories in the user model + this._model.repositories = ( + await RepositoryModel.find({ + externalId: { + $in: repositories.map((repo) => repo.externalId), + }, + }).select("id") + ).map((m) => m.id); + + // have the model + await this._model.save(); + return repositories.map((r) => new GitHubRepository(r)); + } else { + return ( + await RepositoryModel.find({ _id: { $in: this._model.repositories } }) + ).map((i) => new GitHubRepository(i)); + } + } + + /** + * Get the lost of anonymized repositories + * @returns the list of anonymized repositories + */ + async getRepositories() { + const repositories = ( + await AnonymizedRepositoryModel.find({ + owner: this.username, + }).exec() + ).map((d) => new Repository(d)); + const promises = []; + for (let repo of repositories) { + if ( + repo.options.expirationMode != "never" && + repo.options.expirationDate != null && + repo.options.expirationDate < new Date() + ) { + // expire the repository + promises.push(repo.expire()); + } + } + await Promise.all(promises); + return repositories; + } + + get model() { + return this._model; + } + + toJSON() { + return this._model.toJSON(); + } +} diff --git a/src/anonymize-utils.ts b/src/anonymize-utils.ts new file mode 100644 index 0000000..ec55309 --- /dev/null +++ b/src/anonymize-utils.ts @@ -0,0 +1,142 @@ +import config from "../config"; +import Repository from "./Repository"; +import GitHubBase from "./source/GitHubBase"; +import { isText } from "istextorbinary"; +import * as path from "path"; + +import * as stream from "stream"; + +const urlRegex = + /?/g; + +export function isTextFile(filePath, content) { + const filename = path.basename(filePath); + const extensions = filename.split(".").reverse(); + const extension = extensions[0].toLowerCase(); + if (config.additionalExtensions.includes(extension)) { + return true; + } + if (isText(filename)) { + return true; + } + return isText(filename, content); +} + +export function anonymizeStream(filename: string, repository: Repository) { + const ts = new stream.Transform(); + var chunks = [], + len = 0, + pos = 0; + + ts._transform = function _transform(chunk, enc, cb) { + chunks.push(chunk); + len += chunk.length; + + if (pos === 1) { + let data: any = Buffer.concat(chunks, len); + if (isTextFile(filename, data)) { + data = anonymizeContent(data.toString(), repository); + } + + chunks = []; + len = 0; + + this.push(data); + } + + pos = 1 ^ pos; + cb(null); + }; + + ts._flush = function _flush(cb) { + if (chunks.length) { + let data: any = Buffer.concat(chunks, len); + if (isText(filename, data)) { + data = anonymizeContent(data.toString(), repository); + } + + this.push(data); + } + + cb(null); + }; + return ts; +} + +export function anonymizeContent(content: string, repository: Repository) { + if (repository.options?.image === false) { + // remove image in markdown + content = content.replace( + /!\[[^\]]*\]\((?.*?)(?=\"|\))(?\".*\")?\)/g, + "" + ); + } + + if (!repository.options?.link) { + // remove all links + content = content.replace(urlRegex, config.ANONYMIZATION_MASK); + } + + if (repository.source instanceof GitHubBase) { + content = content.replace( + new RegExp( + `https://github.com/${ + repository.source.githubRepository.fullName + }/blob/${repository.source.branch?.name || "HEAD"}\\b`, + "gi" + ), + `https://${config.HOSTNAME}/r/${repository.repoId}` + ); + content = content.replace( + new RegExp( + `https://github.com/${ + repository.source.githubRepository.fullName + }/tree/${(repository.source as GitHubBase).branch?.name || "HEAD"}\\b`, + "gi" + ), + `https://${config.HOSTNAME}/r/${repository.repoId}` + ); + content = content.replace( + new RegExp( + `https://github.com/${repository.source.githubRepository.fullName}`, + "gi" + ), + `https://${config.HOSTNAME}/r/${repository.repoId}` + ); + } + + const terms = repository.options.terms || []; + for (let i = 0; i < terms.length; i++) { + const term = terms[i]; + if (term.trim() == "") { + continue; + } + // remove whole url if it contains the term + content = content.replace(urlRegex, (match) => { + if (new RegExp(`\\b${term}\\b`, "gi").test(match)) + return config.ANONYMIZATION_MASK + "-" + (i + 1); + return match; + }); + + // remove the term in the text + content = content.replace( + new RegExp(`\\b${term}\\b`, "gi"), + config.ANONYMIZATION_MASK + "-" + (i + 1) + ); + } + return content; +} + +export function anonymizePath(path: string, terms: string[]) { + for (let i = 0; i < terms.length; i++) { + const term = terms[i]; + if (term.trim() == "") { + continue; + } + path = path.replace( + new RegExp(term, "gi"), + config.ANONYMIZATION_MASK + "-" + (i + 1) + ); + } + return path; +} diff --git a/src/database/anonymizedRepositories/anonymizedRepositories.model.ts b/src/database/anonymizedRepositories/anonymizedRepositories.model.ts new file mode 100644 index 0000000..9d29ffd --- /dev/null +++ b/src/database/anonymizedRepositories/anonymizedRepositories.model.ts @@ -0,0 +1,15 @@ +import * as mongoose from "mongoose"; +const { model } = mongoose; + +import { + IAnonymizedRepositoryDocument, + IAnonymizedRepositoryModel, +} from "./anonymizedRepositories.types"; +import AnonymizedRepositorySchema from "./anonymizedRepositories.schema"; + +const AnonymizedRepositoryModel = model( + "AnonymizedRepository", + AnonymizedRepositorySchema +) as IAnonymizedRepositoryModel; + +export default AnonymizedRepositoryModel; diff --git a/src/database/anonymizedRepositories/anonymizedRepositories.schema.ts b/src/database/anonymizedRepositories/anonymizedRepositories.schema.ts new file mode 100644 index 0000000..2249fb8 --- /dev/null +++ b/src/database/anonymizedRepositories/anonymizedRepositories.schema.ts @@ -0,0 +1,54 @@ +import * as mongoose from "mongoose"; +const { Schema } = mongoose; + +const AnonymizedRepositorySchema = new Schema({ + repoId: { + type: String, + index: { unique: true }, + }, + status: { + type: String, + default: "preparing", + }, + errorMessage: String, + anonymizeDate: Date, + lastView: Date, + pageView: Number, + accessToken: String, + owner: String, + conference: String, + source: { + type: { type: String }, + branch: String, + commit: String, + repositoryId: String, + repositoryName: String, + accessToken: String, + }, + originalFiles: mongoose.Schema.Types.Mixed, + options: { + terms: [String], + expirationMode: { type: String }, + expirationDate: Date, + update: Boolean, + image: Boolean, + pdf: Boolean, + notebook: Boolean, + link: Boolean, + page: Boolean, + pageSource: { + branch: String, + path: String, + }, + }, + dateOfEntry: { + type: Date, + default: new Date(), + }, + size: { + type: Number, + default: 0, + }, +}); + +export default AnonymizedRepositorySchema; diff --git a/src/database/anonymizedRepositories/anonymizedRepositories.types.ts b/src/database/anonymizedRepositories/anonymizedRepositories.types.ts new file mode 100644 index 0000000..9953fb0 --- /dev/null +++ b/src/database/anonymizedRepositories/anonymizedRepositories.types.ts @@ -0,0 +1,46 @@ +import * as mongoose from "mongoose"; +import { RepositoryStatus, Tree } from "../../types"; + +export interface IAnonymizedRepository { + repoId: string; + status?: RepositoryStatus; + errorMessage?: string; + anonymizeDate: Date; + source: { + type: "GitHubDownload" | "GitHubStream" | "Zip"; + branch?: string; + commit?: string; + repositoryId?: string; + repositoryName?: string; + accessToken?: string; + }; + owner: string; + originalFiles: Tree; + conference: string; + options: { + terms: string[]; + expirationMode: "never" | "redirect" | "remove"; + expirationDate?: Date; + update: boolean; + image: boolean; + pdf: boolean; + notebook: boolean; + link: boolean; + page: boolean; + pageSource?: { + branch: string; + path: string; + }; + }; + pageView: number; + lastView: Date; + size: number; +} + +export interface IAnonymizedRepositoryDocument + extends IAnonymizedRepository, + mongoose.Document { + setLastUpdated: (this: IAnonymizedRepositoryDocument) => Promise; +} +export interface IAnonymizedRepositoryModel + extends mongoose.Model {} diff --git a/src/database/database.ts b/src/database/database.ts new file mode 100644 index 0000000..783aa35 --- /dev/null +++ b/src/database/database.ts @@ -0,0 +1,28 @@ +import * as mongoose from "mongoose"; +import Repository from "../Repository"; +import config from "../../config"; +import AnonymizedRepositoryModel from "./anonymizedRepositories/anonymizedRepositories.model"; + +const MONGO_URL = `mongodb://${config.DB_USERNAME}:${config.DB_PASSWORD}@${config.DB_HOSTNAME}:27017/`; + +export const database = mongoose.connection; + +export async function connect() { + mongoose.set("useNewUrlParser", true); + mongoose.set("useFindAndModify", true); + mongoose.set("useUnifiedTopology", true); + + await mongoose.connect(MONGO_URL + "test", { + authSource: "admin", + useCreateIndex: true, + useFindAndModify: true, + }); + + return database; +} + +export async function getRepository(repoId: string) { + const data = await AnonymizedRepositoryModel.findOne({ repoId }); + if (!data) throw new Error("repo_not_found"); + return new Repository(data); +} diff --git a/src/database/repositories/repositories.model.ts b/src/database/repositories/repositories.model.ts new file mode 100644 index 0000000..f5a5ab3 --- /dev/null +++ b/src/database/repositories/repositories.model.ts @@ -0,0 +1,12 @@ +import * as mongoose from "mongoose"; +const { model } = mongoose; + +import { IRepositoryDocument, IRepositoryModel } from "./repositories.types"; +import RepositorySchema from "./repositories.schema"; + +const RepositoryModel = model( + "Repository", + RepositorySchema +) as IRepositoryModel; + +export default RepositoryModel; diff --git a/src/database/repositories/repositories.schema.ts b/src/database/repositories/repositories.schema.ts new file mode 100644 index 0000000..7261669 --- /dev/null +++ b/src/database/repositories/repositories.schema.ts @@ -0,0 +1,42 @@ +import * as mongoose from "mongoose"; +const { Schema } = mongoose; + +const RepositorySchema = new Schema({ + externalId: { + type: String, + index: { unique: true }, + }, + name: { + type: String, + index: true, + }, + url: String, + source: { + type: String, + default: "github", + }, + hasPage: { type: Boolean, default: false }, + pageSource: { + branch: { type: String }, + path: String, + }, + branches: [ + { + name: { type: String }, + commit: String, + readme: String, + }, + ], + defaultBranch: String, + size: Number, + status: { + type: String, + default: "ready", + }, + dateOfEntry: { + type: Date, + default: new Date(), + }, +}); + +export default RepositorySchema; diff --git a/src/database/repositories/repositories.types.ts b/src/database/repositories/repositories.types.ts new file mode 100644 index 0000000..4c012c6 --- /dev/null +++ b/src/database/repositories/repositories.types.ts @@ -0,0 +1,25 @@ +import * as mongoose from "mongoose"; + +export interface IRepository { + externalId: string; + name: string; + url?: string; + source: "github"; + size?: number; + defaultBranch?: string; + hasPage: boolean; + pageSource?: { + branch: string; + path: string; + }; + branches?: { + name: string; + commit: string; + readme?: string; + }[]; +} + +export interface IRepositoryDocument extends IRepository, mongoose.Document { + setLastUpdated: (this: IRepositoryDocument) => Promise; +} +export interface IRepositoryModel extends mongoose.Model {} diff --git a/src/database/users/users.model.ts b/src/database/users/users.model.ts new file mode 100644 index 0000000..4677b43 --- /dev/null +++ b/src/database/users/users.model.ts @@ -0,0 +1,10 @@ +import * as mongoose from "mongoose"; +const { model } = mongoose; + +import { IUserDocument, IUserModel } from "./users.types"; +import UserSchema from "./users.schema"; + +const UserModel = model("user", UserSchema) as IUserModel; + +export default UserModel + diff --git a/src/database/users/users.schema.ts b/src/database/users/users.schema.ts new file mode 100644 index 0000000..860eeb8 --- /dev/null +++ b/src/database/users/users.schema.ts @@ -0,0 +1,35 @@ +import * as mongoose from "mongoose"; +const { Schema } = mongoose; + +const UserSchema = new Schema({ + accessToken: String, + username: { + type: String, + index: { unique: true }, + }, + email: String, + photo: String, + repositories: [String], + default: { + terms: [String], + options: { + expirationMode: { type: String }, + update: Boolean, + image: Boolean, + pdf: Boolean, + notebook: Boolean, + link: Boolean, + page: { type: String }, + }, + }, + status: { + type: String, + default: "active", + }, + dateOfEntry: { + type: Date, + default: new Date(), + }, +}); + +export default UserSchema; diff --git a/src/database/users/users.types.ts b/src/database/users/users.types.ts new file mode 100644 index 0000000..c649107 --- /dev/null +++ b/src/database/users/users.types.ts @@ -0,0 +1,31 @@ +import * as mongoose from "mongoose"; + +export interface IUser { + accessToken: string; + + username: string; + email: string; + photo?: string; + + repositories?: number[]; + default?: { + terms: string[]; + options: { + expirationMode: "never" | "redirect" | ""; + update: boolean; + image: boolean; + pdf: boolean; + notebook: boolean; + link: boolean; + page: string | null; + }; + }; + status?: "active" | "removed"; + dateOfEntry?: Date; + lastUpdated?: Date; +} + +export interface IUserDocument extends IUser, mongoose.Document { + setLastUpdated: (this: IUserDocument) => Promise; +} +export interface IUserModel extends mongoose.Model {} diff --git a/src/routes/connection.ts b/src/routes/connection.ts new file mode 100644 index 0000000..dabc067 --- /dev/null +++ b/src/routes/connection.ts @@ -0,0 +1,107 @@ +import * as redis from "redis"; +import * as passport from "passport"; +import * as session from "express-session"; +import * as connectRedis from "connect-redis"; +import * as OAuth2Strategy from "passport-oauth2"; +import { Profile, Strategy } from "passport-github2"; +import * as express from "express"; + +import config from "../../config"; +import UserModel from "../database/users/users.model"; + +const RedisStore = connectRedis(session); + +export function ensureAuthenticated( + req: express.Request, + res: express.Response, + next: express.NextFunction +) { + if (req.isAuthenticated()) { + return next(); + } + res.status(401).json({ error: "not_connected" }); +} + +const verify = async ( + accessToken: string, + refreshToken: string, + profile: Profile, + done: OAuth2Strategy.VerifyCallback +): Promise => { + let user; + try { + user = await UserModel.findOne({ username: profile.username }); + if (user) { + user.accessToken = accessToken; + user.email = profile.emails[0]?.value; + user.photo = profile.photos[0]?.value; + await user.save(); + } else { + user = await new UserModel({ + username: profile.username, + accessToken: accessToken, + email: profile.emails[0]?.value, + photo: profile.photos[0]?.value, + }).save(); + } + } catch (error) { + console.error(error); + } finally { + done(null, { + username: profile.username, + accessToken, + refreshToken, + profile, + user, + }); + } +}; + +passport.use( + new Strategy( + { + clientID: config.CLIENT_ID, + clientSecret: config.CLIENT_SECRET, + callbackURL: config.AUTH_CALLBACK, + }, + verify + ) +); + +passport.serializeUser((user: Express.User, done) => { + done(null, user); +}); + +passport.deserializeUser((user: Express.User, done) => { + done(null, user); +}); + +export const appSession = session({ + secret: "keyboard cat", + store: new RedisStore({ + client: redis.createClient({ + port: config.REDIS_PORT, + host: config.REDIS_HOSTNAME, + }), + }), + saveUninitialized: false, + resave: false, +}); + +export const router = express.Router(); + +router.get( + "/login", + passport.authenticate("github", { scope: ["repo"] }), // Note the scope here + function (req: express.Request, res: express.Response) { + res.redirect("/"); + } +); + +router.get( + "/auth", + passport.authenticate("github", { failureRedirect: "/" }), + function (req: express.Request, res: express.Response) { + res.redirect("/"); + } +); diff --git a/src/routes/file.ts b/src/routes/file.ts new file mode 100644 index 0000000..ed63eb4 --- /dev/null +++ b/src/routes/file.ts @@ -0,0 +1,41 @@ +import * as express from "express"; +import AnonymizedFile from "../AnonymizedFile"; +import { getRepo, handleError } from "./route-utils"; + +export const router = express.Router(); + +router.get( + "/:repoId/file/:path*", + async (req: express.Request, res: express.Response) => { + let anonymizedPath = req.params.path; + if (req.params[0]) { + anonymizedPath += req.params[0]; + } + anonymizedPath = anonymizedPath; + + const repo = await getRepo(req, res); + if (!repo) return; + + try { + await repo.countView(); + + const f = new AnonymizedFile({ + repository: repo, + anonymizedPath, + }); + if (!(await f.isFileSupported())) { + return res.status(500).send({ error: "file_not_supported" }); + } + res.attachment( + anonymizedPath.substring(anonymizedPath.lastIndexOf("/") + 1) + ); + // ache the file for 6 hours + res.header('Cache-Control', 'max-age=21600000'); + await f.send(res); + } catch (error) { + return handleError(error, res); + } + } +); + +export default router; diff --git a/src/routes/index.ts b/src/routes/index.ts new file mode 100644 index 0000000..f8b553a --- /dev/null +++ b/src/routes/index.ts @@ -0,0 +1,13 @@ +import repositoryPrivate from "./repository-private"; +import repositoryPublic from "./repository-public"; +import file from "./file"; +import webview from "./webview"; +import user from "./user"; + +export default { + repositoryPrivate, + repositoryPublic, + file, + webview, + user, +}; diff --git a/src/routes/repository-private.ts b/src/routes/repository-private.ts new file mode 100644 index 0000000..6e05113 --- /dev/null +++ b/src/routes/repository-private.ts @@ -0,0 +1,301 @@ +import * as express from "express"; +import { ensureAuthenticated } from "./connection"; + +import * as db from "../database/database"; +import { getRepo, getUser, handleError } from "./route-utils"; +import { getRepositoryFromGitHub } from "../source/GitHubRepository"; +import gh = require("parse-github-url"); +import GitHubBase from "../source/GitHubBase"; +import AnonymizedRepositoryModel from "../database/anonymizedRepositories/anonymizedRepositories.model"; +import config from "../../config"; +import { IAnonymizedRepositoryDocument } from "../database/anonymizedRepositories/anonymizedRepositories.types"; +import Repository from "../Repository"; + +const router = express.Router(); + +// get repository information +router.get("/:repoId/", async (req: express.Request, res: express.Response) => { + const repo = await getRepo(req, res, { nocheck: true }); + if (!repo) return; + + try { + const user = await getUser(req); + if (user.username != repo.model.owner) { + return res.status(401).send({ error: "not_authorized" }); + } + res.json((await db.getRepository(req.params.repoId)).toJSON()); + } catch (error) { + handleError(error, res); + } +}); + +// user needs to be connected for all user API +router.use(ensureAuthenticated); + +// claim a repository +router.post("/claim", async (req: express.Request, res: express.Response) => { + const user = await getUser(req); + try { + if (!req.body.repoId) { + return res.status(500).json({ error: "repoId_not_defined" }); + } + if (!req.body.repoUrl) { + return res.status(500).json({ error: "repoUrl_not_defined" }); + } + + const repoConfig = await db.getRepository(req.body.repoId); + if (repoConfig == null) { + return res.status(500).json({ error: "repo_not_found" }); + } + + const r = gh(req.body.repoUrl); + const repo = await getRepositoryFromGitHub({ + owner: r.owner, + repo: r.name, + accessToken: user.accessToken, + }); + if ((repoConfig.source as GitHubBase).githubRepository.id != repo.id) { + return res.status(500).json({ error: "repo_not_found" }); + } + + console.log(`${user.username} claims ${r.repository}.`); + repoConfig.owner = user; + + await AnonymizedRepositoryModel.updateOne( + { repoId: repoConfig.repoId }, + { $set: { owner: user.username } } + ); + return res.send("Ok"); + } catch (error) { + handleError(error, res); + } +}); + +// refresh a repository +router.post( + "/:repoId/refresh", + async (req: express.Request, res: express.Response) => { + const repo = await getRepo(req, res, { nocheck: true }); + if (!repo) return; + + try { + const user = await getUser(req); + if (repo.owner.username != user.username) { + return res.status(401).json({ error: "not_authorized" }); + } + await repo.anonymize(); + res.end("ok"); + } catch (error) { + handleError(error, res); + } + } +); + +// delete a repository +router.delete( + "/:repoId/", + async (req: express.Request, res: express.Response) => { + const repo = await getRepo(req, res, { nocheck: false }); + if (!repo) return; + try { + const user = await getUser(req); + if (repo.owner.username != user.username) { + return res.status(401).json({ error: "not_authorized" }); + } + await repo.remove(); + console.log(`${req.params.repoId} is removed`); + return res.json("ok"); + } catch (error) { + handleError(error, res); + } + } +); + +router.get( + "/:owner/:repo/", + async (req: express.Request, res: express.Response) => { + const user = await getUser(req); + try { + const repo = await getRepositoryFromGitHub({ + owner: req.params.owner, + repo: req.params.repo, + accessToken: user.accessToken, + }); + res.json(repo.toJSON()); + } catch (error) { + handleError(error, res); + } + } +); + +router.get( + "/:owner/:repo/branches", + async (req: express.Request, res: express.Response) => { + const user = await getUser(req); + try { + const repository = await getRepositoryFromGitHub({ + accessToken: user.accessToken, + owner: req.params.owner, + repo: req.params.repo, + }); + return res.json( + await repository.branches({ + accessToken: user.accessToken, + force: req.query.force == "1", + }) + ); + } catch (error) { + handleError(error, res); + } + } +); + +router.get( + "/:owner/:repo/readme", + async (req: express.Request, res: express.Response) => { + try { + const user = await getUser(req); + + const repo = await getRepositoryFromGitHub({ + owner: req.params.owner, + repo: req.params.repo, + accessToken: user.accessToken, + }); + if (!repo) return res.status(404).send({ error: "repo_not_found" }); + return res.send( + await repo.readme({ + accessToken: user.accessToken, + force: req.query.force == "1", + branch: req.query.branch as string, + }) + ); + } catch (error) { + handleError(error, res); + } + } +); + +function validateNewRepo(repoUpdate) { + const validCharacters = /^[0-9a-zA-Z\-\_]+$/; + if ( + !repoUpdate.repoId.match(validCharacters) || + repoUpdate.repoId.length < 3 + ) { + throw new Error("invalid_repoId"); + } + if (!repoUpdate.branch) { + throw new Error("branch_not_specified"); + } + if (!repoUpdate.options) { + throw new Error("options_not_provided"); + } + if (!Array.isArray(repoUpdate.terms)) { + throw new Error("invalid_terms_format"); + } + if (!/^[a-f0-9]+$/.test(repoUpdate.commit)) { + throw new Error("invalid_commit_format"); + } +} + +function updateRepoModel(model: IAnonymizedRepositoryDocument, repoUpdate) { + model.source.commit = repoUpdate.commit; + model.source.branch = repoUpdate.branch; + model.conference = repoUpdate.conference; + model.options = { + terms: repoUpdate.terms, + expirationMode: repoUpdate.options.expirationMode, + expirationDate: repoUpdate.options.expirationDate + ? new Date(repoUpdate.options.expirationDate) + : null, + update: repoUpdate.options.update, + image: repoUpdate.options.image, + pdf: repoUpdate.options.pdf, + notebook: repoUpdate.options.notebook, + link: repoUpdate.options.link, + page: repoUpdate.options.page, + pageSource: repoUpdate.options.pageSource, + }; +} +// update a repository +router.post( + "/:repoId/", + async (req: express.Request, res: express.Response) => { + const repo = await getRepo(req, res, { nocheck: true }); + if (!repo) return; + const user = await getUser(req); + + if (repo.owner.username != user.username) { + return res.status(401).json({ error: "not_authorized" }); + } + + const repoUpdate = req.body; + + try { + validateNewRepo(repoUpdate); + + if (repoUpdate.commit != repo.model.source.commit) { + repo.model.anonymizeDate = new Date(); + repo.model.source.commit = repoUpdate.commit; + await repo.remove(); + } + + updateRepoModel(repo.model, repoUpdate); + + await repo.updateStatus("preparing"); + + await repo.model.save(); + res.send("ok"); + new Repository(repo.model).anonymize(); + } catch (error) { + return handleError(error, res); + } + } +); + +// add repository +router.post("/", async (req: express.Request, res: express.Response) => { + const user = await getUser(req); + const repoUpdate = req.body; + + try { + validateNewRepo(repoUpdate); + + const r = gh(repoUpdate.fullName); + const repository = await getRepositoryFromGitHub({ + accessToken: user.accessToken, + owner: r.owner, + repo: r.name, + }); + + const repo = new AnonymizedRepositoryModel(); + repo.repoId = repoUpdate.repoId; + repo.anonymizeDate = new Date(); + repo.owner = user.username; + repo.source = { + type: + repoUpdate.options.mode == "download" + ? "GitHubDownload" + : "GitHubStream", + accessToken: user.accessToken, + repositoryId: repository.model.id, + repositoryName: repoUpdate.fullName, + }; + + if (repo.source.type == "GitHubDownload") { + // details.size is in kilobytes + if (repository.size > config.MAX_REPO_SIZE) { + return res.status(500).send({ error: "invalid_mode" }); + } + } + + updateRepoModel(repo, repoUpdate); + + await repo.save(); + res.send("ok"); + new Repository(repo).anonymize(); + } catch (error) { + return handleError(error, res); + } +}); + +export default router; diff --git a/src/routes/repository-public.ts b/src/routes/repository-public.ts new file mode 100644 index 0000000..9a161e0 --- /dev/null +++ b/src/routes/repository-public.ts @@ -0,0 +1,75 @@ +import * as express from "express"; +import config from "../../config"; + +import * as db from "../database/database"; +import { getRepo, handleError } from "./route-utils"; + +const router = express.Router(); + +router.get( + "/:repoId/zip", + async (req: express.Request, res: express.Response) => { + if (!config.ENABLE_DOWNLOAD) + return res.status(403).send({ error: "download_not_enabled" }); + const repo = await getRepo(req, res); + if (!repo) return; + + try { + res.attachment(`${repo.repoId}.zip`); + + // ache the file for 6 hours + res.header('Cache-Control', 'max-age=21600000'); + + repo.zip().pipe(res); + } catch (error) { + handleError(error, res); + } + } +); + +router.get( + "/:repoId/files", + async (req: express.Request, res: express.Response) => { + const repo = await getRepo(req, res); + if (!repo) return; + try { + // ache the file for 6 hours + res.header('Cache-Control', 'max-age=21600000'); + + res.json(await repo.anonymizedFiles({ includeSha: false })); + } catch (error) { + handleError(error, res); + } + } +); + +router.get( + "/:repoId/options", + async (req: express.Request, res: express.Response) => { + try { + const repo = await getRepo(req, res, { nocheck: true }); + + let redirectURL = null; + if ( + repo.status == "expired" && + repo.options.expirationMode == "redirect" && + repo.source.url + ) { + redirectURL = repo.source.url; + } else { + repo.check(); + } + + await repo.updateIfNeeded(); + + res.json({ + url: redirectURL, + download: !!config.ENABLE_DOWNLOAD, + }); + } catch (error) { + handleError(error, res); + } + } +); + +export default router; diff --git a/src/routes/route-utils.ts b/src/routes/route-utils.ts new file mode 100644 index 0000000..41d356e --- /dev/null +++ b/src/routes/route-utils.ts @@ -0,0 +1,63 @@ +import * as express from "express"; +import * as db from "../database/database"; +import UserModel from "../database/users/users.model"; +import User from "../User"; + +export async function getRepo( + req: express.Request, + res: express.Response, + opt?: { nocheck?: boolean } +) { + try { + const repo = await db.getRepository(req.params.repoId); + if (opt?.nocheck == true) { + } else { + // redirect if the repository is expired + if ( + repo.status == "expired" && + repo.options.expirationMode == "redirect" && + repo.source.url + ) { + res.redirect(repo.source.url); + return null; + } + + repo.check(); + } + return repo; + } catch (error) { + handleError(error, res); + return null; + } +} + +export function handleError(error: any, res: express.Response) { + console.log(error); + let message = error; + if (error instanceof Error) { + message = error.message; + } + let status = 500; + if (message && message.indexOf("not_found") > -1) { + status = 400; + } else if (message && message.indexOf("not_connected") > -1) { + status = 401; + } + + res.status(status).send({ error: message }); + return; +} + +export async function getUser(req: express.Request) { + const user = (req.user as any).user; + if (!user) { + req.logout(); + throw new Error("not_connected"); + } + const model = await UserModel.findById(user._id); + if (!model) { + req.logout(); + throw new Error("not_connected"); + } + return new User(model); +} diff --git a/src/routes/user.ts b/src/routes/user.ts new file mode 100644 index 0000000..43ad669 --- /dev/null +++ b/src/routes/user.ts @@ -0,0 +1,108 @@ +import * as express from "express"; +import config from "../../config"; +import { ensureAuthenticated } from "./connection"; +import { handleError, getUser } from "./route-utils"; + +const router = express.Router(); + +// user needs to be connected for all user API +router.use(ensureAuthenticated); + +router.get("/logout", async (req: express.Request, res: express.Response) => { + try { + req.logout(); + res.redirect("/"); + } catch (error) { + handleError(error, res); + } +}); + +router.get("/", async (req: express.Request, res: express.Response) => { + try { + const user = await getUser(req); + res.json({ username: user.username, photo: user.photo }); + } catch (error) { + handleError(error, res); + } +}); + +router.get("/quota", async (req: express.Request, res: express.Response) => { + try { + const user = await getUser(req); + const sizes = await Promise.all( + (await user.getRepositories()) + .filter((r) => r.status == "ready") + .map((r) => r.computeSize()) + ); + res.json({ + used: sizes.reduce((sum, i) => sum + i, 0), + total: config.DEFAULT_QUOTA, + }); + } catch (error) { + handleError(error, res); + } +}); + +router.get("/default", async (req: express.Request, res: express.Response) => { + try { + const user = await getUser(req); + + res.json(user.default); + } catch (error) { + handleError(error, res); + } +}); + +router.post("/default", async (req: express.Request, res: express.Response) => { + try { + const user = await getUser(req); + + const d = req.body; + user.model.default = d; + + await user.model.save(); + res.send("ok"); + } catch (error) { + handleError(error, res); + } +}); + +router.get( + "/anonymized_repositories", + async (req: express.Request, res: express.Response) => { + try { + const user = await getUser(req); + res.json( + (await user.getRepositories()).map((x) => { + return x.toJSON(); + }) + ); + } catch (error) { + handleError(error, res); + } + } +); + +router.get( + "/all_repositories", + async (req: express.Request, res: express.Response) => { + try { + const user = await getUser(req); + const repos = await user.getGitHubRepositories({ + force: req.query.force == "1", + }); + res.json( + repos.map((x) => { + return { + fullName: x.fullName, + id: x.id, + }; + }) + ); + } catch (error) { + handleError(error, res); + } + } +); + +export default router; diff --git a/src/routes/webview.ts b/src/routes/webview.ts new file mode 100644 index 0000000..0f3d37a --- /dev/null +++ b/src/routes/webview.ts @@ -0,0 +1,55 @@ +import * as express from "express"; +import { getRepo, handleError } from "./route-utils"; +import * as path from "path"; +import AnonymizedFile from "../AnonymizedFile"; +import GitHubDownload from "../source/GitHubDownload"; + +const router = express.Router(); + +async function webView(req: express.Request, res: express.Response) { + const repo = await getRepo(req, res); + if (!repo) return; + try { + if (!repo.options.page) { + throw new Error("page_not_activated"); + } + if (!repo.options.pageSource) { + throw new Error("page_not_activated"); + } + + if ( + repo.options.pageSource?.branch != + (repo.source as GitHubDownload).branch.name + ) { + throw new Error("page_not_supported_on_different_branch"); + } + + let requestPath = path.join( + repo.options.pageSource?.path, + req.path.substring( + req.path.indexOf(req.params.repoId) + req.params.repoId.length + ) + ); + if (requestPath[requestPath.length - 1] == "/") { + requestPath = path.join(requestPath, "index.html"); + } + requestPath = requestPath; + const f = new AnonymizedFile({ + repository: repo, + anonymizedPath: requestPath, + }); + if (!(await f.isFileSupported())) { + return res.status(500).send({ error: "file_not_supported" }); + } + f.send(res); + } catch (error) { + handleError(error, res); + } +} + +router.get("/:repoId/*", webView); +router.get("/:repoId", (req: express.Request, res: express.Response) => { + res.redirect("/w" + req.url + "/"); +}); + +export default router; diff --git a/src/server.ts b/src/server.ts new file mode 100644 index 0000000..761824b --- /dev/null +++ b/src/server.ts @@ -0,0 +1,101 @@ +import * as path from "path"; +import * as ofs from "fs"; +import * as redis from "redis"; +import * as rateLimit from "express-rate-limit"; +import * as RedisStore from "rate-limit-redis"; +import * as express from "express"; +import * as compression from "compression"; +import * as db from "./database/database"; +import config from "../config"; +import * as passport from "passport"; + +import * as connection from "./routes/connection"; +import router from "./routes"; +import AnonymizedRepositoryModel from "./database/anonymizedRepositories/anonymizedRepositories.model"; + +function indexResponse(req: express.Request, res: express.Response) { + if ( + req.params.repoId && + req.headers["accept"] && + req.headers["accept"].indexOf("text/html") == -1 + ) { + const repoId = req.path.split("/")[2]; + // if it is not an html request, it assumes that the browser try to load a different type of resource + return res.redirect( + `/api/repo/${repoId}/file/${req.path.substring( + req.path.indexOf(repoId) + repoId.length + 1 + )}` + ); + } + res.sendFile(path.resolve(__dirname, "..", "public", "index.html")); +} + +export default async function start() { + const app = express(); + app.use(express.json()); + + app.use(compression()); + app.set("trust proxy", 1); + + // handle session and connection + app.use(connection.appSession); + app.use(passport.initialize()); + app.use(passport.session()); + + const rate = rateLimit({ + store: new RedisStore({ + client: redis.createClient({ + host: config.REDIS_HOSTNAME, + port: config.REDIS_PORT, + }), + }), + windowMs: 15 * 60 * 1000, // 15 minutes + max: 200, // limit each IP + // delayMs: 0, // disable delaying - full speed until the max limit is reached + }); + + app.use("/github", rate, connection.router); + + // api routes + app.use("/api/user", rate, router.user); + app.use("/api/repo", rate, router.repositoryPublic); + app.use("/api/repo", rate, router.file); + app.use("/api/repo", rate, router.repositoryPrivate); + app.use("/w/", rate, router.webview); + + app.get("/api/message", async (_, res) => { + if (ofs.existsSync("./message.txt")) { + return res.sendFile(path.resolve(__dirname, "..", "message.txt")); + } + res.sendStatus(404); + }); + + app.get("/api/stat", async (_, res) => { + const nbRepositories = + await AnonymizedRepositoryModel.estimatedDocumentCount(); + + const nbUsers = (await AnonymizedRepositoryModel.distinct("owner")).length; + res.json({ nbRepositories, nbUsers }); + }); + + app + .get("/", indexResponse) + .get("/404", indexResponse) + .get("/anonymize", indexResponse) + .get("/r/:repoId/?*", indexResponse) + .get("/repository/:repoId/?*", indexResponse); + + app.use( + express.static(path.join(__dirname, "..", "public"), { + etag: true, + lastModified: true, + maxAge: 3600000, // 1h + }) + ); + + app.get("*", indexResponse); + + await db.connect(); + app.listen(config.PORT); + console.log("Database connected and Server started on port: " + config.PORT); +} diff --git a/src/source/GitHubBase.ts b/src/source/GitHubBase.ts new file mode 100644 index 0000000..94c8683 --- /dev/null +++ b/src/source/GitHubBase.ts @@ -0,0 +1,83 @@ +import AnonymizedFile from "../AnonymizedFile"; +import { Branch, Tree } from "../types"; +import { GitHubRepository } from "./GitHubRepository"; +import config from "../../config"; +import { OAuthApp } from "@octokit/oauth-app"; +import Repository from "../Repository"; +import * as stream from "stream"; +import UserModel from "../database/users/users.model"; + +export default abstract class GitHubBase { + type: "GitHubDownload" | "GitHubStream" | "Zip"; + githubRepository: GitHubRepository; + branch: Branch; + accessToken: string; + repository: Repository; + + constructor( + data: { + type: "GitHubDownload" | "GitHubStream" | "Zip"; + branch?: string; + commit?: string; + repositoryId?: string; + repositoryName?: string; + accessToken?: string; + }, + repository: Repository + ) { + this.type = data.type; + this.accessToken = data.accessToken; + this.githubRepository = new GitHubRepository({ + name: data.repositoryName, + externalId: data.repositoryId, + branches: [{ commit: data.commit, name: data.branch }], + }); + this.repository = repository; + this.branch = { commit: data.commit, name: data.branch }; + } + + async getFileContent(file: AnonymizedFile): Promise { + throw new Error("Method not implemented."); + } + getFiles(): Promise { + throw new Error("Method not implemented."); + } + + async getToken(owner?: string) { + if (owner) { + const user = await UserModel.findOne({ username: owner }); + if (user && user.accessToken) { + return user.accessToken as string; + } + } + if (this.accessToken) { + try { + const app = new OAuthApp({ + clientType: "github-app", + clientId: config.CLIENT_ID, + clientSecret: config.CLIENT_SECRET, + }); + await app.checkToken({ + token: this.accessToken, + }); + return this.accessToken; + } catch (error) { + // console.debug("Token is invalid.", error); + this.accessToken = config.GITHUB_TOKEN; + } + } + return config.GITHUB_TOKEN; + } + + get url() { + return "https://github.com/" + this.githubRepository.fullName; + } + + toJSON(): any { + return { + type: this.type, + fullName: this.githubRepository.fullName?.toString(), + branch: this.branch, + }; + } +} diff --git a/src/source/GitHubDownload.ts b/src/source/GitHubDownload.ts new file mode 100644 index 0000000..9b1bcc1 --- /dev/null +++ b/src/source/GitHubDownload.ts @@ -0,0 +1,75 @@ +import { Octokit } from "@octokit/rest"; +import * as path from "path"; +import config from "../../config"; +import storage from "../storage"; +import Repository from "../Repository"; + +import GitHubBase from "./GitHubBase"; +import AnonymizedFile from "../AnonymizedFile"; +import { SourceBase } from "../types"; +import * as got from "got"; +import * as stream from "stream"; +import { OctokitResponse } from "@octokit/types"; + +export default class GitHubDownload extends GitHubBase implements SourceBase { + constructor( + data: { + type: "GitHubDownload" | "GitHubStream" | "Zip"; + branch?: string; + commit?: string; + repositoryId?: string; + repositoryName?: string; + accessToken?: string; + }, + repository: Repository + ) { + super(data, repository); + } + + private async _getZipUrl( + auth?: string + ): Promise> { + const octokit = new Octokit({ auth }); + return octokit.rest.repos.downloadTarballArchive({ + owner: this.githubRepository.owner, + repo: this.githubRepository.repo, + ref: this.branch?.commit || "HEAD", + method: "HEAD", + }); + } + + async download() { + let response: OctokitResponse; + try { + response = await this._getZipUrl(await this.getToken()); + } catch (error) { + if (error.status == 401 && config.GITHUB_TOKEN) { + try { + response = await this._getZipUrl(config.GITHUB_TOKEN); + } catch (error) { + throw new Error("repo_not_accessible"); + } + } else { + throw new Error("repo_not_accessible"); + } + } + const originalPath = this.repository.originalCachePath; + await storage.mk(originalPath); + await storage.extractTar(originalPath, got.stream(response.url)); + } + + async getFileContent(file: AnonymizedFile): Promise { + await this.download(); + // update the file list + await this.repository.files({ force: true }); + return storage.read(file.originalCachePath); + } + + async getFiles() { + const folder = this.repository.originalCachePath; + if (!(await storage.exists(folder))) { + await this.download(); + } + return storage.listFiles(folder); + } +} diff --git a/src/source/GitHubRepository.ts b/src/source/GitHubRepository.ts new file mode 100644 index 0000000..92bdfc4 --- /dev/null +++ b/src/source/GitHubRepository.ts @@ -0,0 +1,171 @@ +import { Branch } from "../types"; +import * as gh from "parse-github-url"; +import { IRepositoryDocument } from "../database/repositories/repositories.types"; +import { Octokit } from "@octokit/rest"; +import RepositoryModel from "../database/repositories/repositories.model"; + +export class GitHubRepository { + private _data: Partial< + { [P in keyof IRepositoryDocument]: IRepositoryDocument[P] } + >; + constructor( + data: Partial<{ [P in keyof IRepositoryDocument]: IRepositoryDocument[P] }> + ) { + this._data = data; + } + + toJSON() { + return { + repo: this.repo, + owner: this.owner, + hasPage: this._data.hasPage, + pageSource: this._data.pageSource, + fullName: this.fullName, + defaultBranch: this._data.defaultBranch, + size: this.size, + }; + } + + get model() { + return this._data; + } + + public get fullName(): string { + return this._data.name; + } + + public get id(): string { + return this._data.externalId; + } + + public get size(): number { + return this._data.size; + } + + async branches(opt: { + accessToken?: string; + force?: boolean; + }): Promise { + if ( + !this._data.branches || + this._data.branches.length == 0 || + opt?.force === true + ) { + // get the list of repo from github + const octokit = new Octokit({ auth: opt.accessToken }); + const branches = ( + await octokit.paginate(octokit.repos.listBranches, { + owner: this.owner, + repo: this.repo, + per_page: 100, + }) + ).map((b) => { + return { + name: b.name, + commit: b.commit.sha, + readme: this._data.branches?.filter( + (f: Branch) => f.name == b.name + )[0]?.readme, + } as Branch; + }); + this._data.branches = branches; + + await RepositoryModel.updateOne( + { externalId: this.id }, + { $set: { branches } } + ); + } else { + this._data.branches = ( + await RepositoryModel.findOne({ externalId: this.id }).select( + "branches" + ) + ).branches; + } + + return this._data.branches; + } + + async readme(opt: { + branch?: string; + force?: boolean; + accessToken?: string; + }): Promise { + if (!opt.branch) opt.branch = this._data.defaultBranch || "master"; + + const model = await RepositoryModel.findOne({ + externalId: this.id, + }).select("branches"); + + this._data.branches = await this.branches(opt); + model.branches = this._data.branches; + + const selected = model.branches.filter((f) => f.name == opt.branch)[0]; + if (!selected?.readme || opt?.force === true) { + // get the list of repo from github + const octokit = new Octokit({ auth: opt.accessToken }); + const ghRes = await octokit.repos.getReadme({ + owner: this.owner, + repo: this.repo, + ref: selected?.commit, + }); + const readme = Buffer.from( + ghRes.data.content, + ghRes.data.encoding as BufferEncoding + ).toString("utf-8"); + selected.readme = readme; + + await model.save(); + } + + return selected.readme; + } + + public get owner(): string { + const repo = gh(this.fullName); + if (!repo) { + throw "invalid_repo"; + } + return repo.owner || this.fullName; + } + + public get repo(): string { + const repo = gh(this.fullName); + if (!repo) { + throw "invalid_repo"; + } + return repo.name || this.fullName; + } +} + +export async function getRepositoryFromGitHub(opt: { + owner: string; + repo: string; + accessToken: string; +}) { + const octokit = new Octokit({ auth: opt.accessToken }); + const r = ( + await octokit.repos.get({ + owner: opt.owner, + repo: opt.repo, + }) + ).data; + if (!r) throw new Error("repo_not_found"); + let model = await RepositoryModel.findOne({ externalId: "gh_" + r.id }); + if (!model) { + model = new RepositoryModel({ externalId: "gh_" + r.id }); + } + model.name = r.full_name; + model.url = r.html_url; + model.size = r.size; + model.defaultBranch = r.default_branch; + model.hasPage = r.has_pages; + if (model.hasPage) { + const ghPageRes = await octokit.repos.getPages({ + owner: opt.owner, + repo: opt.repo, + }); + model.pageSource = ghPageRes.data.source; + } + await model.save(); + return new GitHubRepository(model); +} diff --git a/src/source/GitHubStream.ts b/src/source/GitHubStream.ts new file mode 100644 index 0000000..32ffdee --- /dev/null +++ b/src/source/GitHubStream.ts @@ -0,0 +1,171 @@ +import { Octokit } from "@octokit/rest"; +import AnonymizedFile from "../AnonymizedFile"; +import Repository from "../Repository"; +import GitHubBase from "./GitHubBase"; +import storage from "../storage"; +import { SourceBase, Tree } from "../types"; +import * as path from "path"; + +import * as stream from "stream"; + +export default class GitHubStream extends GitHubBase implements SourceBase { + constructor( + data: { + type: "GitHubDownload" | "GitHubStream" | "Zip"; + branch?: string; + commit?: string; + repositoryId?: string; + repositoryName?: string; + accessToken?: string; + }, + repository: Repository + ) { + super(data, repository); + } + + async getFileContent(file: AnonymizedFile): Promise { + if (!file.sha) throw new Error("file_sha_not_provided"); + const octokit = new Octokit({ + auth: await this.getToken(), + }); + + try { + const ghRes = await octokit.rest.git.getBlob({ + owner: this.githubRepository.owner, + repo: this.githubRepository.repo, + file_sha: file.sha, + }); + if (!ghRes.data.content && ghRes.data.size != 0) { + throw new Error("file_not_accessible"); + } + // empty file + let content: Buffer; + if (ghRes.data.content) { + content = Buffer.from( + ghRes.data.content, + ghRes.data.encoding as BufferEncoding + ); + } else { + content = Buffer.from(""); + } + await storage.write(file.originalCachePath, content); + return stream.Readable.from(content.toString()); + } catch (error) { + if (error.status == 403) { + throw new Error("file_too_big"); + } + console.error(error); + } + throw new Error("file_not_accessible"); + } + + async getFiles() { + return this.getTree(this.branch.commit); + } + + private async getTree( + sha: string, + truncatedTree: Tree = {}, + parentPath: string = "" + ) { + const octokit = new Octokit({ + auth: await this.getToken(), + }); + const ghRes = await octokit.git.getTree({ + owner: this.githubRepository.owner, + repo: this.githubRepository.repo, + tree_sha: sha, + recursive: "1", + }); + + const tree = this.tree2Tree(ghRes.data.tree, truncatedTree, parentPath); + if (ghRes.data.truncated) { + await this.getTruncatedTree(sha, tree, parentPath); + } + return tree; + } + + private async getTruncatedTree( + sha: string, + truncatedTree: Tree = {}, + parentPath: string = "" + ) { + const octokit = new Octokit({ + auth: await this.getToken(), + }); + const ghRes = await octokit.git.getTree({ + owner: this.githubRepository.owner, + repo: this.githubRepository.repo, + tree_sha: sha, + }); + const tree = ghRes.data.tree; + + for (let elem of tree) { + if (!elem.path) continue; + if (elem.type == "tree") { + const elementPath = path.join(parentPath, elem.path); + const paths = elementPath.split("/"); + + let current = truncatedTree; + for (let i = 0; i < paths.length; i++) { + let p = paths[i]; + if (!current[p]) { + if (elem.sha) + await this.getTree(elem.sha, truncatedTree, elementPath); + break; + } + current = current[p] as Tree; + } + } + } + this.tree2Tree(ghRes.data.tree, truncatedTree, parentPath); + return truncatedTree; + } + + private tree2Tree( + tree: { + path?: string; + mode?: string; + type?: string; + sha?: string; + size?: number; + url?: string; + }[], + partialTree: Tree = {}, + parentPath: string = "" + ) { + for (let elem of tree) { + let current = partialTree; + + if (!elem.path) continue; + + const paths = path.join(parentPath, elem.path).split("/"); + + // if elem is a folder iterate on all folders if it is a file stop before the filename + const end = elem.type == "tree" ? paths.length : paths.length - 1; + for (let i = 0; i < end; i++) { + let p = paths[i]; + if (p[0] == "$") { + p = "\\" + p; + } + if (!current[p]) { + current[p] = {}; + } + current = current[p] as Tree; + } + + // if elem is a file add the file size in the file list + if (elem.type == "blob") { + let p = paths[end]; + if (p[0] == "$") { + p = "\\" + p; + } + current[p] = { + size: elem.size || 0, // size in bit + sha: elem.sha || "", + }; + } + } + return partialTree; + } +} diff --git a/src/source/Zip.ts b/src/source/Zip.ts new file mode 100644 index 0000000..63d2f83 --- /dev/null +++ b/src/source/Zip.ts @@ -0,0 +1,31 @@ +import * as path from "path"; +import AnonymizedFile from "../AnonymizedFile"; +import Repository from "../Repository"; +import storage from "../storage"; +import { SourceBase } from "../types"; +import * as stream from "stream"; + +export default class Zip implements SourceBase { + type = "Zip"; + repository: Repository; + url?: string; + + constructor(data: any, repository: Repository) { + this.repository = repository; + this.url = data.url; + } + + async getFiles() { + return storage.listFiles(this.repository.originalCachePath); + } + + async getFileContent(file: AnonymizedFile): Promise { + return storage.read(file.originalCachePath); + } + + toJSON(): any { + return { + type: this.type, + }; + } +} diff --git a/src/storage.ts b/src/storage.ts new file mode 100644 index 0000000..415b2e5 --- /dev/null +++ b/src/storage.ts @@ -0,0 +1,8 @@ +import config from "../config"; +import FileSystem from "./storage/FileSystem"; +import S3Storage from "./storage/S3"; +import { StorageBase } from "./types"; + +const storage = config.STORAGE == "s3" ? new S3Storage() : new FileSystem(); + +export default storage as StorageBase; diff --git a/src/storage/FileSystem.ts b/src/storage/FileSystem.ts new file mode 100644 index 0000000..83a86f5 --- /dev/null +++ b/src/storage/FileSystem.ts @@ -0,0 +1,139 @@ +import { StorageBase, Tree } from "../types"; +import * as fs from "fs"; +import * as tar from "tar-fs"; +import * as path from "path"; +import * as express from "express"; +import config from "../../config"; +import * as stream from "stream"; +import * as gunzip from "gunzip-maybe"; +import * as archiver from "archiver"; + +export default class FileSystem implements StorageBase { + type = "FileSystem"; + + constructor() {} + + /** @override */ + async exists(p: string): Promise { + return fs.existsSync(path.join(config.FOLDER, p)); + } + + /** @override */ + send(p: string, res: express.Response) { + res.sendFile(path.join(config.FOLDER, p), { dotfiles: "allow" }); + } + + /** @override */ + read(p: string): stream.Readable { + return fs.createReadStream(path.join(config.FOLDER, p)); + } + + /** @override */ + async write(p: string, data: Buffer): Promise { + if (!(await this.exists(path.dirname(p)))) { + await fs.promises.mkdir(path.dirname(path.join(config.FOLDER, p)), { + recursive: true, + }); + } + return fs.promises.writeFile(path.join(config.FOLDER, p), data); + } + + /** @override */ + async rm(dir: string): Promise { + await fs.promises.rm(path.join(config.FOLDER, dir), { + force: true, + recursive: true, + }); + } + + /** @override */ + async mk(dir: string): Promise { + if (!(await this.exists(dir))) + fs.promises.mkdir(path.join(config.FOLDER, dir), { recursive: true }); + } + + /** @override */ + async listFiles( + dir: string, + opt: { + root?: string; + onEntry?: (file: { path: string; size: number }) => void; + } = {} + ): Promise { + if (opt.root == null) { + opt.root = config.FOLDER; + } + let files = await fs.promises.readdir(path.join(opt.root, dir)); + const output: Tree = {}; + for (let file of files) { + let filePath = path.join(dir, file); + try { + const stats = await fs.promises.stat(path.join(opt.root, filePath)); + if (file[0] == "$") { + file = "\\" + file; + } + if (stats.isDirectory()) { + output[file] = await this.listFiles(filePath, opt); + } else if (stats.isFile()) { + if (opt.onEntry) { + opt.onEntry({ + path: filePath, + size: stats.size, + }); + } + output[file] = { size: stats.size, sha: stats.ino.toString() }; + } + } catch (error) { + console.error(error); + } + } + return output; + } + + /** @override */ + async extractTar(p: string, data: stream.Readable): Promise { + return new Promise((resolve, reject) => { + data + .pipe(gunzip()) + .pipe( + tar.extract(path.join(config.FOLDER, p), { + map: (header) => { + header.name = header.name.substr(header.name.indexOf("/") + 1); + return header; + }, + }) + ) + .on("finish", resolve) + .on("error", reject); + }); + } + + /** @override */ + archive( + dir: string, + opt?: { + format?: "zip" | "tar"; + fileTransformer?; + } + ) { + const archive = archiver(opt?.format, {}); + + this.listFiles(dir, { + onEntry: (file) => { + let rs = this.read(file.path); + if (opt?.fileTransformer) { + // apply transformation on the stream + rs = rs.pipe(opt.fileTransformer(file.path)); + } + const f = file.path.replace(dir, ""); + archive.append(rs, { + name: path.basename(f), + prefix: path.dirname(f), + }); + }, + }).then(() => { + archive.finalize(); + }); + return archive; + } +} diff --git a/src/storage/S3.ts b/src/storage/S3.ts new file mode 100644 index 0000000..d9b147e --- /dev/null +++ b/src/storage/S3.ts @@ -0,0 +1,225 @@ +import { StorageBase, Tree, TreeFile } from "../types"; +import { S3 } from "aws-sdk"; +import config from "../../config"; +import * as stream from "stream"; +import { ArchiveStreamToS3 } from "archive-stream-to-s3"; +import * as express from "express"; +import * as mime from "mime-types"; +import * as flow from "xml-flow"; +import * as archiver from "archiver"; +import * as path from "path"; +import * as gunzip from "gunzip-maybe"; + +const originalArchiveStreamToS3Entry: Function = (ArchiveStreamToS3 as any) + .prototype.onEntry; + +export default class S3Storage implements StorageBase { + type = "AWS"; + client: S3; + + constructor() { + if (!config.S3_BUCKET) throw new Error("s3_config_not_provided"); + this.client = new S3({ + region: config.S3_REGION, + endpoint: config.S3_ENDPOINT, + accessKeyId: config.S3_CLIENT_ID, + secretAccessKey: config.S3_CLIENT_SECRET, + }); + } + + /** @override */ + async exists(path: string): Promise { + try { + await this.client + .headObject({ + Bucket: config.S3_BUCKET, + Key: path, + }) + .promise(); + return true; + } catch (err) { + return false; + } + } + + /** @override */ + async mk(dir: string): Promise { + if (dir && dir[dir.length - 1] != "/") dir = dir + "/"; + + await this.client + .putObject({ + Bucket: config.S3_BUCKET, + Key: dir, + }) + .promise(); + } + + /** @override */ + async rm(dir: string): Promise { + const data = await this.client + .listObjectsV2({ + Bucket: config.S3_BUCKET, + Prefix: dir, + }) + .promise(); + + const params = { Bucket: config.S3_BUCKET, Delete: { Objects: [] } }; + + data.Contents.forEach(function (content) { + params.Delete.Objects.push({ Key: content.Key }); + }); + + if (params.Delete.Objects.length == 0) { + // nothing to remove + return; + } + await this.client.deleteObjects(params).promise(); + + if (data.IsTruncated) { + await this.rm(dir); + } + } + + /** @override */ + send(p: string, res: express.Response) { + const s = this.client + .getObject({ + Bucket: config.S3_BUCKET, + Key: p, + }) + .on("httpHeaders", (statusCode, headers, response) => { + res.status(statusCode); + if (statusCode < 300) { + res.set("Content-Length", headers["content-length"]); + res.set("Content-Type", headers["content-type"]); + } + ( + response.httpResponse.createUnbufferedStream() as stream.Readable + ).pipe(res); + }); + + s.send(); + } + + /** @override */ + read(path: string): stream.Readable { + return this.client + .getObject({ + Bucket: config.S3_BUCKET, + Key: path, + }) + .createReadStream(); + } + + /** @override */ + async write(path: string, data: Buffer): Promise { + await this.client + .putObject({ + Bucket: config.S3_BUCKET, + Key: path, + Body: data, + ContentType: mime.lookup(path).toString(), + }) + .promise(); + return; + } + + /** @override */ + async listFiles(dir: string): Promise { + if (dir && dir[dir.length - 1] != "/") dir = dir + "/"; + const out: Tree = {}; + const req = await this.client + .listObjectsV2({ + Bucket: config.S3_BUCKET, + Prefix: dir, + }) + .promise(); + + if (!req.Contents) return out; + for (const f of req.Contents) { + if (!f.Key) continue; + f.Key = f.Key.replace(dir, ""); + const paths = f.Key.split("/"); + let current: Tree = out; + for (let i = 0; i < paths.length - 1; i++) { + let p = paths[i]; + if (!p) continue; + if (!(current[p] as Tree)) { + current[p] = {} as Tree; + } + current = current[p] as Tree; + } + + const fileInfo: TreeFile = { size: f.Size || 0, sha: f.ETag }; + const fileName = paths[paths.length - 1]; + if (fileName) current[fileName] = fileInfo; + } + return out; + } + + /** @override */ + async extractTar(p: string, data: stream.Readable): Promise { + return new Promise((resolve, reject) => { + const toS3 = new ArchiveStreamToS3(config.S3_BUCKET, p, this.client); + + let rootFolder = null; + (ArchiveStreamToS3 as any).prototype.onEntry = function ( + header: any, + stream: any, + next: any + ) { + if (rootFolder == null) { + rootFolder = header.name.substr(0, header.name.indexOf("/") + 1); + } + header.name = header.name.replace(rootFolder, ""); + originalArchiveStreamToS3Entry.call(toS3, header, stream, next); + }; + + toS3.on("finish", (result) => { + resolve(result); + }); + toS3.on("error", (e) => { + reject(e); + }); + data.pipe(gunzip()).pipe(toS3); + }); + } + + /** @override */ + archive( + dir: string, + opt?: { + format?: "zip" | "tar"; + fileTransformer?; + } + ) { + const archive = archiver(opt?.format, {}); + if (dir && dir[dir.length - 1] != "/") dir = dir + "/"; + const req = this.client.listObjectsV2({ + Bucket: config.S3_BUCKET, + Prefix: dir, + }); + const filesStream = req.createReadStream(); + + const xmlStream = flow(filesStream); + + const that = this; + xmlStream.on("tag:contents", function (file) { + let rs = that.read(file.key); + file.key = file.key.replace(dir, ""); + const filename = path.basename(file.key); + if (filename == "") return; + if (opt?.fileTransformer) { + rs = rs.pipe(opt.fileTransformer(filename)); + } + archive.append(rs, { + name: filename, + prefix: path.dirname(file.key), + }); + }); + xmlStream.on("end", () => { + archive.finalize(); + }); + return archive; + } +} diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..c41d03b --- /dev/null +++ b/src/types.ts @@ -0,0 +1,131 @@ +import GitHubDownload from "./source/GitHubDownload"; +import GitHubStream from "./source/GitHubStream"; +import Zip from "./source/Zip"; +import S3Storage from "./storage/S3"; +import FileSystem from "./storage/FileSystem"; +import AnonymizedFile from "./AnonymizedFile"; +import * as stream from "stream"; +import * as archiver from "archiver"; + +export interface SourceBase { + readonly type: string; + + /** + * The url of the source + */ + url?: string; + + /** + * Retrieve the fie content + * @param file the file of the content to retrieve + */ + getFileContent(file: AnonymizedFile): Promise; + + /** + * Get all the files from a specific source + */ + getFiles(): Promise; + + toJSON(): any; +} + +export type Source = GitHubDownload | GitHubStream | Zip; + +export interface StorageBase { + /** + * The type of storage + */ + type: string; + + /** + * check if the path exists + * @param path the path to check + */ + exists(path: string): Promise; + + /** + * Read the content of a file + * @param path the path to the file + */ + read(path: string): stream.Readable; + + /** + * Write data to a file + * @param path the path to the file + * @param data the content of the file + */ + write(path: string, data: Buffer): Promise; + + /** + * List the files from dir + * @param dir + */ + listFiles(dir: string): Promise; + + /** + * Extract the content of tar to dir + * @param dir + * @param tar + */ + extractTar(dir: string, tar: stream.Readable): Promise; + + /** + * Remove the path + * @param dir + */ + rm(dir: string): Promise; + + /** + * Archive the content of dir + * @param dir + * @param opt + */ + archive( + dir: string, + opt?: { + /** + * Archive format + */ + format?: "zip" | "tar"; + /** + * Transformer to apply on the content of the file + */ + fileTransformer?: (p: any) => Transformer; + } + ): archiver.Archiver; + + /** + * Create a directory + * @param dir + */ + mk(dir: string): Promise; +} + +export type Storage = S3Storage | FileSystem; + +export interface Branch { + name: string; + commit: string; + readme?: string; +} + +export type RepositoryStatus = + | "queue" + | "preparing" + | "download" + | "ready" + | "expired" + | "removed"; + +export type SourceStatus = "available" | "unavailable"; + +export type TreeElement = Tree | TreeFile; + +export interface Tree { + [key: string]: TreeElement; +} + +export interface TreeFile { + sha: string; + size: number; +} diff --git a/test/file.test.js b/test/file.test.js deleted file mode 100644 index d400817..0000000 --- a/test/file.test.js +++ /dev/null @@ -1,17 +0,0 @@ -var expect = require("chai").expect; -var assert = require("chai").assert; -const fs = require("fs"); - -const githubUtils = require("../utils/github"); -const fileUtils = require("../utils/file"); -const repoUtils = require("../utils/repository"); -const db = require("../utils/database"); - -describe("Test Files Utils", async function() { - describe("List all files", function() { - it("Get all file from repo with more than 1000 files", async function() { - const fullName = "TQRG/BugSwarm"; - await fileUtils.getTree({ fullName }); - }); - }); -}); diff --git a/test/github.test.js b/test/github.test.js deleted file mode 100644 index f14bcea..0000000 --- a/test/github.test.js +++ /dev/null @@ -1,31 +0,0 @@ -var expect = require("chai").expect; -var assert = require("chai").assert; -const fs = require("fs"); - -const githubUtils = require("../utils/github"); -const repoUtils = require("../utils/repository"); -const db = require("../utils/database"); - -describe("Test GitHub Utils", async function() { - describe("Download Repository", function() { - const target = "/tmp/repo.zip"; - it("Download an exisiting repo to a folder", async function() { - await repoUtils.downloadRepoZip( - { fullName: "tdurieux/binance-trade-bot" }, - target - ); - expect(fs.existsSync(target)).to.equal(true, `${target} should exist`); - fs.unlinkSync(target); - }); - it("Download a non-exisiting repo to a folder", async function() { - try { - await repoUtils.downloadRepoZip( - { fullName: "tdurieux/missing" }, - target - ); - fs.unlinkSync(target); - assert.fail("Should trigger an exception"); - } catch (error) {} - }); - }); -}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..daedde7 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "es6", + "module": "commonjs", + "outDir": "dist", + "removeComments": true, + "preserveConstEnums": true, + "forceConsistentCasingInFileNames": true, + "sourceMap": true + }, + "include": ["src/**/*.ts", "index.ts", "tests3.ts"], + "exclude": ["node_modules", ".vscode"] +} diff --git a/utils/anonymize.js b/utils/anonymize.js deleted file mode 100644 index 2286f8e..0000000 --- a/utils/anonymize.js +++ /dev/null @@ -1,116 +0,0 @@ -const fs = require("fs").promises; -const ofs = require("fs"); -const path = require("path"); -const fileUtils = require("./file"); -const config = require("../config") - -const anonymizeContent = (content, repoConfig) => { - const urlRegex = /?/g; - - if (repoConfig.options.image === false) { - // remove image in markdown - content = content.replace( - /!\[[^\]]*\]\((?.*?)(?=\"|\))(?\".*\")?\)/g, - "" - ); - } - - if (!repoConfig.options.link) { - // remove all links - content = content.replace(urlRegex, config.ANONYMIZATION_MASK); - } - - content = content.replace( - new RegExp( - `https://github.com/${repoConfig.fullName}/blob/${repoConfig.branch}\\b`, - "gi" - ), - `https://anonymous.4open.science/r/${repoConfig.repoId}` - ); - content = content.replace( - new RegExp( - `https://github.com/${repoConfig.fullName}/tree/${repoConfig.branch}\\b`, - "gi" - ), - `https://anonymous.4open.science/r/${repoConfig.repoId}` - ); - content = content.replace( - new RegExp(`https://github.com/${repoConfig.fullName}`, "gi"), - `https://anonymous.4open.science/r/${repoConfig.repoId}` - ); - - for (let term of repoConfig.terms) { - if (term.trim() == "") { - continue; - } - // remove whole url if it contains the term - content = content.replace(urlRegex, (match) => { - if (new RegExp(`\\b${term}\\b`, "gi").test(match)) return config.ANONYMIZATION_MASK; - return match; - }); - - // remove the term in the text - content = content.replace(new RegExp(`\\b${term}\\b`, "gi"), config.ANONYMIZATION_MASK); - } - return content; -}; - -const anonymizePath = (path, repoConfig) => { - for (let term of repoConfig.terms) { - if (term.trim() == "") { - continue; - } - path = path.replace(new RegExp(term, "gi"), config.ANONYMIZATION_MASK); - } - return path; -}; - -async function* walk(dir) { - for await (const d of await fs.opendir(dir)) { - const entry = path.join(dir, d.name); - if (d.isDirectory()) yield* await walk(entry); - else if (d.isFile()) yield entry; - } -} - -const anonymizeFolder = async (root, destination, repoConfig) => { - if (!ofs.existsSync(destination)) { - await fs.mkdir(destination, { recursive: true }); - } - try { - for await (const originalFilePath of walk(root)) { - const destinationFilePath = path.join( - destination, - anonymizePath(originalFilePath.replace(root, ""), repoConfig) - ); - const destinationFolder = path.dirname(destinationFilePath); - if (!ofs.existsSync(destinationFolder)) { - await fs.mkdir(destinationFolder, { recursive: true }); - } - await anonymizeFile(originalFilePath, destinationFilePath, repoConfig); - } - } catch (error) { - fs.rm(destination, { recursive: true, force: true }); - throw error; - } -}; - -const anonymizeFile = async (filePath, target, repoConfig) => { - if (!ofs.existsSync(path.dirname(target))) { - await fs.mkdir(path.dirname(target), { recursive: true }); - } - if (fileUtils.isText(filePath)) { - const content = anonymizeContent( - (await fs.readFile(filePath)).toString(), - repoConfig - ); - await fs.writeFile(target, content); - } else { - await fs.copyFile(filePath, target); - } -}; - -module.exports.anonymizeFile = anonymizeFile; -module.exports.anonymizePath = anonymizePath; -module.exports.anonymizeFolder = anonymizeFolder; -module.exports.anonymizeContent = anonymizeContent; diff --git a/utils/database.js b/utils/database.js deleted file mode 100644 index 8c51c38..0000000 --- a/utils/database.js +++ /dev/null @@ -1,39 +0,0 @@ -const config = require("../config"); - -var MongoClient = require("mongodb").MongoClient; -const MONGO_URL = "mongodb://root:rootpassword@mongodb:27017/?authSource=admin"; -let mongoClient = null; -let DB = null; - -module.exports.get = (collection) => { - if (!collection) return DB; - return DB.collection(collection); -}; - -module.exports.connect = async () => { - mongoClient = await MongoClient.connect( - MONGO_URL, - { useNewUrlParser: true, useUnifiedTopology: true } - ); - DB = mongoClient.db("anonymous_github"); - await DB.collection("anonymized_repositories").createIndex( - { repoId: 1 }, - { unique: true, name: "repoId" } - ); - await DB.collection("anonymized_repositories").createIndex( - { fullName: 1 }, - { name: "fullName" } - ); - await DB.collection("repositories").createIndex( - { fullName: 1 }, - { unique: true, name: "fullName" } - ); - await DB.collection("users").createIndex( - { username: 1 }, - { unique: true, name: "username" } - ); - return DB; -}; -module.exports.close = async () => { - return await mongoClient.close(); -}; diff --git a/utils/file.js b/utils/file.js deleted file mode 100644 index 62cc097..0000000 --- a/utils/file.js +++ /dev/null @@ -1,491 +0,0 @@ -const ofs = require("fs"); -const fs = require("fs").promises; -const path = require("path"); -const { Octokit } = require("@octokit/rest"); -const gh = require("parse-github-url"); -const loc = require("github-linguist").default; -const { isText } = require("istextorbinary"); - -const db = require("./database"); -const repoUtils = require("./repository"); -const githubUtils = require("./github"); -const anonymizeUtils = require("./anonymize"); -const config = require("../config"); - -async function walk(dir, root) { - if (root == null) { - root = dir; - } - let files = await fs.readdir(dir); - const output = { child: {} }; - for (let file of files) { - let filePath = path.join(dir, file); - try { - const stats = await fs.stat(filePath); - if (file[0] == "$") { - file = "\\" + file; - } - if (stats.isDirectory()) { - output.child[file] = await walk(filePath, root); - output.child[file].sha = stats.ino; - } else if (stats.isFile()) { - output.child[file] = { size: stats.size, sha: stats.ino }; - } - } catch (error) { - console.error(error); - } - } - return output; -} -function tree2tree(tree, partialTree, parentPath) { - if (!parentPath) parentPath = ""; - if (partialTree == null) { - partialTree = { child: Object.create(null) }; - } - for (let elem of tree) { - const paths = path.join(parentPath, elem.path).split("/"); - let current = partialTree; - - // if elem is a folder iterate on all folders if it is a file stop before the filename - const end = elem.type == "tree" ? paths.length : paths.length - 1; - for (let i = 0; i < end; i++) { - let p = paths[i]; - if (p[0] == "$") { - p = "\\" + p; - } - if (!current.child[p]) { - current.child[p] = { - child: Object.create(null), - }; - } - current = current.child[p]; - } - - // if elem is a file add the file size in the file list - if (elem.type == "blob") { - let p = paths[end]; - if (p[0] == "$") { - p = "\\" + p; - } - current.child[p] = { - size: elem.size, - sha: elem.sha, - }; - } else { - current.sha = elem.sha; - } - } - return partialTree; -} -async function getTruncatedTree(repoConfig, truncatedTree, sha, parentPath) { - const repo = gh(repoConfig.fullName); - - if (!sha || !/^[a-f0-9]+$/.test(sha)) { - if (repoConfig.commit && /^[a-f0-9]+$/.test(repoConfig.commit)) { - sha = repoConfig.commit; - } else { - sha = "HEAD"; - } - repoConfig.commit = sha; - } - - const octokit = new Octokit({ - auth: await githubUtils.getToken(repoConfig), - }); - const ghRes = await octokit.git.getTree({ - owner: repo.owner, - repo: repo.name, - tree_sha: sha, - }); - const tree = ghRes.data.tree; - - for (let elem of tree) { - if (elem.type == "tree") { - const elementPath = path.join(parentPath, elem.path); - const paths = elementPath.split("/"); - - let current = truncatedTree; - for (let i = 0; i < paths.length; i++) { - let p = paths[i]; - if (!current.child[p]) { - await module.exports.getTree( - repoConfig, - elem.sha, - truncatedTree, - elementPath - ); - break; - } - current = current.child[p]; - } - } - } - - tree2tree(ghRes.data.tree, truncatedTree, parentPath); - - return truncatedTree; -} -module.exports.getTree = async (repoConfig, sha, truncatedTree, parentPath) => { - const repo = gh(repoConfig.fullName); - - if (!sha || !/^[a-f0-9]+$/.test(sha)) { - if (repoConfig.commit && /^[a-f0-9]+$/.test(repoConfig.commit)) { - sha = repoConfig.commit; - } else { - sha = "HEAD"; - } - } - - if (!parentPath) parentPath = ""; - - const token = await githubUtils.getToken(repoConfig); - - const octokit = new Octokit({ - auth: token, - }); - const ghRes = await octokit.git.getTree({ - owner: repo.owner, - repo: repo.name, - tree_sha: sha, - recursive: true, - }); - sha = ghRes.data.sha; - repoConfig.commit = sha; - - const tree = tree2tree(ghRes.data.tree, truncatedTree, parentPath); - if (ghRes.data.truncated) { - await getTruncatedTree(repoConfig, tree, sha, parentPath); - } - return tree; -}; -module.exports.getFileList = async (options) => { - let repoConfig = options.repoConfig; - if (!repoConfig) { - repoConfig = await repoUtils.getConfig(options.repoId); - } - - if (repoConfig == null) { - throw "repo_not_found"; - } - - const r = await db.get("anonymized_repositories").findOne( - { repoId: repoConfig.repoId }, - { - projection: { files: 1 }, - } - ); - if (r && r.files) { - return r.files; - } - - if (repoConfig.options.mode == "stream") { - // get file list from github - const tree = await module.exports.getTree(repoConfig, repoConfig.commit); - const files = anonymizeTree(tree, repoConfig); - await db.get("anonymized_repositories").updateOne( - { repoId: repoConfig.repoId }, - { - $set: { - commit: repoConfig.commit, - originalFiles: tree.child, - files, - }, - }, - { upsert: true } - ); - return files; - } else if (repoConfig.options.mode == "download") { - const originalFiles = await walk( - repoUtils.getOriginalPath(repoConfig.repoId) - ); - const files = anonymizeTree(originalFiles, repoConfig); - await db.get("anonymized_repositories").updateOne( - { repoId: repoConfig.repoId }, - { - $set: { - originalFiles: originalFiles.child, - files, - }, - }, - { upsert: true } - ); - return files; - } else { - throw "non_supported_mode"; - } -}; -function anonymizeTree(tree, repoConfig) { - if (Number.isInteger(tree.size)) { - return tree; - } - const output = {}; - for (let file in tree.child) { - const anonymizedPath = anonymizeUtils.anonymizePath(file, repoConfig); - output[anonymizedPath] = anonymizeTree(tree.child[file], repoConfig); - } - return output; -} - -function tree2sha(tree, output, parent) { - if (!output) { - output = {}; - parent = ""; - } - for (let i in tree) { - if (tree[i].sha) { - output[tree[i].sha] = path.join(parent, i); - } - if (tree[i].child) { - tree2sha(tree[i].child, output, path.join(parent, i)); - } - } - return output; -} - -function getFile(tree, elementPath) { - const paths = elementPath.trim().split("/"); - let current = tree; - if (!tree.child) { - current = { child: tree }; - } - for (let i = 0; i < paths.length; i++) { - let p = paths[i]; - if (p == "") { - continue; - } - let tmp = current; - if (current.child) { - tmp = current.child; - } - if (!tmp[p]) { - return null; - } - current = tmp[p]; - } - return current; -} -module.exports.additionalExtensions = [ - "license", - "dockerfile", - "sbt", - "ipynb", - "gp", - "out", - "sol", - "in", -]; -module.exports.isText = (p) => { - const filename = path.basename(p); - const extensions = filename.split(".").reverse(); - const extension = extensions[0].toLowerCase(); - if (module.exports.additionalExtensions.includes(extension)) { - return true; - } - if (isText(p)) { - return true; - } - if (ofs.existsSync(p)) { - if (isText(p, ofs.readFileSync(p))) { - return true; - } - } - return false; -}; -module.exports.isFileSupported = (repoConfig, p) => { - if (module.exports.isText(p)) { - return true; - } - - const filename = path.basename(p); - const extensions = filename.split(".").reverse(); - const extension = extensions[0].toLowerCase(); - - if (repoConfig.options.pdf && extension == "pdf") { - return true; - } - if ( - repoConfig.options.image && - (extension == "png" || - extension == "ico" || - extension == "jpg" || - extension == "jpeg" || - extension == "gif") - ) { - return true; - } - return false; -}; -module.exports.isFilePathValid = async (options) => { - if (options.path == null) { - throw "invalid_path"; - } - let repoConfig = options.repoConfig; - if (!repoConfig) { - repoConfig = await repoUtils.getConfig(options.repoId); - } - - if (repoConfig == null) { - throw "repo_not_found"; - } - if (repoConfig.status == "expired") { - throw "repository_expired"; - } - if (repoConfig.status == "removed") { - throw "repository_expired"; - } - if (repoConfig.status != "ready") { - throw "repository_not_ready"; - } - - const anonymizedFilePath = path.join( - repoUtils.getAnonymizedPath(repoConfig.repoId), - options.path - ); - - if (ofs.existsSync(anonymizedFilePath)) { - if (ofs.lstatSync(anonymizedFilePath).isDirectory()) { - throw "is_folder"; - } - return true; - } - - let unanonymizePath = options.path; - const files = await module.exports.getFileList({ repoConfig }); - - const file = getFile(files, options.path); - if (file == null) { - throw "file_not_found"; - } - if (file) { - const r = await db - .get("anonymized_repositories") - .findOne( - { repoId: repoConfig.repoId }, - { projection: { originalFiles: 1 } } - ); - - const shatree = tree2sha(r.originalFiles); - if (shatree[file.sha]) { - unanonymizePath = shatree[file.sha]; - } - } - - const originalFilePath = path.join( - repoUtils.getOriginalPath(repoConfig.repoId), - unanonymizePath - ); - - if (ofs.existsSync(originalFilePath)) { - if (ofs.lstatSync(originalFilePath).isDirectory()) { - throw "is_folder"; - } - if (!module.exports.isFileSupported(repoConfig, originalFilePath)) { - throw "file_not_supported"; - } - await anonymizeUtils.anonymizeFile( - originalFilePath, - anonymizedFilePath, - repoConfig - ); - return true; - } - // if stream mode check download the file - if (repoConfig.options.mode == "stream") { - if (!file.sha) { - throw "is_folder"; - } - if (file.size > config.MAX_FILE_SIZE) { - // file bigger than 10mb - throw "file_too_big"; - } - const octokit = new Octokit({ - auth: await githubUtils.getToken(repoConfig), - }); - - let ghRes = null; - try { - const repo = gh(repoConfig.fullName); - ghRes = await octokit.request( - "GET /repos/{owner}/{repo}/git/blobs/{file_sha}", - { - owner: repo.owner, - repo: repo.name, - file_sha: file.sha, - } - ); - } catch (error) { - if (error.status == 403) { - throw "file_too_big"; - } - console.error(error); - throw "file_not_accessible"; - } - if (!ghRes.data.content && ghRes.data.size != 0) { - throw "file_not_accessible"; - } - // empty file - let content = ""; - if (ghRes.data.content) { - content = new Buffer.from(ghRes.data.content, ghRes.data.encoding); - } - - try { - await fs.mkdir(path.dirname(originalFilePath), { recursive: true }); - } catch (_) { - // ignore - } - try { - await fs.writeFile(originalFilePath, content, { encoding: "utf-8" }); - } catch (error) { - console.error(error); - throw "unable_to_write_file"; - } - if (!module.exports.isFileSupported(repoConfig, originalFilePath)) { - throw "file_not_supported"; - } - await anonymizeUtils.anonymizeFile( - originalFilePath, - anonymizedFilePath, - repoConfig - ); - return true; - } - return false; -}; - -module.exports.getStats = async (options) => { - let repoConfig = options.repoConfig; - if (!repoConfig) { - repoConfig = await repoUtils.getConfig(options.repoId); - } - - if (repoConfig == null) { - throw "repo_not_found"; - } - if (repoConfig.options.mode != "download") { - throw "stats_unsupported"; - } - - if (repoConfig.loc) { - return repoConfig.loc; - } - - const repoCache = repoUtils.getOriginalPath(repoConfig.repoId); - try { - await fs.access(repoCache, ofs.constants.R_OK); - } catch (error) { - throw "repo_not_found"; - } - const o = await loc(repoCache); - delete o.files; - await db.get("anonymized_repositories").updateOne( - { repoId: repoConfig.repoId }, - { - $set: { - loc: o, - }, - }, - { upsert: true } - ); - return o; -}; diff --git a/utils/github.js b/utils/github.js deleted file mode 100644 index b785d72..0000000 --- a/utils/github.js +++ /dev/null @@ -1,75 +0,0 @@ -const ofs = require("fs"); -const { OAuthApp } = require("@octokit/oauth-app"); - -const db = require("./database"); -const repoUtils = require("./repository"); -const fileUtils = require("./file"); - -const config = require("../config"); - -const app = new OAuthApp({ - clientType: "github-app", - clientId: config.CLIENT_ID, - clientSecret: config.CLIENT_SECRET, -}); - -module.exports.getToken = async (repoConfig) => { - if (repoConfig.owner) { - const user = await db - .get() - .collection("users") - .findOne( - { username: repoConfig.owner }, - { projection: { accessToken: 1 } } - ); - if (user && user.accessToken) { - return user.accessToken; - } - } - if (repoConfig.token) { - try { - await app.checkToken({ - token: repoConfig.token, - }); - return repoConfig.token; - } catch (error) { - console.debug("Token is invalid.", error); - delete repoConfig.token; - } - } - return config.GITHUB_TOKEN; -}; - -module.exports.downloadRepoAndAnonymize = async (repoConfig) => { - const cachePath = repoUtils.getAnonymizedPath(repoConfig.repoId); - const originalPath = repoUtils.getOriginalPath(repoConfig.repoId); - if (ofs.existsSync(cachePath) || ofs.existsSync(originalPath)) { - return true; - } - if (repoConfig.options.mode == "download") { - // if cache folder does not exist download and anonymize it - - const originalPath = repoUtils.getOriginalPath(repoConfig.repoId); - - await repoUtils.updateStatus(repoConfig, "downloading"); - await repoUtils.downloadOriginalRepo(repoConfig, originalPath); - await repoUtils.updateStatus(repoConfig, "ready"); - - // anonymize all the files - // await repoUtils.updateStatus(repoConfig, "anonymize"); - - // await anonymizeUtils.anonymizeFolder(originalPath, cachePath, repoConfig); - // await repoUtils.updateStatus(repoConfig, "anonymized"); - - // clean up - // await fs.rm(originalPath, { recursive: true, force: true }); - return true; - } else if (repoConfig.options.mode == "stream") { - // in stream mode only download the list of file from github - await repoUtils.updateStatus(repoConfig, "downloading"); - await fileUtils.getFileList({ repoConfig }); - await repoUtils.updateStatus(repoConfig, "ready"); - return true; - } - return false; -}; diff --git a/utils/repository.js b/utils/repository.js deleted file mode 100644 index 34aca34..0000000 --- a/utils/repository.js +++ /dev/null @@ -1,369 +0,0 @@ -const fs = require("fs").promises; -const ofs = require("fs"); -const path = require("path"); -const gh = require("parse-github-url"); -const { Octokit } = require("@octokit/rest"); -const extract = require("extract-zip"); - -const db = require("./database"); -const githubUtils = require("./github"); -const config = require("../config"); - -module.exports.getPath = (repoId) => { - return path.resolve(__dirname, "..", "repositories", repoId); -}; -module.exports.getOriginalPath = (repoId) => { - return path.resolve(__dirname, "..", "repositories", repoId, "original"); -}; -module.exports.getAnonymizedPath = (repoId) => { - return path.resolve(__dirname, "..", "repositories", repoId, "cache"); -}; - -module.exports.getConfig = async (repoId) => { - const repo = await db - .get() - .collection("anonymized_repositories") - .findOne( - { repoId }, - { - projection: { - // files: 1, - token: 1, - branch: 1, - commit: 1, - owner: 1, - fullName: 1, - repoId: 1, - terms: 1, - options: 1, - loc: 1, - status: 1, - lastView: 1, - }, - } - ); - - if (repo && repo.options.expirationDate) { - repo.options.expirationDate = new Date(repo.options.expirationDate); - repo.lastView = new Date(repo.lastView); - } - return repo; -}; - -module.exports.getRepoDetails = async (options) => { - const query = {}; - if (options.fullName) { - query.fullName = options.fullName; - } else if (options.repoConfig) { - query.fullName = options.repoConfig.fullName; - options.fullName = query.fullName; - } else if (options.owner && options.repo) { - query.fullName = `${options.owner}/${options.repo}`; - options.fullName = query.fullName; - } else { - throw "invalid_options"; - } - - if (options.force !== true) { - const repository = await db - .get("repositories") - .findOne(query, { projection: { readme: 0 } }); - if (repository && repository.id) return repository; - } - - try { - const repo = gh(options.fullName); - - const octokit = new Octokit({ auth: options.token }); - let ghRes = await octokit.repos.get({ - owner: repo.owner, - repo: repo.name, - }); - ghRes.data.fullName = ghRes.data.full_name; - if (ghRes.data.fullName != query.fullName) { - // repo renamed keep the old name - ghRes.data.fullName = query.fullName; - } - if (ghRes.data.has_pages) { - ghPageRes = await octokit.request("GET /repos/{owner}/{repo}/pages", { - owner: repo.owner, - repo: repo.name, - }); - ghRes.data.pageSource = ghPageRes.data.source; - } - - delete ghRes.data.full_name; - await db - .get("repositories") - .updateOne(query, { $set: ghRes.data }, { upsert: true }); - return ghRes.data; - } catch (error) { - console.log(query, error); - if (error.status == 401 && options.token != config.GITHUB_TOKEN) { - options.token = config.GITHUB_TOKEN; - return await module.exports.getRepoDetails(options); - } else if (error.status == 403) { - throw "repo_not_accessible"; - } - throw "repo_not_found"; - } -}; - -module.exports.downloadRepoZip = async (repoConfig, target) => { - const repo = gh(repoConfig.fullName); - - async function getZip(token) { - const octokit = new Octokit({ auth: token }); - return await octokit.request("GET /repos/{owner}/{repo}/zipball/{ref}", { - owner: repo.owner, - repo: repo.name, - ref: repoConfig.commit, - }); - } - let response = null; - try { - response = await getZip(await githubUtils.getToken(repoConfig)); - } catch (error) { - if (error.status == 401 && config.GITHUB_TOKEN) { - try { - response = await getZip(config.GITHUB_TOKEN); - } catch (error) { - throw "repo_not_accessible"; - } - } else { - throw "repo_not_accessible"; - } - } - - await fs.mkdir(path.dirname(target), { recursive: true }); - await fs.writeFile(target, Buffer.from(response.data), { - encoding: "binary", - }); -}; - -module.exports.updateStatus = async (repoConfig, status, errorMessage) => { - repoConfig.status = status; - repoConfig.errorMessage = errorMessage; - const update = { $set: { status } }; - if (!errorMessage) { - update["$unset"] = { errorMessage: "" }; - } else { - update["$set"].errorMessage = errorMessage; - } - - await db - .get("anonymized_repositories") - .updateOne({ repoId: repoConfig.repoId }, update); -}; - -module.exports.downloadOriginalRepo = async (repoConfig, destination) => { - const zipPath = path.join( - module.exports.getPath(repoConfig.repoId), - "content.zip" - ); - const destinationZip = destination + "_zip"; - - // download the repository and unzip it - await module.exports.downloadRepoZip(repoConfig, zipPath); - await extract(zipPath, { dir: destinationZip }); - - const folders = await fs.readdir(destinationZip); - if (ofs.existsSync(destination)) { - await fs.rm(destination, {force: true, recursive: true}) - } - fs.rename(path.join(destinationZip, folders[0]), destination); - await fs.rm(zipPath); - await fs.rm(destinationZip, { recursive: true }); -}; - -module.exports.getAnonymizedRepoDetails = async (repoId, user) => { - return db.get("anonymized_repositories").findOne( - { - repoId, - owner: user.username, - }, - { projection: { token: 0, files: 0, originalFiles: 0, loc: 0 } } - ); -}; - -module.exports.getRepoCommit = async (options) => { - let repoConfig = options.repoConfig; - if (!repoConfig) { - repoConfig = await module.exports.getConfig(options.repoId); - } - - if (repoConfig == null) { - throw "repo_not_found"; - } - - if (options.force !== true) { - const query = { fullName: repoConfig.fullName }; - query["branches." + repoConfig.branch + ""] = { $exists: true }; - const repository = await db - .get("repositories") - .findOne(query, { projection: { branches: 1 } }); - if ( - repository && - repository.branches && - repository.branches[repoConfig.branch] - ) - return repository.branches[repoConfig.branch].commit.sha; - } - const branches = await module.exports.getRepoBranches({ - repoConfig, - token: await githubUtils.getToken(repoConfig), - force: options.force, - }); - if (!branches[repoConfig.branch]) { - throw "branch_not_found"; - } - return branches[repoConfig.branch].commit.sha; -}; - -module.exports.getRepoBranches = async (options) => { - const query = {}; - if (options.fullName) { - query.fullName = options.fullName; - } else if (options.repoConfig) { - query.fullName = options.repoConfig.fullName; - options.fullName = query.fullName; - } else if (options.owner && options.repo) { - query.fullName = `${options.owner}/${options.repo}`; - options.fullName = query.fullName; - } else { - throw new Error("Invalid options"); - } - - if (options.force !== true) { - let repository = await db - .get("repositories") - .findOne(query, { projection: { branches: 1 } }); - if (repository && repository.branches) return repository.branches; - } - - try { - const repo = gh(options.fullName); - - const octokit = new Octokit({ auth: options.token }); - const data = await octokit.paginate(octokit.repos.listBranches, { - owner: repo.owner, - repo: repo.name, - per_page: 100, - }); - - const branches = {}; - for (let b of data) { - branches[b.name] = b; - } - await db - .get("repositories") - .updateOne(query, { $set: { branches } }, { upsert: true }); - return branches; - } catch (error) { - if (error.status == 401 && options.token != config.GITHUB_TOKEN) { - options.token = config.GITHUB_TOKEN; - return await module.exports.getRepoBranches(options); - } - if (error.status == 404) { - throw "repo_not_found"; - } - console.error(error); - throw "branches_not_found"; - } -}; - -module.exports.getRepoReadme = async (options) => { - const query = {}; - if (options.fullName) { - query.fullName = options.fullName; - } else if (options.repoConfig) { - query.fullName = options.repoConfig.fullName; - options.fullName = query.fullName; - } else if (options.owner && options.repo) { - query.fullName = `${options.owner}/${options.repo}`; - options.fullName = query.fullName; - } else { - throw new Error("Invalid options"); - } - - if (options.force !== true) { - let repository = await db - .get("repositories") - .findOne(query, { projection: { readme: 1 } }); - if (repository && repository.readme) return repository.readme; - } - - try { - const repo = gh(options.fullName); - - const octokit = new Octokit({ auth: options.token }); - const ghRes = await octokit.repos.getReadme({ - owner: repo.owner, - repo: repo.name, - }); - const readme = new Buffer.from(ghRes.data.content, "base64").toString( - "utf-8" - ); - await db - .get("repositories") - .updateOne(query, { $set: { readme } }, { upsert: true }); - return readme; - } catch (error) { - throw "readme_not_available"; - } -}; - -module.exports.updateAnonymizedRepository = async (repoConfig) => { - if (repoConfig.status == "updating") { - throw "repo_is_updating"; - } - repoConfig = await module.exports.getConfig(repoConfig.repoId); - if (repoConfig.status == "updating") { - throw "repo_is_updating"; - } - // check new commit - const commit = await module.exports.getRepoCommit({ - repoConfig, - force: true, - }); - if (commit == repoConfig.commit) { - console.log(`${repoConfig.repoId} is up to date`); - return true; - } - repoConfig.commit = commit; - console.log(`${repoConfig.repoId} will be updated to ${commit}`); - await module.exports.updateStatus(repoConfig, "updating"); - await db - .get("anonymized_repositories") - .updateOne({ repoId: repoConfig.repoId }, { $set: { commit } }); - await module.exports.removeRepository(repoConfig); - await githubUtils.downloadRepoAndAnonymize(repoConfig); - await module.exports.updateStatus(repoConfig, "ready"); -}; - -module.exports.removeRepository = async (repoConfig) => { - try { - if (ofs.existsSync(module.exports.getOriginalPath(repoConfig.repoId))) { - await fs.rm(module.exports.getOriginalPath(repoConfig.repoId), { - recursive: true, - force: true, - }); - } - if (ofs.existsSync(module.exports.getAnonymizedPath(repoConfig.repoId))) { - await fs.rm(module.exports.getAnonymizedPath(repoConfig.repoId), { - recursive: true, - force: true, - }); - } - - await db - .get("anonymized_repositories") - .updateOne( - { repoId: repoConfig.repoId }, - { $unset: { files: "", originalFiles: "", loc: "" } } - ); - } catch (error) { - console.log(error); - throw error; - } -};