diff --git a/common/.vscode/launch.json b/common/.vscode/launch.json index 4bebc08d3c..b9dd24b363 100644 --- a/common/.vscode/launch.json +++ b/common/.vscode/launch.json @@ -5,17 +5,19 @@ "version": "0.2.0", "configurations": [ { - "type": "pwa-node", + "name": "ts-node", + "type": "node", "request": "launch", - "name": "Launch Program", - "skipFiles": [ - "/**" + "args": [ + "${workspaceFolder}/src/test.ts", ], - "program": "${workspaceFolder}/dist/common/src/test.js", - "preLaunchTask": "npm: build", - "outFiles": [ - "${workspaceFolder}/**/*.js" - ] - } + "runtimeArgs": [ + "-r", + "ts-node/register" + ], + "cwd": "${workspaceRoot}", + "protocol": "inspector", + "internalConsoleOptions": "openOnSessionStart" + }, ] } \ No newline at end of file diff --git a/common/package-lock.json b/common/package-lock.json index cd1833a0c6..12d4933ca2 100644 --- a/common/package-lock.json +++ b/common/package-lock.json @@ -1,22 +1,23 @@ { "name": "@scrypted/common", - "version": "1.0.2", + "version": "1.0.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@scrypted/common", - "version": "1.0.2", + "version": "1.0.1", "license": "ISC", "dependencies": { "@scrypted/sdk": "file:../sdk", "@scrypted/server": "file:../server", "http-auth-utils": "^3.0.2", "node-fetch-commonjs": "^3.1.1", - "typescript": "^4.4.3" + "typescript": "^5.3.3" }, "devDependencies": { - "@types/node": "^16.9.0" + "@types/node": "^20.10.8", + "ts-node": "^10.9.2" } }, "../external/werift/packages/webrtc": { @@ -74,7 +75,7 @@ }, "../sdk": { "name": "@scrypted/sdk", - "version": "0.2.68", + "version": "0.3.4", "license": "ISC", "dependencies": { "@babel/preset-typescript": "^7.18.6", @@ -111,68 +112,103 @@ }, "../server": { "name": "@scrypted/server", - "version": "0.6.19", + "version": "0.81.0", "license": "ISC", "dependencies": { - "@ffmpeg-installer/ffmpeg": "^1.1.0", - "@mapbox/node-pre-gyp": "^1.0.10", - "@scrypted/types": "^0.2.63", - "adm-zip": "^0.5.9", - "axios": "^0.21.4", - "body-parser": "^1.19.0", + "@mapbox/node-pre-gyp": "^1.0.11", + "@scrypted/types": "^0.3.4", + "adm-zip": "^0.5.10", + "body-parser": "^1.20.2", "cookie-parser": "^1.4.6", "debug": "^4.3.4", - "engine.io": "^6.2.0", + "engine.io": "^6.5.4", "express": "^4.18.2", - "ffmpeg-static": "^5.1.0", + "ffmpeg-static": "^5.2.0", + "follow-redirects": "^1.15.4", "http-auth": "^4.2.0", "ip": "^1.1.8", - "level": "^6.0.1", + "level": "^8.0.0", "linkfs": "^2.1.0", "lodash": "^4.17.21", - "memfs": "^3.4.7", + "memfs": "^4.6.0", "mime": "^3.0.0", - "mkdirp": "^1.0.4", - "nan": "^2.17.0", + "nan": "^2.18.0", "node-dijkstra": "^2.5.0", "node-forge": "^1.3.1", - "node-gyp": "^8.4.1", - "router": "^1.3.7", - "semver": "^7.3.8", + "node-gyp": "^10.0.1", + "router": "^1.3.8", + "semver": "^7.5.4", + "sharp": "^0.33.1", "source-map-support": "^0.5.21", - "tar": "^6.1.11", - "tslib": "^2.4.0", - "typescript": "^4.8.4", - "whatwg-mimetype": "^2.3.0", - "ws": "^8.9.0" + "tar": "^6.2.0", + "tslib": "^2.6.2", + "typescript": "^5.3.3", + "whatwg-mimetype": "^4.0.0", + "ws": "^8.16.0" }, "bin": { "scrypted-serve": "bin/scrypted-serve" }, "devDependencies": { - "@types/adm-zip": "^0.4.34", - "@types/cookie-parser": "^1.4.3", - "@types/debug": "^4.1.7", - "@types/express": "^4.17.14", - "@types/http-auth": "^4.1.1", - "@types/ip": "^1.1.0", - "@types/lodash": "^4.14.186", - "@types/mime": "^3.0.1", - "@types/mkdirp": "^1.0.2", - "@types/node-dijkstra": "^2.5.3", - "@types/node-forge": "^1.3.0", - "@types/pem": "^1.9.6", - "@types/rimraf": "^3.0.2", - "@types/semver": "^7.3.12", - "@types/source-map-support": "^0.5.6", - "@types/tar": "^4.0.5", - "@types/whatwg-mimetype": "^2.1.1", - "@types/ws": "^7.4.7" + "@types/adm-zip": "^0.5.5", + "@types/cookie-parser": "^1.4.6", + "@types/debug": "^4.1.12", + "@types/express": "^4.17.21", + "@types/follow-redirects": "^1.14.4", + "@types/http-auth": "^4.1.4", + "@types/ip": "^1.1.3", + "@types/lodash": "^4.14.202", + "@types/mime": "^3.0.4", + "@types/node-dijkstra": "^2.5.6", + "@types/node-forge": "^1.3.10", + "@types/pem": "^1.14.4", + "@types/semver": "^7.5.6", + "@types/source-map-support": "^0.5.10", + "@types/tar": "^6.1.10", + "@types/whatwg-mimetype": "^3.0.2", + "@types/ws": "^8.5.10" }, "optionalDependencies": { "node-pty-prebuilt-multiarch": "^0.10.1-pre.5" } }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@scrypted/sdk": { "resolved": "../sdk", "link": true @@ -181,12 +217,81 @@ "resolved": "../server", "link": true }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, "node_modules/@types/node": { - "version": "16.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.0.tgz", - "integrity": "sha512-nmP+VR4oT0pJUPFbKE4SXj3Yb4Q/kz3M9dSAO1GGMebRKWHQxLfDNmU/yh3xxCJha3N60nQ/JwXWwOE/ZSEVag==", + "version": "20.10.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.8.tgz", + "integrity": "sha512-f8nQs3cLxbAFc00vEU59yf9UyGUftkPaLGfvbVOIDdx2i1b8epBqj2aNGyP19fiyXWvlmZ7qC1XLjAzw/OKIeA==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz", + "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/fetch-blob": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.4.tgz", @@ -231,6 +336,12 @@ "node": ">=12.19.0" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -265,18 +376,73 @@ "url": "https://opencollective.com/node-fetch" } }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, "node_modules/typescript": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", - "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, "node_modules/web-streams-polyfill": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz", @@ -286,15 +452,55 @@ } }, "node_modules/yerror": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/yerror/-/yerror-6.0.1.tgz", - "integrity": "sha512-0Bxo+NyeucjxhmPB5z3lmI/N/cOu8L1Q8JVta6/I5G6J/JhCSSPwk8qt9N4yOFSjwkvhDwzUSQglfBIAllvi1Q==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/yerror/-/yerror-6.2.1.tgz", + "integrity": "sha512-WPZgybhCBzsMSSqGYBnj20NZo4FiFKQG0+i/21cYGVd4B7eYtvYDOpjk/0e8UM1eVHJ+4Ja6bZ7TAjHH6mk+ew==", "engines": { "node": ">=12.19.0" } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } } }, "dependencies": { + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "@scrypted/sdk": { "version": "file:../sdk", "requires": { @@ -322,62 +528,117 @@ "@scrypted/server": { "version": "file:../server", "requires": { - "@ffmpeg-installer/ffmpeg": "^1.1.0", - "@mapbox/node-pre-gyp": "^1.0.10", - "@scrypted/types": "^0.2.63", - "@types/adm-zip": "^0.4.34", - "@types/cookie-parser": "^1.4.3", - "@types/debug": "^4.1.7", - "@types/express": "^4.17.14", - "@types/http-auth": "^4.1.1", - "@types/ip": "^1.1.0", - "@types/lodash": "^4.14.186", - "@types/mime": "^3.0.1", - "@types/mkdirp": "^1.0.2", - "@types/node-dijkstra": "^2.5.3", - "@types/node-forge": "^1.3.0", - "@types/pem": "^1.9.6", - "@types/rimraf": "^3.0.2", - "@types/semver": "^7.3.12", - "@types/source-map-support": "^0.5.6", - "@types/tar": "^4.0.5", - "@types/whatwg-mimetype": "^2.1.1", - "@types/ws": "^7.4.7", - "adm-zip": "^0.5.9", - "axios": "^0.21.4", - "body-parser": "^1.19.0", + "@mapbox/node-pre-gyp": "^1.0.11", + "@scrypted/types": "^0.3.4", + "@types/adm-zip": "^0.5.5", + "@types/cookie-parser": "^1.4.6", + "@types/debug": "^4.1.12", + "@types/express": "^4.17.21", + "@types/follow-redirects": "^1.14.4", + "@types/http-auth": "^4.1.4", + "@types/ip": "^1.1.3", + "@types/lodash": "^4.14.202", + "@types/mime": "^3.0.4", + "@types/node-dijkstra": "^2.5.6", + "@types/node-forge": "^1.3.10", + "@types/pem": "^1.14.4", + "@types/semver": "^7.5.6", + "@types/source-map-support": "^0.5.10", + "@types/tar": "^6.1.10", + "@types/whatwg-mimetype": "^3.0.2", + "@types/ws": "^8.5.10", + "adm-zip": "^0.5.10", + "body-parser": "^1.20.2", "cookie-parser": "^1.4.6", "debug": "^4.3.4", - "engine.io": "^6.2.0", + "engine.io": "^6.5.4", "express": "^4.18.2", - "ffmpeg-static": "^5.1.0", + "ffmpeg-static": "^5.2.0", + "follow-redirects": "^1.15.4", "http-auth": "^4.2.0", "ip": "^1.1.8", - "level": "^6.0.1", + "level": "^8.0.0", "linkfs": "^2.1.0", "lodash": "^4.17.21", - "memfs": "^3.4.7", + "memfs": "^4.6.0", "mime": "^3.0.0", - "mkdirp": "^1.0.4", - "nan": "^2.17.0", + "nan": "^2.18.0", "node-dijkstra": "^2.5.0", "node-forge": "^1.3.1", - "node-gyp": "^8.4.1", + "node-gyp": "^10.0.1", "node-pty-prebuilt-multiarch": "^0.10.1-pre.5", - "router": "^1.3.7", - "semver": "^7.3.8", + "router": "^1.3.8", + "semver": "^7.5.4", + "sharp": "^0.33.1", "source-map-support": "^0.5.21", - "tar": "^6.1.11", - "tslib": "^2.4.0", - "typescript": "^4.8.4", - "whatwg-mimetype": "^2.3.0", - "ws": "^8.9.0" + "tar": "^6.2.0", + "tslib": "^2.6.2", + "typescript": "^5.3.3", + "whatwg-mimetype": "^4.0.0", + "ws": "^8.16.0" } }, + "@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, "@types/node": { - "version": "16.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.0.tgz", - "integrity": "sha512-nmP+VR4oT0pJUPFbKE4SXj3Yb4Q/kz3M9dSAO1GGMebRKWHQxLfDNmU/yh3xxCJha3N60nQ/JwXWwOE/ZSEVag==", + "version": "20.10.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.8.tgz", + "integrity": "sha512-f8nQs3cLxbAFc00vEU59yf9UyGUftkPaLGfvbVOIDdx2i1b8epBqj2aNGyP19fiyXWvlmZ7qC1XLjAzw/OKIeA==", + "dev": true, + "requires": { + "undici-types": "~5.26.4" + } + }, + "acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true + }, + "acorn-walk": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz", + "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==", + "dev": true + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, "fetch-blob": { @@ -405,6 +666,12 @@ "yerror": "^6.0.0" } }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -419,10 +686,43 @@ "web-streams-polyfill": "^3.1.1" } }, + "ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + } + }, "typescript": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", - "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==" + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==" + }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true }, "web-streams-polyfill": { "version": "3.2.0", @@ -430,9 +730,15 @@ "integrity": "sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA==" }, "yerror": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/yerror/-/yerror-6.0.1.tgz", - "integrity": "sha512-0Bxo+NyeucjxhmPB5z3lmI/N/cOu8L1Q8JVta6/I5G6J/JhCSSPwk8qt9N4yOFSjwkvhDwzUSQglfBIAllvi1Q==" + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/yerror/-/yerror-6.2.1.tgz", + "integrity": "sha512-WPZgybhCBzsMSSqGYBnj20NZo4FiFKQG0+i/21cYGVd4B7eYtvYDOpjk/0e8UM1eVHJ+4Ja6bZ7TAjHH6mk+ew==" + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true } } } diff --git a/common/package.json b/common/package.json index 7e6c1ee426..fa7fecdb86 100644 --- a/common/package.json +++ b/common/package.json @@ -11,13 +11,14 @@ "author": "", "license": "ISC", "dependencies": { - "@scrypted/server": "file:../server", "@scrypted/sdk": "file:../sdk", + "@scrypted/server": "file:../server", "http-auth-utils": "^3.0.2", "node-fetch-commonjs": "^3.1.1", - "typescript": "^4.4.3" + "typescript": "^5.3.3" }, "devDependencies": { - "@types/node": "^16.9.0" + "@types/node": "^20.10.8", + "ts-node": "^10.9.2" } } diff --git a/common/src/alert-recommended-plugins.ts b/common/src/alert-recommended-plugins.ts deleted file mode 100644 index e09ec4d177..0000000000 --- a/common/src/alert-recommended-plugins.ts +++ /dev/null @@ -1,30 +0,0 @@ -import sdk from "@scrypted/sdk"; - -const { systemManager, log } = sdk; - -export async function alertRecommendedPlugins(plugins: { [pkg: string]: string }) { - const pluginsComponent = await systemManager.getComponent('plugins'); - let recommended: any; - try { - recommended = JSON.parse(localStorage.getItem('alert-recommended')); - } - catch (e) { - recommended = {}; - } - for (const plugin of Object.keys(plugins)) { - try { - if (recommended[plugin]) - continue; - - recommended[plugin] = true; - localStorage.setItem('alert-recommended', JSON.stringify(recommended)); - const id = await pluginsComponent.getIdForPluginId(plugin); - if (id) - continue; - const name = plugins[plugin]; - log.a(`Installation of the ${name} plugin is also recommended. origin:/#/component/plugin/install/${plugin}`) - } - catch (e) { - } - } -} diff --git a/common/src/http-auth-fetch.ts b/common/src/http-auth-fetch.ts new file mode 100644 index 0000000000..df9cdbfd89 --- /dev/null +++ b/common/src/http-auth-fetch.ts @@ -0,0 +1,111 @@ +import { FetchParser, HttpFetchOptions, HttpFetchResponse, JSONParser, StreamParser, checkStatus, httpFetch } from '@scrypted/server/src/http-fetch-helpers'; +import crypto from 'crypto'; +import { RequestOptions } from 'http'; +import { BASIC, DIGEST, buildAuthorizationHeader, parseWWWAuthenticateHeader } from 'http-auth-utils/src/index'; + +export interface AuthFetchCredentialState { + username: string; + password: string; + count?: number; + digest?: ReturnType>; + basic?: ReturnType>; +} + +export interface AuthFetchOptions extends HttpFetchOptions { + url: string; + credential: AuthFetchCredentialState; +} + +function getAuth(options: AuthFetchOptions, method: string) { + const { digest, basic } = options.credential; + if (digest) { + options.credential.count ||= 0; + ++options.credential.count; + const nc = ('00000000' + options.credential.count).slice(-8); + const cnonce = crypto.randomBytes(24).toString('hex'); + const uri = new URL(options.url).pathname; + + const response = DIGEST.computeHash({ + username: options.credential.username, + password: options.credential.password, + method, + uri, + nc, + cnonce, + algorithm: 'MD5', + qop: digest.data.qop!, + ...digest.data, + }); + + const header = buildAuthorizationHeader(DIGEST, { + username: options.credential.username, + uri, + nc, + cnonce, + algorithm: digest.data.algorithm!, + qop: digest.data.qop!, + response, + ...digest.data, + }); + + return header; + } + else if (basic) { + const header = buildAuthorizationHeader(BASIC, { + username: options.credential.username, + password: options.credential.password, + }); + + return header; + } + +} + +export async function authHttpFetch(options: AuthFetchOptions, init?: RequestOptions, parser: FetchParser = JSONParser): Promise> { + const method = init?.method || 'GET'; + init ||= {}; + init.headers ||= {}; + + const initialHeader = getAuth(options, method); + if (initialHeader) + init.headers['Authorization'] = initialHeader; + + const initialResponse = await httpFetch({ + ...options, + ignoreStatusCode: true, + }, init, StreamParser); + + if (initialResponse.statusCode !== 401) { + if (!options?.ignoreStatusCode) + checkStatus(initialResponse.statusCode); + return { + ...initialResponse, + body: await parser.parse(initialResponse.body), + }; + } + + let authenticateHeaders: string | string[] = initialResponse.headers['www-authenticate']; + if (!authenticateHeaders) + throw new Error('Did not find WWW-Authenticate header.'); + + + if (typeof authenticateHeaders === 'string') + authenticateHeaders = [authenticateHeaders]; + + const parsedHeaders = authenticateHeaders.map(h => parseWWWAuthenticateHeader(h)); + + const digest = parsedHeaders.find(p => p.type === 'Digest') as ReturnType>; + const basic = parsedHeaders.find(p => p.type === 'Basic') as ReturnType>; + + options.credential.digest = digest; + options.credential.basic = basic; + + if (!digest && !basic) + throw new Error(`Unknown WWW-Authenticate type: ${parsedHeaders[0]?.type}`); + + const header = getAuth(options, method); + if (header) + init.headers['Authorization'] = header; + + return httpFetch(options, init, parser); +} diff --git a/sdk/types/src/types.input.ts b/sdk/types/src/types.input.ts index f6104b036f..0c752ef956 100644 --- a/sdk/types/src/types.input.ts +++ b/sdk/types/src/types.input.ts @@ -219,7 +219,7 @@ export interface NotifierOptions { requireInteraction?: boolean; silent?: boolean; tag?: string; - timestamp?: EpochTimeStamp; + timestamp?: number; vibrate?: VibratePattern; } diff --git a/server/package-lock.json b/server/package-lock.json index f02438669c..871e684c4b 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -1,12 +1,12 @@ { "name": "@scrypted/server", - "version": "0.80.0", + "version": "0.81.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@scrypted/server", - "version": "0.80.0", + "version": "0.81.0", "license": "ISC", "dependencies": { "@mapbox/node-pre-gyp": "^1.0.11", diff --git a/server/src/http-fetch-helpers.ts b/server/src/http-fetch-helpers.ts index 4d3cde9b62..3a447e8e50 100644 --- a/server/src/http-fetch-helpers.ts +++ b/server/src/http-fetch-helpers.ts @@ -1,61 +1,143 @@ import { once } from 'events'; import { http, https } from 'follow-redirects'; -import { RequestOptions, IncomingMessage } from 'http'; +import { RequestOptions, IncomingMessage, Agent as HttpAgent, IncomingHttpHeaders } from 'http'; +import { Agent as HttpsAgent } from 'https'; +import { Readable, PassThrough } from 'stream'; + +export interface HttpFetchOptions { + url: string; + ignoreStatusCode?: boolean; + httpAgent?: HttpAgent, + httpsAgent?: HttpsAgent; + body?: Readable; +} + +async function readMessageBuffer(response: IncomingMessage) { + const buffers: Buffer[] = []; + response.on('data', buffer => buffers.push(buffer)); + await once(response, 'end'); + return Buffer.concat(buffers); +} + +export interface FetchParser { + accept: string; + parse(message: IncomingMessage): Promise; +} + +export const TextParser: FetchParser = { + accept: 'text/plain', + async parse(message: IncomingMessage) { + return (await readMessageBuffer(message)).toString(); + } +} +export const JSONParser: FetchParser = { + accept: 'application/json', + async parse(message: IncomingMessage) { + return JSON.parse((await readMessageBuffer(message)).toString()); + } +} + +export const BufferParser: FetchParser = { + accept: undefined as string, + async parse(message: IncomingMessage) { + return readMessageBuffer(message); + } +} + +export const StreamParser: FetchParser = { + accept: undefined as string, + async parse(message: IncomingMessage) { + return message; + } +} export async function getNpmPackageInfo(pkg: string) { - const { json } = await fetchJSON(`https://registry.npmjs.org/${pkg}`, { + const { body } = await httpFetch({ url: `https://registry.npmjs.org/${pkg}` }, { // force ipv4 in case of busted ipv6. family: 4, }); - return json; + return body; } -export async function fetchJSON(url: string, init?: RequestOptions) { +export function setFetchAcceptOptions(accept: string, init?: RequestOptions) { init ||= {}; init.headers = { ...init.headers, - Accept: 'application/json', + Accept: accept, }; - const { body, headers } = await fetchBuffer(url, init); - return { - json: JSON.parse(body.toString()), - headers, - } + return init; } -export async function fetchPostJSON(url: string, postBody: any, init?: RequestOptions) { +export async function httpPostFetch(options: HttpFetchOptions, postBody: any, init?: RequestOptions, parser = JSONParser) { init ||= {}; init.method = 'POST'; init.headers = { ...init.headers, - Accept: 'application/json', 'Content-Type': 'application/json', }; - const { body, headers } = await fetchBuffer(url, init, Buffer.from(JSON.stringify(postBody))); + const pt = new PassThrough(); + pt.write(Buffer.from(JSON.stringify(postBody))); + pt.end(); + options.body = pt; + + const { body, headers, statusCode } = await httpFetch(options, init, parser); return { + statusCode, json: JSON.parse(body.toString()), headers, } } -export async function fetchBuffer(url: string, init?: RequestOptions, body?: Buffer) { - const proto = url.startsWith('https:') ? https : http; +export function fetchStatusCodeOk(statusCode: number) { + return statusCode >= 200 && statusCode <= 299; +} + +export function checkStatus(statusCode: number) { + if (!fetchStatusCodeOk(statusCode)) + throw new Error(`http response statusCode ${statusCode}`); +} + +export interface HttpFetchResponse { + statusCode: number; + headers: IncomingHttpHeaders; + body: T; +} + +export async function httpFetch(options: HttpFetchOptions, init?: RequestOptions, parser: FetchParser = JSONParser): Promise> { + if (parser.accept) + init = setFetchAcceptOptions(parser.accept, init); + + const { url } = options; + const isSecure = url.startsWith('https:'); + const proto = isSecure ? https : http; const request = proto.request(url, { ...init, + agents: { + http: options?.httpAgent, + https: options?.httpsAgent, + } }); - if (body) - request.write(body); - request.end(); + if (options.body) + options.body.pipe(request); + else + request.end(); const [response] = await once(request, 'response') as IncomingMessage[]; - const buffers: Buffer[] = []; - response.on('data', buffer => buffers.push(buffer)); - await once(response, 'end'); + if (!options?.ignoreStatusCode) { + try { + checkStatus(response.statusCode); + } + catch (e) { + readMessageBuffer(response).catch(() => { }); + throw e; + } + } return { + statusCode: response.statusCode, headers: response.headers, - body: Buffer.concat(buffers), + body: await parser.parse(response), }; }