mirror of
https://github.com/samuelthomas2774/nxapi.git
synced 2026-03-21 18:04:10 -05:00
Add command/menu item to export log files
This commit is contained in:
parent
83456275fb
commit
bde495fcce
254
package-lock.json
generated
254
package-lock.json
generated
|
|
@ -9,6 +9,7 @@
|
|||
"version": "1.6.1",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@samuelthomas2774/saltpack": "^0.4.0",
|
||||
"body-parser": "^1.20.2",
|
||||
"cli-table": "^0.3.11",
|
||||
"debug": "^4.3.4",
|
||||
|
|
@ -23,6 +24,7 @@
|
|||
"sharp": "^0.33.3",
|
||||
"splatnet3-types": "^0.2.20231119210145",
|
||||
"supports-color": "^9.4.0",
|
||||
"tar": "^7.4.3",
|
||||
"tslib": "^2.6.2",
|
||||
"undici": "^6.15.0",
|
||||
"yargs": "^17.7.2"
|
||||
|
|
@ -2982,6 +2984,27 @@
|
|||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/fs-minipass": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
|
||||
"integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"minipass": "^7.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/fs-minipass/node_modules/minipass": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/ttlcache": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz",
|
||||
|
|
@ -3223,6 +3246,15 @@
|
|||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@msgpack/msgpack": {
|
||||
"version": "1.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-1.12.2.tgz",
|
||||
"integrity": "sha512-Vwhc3ObxmDZmA5hY8mfsau2rJ4vGPvzbj20QSZ2/E1GDPF61QVyjLfNHak9xmel6pW4heRt3v1fHa6np9Ehfeg==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
|
|
@ -4262,6 +4294,21 @@
|
|||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@samuelthomas2774/saltpack": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@samuelthomas2774/saltpack/-/saltpack-0.4.0.tgz",
|
||||
"integrity": "sha512-QmG4/hHBefj4ph5HBfK5ZMzRM0lPFLozltQjddy58XaFupPBSgydHWKwut5bVmxcyRNRqefSvRoLrcnqObYbKQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@msgpack/msgpack": "^1.12.2",
|
||||
"lodash.chunk": "^4.2.0",
|
||||
"pumpify": "^2.0.1",
|
||||
"tweetnacl": "^1.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.0.0 || >=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sideway/address": {
|
||||
"version": "4.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz",
|
||||
|
|
@ -5032,6 +5079,16 @@
|
|||
"electron-builder-squirrel-windows": "24.13.3"
|
||||
}
|
||||
},
|
||||
"node_modules/app-builder-lib/node_modules/chownr": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
||||
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/app-builder-lib/node_modules/fs-extra": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||
|
|
@ -5060,6 +5117,46 @@
|
|||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/app-builder-lib/node_modules/minizlib": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
|
||||
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"minipass": "^3.0.0",
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/app-builder-lib/node_modules/minizlib/node_modules/minipass": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
|
||||
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/app-builder-lib/node_modules/mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/app-builder-lib/node_modules/semver": {
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
|
||||
|
|
@ -5073,6 +5170,24 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/app-builder-lib/node_modules/tar": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
|
||||
"integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"chownr": "^2.0.0",
|
||||
"fs-minipass": "^2.0.0",
|
||||
"minipass": "^5.0.0",
|
||||
"minizlib": "^2.1.1",
|
||||
"mkdirp": "^1.0.3",
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/app-builder-lib/node_modules/universalify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
|
|
@ -5884,13 +5999,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/chownr": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
||||
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
|
||||
"integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/chrome-launcher": {
|
||||
|
|
@ -6988,6 +7102,18 @@
|
|||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/duplexify": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz",
|
||||
"integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"end-of-stream": "^1.4.1",
|
||||
"inherits": "^2.0.3",
|
||||
"readable-stream": "^3.1.1",
|
||||
"stream-shift": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/eastasianwidth": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||
|
|
@ -7237,7 +7363,6 @@
|
|||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"once": "^1.4.0"
|
||||
|
|
@ -9342,6 +9467,12 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.chunk": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz",
|
||||
"integrity": "sha512-ZzydJKfUHJwHa+hF5X66zLFCBrWn5GeF28OHEr4WVWtNDXlQ/IjWKPBiikqKo2ne0+v6JgCgJ0GzJp8k8bHC7w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.debounce": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
||||
|
|
@ -10360,30 +10491,24 @@
|
|||
}
|
||||
},
|
||||
"node_modules/minizlib": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
|
||||
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
|
||||
"dev": true,
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz",
|
||||
"integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"minipass": "^3.0.0",
|
||||
"yallist": "^4.0.0"
|
||||
"minipass": "^7.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/minizlib/node_modules/minipass": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
|
||||
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
|
||||
"dev": true,
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/mkdirp": {
|
||||
|
|
@ -10713,7 +10838,6 @@
|
|||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
|
|
@ -11251,13 +11375,23 @@
|
|||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
|
||||
"integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/pumpify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz",
|
||||
"integrity": "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"duplexify": "^4.1.1",
|
||||
"inherits": "^2.0.3",
|
||||
"pump": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
|
|
@ -11713,9 +11847,7 @@
|
|||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
|
|
@ -12694,13 +12826,17 @@
|
|||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/stream-shift": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz",
|
||||
"integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/string_decoder": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "~5.2.0"
|
||||
}
|
||||
|
|
@ -12872,21 +13008,20 @@
|
|||
}
|
||||
},
|
||||
"node_modules/tar": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
|
||||
"integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
|
||||
"dev": true,
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz",
|
||||
"integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"chownr": "^2.0.0",
|
||||
"fs-minipass": "^2.0.0",
|
||||
"minipass": "^5.0.0",
|
||||
"minizlib": "^2.1.1",
|
||||
"mkdirp": "^1.0.3",
|
||||
"yallist": "^4.0.0"
|
||||
"@isaacs/fs-minipass": "^4.0.0",
|
||||
"chownr": "^3.0.0",
|
||||
"minipass": "^7.1.2",
|
||||
"minizlib": "^3.0.1",
|
||||
"mkdirp": "^3.0.1",
|
||||
"yallist": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tar-stream": {
|
||||
|
|
@ -12907,17 +13042,37 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/tar/node_modules/minipass": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/tar/node_modules/mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
|
||||
"dev": true,
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
|
||||
"integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
"mkdirp": "dist/cjs/src/bin.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/tar/node_modules/yallist": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
|
||||
"integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/temp": {
|
||||
|
|
@ -13295,6 +13450,12 @@
|
|||
"integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/tweetnacl": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
|
||||
"integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==",
|
||||
"license": "Unlicense"
|
||||
},
|
||||
"node_modules/type-detect": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
|
||||
|
|
@ -13510,9 +13671,7 @@
|
|||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/utils-merge": {
|
||||
"version": "1.0.1",
|
||||
|
|
@ -13709,7 +13868,6 @@
|
|||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/write-file-atomic": {
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@samuelthomas2774/saltpack": "^0.4.0",
|
||||
"body-parser": "^1.20.2",
|
||||
"cli-table": "^0.3.11",
|
||||
"debug": "^4.3.4",
|
||||
|
|
@ -50,6 +51,7 @@
|
|||
"sharp": "^0.33.3",
|
||||
"splatnet3-types": "^0.2.20231119210145",
|
||||
"supports-color": "^9.4.0",
|
||||
"tar": "^7.4.3",
|
||||
"tslib": "^2.6.2",
|
||||
"undici": "^6.15.0",
|
||||
"yargs": "^17.7.2"
|
||||
|
|
@ -76,8 +78,8 @@
|
|||
"@types/yargs": "^17.0.32",
|
||||
"electron": "^30.0.1",
|
||||
"electron-builder": "^24.13.3",
|
||||
"mime-types": "^2.1.35",
|
||||
"i18next": "^22.4.6",
|
||||
"mime-types": "^2.1.35",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-i18next": "^12.1.1",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"require_version": [],
|
||||
"log_encryption_key": "E2Sii_7drCzK-68RsEoArmopiAIlZD_6TMA2F_UAAU0",
|
||||
"coral": {
|
||||
"znca_version": "2.12.0"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ export const menus = {
|
|||
friend: {
|
||||
presence_online: 'Online',
|
||||
game_first_played: 'Zuerst gespielt: {{date, datetime}}',
|
||||
|
||||
|
||||
game_play_time_h: 'Spielzeit: $t(friend.hours, {"count": {{hours}}})',
|
||||
game_play_time_hm: 'Spielzeit: $t(friend.hours, {"count": {{hours}}}), $t(friend.minutes, {"count": {{minutes}}})',
|
||||
game_play_time_m: 'Spielzeit: $t(friend.minutes, {"count": {{minutes}}})',
|
||||
|
|
@ -109,7 +109,7 @@ export const na_auth = {
|
|||
|
||||
text: `Um Zugriff auf die API der Nintendo Switch Online App zu erhalten, muss nxapi einige Daten an Drittanbieter-APIs senden. Dieser Schritt wird benötigt, um Daten zu generieren, damit Nintendo denkt, dass du die echte Nintendo Switch Online App verwendest.
|
||||
Standardmäßig wird nxapi-znca-api.fancy.org.uk oder api.imink.app benutzt. Ein anderer Service kann ebenfalls benutzt werden, indem eine Umgebungsvariable gesetzt wird. Die standardmäßige API könnte sich jederzeit ohne Hinweis ändern, wenn du keinen spezifischen Service erzwingst.
|
||||
|
||||
|
||||
Die gesendeten Daten beinhalten:
|
||||
|
||||
- Deine Nintendo Account ID
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ export const app_menu = {
|
|||
learn_more: 'Learn More',
|
||||
learn_more_github: 'Learn More (GitHub)',
|
||||
search_issues: 'Search Issues',
|
||||
export_logs: 'Export Logs',
|
||||
|
||||
refresh: 'Refresh',
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { i18n } from 'i18next';
|
|||
import { GITHUB_MIRROR_URL, GITLAB_URL, ISSUES_URL } from '../../common/constants.js';
|
||||
import { app, BrowserWindow, Menu, MenuItem, shell } from 'electron';
|
||||
import { App } from './index.js';
|
||||
import { createLogArchive } from './support.js';
|
||||
|
||||
let appinstance: App | null;
|
||||
|
||||
|
|
@ -59,6 +60,12 @@ function createAppMenuItems(i18n?: i18n) {
|
|||
await shell.openExternal(ISSUES_URL);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: i18n?.t('app_menu:export_logs') ?? 'Export Logs',
|
||||
click: () => {
|
||||
createLogArchive();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ function buildUserMenu(app: App, user: NintendoAccountUser, nso?: CurrentUser, m
|
|||
new MenuItem({label: t('discord_disable')!,
|
||||
click: () => app.menu?.setActiveDiscordPresenceUser(null)}),
|
||||
] : monitor?.presence_user ? [
|
||||
new MenuItem({label: t('discord_enabled_for', {name:
|
||||
new MenuItem({label: t('discord_enabled_for', {name:
|
||||
monitor.user?.friends.result.friends.find(f => f.nsaId === monitor.presence_user)?.name ??
|
||||
monitor.presence_user})!,
|
||||
enabled: false}),
|
||||
|
|
|
|||
88
src/app/main/support.ts
Normal file
88
src/app/main/support.ts
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
import { Buffer } from 'node:buffer';
|
||||
import { createWriteStream, WriteStream } from 'node:fs';
|
||||
import { app, dialog, Notification, shell } from 'electron';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { generateEncryptedLogArchive } from '../../util/support.js';
|
||||
import { join } from 'node:path';
|
||||
import { showErrorDialog } from './util.js';
|
||||
|
||||
const debug = createDebug('app:main:support');
|
||||
|
||||
export async function createLogArchive() {
|
||||
let start_notification: Notification | null = null;
|
||||
|
||||
try {
|
||||
const { default: config } = await import('../../common/remote-config.js');
|
||||
|
||||
if (!config.log_encryption_key) {
|
||||
throw new Error('No log encryption key in remote configuration');
|
||||
}
|
||||
|
||||
const default_name = 'nxapi-logs-' +
|
||||
new Date().toISOString().replace(/[-:Z]/g, '').replace(/\.\d+/, '').replace(/T/, '-') +
|
||||
'.tar.gz';
|
||||
|
||||
const result = await dialog.showSaveDialog({
|
||||
defaultPath: join(app.getPath('downloads'), default_name),
|
||||
filters: [{name: 'Tape archive (encrypted)', extensions: ['tgz', 'tar.gz']}],
|
||||
});
|
||||
|
||||
if (result.canceled) return;
|
||||
|
||||
const out = await createOutputStream(result.filePath);
|
||||
|
||||
debug('creating log archive');
|
||||
|
||||
start_notification = new Notification({
|
||||
title: 'Creating log archive',
|
||||
});
|
||||
start_notification.show();
|
||||
|
||||
const key = Buffer.from(config.log_encryption_key, 'base64url');
|
||||
const [encrypt] = await generateEncryptedLogArchive(key);
|
||||
|
||||
encrypt.pipe(out);
|
||||
|
||||
await new Promise((rs, rj) => {
|
||||
encrypt.on('end', rs);
|
||||
encrypt.on('error', rj);
|
||||
});
|
||||
|
||||
debug('done');
|
||||
|
||||
start_notification.close();
|
||||
|
||||
new Notification({
|
||||
title: 'Created log archive',
|
||||
}).show();
|
||||
|
||||
shell.showItemInFolder(result.filePath);
|
||||
} catch (err) {
|
||||
start_notification?.close();
|
||||
|
||||
showErrorDialog({
|
||||
message: 'Error creating log archive',
|
||||
error: err,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function createOutputStream(path: string) {
|
||||
return new Promise<WriteStream>((rs, rj) => {
|
||||
const out = createWriteStream(path);
|
||||
|
||||
const onready = () => {
|
||||
out.removeListener('ready', onready);
|
||||
out.removeListener('error', onerror);
|
||||
rs(out);
|
||||
};
|
||||
const onerror = () => {
|
||||
out.removeListener('ready', onready);
|
||||
out.removeListener('error', onerror);
|
||||
rs(out);
|
||||
};
|
||||
|
||||
out.on('ready', onready);
|
||||
out.on('error', onerror);
|
||||
});
|
||||
}
|
||||
|
|
@ -7,3 +7,5 @@ export * as remoteConfig from './remote-config.js';
|
|||
export * as storage from './storage.js';
|
||||
export * as presenceEmbedRender from './presence-embed-render.js';
|
||||
export * as presenceEmbedServer from './presence-embed-server.js';
|
||||
export * as logArchive from './log-archive.js';
|
||||
export * as decryptLogArchive from './decrypt-log-archive.js';
|
||||
|
|
|
|||
34
src/cli/util/decrypt-log-archive.ts
Normal file
34
src/cli/util/decrypt-log-archive.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import { Buffer } from 'node:buffer';
|
||||
import { DecryptStream } from '@samuelthomas2774/saltpack';
|
||||
import tweetnacl from 'tweetnacl';
|
||||
import type { Arguments as ParentArguments } from './index.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
|
||||
const debug = createDebug('cli:util:decrypt-log-archive');
|
||||
|
||||
export const command = 'decrypt-log-archive';
|
||||
export const desc = null;
|
||||
|
||||
export function builder(yargs: Argv<ParentArguments>) {
|
||||
return yargs;
|
||||
}
|
||||
|
||||
type Arguments = YargsArguments<ReturnType<typeof builder>>;
|
||||
|
||||
export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
||||
if (!process.env.NXAPI_SUPPORT_SECRET_KEY) {
|
||||
throw new Error('Missing NXAPI_SUPPORT_SECRET_KEY environment variable');
|
||||
}
|
||||
|
||||
const key = Buffer.from(process.env.NXAPI_SUPPORT_SECRET_KEY, 'base64url');
|
||||
const keypair = tweetnacl.box.keyPair.fromSecretKey(key);
|
||||
|
||||
const decrypt = new DecryptStream(keypair);
|
||||
|
||||
decrypt.pipe(process.stdout);
|
||||
|
||||
debug('decrypting tar.gz to stdout');
|
||||
|
||||
process.stdin.pipe(decrypt);
|
||||
}
|
||||
70
src/cli/util/log-archive.ts
Normal file
70
src/cli/util/log-archive.ts
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
import { Buffer } from 'node:buffer';
|
||||
import { createWriteStream, WriteStream } from 'node:fs';
|
||||
import type { Arguments as ParentArguments } from './index.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { generateEncryptedLogArchive } from '../../util/support.js';
|
||||
|
||||
const debug = createDebug('cli:util:log-archive');
|
||||
|
||||
export const command = 'log-archive [output]';
|
||||
export const desc = 'Create an encrypted log archive for support';
|
||||
|
||||
export function builder(yargs: Argv<ParentArguments>) {
|
||||
return yargs.positional('output', {
|
||||
describe: 'Output path',
|
||||
type: 'string',
|
||||
});
|
||||
}
|
||||
|
||||
type Arguments = YargsArguments<ReturnType<typeof builder>>;
|
||||
|
||||
export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
||||
const { default: config } = await import('../../common/remote-config.js');
|
||||
|
||||
if (!config.log_encryption_key) {
|
||||
throw new Error('No log encryption key in remote configuration');
|
||||
}
|
||||
|
||||
const out = await createOutputStream(argv.output);
|
||||
|
||||
debug('creating log archive');
|
||||
|
||||
const key = Buffer.from(config.log_encryption_key, 'base64url');
|
||||
const [encrypt] = await generateEncryptedLogArchive(key);
|
||||
|
||||
encrypt.pipe(out);
|
||||
|
||||
encrypt.on('end', () => {
|
||||
debug('done');
|
||||
});
|
||||
}
|
||||
|
||||
async function createOutputStream(path?: string) {
|
||||
if (!path && process.stdout.isTTY) {
|
||||
console.error('No output path set but stdout is a TTY. Run `nxapi util log-archive -` to force output to a terminal.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!path || path === '-') {
|
||||
return process.stdout;
|
||||
}
|
||||
|
||||
return new Promise<WriteStream>((rs, rj) => {
|
||||
const out = createWriteStream(path);
|
||||
|
||||
const onready = () => {
|
||||
out.removeListener('ready', onready);
|
||||
out.removeListener('error', onerror);
|
||||
rs(out);
|
||||
};
|
||||
const onerror = () => {
|
||||
out.removeListener('ready', onready);
|
||||
out.removeListener('error', onerror);
|
||||
rs(out);
|
||||
};
|
||||
|
||||
out.on('ready', onready);
|
||||
out.on('error', onerror);
|
||||
});
|
||||
}
|
||||
|
|
@ -251,6 +251,8 @@ export interface NxapiRemoteConfig {
|
|||
*/
|
||||
require_version: string[];
|
||||
|
||||
log_encryption_key?: string;
|
||||
|
||||
// If null the API should not be used
|
||||
coral: CoralRemoteConfig | null;
|
||||
coral_auth: {
|
||||
|
|
|
|||
119
src/util/support.ts
Normal file
119
src/util/support.ts
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
import { resolve } from 'node:path';
|
||||
import * as os from 'node:os';
|
||||
import { EncryptStream } from '@samuelthomas2774/saltpack';
|
||||
import { Header, list, Pack, ReadEntry } from 'tar';
|
||||
import createDebug from './debug.js';
|
||||
import { dev, docker, git, paths, product, release, version } from './product.js';
|
||||
import { getUserAgent } from './useragent.js';
|
||||
|
||||
const debug = createDebug('nxapi:util:support');
|
||||
|
||||
export async function createLogArchive(log_path = paths.log) {
|
||||
const tar = new Pack({
|
||||
gzip: true,
|
||||
cwd: log_path,
|
||||
preservePaths: true,
|
||||
onWriteEntry: e => {
|
||||
if (e.path === 'info.json') return;
|
||||
if (e.path.startsWith(log_path)) {
|
||||
e.path = e.path.substring(log_path.length + 1);
|
||||
}
|
||||
e.path = 'log/' + e.path;
|
||||
},
|
||||
});
|
||||
|
||||
tar.on('error', err => {
|
||||
debug('archive error', err);
|
||||
});
|
||||
|
||||
const data = getSystemInfo();
|
||||
tar.add(createJsonFileEntry(data, 'info.json'));
|
||||
|
||||
await addFiles(tar, log_path);
|
||||
|
||||
tar.end();
|
||||
|
||||
return tar;
|
||||
}
|
||||
|
||||
async function addFiles(tar: Pack, file: string) {
|
||||
if (file.charAt(0) === '@') {
|
||||
await list({
|
||||
file: resolve(tar.cwd, file.slice(1)),
|
||||
noResume: true,
|
||||
onReadEntry: entry => {
|
||||
tar.add(entry);
|
||||
},
|
||||
});
|
||||
} else {
|
||||
tar.add(file);
|
||||
}
|
||||
}
|
||||
|
||||
function getSystemInfo() {
|
||||
return {
|
||||
version,
|
||||
created_at: new Date(),
|
||||
product: {
|
||||
release,
|
||||
docker,
|
||||
git,
|
||||
dev,
|
||||
product,
|
||||
user_agent: getUserAgent(),
|
||||
},
|
||||
environment: {
|
||||
execPath: process.execPath,
|
||||
execArgv: process.execArgv,
|
||||
argv: process.argv,
|
||||
env: process.env,
|
||||
paths,
|
||||
},
|
||||
node: {
|
||||
versions: process.versions,
|
||||
features: process.features,
|
||||
},
|
||||
system: {
|
||||
platform: process.platform,
|
||||
arch: process.arch,
|
||||
uname: os.version(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function createJsonFileEntry(data: unknown, name: string, date = new Date()) {
|
||||
debug('adding file', name, data);
|
||||
|
||||
const buffer = Buffer.from(JSON.stringify(data, null, 4) + '\n', 'utf-8');
|
||||
|
||||
const header = new Header({
|
||||
path: name,
|
||||
mode: 0o600,
|
||||
uid: process.getuid?.() ?? 0,
|
||||
gid: process.getgid?.() ?? 0,
|
||||
ctime: date,
|
||||
mtime: date,
|
||||
size: buffer.length,
|
||||
type: 'File',
|
||||
});
|
||||
|
||||
const entry = new ReadEntry(header);
|
||||
|
||||
entry.end(buffer);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
export async function generateEncryptedLogArchive(key: Uint8Array, log_path = paths.log) {
|
||||
const encrypt = new EncryptStream(null, [key]);
|
||||
|
||||
encrypt.on('error', err => {
|
||||
debug('encrypt error', err);
|
||||
});
|
||||
|
||||
const tar = await createLogArchive();
|
||||
|
||||
tar.pipe(encrypt);
|
||||
|
||||
return [encrypt, tar] as const;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user