diff --git a/bills/billsListMedia.ts b/bills/billsListMedia.ts index 9a8b69d..2ddd1e5 100644 --- a/bills/billsListMedia.ts +++ b/bills/billsListMedia.ts @@ -1,14 +1,14 @@ import { Request, Response } from "express"; +import ft from "file-type"; +import core from "file-type/core"; import fs from "fs-extra"; import path, { relative } from "path"; +import GenerateUrl from "../util/MediaUrlGen"; import GenerateThumbnail from "../util/generateThumbnail"; import MediaFile from "../util/interfaces/MediaFile"; import ListableChecker from "../util/listableChecker"; -import GenerateUrl from "../util/MediaUrlGen"; -import { PathToRoBillsFolder, PathToRoFolder } from "../util/pathGenerators"; +import { PathToRoBillsFolder } from "../util/pathGenerators"; import { FolderPaths } from "../util/serverInit"; -import core from "file-type/core"; -import ft from "file-type"; /** @description Bills will use the hierarchy of PDFs stored under the Job first, and then the Bills folder. */ export async function BillsListMedia(req: Request, res: Response) { @@ -35,6 +35,7 @@ export async function BillsListMedia(req: Request, res: Response) { ); return { type, + size: file.size, src: GenerateUrl([ FolderPaths.StaticPath, FolderPaths.JobsFolder, @@ -52,6 +53,7 @@ export async function BillsListMedia(req: Request, res: Response) { thumbnailHeight: 250, thumbnailWidth: 250, filename: file.filename, + relativeFilePath, }; }) ); @@ -83,9 +85,10 @@ export async function BillsListMedia(req: Request, res: Response) { const type: core.FileTypeResult | undefined = await ft.fromFile( relativeFilePath ); - + const fileSize = await fs.stat(relativeFilePath); return { type, + size: fileSize.size, src: GenerateUrl([ FolderPaths.StaticPath, FolderPaths.JobsFolder, @@ -103,6 +106,7 @@ export async function BillsListMedia(req: Request, res: Response) { thumbnailHeight: 250, thumbnailWidth: 250, filename: file.name, + relativeFilePath, }; }) ); diff --git a/jobs/jobsDeleteMedia.ts b/jobs/jobsDeleteMedia.ts index 6d79969..b371145 100644 --- a/jobs/jobsDeleteMedia.ts +++ b/jobs/jobsDeleteMedia.ts @@ -2,14 +2,10 @@ import { Request, Response } from "express"; import fs from "fs-extra"; import path from "path"; import { logger } from "../server"; -import GenerateThumbnail from "../util/generateThumbnail"; import MediaFile from "../util/interfaces/MediaFile"; import ListableChecker from "../util/listableChecker"; -import GenerateUrl from "../util/MediaUrlGen"; -import { PathToRoFolder } from "../util/pathGenerators"; -import { FolderPaths, JobRelativeFilePath } from "../util/serverInit"; -import ft from "file-type"; -import core from "file-type/core"; +import { PathToRoBillsFolder, PathToRoFolder } from "../util/pathGenerators"; +import { BillsRelativeFilePath, JobRelativeFilePath } from "../util/serverInit"; export async function JobsDeleteMedia(req: Request, res: Response) { const jobid: string = (req.body.jobid || "").trim(); @@ -18,12 +14,33 @@ export async function JobsDeleteMedia(req: Request, res: Response) { logger.debug("Deleteing media for job: " + PathToRoFolder(jobid)); let ret: MediaFile[]; try { - //We just uploaded files, we're going to send only those back. - await Promise.all( - files.map(async (filename) => { - const relativeFilePath: string = JobRelativeFilePath(jobid, filename); + // Setup lists for both file locations + const jobFileList: fs.Dirent[] = ( + await fs.readdir(PathToRoFolder(jobid), { + withFileTypes: true, + }) + ).filter((f) => f.isFile() && ListableChecker(f)); + const billFileList: fs.Dirent[] = ( + await fs.readdir(PathToRoBillsFolder(jobid), { + withFileTypes: true, + }) + ).filter((f) => f.isFile() && ListableChecker(f)); - await fs.remove(relativeFilePath); + // Check both list for the files that need to be deleted + await Promise.all( + jobFileList.map(async (file) => { + if (files.includes(path.parse(path.basename(file.name)).base)) { + // File is in the set of requested files. + await fs.remove(JobRelativeFilePath(jobid, file.name)); + } + }) + ); + await Promise.all( + billFileList.map(async (file) => { + if (files.includes(path.parse(path.basename(file.name)).base)) { + // File is in the set of requested files. + await fs.remove(BillsRelativeFilePath(jobid, file.name)); + } }) ); diff --git a/jobs/jobsDownloadMedia.ts b/jobs/jobsDownloadMedia.ts index 42973ad..ebd220a 100644 --- a/jobs/jobsDownloadMedia.ts +++ b/jobs/jobsDownloadMedia.ts @@ -1,16 +1,11 @@ import { Request, Response } from "express"; import fs from "fs-extra"; -import multer from "multer"; +import JSZip from "jszip"; import path from "path"; import { logger } from "../server"; -import GenerateThumbnail from "../util/generateThumbnail"; -import generateUniqueFilename from "../util/generateUniqueFilename"; -import { ConvertHeicFiles } from "../util/heicConverter"; -import { PathToRoFolder } from "../util/pathGenerators"; -import { JobsListMedia } from "./jobsListMedia"; -import JSZip from "jszip"; import ListableChecker from "../util/listableChecker"; -import { JobRelativeFilePath } from "../util/serverInit"; +import { PathToRoBillsFolder, PathToRoFolder } from "../util/pathGenerators"; +import { BillsRelativeFilePath, JobRelativeFilePath } from "../util/serverInit"; //param: files: string[] | array of filenames. export async function jobsDownloadMedia(req: Request, res: Response) { @@ -25,17 +20,21 @@ export async function jobsDownloadMedia(req: Request, res: Response) { logger.debug(`Generating batch download for Job ID ${jobid}`, files); //Prepare the zip file. - const filesList: fs.Dirent[] = ( + const jobFileList: fs.Dirent[] = ( await fs.readdir(PathToRoFolder(jobid), { withFileTypes: true, }) ).filter((f) => f.isFile() && ListableChecker(f)); + const billFileList: fs.Dirent[] = ( + await fs.readdir(PathToRoBillsFolder(jobid), { + withFileTypes: true, + }) + ).filter((f) => f.isFile() && ListableChecker(f)); if (files.length === 0) { //Get everything. - await Promise.all( - filesList.map(async (file) => { + jobFileList.map(async (file) => { //Do something async const fileOnDisk: Buffer = await fs.readFile( JobRelativeFilePath(jobid, file.name) @@ -43,10 +42,19 @@ export async function jobsDownloadMedia(req: Request, res: Response) { zip.file(path.parse(path.basename(file.name)).base, fileOnDisk); }) ); + await Promise.all( + billFileList.map(async (file) => { + //Do something async + const fileOnDisk: Buffer = await fs.readFile( + BillsRelativeFilePath(jobid, file.name) + ); + zip.file(path.parse(path.basename(file.name)).base, fileOnDisk); + }) + ); } else { //Get the files that are in the list and see which are requested. await Promise.all( - filesList.map(async (file) => { + jobFileList.map(async (file) => { if (files.includes(path.parse(path.basename(file.name)).base)) { // File is in the set of requested files. const fileOnDisk: Buffer = await fs.readFile( @@ -54,7 +62,18 @@ export async function jobsDownloadMedia(req: Request, res: Response) { ); zip.file(path.parse(path.basename(file.name)).base, fileOnDisk); } - }) + }), + ); + await Promise.all( + billFileList.map(async (file) => { + if (files.includes(path.parse(path.basename(file.name)).base)) { + // File is in the set of requested files. + const fileOnDisk: Buffer = await fs.readFile( + BillsRelativeFilePath(jobid, file.name) + ); + zip.file(path.parse(path.basename(file.name)).base, fileOnDisk); + } + }), ); } //Send it as a response to download it automatically. diff --git a/jobs/jobsListMedia.ts b/jobs/jobsListMedia.ts index 8240c20..a8d9f11 100644 --- a/jobs/jobsListMedia.ts +++ b/jobs/jobsListMedia.ts @@ -1,15 +1,14 @@ import { Request, Response } from "express"; +import ft from "file-type"; +import core from "file-type/core"; import fs from "fs-extra"; -import path from "path"; import { logger } from "../server"; +import GenerateUrl from "../util/MediaUrlGen"; import GenerateThumbnail from "../util/generateThumbnail"; import MediaFile from "../util/interfaces/MediaFile"; import ListableChecker from "../util/listableChecker"; -import GenerateUrl from "../util/MediaUrlGen"; import { PathToRoFolder } from "../util/pathGenerators"; import { FolderPaths, JobRelativeFilePath } from "../util/serverInit"; -import ft from "file-type"; -import core from "file-type/core"; export async function JobsListMedia(req: Request, res: Response) { const jobid: string = (req.body.jobid || "").trim(); diff --git a/jobs/jobsMoveMedia.ts b/jobs/jobsMoveMedia.ts index 6f90851..6776691 100644 --- a/jobs/jobsMoveMedia.ts +++ b/jobs/jobsMoveMedia.ts @@ -1,13 +1,11 @@ import { Request, Response } from "express"; import fs from "fs-extra"; import path from "path"; -import GenerateThumbnail from "../util/generateThumbnail"; -import GenerateUrl from "../util/MediaUrlGen"; -import { FolderPaths } from "../util/serverInit"; -import multer from "multer"; -import { JobsListMedia } from "./jobsListMedia"; -import { PathToRoFolder } from "../util/pathGenerators"; import { logger } from "../server"; +import ListableChecker from "../util/listableChecker"; +import { PathToRoBillsFolder, PathToRoFolder } from "../util/pathGenerators"; +import { FolderPaths } from "../util/serverInit"; +import { JobsListMedia } from "./jobsListMedia"; export async function JobsMoveMedia(req: Request, res: Response) { const jobid: string = (req.body.jobid || "").trim(); @@ -16,7 +14,6 @@ export async function JobsMoveMedia(req: Request, res: Response) { try { //Validate the request is valid and contains everything that it needs. - if (from_jobid === "") { res.status(400).json({ error: "from_jobid must be specified. " }); return; @@ -25,30 +22,81 @@ export async function JobsMoveMedia(req: Request, res: Response) { res.status(400).json({ error: "files must be specified. " }); return; } + + // Setup lists for both file locations + const jobFileList: string[] = ( + await fs.readdir(PathToRoFolder(from_jobid), { + withFileTypes: true, + }) + ) + .filter((f) => f.isFile() && ListableChecker(f)) + .map((dirent) => dirent.name); + const billFileList: string[] = ( + await fs.readdir(PathToRoBillsFolder(from_jobid), { + withFileTypes: true, + }) + ) + .filter((f) => f.isFile() && ListableChecker(f)) + .map((dirent) => dirent.name); + //Make sure the destination RO directory exists. await fs.ensureDir(PathToRoFolder(jobid)); logger.debug("Moving job based media.", { jobid, from_jobid, files }); const movingQueue: Promise[] = []; files.forEach((file) => { - movingQueue.push( - fs.move( - path.join(FolderPaths.Jobs, from_jobid, file), - path.join(FolderPaths.Jobs, jobid, file) - ) - ); + if (jobFileList.includes(file)) { + movingQueue.push( + fs.move( + path.join(FolderPaths.Jobs, from_jobid, file), + path.join(FolderPaths.Jobs, jobid, file) + ) + ); - movingQueue.push( - fs.move( - path.join( - FolderPaths.Jobs, - from_jobid, - FolderPaths.ThumbsSubDir, - file - ), - path.join(FolderPaths.Jobs, jobid, FolderPaths.ThumbsSubDir, file) - ) - ); + movingQueue.push( + fs.move( + path.join( + FolderPaths.Jobs, + from_jobid, + FolderPaths.ThumbsSubDir, + file + ), + path.join(FolderPaths.Jobs, jobid, FolderPaths.ThumbsSubDir, file) + ) + ); + } + if (billFileList.includes(file)) { + movingQueue.push( + fs.move( + path.join( + FolderPaths.Jobs, + from_jobid, + FolderPaths.BillsSubDir, + file + ), + path.join(FolderPaths.Jobs, jobid, FolderPaths.BillsSubDir, file) + ) + ); + + movingQueue.push( + fs.move( + path.join( + FolderPaths.Jobs, + from_jobid, + FolderPaths.BillsSubDir, + FolderPaths.ThumbsSubDir, + file + ), + path.join( + FolderPaths.Jobs, + jobid, + FolderPaths.BillsSubDir, + FolderPaths.ThumbsSubDir, + file + ) + ) + ); + } }); //Use AllSettled as it allows for individual moves to fail. diff --git a/package-lock.json b/package-lock.json index 0cc7805..0e567f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "bodyshop-media-server", - "version": "0.0.1", + "version": "1.0.10", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "bodyshop-media-server", - "version": "0.0.1", + "version": "1.0.10", "license": "UNLICENSED", "dependencies": { "axios": "^0.24.0", @@ -15,14 +15,15 @@ "cors": "^2.8.5", "dotenv": "10.0.0", "express": "^4.17.3", - "ffmpeg-static": "^5.0.0", "file-type": "^16.5.3", "fs-extra": "^10.1.0", "gm": "^1.23.1", "helmet": "^5.0.2", "image-thumbnail": "^1.0.14", + "jszip": "^3.10.0", "morgan": "^1.10.0", "multer": "^1.4.4", + "nocache": "^3.0.4", "response-time": "^2.3.2", "simple-thumbnail": "^1.6.5", "winston": "^3.7.2", @@ -43,7 +44,7 @@ "typescript": "^4.6.4" }, "engines": { - "node": "16.15.0" + "node": "^16.14.0" } }, "node_modules/@colors/colors": { @@ -89,20 +90,6 @@ "kuler": "^2.0.0" } }, - "node_modules/@derhuerst/http-basic": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@derhuerst/http-basic/-/http-basic-8.2.2.tgz", - "integrity": "sha512-ek065nW95mleLHo8vZ+ob7QTQPNOwDEjCe27BX2flme/UTu9z2mD1uRRPko38u7al4tTZADMtozpll8PQHAZgg==", - "dependencies": { - "caseless": "^0.12.0", - "concat-stream": "^1.6.2", - "http-response-object": "^3.0.1", - "parse-cache-control": "^1.0.1" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -354,38 +341,6 @@ "node": ">=0.4.0" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/agent-base/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/agent-base/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/ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -808,11 +763,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" - }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -1354,14 +1304,6 @@ "once": "^1.4.0" } }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "engines": { - "node": ">=6" - } - }, "node_modules/escape-goat": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", @@ -1464,21 +1406,6 @@ "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", "license": "MIT" }, - "node_modules/ffmpeg-static": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ffmpeg-static/-/ffmpeg-static-5.0.0.tgz", - "integrity": "sha512-z96jGVa8uCVMnyrTvbDZe0d5zbvIVQnfBN+vKDZoVK+ssYpfUJGEmo2DkuY43CA9Ytlsk+5ZVTFTqzvKw1gSaA==", - "hasInstallScript": true, - "dependencies": { - "@derhuerst/http-basic": "^8.2.0", - "env-paths": "^2.2.0", - "https-proxy-agent": "^5.0.0", - "progress": "^2.0.3" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/file-stream-rotator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/file-stream-rotator/-/file-stream-rotator-0.6.1.tgz", @@ -1871,52 +1798,6 @@ "node": ">= 0.8" } }, - "node_modules/http-response-object": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz", - "integrity": "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==", - "dependencies": { - "@types/node": "^10.0.3" - } - }, - "node_modules/http-response-object/node_modules/@types/node": { - "version": "10.17.60", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", - "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==" - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/https-proxy-agent/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/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1992,6 +1873,11 @@ "follow-redirects": "^1.14.0" } }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" + }, "node_modules/import-lazy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", @@ -2218,6 +2104,36 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/jszip/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/jszip/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "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/keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -2247,6 +2163,14 @@ "node": ">=8" } }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dependencies": { + "immediate": "~3.0.5" + } + }, "node_modules/logform": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/logform/-/logform-2.4.0.tgz", @@ -2484,6 +2408,14 @@ "node": ">= 0.6" } }, + "node_modules/nocache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-3.0.4.tgz", + "integrity": "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw==", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/node-abi": { "version": "2.30.1", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", @@ -2704,10 +2636,10 @@ "node": ">=8" } }, - "node_modules/parse-cache-control": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", - "integrity": "sha1-juqz5U+laSD+Fro493+iGqzC104=" + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, "node_modules/parseurl": { "version": "1.3.3", @@ -2793,14 +2725,6 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "license": "MIT" }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -3107,6 +3031,11 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "license": "ISC" }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -3967,17 +3896,6 @@ "kuler": "^2.0.0" } }, - "@derhuerst/http-basic": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@derhuerst/http-basic/-/http-basic-8.2.2.tgz", - "integrity": "sha512-ek065nW95mleLHo8vZ+ob7QTQPNOwDEjCe27BX2flme/UTu9z2mD1uRRPko38u7al4tTZADMtozpll8PQHAZgg==", - "requires": { - "caseless": "^0.12.0", - "concat-stream": "^1.6.2", - "http-response-object": "^3.0.1", - "parse-cache-control": "^1.0.1" - } - }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -4186,29 +4104,6 @@ "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "dev": true }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "requires": { - "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, "ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -4514,11 +4409,6 @@ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" - }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -4915,11 +4805,6 @@ "once": "^1.4.0" } }, - "env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==" - }, "escape-goat": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", @@ -4991,17 +4876,6 @@ "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" }, - "ffmpeg-static": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ffmpeg-static/-/ffmpeg-static-5.0.0.tgz", - "integrity": "sha512-z96jGVa8uCVMnyrTvbDZe0d5zbvIVQnfBN+vKDZoVK+ssYpfUJGEmo2DkuY43CA9Ytlsk+5ZVTFTqzvKw1gSaA==", - "requires": { - "@derhuerst/http-basic": "^8.2.0", - "env-paths": "^2.2.0", - "https-proxy-agent": "^5.0.0", - "progress": "^2.0.3" - } - }, "file-stream-rotator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/file-stream-rotator/-/file-stream-rotator-0.6.1.tgz", @@ -5276,45 +5150,6 @@ "toidentifier": "1.0.1" } }, - "http-response-object": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz", - "integrity": "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==", - "requires": { - "@types/node": "^10.0.3" - }, - "dependencies": { - "@types/node": { - "version": "10.17.60", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", - "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==" - } - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "requires": { - "agent-base": "6", - "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -5363,6 +5198,11 @@ } } }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" + }, "import-lazy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", @@ -5510,6 +5350,38 @@ "universalify": "^2.0.0" } }, + "jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "requires": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "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" + } + } + } + }, "keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -5533,6 +5405,14 @@ "package-json": "^6.3.0" } }, + "lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "requires": { + "immediate": "~3.0.5" + } + }, "logform": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/logform/-/logform-2.4.0.tgz", @@ -5698,6 +5578,11 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, + "nocache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-3.0.4.tgz", + "integrity": "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw==" + }, "node-abi": { "version": "2.30.1", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", @@ -5852,10 +5737,10 @@ "semver": "^6.2.0" } }, - "parse-cache-control": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", - "integrity": "sha1-juqz5U+laSD+Fro493+iGqzC104=" + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, "parseurl": { "version": "1.3.3", @@ -5909,11 +5794,6 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" - }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -6138,6 +6018,11 @@ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" + }, "setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", diff --git a/readme.md b/readme.md index 20604d0..ceabae6 100644 --- a/readme.md +++ b/readme.md @@ -28,43 +28,136 @@ reverse_proxy ims:8000 } ``` -## Sample Docker Compose file. +## Sample Docker Compose file ```docker version: '2' -services: - ims: + +services: + traefik: + container_name: traefik-ims + image: traefik:latest + restart: always + init: true + command: # CLI arguments + - --global.checkNewVersion=true + - --global.sendAnonymousUsage=false + - --pilot.dashboard=false + - --entrypoints.https.address=:10443 + - --entrypoints.https.forwardedHeaders.trustedIPs=173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/12,172.64.0.0/13,131.0.72.0/22,2400:cb00::/32,2606:4700::/32,2803:f800::/32,2405:b500::/32,2405:8100::/32,2a06:98c0::/29,2c0f:f248::/32 + - --log=true + - --log.level=ERROR # (Default: error) DEBUG, INFO, WARN, ERROR, FATAL, PANIC + - --providers.docker=true + - --providers.docker.exposedbydefault=false + - --providers.docker.network=t2_proxy + - --certificatesResolvers.dns-cloudflare.acme.email=cloudflare@thinkimex.com + - --certificatesResolvers.dns-cloudflare.acme.storage=/acme.json + - --certificatesResolvers.dns-cloudflare.acme.keyType=EC384 + - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.provider=cloudflare + - --certificatesresolvers.dns-cloudflare.acme.dnschallenge.resolvers=1.1.1.1:53,1.0.0.1:53,2606:4700:4700::1111:53,2606:4700:4700::1001:53 + - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.delayBeforeCheck=90 # To delay DNS check and reduce LE hitrate + networks: + t2_proxy: + ipv4_address: 192.168.90.254 ports: - - 8000:8000 + - target: 10443 + published: 10443 + protocol: tcp + mode: host + environment: + - TZ=America/Vancouver + - CF_API_EMAIL=cloudflare@thinkimex.com + - CF_DNS_API_TOKEN=b8BWRbkJckVK0IG6600Iq5AYx4HYZ7dLzDWUOZ2D volumes: - - ~:/root - - "C:\\IMS:/media" - #- "/Users/pfic/Desktop/ISM:/media" + - "/var/run/docker.sock:/var/run/docker.sock:ro" + - /home/imex/ims/traefik/acme/acme.json:/acme.json # cert location - you must touch this file and change permissions to 600 + labels: + - "traefik.enable=false" + cf-ddns: + container_name: cf-ddns + image: oznu/cloudflare-ddns:latest + networks: + - t2_proxy + restart: always + environment: + - API_KEY=b8BWRbkJckVK0IG6600Iq5AYx4HYZ7dLzDWUOZ2D + - ZONE=imexmedia.ca + - SUBDOMAIN=fastrack + - PROXIED=false + - RRTYPE=A + - DELETE_ON_STOP=false + - DNS_SERVER=1.1.1.1 + labels: + - "traefik.enable=false" + ims: + container_name: ims + networks: + - t2_proxy + volumes: + - /mnt/ims:/media environment: - MEDIA_PATH=/media - - DUPLICATE_BILL_TO_VENDOR=false - - IMS_TOKEN=ThisIsAnImEXSecretTokenToBeSent + - DUPLICATE_BILL_TO_VENDOR=true + - IMS_TOKEN=6Q9pjF5wFQ2grGyom2rvRPXnkKZDA3BvfNK2J5qQXVuyxTFhjHVX6zwWeYDw3GLAk + - CONVERT_QUALITY=0.8 + - KEEP_CONVERTED_ORIGINALS=TRUE image: imexonline/media-server:latest - #image: imexonline/media-server:beta - restart: unless-stopped + restart: always + labels: + - "traefik.enable=true" + # HTTP Routers + - "traefik.http.routers.ims-rtr.entrypoints=https" + - "traefik.http.routers.ims-rtr.rule=Host(`fastrack.imexmedia.ca`)" + - "traefik.http.routers.ims-rtr.tls.certresolver=dns-cloudflare" + ## HTTP Services + - "traefik.http.routers.ims-rtr.service=ims-svc" + - "traefik.http.services.ims-svc.loadbalancer.server.port=8000" + dozzle: + container_name: logs + image: amir20/dozzle:latest + restart: always + networks: + - t2_proxy + ports: + - "8080:8080" + security_opt: + - no-new-privileges:true + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + environment: + DOZZLE_LEVEL: info + DOZZLE_TAILSIZE: 300 + DOZZLE_FILTER: "status=running" + DOZZLE_NO_ANALYTICS: "true" watchtower: + container_name: watchtower-ims image: containrrr/watchtower + networks: + - t2_proxy volumes: - /var/run/docker.sock:/var/run/docker.sock - - /root/.docker/config.json:/config.json - command: --interval 3600 - caddy: - image: caddy/caddy:latest - container_name: caddy-service - restart: unless-stopped - ports: - - "80:80" - - "443:443" - volumes: - - $PWD/Caddyfile:/etc/caddy/Caddyfile - - caddy_data:/data - - caddy_config:/config -volumes: - caddy_data: - caddy_config: + environment: + - TZ=America/Vancouver + - WATCHTOWER_CLEANUP=true + - WATCHTOWER_REMOVE_VOLUMES=true + - WATCHTOWER_INCLUDE_STOPPED=true + - WATCHTOWER_INCLUDE_RESTARTING=true + - WATCHTOWER_NO_STARTUP_MESSAGE=false + - WATCHTOWER_REVIVE_STOPPED=true + - WATCHTOWER_ROLLING_RESTART=true + - WATCHTOWER_TIMEOUT=60s + - WATCHTOWER_POLL_INTERVAL=3600 + restart: unless-stopped + labels: + - "traefik.enable=false" + +networks: + t2_proxy: + name: t2_proxy + driver: bridge + ipam: + config: + - subnet: 192.168.90.0/24 ``` diff --git a/util/serverInit.ts b/util/serverInit.ts index 4fc0419..8e21961 100644 --- a/util/serverInit.ts +++ b/util/serverInit.ts @@ -1,7 +1,7 @@ import fs = require("fs-extra"); -import path, { resolve } from "path"; import dotenv from "dotenv"; import os from "os"; +import path, { resolve } from "path"; import { logger } from "../server"; dotenv.config({ @@ -31,6 +31,9 @@ export const AssetPaths = { export function JobRelativeFilePath(jobid: string, filename: string) { return path.join(FolderPaths.Jobs, jobid, filename); } +export function BillsRelativeFilePath(jobid: string, filename: string) { + return path.join(FolderPaths.Jobs, jobid, FolderPaths.BillsSubDir, filename); +} export default function InitServer() { logger.info(`Ensuring Root media path exists: ${FolderPaths.Root}`); fs.ensureDirSync(FolderPaths.Root); diff --git a/yarn.lock b/yarn.lock index c7725e6..4d82ddb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -869,7 +869,7 @@ fs-extra@^10.1.0: fsevents@~2.3.2: version "2.3.2" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== function-bind@^1.1.1: @@ -1054,7 +1054,7 @@ image-thumbnail@^1.0.14: immediate@~3.0.5: version "3.0.6" - resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" + resolved "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz" integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== import-lazy@^2.1.0: @@ -1203,9 +1203,9 @@ jsonfile@^6.0.1: graceful-fs "^4.1.6" jszip@^3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.0.tgz#faf3db2b4b8515425e34effcdbb086750a346061" - integrity sha512-LDfVtOLtOxb9RXkYOwPyNBTQDL4eUbqahtoY6x07GiDJHwSYvn8sHHIw8wINImV3MqbMNve2gSuM1DDqEKk09Q== + version "3.10.1" + resolved "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz" + integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g== dependencies: lie "~3.3.0" pako "~1.0.2" @@ -1233,7 +1233,7 @@ latest-version@^5.1.0: lie@~3.3.0: version "3.3.0" - resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a" + resolved "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz" integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== dependencies: immediate "~3.0.5" @@ -1404,7 +1404,7 @@ negotiator@0.6.3: nocache@^3.0.4: version "3.0.4" - resolved "https://registry.yarnpkg.com/nocache/-/nocache-3.0.4.tgz#5b37a56ec6e09fc7d401dceaed2eab40c8bfdf79" + resolved "https://registry.npmjs.org/nocache/-/nocache-3.0.4.tgz" integrity sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw== node-abi@^2.21.0: @@ -1532,7 +1532,7 @@ package-json@^6.3.0: pako@~1.0.2: version "1.0.11" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + resolved "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== parseurl@~1.3.3: @@ -1666,7 +1666,7 @@ readable-stream@1.1.x: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@~2.3.6: +readable-stream@^2.0.6, readable-stream@^2.2.2: version "2.3.7" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -1688,6 +1688,19 @@ readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@~2.3.6: + version "2.3.8" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + 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" + readable-web-to-node-stream@^3.0.0: version "3.0.2" resolved "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz" @@ -1811,7 +1824,7 @@ set-blocking@~2.0.0: setimmediate@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + resolved "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== setprototypeof@1.2.0: