mirror of
https://github.com/koush/scrypted.git
synced 2026-05-26 14:40:29 +01:00
server/sdk/opencv: install optional dependencies as needed
This commit is contained in:
5
plugins/opencv/.gitignore
vendored
5
plugins/opencv/.gitignore
vendored
@@ -1 +1,4 @@
|
||||
*
|
||||
.DS_Store
|
||||
out/
|
||||
node_modules/
|
||||
dist/
|
||||
|
||||
492
plugins/opencv/package-lock.json
generated
492
plugins/opencv/package-lock.json
generated
@@ -1,20 +1,22 @@
|
||||
{
|
||||
"name": "@scrypted/opencv",
|
||||
"version": "0.0.17",
|
||||
"version": "0.0.12",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/opencv",
|
||||
"version": "0.0.17",
|
||||
"version": "0.0.12",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@scrypted/common": "file:../../common",
|
||||
"@scrypted/sdk": "file:../../sdk",
|
||||
"opencv-wasm": "^4.3.0-10"
|
||||
"@scrypted/sdk": "file:../../sdk"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^14.17.11"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@koush/opencv4nodejs": "^5.6.6"
|
||||
}
|
||||
},
|
||||
"../../common": {
|
||||
@@ -47,6 +49,7 @@
|
||||
"babel-loader": "^8.2.3",
|
||||
"babel-plugin-const-enum": "^1.1.0",
|
||||
"esbuild": "^0.13.8",
|
||||
"ncp": "^2.0.0",
|
||||
"raw-loader": "^4.0.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-loader": "^9.2.6",
|
||||
@@ -65,6 +68,21 @@
|
||||
"../sdk": {
|
||||
"extraneous": true
|
||||
},
|
||||
"node_modules/@koush/opencv4nodejs": {
|
||||
"version": "5.6.6",
|
||||
"resolved": "https://registry.npmjs.org/@koush/opencv4nodejs/-/opencv4nodejs-5.6.6.tgz",
|
||||
"integrity": "sha512-PHwfe+j4+UmgMoh70aM/lNnFxb+f/okLSZRKE7Aq+cqDyS8XOBn5cFRcTEbTpVjJslGV8ab7o+jDKQ0ukGJDxw==",
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"nan": "^2.14.0",
|
||||
"native-node-utils": "^0.2.7",
|
||||
"npmlog": "^4.1.2"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@types/node": ">6"
|
||||
}
|
||||
},
|
||||
"node_modules/@scrypted/common": {
|
||||
"resolved": "../../common",
|
||||
"link": true
|
||||
@@ -77,15 +95,254 @@
|
||||
"version": "14.17.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.11.tgz",
|
||||
"integrity": "sha512-n2OQ+0Bz6WEsUjrvcHD1xZ8K+Kgo4cn9/w94s1bJS690QMUWfJPW/m7CCb7gPkA1fcYwL2UpjXP/rq/Eo41m6w==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/opencv-wasm": {
|
||||
"version": "4.3.0-10",
|
||||
"resolved": "https://registry.npmjs.org/opencv-wasm/-/opencv-wasm-4.3.0-10.tgz",
|
||||
"integrity": "sha512-EWmWLUzp2suoc6N44Y4ouWT85QwvShx23Q430R+lp6NyS828bjQn6mCgA3NJ6Z/S59aaTeeu+RhqPQIJIYld1w=="
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/aproba": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
|
||||
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/are-we-there-yet": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
|
||||
"integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"delegates": "^1.0.0",
|
||||
"readable-stream": "^2.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
|
||||
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/core-util-is": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/delegates": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
||||
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/gauge": {
|
||||
"version": "2.7.4",
|
||||
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
|
||||
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"aproba": "^1.0.3",
|
||||
"console-control-strings": "^1.0.0",
|
||||
"has-unicode": "^2.0.0",
|
||||
"object-assign": "^4.1.0",
|
||||
"signal-exit": "^3.0.0",
|
||||
"string-width": "^1.0.1",
|
||||
"strip-ansi": "^3.0.1",
|
||||
"wide-align": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/has-unicode": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
|
||||
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
|
||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/nan": {
|
||||
"version": "2.15.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
|
||||
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/native-node-utils": {
|
||||
"version": "0.2.7",
|
||||
"resolved": "https://registry.npmjs.org/native-node-utils/-/native-node-utils-0.2.7.tgz",
|
||||
"integrity": "sha512-61v0G3uVxWlXHppSZGwZi+ZEIgGUKI8QvEkEJLb1GVePI7P8SBe+G747z+QMXSt4TxfgbVZP0DyobbRKYVIjdw==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"nan": "^2.13.2"
|
||||
}
|
||||
},
|
||||
"node_modules/npmlog": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
|
||||
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"are-we-there-yet": "~1.1.2",
|
||||
"console-control-strings": "~1.1.0",
|
||||
"gauge": "~2.7.3",
|
||||
"set-blocking": "~2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
|
||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/readable-stream": {
|
||||
"version": "2.3.7",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~2.0.0",
|
||||
"safe-buffer": "~5.1.1",
|
||||
"string_decoder": "~1.1.1",
|
||||
"util-deprecate": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/signal-exit": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz",
|
||||
"integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/string-width": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
"strip-ansi": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/wide-align": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
|
||||
"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"string-width": "^1.0.2 || 2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@koush/opencv4nodejs": {
|
||||
"version": "5.6.6",
|
||||
"resolved": "https://registry.npmjs.org/@koush/opencv4nodejs/-/opencv4nodejs-5.6.6.tgz",
|
||||
"integrity": "sha512-PHwfe+j4+UmgMoh70aM/lNnFxb+f/okLSZRKE7Aq+cqDyS8XOBn5cFRcTEbTpVjJslGV8ab7o+jDKQ0ukGJDxw==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@types/node": ">6",
|
||||
"nan": "^2.14.0",
|
||||
"native-node-utils": "^0.2.7",
|
||||
"npmlog": "^4.1.2"
|
||||
}
|
||||
},
|
||||
"@scrypted/common": {
|
||||
"version": "file:../../common",
|
||||
"requires": {
|
||||
@@ -110,6 +367,7 @@
|
||||
"babel-loader": "^8.2.3",
|
||||
"babel-plugin-const-enum": "^1.1.0",
|
||||
"esbuild": "^0.13.8",
|
||||
"ncp": "^2.0.0",
|
||||
"raw-loader": "^4.0.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-loader": "^9.2.6",
|
||||
@@ -121,12 +379,218 @@
|
||||
"version": "14.17.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.11.tgz",
|
||||
"integrity": "sha512-n2OQ+0Bz6WEsUjrvcHD1xZ8K+Kgo4cn9/w94s1bJS690QMUWfJPW/m7CCb7gPkA1fcYwL2UpjXP/rq/Eo41m6w==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"opencv-wasm": {
|
||||
"version": "4.3.0-10",
|
||||
"resolved": "https://registry.npmjs.org/opencv-wasm/-/opencv-wasm-4.3.0-10.tgz",
|
||||
"integrity": "sha512-EWmWLUzp2suoc6N44Y4ouWT85QwvShx23Q430R+lp6NyS828bjQn6mCgA3NJ6Z/S59aaTeeu+RhqPQIJIYld1w=="
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||
"optional": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
|
||||
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
|
||||
"optional": true
|
||||
},
|
||||
"are-we-there-yet": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
|
||||
"integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"delegates": "^1.0.0",
|
||||
"readable-stream": "^2.0.6"
|
||||
}
|
||||
},
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
|
||||
"optional": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
|
||||
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
|
||||
"optional": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
|
||||
"optional": true
|
||||
},
|
||||
"delegates": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
||||
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
|
||||
"optional": true
|
||||
},
|
||||
"gauge": {
|
||||
"version": "2.7.4",
|
||||
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
|
||||
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"aproba": "^1.0.3",
|
||||
"console-control-strings": "^1.0.0",
|
||||
"has-unicode": "^2.0.0",
|
||||
"object-assign": "^4.1.0",
|
||||
"signal-exit": "^3.0.0",
|
||||
"string-width": "^1.0.1",
|
||||
"strip-ansi": "^3.0.1",
|
||||
"wide-align": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"has-unicode": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
|
||||
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
|
||||
"optional": true
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"optional": true
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
|
||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
|
||||
"optional": true
|
||||
},
|
||||
"nan": {
|
||||
"version": "2.15.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
|
||||
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==",
|
||||
"optional": true
|
||||
},
|
||||
"native-node-utils": {
|
||||
"version": "0.2.7",
|
||||
"resolved": "https://registry.npmjs.org/native-node-utils/-/native-node-utils-0.2.7.tgz",
|
||||
"integrity": "sha512-61v0G3uVxWlXHppSZGwZi+ZEIgGUKI8QvEkEJLb1GVePI7P8SBe+G747z+QMXSt4TxfgbVZP0DyobbRKYVIjdw==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"nan": "^2.13.2"
|
||||
}
|
||||
},
|
||||
"npmlog": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
|
||||
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"are-we-there-yet": "~1.1.2",
|
||||
"console-control-strings": "~1.1.0",
|
||||
"gauge": "~2.7.3",
|
||||
"set-blocking": "~2.0.0"
|
||||
}
|
||||
},
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
|
||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
|
||||
"optional": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
|
||||
"optional": true
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||
"optional": true
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.7",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~2.0.0",
|
||||
"safe-buffer": "~5.1.1",
|
||||
"string_decoder": "~1.1.1",
|
||||
"util-deprecate": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"optional": true
|
||||
},
|
||||
"set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
|
||||
"optional": true
|
||||
},
|
||||
"signal-exit": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz",
|
||||
"integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==",
|
||||
"optional": true
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
"strip-ansi": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
||||
"optional": true
|
||||
},
|
||||
"wide-align": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
|
||||
"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"string-width": "^1.0.2 || 2"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,16 +5,15 @@
|
||||
"author": "Scrypted",
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"prepublishOnly": "npm run opencv-deps && NODE_ENV=production scrypted-webpack",
|
||||
"prescrypted-vscode-launch": "npm run opencv-deps && scrypted-webpack",
|
||||
"prepublishOnly": "NODE_ENV=production scrypted-webpack",
|
||||
"prescrypted-vscode-launch": "scrypted-webpack",
|
||||
"scrypted-vscode-launch": "scrypted-deploy-debug",
|
||||
"scrypted-deploy-debug": "scrypted-deploy-debug",
|
||||
"scrypted-debug": "scrypted-debug",
|
||||
"scrypted-deploy": "scrypted-deploy",
|
||||
"scrypted-readme": "scrypted-readme",
|
||||
"scrypted-package-json": "scrypted-package-json",
|
||||
"opencv-deps": "cp node_modules/opencv-wasm/index.js src/opencv && cp node_modules/opencv-wasm/opencv.js src/opencv && sed -i '' 's/this, function/exports, function/g' src/opencv/opencv.js",
|
||||
"scrypted-webpack": "npm run opencv-deps && scrypted-webpack"
|
||||
"scrypted-webpack": "scrypted-webpack"
|
||||
},
|
||||
"keywords": [
|
||||
"scrypted",
|
||||
@@ -31,12 +30,15 @@
|
||||
"type": "API",
|
||||
"interfaces": [
|
||||
"MixinProvider"
|
||||
]
|
||||
],
|
||||
"realfs": true
|
||||
},
|
||||
"dependencies": {
|
||||
"@scrypted/common": "file:../../common",
|
||||
"@scrypted/sdk": "file:../../sdk",
|
||||
"opencv-wasm": "^4.3.0-10"
|
||||
"@scrypted/sdk": "file:../../sdk"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@koush/opencv4nodejs": "^5.6.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^14.17.11"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
import { MixinProvider, ScryptedDeviceType, ScryptedInterface, VideoCamera, MediaStreamOptions, Settings, Setting, ScryptedMimeTypes, FFMpegInput, MotionSensor } from '@scrypted/sdk';
|
||||
import sdk from '@scrypted/sdk';
|
||||
import { once } from 'events';
|
||||
@@ -5,15 +6,7 @@ import { SettingsMixinDeviceBase } from "../../../common/src/settings-mixin";
|
||||
import { FFMpegRebroadcastSession, startRebroadcastSession } from '@scrypted/common/src/ffmpeg-rebroadcast';
|
||||
import { StreamChunk, createRawVideoParser } from '@scrypted/common/src/stream-parser';
|
||||
import { AutoenableMixinProvider } from '@scrypted/common/src/autoenable-mixin-provider';
|
||||
import { getH264DecoderArgs } from "@scrypted/common/src/ffmpeg-hardware-acceleration"
|
||||
import { HeapScope } from './heap';
|
||||
|
||||
// necessary for opencv wasm to not crap itself due to webpack.
|
||||
global.__filename = undefined;
|
||||
// todo: remove this.
|
||||
window = undefined;
|
||||
// import { cv } from 'opencv-wasm';
|
||||
const { cv } = require('./opencv');
|
||||
import cv, { Mat, Size } from "@koush/opencv4nodejs";
|
||||
|
||||
const { mediaManager, log, systemManager, deviceManager } = sdk;
|
||||
|
||||
@@ -104,11 +97,6 @@ class OpenCVMixin extends SettingsMixinDeviceBase<VideoCamera> implements Motion
|
||||
width = Math.floor(width / 6) * 6;
|
||||
height = Math.floor(height / 6) * 6;
|
||||
|
||||
const videoDecoderArguments = this.storage.getItem('videoDecoderArguments') || '';
|
||||
if (videoDecoderArguments) {
|
||||
ffmpegInput.inputArguments.unshift(...videoDecoderArguments.split(' '));
|
||||
}
|
||||
|
||||
this.sessionPromise = startRebroadcastSession(ffmpegInput, {
|
||||
console: this.console,
|
||||
parsers: {
|
||||
@@ -123,7 +111,6 @@ class OpenCVMixin extends SettingsMixinDeviceBase<VideoCamera> implements Motion
|
||||
});
|
||||
|
||||
const session = await this.sessionPromise;
|
||||
session.events.on('error', e => this.console.log('ffmpeg error', e));
|
||||
|
||||
let watchdog: NodeJS.Timeout;
|
||||
const restartWatchdog = () => {
|
||||
@@ -145,88 +132,57 @@ class OpenCVMixin extends SettingsMixinDeviceBase<VideoCamera> implements Motion
|
||||
await this.startWrapped(session);
|
||||
}
|
||||
finally {
|
||||
clearTimeout(watchdog);
|
||||
session.kill();
|
||||
}
|
||||
}
|
||||
|
||||
async startWrapped(session: FFMpegRebroadcastSession) {
|
||||
let previousFrame: any;
|
||||
try {
|
||||
let timeout: NodeJS.Timeout;
|
||||
let previousFrame: Mat;
|
||||
let timeout: NodeJS.Timeout;
|
||||
|
||||
const triggerMotion = () => {
|
||||
this.motionDetected = true;
|
||||
clearTimeout(timeout);
|
||||
setTimeout(() => this.motionDetected = false, 10000);
|
||||
const triggerMotion = () => {
|
||||
this.motionDetected = true;
|
||||
clearTimeout(timeout);
|
||||
setTimeout(() => this.motionDetected = false, 10000);
|
||||
}
|
||||
|
||||
this.motionDetected = false;
|
||||
|
||||
while (!this.released) {
|
||||
if (this.motionDetected) {
|
||||
// during motion just eat the frames.
|
||||
previousFrame = undefined;
|
||||
await sleep(1000);
|
||||
continue;
|
||||
}
|
||||
|
||||
this.motionDetected = false;
|
||||
const args = await once(session.events, 'rawvideo-data');
|
||||
const chunk: StreamChunk = args[0];
|
||||
// should be one chunk from the parser, but let's not assume that.
|
||||
const raw = chunk.chunks.length === 1 ? chunk.chunks[0] : Buffer.concat(chunk.chunks);
|
||||
const mat = new Mat(raw, chunk.height * 3 / 2, chunk.width, cv.CV_8U);
|
||||
|
||||
while (!this.released && session.isActive()) {
|
||||
if (this.motionDetected) {
|
||||
// during motion just eat the frames.
|
||||
previousFrame = undefined;
|
||||
await sleep(1000);
|
||||
const gray = await mat.cvtColorAsync(cv.COLOR_YUV420p2GRAY);
|
||||
const curFrame = await gray.gaussianBlurAsync(new Size(21, 21), 0);
|
||||
|
||||
try {
|
||||
if (!previousFrame) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const args = await once(session.events, 'rawvideo-data');
|
||||
const chunk: StreamChunk = args[0];
|
||||
// should be one chunk from the parser, but let's not assume that.
|
||||
const raw = chunk.chunks.length === 1 ? chunk.chunks[0] : Buffer.concat(chunk.chunks);
|
||||
|
||||
const scope = new HeapScope();
|
||||
const mat = scope.new(cv.Mat, chunk.height * 3 / 2, chunk.width, cv.CV_8U);
|
||||
mat.data.set(raw);
|
||||
|
||||
const gray = scope.new(cv.Mat);
|
||||
cv.cvtColor(mat, gray, cv.COLOR_YUV420p2GRAY);
|
||||
const curFrame = new cv.Mat();
|
||||
cv.GaussianBlur(gray, curFrame, new cv.Size(21, 21), 0);
|
||||
|
||||
try {
|
||||
if (!previousFrame) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const frameDelta = scope.new(cv.Mat);
|
||||
cv.absdiff(previousFrame, curFrame, frameDelta);
|
||||
const thresh = scope.new(cv.Mat);
|
||||
cv.threshold(frameDelta, thresh, this.threshold, 255, cv.THRESH_BINARY);
|
||||
const dilated = scope.new(cv.Mat);
|
||||
const structuringElement = cv.getStructuringElement(cv.MORPH_ELLIPSE, new cv.Size(4, 4));
|
||||
scope.tracking.push(structuringElement);
|
||||
cv.dilate(thresh, dilated, structuringElement, new cv.Point(-1, -1), 2);
|
||||
const contours = scope.new(cv.MatVector);
|
||||
const hierarchy = scope.new(cv.Mat);
|
||||
cv.findContours(dilated, contours, hierarchy, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE);
|
||||
const filteredContours: number[] = [];
|
||||
for (let i = 0; i < contours.size(); i++) {
|
||||
const contourArea = cv.contourArea(contours.get(i));
|
||||
if (contourArea > this.area) {
|
||||
filteredContours.push(contourArea);
|
||||
}
|
||||
}
|
||||
if (filteredContours.length) {
|
||||
this.console.log('motion triggered by area(s)', filteredContours.join(','));
|
||||
triggerMotion();
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
this.console.log('cv error', e);
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
previousFrame?.delete();
|
||||
previousFrame = curFrame;
|
||||
|
||||
scope.dispose();
|
||||
const frameDelta = previousFrame.absdiff(curFrame);
|
||||
const thresh = await frameDelta.thresholdAsync(this.threshold, 255, cv.THRESH_BINARY);
|
||||
const dilated = await thresh.dilateAsync(cv.getStructuringElement(cv.MORPH_ELLIPSE, new cv.Size(4, 4)), new cv.Point2(-1, -1), 2)
|
||||
const contours = await dilated.findContoursAsync(cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE);
|
||||
const filteredContours = contours.filter(cnt => cnt.area > this.area).map(cnt => cnt.area);
|
||||
if (filteredContours.length) {
|
||||
this.console.log('motion triggered by area(s)', filteredContours.join(','));
|
||||
triggerMotion();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
previousFrame?.delete();
|
||||
finally {
|
||||
previousFrame = curFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,18 +208,7 @@ class OpenCVMixin extends SettingsMixinDeviceBase<VideoCamera> implements Motion
|
||||
});
|
||||
}
|
||||
|
||||
const decoderArgs = getH264DecoderArgs();
|
||||
|
||||
settings.push(
|
||||
{
|
||||
title: 'Video Decoder Arguments',
|
||||
key: "videoDecoderArguments",
|
||||
value: this.storage.getItem('videoDecoderArguments'),
|
||||
description: 'FFmpeg arguments used to decode input video.',
|
||||
placeholder: '-hwaccel auto',
|
||||
choices: Object.keys(decoderArgs),
|
||||
combobox: true,
|
||||
},
|
||||
{
|
||||
title: "Motion Area",
|
||||
description: "The area size required to trigger motion. Higher values (larger areas) are less sensitive.",
|
||||
@@ -294,26 +239,19 @@ class OpenCVMixin extends SettingsMixinDeviceBase<VideoCamera> implements Motion
|
||||
}
|
||||
|
||||
async putMixinSetting(key: string, value: string | number | boolean): Promise<void> {
|
||||
this.storage.setItem(key, value.toString());
|
||||
if (key === 'area')
|
||||
this.area = parseInt(value.toString()) || defaultArea;
|
||||
if (key === 'threshold')
|
||||
this.threshold = parseInt(value.toString()) || defaultThreshold;
|
||||
if (key === 'videoDecoderArguments') {
|
||||
const decoderArgs = getH264DecoderArgs();
|
||||
value = decoderArgs[value.toString()]?.join(' ') || value;
|
||||
}
|
||||
|
||||
if (key === 'motionChannel' || key === 'videoDecoderArguments') {
|
||||
if (key === 'motionChannel') {
|
||||
this.sessionPromise?.then(session => session.kill());
|
||||
}
|
||||
|
||||
this.storage.setItem(key, value.toString());
|
||||
deviceManager.onMixinEvent(this.id, this.mixinProviderNativeId, ScryptedInterface.Settings, undefined);
|
||||
}
|
||||
|
||||
release() {
|
||||
this.released = true;
|
||||
this.sessionPromise?.then(session => session.kill());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ const rimraf = require('rimraf');
|
||||
const webpack = require('webpack');
|
||||
const esbuild = require('esbuild');
|
||||
const ncp = require('ncp');
|
||||
const tmp = require('tmp');
|
||||
|
||||
if (fs.existsSync(path.resolve(cwd, 'src/main.py'))) {
|
||||
let out;
|
||||
@@ -91,6 +92,9 @@ else {
|
||||
}
|
||||
}
|
||||
|
||||
const packageJson = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json').toString()));
|
||||
const optionalDependencies = Object.keys(packageJson.optionalDependencies || {});
|
||||
|
||||
const runtimes = [
|
||||
// {
|
||||
// config: 'webpack.duktape.config.js',
|
||||
@@ -158,6 +162,19 @@ else {
|
||||
config.output.path = out;
|
||||
config.output.filename = runtime.output;
|
||||
|
||||
|
||||
for (const opt of optionalDependencies) {
|
||||
const t = tmp.tmpNameSync({
|
||||
postfix: '.js',
|
||||
});
|
||||
console.log(t);
|
||||
fs.writeFileSync(t, `
|
||||
const e = __non_webpack_require__('${opt}');
|
||||
module.exports = e;
|
||||
`);
|
||||
config.resolve.alias[opt] = t;
|
||||
}
|
||||
|
||||
webpack(config, (err, stats) => {
|
||||
if (err)
|
||||
return reject(err);
|
||||
|
||||
20
sdk/package-lock.json
generated
20
sdk/package-lock.json
generated
@@ -25,6 +25,7 @@
|
||||
"ncp": "^2.0.0",
|
||||
"raw-loader": "^4.0.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"tmp": "^0.2.1",
|
||||
"ts-loader": "^9.2.6",
|
||||
"typescript-json-schema": "^0.50.1",
|
||||
"webpack": "^5.59.0"
|
||||
@@ -2202,6 +2203,17 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/tmp": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
|
||||
"integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
|
||||
"dependencies": {
|
||||
"rimraf": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/to-fast-properties": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
||||
@@ -4141,6 +4153,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"tmp": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
|
||||
"integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
|
||||
"requires": {
|
||||
"rimraf": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"to-fast-properties": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
"ncp": "^2.0.0",
|
||||
"raw-loader": "^4.0.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"tmp": "^0.2.1",
|
||||
"ts-loader": "^9.2.6",
|
||||
"typescript-json-schema": "^0.50.1",
|
||||
"webpack": "^5.59.0"
|
||||
|
||||
@@ -27,6 +27,17 @@ import { PluginDebug } from './plugin-debug';
|
||||
import readline from 'readline';
|
||||
import { Readable, Writable } from 'stream';
|
||||
|
||||
export function ensurePluginVolume(pluginId: string) {
|
||||
const volume = path.join(process.cwd(), 'volume');
|
||||
const pluginVolume = path.join(volume, 'plugins', pluginId);
|
||||
try {
|
||||
mkdirp.sync(pluginVolume);
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
return pluginVolume;
|
||||
}
|
||||
|
||||
export class PluginHost {
|
||||
worker: child_process.ChildProcess;
|
||||
peer: RpcPeer;
|
||||
@@ -91,14 +102,10 @@ export class PluginHost {
|
||||
const logger = scrypted.getDeviceLogger(scrypted.findPluginDevice(plugin._id));
|
||||
|
||||
const volume = path.join(process.cwd(), 'volume');
|
||||
const cwd = path.join(volume, 'plugins', this.pluginId);
|
||||
try {
|
||||
mkdirp.sync(cwd);
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
const cwd = ensurePluginVolume(this.pluginId);
|
||||
|
||||
this.startPluginClusterHost(logger, {
|
||||
NODE_PATH: path.join(cwd, 'node_modules'),
|
||||
SCRYPTED_PLUGIN_VOLUME: cwd,
|
||||
}, plugin.packageJson.scrypted.runtime);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Level } from './level';
|
||||
import { PluginHost } from './plugin/plugin-host';
|
||||
import { ensurePluginVolume, PluginHost } from './plugin/plugin-host';
|
||||
import cluster from 'cluster';
|
||||
import { ScryptedNativeId, Device, EngineIOHandler, HttpRequest, HttpRequestHandler, OauthClient, PushHandler, ScryptedDevice, ScryptedInterface, ScryptedInterfaceProperty } from '@scrypted/sdk/types';
|
||||
import { PluginDeviceProxyHandler } from './plugin/plugin-device';
|
||||
@@ -29,6 +29,9 @@ import { Alerts } from './services/alerts';
|
||||
import { Info } from './services/info';
|
||||
import io from 'engine.io';
|
||||
import {spawn as ptySpawn} from 'node-pty';
|
||||
import child_process from 'child_process';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
interface DeviceProxyPair {
|
||||
handler: PluginDeviceProxyHandler;
|
||||
@@ -424,6 +427,31 @@ export class ScryptedRuntime {
|
||||
return proxyPair;
|
||||
}
|
||||
|
||||
async installOptionalDependencies(packageJson: any, currentPackageJson: any) {
|
||||
const { optionalDependencies } = packageJson;
|
||||
if (!optionalDependencies)
|
||||
return;
|
||||
if (!Object.keys(packageJson).length)
|
||||
return;
|
||||
const currentOptionalDependencies = currentPackageJson?.optionalDependencies || {};
|
||||
|
||||
if (JSON.stringify(optionalDependencies) === JSON.stringify(currentOptionalDependencies))
|
||||
return;
|
||||
|
||||
const reduced = Object.assign({}, packageJson);
|
||||
delete reduced.dependencies;
|
||||
delete reduced.devDependencies;
|
||||
|
||||
const pluginVolume = ensurePluginVolume(reduced.name);
|
||||
const optPj = path.join(pluginVolume, 'package.json');
|
||||
fs.writeFileSync(optPj, JSON.stringify(reduced));
|
||||
const cp = child_process.spawn('npm', ['install'], {
|
||||
cwd: pluginVolume,
|
||||
});
|
||||
|
||||
await once(cp, 'exit');
|
||||
}
|
||||
|
||||
async installNpm(pkg: string, version?: string): Promise<PluginHost> {
|
||||
const registry = (await axios(`https://registry.npmjs.org/${pkg}`)).data;
|
||||
if (!version) {
|
||||
@@ -458,6 +486,7 @@ export class ScryptedRuntime {
|
||||
const packageJson = JSON.parse(packageJsonEntry.toString());
|
||||
const npmPackage = packageJson.name;
|
||||
const plugin = await this.datastore.tryGet(Plugin, npmPackage) || new Plugin();
|
||||
await this.installOptionalDependencies(packageJson, plugin.packageJson);
|
||||
|
||||
plugin._id = npmPackage;
|
||||
plugin.packageJson = packageJson;
|
||||
|
||||
@@ -286,6 +286,9 @@ else {
|
||||
const npmPackage = req.query.npmPackage as string;
|
||||
const plugin = await db.tryGet(Plugin, npmPackage) || new Plugin();
|
||||
|
||||
const packageJson = req.body;
|
||||
await scrypted.installOptionalDependencies(packageJson, plugin.packageJson);
|
||||
|
||||
plugin._id = npmPackage;
|
||||
plugin.packageJson = req.body;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user