From a3cbce61901651d526d9575f3c4bb2aafc21c40f Mon Sep 17 00:00:00 2001 From: Mikael Finstad Date: Sun, 15 Oct 2023 23:36:54 +0800 Subject: [PATCH] implement http api #980 #868 - add closeCurrentFile action - allow export confirm also via action - upgrade electron --- README.md | 4 +- api.md | 48 +++ cli.md | 44 ++- issues.md | 2 +- package.json | 5 +- public/electron.js | 32 +- public/httpServer.js | 50 +++ src/App.jsx | 45 ++- src/components/KeyboardShortcuts.jsx | 4 + yarn.lock | 505 +++++++++++++++++++++++++-- 10 files changed, 676 insertions(+), 63 deletions(-) create mode 100644 api.md create mode 100644 public/httpServer.js diff --git a/README.md b/README.md index 3d809a11..7edcd27a 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ The main feature is lossless trimming and cutting of video and audio files, whic - Black scene detection, silent audio detection, and scene change detection - Divide timeline into segments with length L or into N segments or even randomized segments! - Speed up / slow down video or audio file ([changing FPS](https://github.com/mifi/lossless-cut/issues/1712)) -- [Basic CLI support](cli.md) +- Basic [CLI](cli.md) and [HTTP API](api.md) ## Example lossless use cases @@ -167,7 +167,7 @@ Unsupported files can still be converted to a supported format/codec from the `F ## [Import / export](import-export.md) -## [Command line interface (CLI) / API](cli.md) +## [Command line interface (CLI)](cli.md) & [HTTP API](api.md) ## [Known issues, limitations, troubleshooting, FAQ](issues.md) diff --git a/api.md b/api.md new file mode 100644 index 00000000..c76e2666 --- /dev/null +++ b/api.md @@ -0,0 +1,48 @@ +# HTTP API + +LosslessCut can be controlled via a HTTP API, if it is being run with the command line option `--http-api`. See also [CLI](./cli.md). **Note that the HTTP API is experimental and may change at any time.** + +## Programmatically opening a file + +This must be done with [the CLI](./cli.md). + +## Enabling the API + +```bash +LosslessCut --http-api +``` + +## API endpoints + +### `POST /api/shortcuts/action` + +Execute a keyboard shortcut `action`, similar to the `--keyboard-action` CLI option. This is different from the CLI in that most of the actions will wait for the action to finish before responding to the HTTP request (but not all). + +#### [Available keyboard actions](./cli.md#available-keyboard-actions) + +#### Example + +Export the currently opened file: + +```bash +curl -X POST http://localhost:8080/api/shortcuts/export +``` + +### Batch example + +Start the main LosslessCut in one terminal with the HTTP API enabled: + +```bash +LosslessCut --http-api +``` + +Then run the script in a different terminal: + +```bash +for PROJECT in /path/to/folder/with/projects/*.llc + LosslessCut $PROJECT + sleep 5 # wait for the file to open + curl -X POST http://localhost:8080/api/shortcuts/export + curl -X POST http://localhost:8080/api/shortcuts/closeCurrentFile +done +``` diff --git a/cli.md b/cli.md index 8a80bec7..42fe4d3b 100644 --- a/cli.md +++ b/cli.md @@ -1,9 +1,17 @@ # Command line interface (CLI) -LosslessCut has limited support for automation through the CLI. Note that these examples assume that you have set up LosslessCut in your `PATH` environment. Alternatively you can run it like this: +LosslessCut has basic support for automation through the CLI. See also [HTTP API](./api.md). + +```bash +LosslessCut [options] [files] +``` + +Note that these examples assume that you have set up the LosslessCut executable to be available in your `PATH` (command line environment). Alternatively you can run it like this: + ```bash # First navigate to the folder containing the LosslessCut app cd /path/to/directory/containing/app +# Then run it # On Linux: ./LosslessCut arguments # On Windows: @@ -18,36 +26,42 @@ LosslessCut file1.mp4 file2.mkv ``` ## Override settings (experimental) -See [available settings](https://github.com/mifi/lossless-cut/blob/master/public/configStore.js). Note that this is subject to change in newer versions. ⚠️ If you specify incorrect values it could corrupt your configuration file. You may use JSON or JSON5: +See [available settings](https://github.com/mifi/lossless-cut/blob/master/public/configStore.js). Note that this is subject to change in newer versions. ⚠️ If you specify incorrect values it could corrupt your configuration file. You may use JSON or JSON5. Example: ```bash LosslessCut --settings-json '{captureFormat:"jpeg", "keyframeCut":true}' ``` +## Other options + +- `--locales-path` Customise path to locales (useful for [translators](./translation.md)). +- `--disable-networking` Turn off all network requests. +- `--http-api` Start the [HTTP server with an API](./api.md) to control LosslessCut, optionally specifying a port (default `8080`). +- `--keyboard-action` Run a keyboard action (see below.) + ## Controlling a running instance (experimental) -If you have the "Allow multiple instances" setting enabled, you can control a running instance of LosslessCut from the outside, using for example a command line. You do this by issuing messages to it through the `LosslessCut` command. Currently only keyboard actions are supported. *Note that this is considered experimental and the API may change at any time.* +If you have the "Allow multiple instances" setting enabled, you can control a running instance of LosslessCut from the outside, using for example a command line. You do this by issuing messages to it through the `LosslessCut` command. Currently only keyboard actions are supported, and you can open files. *Note that this is considered experimental and the API may change at any time.* ### Keyboard actions, `--keyboard-action` -Simulate a keyboard press action. The available action names can be found in the "Keyboard shortcuts" dialog (Note: you don't have to bind them to any key). +Simulate a keyboard press action in an already running instance of LosslessCut. Note that the command will return immediately, so if you want to run multiple actions in a sequence, you have to `sleep` for a few seconds between the commands. Alternatively if you want to wait until an action has finished processing, you can use the [HTTP API](./api.md) instead. Note that the HTTP API does not support opening files, and it is currently not possible to wait for a file to have finished opening. + +### Available keyboard actions + +A list of the available action names can be found in the "Keyboard shortcuts" dialog in the app. Note that you don't have to bind them to any key before using them. Example: ```bash +# Open a file in an already running instance +LosslessCut file.mp4 +sleep 3 # hopefully the file has loaded by now # Export the currently opened file LosslessCut --keyboard-action export ``` -#### Batch example - -Note that there is no synchronization, and the action will exit immediately, regardless of how long the action takes. This means that you will have to sleep between multiple actions. +### Open files in running instance ```bash -for PROJECT in /path/to/folder/with/projects/*.llc - LosslessCut $PROJECT - sleep 5 # wait for the file to open - LosslessCut --keyboard-action export - sleep 10 # hopefully done by then - LosslessCut --keyboard-action quit -done -``` \ No newline at end of file +LosslessCut file1.mp4 file2.mkv +``` diff --git a/issues.md b/issues.md index 298e4461..00e3e4c1 100644 --- a/issues.md +++ b/issues.md @@ -3,7 +3,7 @@ - **Can LosslessCut crop, resize, stretch, mirror, overlay text/images, watermark, blur, redact, re-encode, create GIF, slideshow, burn subtitles, color grading, fade/transition between video clips, fade/combine/mix/merge audio tracks or change audio volume?** - No, these are all lossy operations (meaning you *have* to re-encode the file), but in the future I may start to implement such features. [See this issue for more information.](https://github.com/mifi/lossless-cut/issues/372) - Can LosslessCut be batched/automated using a CLI or API? - - While it was never designed for advanced batching/automation, it does have a [basic CLI](./cli.md), and there are a few feature requests regarding this: [#980](https://github.com/mifi/lossless-cut/issues/980) [#868](https://github.com/mifi/lossless-cut/issues/868). + - While it was never designed for advanced batching/automation, it does have a [basic CLI and a HTTP API](./cli.md), and there are a few feature requests regarding this: [#980](https://github.com/mifi/lossless-cut/issues/980) [#868](https://github.com/mifi/lossless-cut/issues/868). - Is there a keyboard shortcut to do X? - First check the Keyboard shortcuts dialog. If you cannot find your shortcut there, [see this issue.](https://github.com/mifi/lossless-cut/issues/254) - When will you implement feature X? diff --git a/package.json b/package.json index 02d9b5ad..60399570 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "cross-env": "^7.0.3", "csv-parse": "^4.15.3", "csv-stringify": "^5.6.2", - "electron": "^26.2.4", + "electron": "^27.0.0", "electron-builder": "^24.6.3", "electron-builder-notarize": "^1.5.1", "electron-devtools-installer": "^3.2.0", @@ -105,6 +105,8 @@ "electron-store": "5.1.1", "electron-unhandled": "^4.0.1", "execa": "5", + "express": "^4.18.2", + "express-async-handler": "^1.2.0", "file-type": "16", "file-url": "^3.0.0", "fs-extra": "^8.1.0", @@ -114,6 +116,7 @@ "json5": "^2.2.2", "lodash": "^4.17.19", "mime-types": "^2.1.14", + "morgan": "^1.10.0", "semver": "^7.5.2", "string-to-stream": "^1.1.1", "strtok3": "^6.0.0", diff --git a/public/electron.js b/public/electron.js index 3c5c9638..16c10229 100644 --- a/public/electron.js +++ b/public/electron.js @@ -16,6 +16,7 @@ const menu = require('./menu'); const configStore = require('./configStore'); const { frontendBuildDir } = require('./util'); const attachContextMenu = require('./contextMenu'); +const HttpServer = require('./httpServer'); const { checkNewVersion } = require('./update-checker'); @@ -62,6 +63,22 @@ let disableNetworking; const openFiles = (paths) => mainWindow.webContents.send('openFiles', paths); +let apiKeyboardActionRequestsId = 0; +const apiKeyboardActionRequests = new Map(); + +async function sendApiKeyboardAction(action) { + try { + const id = apiKeyboardActionRequestsId; + apiKeyboardActionRequestsId += 1; + mainWindow.webContents.send('apiKeyboardAction', { id, action }); + await new Promise((resolve) => { + apiKeyboardActionRequests.set(id, resolve); + }); + } catch (err) { + logger.error('sendApiKeyboardAction', err); + } +} + // https://github.com/electron/electron/issues/526#issuecomment-563010533 function getSizeOptions() { const bounds = configStore.get('windowBounds'); @@ -205,7 +222,7 @@ function initApp() { logger.info('second-instance', argv2); if (argv2._ && argv2._.length > 0) openFilesEventually(argv2._); - else if (argv2.keyboardAction) mainWindow.webContents.send('apiKeyboardAction', argv2.keyboardAction); + else if (argv2.keyboardAction) sendApiKeyboardAction(argv2.keyboardAction); }); // Quit when all windows are closed. @@ -249,6 +266,10 @@ function initApp() { } await shell.trashItem(path); }); + + ipcMain.on('apiKeyboardActionResponse', (e, { id }) => { + apiKeyboardActionRequests.get(id)?.(); + }); } @@ -290,6 +311,15 @@ const readyPromise = app.whenReady(); }); } + const { httpApi } = argv; + + if (httpApi != null) { + const port = typeof httpApi === 'number' ? httpApi : 8080; + const { startHttpServer } = HttpServer({ port, onKeyboardAction: sendApiKeyboardAction }); + await startHttpServer(); + } + + if (isDev) { const { default: installExtension, REACT_DEVELOPER_TOOLS } = require('electron-devtools-installer'); // eslint-disable-line global-require,import/no-extraneous-dependencies diff --git a/public/httpServer.js b/public/httpServer.js new file mode 100644 index 00000000..70fa8832 --- /dev/null +++ b/public/httpServer.js @@ -0,0 +1,50 @@ +const express = require('express'); +const morgan = require('morgan'); +const http = require('http'); +const asyncHandler = require('express-async-handler'); +const { homepage } = require('./constants'); + + +const logger = require('./logger'); + + +module.exports = ({ port, onKeyboardAction }) => { + const app = express(); + + // https://expressjs.com/en/resources/middleware/morgan.html + const morganFormat = ':remote-addr :method :url HTTP/:http-version :status - :response-time ms'; + // https://stackoverflow.com/questions/27906551/node-js-logging-use-morgan-and-winston + app.use(morgan(morganFormat, { + stream: { write: (message) => logger.info(message.trim()) }, + })); + + const apiRouter = express.Router(); + + app.get('/', (req, res) => res.send(`See ${homepage}`)); + + app.use('/api', apiRouter); + + apiRouter.post('/shortcuts/:action', express.json(), asyncHandler(async (req, res) => { + await onKeyboardAction(req.params.action); + res.end(); + })); + + const server = http.createServer(app); + + server.on('error', (err) => logger.error('http server error', err)); + + const startHttpServer = async () => new Promise((resolve, reject) => { + // force ipv4 + const host = '127.0.0.1'; + server.listen(port, host, () => { + logger.info('HTTP API listening on', `http://${host}:${port}/`); + resolve(); + }); + + server.once('error', reject); + }); + + return { + startHttpServer, + }; +}; diff --git a/src/App.jsx b/src/App.jsx index 6e68c202..8fa62330 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1139,6 +1139,15 @@ const App = memo(() => { return; } + if (segmentsToExport.length < 1) { + return; + } + + if (haveInvalidSegs) { + errorToast(i18n.t('Start time must be before end time')); + return; + } + setStreamsSelectorShown(false); setExportConfirmVisible(false); @@ -1267,19 +1276,17 @@ const App = memo(() => { setWorking(); setCutProgress(); } - }, [numStreamsToCopy, setWorking, segmentsToChaptersOnly, outSegTemplateOrDefault, generateOutSegFileNames, segmentsToExport, getOutSegError, cutMultiple, outputDir, customOutDir, fileFormat, duration, isRotationSet, effectiveRotation, copyFileStreams, allFilesMeta, keyframeCut, shortestFlag, ffmpegExperimental, preserveMovData, preserveMetadataOnMerge, movFastStart, avoidNegativeTs, customTagsByFile, paramsByStreamId, detectedFps, willMerge, enableOverwriteOutput, exportConfirmEnabled, mainFileFormatData, mainStreams, exportExtraStreams, areWeCutting, mergedOutFilePath, hideAllNotifications, cleanupChoices, cleanupFilesWithDialog, selectedSegmentsOrInverse, segmentsToChapters, invertCutSegments, autoConcatCutSegments, autoDeleteMergedSegments, nonCopiedExtraStreams, filePath, handleExportFailed]); + }, [numStreamsToCopy, segmentsToExport, haveInvalidSegs, setWorking, segmentsToChaptersOnly, outSegTemplateOrDefault, generateOutSegFileNames, getOutSegError, cutMultiple, outputDir, customOutDir, fileFormat, duration, isRotationSet, effectiveRotation, copyFileStreams, allFilesMeta, keyframeCut, shortestFlag, ffmpegExperimental, preserveMovData, preserveMetadataOnMerge, movFastStart, avoidNegativeTs, customTagsByFile, paramsByStreamId, detectedFps, willMerge, enableOverwriteOutput, exportConfirmEnabled, mainFileFormatData, mainStreams, exportExtraStreams, areWeCutting, mergedOutFilePath, hideAllNotifications, cleanupChoices.cleanupAfterExport, cleanupFilesWithDialog, selectedSegmentsOrInverse, segmentsToChapters, invertCutSegments, autoConcatCutSegments, autoDeleteMergedSegments, nonCopiedExtraStreams, filePath, handleExportFailed]); const onExportPress = useCallback(async () => { - if (!filePath || workingRef.current || segmentsToExport.length < 1) return; + if (!filePath) return; - if (haveInvalidSegs) { - errorToast(i18n.t('Start time must be before end time')); - return; + if (!exportConfirmEnabled || exportConfirmVisible) { + await onExportConfirm(); + } else { + setExportConfirmVisible(true); } - - if (exportConfirmEnabled) setExportConfirmVisible(true); - else await onExportConfirm(); - }, [filePath, haveInvalidSegs, segmentsToExport, exportConfirmEnabled, onExportConfirm]); + }, [filePath, exportConfirmEnabled, exportConfirmVisible, onExportConfirm]); const captureSnapshot = useCallback(async () => { if (!filePath) return; @@ -1997,10 +2004,11 @@ const App = memo(() => { copySegmentsToClipboard, reloadFile: () => setCacheBuster((v) => v + 1), quit: () => quitApp(), + closeCurrentFile: () => { closeFileWithConfirm(); }, }; return mainActions[action]; - }, [addSegment, alignSegmentTimesToKeyframes, askSetStartTimeOffset, batchFileJump, batchOpenSelectedFile, captureSnapshot, captureSnapshotAsCoverArt, changePlaybackRate, cleanupFilesDialog, clearSegments, closeBatch, combineOverlappingSegments, combineSelectedSegments, concatCurrentBatch, convertFormatBatch, copySegmentsToClipboard, createFixedDurationSegments, createNumSegments, createRandomSegments, currentSegIndexSafe, cutSegmentsHistory, deselectAllSegments, duplicateCurrentSegment, extractAllStreams, extractCurrentSegmentFramesAsImages, extractSelectedSegmentsFramesAsImages, fillSegmentsGaps, goToTimecode, increaseRotation, invertAllSegments, invertSelectedSegments, jumpCutEnd, jumpCutStart, jumpSeg, jumpTimelineEnd, jumpTimelineStart, keyboardNormalSeekSpeed, keyboardSeekAccFactor, onExportPress, onLabelSegment, pause, play, removeCutSegment, removeSelectedSegments, reorderSegsByStartTime, seekClosestKeyframe, seekRel, seekRelPercent, selectAllSegments, selectOnlyCurrentSegment, setCutEnd, setCutStart, setPlaybackVolume, shiftAllSegmentTimes, shortStep, shuffleSegments, splitCurrentSegment, timelineToggleComfortZoom, toggleCaptureFormat, toggleCurrentSegmentSelected, toggleKeyframeCut, toggleLastCommands, toggleLoopSelectedSegments, togglePlay, toggleSegmentsList, toggleStreamsSelector, toggleStripAudio, tryFixInvalidDuration, userHtml5ifyCurrentFile, zoomRel]); + }, [addSegment, alignSegmentTimesToKeyframes, askSetStartTimeOffset, batchFileJump, batchOpenSelectedFile, captureSnapshot, captureSnapshotAsCoverArt, changePlaybackRate, cleanupFilesDialog, clearSegments, closeBatch, closeFileWithConfirm, combineOverlappingSegments, combineSelectedSegments, concatCurrentBatch, convertFormatBatch, copySegmentsToClipboard, createFixedDurationSegments, createNumSegments, createRandomSegments, currentSegIndexSafe, cutSegmentsHistory, deselectAllSegments, duplicateCurrentSegment, extractAllStreams, extractCurrentSegmentFramesAsImages, extractSelectedSegmentsFramesAsImages, fillSegmentsGaps, goToTimecode, increaseRotation, invertAllSegments, invertSelectedSegments, jumpCutEnd, jumpCutStart, jumpSeg, jumpTimelineEnd, jumpTimelineStart, keyboardNormalSeekSpeed, keyboardSeekAccFactor, onExportPress, onLabelSegment, pause, play, removeCutSegment, removeSelectedSegments, reorderSegsByStartTime, seekClosestKeyframe, seekRel, seekRelPercent, selectAllSegments, selectOnlyCurrentSegment, setCutEnd, setCutStart, setPlaybackVolume, shiftAllSegmentTimes, shortStep, shuffleSegments, splitCurrentSegment, timelineToggleComfortZoom, toggleCaptureFormat, toggleCurrentSegmentSelected, toggleKeyframeCut, toggleLastCommands, toggleLoopSelectedSegments, togglePlay, toggleSegmentsList, toggleStreamsSelector, toggleStripAudio, tryFixInvalidDuration, userHtml5ifyCurrentFile, zoomRel]); const onKeyPress = useCallback(({ action, keyup }) => { function tryMainActions() { @@ -2153,18 +2161,21 @@ const App = memo(() => { } } - function tryKeyboardAction(action) { - const fn = getKeyboardAction({ action }); - if (!fn) { - console.error('Action not found:', action); - return; + async function tryApiKeyboardAction(event, { id, action }) { + console.log('API keyboard action:', action); + try { + const fn = getKeyboardAction({ action }); + if (!fn) throw new Error(`Action not found: ${action}`); + await fn(); + } finally { + // todo correlation ids + event.sender.send('apiKeyboardActionResponse', { id }); } - fn(); } const actions = { openFiles: (event, filePaths) => { userOpenFiles(filePaths.map(resolvePathIfNeeded)); }, - apiKeyboardAction: (event, action) => tryKeyboardAction(action), + apiKeyboardAction: tryApiKeyboardAction, openFilesDialog, closeCurrentFile: () => { closeFileWithConfirm(); }, closeBatchFiles: () => { closeBatch(); }, diff --git a/src/components/KeyboardShortcuts.jsx b/src/components/KeyboardShortcuts.jsx index 16e833ad..9e689014 100644 --- a/src/components/KeyboardShortcuts.jsx +++ b/src/components/KeyboardShortcuts.jsx @@ -504,6 +504,10 @@ const KeyboardShortcuts = memo(({ name: t('Close current screen'), category: otherCategory, }, + closeCurrentFile: { + name: t('Close current file'), + category: otherCategory, + }, quit: { name: t('Quit LosslessCut'), category: otherCategory, diff --git a/yarn.lock b/yarn.lock index 330f07f1..48279e52 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1730,6 +1730,16 @@ __metadata: languageName: node linkType: hard +"accepts@npm:~1.3.8": + version: 1.3.8 + resolution: "accepts@npm:1.3.8" + dependencies: + mime-types: ~2.1.34 + negotiator: 0.6.3 + checksum: 50c43d32e7b50285ebe84b613ee4a3aa426715a7d131b65b786e2ead0fd76b6b60091b9916d3478a75f11f162628a2139991b6c03ab3f1d9ab7c86075dc8eab4 + languageName: node + linkType: hard + "acorn-jsx@npm:^5.3.1": version: 5.3.2 resolution: "acorn-jsx@npm:5.3.2" @@ -1997,6 +2007,13 @@ __metadata: languageName: node linkType: hard +"array-flatten@npm:1.1.1": + version: 1.1.1 + resolution: "array-flatten@npm:1.1.1" + checksum: a9925bf3512d9dce202112965de90c222cd59a4fbfce68a0951d25d965cf44642931f40aac72309c41f12df19afa010ecadceb07cfff9ccc1621e99d89ab5f3b + languageName: node + linkType: hard + "array-includes@npm:^3.1.3, array-includes@npm:^3.1.4": version: 3.1.4 resolution: "array-includes@npm:3.1.4" @@ -2156,6 +2173,15 @@ __metadata: languageName: node linkType: hard +"basic-auth@npm:~2.0.1": + version: 2.0.1 + resolution: "basic-auth@npm:2.0.1" + dependencies: + safe-buffer: 5.1.2 + checksum: 3419b805d5dfc518f3a05dcf42aa53aa9ce820e50b6df5097f9e186322e1bc733c36722b624802cd37e791035aa73b828ed814d8362333d42d7f5cd04d7a5e48 + languageName: node + linkType: hard + "bl@npm:^4.0.3": version: 4.1.0 resolution: "bl@npm:4.1.0" @@ -2183,6 +2209,26 @@ __metadata: languageName: node linkType: hard +"body-parser@npm:1.20.1": + version: 1.20.1 + resolution: "body-parser@npm:1.20.1" + dependencies: + bytes: 3.1.2 + content-type: ~1.0.4 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.1 + type-is: ~1.6.18 + unpipe: 1.0.0 + checksum: f1050dbac3bede6a78f0b87947a8d548ce43f91ccc718a50dd774f3c81f2d8b04693e52acf62659fad23101827dd318da1fb1363444ff9a8482b886a3e4a5266 + languageName: node + linkType: hard + "boolbase@npm:^1.0.0": version: 1.0.0 resolution: "boolbase@npm:1.0.0" @@ -2351,6 +2397,13 @@ __metadata: languageName: node linkType: hard +"bytes@npm:3.1.2": + version: 3.1.2 + resolution: "bytes@npm:3.1.2" + checksum: e4bcd3948d289c5127591fbedf10c0b639ccbf00243504e4e127374a15c3bc8eed0d28d4aaab08ff6f1cf2abc0cce6ba3085ed32f4f90e82a5683ce0014e1b6e + languageName: node + linkType: hard + "cac@npm:^6.7.14": version: 6.7.14 resolution: "cac@npm:6.7.14" @@ -2903,6 +2956,22 @@ __metadata: languageName: node linkType: hard +"content-disposition@npm:0.5.4": + version: 0.5.4 + resolution: "content-disposition@npm:0.5.4" + dependencies: + safe-buffer: 5.2.1 + checksum: afb9d545e296a5171d7574fcad634b2fdf698875f4006a9dd04a3e1333880c5c0c98d47b560d01216fb6505a54a2ba6a843ee3a02ec86d7e911e8315255f56c3 + languageName: node + linkType: hard + +"content-type@npm:~1.0.4": + version: 1.0.5 + resolution: "content-type@npm:1.0.5" + checksum: 566271e0a251642254cde0f845f9dd4f9856e52d988f4eb0d0dcffbb7a1f8ec98de7a5215fc628f3bce30fe2fb6fd2bc064b562d721658c59b544e2d34ea2766 + languageName: node + linkType: hard + "convert-source-map@npm:^1.5.0, convert-source-map@npm:^1.7.0": version: 1.8.0 resolution: "convert-source-map@npm:1.8.0" @@ -2912,6 +2981,20 @@ __metadata: languageName: node linkType: hard +"cookie-signature@npm:1.0.6": + version: 1.0.6 + resolution: "cookie-signature@npm:1.0.6" + checksum: f4e1b0a98a27a0e6e66fd7ea4e4e9d8e038f624058371bf4499cfcd8f3980be9a121486995202ba3fca74fbed93a407d6d54d43a43f96fd28d0bd7a06761591a + languageName: node + linkType: hard + +"cookie@npm:0.5.0": + version: 0.5.0 + resolution: "cookie@npm:0.5.0" + checksum: 1f4bd2ca5765f8c9689a7e8954183f5332139eb72b6ff783d8947032ec1fdf43109852c178e21a953a30c0dd42257828185be01b49d1eb1a67fd054ca588a180 + languageName: node + linkType: hard + "copy-to-clipboard@npm:^3.3.1": version: 3.3.1 resolution: "copy-to-clipboard@npm:3.3.1" @@ -3101,6 +3184,15 @@ __metadata: languageName: node linkType: hard +"debug@npm:2.6.9, debug@npm:^2.2.0, debug@npm:^2.6.9": + version: 2.6.9 + resolution: "debug@npm:2.6.9" + dependencies: + ms: 2.0.0 + checksum: d2f51589ca66df60bf36e1fa6e4386b318c3f1e06772280eea5b1ae9fd3d05e9c2b7fd8a7d862457d00853c75b00451aa2d7459b924629ee385287a650f58fe6 + languageName: node + linkType: hard + "debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2": version: 4.3.3 resolution: "debug@npm:4.3.3" @@ -3113,15 +3205,6 @@ __metadata: languageName: node linkType: hard -"debug@npm:^2.2.0, debug@npm:^2.6.9": - version: 2.6.9 - resolution: "debug@npm:2.6.9" - dependencies: - ms: 2.0.0 - checksum: d2f51589ca66df60bf36e1fa6e4386b318c3f1e06772280eea5b1ae9fd3d05e9c2b7fd8a7d862457d00853c75b00451aa2d7459b924629ee385287a650f58fe6 - languageName: node - linkType: hard - "debug@npm:^3.2.7": version: 3.2.7 resolution: "debug@npm:3.2.7" @@ -3221,6 +3304,13 @@ __metadata: languageName: node linkType: hard +"depd@npm:2.0.0, depd@npm:~2.0.0": + version: 2.0.0 + resolution: "depd@npm:2.0.0" + checksum: abbe19c768c97ee2eed6282d8ce3031126662252c58d711f646921c9623f9052e3e1906443066beec1095832f534e57c523b7333f8e7e0d93051ab6baef5ab3a + languageName: node + linkType: hard + "depd@npm:^1.1.2": version: 1.1.2 resolution: "depd@npm:1.1.2" @@ -3228,6 +3318,13 @@ __metadata: languageName: node linkType: hard +"destroy@npm:1.2.0": + version: 1.2.0 + resolution: "destroy@npm:1.2.0" + checksum: 0acb300b7478a08b92d810ab229d5afe0d2f4399272045ab22affa0d99dbaf12637659411530a6fcd597a9bdac718fc94373a61a95b4651bbc7b83684a565e38 + languageName: node + linkType: hard + "detect-libc@npm:^1.0.3": version: 1.0.3 resolution: "detect-libc@npm:1.0.3" @@ -3442,6 +3539,13 @@ __metadata: languageName: node linkType: hard +"ee-first@npm:1.1.1": + version: 1.1.1 + resolution: "ee-first@npm:1.1.1" + checksum: 1b4cac778d64ce3b582a7e26b218afe07e207a0f9bfe13cc7395a6d307849cfe361e65033c3251e00c27dd060cab43014c2d6b2647676135e18b77d2d05b3f4f + languageName: node + linkType: hard + "ejs@npm:^3.1.8": version: 3.1.9 resolution: "ejs@npm:3.1.9" @@ -3563,16 +3667,16 @@ __metadata: languageName: node linkType: hard -"electron@npm:^26.2.4": - version: 26.3.0 - resolution: "electron@npm:26.3.0" +"electron@npm:^27.0.0": + version: 27.0.0 + resolution: "electron@npm:27.0.0" dependencies: "@electron/get": ^2.0.0 "@types/node": ^18.11.18 extract-zip: ^2.0.1 bin: electron: cli.js - checksum: e904f7a7a3281d0cbf899ce06199f71dd7db9553f6650a7a2dda5001e3a4026933554ce44da2f3106500623aa28a10e4b5f9b42599f5442af11983f032d18275 + checksum: 4a84cb894d5f626fe7a2b5171693e903ce82a7673aabc419e5d3d0d2f9cc8441e5088524ecd86a046beab4ba7dd13820b7a94c361c3e7bc2f0959d1a1a860df5 languageName: node linkType: hard @@ -3597,6 +3701,13 @@ __metadata: languageName: node linkType: hard +"encodeurl@npm:~1.0.2": + version: 1.0.2 + resolution: "encodeurl@npm:1.0.2" + checksum: e50e3d508cdd9c4565ba72d2012e65038e5d71bdc9198cb125beb6237b5b1ade6c0d343998da9e170fb2eae52c1bed37d4d6d98a46ea423a0cddbed5ac3f780c + languageName: node + linkType: hard + "encoding@npm:^0.1.11, encoding@npm:^0.1.13": version: 0.1.13 resolution: "encoding@npm:0.1.13" @@ -3968,6 +4079,13 @@ __metadata: languageName: node linkType: hard +"escape-html@npm:~1.0.3": + version: 1.0.3 + resolution: "escape-html@npm:1.0.3" + checksum: 6213ca9ae00d0ab8bccb6d8d4e0a98e76237b2410302cf7df70aaa6591d509a2a37ce8998008cbecae8fc8ffaadf3fb0229535e6a145f3ce0b211d060decbb24 + languageName: node + linkType: hard + "escape-string-regexp@npm:5.0.0": version: 5.0.0 resolution: "escape-string-regexp@npm:5.0.0" @@ -4255,6 +4373,13 @@ __metadata: languageName: node linkType: hard +"etag@npm:~1.8.1": + version: 1.8.1 + resolution: "etag@npm:1.8.1" + checksum: 571aeb3dbe0f2bbd4e4fadbdb44f325fc75335cd5f6f6b6a091e6a06a9f25ed5392f0863c5442acb0646787446e816f13cbfc6edce5b07658541dff573cab1ff + languageName: node + linkType: hard + "evergreen-ui@npm:^6.13.1": version: 6.13.1 resolution: "evergreen-ui@npm:6.13.1" @@ -4312,6 +4437,52 @@ __metadata: languageName: node linkType: hard +"express-async-handler@npm:^1.2.0": + version: 1.2.0 + resolution: "express-async-handler@npm:1.2.0" + checksum: ab9ebba8b8366954cb06ab87cf91fc974428993a97940c499114134ce33144f5d1ffad380e60a53a1569c3cd9501cb209e1fb57b1845a4fc8ff449937598f2f1 + languageName: node + linkType: hard + +"express@npm:^4.18.2": + version: 4.18.2 + resolution: "express@npm:4.18.2" + dependencies: + accepts: ~1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.1 + content-disposition: 0.5.4 + content-type: ~1.0.4 + cookie: 0.5.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: ~1.0.2 + escape-html: ~1.0.3 + etag: ~1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: ~1.1.2 + on-finished: 2.4.1 + parseurl: ~1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: ~2.0.7 + qs: 6.11.0 + range-parser: ~1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: ~1.6.18 + utils-merge: 1.0.1 + vary: ~1.1.2 + checksum: 3c4b9b076879442f6b968fe53d85d9f1eeacbb4f4c41e5f16cc36d77ce39a2b0d81b3f250514982110d815b2f7173f5561367f9110fcc541f9371948e8c8b037 + languageName: node + linkType: hard + "extend@npm:^3.0.0": version: 3.0.2 resolution: "extend@npm:3.0.2" @@ -4503,6 +4674,21 @@ __metadata: languageName: node linkType: hard +"finalhandler@npm:1.2.0": + version: 1.2.0 + resolution: "finalhandler@npm:1.2.0" + dependencies: + debug: 2.6.9 + encodeurl: ~1.0.2 + escape-html: ~1.0.3 + on-finished: 2.4.1 + parseurl: ~1.3.3 + statuses: 2.0.1 + unpipe: ~1.0.0 + checksum: 92effbfd32e22a7dff2994acedbd9bcc3aa646a3e919ea6a53238090e87097f8ef07cced90aa2cc421abdf993aefbdd5b00104d55c7c5479a8d00ed105b45716 + languageName: node + linkType: hard + "find-up@npm:^2.1.0": version: 2.1.0 resolution: "find-up@npm:2.1.0" @@ -4612,6 +4798,13 @@ __metadata: languageName: node linkType: hard +"forwarded@npm:0.2.0": + version: 0.2.0 + resolution: "forwarded@npm:0.2.0" + checksum: fd27e2394d8887ebd16a66ffc889dc983fbbd797d5d3f01087c020283c0f019a7d05ee85669383d8e0d216b116d720fc0cef2f6e9b7eb9f4c90c6e0bc7fd28e6 + languageName: node + linkType: hard + "framer-motion@npm:^9.0.3": version: 9.0.3 resolution: "framer-motion@npm:9.0.3" @@ -4630,6 +4823,13 @@ __metadata: languageName: node linkType: hard +"fresh@npm:0.5.2": + version: 0.5.2 + resolution: "fresh@npm:0.5.2" + checksum: 13ea8b08f91e669a64e3ba3a20eb79d7ca5379a81f1ff7f4310d54e2320645503cc0c78daedc93dfb6191287295f6479544a649c64d8e41a1c0fb0c221552346 + languageName: node + linkType: hard + "fs-constants@npm:^1.0.0": version: 1.0.0 resolution: "fs-constants@npm:1.0.0" @@ -5238,6 +5438,19 @@ __metadata: languageName: node linkType: hard +"http-errors@npm:2.0.0": + version: 2.0.0 + resolution: "http-errors@npm:2.0.0" + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + checksum: 9b0a3782665c52ce9dc658a0d1560bcb0214ba5699e4ea15aefb2a496e2ca83db03ebc42e1cce4ac1f413e4e0d2d736a3fd755772c556a9a06853ba2a0b7d920 + languageName: node + linkType: hard + "http-proxy-agent@npm:^5.0.0": version: 5.0.0 resolution: "http-proxy-agent@npm:5.0.0" @@ -5381,6 +5594,15 @@ __metadata: languageName: node linkType: hard +"iconv-lite@npm:0.4.24": + version: 0.4.24 + resolution: "iconv-lite@npm:0.4.24" + dependencies: + safer-buffer: ">= 2.1.2 < 3" + checksum: bd9f120f5a5b306f0bc0b9ae1edeb1577161503f5f8252a20f1a9e56ef8775c9959fd01c55f2d3a39d9a8abaf3e30c1abeb1895f367dcbbe0a8fd1c9ca01c4f6 + languageName: node + linkType: hard + "iconv-lite@npm:^0.6.2": version: 0.6.3 resolution: "iconv-lite@npm:0.6.3" @@ -5473,7 +5695,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": +"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 @@ -5533,6 +5755,13 @@ __metadata: languageName: node linkType: hard +"ipaddr.js@npm:1.9.1": + version: 1.9.1 + resolution: "ipaddr.js@npm:1.9.1" + checksum: f88d3825981486f5a1942414c8d77dd6674dd71c065adcfa46f578d677edcb99fda25af42675cb59db492fdf427b34a5abfcde3982da11a8fd83a500b41cfe77 + languageName: node + linkType: hard + "is-absolute@npm:^1.0.0": version: 1.0.0 resolution: "is-absolute@npm:1.0.0" @@ -6389,7 +6618,7 @@ __metadata: csv-stringify: ^5.6.2 cue-parser: ^0.3.0 data-uri-to-buffer: ^4.0.0 - electron: ^26.2.4 + electron: ^27.0.0 electron-builder: ^24.6.3 electron-builder-notarize: ^1.5.1 electron-devtools-installer: ^3.2.0 @@ -6404,6 +6633,8 @@ __metadata: eslint-plugin-react-hooks: ^4.3.0 evergreen-ui: ^6.13.1 execa: 5 + express: ^4.18.2 + express-async-handler: ^1.2.0 fast-xml-parser: ^4.2.5 file-type: 16 file-url: ^3.0.0 @@ -6421,6 +6652,7 @@ __metadata: luxon: ^3.3.0 mime-types: ^2.1.14 mkdirp: ^1.0.3 + morgan: ^1.10.0 mousetrap: ^1.6.5 p-map: ^5.5.0 patch-package: ^6.2.1 @@ -6587,6 +6819,20 @@ __metadata: languageName: node linkType: hard +"media-typer@npm:0.3.0": + version: 0.3.0 + resolution: "media-typer@npm:0.3.0" + checksum: af1b38516c28ec95d6b0826f6c8f276c58aec391f76be42aa07646b4e39d317723e869700933ca6995b056db4b09a78c92d5440dc23657e6764be5d28874bba1 + languageName: node + linkType: hard + +"merge-descriptors@npm:1.0.1": + version: 1.0.1 + resolution: "merge-descriptors@npm:1.0.1" + checksum: 5abc259d2ae25bb06d19ce2b94a21632583c74e2a9109ee1ba7fd147aa7362b380d971e0251069f8b3eb7d48c21ac839e21fa177b335e82c76ec172e30c31a26 + languageName: node + linkType: hard + "merge-stream@npm:^2.0.0": version: 2.0.0 resolution: "merge-stream@npm:2.0.0" @@ -6601,6 +6847,13 @@ __metadata: languageName: node linkType: hard +"methods@npm:~1.1.2": + version: 1.1.2 + resolution: "methods@npm:1.1.2" + checksum: 0917ff4041fa8e2f2fda5425a955fe16ca411591fbd123c0d722fcf02b73971ed6f764d85f0a6f547ce49ee0221ce2c19a5fa692157931cecb422984f1dcd13a + languageName: node + linkType: hard + "micromatch@npm:^4.0.2, micromatch@npm:^4.0.4": version: 4.0.4 resolution: "micromatch@npm:4.0.4" @@ -6618,6 +6871,13 @@ __metadata: languageName: node linkType: hard +"mime-db@npm:1.52.0": + version: 1.52.0 + resolution: "mime-db@npm:1.52.0" + checksum: 0d99a03585f8b39d68182803b12ac601d9c01abfa28ec56204fa330bc9f3d1c5e14beb049bafadb3dbdf646dfb94b87e24d4ec7b31b7279ef906a8ea9b6a513f + languageName: node + linkType: hard + "mime-types@npm:^2.1.12, mime-types@npm:^2.1.14": version: 2.1.34 resolution: "mime-types@npm:2.1.34" @@ -6627,6 +6887,24 @@ __metadata: languageName: node linkType: hard +"mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": + version: 2.1.35 + resolution: "mime-types@npm:2.1.35" + dependencies: + mime-db: 1.52.0 + checksum: 89a5b7f1def9f3af5dad6496c5ed50191ae4331cc5389d7c521c8ad28d5fdad2d06fd81baf38fed813dc4e46bb55c8145bb0ff406330818c9cf712fb2e9b3836 + languageName: node + linkType: hard + +"mime@npm:1.6.0": + version: 1.6.0 + resolution: "mime@npm:1.6.0" + bin: + mime: cli.js + checksum: fef25e39263e6d207580bdc629f8872a3f9772c923c7f8c7e793175cee22777bbe8bba95e5d509a40aaa292d8974514ce634ae35769faa45f22d17edda5e8557 + languageName: node + linkType: hard + "mime@npm:^2.5.2": version: 2.6.0 resolution: "mime@npm:2.6.0" @@ -6837,6 +7115,19 @@ __metadata: languageName: node linkType: hard +"morgan@npm:^1.10.0": + version: 1.10.0 + resolution: "morgan@npm:1.10.0" + dependencies: + basic-auth: ~2.0.1 + debug: 2.6.9 + depd: ~2.0.0 + on-finished: ~2.3.0 + on-headers: ~1.0.2 + checksum: fb41e226ab5a1abf7e8909e486b387076534716d60207e361acfb5df78b84d703a7b7ea58f3046a9fd0b83d3c94bfabde32323341a1f1b26ce50680abd2ea5dd + languageName: node + linkType: hard + "mousetrap@npm:^1.6.5": version: 1.6.5 resolution: "mousetrap@npm:1.6.5" @@ -6858,7 +7149,7 @@ __metadata: languageName: node linkType: hard -"ms@npm:^2.0.0, ms@npm:^2.1.1": +"ms@npm:2.1.3, ms@npm:^2.0.0, ms@npm:^2.1.1": version: 2.1.3 resolution: "ms@npm:2.1.3" checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d @@ -6907,7 +7198,7 @@ __metadata: languageName: node linkType: hard -"negotiator@npm:^0.6.3": +"negotiator@npm:0.6.3, negotiator@npm:^0.6.3": version: 0.6.3 resolution: "negotiator@npm:0.6.3" checksum: b8ffeb1e262eff7968fc90a2b6767b04cfd9842582a9d0ece0af7049537266e7b2506dfb1d107a32f06dd849ab2aea834d5830f7f4d0e5cb7d36e1ae55d021d9 @@ -7167,6 +7458,31 @@ __metadata: languageName: node linkType: hard +"on-finished@npm:2.4.1": + version: 2.4.1 + resolution: "on-finished@npm:2.4.1" + dependencies: + ee-first: 1.1.1 + checksum: d20929a25e7f0bb62f937a425b5edeb4e4cde0540d77ba146ec9357f00b0d497cdb3b9b05b9c8e46222407d1548d08166bff69cc56dfa55ba0e4469228920ff0 + languageName: node + linkType: hard + +"on-finished@npm:~2.3.0": + version: 2.3.0 + resolution: "on-finished@npm:2.3.0" + dependencies: + ee-first: 1.1.1 + checksum: 1db595bd963b0124d6fa261d18320422407b8f01dc65863840f3ddaaf7bcad5b28ff6847286703ca53f4ec19595bd67a2f1253db79fc4094911ec6aa8df1671b + languageName: node + linkType: hard + +"on-headers@npm:~1.0.2": + version: 1.0.2 + resolution: "on-headers@npm:1.0.2" + checksum: 2bf13467215d1e540a62a75021e8b318a6cfc5d4fc53af8e8f84ad98dbcea02d506c6d24180cd62e1d769c44721ba542f3154effc1f7579a8288c9f7873ed8e5 + languageName: node + linkType: hard + "once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.3.2, once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" @@ -7388,6 +7704,13 @@ __metadata: languageName: node linkType: hard +"parseurl@npm:~1.3.3": + version: 1.3.3 + resolution: "parseurl@npm:1.3.3" + checksum: 407cee8e0a3a4c5cd472559bca8b6a45b82c124e9a4703302326e9ab60fc1081442ada4e02628efef1eb16197ddc7f8822f5a91fd7d7c86b51f530aedb17dfa2 + languageName: node + linkType: hard + "patch-package@npm:^6.2.1": version: 6.4.7 resolution: "patch-package@npm:6.4.7" @@ -7467,6 +7790,13 @@ __metadata: languageName: node linkType: hard +"path-to-regexp@npm:0.1.7": + version: 0.1.7 + resolution: "path-to-regexp@npm:0.1.7" + checksum: 69a14ea24db543e8b0f4353305c5eac6907917031340e5a8b37df688e52accd09e3cebfe1660b70d76b6bd89152f52183f28c74813dbf454ba1a01c82a38abce + languageName: node + linkType: hard + "path-type@npm:^4.0.0": version: 4.0.0 resolution: "path-type@npm:4.0.0" @@ -7718,6 +8048,16 @@ __metadata: languageName: node linkType: hard +"proxy-addr@npm:~2.0.7": + version: 2.0.7 + resolution: "proxy-addr@npm:2.0.7" + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + checksum: 29c6990ce9364648255454842f06f8c46fcd124d3e6d7c5066df44662de63cdc0bad032e9bf5a3d653ff72141cc7b6019873d685708ac8210c30458ad99f2b74 + languageName: node + linkType: hard + "pump@npm:^2.0.0": version: 2.0.1 resolution: "pump@npm:2.0.1" @@ -7756,6 +8096,15 @@ __metadata: languageName: node linkType: hard +"qs@npm:6.11.0": + version: 6.11.0 + resolution: "qs@npm:6.11.0" + dependencies: + side-channel: ^1.0.4 + checksum: 6e1f29dd5385f7488ec74ac7b6c92f4d09a90408882d0c208414a34dd33badc1a621019d4c799a3df15ab9b1d0292f97c1dd71dc7c045e69f81a8064e5af7297 + languageName: node + linkType: hard + "queue-microtask@npm:^1.2.2": version: 1.2.3 resolution: "queue-microtask@npm:1.2.3" @@ -7788,6 +8137,25 @@ __metadata: languageName: node linkType: hard +"range-parser@npm:~1.2.1": + version: 1.2.1 + resolution: "range-parser@npm:1.2.1" + checksum: 0a268d4fea508661cf5743dfe3d5f47ce214fd6b7dec1de0da4d669dd4ef3d2144468ebe4179049eff253d9d27e719c88dae55be64f954e80135a0cada804ec9 + languageName: node + linkType: hard + +"raw-body@npm:2.5.1": + version: 2.5.1 + resolution: "raw-body@npm:2.5.1" + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + checksum: 5362adff1575d691bb3f75998803a0ffed8c64eabeaa06e54b4ada25a0cd1b2ae7f4f5ec46565d1bec337e08b5ac90c76eaa0758de6f72a633f025d754dec29e + languageName: node + linkType: hard + "rc@npm:^1.2.7": version: 1.2.8 resolution: "rc@npm:1.2.8" @@ -8380,20 +8748,20 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:~5.2.0": - version: 5.2.1 - resolution: "safe-buffer@npm:5.2.1" - checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 - languageName: node - linkType: hard - -"safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": +"safe-buffer@npm:5.1.2, safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": version: 5.1.2 resolution: "safe-buffer@npm:5.1.2" checksum: f2f1f7943ca44a594893a852894055cf619c1fbcb611237fc39e461ae751187e7baf4dc391a72125e0ac4fb2d8c5c0b3c71529622e6a58f46b960211e704903c languageName: node linkType: hard +"safe-buffer@npm:5.2.1, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:~5.2.0": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 + languageName: node + linkType: hard + "safe-stable-stringify@npm:^2.3.1": version: 2.3.1 resolution: "safe-stable-stringify@npm:2.3.1" @@ -8401,7 +8769,7 @@ __metadata: languageName: node linkType: hard -"safer-buffer@npm:>= 2.1.2 < 3.0.0": +"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0": version: 2.1.2 resolution: "safer-buffer@npm:2.1.2" checksum: cab8f25ae6f1434abee8d80023d7e72b598cf1327164ddab31003c51215526801e40b66c5e65d658a0af1e9d6478cadcb4c745f4bd6751f97d8644786c0978b0 @@ -8507,6 +8875,27 @@ __metadata: languageName: node linkType: hard +"send@npm:0.18.0": + version: 0.18.0 + resolution: "send@npm:0.18.0" + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: ~1.0.2 + escape-html: ~1.0.3 + etag: ~1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: ~1.2.1 + statuses: 2.0.1 + checksum: 74fc07ebb58566b87b078ec63e5a3e41ecd987e4272ba67b7467e86c6ad51bc6b0b0154133b6d8b08a2ddda360464f71382f7ef864700f34844a76c8027817a8 + languageName: node + linkType: hard + "serialize-error@npm:^7.0.1": version: 7.0.1 resolution: "serialize-error@npm:7.0.1" @@ -8525,6 +8914,18 @@ __metadata: languageName: node linkType: hard +"serve-static@npm:1.15.0": + version: 1.15.0 + resolution: "serve-static@npm:1.15.0" + dependencies: + encodeurl: ~1.0.2 + escape-html: ~1.0.3 + parseurl: ~1.3.3 + send: 0.18.0 + checksum: af57fc13be40d90a12562e98c0b7855cf6e8bd4c107fe9a45c212bf023058d54a1871b1c89511c3958f70626fff47faeb795f5d83f8cf88514dbaeb2b724464d + languageName: node + linkType: hard + "set-blocking@npm:^2.0.0, set-blocking@npm:~2.0.0": version: 2.0.0 resolution: "set-blocking@npm:2.0.0" @@ -8546,6 +8947,13 @@ __metadata: languageName: node linkType: hard +"setprototypeof@npm:1.2.0": + version: 1.2.0 + resolution: "setprototypeof@npm:1.2.0" + checksum: be18cbbf70e7d8097c97f713a2e76edf84e87299b40d085c6bf8b65314e994cc15e2e317727342fa6996e38e1f52c59720b53fe621e2eb593a6847bf0356db89 + languageName: node + linkType: hard + "sharp@npm:^0.29.3": version: 0.29.3 resolution: "sharp@npm:0.29.3" @@ -8933,6 +9341,13 @@ __metadata: languageName: node linkType: hard +"statuses@npm:2.0.1": + version: 2.0.1 + resolution: "statuses@npm:2.0.1" + checksum: 18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb + languageName: node + linkType: hard + "std-env@npm:^3.3.1": version: 3.3.2 resolution: "std-env@npm:3.3.2" @@ -9467,6 +9882,13 @@ __metadata: languageName: node linkType: hard +"toidentifier@npm:1.0.1": + version: 1.0.1 + resolution: "toidentifier@npm:1.0.1" + checksum: 952c29e2a85d7123239b5cfdd889a0dde47ab0497f0913d70588f19c53f7e0b5327c95f4651e413c74b785147f9637b17410ac8c846d5d4a20a5a33eb6dc3a45 + languageName: node + linkType: hard + "token-types@npm:^4.1.1": version: 4.2.1 resolution: "token-types@npm:4.2.1" @@ -9602,6 +10024,16 @@ __metadata: languageName: node linkType: hard +"type-is@npm:~1.6.18": + version: 1.6.18 + resolution: "type-is@npm:1.6.18" + dependencies: + media-typer: 0.3.0 + mime-types: ~2.1.24 + checksum: 2c8e47675d55f8b4e404bcf529abdf5036c537a04c2b20177bcf78c9e3c1da69da3942b1346e6edb09e823228c0ee656ef0e033765ec39a70d496ef601a0c657 + languageName: node + linkType: hard + "typedarray-to-buffer@npm:^3.1.5": version: 3.1.5 resolution: "typedarray-to-buffer@npm:3.1.5" @@ -9736,6 +10168,13 @@ __metadata: languageName: node linkType: hard +"unpipe@npm:1.0.0, unpipe@npm:~1.0.0": + version: 1.0.0 + resolution: "unpipe@npm:1.0.0" + checksum: 4fa18d8d8d977c55cb09715385c203197105e10a6d220087ec819f50cb68870f02942244f1017565484237f1f8c5d3cd413631b1ae104d3096f24fdfde1b4aa2 + languageName: node + linkType: hard + "unzip-crx-3@npm:^0.2.0": version: 0.2.0 resolution: "unzip-crx-3@npm:0.2.0" @@ -9807,6 +10246,13 @@ __metadata: languageName: node linkType: hard +"utils-merge@npm:1.0.1": + version: 1.0.1 + resolution: "utils-merge@npm:1.0.1" + checksum: c81095493225ecfc28add49c106ca4f09cdf56bc66731aa8dabc2edbbccb1e1bfe2de6a115e5c6a380d3ea166d1636410b62ef216bb07b3feb1cfde1d95d5080 + languageName: node + linkType: hard + "uuid@npm:^8.3.2": version: 8.3.2 resolution: "uuid@npm:8.3.2" @@ -9840,6 +10286,13 @@ __metadata: languageName: node linkType: hard +"vary@npm:~1.1.2": + version: 1.1.2 + resolution: "vary@npm:1.1.2" + checksum: ae0123222c6df65b437669d63dfa8c36cee20a504101b2fcd97b8bf76f91259c17f9f2b4d70a1e3c6bbcee7f51b28392833adb6b2770b23b01abec84e369660b + languageName: node + linkType: hard + "verror@npm:^1.10.0": version: 1.10.1 resolution: "verror@npm:1.10.1"