├── .gitignore ├── README.MD ├── createhttpskeys.sh ├── index.js ├── package-lock.json └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | key.pem 3 | cert.pem 4 | 5 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | ## Remote NetMD 2 | *Brings Wireless to NetMD Devices* 3 | 4 | Remote NetMD lets you set up a NetMD server on, for example, a Raspberry Pi connected to a NetMD-capable deck. It's then possible to remotely control that deck with any device on the same network with the help of Web Minidisc Pro. The program will automatically detect it when a device disconnects and connects again, so it can be left running unattended. 5 | To get it working, you need to: 6 | 7 | 1. [Define the correct udev rules](https://github.com/glaubitz/linux-minidisc/tree/master/netmd/etc) on the Pi, so that the node application can access your device. 8 | 2. Clone `https://github.com/asivery/remote-netmd-server` 9 | 3. Run a script to generate the HTTPS self-signed certificates: `bash createhttpskeys.sh` 10 | 4. Install the dependencies with `npm i` 11 | 5. Run `node index.js` 12 | 6. Visit the page hosted at `https://:11396/`, and acknowledge the security risk 13 | 7. Add it in Web Minidisc Pro, by clicking the 'Add Custom Device' in the connect screen's dropdown. Then, after filling in the address and the name you want to see the server displayed as in Web Minidisc Pro, you can select your device from the connect screen's dropdown and connect to it. 14 | -------------------------------------------------------------------------------- /createhttpskeys.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 99999 -nodes -subj '/CN=remotemd' 3 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | import express from 'express'; 4 | import http from 'http'; 5 | import https from 'https'; 6 | import expressWs from 'express-ws'; 7 | import { 8 | WebUSB 9 | } from 'usb'; 10 | import yargs from 'yargs'; 11 | import fs from 'fs'; 12 | import { 13 | hideBin 14 | } from 'yargs/helpers'; 15 | import { 16 | sanitizeFullWidthTitle, 17 | sanitizeHalfWidthTitle 18 | } from 'netmd-js/dist/utils.js'; 19 | import { 20 | MDTrack, 21 | getDeviceStatus, 22 | Encoding, 23 | listContent, 24 | openNewDevice, 25 | renameDisc, 26 | DevicesIds, 27 | rewriteDiscGroups, 28 | prepareDownload, 29 | EKBOpenSource, 30 | MDSession, 31 | Wireformat 32 | } from 'netmd-js'; 33 | import { 34 | Mutex 35 | } from 'async-mutex'; 36 | 37 | // Compatibility methods. Do NOT use these unless absolutely necessary!! 38 | export function convertDiscToWMD(source){ 39 | return { 40 | ...source, 41 | left: Math.ceil(source.left / 512), 42 | total: Math.ceil(source.total / 512), 43 | groups: source.groups.map(convertGroupToWMD), 44 | }; 45 | } 46 | 47 | export function convertDiscToNJS(source){ 48 | return { 49 | ...source, 50 | left: source.left * 512, 51 | total: source.total * 512, 52 | groups: source.groups.map(convertGroupToNJS), 53 | }; 54 | } 55 | 56 | export function convertGroupToWMD(source){ 57 | return { 58 | ...source, 59 | tracks: source.tracks.map(convertTrackToWMD) 60 | }; 61 | } 62 | 63 | export function convertGroupToNJS(source){ 64 | return { 65 | ...source, 66 | tracks: source.tracks.map(convertTrackToNJS), 67 | }; 68 | } 69 | 70 | export function convertTrackToWMD(source){ 71 | return ({ 72 | ...source, 73 | duration: Math.ceil(source.duration / 512), 74 | encoding: ({ 75 | [Encoding.sp]: { codec: "SP" }, 76 | [Encoding.lp2]: { codec: "LP2" }, 77 | [Encoding.lp4]: { codec: "LP4" }, 78 | })[source.encoding], 79 | }); 80 | } 81 | 82 | export function convertTrackToNJS(source){ 83 | return { 84 | ...source, 85 | duration: source.duration * 512, 86 | encoding: ({ 87 | "SP": Encoding.sp, 88 | "LP2": Encoding.lp2, 89 | "LP4": Encoding.lp4, 90 | })[["SP", "LP2", "LP4"].includes(source.encoding.codec) ? source.encoding.codec : "SP"], 91 | } 92 | } 93 | 94 | function isSequential(numbers) { 95 | if (numbers.length === 0) return true; 96 | let last = numbers[0]; 97 | for (let num of numbers) { 98 | if (num === last) { 99 | ++last; 100 | } else return false; 101 | } 102 | return true; 103 | } 104 | 105 | const webusb = new WebUSB({ 106 | allowedDevices: DevicesIds.map(({ 107 | deviceId, 108 | vendorId 109 | }) => ({ 110 | deviceId, 111 | vendorId 112 | })), 113 | deviceTimeout: 1000000, 114 | }); 115 | const mutex = new Mutex(); 116 | 117 | const netmdLogger = { 118 | debug: () => {}, 119 | info: console.log, 120 | warn: console.log, 121 | error: console.log, 122 | child: () => netmdLogger, 123 | }; 124 | 125 | let awaitingDeviceLockMutexRelease = null; 126 | let device = null; 127 | let cachedContent = undefined; 128 | 129 | async function getCachedContent() { 130 | if (!cachedContent) cachedContent = await listContent(device); 131 | return cachedContent; 132 | } 133 | 134 | function flushCache() { 135 | cachedContent = undefined; 136 | } 137 | 138 | function sleep(ms) { 139 | return new Promise(resolve => { 140 | setTimeout(resolve, ms); 141 | }); 142 | } 143 | 144 | 145 | function fail(res, error) { 146 | try { 147 | res.json({ 148 | ok: false, 149 | error 150 | }); 151 | } catch (err) {} 152 | } 153 | 154 | function success(res, value) { 155 | try { 156 | res.json(value ? { 157 | ok: true, 158 | value 159 | } : { 160 | ok: true 161 | }); 162 | } catch (err) {} 163 | } 164 | 165 | async function awaitPromiseReturnStatus(promise, res) { 166 | try{ 167 | success(res, await promise); 168 | }catch(ex){ 169 | fail(res, ex); 170 | } 171 | } 172 | 173 | function assertPresent(res, value) { 174 | if ((isNaN(value) && (typeof value === 'number')) || value === undefined || value === null) { 175 | fail(res, "Missing parameter."); 176 | return false; 177 | } 178 | return true; 179 | } 180 | 181 | async function main() { 182 | 183 | const args = yargs(hideBin(process.argv)) 184 | .option("https", { 185 | type: "boolean", 186 | describe: "Use HTTPS instead of HTTP", 187 | }) 188 | .option("httpsCert", { 189 | type: "string", 190 | describe: "The HTTPS certificate", 191 | }) 192 | .option("httpsKey", { 193 | type: "string", 194 | describe: "The HTTPS key", 195 | }) 196 | .option("port", { 197 | type: "number", 198 | describe: "The port on which to host", 199 | }) 200 | .default("port", 11396) 201 | .default("https", true) 202 | .default("httpsCert", "cert.pem") 203 | .default("httpsKey", "key.pem") 204 | .help() 205 | .parse(); 206 | 207 | const { 208 | port, 209 | https: useHttps, 210 | httpsCert, 211 | httpsKey 212 | } = args; 213 | // ********************** Express initialization ********************* 214 | const app = express(); 215 | const server = useHttps ? https.createServer({ 216 | key: fs.readFileSync(httpsKey), 217 | cert: fs.readFileSync(httpsCert), 218 | }, app) : http.createServer(app); 219 | expressWs(app, server); 220 | app.use(express.json()); 221 | 222 | // Make sure there is no way to call two methods at the same time. 223 | app.use((req, res, next) => { 224 | res.set("Access-Control-Allow-Origin", "*"); 225 | res.set("Access-Control-Allow-Headers", "Content-Type"); 226 | if (awaitingDeviceLockMutexRelease) { 227 | fail(res, "Not ready."); 228 | return; 229 | } 230 | console.log(`Called ${req.url}`); 231 | if (!req.url.includes("upload")) 232 | mutex.acquire().then(release => { 233 | res.on('finish', release); 234 | res.on('error', (e) => { 235 | console.log(`Error while handling: ${e}.`); 236 | release(); 237 | }); 238 | res.on('close', release); 239 | next(); 240 | }).catch(ex => console.log(ex)); 241 | else next(); 242 | }); 243 | 244 | // Fliter out preflight requests 245 | app.use((req, res, next) => { 246 | if(req.method === "OPTIONS"){ 247 | console.log(`Preflight request to ${req.url}`); 248 | if(req.header("Access-Control-Request-Private-Network") === "true"){ 249 | res.header("Access-Control-Allow-Private-Network", "true"); 250 | } 251 | res.status(204).send(""); 252 | return; 253 | } 254 | next(); 255 | }); 256 | 257 | setup(app); 258 | 259 | // *********************** NetMD initialization ********************** 260 | setTimeout(async function reloadDevices() { 261 | try{ 262 | if (awaitingDeviceLockMutexRelease) { 263 | device = await openNewDevice(webusb, netmdLogger); 264 | if (device !== null) { 265 | awaitingDeviceLockMutexRelease(); 266 | awaitingDeviceLockMutexRelease = null; 267 | console.log("New device connected! Application resumed."); 268 | cachedContent = null; 269 | } 270 | } 271 | }catch(ex){ 272 | console.log(ex); 273 | } 274 | setTimeout(reloadDevices, 1000); 275 | }, 1000); 276 | 277 | webusb.addEventListener("disconnect", () => { 278 | if(mutex.isLocked()){ 279 | mutex.cancel(); 280 | mutex.release(); 281 | } 282 | device = null; 283 | console.log("Device disconnected."); 284 | console.log("Awaiting new device..."); 285 | flushCache(); 286 | mutex.acquire().then(release => awaitingDeviceLockMutexRelease = release); 287 | }); 288 | 289 | device = await openNewDevice(webusb, netmdLogger); 290 | 291 | if (device === null) { 292 | console.log("Error: No NetMD devices found."); 293 | console.log("Awaiting new device..."); 294 | mutex.acquire().then(release => awaitingDeviceLockMutexRelease = release); 295 | } else { 296 | console.log(`Connected to ${device.netMd.getDeviceName()}`); 297 | } 298 | 299 | 300 | server.listen(port, () => console.log(`Started ${useHttps ? "https" : "http"} server on port ${port}.`)); 301 | } 302 | main(); 303 | 304 | function setup(app) { 305 | // ********************* NetMD <==> REST bridge ********************** 306 | // Basic pages: 307 | app.get("/", (req, res) => { 308 | success(res, { 309 | device: device.netMd.getDeviceName(), 310 | capabilities: ['contentList', 'playbackControl', 'metadataEdit', 'trackUpload'], 311 | version: '1.0', 312 | }); 313 | }); 314 | 315 | app.get('/deviceStatus', async (req, res) => { 316 | const devStat = await getDeviceStatus(device); 317 | if(!devStat.discPresent) flushCache(); 318 | success(res, devStat); 319 | }); 320 | 321 | // The 'contentList' capability: 322 | 323 | app.get('/listContent', (req, res) => { 324 | if(req.query.flushCache){ 325 | flushCache(); 326 | } 327 | awaitPromiseReturnStatus(new Promise(async (res, rej) => { 328 | try{ 329 | const content = await getCachedContent(); 330 | return res(convertDiscToWMD(content)); 331 | }catch(ex){ 332 | rej(ex); 333 | } 334 | }), res); 335 | }); 336 | 337 | app.get('/deviceName', (req, res) => { 338 | success(res, device.netMd.getDeviceName()); 339 | }); 340 | 341 | // The 'metadataEdit' capability: 342 | 343 | app.get('/renameTrack', async (req, res) => { 344 | let { 345 | index, 346 | title, 347 | fullWidthTitle 348 | } = req.query; 349 | 350 | index = parseInt(index); 351 | if (!assertPresent(res, title) || !assertPresent(res, index)) return; 352 | 353 | await device.setTrackTitle(index, title, false); 354 | if (fullWidthTitle !== undefined) { 355 | await device.setTrackTitle(index, fullWidthTitle, true); 356 | } 357 | flushCache(); 358 | success(res); 359 | }); 360 | 361 | app.get('/renameDisc', (req, res) => { 362 | let { 363 | title, 364 | fullWidthTitle 365 | } = req.query; 366 | if (!fullWidthTitle) fullWidthTitle = ''; 367 | if (!assertPresent(res, title)) return; 368 | flushCache(); 369 | awaitPromiseReturnStatus(renameDisc(device, title, fullWidthTitle), res); 370 | }); 371 | 372 | app.get('/renameGroup', async (req, res) => { 373 | let { 374 | groupIndex, 375 | title, 376 | fullWidthTitle 377 | } = req.query; 378 | if (!fullWidthTitle) fullWidthTitle = ''; 379 | groupIndex = parseInt(groupIndex); 380 | if (!assertPresent(res, groupIndex) || !assertPresent(res, title)) return; 381 | 382 | const disc = await getCachedContent(); 383 | let thisGroup = disc.groups.find(g => g.index === groupIndex); 384 | if (!thisGroup) { 385 | return; 386 | } 387 | 388 | thisGroup.title = title; 389 | if (fullWidthTitle !== undefined) { 390 | thisGroup.fullWidthTitle = fullWidthTitle; 391 | } 392 | awaitPromiseReturnStatus(rewriteDiscGroups(device, disc), res); 393 | flushCache(); 394 | }); 395 | 396 | app.get('/addGroup', async (req, res) => { 397 | let { 398 | groupBegin, 399 | groupLength, 400 | title 401 | } = req.query; 402 | const disc = await getCachedContent(); 403 | 404 | groupBegin = parseInt(groupBegin); 405 | groupLength = parseInt(groupLength); 406 | 407 | if (!assertPresent(res, groupBegin) || !assertPresent(res, groupLength)) return; 408 | 409 | let ungrouped = disc.groups.find(n => n.title === null); 410 | if (!ungrouped) { 411 | fail(res, "No groupable tracks on the disc."); 412 | return; // You can only group tracks that aren't already in a different group, if there's no such tracks, there's no point to continue 413 | } 414 | 415 | let ungroupedLengthBeforeGroup = ungrouped.tracks.length; 416 | 417 | let thisGroupTracks = ungrouped.tracks.filter(n => n.index >= groupBegin && n.index < groupBegin + groupLength); 418 | ungrouped.tracks = ungrouped.tracks.filter(n => !thisGroupTracks.includes(n)); 419 | 420 | if (ungroupedLengthBeforeGroup - ungrouped.tracks.length !== groupLength) { 421 | throw new Error('A track cannot be in 2 groups!'); 422 | } 423 | 424 | if (!isSequential(thisGroupTracks.map(n => n.index))) { 425 | throw new Error('Invalid sequence of tracks!'); 426 | } 427 | 428 | disc.groups.push({ 429 | title, 430 | fullWidthTitle: '', 431 | index: disc.groups.length, 432 | tracks: thisGroupTracks, 433 | }); 434 | disc.groups = disc.groups.filter(g => g.tracks.length !== 0).sort((a, b) => a.tracks[0].index - b.tracks[0].index); 435 | flushCache(); 436 | awaitPromiseReturnStatus(rewriteDiscGroups(device, disc), res); 437 | }); 438 | 439 | app.get('/deleteGroup', async (req, res) => { 440 | let { 441 | index 442 | } = req.query; 443 | index = parseInt(index); 444 | if (!assertPresent(res, index)) return; 445 | 446 | const disc = await getCachedContent(); 447 | 448 | let groupIndex = disc.groups.findIndex(g => g.index === index); 449 | if (groupIndex >= 0) { 450 | disc.groups.splice(groupIndex, 1); 451 | } 452 | flushCache(); 453 | awaitPromiseReturnStatus(rewriteDiscGroups(device, disc), res); 454 | }); 455 | 456 | app.post('/rewriteGroups', async (req, res) => { 457 | if (!assertPresent(res, req.body.groups)); 458 | awaitPromiseReturnStatus(rewriteDiscGroups(device, { 459 | ...getCachedContent(), 460 | groups: req.body.groups.map(convertGroupToNJS) 461 | }), res); 462 | flushCache(); 463 | }); 464 | 465 | app.post('/deleteTracks', async (req, res) => { 466 | if (!assertPresent(res, req.body.indexes) || !assertPresent(res, Array.isArray(req.body.indexes))) return; 467 | let indexes = req.body.indexes; 468 | for (let i = 0; i < indexes.length; i++) { 469 | indexes[i] = parseInt(indexes[i]); 470 | if (!assertPresent(res, indexes[i])) return; 471 | } 472 | indexes = indexes.sort(); 473 | indexes.reverse(); 474 | let content = await getCachedContent(); 475 | for (let index of indexes) { 476 | //content = recomputeGroupsAfterTrackMove(content, index, -1); 477 | await device.eraseTrack(index); 478 | await sleep(100); 479 | } 480 | flushCache(); 481 | awaitPromiseReturnStatus(rewriteDiscGroups(device, content), res); 482 | }); 483 | 484 | app.get('/moveTrack', async (req, res) => { 485 | let { 486 | src, 487 | dst 488 | } = req.query; 489 | 490 | src = parseInt(src); 491 | dst = parseInt(dst); 492 | 493 | if (!assertPresent(res, src) || !assertPresent(res, src)) return; 494 | flushCache(); 495 | awaitPromiseReturnStatus(device.moveTrack(src, dst), res); 496 | }); 497 | 498 | app.get('/wipeDisc', (req, res) => { 499 | flushCache(); 500 | awaitPromiseReturnStatus(device.eraseDisc(), res); 501 | }); 502 | 503 | // The 'playbackControl' capability: 504 | 505 | app.get('/play', (req, res) => awaitPromiseReturnStatus(device.play(), res)); 506 | app.get('/pause', (req, res) => awaitPromiseReturnStatus(device.pause(), res)); 507 | app.get('/stop', (req, res) => awaitPromiseReturnStatus(device.stop(), res)); 508 | app.get('/next', (req, res) => awaitPromiseReturnStatus(device.nextTrack(), res)); 509 | app.get('/prev', (req, res) => awaitPromiseReturnStatus(device.previousTrack(), res)); 510 | app.get('/goto', (req, res) => { 511 | let { 512 | index 513 | } = req.query; 514 | index = parseInt(index); 515 | if (!assertPresent(res, index)) return; 516 | awaitPromiseReturnStatus(device.gotoTrack(index), res); 517 | }); 518 | app.get('/gotoTime', (req, res) => { 519 | let { 520 | index, 521 | hour, 522 | minute, 523 | second, 524 | frame 525 | } = req.query; 526 | index = parseInt(index); 527 | hour = parseInt(hour); 528 | minute = parseInt(minute); 529 | second = parseInt(second); 530 | frame = parseInt(frame); 531 | if (!assertPresent(res, index) || !assertPresent(res, hour) || !assertPresent(res, minute) || !assertPresent(res, second) || !assertPresent(res, frame)) return; 532 | awaitPromiseReturnStatus(device.gotoTime(track, hour, minute, second, frame)); 533 | }); 534 | app.get('/getPosition', (req, res) => awaitPromiseReturnStatus(device.getPosition(), res)); 535 | let session = null; 536 | app.get('/prepareUpload', async (req, res) => { 537 | await prepareDownload(device); 538 | session = new MDSession(device, new EKBOpenSource()); 539 | await session.init(); 540 | success(res); 541 | }); 542 | app.get('/finalizeUpload', async (req, res) => { 543 | await session.close(); 544 | await device.release(); 545 | session = null; 546 | flushCache(); 547 | success(res); 548 | }); 549 | 550 | app.ws('/upload', (ws, req) => { 551 | if(!session){ 552 | console.log("You need to call /prepareUpload first"); 553 | ws.close(); 554 | } 555 | mutex.acquire().then(async release => { 556 | let { 557 | title, 558 | fullWidthTitle, 559 | format, 560 | totalLength, 561 | chunked 562 | } = req.query; 563 | if (!fullWidthTitle) fullWidthTitle = ''; 564 | if (title === undefined || title === null || format === undefined || format === null) ws.close(); 565 | const WireformatDict = { 566 | SP: Wireformat.pcm, 567 | LP2: Wireformat.lp2, 568 | LP105: Wireformat.l105kbps, 569 | LP4: Wireformat.lp4, 570 | }; 571 | format = WireformatDict[format]; 572 | 573 | let written = 0; 574 | 575 | let lastTime = 0; 576 | 577 | function updateProgress() { 578 | let newTime = new Date().getTime(); 579 | if(newTime - lastTime > 100){ 580 | ws.send(JSON.stringify({ 581 | written 582 | })); 583 | lastTime = newTime; 584 | } 585 | } 586 | 587 | let halfWidthTitle = sanitizeHalfWidthTitle(title); 588 | fullWidthTitle = sanitizeFullWidthTitle(fullWidthTitle); 589 | 590 | let queue = []; 591 | 592 | ws.on('message', async _piece => { 593 | // Deserialize data 594 | try{ 595 | const piece = new Uint8Array(_piece); 596 | const type = piece[0]; 597 | if(type === 0){ 598 | const iv = piece.subarray(1, 9); 599 | const key = piece.subarray(9, 17); 600 | const data = piece.subarray(17); 601 | queue.push({ iv, key, data }); 602 | }else{ 603 | console.log(`As of the start of upload, received ${queue.length} packets. Expecting ${totalLength} bytes got ${queue.reduce((a, b) => a + b.data.length, 0)}`); 604 | let mdTrack = new MDTrack(halfWidthTitle, format, { 605 | byteLength: parseInt(totalLength), 606 | }, 0x400, fullWidthTitle, () => ({ 607 | async *[Symbol.asyncIterator](){ 608 | for(let e of queue){ 609 | yield e; 610 | } 611 | } 612 | })); 613 | await session.downloadTrack(mdTrack, ({ 614 | writtenBytes 615 | }) => { 616 | written = writtenBytes; 617 | updateProgress(); 618 | }); 619 | 620 | flushCache(); 621 | ws.send(JSON.stringify({ terminate: true })); 622 | console.log("Upload completed."); 623 | release(); 624 | 625 | } 626 | }catch(ex){ 627 | console.log(ex); 628 | } 629 | }); 630 | 631 | ws.send(JSON.stringify({ init: true })); 632 | }).catch(e => console.log(e)); 633 | }); 634 | 635 | app.get('/upload', (res, req) => fail(req, "This is a WebSocket-only endpoint.")); 636 | } 637 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "netmd-serv", 3 | "version": "0.1.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "netmd-serv", 9 | "version": "0.1.0", 10 | "license": "GPL v2", 11 | "dependencies": { 12 | "async-mutex": "^0.3.2", 13 | "express": "^4.17.1", 14 | "express-ws": "^5.0.2", 15 | "netmd-js": "file:../netmd-js-workingtree", 16 | "usb": "^2.7.0", 17 | "yargs": "^17.3.1" 18 | } 19 | }, 20 | "../netmd-js-workingtree": { 21 | "version": "4.1.3", 22 | "license": "GPL-2.0", 23 | "dependencies": { 24 | "@originjs/crypto-js-wasm": "github:asivery/crypto-js-wasm", 25 | "browser-bunyan": "^1.5.3", 26 | "buffer": "^5.5.0", 27 | "bunyan": "^1.8.12", 28 | "diacritics": "^1.3.0", 29 | "jconv": "^0.1.5", 30 | "jsbi": "^3.1.1", 31 | "usb": "^2.4.2", 32 | "yargs": "^15.1.0" 33 | }, 34 | "bin": { 35 | "netmdcli": "dist/cli.js" 36 | }, 37 | "devDependencies": { 38 | "@types/browser-bunyan": "^0.4.5", 39 | "@types/bunyan": "^1.8.6", 40 | "@types/diacritics": "^1.3.1", 41 | "@types/jest": "^25.1.2", 42 | "@types/node": "^13.9.0", 43 | "@types/w3c-web-usb": "^1.0.4", 44 | "@types/yargs": "^15.0.4", 45 | "husky": "^4.2.3", 46 | "jest": "^25.1.0", 47 | "lint-staged": "^10.0.8", 48 | "prettier": "^1.19.1", 49 | "ts-jest": "^25.2.0", 50 | "ts-node": "^10.8.1", 51 | "typescript": "^3.9.10" 52 | }, 53 | "engines": { 54 | "node": ">=12.0.0" 55 | } 56 | }, 57 | "node_modules/@types/w3c-web-usb": { 58 | "version": "1.0.6", 59 | "resolved": "https://registry.npmjs.org/@types/w3c-web-usb/-/w3c-web-usb-1.0.6.tgz", 60 | "integrity": "sha512-cSjhgrr8g4KbPnnijAr/KJDNKa/bBa+ixYkywFRvrhvi9n1WEl7yYbtRyzE6jqNQiSxxJxoAW3STaOQwJHndaw==" 61 | }, 62 | "node_modules/accepts": { 63 | "version": "1.3.7", 64 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 65 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 66 | "dependencies": { 67 | "mime-types": "~2.1.24", 68 | "negotiator": "0.6.2" 69 | }, 70 | "engines": { 71 | "node": ">= 0.6" 72 | } 73 | }, 74 | "node_modules/ansi-regex": { 75 | "version": "5.0.1", 76 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 77 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 78 | "engines": { 79 | "node": ">=8" 80 | } 81 | }, 82 | "node_modules/ansi-styles": { 83 | "version": "4.3.0", 84 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 85 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 86 | "dependencies": { 87 | "color-convert": "^2.0.1" 88 | }, 89 | "engines": { 90 | "node": ">=8" 91 | }, 92 | "funding": { 93 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 94 | } 95 | }, 96 | "node_modules/array-flatten": { 97 | "version": "1.1.1", 98 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 99 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 100 | }, 101 | "node_modules/async-mutex": { 102 | "version": "0.3.2", 103 | "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.3.2.tgz", 104 | "integrity": "sha512-HuTK7E7MT7jZEh1P9GtRW9+aTWiDWWi9InbZ5hjxrnRa39KS4BW04+xLBhYNS2aXhHUIKZSw3gj4Pn1pj+qGAA==", 105 | "dependencies": { 106 | "tslib": "^2.3.1" 107 | } 108 | }, 109 | "node_modules/body-parser": { 110 | "version": "1.19.0", 111 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 112 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 113 | "dependencies": { 114 | "bytes": "3.1.0", 115 | "content-type": "~1.0.4", 116 | "debug": "2.6.9", 117 | "depd": "~1.1.2", 118 | "http-errors": "1.7.2", 119 | "iconv-lite": "0.4.24", 120 | "on-finished": "~2.3.0", 121 | "qs": "6.7.0", 122 | "raw-body": "2.4.0", 123 | "type-is": "~1.6.17" 124 | }, 125 | "engines": { 126 | "node": ">= 0.8" 127 | } 128 | }, 129 | "node_modules/bytes": { 130 | "version": "3.1.0", 131 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 132 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", 133 | "engines": { 134 | "node": ">= 0.8" 135 | } 136 | }, 137 | "node_modules/cliui": { 138 | "version": "7.0.4", 139 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 140 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 141 | "dependencies": { 142 | "string-width": "^4.2.0", 143 | "strip-ansi": "^6.0.0", 144 | "wrap-ansi": "^7.0.0" 145 | } 146 | }, 147 | "node_modules/color-convert": { 148 | "version": "2.0.1", 149 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 150 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 151 | "dependencies": { 152 | "color-name": "~1.1.4" 153 | }, 154 | "engines": { 155 | "node": ">=7.0.0" 156 | } 157 | }, 158 | "node_modules/color-name": { 159 | "version": "1.1.4", 160 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 161 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 162 | }, 163 | "node_modules/content-disposition": { 164 | "version": "0.5.3", 165 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 166 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 167 | "dependencies": { 168 | "safe-buffer": "5.1.2" 169 | }, 170 | "engines": { 171 | "node": ">= 0.6" 172 | } 173 | }, 174 | "node_modules/content-type": { 175 | "version": "1.0.4", 176 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 177 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", 178 | "engines": { 179 | "node": ">= 0.6" 180 | } 181 | }, 182 | "node_modules/cookie": { 183 | "version": "0.4.0", 184 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 185 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", 186 | "engines": { 187 | "node": ">= 0.6" 188 | } 189 | }, 190 | "node_modules/cookie-signature": { 191 | "version": "1.0.6", 192 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 193 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 194 | }, 195 | "node_modules/debug": { 196 | "version": "2.6.9", 197 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 198 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 199 | "dependencies": { 200 | "ms": "2.0.0" 201 | } 202 | }, 203 | "node_modules/depd": { 204 | "version": "1.1.2", 205 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 206 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", 207 | "engines": { 208 | "node": ">= 0.6" 209 | } 210 | }, 211 | "node_modules/destroy": { 212 | "version": "1.0.4", 213 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 214 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 215 | }, 216 | "node_modules/ee-first": { 217 | "version": "1.1.1", 218 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 219 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 220 | }, 221 | "node_modules/emoji-regex": { 222 | "version": "8.0.0", 223 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 224 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 225 | }, 226 | "node_modules/encodeurl": { 227 | "version": "1.0.2", 228 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 229 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", 230 | "engines": { 231 | "node": ">= 0.8" 232 | } 233 | }, 234 | "node_modules/escalade": { 235 | "version": "3.1.1", 236 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 237 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 238 | "engines": { 239 | "node": ">=6" 240 | } 241 | }, 242 | "node_modules/escape-html": { 243 | "version": "1.0.3", 244 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 245 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 246 | }, 247 | "node_modules/etag": { 248 | "version": "1.8.1", 249 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 250 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", 251 | "engines": { 252 | "node": ">= 0.6" 253 | } 254 | }, 255 | "node_modules/express": { 256 | "version": "4.17.1", 257 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 258 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 259 | "dependencies": { 260 | "accepts": "~1.3.7", 261 | "array-flatten": "1.1.1", 262 | "body-parser": "1.19.0", 263 | "content-disposition": "0.5.3", 264 | "content-type": "~1.0.4", 265 | "cookie": "0.4.0", 266 | "cookie-signature": "1.0.6", 267 | "debug": "2.6.9", 268 | "depd": "~1.1.2", 269 | "encodeurl": "~1.0.2", 270 | "escape-html": "~1.0.3", 271 | "etag": "~1.8.1", 272 | "finalhandler": "~1.1.2", 273 | "fresh": "0.5.2", 274 | "merge-descriptors": "1.0.1", 275 | "methods": "~1.1.2", 276 | "on-finished": "~2.3.0", 277 | "parseurl": "~1.3.3", 278 | "path-to-regexp": "0.1.7", 279 | "proxy-addr": "~2.0.5", 280 | "qs": "6.7.0", 281 | "range-parser": "~1.2.1", 282 | "safe-buffer": "5.1.2", 283 | "send": "0.17.1", 284 | "serve-static": "1.14.1", 285 | "setprototypeof": "1.1.1", 286 | "statuses": "~1.5.0", 287 | "type-is": "~1.6.18", 288 | "utils-merge": "1.0.1", 289 | "vary": "~1.1.2" 290 | }, 291 | "engines": { 292 | "node": ">= 0.10.0" 293 | } 294 | }, 295 | "node_modules/express-ws": { 296 | "version": "5.0.2", 297 | "resolved": "https://registry.npmjs.org/express-ws/-/express-ws-5.0.2.tgz", 298 | "integrity": "sha512-0uvmuk61O9HXgLhGl3QhNSEtRsQevtmbL94/eILaliEADZBHZOQUAiHFrGPrgsjikohyrmSG5g+sCfASTt0lkQ==", 299 | "dependencies": { 300 | "ws": "^7.4.6" 301 | }, 302 | "engines": { 303 | "node": ">=4.5.0" 304 | }, 305 | "peerDependencies": { 306 | "express": "^4.0.0 || ^5.0.0-alpha.1" 307 | } 308 | }, 309 | "node_modules/finalhandler": { 310 | "version": "1.1.2", 311 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 312 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 313 | "dependencies": { 314 | "debug": "2.6.9", 315 | "encodeurl": "~1.0.2", 316 | "escape-html": "~1.0.3", 317 | "on-finished": "~2.3.0", 318 | "parseurl": "~1.3.3", 319 | "statuses": "~1.5.0", 320 | "unpipe": "~1.0.0" 321 | }, 322 | "engines": { 323 | "node": ">= 0.8" 324 | } 325 | }, 326 | "node_modules/forwarded": { 327 | "version": "0.2.0", 328 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 329 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 330 | "engines": { 331 | "node": ">= 0.6" 332 | } 333 | }, 334 | "node_modules/fresh": { 335 | "version": "0.5.2", 336 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 337 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", 338 | "engines": { 339 | "node": ">= 0.6" 340 | } 341 | }, 342 | "node_modules/get-caller-file": { 343 | "version": "2.0.5", 344 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 345 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 346 | "engines": { 347 | "node": "6.* || 8.* || >= 10.*" 348 | } 349 | }, 350 | "node_modules/http-errors": { 351 | "version": "1.7.2", 352 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 353 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 354 | "dependencies": { 355 | "depd": "~1.1.2", 356 | "inherits": "2.0.3", 357 | "setprototypeof": "1.1.1", 358 | "statuses": ">= 1.5.0 < 2", 359 | "toidentifier": "1.0.0" 360 | }, 361 | "engines": { 362 | "node": ">= 0.6" 363 | } 364 | }, 365 | "node_modules/iconv-lite": { 366 | "version": "0.4.24", 367 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 368 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 369 | "dependencies": { 370 | "safer-buffer": ">= 2.1.2 < 3" 371 | }, 372 | "engines": { 373 | "node": ">=0.10.0" 374 | } 375 | }, 376 | "node_modules/inherits": { 377 | "version": "2.0.3", 378 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 379 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 380 | }, 381 | "node_modules/ipaddr.js": { 382 | "version": "1.9.1", 383 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 384 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 385 | "engines": { 386 | "node": ">= 0.10" 387 | } 388 | }, 389 | "node_modules/is-fullwidth-code-point": { 390 | "version": "3.0.0", 391 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 392 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 393 | "engines": { 394 | "node": ">=8" 395 | } 396 | }, 397 | "node_modules/media-typer": { 398 | "version": "0.3.0", 399 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 400 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", 401 | "engines": { 402 | "node": ">= 0.6" 403 | } 404 | }, 405 | "node_modules/merge-descriptors": { 406 | "version": "1.0.1", 407 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 408 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 409 | }, 410 | "node_modules/methods": { 411 | "version": "1.1.2", 412 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 413 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", 414 | "engines": { 415 | "node": ">= 0.6" 416 | } 417 | }, 418 | "node_modules/mime": { 419 | "version": "1.6.0", 420 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 421 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 422 | "bin": { 423 | "mime": "cli.js" 424 | }, 425 | "engines": { 426 | "node": ">=4" 427 | } 428 | }, 429 | "node_modules/mime-db": { 430 | "version": "1.51.0", 431 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", 432 | "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", 433 | "engines": { 434 | "node": ">= 0.6" 435 | } 436 | }, 437 | "node_modules/mime-types": { 438 | "version": "2.1.34", 439 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", 440 | "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", 441 | "dependencies": { 442 | "mime-db": "1.51.0" 443 | }, 444 | "engines": { 445 | "node": ">= 0.6" 446 | } 447 | }, 448 | "node_modules/ms": { 449 | "version": "2.0.0", 450 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 451 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 452 | }, 453 | "node_modules/negotiator": { 454 | "version": "0.6.2", 455 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 456 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", 457 | "engines": { 458 | "node": ">= 0.6" 459 | } 460 | }, 461 | "node_modules/netmd-js": { 462 | "resolved": "../netmd-js-workingtree", 463 | "link": true 464 | }, 465 | "node_modules/node-addon-api": { 466 | "version": "5.1.0", 467 | "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", 468 | "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" 469 | }, 470 | "node_modules/node-gyp-build": { 471 | "version": "4.6.0", 472 | "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", 473 | "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", 474 | "bin": { 475 | "node-gyp-build": "bin.js", 476 | "node-gyp-build-optional": "optional.js", 477 | "node-gyp-build-test": "build-test.js" 478 | } 479 | }, 480 | "node_modules/on-finished": { 481 | "version": "2.3.0", 482 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 483 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 484 | "dependencies": { 485 | "ee-first": "1.1.1" 486 | }, 487 | "engines": { 488 | "node": ">= 0.8" 489 | } 490 | }, 491 | "node_modules/parseurl": { 492 | "version": "1.3.3", 493 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 494 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 495 | "engines": { 496 | "node": ">= 0.8" 497 | } 498 | }, 499 | "node_modules/path-to-regexp": { 500 | "version": "0.1.7", 501 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 502 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 503 | }, 504 | "node_modules/proxy-addr": { 505 | "version": "2.0.7", 506 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 507 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 508 | "dependencies": { 509 | "forwarded": "0.2.0", 510 | "ipaddr.js": "1.9.1" 511 | }, 512 | "engines": { 513 | "node": ">= 0.10" 514 | } 515 | }, 516 | "node_modules/qs": { 517 | "version": "6.7.0", 518 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 519 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", 520 | "engines": { 521 | "node": ">=0.6" 522 | } 523 | }, 524 | "node_modules/range-parser": { 525 | "version": "1.2.1", 526 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 527 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 528 | "engines": { 529 | "node": ">= 0.6" 530 | } 531 | }, 532 | "node_modules/raw-body": { 533 | "version": "2.4.0", 534 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 535 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 536 | "dependencies": { 537 | "bytes": "3.1.0", 538 | "http-errors": "1.7.2", 539 | "iconv-lite": "0.4.24", 540 | "unpipe": "1.0.0" 541 | }, 542 | "engines": { 543 | "node": ">= 0.8" 544 | } 545 | }, 546 | "node_modules/require-directory": { 547 | "version": "2.1.1", 548 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 549 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 550 | "engines": { 551 | "node": ">=0.10.0" 552 | } 553 | }, 554 | "node_modules/safe-buffer": { 555 | "version": "5.1.2", 556 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 557 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 558 | }, 559 | "node_modules/safer-buffer": { 560 | "version": "2.1.2", 561 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 562 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 563 | }, 564 | "node_modules/send": { 565 | "version": "0.17.1", 566 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 567 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 568 | "dependencies": { 569 | "debug": "2.6.9", 570 | "depd": "~1.1.2", 571 | "destroy": "~1.0.4", 572 | "encodeurl": "~1.0.2", 573 | "escape-html": "~1.0.3", 574 | "etag": "~1.8.1", 575 | "fresh": "0.5.2", 576 | "http-errors": "~1.7.2", 577 | "mime": "1.6.0", 578 | "ms": "2.1.1", 579 | "on-finished": "~2.3.0", 580 | "range-parser": "~1.2.1", 581 | "statuses": "~1.5.0" 582 | }, 583 | "engines": { 584 | "node": ">= 0.8.0" 585 | } 586 | }, 587 | "node_modules/send/node_modules/ms": { 588 | "version": "2.1.1", 589 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 590 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 591 | }, 592 | "node_modules/serve-static": { 593 | "version": "1.14.1", 594 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 595 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 596 | "dependencies": { 597 | "encodeurl": "~1.0.2", 598 | "escape-html": "~1.0.3", 599 | "parseurl": "~1.3.3", 600 | "send": "0.17.1" 601 | }, 602 | "engines": { 603 | "node": ">= 0.8.0" 604 | } 605 | }, 606 | "node_modules/setprototypeof": { 607 | "version": "1.1.1", 608 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 609 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 610 | }, 611 | "node_modules/statuses": { 612 | "version": "1.5.0", 613 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 614 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", 615 | "engines": { 616 | "node": ">= 0.6" 617 | } 618 | }, 619 | "node_modules/string-width": { 620 | "version": "4.2.3", 621 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 622 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 623 | "dependencies": { 624 | "emoji-regex": "^8.0.0", 625 | "is-fullwidth-code-point": "^3.0.0", 626 | "strip-ansi": "^6.0.1" 627 | }, 628 | "engines": { 629 | "node": ">=8" 630 | } 631 | }, 632 | "node_modules/strip-ansi": { 633 | "version": "6.0.1", 634 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 635 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 636 | "dependencies": { 637 | "ansi-regex": "^5.0.1" 638 | }, 639 | "engines": { 640 | "node": ">=8" 641 | } 642 | }, 643 | "node_modules/toidentifier": { 644 | "version": "1.0.0", 645 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 646 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", 647 | "engines": { 648 | "node": ">=0.6" 649 | } 650 | }, 651 | "node_modules/tslib": { 652 | "version": "2.3.1", 653 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", 654 | "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" 655 | }, 656 | "node_modules/type-is": { 657 | "version": "1.6.18", 658 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 659 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 660 | "dependencies": { 661 | "media-typer": "0.3.0", 662 | "mime-types": "~2.1.24" 663 | }, 664 | "engines": { 665 | "node": ">= 0.6" 666 | } 667 | }, 668 | "node_modules/unpipe": { 669 | "version": "1.0.0", 670 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 671 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", 672 | "engines": { 673 | "node": ">= 0.8" 674 | } 675 | }, 676 | "node_modules/usb": { 677 | "version": "2.7.0", 678 | "resolved": "https://registry.npmjs.org/usb/-/usb-2.7.0.tgz", 679 | "integrity": "sha512-63sB4hPrueUojpeNc8FpXkwO7CL36WbLSnrbK9S4QtS2+2FvZs3Ju8PGWRy2e7DaHLxYekFOJZMyZQ3ZmSu7Ag==", 680 | "hasInstallScript": true, 681 | "dependencies": { 682 | "@types/w3c-web-usb": "^1.0.6", 683 | "node-addon-api": "^5.0.0", 684 | "node-gyp-build": "^4.5.0" 685 | }, 686 | "engines": { 687 | "node": ">=10.20.0 <11.x || >=12.17.0 <13.0 || >=14.0.0" 688 | } 689 | }, 690 | "node_modules/utils-merge": { 691 | "version": "1.0.1", 692 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 693 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", 694 | "engines": { 695 | "node": ">= 0.4.0" 696 | } 697 | }, 698 | "node_modules/vary": { 699 | "version": "1.1.2", 700 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 701 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", 702 | "engines": { 703 | "node": ">= 0.8" 704 | } 705 | }, 706 | "node_modules/wrap-ansi": { 707 | "version": "7.0.0", 708 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 709 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 710 | "dependencies": { 711 | "ansi-styles": "^4.0.0", 712 | "string-width": "^4.1.0", 713 | "strip-ansi": "^6.0.0" 714 | }, 715 | "engines": { 716 | "node": ">=10" 717 | }, 718 | "funding": { 719 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 720 | } 721 | }, 722 | "node_modules/ws": { 723 | "version": "7.5.6", 724 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz", 725 | "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==", 726 | "engines": { 727 | "node": ">=8.3.0" 728 | }, 729 | "peerDependencies": { 730 | "bufferutil": "^4.0.1", 731 | "utf-8-validate": "^5.0.2" 732 | }, 733 | "peerDependenciesMeta": { 734 | "bufferutil": { 735 | "optional": true 736 | }, 737 | "utf-8-validate": { 738 | "optional": true 739 | } 740 | } 741 | }, 742 | "node_modules/y18n": { 743 | "version": "5.0.8", 744 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 745 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 746 | "engines": { 747 | "node": ">=10" 748 | } 749 | }, 750 | "node_modules/yargs": { 751 | "version": "17.3.1", 752 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", 753 | "integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==", 754 | "dependencies": { 755 | "cliui": "^7.0.2", 756 | "escalade": "^3.1.1", 757 | "get-caller-file": "^2.0.5", 758 | "require-directory": "^2.1.1", 759 | "string-width": "^4.2.3", 760 | "y18n": "^5.0.5", 761 | "yargs-parser": "^21.0.0" 762 | }, 763 | "engines": { 764 | "node": ">=12" 765 | } 766 | }, 767 | "node_modules/yargs-parser": { 768 | "version": "21.0.0", 769 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz", 770 | "integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==", 771 | "engines": { 772 | "node": ">=12" 773 | } 774 | } 775 | }, 776 | "dependencies": { 777 | "@types/w3c-web-usb": { 778 | "version": "1.0.6", 779 | "resolved": "https://registry.npmjs.org/@types/w3c-web-usb/-/w3c-web-usb-1.0.6.tgz", 780 | "integrity": "sha512-cSjhgrr8g4KbPnnijAr/KJDNKa/bBa+ixYkywFRvrhvi9n1WEl7yYbtRyzE6jqNQiSxxJxoAW3STaOQwJHndaw==" 781 | }, 782 | "accepts": { 783 | "version": "1.3.7", 784 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 785 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 786 | "requires": { 787 | "mime-types": "~2.1.24", 788 | "negotiator": "0.6.2" 789 | } 790 | }, 791 | "ansi-regex": { 792 | "version": "5.0.1", 793 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 794 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" 795 | }, 796 | "ansi-styles": { 797 | "version": "4.3.0", 798 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 799 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 800 | "requires": { 801 | "color-convert": "^2.0.1" 802 | } 803 | }, 804 | "array-flatten": { 805 | "version": "1.1.1", 806 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 807 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 808 | }, 809 | "async-mutex": { 810 | "version": "0.3.2", 811 | "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.3.2.tgz", 812 | "integrity": "sha512-HuTK7E7MT7jZEh1P9GtRW9+aTWiDWWi9InbZ5hjxrnRa39KS4BW04+xLBhYNS2aXhHUIKZSw3gj4Pn1pj+qGAA==", 813 | "requires": { 814 | "tslib": "^2.3.1" 815 | } 816 | }, 817 | "body-parser": { 818 | "version": "1.19.0", 819 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 820 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 821 | "requires": { 822 | "bytes": "3.1.0", 823 | "content-type": "~1.0.4", 824 | "debug": "2.6.9", 825 | "depd": "~1.1.2", 826 | "http-errors": "1.7.2", 827 | "iconv-lite": "0.4.24", 828 | "on-finished": "~2.3.0", 829 | "qs": "6.7.0", 830 | "raw-body": "2.4.0", 831 | "type-is": "~1.6.17" 832 | } 833 | }, 834 | "bytes": { 835 | "version": "3.1.0", 836 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 837 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 838 | }, 839 | "cliui": { 840 | "version": "7.0.4", 841 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 842 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 843 | "requires": { 844 | "string-width": "^4.2.0", 845 | "strip-ansi": "^6.0.0", 846 | "wrap-ansi": "^7.0.0" 847 | } 848 | }, 849 | "color-convert": { 850 | "version": "2.0.1", 851 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 852 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 853 | "requires": { 854 | "color-name": "~1.1.4" 855 | } 856 | }, 857 | "color-name": { 858 | "version": "1.1.4", 859 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 860 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 861 | }, 862 | "content-disposition": { 863 | "version": "0.5.3", 864 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 865 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 866 | "requires": { 867 | "safe-buffer": "5.1.2" 868 | } 869 | }, 870 | "content-type": { 871 | "version": "1.0.4", 872 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 873 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 874 | }, 875 | "cookie": { 876 | "version": "0.4.0", 877 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 878 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 879 | }, 880 | "cookie-signature": { 881 | "version": "1.0.6", 882 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 883 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 884 | }, 885 | "debug": { 886 | "version": "2.6.9", 887 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 888 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 889 | "requires": { 890 | "ms": "2.0.0" 891 | } 892 | }, 893 | "depd": { 894 | "version": "1.1.2", 895 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 896 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 897 | }, 898 | "destroy": { 899 | "version": "1.0.4", 900 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 901 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 902 | }, 903 | "ee-first": { 904 | "version": "1.1.1", 905 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 906 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 907 | }, 908 | "emoji-regex": { 909 | "version": "8.0.0", 910 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 911 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 912 | }, 913 | "encodeurl": { 914 | "version": "1.0.2", 915 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 916 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 917 | }, 918 | "escalade": { 919 | "version": "3.1.1", 920 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 921 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" 922 | }, 923 | "escape-html": { 924 | "version": "1.0.3", 925 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 926 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 927 | }, 928 | "etag": { 929 | "version": "1.8.1", 930 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 931 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 932 | }, 933 | "express": { 934 | "version": "4.17.1", 935 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 936 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 937 | "requires": { 938 | "accepts": "~1.3.7", 939 | "array-flatten": "1.1.1", 940 | "body-parser": "1.19.0", 941 | "content-disposition": "0.5.3", 942 | "content-type": "~1.0.4", 943 | "cookie": "0.4.0", 944 | "cookie-signature": "1.0.6", 945 | "debug": "2.6.9", 946 | "depd": "~1.1.2", 947 | "encodeurl": "~1.0.2", 948 | "escape-html": "~1.0.3", 949 | "etag": "~1.8.1", 950 | "finalhandler": "~1.1.2", 951 | "fresh": "0.5.2", 952 | "merge-descriptors": "1.0.1", 953 | "methods": "~1.1.2", 954 | "on-finished": "~2.3.0", 955 | "parseurl": "~1.3.3", 956 | "path-to-regexp": "0.1.7", 957 | "proxy-addr": "~2.0.5", 958 | "qs": "6.7.0", 959 | "range-parser": "~1.2.1", 960 | "safe-buffer": "5.1.2", 961 | "send": "0.17.1", 962 | "serve-static": "1.14.1", 963 | "setprototypeof": "1.1.1", 964 | "statuses": "~1.5.0", 965 | "type-is": "~1.6.18", 966 | "utils-merge": "1.0.1", 967 | "vary": "~1.1.2" 968 | } 969 | }, 970 | "express-ws": { 971 | "version": "5.0.2", 972 | "resolved": "https://registry.npmjs.org/express-ws/-/express-ws-5.0.2.tgz", 973 | "integrity": "sha512-0uvmuk61O9HXgLhGl3QhNSEtRsQevtmbL94/eILaliEADZBHZOQUAiHFrGPrgsjikohyrmSG5g+sCfASTt0lkQ==", 974 | "requires": { 975 | "ws": "^7.4.6" 976 | } 977 | }, 978 | "finalhandler": { 979 | "version": "1.1.2", 980 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 981 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 982 | "requires": { 983 | "debug": "2.6.9", 984 | "encodeurl": "~1.0.2", 985 | "escape-html": "~1.0.3", 986 | "on-finished": "~2.3.0", 987 | "parseurl": "~1.3.3", 988 | "statuses": "~1.5.0", 989 | "unpipe": "~1.0.0" 990 | } 991 | }, 992 | "forwarded": { 993 | "version": "0.2.0", 994 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 995 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" 996 | }, 997 | "fresh": { 998 | "version": "0.5.2", 999 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 1000 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 1001 | }, 1002 | "get-caller-file": { 1003 | "version": "2.0.5", 1004 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 1005 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" 1006 | }, 1007 | "http-errors": { 1008 | "version": "1.7.2", 1009 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 1010 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 1011 | "requires": { 1012 | "depd": "~1.1.2", 1013 | "inherits": "2.0.3", 1014 | "setprototypeof": "1.1.1", 1015 | "statuses": ">= 1.5.0 < 2", 1016 | "toidentifier": "1.0.0" 1017 | } 1018 | }, 1019 | "iconv-lite": { 1020 | "version": "0.4.24", 1021 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 1022 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 1023 | "requires": { 1024 | "safer-buffer": ">= 2.1.2 < 3" 1025 | } 1026 | }, 1027 | "inherits": { 1028 | "version": "2.0.3", 1029 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 1030 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 1031 | }, 1032 | "ipaddr.js": { 1033 | "version": "1.9.1", 1034 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 1035 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 1036 | }, 1037 | "is-fullwidth-code-point": { 1038 | "version": "3.0.0", 1039 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 1040 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" 1041 | }, 1042 | "media-typer": { 1043 | "version": "0.3.0", 1044 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 1045 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 1046 | }, 1047 | "merge-descriptors": { 1048 | "version": "1.0.1", 1049 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 1050 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 1051 | }, 1052 | "methods": { 1053 | "version": "1.1.2", 1054 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 1055 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 1056 | }, 1057 | "mime": { 1058 | "version": "1.6.0", 1059 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 1060 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 1061 | }, 1062 | "mime-db": { 1063 | "version": "1.51.0", 1064 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", 1065 | "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" 1066 | }, 1067 | "mime-types": { 1068 | "version": "2.1.34", 1069 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", 1070 | "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", 1071 | "requires": { 1072 | "mime-db": "1.51.0" 1073 | } 1074 | }, 1075 | "ms": { 1076 | "version": "2.0.0", 1077 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1078 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1079 | }, 1080 | "negotiator": { 1081 | "version": "0.6.2", 1082 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 1083 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 1084 | }, 1085 | "netmd-js": { 1086 | "version": "file:../netmd-js-workingtree", 1087 | "requires": { 1088 | "@originjs/crypto-js-wasm": "github:asivery/crypto-js-wasm", 1089 | "@types/browser-bunyan": "^0.4.5", 1090 | "@types/bunyan": "^1.8.6", 1091 | "@types/diacritics": "^1.3.1", 1092 | "@types/jest": "^25.1.2", 1093 | "@types/node": "^13.9.0", 1094 | "@types/w3c-web-usb": "^1.0.4", 1095 | "@types/yargs": "^15.0.4", 1096 | "browser-bunyan": "^1.5.3", 1097 | "buffer": "^5.5.0", 1098 | "bunyan": "^1.8.12", 1099 | "diacritics": "^1.3.0", 1100 | "husky": "^4.2.3", 1101 | "jconv": "^0.1.5", 1102 | "jest": "^25.1.0", 1103 | "jsbi": "^3.1.1", 1104 | "lint-staged": "^10.0.8", 1105 | "prettier": "^1.19.1", 1106 | "ts-jest": "^25.2.0", 1107 | "ts-node": "^10.8.1", 1108 | "typescript": "^3.9.10", 1109 | "usb": "^2.4.2", 1110 | "yargs": "^15.1.0" 1111 | } 1112 | }, 1113 | "node-addon-api": { 1114 | "version": "5.1.0", 1115 | "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", 1116 | "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" 1117 | }, 1118 | "node-gyp-build": { 1119 | "version": "4.6.0", 1120 | "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", 1121 | "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==" 1122 | }, 1123 | "on-finished": { 1124 | "version": "2.3.0", 1125 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 1126 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 1127 | "requires": { 1128 | "ee-first": "1.1.1" 1129 | } 1130 | }, 1131 | "parseurl": { 1132 | "version": "1.3.3", 1133 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1134 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 1135 | }, 1136 | "path-to-regexp": { 1137 | "version": "0.1.7", 1138 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 1139 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 1140 | }, 1141 | "proxy-addr": { 1142 | "version": "2.0.7", 1143 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 1144 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 1145 | "requires": { 1146 | "forwarded": "0.2.0", 1147 | "ipaddr.js": "1.9.1" 1148 | } 1149 | }, 1150 | "qs": { 1151 | "version": "6.7.0", 1152 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 1153 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 1154 | }, 1155 | "range-parser": { 1156 | "version": "1.2.1", 1157 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1158 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 1159 | }, 1160 | "raw-body": { 1161 | "version": "2.4.0", 1162 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 1163 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 1164 | "requires": { 1165 | "bytes": "3.1.0", 1166 | "http-errors": "1.7.2", 1167 | "iconv-lite": "0.4.24", 1168 | "unpipe": "1.0.0" 1169 | } 1170 | }, 1171 | "require-directory": { 1172 | "version": "2.1.1", 1173 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1174 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" 1175 | }, 1176 | "safe-buffer": { 1177 | "version": "5.1.2", 1178 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1179 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1180 | }, 1181 | "safer-buffer": { 1182 | "version": "2.1.2", 1183 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1184 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1185 | }, 1186 | "send": { 1187 | "version": "0.17.1", 1188 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 1189 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 1190 | "requires": { 1191 | "debug": "2.6.9", 1192 | "depd": "~1.1.2", 1193 | "destroy": "~1.0.4", 1194 | "encodeurl": "~1.0.2", 1195 | "escape-html": "~1.0.3", 1196 | "etag": "~1.8.1", 1197 | "fresh": "0.5.2", 1198 | "http-errors": "~1.7.2", 1199 | "mime": "1.6.0", 1200 | "ms": "2.1.1", 1201 | "on-finished": "~2.3.0", 1202 | "range-parser": "~1.2.1", 1203 | "statuses": "~1.5.0" 1204 | }, 1205 | "dependencies": { 1206 | "ms": { 1207 | "version": "2.1.1", 1208 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 1209 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 1210 | } 1211 | } 1212 | }, 1213 | "serve-static": { 1214 | "version": "1.14.1", 1215 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 1216 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 1217 | "requires": { 1218 | "encodeurl": "~1.0.2", 1219 | "escape-html": "~1.0.3", 1220 | "parseurl": "~1.3.3", 1221 | "send": "0.17.1" 1222 | } 1223 | }, 1224 | "setprototypeof": { 1225 | "version": "1.1.1", 1226 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 1227 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 1228 | }, 1229 | "statuses": { 1230 | "version": "1.5.0", 1231 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 1232 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 1233 | }, 1234 | "string-width": { 1235 | "version": "4.2.3", 1236 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1237 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1238 | "requires": { 1239 | "emoji-regex": "^8.0.0", 1240 | "is-fullwidth-code-point": "^3.0.0", 1241 | "strip-ansi": "^6.0.1" 1242 | } 1243 | }, 1244 | "strip-ansi": { 1245 | "version": "6.0.1", 1246 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1247 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1248 | "requires": { 1249 | "ansi-regex": "^5.0.1" 1250 | } 1251 | }, 1252 | "toidentifier": { 1253 | "version": "1.0.0", 1254 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 1255 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 1256 | }, 1257 | "tslib": { 1258 | "version": "2.3.1", 1259 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", 1260 | "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" 1261 | }, 1262 | "type-is": { 1263 | "version": "1.6.18", 1264 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1265 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1266 | "requires": { 1267 | "media-typer": "0.3.0", 1268 | "mime-types": "~2.1.24" 1269 | } 1270 | }, 1271 | "unpipe": { 1272 | "version": "1.0.0", 1273 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1274 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 1275 | }, 1276 | "usb": { 1277 | "version": "2.7.0", 1278 | "resolved": "https://registry.npmjs.org/usb/-/usb-2.7.0.tgz", 1279 | "integrity": "sha512-63sB4hPrueUojpeNc8FpXkwO7CL36WbLSnrbK9S4QtS2+2FvZs3Ju8PGWRy2e7DaHLxYekFOJZMyZQ3ZmSu7Ag==", 1280 | "requires": { 1281 | "@types/w3c-web-usb": "^1.0.6", 1282 | "node-addon-api": "^5.0.0", 1283 | "node-gyp-build": "^4.5.0" 1284 | } 1285 | }, 1286 | "utils-merge": { 1287 | "version": "1.0.1", 1288 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1289 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 1290 | }, 1291 | "vary": { 1292 | "version": "1.1.2", 1293 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1294 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 1295 | }, 1296 | "wrap-ansi": { 1297 | "version": "7.0.0", 1298 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 1299 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 1300 | "requires": { 1301 | "ansi-styles": "^4.0.0", 1302 | "string-width": "^4.1.0", 1303 | "strip-ansi": "^6.0.0" 1304 | } 1305 | }, 1306 | "ws": { 1307 | "version": "7.5.6", 1308 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz", 1309 | "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==" 1310 | }, 1311 | "y18n": { 1312 | "version": "5.0.8", 1313 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 1314 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" 1315 | }, 1316 | "yargs": { 1317 | "version": "17.3.1", 1318 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", 1319 | "integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==", 1320 | "requires": { 1321 | "cliui": "^7.0.2", 1322 | "escalade": "^3.1.1", 1323 | "get-caller-file": "^2.0.5", 1324 | "require-directory": "^2.1.1", 1325 | "string-width": "^4.2.3", 1326 | "y18n": "^5.0.5", 1327 | "yargs-parser": "^21.0.0" 1328 | } 1329 | }, 1330 | "yargs-parser": { 1331 | "version": "21.0.0", 1332 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz", 1333 | "integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==" 1334 | } 1335 | } 1336 | } 1337 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "netmd-serv", 3 | "version": "0.1.0", 4 | "description": "NetMD recorder server", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "asivery", 10 | "license": "GPL v2", 11 | "type": "module", 12 | "dependencies": { 13 | "async-mutex": "^0.3.2", 14 | "express": "^4.17.1", 15 | "express-ws": "^5.0.2", 16 | "netmd-js": "file:../netmd-js-workingtree", 17 | "usb": "^2.7.0", 18 | "yargs": "^17.3.1" 19 | } 20 | } 21 | --------------------------------------------------------------------------------