diff --git a/gulpfile.js/thirdparty-lib-copy.js b/gulpfile.js/thirdparty-lib-copy.js index 466db4ec62..3e35b93808 100644 --- a/gulpfile.js/thirdparty-lib-copy.js +++ b/gulpfile.js/thirdparty-lib-copy.js @@ -242,7 +242,9 @@ let copyThirdPartyLibs = series( // jasmine-reporters copyFiles.bind(copyFiles, ['node_modules/jasmine-reporters/src/**/*'], 'test/thirdparty/jasmine-reporters/'), - copyLicence.bind(copyLicence, 'node_modules/jasmine-reporters/LICENSE', 'jasmine-reporters') + copyLicence.bind(copyLicence, 'node_modules/jasmine-reporters/LICENSE', 'jasmine-reporters'), + // lmdb + copyLicence.bind(copyLicence, 'node_modules/lmdb/LICENSE', 'lmdb') ); diff --git a/package-lock.json b/package-lock.json index 62ced99241..ae112e8ece 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix", - "version": "5.1.0-0", + "version": "5.1.1-0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix", - "version": "5.1.0-0", + "version": "5.1.1-0", "dependencies": { "@bugsnag/js": "^7.18.0", "@floating-ui/dom": "^0.5.4", @@ -64,6 +64,7 @@ "jasmine-core": "^4.2.0", "jasmine-reporters": "^2.5.0", "jsdoc-to-markdown": "^9.1.1", + "lmdb": "^3.5.1", "readable-stream": "^3.6.0", "through2": "^4.0.2" } @@ -797,6 +798,13 @@ "xtend": "~4.0.1" } }, + "node_modules/@harperfast/extended-iterable": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@harperfast/extended-iterable/-/extended-iterable-1.0.3.tgz", + "integrity": "sha512-sSAYhQca3rDWtQUHSAPeO7axFIUJOI6hn1gjRC5APVE1a90tuyT8f5WIgRsFhhWA7htNkju2veB9eWL6YHi/Lw==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/@highlightjs/cdn-assets": { "version": "11.5.1", "resolved": "https://registry.npmjs.org/@highlightjs/cdn-assets/-/cdn-assets-11.5.1.tgz", @@ -862,6 +870,188 @@ "node": ">=v12.0.0" } }, + "node_modules/@lmdb/lmdb-darwin-arm64": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.5.1.tgz", + "integrity": "sha512-tpfN4kKrrMpQ+If1l8bhmoNkECJi0iOu6AEdrTJvWVC+32sLxTARX5Rsu579mPImRP9YFWfWgeRQ5oav7zApQQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@lmdb/lmdb-darwin-x64": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.5.1.tgz", + "integrity": "sha512-+a2tTfc3rmWhLAolFUWRgJtpSuu+Fw/yjn4rF406NMxhfjbMuiOUTDRvRlMFV+DzyjkwnokisskHbCWkS3Ly5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@lmdb/lmdb-linux-arm": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.5.1.tgz", + "integrity": "sha512-0EgcE6reYr8InjD7V37EgXcYrloqpxVPINy3ig1MwDSbl6LF/vXTYRH9OE1Ti1D8YZnB35ZH9aTcdfSb5lql2A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@lmdb/lmdb-linux-arm64": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.5.1.tgz", + "integrity": "sha512-aoERa5B6ywXdyFeYGQ1gbQpkMkDbEo45qVoXE5QpIRavqjnyPwjOulMkmkypkmsbJ5z4Wi0TBztON8agCTG0Vg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@lmdb/lmdb-linux-x64": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.5.1.tgz", + "integrity": "sha512-SqNDY1+vpji7bh0sFH5wlWyFTOzjbDOl0/kB5RLLYDAFyd/uw3n7wyrmas3rYPpAW7z18lMOi1yKlTPv967E3g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@lmdb/lmdb-win32-arm64": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-arm64/-/lmdb-win32-arm64-3.5.1.tgz", + "integrity": "sha512-50v0O1Lt37cwrmR9vWZK5hRW0Aw+KEmxJJ75fge/zIYdvNKB/0bSMSVR5Uc2OV9JhosIUyklOmrEvavwNJ8D6w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@lmdb/lmdb-win32-x64": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.5.1.tgz", + "integrity": "sha512-qwosvPyl+zpUlp3gRb7UcJ3H8S28XHCzkv0Y0EgQToXjQP91ZD67EHSCDmaLjtKhe+GVIW5om1KUpzVLA0l6pg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", + "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", + "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", + "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", + "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", + "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", + "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1082,6 +1272,7 @@ "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", "dev": true, + "peer": true, "dependencies": { "@types/linkify-it": "^5", "@types/mdurl": "^2" @@ -1103,7 +1294,8 @@ "version": "17.0.8", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.8.tgz", "integrity": "sha512-YofkM6fGv4gDJq78g4j0mMuGMkZVxZDgtU0JRdx6FgiJDG+0fY0GKVolOV8WqVmEhLCXkQRjwDdKyPxJp/uucg==", - "dev": true + "dev": true, + "peer": true }, "node_modules/@types/normalize-package-data": { "version": "2.4.4", @@ -1149,6 +1341,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3821,6 +4014,16 @@ "node": ">=0.10.0" } }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/devicon": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/devicon/-/devicon-2.15.1.tgz", @@ -4201,6 +4404,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.19.0.tgz", "integrity": "sha512-SXOPj3x9VKvPe81TjjUJCYlV4oJjQw68Uek+AM0X4p+33dj2HY5bpTZOgnQHcG2eAm1mtCU9uNMnJi7exU/kYw==", "dev": true, + "peer": true, "dependencies": { "@eslint/eslintrc": "^1.3.0", "@humanwhocodes/config-array": "^0.9.2", @@ -5900,6 +6104,7 @@ "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", "dev": true, + "peer": true, "dependencies": { "glob-watcher": "^5.0.3", "gulp-cli": "^2.2.0", @@ -8028,6 +8233,34 @@ "uc.micro": "^2.0.0" } }, + "node_modules/lmdb": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.5.1.tgz", + "integrity": "sha512-NYHA0MRPjvNX+vSw8Xxg6FLKxzAG+e7Pt8RqAQA/EehzHVXq9SxDqJIN3JL1hK0dweb884y8kIh6rkWvPyg9Wg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@harperfast/extended-iterable": "^1.0.3", + "msgpackr": "^1.11.2", + "node-addon-api": "^6.1.0", + "node-gyp-build-optional-packages": "5.2.2", + "ordered-binary": "^1.5.3", + "weak-lru-cache": "^1.2.2" + }, + "bin": { + "download-lmdb-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@lmdb/lmdb-darwin-arm64": "3.5.1", + "@lmdb/lmdb-darwin-x64": "3.5.1", + "@lmdb/lmdb-linux-arm": "3.5.1", + "@lmdb/lmdb-linux-arm64": "3.5.1", + "@lmdb/lmdb-linux-x64": "3.5.1", + "@lmdb/lmdb-win32-arm64": "3.5.1", + "@lmdb/lmdb-win32-x64": "3.5.1" + } + }, "node_modules/load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -8819,6 +9052,39 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "devOptional": true }, + "node_modules/msgpackr": { + "version": "1.11.8", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.8.tgz", + "integrity": "sha512-bC4UGzHhVvgDNS7kn9tV8fAucIYUBuGojcaLiz7v+P63Lmtm0Xeji8B/8tYKddALXxJLpwIeBmUN3u64C4YkRA==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "msgpackr-extract": "^3.0.2" + } + }, + "node_modules/msgpackr-extract": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", + "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build-optional-packages": "5.2.2" + }, + "bin": { + "download-msgpackr-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" + } + }, "node_modules/multipipe": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", @@ -8939,6 +9205,28 @@ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", "dev": true }, + "node_modules/node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-gyp-build-optional-packages": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", + "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.1" + }, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" + } + }, "node_modules/node.extend": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.8.tgz", @@ -9270,6 +9558,13 @@ "node": ">= 0.8.0" } }, + "node_modules/ordered-binary": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.6.1.tgz", + "integrity": "sha512-QkCdPooczexPLiXIrbVOPYkR3VO3T6v2OyKRkR1Xbhpy7/LAVXwahnRCgRp78Oe/Ehf0C/HATAxfSr6eA1oX+w==", + "dev": true, + "license": "MIT" + }, "node_modules/ordered-read-streams": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", @@ -10054,6 +10349,7 @@ "version": "3.2.5", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -12148,6 +12444,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -12607,6 +12904,13 @@ "node >=0.1.95" ] }, + "node_modules/weak-lru-cache": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz", + "integrity": "sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw==", + "dev": true, + "license": "MIT" + }, "node_modules/websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", @@ -13533,6 +13837,12 @@ } } }, + "@harperfast/extended-iterable": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@harperfast/extended-iterable/-/extended-iterable-1.0.3.tgz", + "integrity": "sha512-sSAYhQca3rDWtQUHSAPeO7axFIUJOI6hn1gjRC5APVE1a90tuyT8f5WIgRsFhhWA7htNkju2veB9eWL6YHi/Lw==", + "dev": true + }, "@highlightjs/cdn-assets": { "version": "11.5.1", "resolved": "https://registry.npmjs.org/@highlightjs/cdn-assets/-/cdn-assets-11.5.1.tgz", @@ -13586,6 +13896,97 @@ "lodash": "^4.17.21" } }, + "@lmdb/lmdb-darwin-arm64": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.5.1.tgz", + "integrity": "sha512-tpfN4kKrrMpQ+If1l8bhmoNkECJi0iOu6AEdrTJvWVC+32sLxTARX5Rsu579mPImRP9YFWfWgeRQ5oav7zApQQ==", + "dev": true, + "optional": true + }, + "@lmdb/lmdb-darwin-x64": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.5.1.tgz", + "integrity": "sha512-+a2tTfc3rmWhLAolFUWRgJtpSuu+Fw/yjn4rF406NMxhfjbMuiOUTDRvRlMFV+DzyjkwnokisskHbCWkS3Ly5w==", + "dev": true, + "optional": true + }, + "@lmdb/lmdb-linux-arm": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.5.1.tgz", + "integrity": "sha512-0EgcE6reYr8InjD7V37EgXcYrloqpxVPINy3ig1MwDSbl6LF/vXTYRH9OE1Ti1D8YZnB35ZH9aTcdfSb5lql2A==", + "dev": true, + "optional": true + }, + "@lmdb/lmdb-linux-arm64": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.5.1.tgz", + "integrity": "sha512-aoERa5B6ywXdyFeYGQ1gbQpkMkDbEo45qVoXE5QpIRavqjnyPwjOulMkmkypkmsbJ5z4Wi0TBztON8agCTG0Vg==", + "dev": true, + "optional": true + }, + "@lmdb/lmdb-linux-x64": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.5.1.tgz", + "integrity": "sha512-SqNDY1+vpji7bh0sFH5wlWyFTOzjbDOl0/kB5RLLYDAFyd/uw3n7wyrmas3rYPpAW7z18lMOi1yKlTPv967E3g==", + "dev": true, + "optional": true + }, + "@lmdb/lmdb-win32-arm64": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-arm64/-/lmdb-win32-arm64-3.5.1.tgz", + "integrity": "sha512-50v0O1Lt37cwrmR9vWZK5hRW0Aw+KEmxJJ75fge/zIYdvNKB/0bSMSVR5Uc2OV9JhosIUyklOmrEvavwNJ8D6w==", + "dev": true, + "optional": true + }, + "@lmdb/lmdb-win32-x64": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.5.1.tgz", + "integrity": "sha512-qwosvPyl+zpUlp3gRb7UcJ3H8S28XHCzkv0Y0EgQToXjQP91ZD67EHSCDmaLjtKhe+GVIW5om1KUpzVLA0l6pg==", + "dev": true, + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", + "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", + "dev": true, + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", + "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", + "dev": true, + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", + "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", + "dev": true, + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", + "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", + "dev": true, + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", + "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", + "dev": true, + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", + "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", + "dev": true, + "optional": true + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -13749,6 +14150,7 @@ "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", "dev": true, + "peer": true, "requires": { "@types/linkify-it": "^5", "@types/mdurl": "^2" @@ -13770,7 +14172,8 @@ "version": "17.0.8", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.8.tgz", "integrity": "sha512-YofkM6fGv4gDJq78g4j0mMuGMkZVxZDgtU0JRdx6FgiJDG+0fY0GKVolOV8WqVmEhLCXkQRjwDdKyPxJp/uucg==", - "dev": true + "dev": true, + "peer": true }, "@types/normalize-package-data": { "version": "2.4.4", @@ -13809,7 +14212,8 @@ "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true + "dev": true, + "peer": true }, "acorn-jsx": { "version": "5.3.2", @@ -15924,6 +16328,12 @@ "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", "dev": true }, + "detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true + }, "devicon": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/devicon/-/devicon-2.15.1.tgz", @@ -16250,6 +16660,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.19.0.tgz", "integrity": "sha512-SXOPj3x9VKvPe81TjjUJCYlV4oJjQw68Uek+AM0X4p+33dj2HY5bpTZOgnQHcG2eAm1mtCU9uNMnJi7exU/kYw==", "dev": true, + "peer": true, "requires": { "@eslint/eslintrc": "^1.3.0", "@humanwhocodes/config-array": "^0.9.2", @@ -17603,6 +18014,7 @@ "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", "dev": true, + "peer": true, "requires": { "glob-watcher": "^5.0.3", "gulp-cli": "^2.2.0", @@ -19310,6 +19722,27 @@ "uc.micro": "^2.0.0" } }, + "lmdb": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.5.1.tgz", + "integrity": "sha512-NYHA0MRPjvNX+vSw8Xxg6FLKxzAG+e7Pt8RqAQA/EehzHVXq9SxDqJIN3JL1hK0dweb884y8kIh6rkWvPyg9Wg==", + "dev": true, + "requires": { + "@harperfast/extended-iterable": "^1.0.3", + "@lmdb/lmdb-darwin-arm64": "3.5.1", + "@lmdb/lmdb-darwin-x64": "3.5.1", + "@lmdb/lmdb-linux-arm": "3.5.1", + "@lmdb/lmdb-linux-arm64": "3.5.1", + "@lmdb/lmdb-linux-x64": "3.5.1", + "@lmdb/lmdb-win32-arm64": "3.5.1", + "@lmdb/lmdb-win32-x64": "3.5.1", + "msgpackr": "^1.11.2", + "node-addon-api": "^6.1.0", + "node-gyp-build-optional-packages": "5.2.2", + "ordered-binary": "^1.5.3", + "weak-lru-cache": "^1.2.2" + } + }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -19977,6 +20410,31 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "devOptional": true }, + "msgpackr": { + "version": "1.11.8", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.8.tgz", + "integrity": "sha512-bC4UGzHhVvgDNS7kn9tV8fAucIYUBuGojcaLiz7v+P63Lmtm0Xeji8B/8tYKddALXxJLpwIeBmUN3u64C4YkRA==", + "dev": true, + "requires": { + "msgpackr-extract": "^3.0.2" + } + }, + "msgpackr-extract": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", + "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", + "dev": true, + "optional": true, + "requires": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3", + "node-gyp-build-optional-packages": "5.2.2" + } + }, "multipipe": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", @@ -20078,6 +20536,21 @@ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", "dev": true }, + "node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", + "dev": true + }, + "node-gyp-build-optional-packages": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", + "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", + "dev": true, + "requires": { + "detect-libc": "^2.0.1" + } + }, "node.extend": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.8.tgz", @@ -20329,6 +20802,12 @@ "word-wrap": "^1.2.3" } }, + "ordered-binary": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.6.1.tgz", + "integrity": "sha512-QkCdPooczexPLiXIrbVOPYkR3VO3T6v2OyKRkR1Xbhpy7/LAVXwahnRCgRp78Oe/Ehf0C/HATAxfSr6eA1oX+w==", + "dev": true + }, "ordered-read-streams": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", @@ -20987,7 +21466,8 @@ "prettier": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", - "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==" + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "peer": true }, "pretty-hrtime": { "version": "1.0.3", @@ -22668,7 +23148,8 @@ "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "dev": true + "dev": true, + "peer": true }, "typical": { "version": "7.3.0", @@ -23043,6 +23524,12 @@ "integrity": "sha1-6NugkbdFZ5mjr1eXi5hud+EyBAY=", "dev": true }, + "weak-lru-cache": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz", + "integrity": "sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw==", + "dev": true + }, "websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", diff --git a/package.json b/package.json index f539312bed..d5d08f5a93 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,8 @@ "jasmine-reporters": "^2.5.0", "jsdoc-to-markdown": "^9.1.1", "readable-stream": "^3.6.0", - "through2": "^4.0.2" + "through2": "^4.0.2", + "lmdb": "^3.5.1" }, "scripts": { "lint": "eslint --quiet src test", @@ -121,4 +122,4 @@ "tinycolor2": "^1.4.2", "underscore": "^1.13.4" } -} \ No newline at end of file +} diff --git a/src-node/package-lock.json b/src-node/package-lock.json index d95b7de1a1..ec84f2d7c8 100644 --- a/src-node/package-lock.json +++ b/src-node/package-lock.json @@ -1,18 +1,18 @@ { "name": "@phcode/node-core", - "version": "5.1.0-0", + "version": "5.1.1-0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@phcode/node-core", - "version": "5.1.0-0", + "version": "5.1.1-0", "license": "GNU-AGPL3.0", "dependencies": { "@expo/sudo-prompt": "^9.3.2", "@phcode/fs": "^4.0.2", "cross-spawn": "^7.0.6", - "lmdb": "^2.9.2", + "lmdb": "^3.5.1", "mime-types": "^2.1.35", "npm": "11.8.0", "open": "^10.1.0", @@ -20,7 +20,7 @@ "ws": "^8.17.1" }, "engines": { - "node": "20" + "node": "24" } }, "node_modules/@expo/sudo-prompt": { @@ -28,145 +28,176 @@ "resolved": "https://registry.npmjs.org/@expo/sudo-prompt/-/sudo-prompt-9.3.2.tgz", "integrity": "sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw==" }, + "node_modules/@harperfast/extended-iterable": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@harperfast/extended-iterable/-/extended-iterable-1.0.3.tgz", + "integrity": "sha512-sSAYhQca3rDWtQUHSAPeO7axFIUJOI6hn1gjRC5APVE1a90tuyT8f5WIgRsFhhWA7htNkju2veB9eWL6YHi/Lw==", + "license": "Apache-2.0" + }, "node_modules/@lmdb/lmdb-darwin-arm64": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-2.9.2.tgz", - "integrity": "sha512-+GX51Fi8nZOrEXCFiQHnrCpKAzkfDA2sY5+M6Ry4wZEu711o2qlvg+7xXP+j7OT7+JsfB9ayGCdhra2AAaX02g==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.5.1.tgz", + "integrity": "sha512-tpfN4kKrrMpQ+If1l8bhmoNkECJi0iOu6AEdrTJvWVC+32sLxTARX5Rsu579mPImRP9YFWfWgeRQ5oav7zApQQ==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@lmdb/lmdb-darwin-x64": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-2.9.2.tgz", - "integrity": "sha512-ajkq2oZTd/RXXpgaZqVm6LHoJYf4A42q+S+U4gYKRYpeR4ERGvG+VGCK9bi9MXInQfeq0KM1yv6rsYpvCOoNhQ==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.5.1.tgz", + "integrity": "sha512-+a2tTfc3rmWhLAolFUWRgJtpSuu+Fw/yjn4rF406NMxhfjbMuiOUTDRvRlMFV+DzyjkwnokisskHbCWkS3Ly5w==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@lmdb/lmdb-linux-arm": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-2.9.2.tgz", - "integrity": "sha512-AAdmxDIh1tMYzXOUuDP+TNhvl9pLgvS63M6xhwgVArr79As4msraUSjIJ8J0jlhFKsN7nVoXzPB/jvpp8aK49w==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.5.1.tgz", + "integrity": "sha512-0EgcE6reYr8InjD7V37EgXcYrloqpxVPINy3ig1MwDSbl6LF/vXTYRH9OE1Ti1D8YZnB35ZH9aTcdfSb5lql2A==", "cpu": [ "arm" ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@lmdb/lmdb-linux-arm64": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-2.9.2.tgz", - "integrity": "sha512-WqQqWwFyL8JPVpKJyKnyyg7tnsVlD08PHEyxSMxDQC2EkPpvZuUz2oMqasDoy5tmYB0jANOI13/Qz3Mbh9endQ==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.5.1.tgz", + "integrity": "sha512-aoERa5B6ywXdyFeYGQ1gbQpkMkDbEo45qVoXE5QpIRavqjnyPwjOulMkmkypkmsbJ5z4Wi0TBztON8agCTG0Vg==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@lmdb/lmdb-linux-x64": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-2.9.2.tgz", - "integrity": "sha512-rB4tE80EOxXwTJr9rsATWZghOVP8+mV085P5u/dBdttJSq3TLxY0CMZ8NKB/WJpryNnsfCI4OvjOAibF/fg+GQ==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.5.1.tgz", + "integrity": "sha512-SqNDY1+vpji7bh0sFH5wlWyFTOzjbDOl0/kB5RLLYDAFyd/uw3n7wyrmas3rYPpAW7z18lMOi1yKlTPv967E3g==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, + "node_modules/@lmdb/lmdb-win32-arm64": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-arm64/-/lmdb-win32-arm64-3.5.1.tgz", + "integrity": "sha512-50v0O1Lt37cwrmR9vWZK5hRW0Aw+KEmxJJ75fge/zIYdvNKB/0bSMSVR5Uc2OV9JhosIUyklOmrEvavwNJ8D6w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@lmdb/lmdb-win32-x64": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-2.9.2.tgz", - "integrity": "sha512-VRrM/Zq/k8YEZlGuDvFi3NU753cm+vOa1kUcq4iNyeAEVXzjrSg5K3sHI0d6Od5gLsKctjlQeaFn6+21inU4bw==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.5.1.tgz", + "integrity": "sha512-qwosvPyl+zpUlp3gRb7UcJ3H8S28XHCzkv0Y0EgQToXjQP91ZD67EHSCDmaLjtKhe+GVIW5om1KUpzVLA0l6pg==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.2.tgz", - "integrity": "sha512-9bfjwDxIDWmmOKusUcqdS4Rw+SETlp9Dy39Xui9BEGEk19dDwH0jhipwFzEff/pFg95NKymc6TOTbRKcWeRqyQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", + "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.2.tgz", - "integrity": "sha512-lwriRAHm1Yg4iDf23Oxm9n/t5Zpw1lVnxYU3HnJPTi2lJRkKTrps1KVgvL6m7WvmhYVt/FIsssWay+k45QHeuw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", + "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.2.tgz", - "integrity": "sha512-MOI9Dlfrpi2Cuc7i5dXdxPbFIgbDBGgKR5F2yWEa6FVEtSWncfVNKW5AKjImAQ6CZlBK9tympdsZJ2xThBiWWA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", + "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", "cpu": [ "arm" ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.2.tgz", - "integrity": "sha512-FU20Bo66/f7He9Fp9sP2zaJ1Q8L9uLPZQDub/WlUip78JlPeMbVL8546HbZfcW9LNciEXc8d+tThSJjSC+tmsg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", + "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.2.tgz", - "integrity": "sha512-gsWNDCklNy7Ajk0vBBf9jEx04RUxuDQfBse918Ww+Qb9HCPoGzS+XJTLe96iN3BVK7grnLiYghP/M4L8VsaHeA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", + "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.2.tgz", - "integrity": "sha512-O+6Gs8UeDbyFpbSh2CPEz/UOrrdWPTBYNblZK5CxxLisYt4kGX3Sc+czffFonyjiGSq3jWLwJS/CCJc7tBr4sQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", + "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -304,9 +335,10 @@ } }, "node_modules/detect-libc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", - "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", "engines": { "node": ">=8" } @@ -443,27 +475,30 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/lmdb": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-2.9.2.tgz", - "integrity": "sha512-Q5SQzu4u4sdz4U8QT1uCS04beS7hS/1YYb1suJwaijqVETGAkrPBKr0ERxTeza/u2F6ei5+8UTnzm4ae3PJG3w==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.5.1.tgz", + "integrity": "sha512-NYHA0MRPjvNX+vSw8Xxg6FLKxzAG+e7Pt8RqAQA/EehzHVXq9SxDqJIN3JL1hK0dweb884y8kIh6rkWvPyg9Wg==", "hasInstallScript": true, + "license": "MIT", "dependencies": { - "msgpackr": "^1.9.9", + "@harperfast/extended-iterable": "^1.0.3", + "msgpackr": "^1.11.2", "node-addon-api": "^6.1.0", - "node-gyp-build-optional-packages": "5.1.1", - "ordered-binary": "^1.4.1", + "node-gyp-build-optional-packages": "5.2.2", + "ordered-binary": "^1.5.3", "weak-lru-cache": "^1.2.2" }, "bin": { "download-lmdb-prebuilds": "bin/download-prebuilds.js" }, "optionalDependencies": { - "@lmdb/lmdb-darwin-arm64": "2.9.2", - "@lmdb/lmdb-darwin-x64": "2.9.2", - "@lmdb/lmdb-linux-arm": "2.9.2", - "@lmdb/lmdb-linux-arm64": "2.9.2", - "@lmdb/lmdb-linux-x64": "2.9.2", - "@lmdb/lmdb-win32-x64": "2.9.2" + "@lmdb/lmdb-darwin-arm64": "3.5.1", + "@lmdb/lmdb-darwin-x64": "3.5.1", + "@lmdb/lmdb-linux-arm": "3.5.1", + "@lmdb/lmdb-linux-arm64": "3.5.1", + "@lmdb/lmdb-linux-x64": "3.5.1", + "@lmdb/lmdb-win32-arm64": "3.5.1", + "@lmdb/lmdb-win32-x64": "3.5.1" } }, "node_modules/mime-db": { @@ -486,43 +521,34 @@ } }, "node_modules/msgpackr": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.10.1.tgz", - "integrity": "sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ==", + "version": "1.11.8", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.8.tgz", + "integrity": "sha512-bC4UGzHhVvgDNS7kn9tV8fAucIYUBuGojcaLiz7v+P63Lmtm0Xeji8B/8tYKddALXxJLpwIeBmUN3u64C4YkRA==", + "license": "MIT", "optionalDependencies": { "msgpackr-extract": "^3.0.2" } }, "node_modules/msgpackr-extract": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.2.tgz", - "integrity": "sha512-SdzXp4kD/Qf8agZ9+iTu6eql0m3kWm1A2y1hkpTeVNENutaB0BwHlSvAIaMxwntmRUAUjon2V4L8Z/njd0Ct8A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", + "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", "hasInstallScript": true, + "license": "MIT", "optional": true, "dependencies": { - "node-gyp-build-optional-packages": "5.0.7" + "node-gyp-build-optional-packages": "5.2.2" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" }, "optionalDependencies": { - "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.2", - "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.2" - } - }, - "node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.7.tgz", - "integrity": "sha512-YlCCc6Wffkx0kHkmam79GKvDQ6x+QZkMjFGrIMxgFNILFvGSbCp2fCBC55pGTT9gVaz8Na5CLmxt/urtzRv36w==", - "optional": true, - "bin": { - "node-gyp-build-optional-packages": "bin.js", - "node-gyp-build-optional-packages-optional": "optional.js", - "node-gyp-build-optional-packages-test": "build-test.js" + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" } }, "node_modules/node-addon-api": { @@ -531,9 +557,10 @@ "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" }, "node_modules/node-gyp-build-optional-packages": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.1.1.tgz", - "integrity": "sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", + "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", + "license": "MIT", "dependencies": { "detect-libc": "^2.0.1" }, @@ -2371,6 +2398,7 @@ "version": "4.0.3", "inBundle": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -2509,9 +2537,10 @@ } }, "node_modules/ordered-binary": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.5.1.tgz", - "integrity": "sha512-5VyHfHY3cd0iza71JepYG50My+YUbrFtGoUz2ooEydPyPM7Aai/JW098juLr+RG6+rDJuzNNTsEQu2DZa1A41A==" + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.6.1.tgz", + "integrity": "sha512-QkCdPooczexPLiXIrbVOPYkR3VO3T6v2OyKRkR1Xbhpy7/LAVXwahnRCgRp78Oe/Ehf0C/HATAxfSr6eA1oX+w==", + "license": "MIT" }, "node_modules/path-key": { "version": "3.1.1", diff --git a/src-node/package.json b/src-node/package.json index badcd55ed8..3ebf0415d8 100644 --- a/src-node/package.json +++ b/src-node/package.json @@ -23,10 +23,10 @@ "open": "^10.1.0", "npm": "11.8.0", "ws": "^8.17.1", - "lmdb": "^2.9.2", + "lmdb": "^3.5.1", "mime-types": "^2.1.35", "cross-spawn": "^7.0.6", "which": "^2.0.1", "@expo/sudo-prompt": "^9.3.2" } -} \ No newline at end of file +} diff --git a/src/document/DocumentCommandHandlers.js b/src/document/DocumentCommandHandlers.js index 695e581c1b..e9e64ca517 100644 --- a/src/document/DocumentCommandHandlers.js +++ b/src/document/DocumentCommandHandlers.js @@ -1731,7 +1731,13 @@ define(function (require, exports, module) { .finally(()=>{ raceAgainstTime(_safeNodeTerminate()) .finally(()=>{ - Phoenix.app.closeWindow(); + // In Electron, use allowClose() to bypass the close handler + // (which would otherwise trigger another cleanup cycle). + if(window.__ELECTRON__) { + window.electronAPI.allowClose(); + } else { + Phoenix.app.closeWindow(); + } }); }); }, @@ -1742,8 +1748,10 @@ define(function (require, exports, module) { } function newPhoenixWindow(cliArgsArray = null, cwd=null) { - let width = window.innerWidth; - let height = window.innerHeight; + // Electron needs outerWidth/outerHeight (includes window chrome). + // Tauri needs innerWidth/innerHeight. + let width = window.__ELECTRON__ ? window.outerWidth : window.innerWidth; + let height = window.__ELECTRON__ ? window.outerHeight : window.innerHeight; Phoenix.app.openNewPhoenixEditorWindow(width, height, cliArgsArray, cwd); } @@ -2252,7 +2260,7 @@ define(function (require, exports, module) { Phoenix.app.closeWindow(true); } } - function attachTauriUnloadHandler() { + function _attachNativeUnloadHandler() { Phoenix.app.onCloseWindowRequested(()=>{ _forceQuitIfNeeded(); if(closeInProgress){ @@ -2268,7 +2276,14 @@ define(function (require, exports, module) { raceAgainstTime(_safeNodeTerminate()) .finally(()=>{ closeInProgress = false; - Phoenix.app.closeWindow(); + // In Electron, we must call allowClose() to complete the original + // close request (sets forceClose=true). Calling closeWindow() would + // trigger a new close sequence and cause an infinite loop. + if(window.__ELECTRON__) { + window.electronAPI.allowClose(); + } else { + Phoenix.app.closeWindow(); + } }); }); }, closeFail=>{ @@ -2282,7 +2297,7 @@ define(function (require, exports, module) { let isTestWindow = (new window.URLSearchParams(window.location.search || "")).get("testEnvironment"); if (!isTestWindow) { if(Phoenix.isNativeApp) { - attachTauriUnloadHandler(); + _attachNativeUnloadHandler(); } else { attachBrowserUnloadHandler(); } diff --git a/src/index.html b/src/index.html index 842b67ceb8..136ec1f456 100644 --- a/src/index.html +++ b/src/index.html @@ -276,7 +276,9 @@ if(data && data.__fsError) { throw new Error(data.message); } - return data; + // fsReadFile returns binary data, decode to text + const decoder = new TextDecoder("utf-8"); + return decoder.decode(data); }) .catch(err => { console.error("First boot detected or Failed to init storage from cache." + diff --git a/src/main.js b/src/main.js index 2c98caf5af..16ba27da5f 100644 --- a/src/main.js +++ b/src/main.js @@ -225,7 +225,8 @@ function confirmReload(title, message) { }); copyButton.textContent = 'Copy Error'; getHelpButton.textContent = 'Get Help'; - reloadButton.textContent = 'Restart App'; + // In native apps, we can't reload because AES trust ring won't survive - must quit and restart manually + reloadButton.textContent = Phoenix.isNativeApp ? 'Quit App' : 'Restart App'; // Styling for visibility // Define common styles for buttons const buttonStyles = { @@ -303,7 +304,7 @@ function confirmReload(title, message) { return new Promise(resolve =>{ reloadButton.onclick = function() { resolve(true); - reloadButton.textContent = 'Reloading...'; + reloadButton.textContent = Phoenix.isNativeApp ? 'Quitting...' : 'Reloading...'; reloadButton.style.color = 'darkgray'; reloadButton.style.backgroundColor = 'grey'; }; @@ -311,6 +312,14 @@ function confirmReload(title, message) { } function resetCacheAndRestart() { + // In native apps, we can't reload because AES trust ring won't survive - must quit + if (Phoenix.isNativeApp) { + // wait for 3 seconds for bugsnag to send report, then quit + setTimeout(() => { + Phoenix.app.closeWindow(true); // force close + }, 1000); + return; + } // try a cache reset if(window._resetCacheIfNeeded){ window._resetCacheIfNeeded(true) @@ -341,7 +350,9 @@ async function _recoverOnFailure(err) { 'Critical error when loading brackets. Trying to reload again.'); const restartedOnce = sessionStorage.getItem(SESSION_RESTART_ONCE_DUE_TO_CRITICAL_ERROR); let shouldRestart; - if(!restartedOnce){ + // In native apps, we can't auto-restart because the AES trust ring won't survive a reload + // without proper dismantling. Always show confirmation dialog for native apps. + if(!restartedOnce && !Phoenix.isNativeApp){ sessionStorage.setItem(SESSION_RESTART_ONCE_DUE_TO_CRITICAL_ERROR, "true"); shouldRestart = true; } else { diff --git a/src/node-loader.js b/src/node-loader.js index a71852c7cd..67bcf80c1a 100644 --- a/src/node-loader.js +++ b/src/node-loader.js @@ -635,110 +635,230 @@ function nodeLoader() { nodeErrorLogCount = 0; }, NODE_ERROR_LOGS_RESET_INTERVAL); - window.__TAURI__.path.resolveResource("src-node/index.js") - .then(async nodeSrcPath=>{ - // Strip Windows UNC prefix (\\?\) that Tauri adds on Windows - // Node 24 doesn't handle UNC paths correctly in module resolution - if (Phoenix.platform === "win" && nodeSrcPath.startsWith('\\\\?\\')) { - nodeSrcPath = nodeSrcPath.slice(4); + async function _tauriNodeSetup() { + let nodeSrcPath = await window.__TAURI__.path.resolveResource("src-node/index.js"); + // Strip Windows UNC prefix (\\?\) that Tauri adds on Windows + // Node 24 doesn't handle UNC paths correctly in module resolution + if (Phoenix.platform === "win" && nodeSrcPath.startsWith('\\\\?\\')) { + nodeSrcPath = nodeSrcPath.slice(4); + } + if(Phoenix.platform === "linux") { + // in linux installed distributions, src-node is present in the same dir as the executable. + const cliArgs = await window.__TAURI__.invoke('_get_commandline_args'); + nodeSrcPath = `${window.path.dirname(cliArgs[0])}/src-node/index.js`; + } + // node is designed such that it is not required at boot time to lower startup time. + // Keep this so to increase boot speed. + const inspectPort = Phoenix.isTestWindow ? getRandomNumber(5000, 50000) : 9229; + const argsArray = isInspectEnabled() ? [`--inspect=${inspectPort}`, nodeSrcPath] : [nodeSrcPath, '']; + command = window.__TAURI__.shell.Command.sidecar('phnode', argsArray); + command.on('close', data => { + window.isNodeTerminated = true; + window.isNodeReady = false; + nodeTerminationResolve(); + console.log(`PhNode: command finished with code ${data.code} and signal ${data.signal}`); + if(!resolved) { + reject("PhNode: closed - Terminated."); } - if(Phoenix.platform === "linux") { - // in linux installed distributions, src-node is present in the same dir as the executable. - const cliArgs = await window.__TAURI__.invoke('_get_commandline_args'); - nodeSrcPath = `${window.path.dirname(cliArgs[0])}/src-node/index.js`; + }); + command.on('error', error => { + window.isNodeTerminated = true; + window.isNodeReady = false; + nodeTerminationResolve(); + console.error(`PhNode: command error: "${error}"`); + if(!resolved) { + logger.reportError(error, `PhNode failed to start!`); + reject("PhNode: closed - Terminated."); } - // node is designed such that it is not required at boot time to lower startup time. - // Keep this so to increase boot speed. - const inspectPort = Phoenix.isTestWindow ? getRandomNumber(5000, 50000) : 9229; - const argsArray = isInspectEnabled() ? [`--inspect=${inspectPort}`, nodeSrcPath] : [nodeSrcPath, '']; - command = window.__TAURI__.shell.Command.sidecar('phnode', argsArray); - command.on('close', data => { - window.isNodeTerminated = true; - window.isNodeReady = false; - nodeTerminationResolve(); - console.log(`PhNode: command finished with code ${data.code} and signal ${data.signal}`); - if(!resolved) { - reject("PhNode: closed - Terminated."); - } - }); - command.on('error', error => { - window.isNodeTerminated = true; - window.isNodeReady = false; - nodeTerminationResolve(); - console.error(`PhNode: command error: "${error}"`); - if(!resolved) { - logger.reportError(error, `PhNode failed to start!`); - reject("PhNode: closed - Terminated."); - } - }); - command.stdout.on('data', line => { - if(line){ - if(line.startsWith(COMMAND_RESPONSE_PREFIX)){ - // its a js response object - line = line.replace(COMMAND_RESPONSE_PREFIX, ""); - const jsonMsg = JSON.parse(line); - pendingCommands[jsonMsg.commandID].resolve(jsonMsg.message); - delete pendingCommands[jsonMsg.commandID]; - } else if(line.startsWith(COMMAND_ERROR_PREFIX)){ - // its a js response object - line = line.replace(COMMAND_ERROR_PREFIX, ""); - const err = JSON.parse(line); - logger.reportError(err, `PhNode ${err.type}:${err.code?err.code:''}`); - } else { - console.log(`PhNode: ${line}`); - } + }); + command.stdout.on('data', line => { + if(line){ + if(line.startsWith(COMMAND_RESPONSE_PREFIX)){ + // its a js response object + line = line.replace(COMMAND_RESPONSE_PREFIX, ""); + const jsonMsg = JSON.parse(line); + pendingCommands[jsonMsg.commandID].resolve(jsonMsg.message); + delete pendingCommands[jsonMsg.commandID]; + } else if(line.startsWith(COMMAND_ERROR_PREFIX)){ + // its a js response object + line = line.replace(COMMAND_ERROR_PREFIX, ""); + const err = JSON.parse(line); + logger.reportError(err, `PhNode ${err.type}:${err.code?err.code:''}`); + } else { + console.log(`PhNode: ${line}`); } + } + }); + command.stderr.on('data', line => { + if(window.debugMode || nodeErrorLogCount < MAX_NODE_ERROR_LOGS_ALLOWED){ + // in release builds, too many node errors from file system/other sources can + // happen, Eg. user opens a very large project and fs watchers goes bust. + // if that happens, the app may get stuck logging large number of errors to console, so + // we show atmost 10 error lines every 10 seconds in non-debug builds. + console.error(`PhNode: ${line}`); + } + nodeErrorLogCount ++; + }); + child = await command.spawn(); + + const execNode = function (commandCode, commandData) { + if(window.isNodeTerminated){ + return Promise.reject("Node is terminated! Cannot execute: " + commandCode); + } + const newCommandID = commandID ++; + child.write(JSON.stringify({ + commandCode: commandCode, commandID: newCommandID, commandData + }) + "\n"); + let resolveP, rejectP; + const promise = new Promise((resolve, reject) => { resolveP = resolve; rejectP=reject; }); + pendingCommands[newCommandID]= {resolve: resolveP, reject: rejectP}; + return promise; + }; + + window.PhNodeEngine.terminateNode = function () { + if(!window.isNodeTerminated) { + execNode(NODE_COMMANDS.TERMINATE); + } + return nodeTerminationPromise; + }; + window.PhNodeEngine.getInspectPort = function () { + return inspectPort; + }; + + execNode(NODE_COMMANDS.GET_ENDPOINTS) + .then(message=>{ + fs.setNodeWSEndpoint(message.phoenixFSURL); + fs.forceUseNodeWSEndpoint(true); + setNodeWSEndpoint(message.phoenixNodeURL); + KernalModeTrust.localAutoAuthURL = message.autoAuthURL; + window.isNodeReady = true; + resolve(message); + // node is designed such that it is not required at boot time to lower startup time. + // Keep this so to increase boot speed. + window.PhNodeEngine._nodeLoadTime = Date.now() - nodeLoadstartTime; }); - command.stderr.on('data', line => { - if(window.debugMode || nodeErrorLogCount < MAX_NODE_ERROR_LOGS_ALLOWED){ - // in release builds, too many node errors from file system/other sources can - // happen, Eg. user opens a very large project and fs watchers goes bust. - // if that happens, the app may get stuck logging large number of errors to console, so - // we show atmost 10 error lines every 10 seconds in non-debug builds. - console.error(`PhNode: ${line}`); + execNode(NODE_COMMANDS.SET_DEBUG_MODE, window.debugMode); + } + + async function _electronNodeSetup() { + // Get phnode path and src-node path, similar to Tauri's sidecar approach + const phNodePath = await window.electronAPI.getPhNodePath(); + const nodeSrcPath = `${await window.electronAPI.getSrcNodePath()}/index.js`; + + const inspectPort = Phoenix.isTestWindow ? getRandomNumber(5000, 50000) : 9229; + const argsArray = isInspectEnabled() + ? [`--inspect=${inspectPort}`, nodeSrcPath] + : [nodeSrcPath, '']; + + // Spawn the node process + const instanceId = await window.electronAppAPI.spawnProcess(phNodePath, argsArray); + + // Register event handlers - filter by our instanceId since callbacks are global + window.electronAppAPI.onProcessClose((eventInstanceId, data) => { + if (eventInstanceId !== instanceId) { + return; + } + window.isNodeTerminated = true; + window.isNodeReady = false; + nodeTerminationResolve(); + console.log(`PhNode: command finished with code ${data.code} and signal ${data.signal}`); + if (!resolved) { + reject("PhNode: closed - Terminated."); + } + }); + + window.electronAppAPI.onProcessError((eventInstanceId, err) => { + if (eventInstanceId !== instanceId) { + return; + } + window.isNodeTerminated = true; + window.isNodeReady = false; + nodeTerminationResolve(); + console.error(`PhNode: command error: "${err.message}"`); + if (!resolved) { + logger.reportError(err, `PhNode failed to start!`); + reject("PhNode: closed - Terminated."); + } + }); + + window.electronAppAPI.onProcessStdout((eventInstanceId, line) => { + if (eventInstanceId !== instanceId) { + return; + } + if (line) { + if (line.startsWith(COMMAND_RESPONSE_PREFIX)) { + // its a js response object + line = line.replace(COMMAND_RESPONSE_PREFIX, ""); + const jsonMsg = JSON.parse(line); + pendingCommands[jsonMsg.commandID].resolve(jsonMsg.message); + delete pendingCommands[jsonMsg.commandID]; + } else if (line.startsWith(COMMAND_ERROR_PREFIX)) { + // its a js response object + line = line.replace(COMMAND_ERROR_PREFIX, ""); + const err = JSON.parse(line); + logger.reportError(err, `PhNode ${err.type}:${err.code ? err.code : ''}`); + } else { + console.log(`PhNode: ${line}`); } - nodeErrorLogCount ++; + } + }); + + window.electronAppAPI.onProcessStderr((eventInstanceId, line) => { + if (eventInstanceId !== instanceId) { + return; + } + if (window.debugMode || nodeErrorLogCount < MAX_NODE_ERROR_LOGS_ALLOWED) { + console.error(`PhNode: ${line}`); + } + nodeErrorLogCount++; + }); + + const execNode = function (commandCode, commandData) { + if (window.isNodeTerminated) { + return Promise.reject("Node is terminated! Cannot execute: " + commandCode); + } + const newCommandID = commandID++; + window.electronAppAPI.writeToProcess(instanceId, JSON.stringify({ + commandCode: commandCode, commandID: newCommandID, commandData + }) + "\n"); + let resolveP, rejectP; + const promise = new Promise((res, rej) => { resolveP = res; rejectP = rej; }); + pendingCommands[newCommandID] = { resolve: resolveP, reject: rejectP }; + return promise; + }; + + window.PhNodeEngine.terminateNode = function () { + if (!window.isNodeTerminated) { + execNode(NODE_COMMANDS.TERMINATE); + } + return nodeTerminationPromise; + }; + window.PhNodeEngine.getInspectPort = function () { + return inspectPort; + }; + + execNode(NODE_COMMANDS.GET_ENDPOINTS) + .then(message => { + fs.setNodeWSEndpoint(message.phoenixFSURL); + fs.forceUseNodeWSEndpoint(true); + setNodeWSEndpoint(message.phoenixNodeURL); + KernalModeTrust.localAutoAuthURL = message.autoAuthURL; + window.isNodeReady = true; + resolve(message); + window.PhNodeEngine._nodeLoadTime = Date.now() - nodeLoadstartTime; }); - child = await command.spawn(); + execNode(NODE_COMMANDS.SET_DEBUG_MODE, window.debugMode); + } - const execNode = function (commandCode, commandData) { - if(window.isNodeTerminated){ - return Promise.reject("Node is terminated! Cannot execute: " + commandCode); - } - const newCommandID = commandID ++; - child.write(JSON.stringify({ - commandCode: commandCode, commandID: newCommandID, commandData - }) + "\n"); - let resolveP, rejectP; - const promise = new Promise((resolve, reject) => { resolveP = resolve; rejectP=reject; }); - pendingCommands[newCommandID]= {resolve: resolveP, reject: rejectP}; - return promise; - }; - - window.PhNodeEngine.terminateNode = function () { - if(!window.isNodeTerminated) { - execNode(NODE_COMMANDS.TERMINATE); - } - return nodeTerminationPromise; - }; - window.PhNodeEngine.getInspectPort = function () { - return inspectPort; - }; - - execNode(NODE_COMMANDS.GET_ENDPOINTS) - .then(message=>{ - fs.setNodeWSEndpoint(message.phoenixFSURL); - fs.forceUseNodeWSEndpoint(true); - setNodeWSEndpoint(message.phoenixNodeURL); - KernalModeTrust.localAutoAuthURL = message.autoAuthURL; - window.isNodeReady = true; - resolve(message); - // node is designed such that it is not required at boot time to lower startup time. - // Keep this so to increase boot speed. - window.PhNodeEngine._nodeLoadTime = Date.now() - nodeLoadstartTime; - }); - execNode(NODE_COMMANDS.SET_DEBUG_MODE, window.debugMode); + if(window.__TAURI__) { + _tauriNodeSetup().catch(err => { + logger.reportError(err, "PhNode Tauri setup failed"); }); + } else if(window.__ELECTRON__) { + _electronNodeSetup().catch(err => { + logger.reportError(err, "PhNode Electron setup failed"); + }); + } }); } diff --git a/src/phoenix/shell.js b/src/phoenix/shell.js index fcdbf3fc4b..f6796f5122 100644 --- a/src/phoenix/shell.js +++ b/src/phoenix/shell.js @@ -85,9 +85,22 @@ async function openURLInPhoenixWindow(url, { acceptFirstMouse: acceptFirstMouse === undefined ? true : acceptFirstMouse, fileDropEnabled: false }); - tauriWindow.isTauriWindow = true; + tauriWindow.isNativeWindow = true; return tauriWindow; } + if(window.__ELECTRON__){ + const label = await window.electronAPI.createPhoenixWindow(url, { + windowTitle, + fullscreen, + resizable: resizable === undefined ? true : resizable, + height: height || defaultHeight, + minHeight: minHeight || 600, + width: width || defaultWidth, + minWidth: minWidth || 800, + isExtension: _prefixPvt === PHOENIX_EXTENSION_WINDOW_PREFIX + }); + return { label, isNativeWindow: true }; + } let features = 'toolbar=no,location=no, status=no, menubar=no, scrollbars=yes'; features = `${features}, width=${width||defaultWidth}, height=${height||defaultHeight}`; if(resizable === undefined || resizable){ @@ -97,7 +110,7 @@ async function openURLInPhoenixWindow(url, { features = ""; } const nativeWindow = window.open(url, '_blank', features); - nativeWindow.isTauriWindow = false; + nativeWindow.isNativeWindow = false; return nativeWindow; } @@ -123,7 +136,12 @@ Phoenix.app = { if(!Phoenix.isNativeApp){ throw new Error("getProcessID is not supported in browsers"); } - return window.__TAURI__.invoke("get_process_id"); + if(window.__TAURI__){ + return window.__TAURI__.invoke("get_process_id"); + } + if(window.__ELECTRON__){ + return window.electronAPI.getProcessId(); + } }, registerQuitTimeAppUpdateHandler: function (handler) { if(!Phoenix.isNativeApp){ @@ -135,7 +153,12 @@ Phoenix.app = { if(!Phoenix.isNativeApp){ throw new Error("toggle_devtools is not supported in browsers"); } - return window.__TAURI__.invoke("toggle_devtools", {}); + if(window.__TAURI__){ + return window.__TAURI__.invoke("toggle_devtools", {}); + } + if(window.__ELECTRON__){ + return window.electronAPI.toggleDevTools(); + } }, onCloseWindowRequested: function (_closeHandlerCb) { if(typeof _closeHandlerCb !== 'function'){ @@ -145,12 +168,22 @@ Phoenix.app = { throw new Error("onCloseWindowRequested can only be registered once!"); } closeHandlerCb = _closeHandlerCb; - window.__TAURI__.window.appWindow.onCloseRequested((event)=>{ - const shouldClose = closeHandlerCb(); - if(!shouldClose){ - event.preventDefault(); - } - }); + if(window.__TAURI__){ + window.__TAURI__.window.appWindow.onCloseRequested((event)=>{ + const shouldClose = closeHandlerCb(); + if(!shouldClose){ + event.preventDefault(); + } + }); + } else if(window.__ELECTRON__){ + window.electronAPI.registerCloseHandler(); + window.electronAPI.onCloseRequested(()=>{ + const shouldClose = closeHandlerCb(); + if(shouldClose){ + window.electronAPI.allowClose(); + } + }); + } }, closeWindow: async function (forceClose) { if(!Phoenix.isNativeApp){ @@ -160,9 +193,14 @@ Phoenix.app = { let extensionWindowCount = 0; try{ instanceCount = await Phoenix.app.getPhoenixInstanceCount(); - const allTauriWindowsLabels = await window.__TAURI__.invoke('_get_window_labels'); - for(let tauriWindowLabel of allTauriWindowsLabels){ - if(tauriWindowLabel && tauriWindowLabel.startsWith(PHOENIX_EXTENSION_WINDOW_PREFIX)) { + let allWindowLabels; + if(window.__TAURI__){ + allWindowLabels = await window.__TAURI__.invoke('_get_window_labels'); + } else if(window.__ELECTRON__){ + allWindowLabels = await window.electronAPI.getWindowLabels(); + } + for(let windowLabel of allWindowLabels){ + if(windowLabel && windowLabel.startsWith(PHOENIX_EXTENSION_WINDOW_PREFIX)) { extensionWindowCount ++; } } @@ -179,18 +217,30 @@ Phoenix.app = { console.error(e); } } - window.__TAURI__.process.exit(0); + if(window.__TAURI__){ + window.__TAURI__.process.exit(0); + } else if(window.__ELECTRON__){ + window.electronAPI.quitApp(0); + } return; } - window.__TAURI__.window.getCurrent().close(); + if(window.__TAURI__){ + window.__TAURI__.window.getCurrent().close(); + } else if(window.__ELECTRON__){ + window.electronAPI.closeWindow(); + } }, focusWindow: function () { if(!Phoenix.isNativeApp){ return Promise.reject(new Error("focusWindow is not supported in browsers")); } - window.__TAURI__.window.getCurrent().setAlwaysOnTop(true); - window.__TAURI__.window.getCurrent().setFocus(); - window.__TAURI__.window.getCurrent().setAlwaysOnTop(false); + if(window.__TAURI__){ + window.__TAURI__.window.getCurrent().setAlwaysOnTop(true); + window.__TAURI__.window.getCurrent().setFocus(); + window.__TAURI__.window.getCurrent().setAlwaysOnTop(false); + } else if(window.__ELECTRON__){ + return window.electronAPI.focusWindow(); + } }, /** * Gets the commandline argument in desktop builds and null in browser builds. @@ -222,8 +272,13 @@ Phoenix.app = { }; } cliArgs = null; - cliCWD = await window.__TAURI__.invoke("get_current_working_dir"); - cliArgs = await window.__TAURI__.invoke('_get_commandline_args'); + if(window.__TAURI__){ + cliCWD = await window.__TAURI__.invoke("get_current_working_dir"); + cliArgs = await window.__TAURI__.invoke('_get_commandline_args'); + } else if(window.__ELECTRON__){ + cliCWD = await window.electronAPI.getCwd(); + cliArgs = await window.electronAppAPI.getCliArgs(); + } return { cwd: cliCWD, args: cliArgs @@ -244,7 +299,7 @@ Phoenix.app = { if(handlerFn){ singleInstanceCLIHandler = handlerFn; } - if(Phoenix.isNativeApp){ + if(window.__TAURI__){ window.__TAURI__.event.listen("single-instance", ({payload})=> { handlerFn(payload.args, payload.cwd); }); @@ -283,40 +338,59 @@ Phoenix.app = { window.__TAURI__.event.emit('scheme-request-received', {fileURLArray: filesURLList}); }); }); + } else if(window.__ELECTRON__){ + // Listen for single instance event from main process + window.electronAPI.onSingleInstance((payload) => { + handlerFn(payload.args, payload.cwd); + }); + // macOS deep linking (scheme-request-received, get_mac_deep_link_requests) not implemented for Electron yet + // Implement macOS open-with handling when needed. we dont have a electron edge now in mac/windows. } }, clipboardReadText: function () { - if(Phoenix.isNativeApp){ + if(window.__TAURI__){ return window.__TAURI__.clipboard.readText(); - } else if(window.navigator && window.navigator.clipboard){ + } + if(window.__ELECTRON__){ + return window.electronAPI.clipboardReadText(); + } + if(window.navigator && window.navigator.clipboard){ return window.navigator.clipboard.readText(); } return Promise.reject(new Error("clipboardReadText: Not supported.")); }, clipboardReadFiles: function () { return new Promise((resolve, reject)=>{ - if(Phoenix.isNativeApp){ - window.__TAURI__.tauri.invoke('_get_clipboard_files') - .then(files =>{ - if(!files){ - resolve(files); - return; - } - const vfsPaths = []; - for(let platformPath of files) { - vfsPaths.push(Phoenix.VFS.getTauriVirtualPath(platformPath)); - } - resolve(vfsPaths); - }).catch(reject); + let filesPromise; + if(window.__TAURI__){ + filesPromise = window.__TAURI__.tauri.invoke('_get_clipboard_files'); + } else if(window.__ELECTRON__){ + filesPromise = window.electronAPI.clipboardReadFiles(); } else { resolve(); + return; } + filesPromise.then(files =>{ + if(!files){ + resolve(files); + return; + } + const vfsPaths = []; + for(let platformPath of files) { + vfsPaths.push(Phoenix.VFS.getTauriVirtualPath(platformPath)); + } + resolve(vfsPaths); + }).catch(reject); }); }, copyToClipboard: function (textToCopy) { - if(Phoenix.isNativeApp){ + if(window.__TAURI__){ return window.__TAURI__.clipboard.writeText(textToCopy); - } else if(window.navigator && window.navigator.clipboard){ + } + if(window.__ELECTRON__){ + return window.electronAPI.clipboardWriteText(textToCopy); + } + if(window.navigator && window.navigator.clipboard){ return window.navigator.clipboard.writeText(textToCopy); } const textArea = document.createElement("textarea"); @@ -332,7 +406,12 @@ Phoenix.app = { // use browser full screen api in browsers. return Promise.resolve(!!document.fullscreenElement); } - return window.__TAURI__.window.appWindow.isFullscreen(); + if(window.__TAURI__){ + return window.__TAURI__.window.appWindow.isFullscreen(); + } + if(window.__ELECTRON__){ + return window.electronAPI.isFullscreen(); + } }, setFullscreen: function (enable) { if(!Phoenix.isNativeApp) { @@ -340,12 +419,17 @@ Phoenix.app = { if (enable) { return document.documentElement.requestFullscreen(); } else if (document.exitFullscreen) { - return document.exitFullscreen(); + return document.exitFullscreen(); } else { return Promise.resolve(); } } - return window.__TAURI__.window.appWindow.setFullscreen(enable); + if(window.__TAURI__){ + return window.__TAURI__.window.appWindow.setFullscreen(enable); + } + if(window.__ELECTRON__){ + return window.electronAPI.setFullscreen(enable); + } }, getDisplayLocation: function (fullVFSPath) { // reruns a user-friendly location that can be shown to the user to make some sense of the virtual file path. @@ -390,46 +474,61 @@ Phoenix.app = { throw new Error("Please specify a path to move to trash"); } if(!fullVFSPath.startsWith(Phoenix.VFS.getTauriDir())) { - throw new Error("moveToTrash only works with tauri paths, but got: "+ fullVFSPath); + throw new Error("moveToTrash only works with native paths, but got: "+ fullVFSPath); } const platformPath = Phoenix.fs.getTauriPlatformPath(fullVFSPath); - return window.__TAURI__.invoke('move_to_trash', { deletePath: platformPath }); + if(window.__TAURI__){ + return window.__TAURI__.invoke('move_to_trash', { deletePath: platformPath }); + } + if(window.__ELECTRON__){ + return window.electronAPI.moveToTrash(platformPath); + } }, setWindowTitle: async function (title) { window.document.title = title; - if(Phoenix.isNativeApp) { + if(window.__TAURI__) { await window.__TAURI__.window.appWindow.setTitle(title); + } else if(window.__ELECTRON__) { + await window.electronAPI.setWindowTitle(title); } }, getWindowTitle: async function () { - if(Phoenix.isNativeApp) { + if(window.__TAURI__) { return window.__TAURI__.window.appWindow.title(); } + if(window.__ELECTRON__) { + return window.electronAPI.getWindowTitle(); + } return window.document.title; }, openPathInFileBrowser: function (fullVFSPath){ return new Promise((resolve, reject)=>{ - if(!window.__TAURI__ || + if(!Phoenix.isNativeApp || !fullVFSPath.startsWith(Phoenix.VFS.getTauriDir())) { - reject("openPathInFileBrowser is only currently supported in Native builds for tauri paths!"); + reject("openPathInFileBrowser is only currently supported in Native builds for native paths!"); return; } if(fullVFSPath.toLowerCase().startsWith("http://") || fullVFSPath.toLowerCase().startsWith("https://") || fullVFSPath.toLowerCase().startsWith("file://")) { - reject("Please use openPathInFileBrowser API to open URLs"); + reject("Please use openURLInDefaultBrowser API to open URLs"); return; } const platformPath = Phoenix.fs.getTauriPlatformPath(fullVFSPath); - window.__TAURI__.tauri - .invoke('show_in_folder', {path: platformPath}) - .then(resolve) - .catch(reject); + if(window.__TAURI__){ + window.__TAURI__.tauri + .invoke('show_in_folder', {path: platformPath}) + .then(resolve) + .catch(reject); + } else if(window.__ELECTRON__){ + window.electronAPI.showInFolder(platformPath); + resolve(); + } }); }, openURLInDefaultBrowser: function (url, tabIdentifier='_blank'){ return new Promise((resolve, reject)=>{ - if(!window.__TAURI__) { + if(!Phoenix.isNativeApp) { resolve(window.open(url, tabIdentifier, 'noopener,noreferrer')); return; } @@ -437,9 +536,15 @@ Phoenix.app = { reject("openURLInDefaultBrowser: URL should be http or https, but was " + url); return; } - window.__TAURI__.shell.open(url) - .then(resolve) - .catch(reject); + if(window.__TAURI__){ + window.__TAURI__.shell.open(url) + .then(resolve) + .catch(reject); + } else if(window.__ELECTRON__){ + window.electronAPI.openExternal(url) + .then(resolve) + .catch(reject); + } }); }, /** @@ -456,21 +561,27 @@ Phoenix.app = { console.error("isPrimaryDesktopPhoenixWindow is not supported in browsers!"); return true; } - const currentWindowLabel = window.__TAURI__.window.getCurrent().label; + let currentWindowLabel, allWindowLabels; + if(window.__TAURI__){ + currentWindowLabel = window.__TAURI__.window.getCurrent().label; + allWindowLabels = await window.__TAURI__.invoke('_get_window_labels'); + } else if(window.__ELECTRON__){ + currentWindowLabel = await window.electronAPI.getCurrentWindowLabel(); + allWindowLabels = await window.electronAPI.getWindowLabels(); + } if(currentWindowLabel === 'main'){ // main window if there will be the primary return true; } - const allTauriWindowsLabels = await window.__TAURI__.invoke('_get_window_labels'); - if(allTauriWindowsLabels.includes('main')){ - // we are not main and there is a main window in tauri windows + if(allWindowLabels.includes('main')){ + // we are not main and there is a main window return false; } // the main window has been closed and some other window is the primary now. // the one with the lowest label is primary - for(let tauriWindowLabel of allTauriWindowsLabels){ - if(tauriWindowLabel && tauriWindowLabel.startsWith(PHOENIX_WINDOW_PREFIX) && - currentWindowLabel !== tauriWindowLabel && currentWindowLabel > tauriWindowLabel) { + for(let windowLabel of allWindowLabels){ + if(windowLabel && windowLabel.startsWith(PHOENIX_WINDOW_PREFIX) && + currentWindowLabel !== windowLabel && currentWindowLabel > windowLabel) { return false; } } @@ -484,29 +595,38 @@ Phoenix.app = { if(!Phoenix.isNativeApp) { // there is no primary window concept in browsers. all are primary for now. console.error("getPhoenixInstanceCount is not supported in browsers!"); - return true; + return 1; } let windowCount = 0; - const allTauriWindowsLabels = await window.__TAURI__.invoke('_get_window_labels'); - for(let tauriWindowLabel of allTauriWindowsLabels){ - if(tauriWindowLabel && (tauriWindowLabel.startsWith(PHOENIX_WINDOW_PREFIX) || tauriWindowLabel === 'main')) { + let allWindowLabels; + if(window.__TAURI__){ + allWindowLabels = await window.__TAURI__.invoke('_get_window_labels'); + } else if(window.__ELECTRON__){ + allWindowLabels = await window.electronAPI.getWindowLabels(); + } + for(let windowLabel of allWindowLabels){ + if(windowLabel && (windowLabel.startsWith(PHOENIX_WINDOW_PREFIX) || windowLabel === 'main')) { windowCount ++; } } return windowCount; }, /** - * Returns the operating system CPU architecture for which the tauri app was compiled. Possible values are - * 'x86', 'x86_64', 'arm', 'aarch64', 'mips', 'mips64', 'powerpc', 'powerpc64', 'riscv64', 's390x', 'sparc64'. + * Returns the operating system CPU architecture for which the app was compiled. Possible values are + * 'x86', 'x86_64', 'arm', 'aarch64', 'arm64', 'ia32', 'x64', etc. * @return {Promise} */ getPlatformArch: async function () { if(!Phoenix.isNativeApp) { - // there is no primary window concept in browsers. all are primary for now. console.error("getPlatformArch is not supported in browsers!"); - return true; + return null; + } + if(window.__TAURI__){ + return window.__TAURI__.os.arch(); + } + if(window.__ELECTRON__){ + return window.electronAPI.getPlatformArch(); } - return window.__TAURI__.os.arch(); }, openNewPhoenixEditorWindow: async function (preferredWidth, preferredHeight, _cliArgsArray, _cwd) { const phoenixURL = new URL(location.href); @@ -553,7 +673,12 @@ Phoenix.app = { if(Phoenix.platform !== "win") { throw new Error("_openUrlInBrowserWin is only supported in windows"); } - return window.__TAURI__.invoke('_open_url_in_browser_win', { url, browser }); + if(window.__TAURI__){ + return window.__TAURI__.invoke('_open_url_in_browser_win', { url, browser }); + } + if(window.__ELECTRON__){ + return window.electronAPI.openUrlInBrowserWin(url, browser); + } }, getApplicationSupportDirectory: Phoenix.VFS.getAppSupportDir, getExtensionsDirectory: Phoenix.VFS.getExtensionDir, diff --git a/src/phoenix/trust_ring.js b/src/phoenix/trust_ring.js index bfcd37368a..6f40ee906c 100644 --- a/src/phoenix/trust_ring.js +++ b/src/phoenix/trust_ring.js @@ -185,23 +185,33 @@ const VERSION_PORTER_KEY = Phoenix.isTestWindow ? "VERSION_PORTER_TEST" : "VERSI const { key, iv } = _selectKeys(); async function setCredential(credKey, secret) { - if(!window.__TAURI__){ - throw new Error("Phoenix API key can only be set in tauri shell!"); + if(!window.__IS_NATIVE_SHELL__){ + throw new Error("Phoenix API key can only be set in native shell!"); } if(!credKey){ throw new Error("credKey is required to set credential!"); } - return window.__TAURI__.tauri.invoke("store_credential", {scopeName: credKey, secretVal: secret}); + if(window.__TAURI__) { + return window.__TAURI__.tauri.invoke("store_credential", {scopeName: credKey, secretVal: secret}); + } + if(window.__ELECTRON__) { + return window.electronAPI.storeCredential(credKey, secret); + } } async function getCredential(credKey) { - if(!window.__TAURI__){ - throw new Error("Phoenix API key can only be get in tauri shell!"); + if(!window.__IS_NATIVE_SHELL__){ + throw new Error("Phoenix API key can only be get in native shell!"); } if(!credKey){ throw new Error("credKey is required to get credential!"); } - const encryptedKey = await window.__TAURI__.tauri.invoke("get_credential", {scopeName: credKey}); + let encryptedKey; + if(window.__TAURI__) { + encryptedKey = await window.__TAURI__.tauri.invoke("get_credential", {scopeName: credKey}); + } else if(window.__ELECTRON__) { + encryptedKey = await window.electronAPI.getCredential(credKey); + } if(!encryptedKey){ return null; } @@ -209,13 +219,18 @@ async function getCredential(credKey) { } async function removeCredential(credKey) { - if(!window.__TAURI__){ - throw new Error("Phoenix API key can only be set in tauri shell!"); + if(!window.__IS_NATIVE_SHELL__){ + throw new Error("Phoenix API key can only be removed in native shell!"); } if(!credKey){ throw new Error("credKey is required to remove credential!"); } - return window.__TAURI__.tauri.invoke("delete_credential", {scopeName: credKey}); + if(window.__TAURI__) { + return window.__TAURI__.tauri.invoke("delete_credential", {scopeName: credKey}); + } + if(window.__ELECTRON__) { + return window.electronAPI.deleteCredential(credKey); + } } let _dismatled = false; @@ -231,25 +246,34 @@ async function dismantleKeyring() { console.error("Invalid kernal keys supplied to shutdown. Ignoring kernal trust reset at shutdown."); return; } - if(!window.__TAURI__){ + if(!window.__IS_NATIVE_SHELL__){ return; } - return window.__TAURI__.tauri.invoke("remove_trust_window_aes_key", {key, iv}); + if(window.__TAURI__) { + return window.__TAURI__.tauri.invoke("remove_trust_window_aes_key", {key, iv}); + } + if(window.__ELECTRON__) { + return window.electronAPI.removeTrustWindowAesKey(key, iv); + } } export async function initTrustRing() { - if(!window.__TAURI__){ + if(!window.__IS_NATIVE_SHELL__){ return; } // this will only work once in a window unless dismantleKeyring is called. So this is safe as // a public export as essentially this is a fn that only works in the boot and shutdown phase. - await window.__TAURI__.tauri.invoke("trust_window_aes_key", {key, iv}); + if(window.__TAURI__) { + await window.__TAURI__.tauri.invoke("trust_window_aes_key", {key, iv}); + } else if(window.__ELECTRON__) { + await window.electronAPI.trustWindowAesKey(key, iv); + } - _portCredentials(); + await _portCredentials(); } async function reinstallCreds() { - if(!window.__TAURI__){ - throw new Error("reinstallCreds can only be called in tauri shell!"); + if(!window.__IS_NATIVE_SHELL__){ + throw new Error("reinstallCreds can only be called in native shell!"); } // Read current credential values const apiKey = await getCredential(CRED_KEY_API); diff --git a/src/thirdparty/licences/lmdb.markdown b/src/thirdparty/licences/lmdb.markdown new file mode 100644 index 0000000000..5a80d7579b --- /dev/null +++ b/src/thirdparty/licences/lmdb.markdown @@ -0,0 +1,21 @@ +The MIT License (MIT) + +This project contains is based on the code from the node-lmdb project ([Copyright (c) 2014 Timur Kristóf](https://github.com/venemo/node-lmdb/)) and LMDB, which has a specific [OpenLDAP license](dependencies/lmdb/libraries/liblmdb/LICENSE), + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/src/utils/DragAndDrop.js b/src/utils/DragAndDrop.js index 50af3fbab4..f4bd9f4ab3 100644 --- a/src/utils/DragAndDrop.js +++ b/src/utils/DragAndDrop.js @@ -186,16 +186,20 @@ define(function (require, exports, module) { async function _focusAndOpenDroppedFiles(droppedPaths) { try{ - const currentWindow = window.__TAURI__.window.getCurrent(); - await currentWindow.setAlwaysOnTop(true); - await currentWindow.setAlwaysOnTop(false); + if(window.__TAURI__) { + const currentWindow = window.__TAURI__.window.getCurrent(); + await currentWindow.setAlwaysOnTop(true); + await currentWindow.setAlwaysOnTop(false); + } else if(window.__ELECTRON__) { + await window.electronAPI.focusWindow(); + } } catch (e) { console.error("Error focusing window"); } openDroppedFiles(droppedPaths); } - if(Phoenix.isNativeApp){ + if(window.__TAURI__){ window.__TAURI__.event.listen('file-drop-event-phoenix', ({payload})=> { if(!payload || !payload.pathList || !payload.pathList.length || !payload.windowLabelOfListener || payload.windowLabelOfListener !== window.__TAURI__.window.appWindow.label){ @@ -302,10 +306,24 @@ define(function (require, exports, module) { event.dataTransfer.types && event.dataTransfer.types.includes("Files")){ // in linux, there is a bug in ubuntu 24 where dropping a file will cause a ghost icon which only // goes away on reboot. So we dont support drop files in linux for now. - showAndResizeFileDropWindow(event); + if(window.__TAURI__) { + showAndResizeFileDropWindow(event); + } } - if (files && files.length) { + if(window.__ELECTRON__ && + event.dataTransfer.types && event.dataTransfer.types.includes("Files")) { + // In Electron (Chromium), dataTransfer.files is empty during dragover for + // security reasons - only populated on drop. We must call preventDefault() + // here based on types to allow the drop event to fire. + event.stopPropagation(); + event.preventDefault(); + if ($(".modal.instance").length === 0) { + event.dataTransfer.dropEffect = "copy"; + } else { + event.dataTransfer.dropEffect = "none"; + } + } else if (files && files.length) { event.stopPropagation(); event.preventDefault(); @@ -331,11 +349,34 @@ define(function (require, exports, module) { event.stopPropagation(); event.preventDefault(); - brackets.app.getDroppedFiles(function (err, paths) { - if (!err) { - openDroppedFiles(paths); + if(window.__ELECTRON__) { + // With contextIsolation, file.path is not available. + // Use Electron's webUtils.getPathForFile() exposed via preload. + const droppedVirtualPaths = []; + for (const file of files) { + const filePath = window.electronAPI.getPathForFile(file); + if (filePath) { + try { + droppedVirtualPaths.push( + window.fs.getTauriVirtualPath(filePath) + ); + } catch (e) { + console.error("Error resolving dropped path: ", + filePath); + } + } + } + if (droppedVirtualPaths.length) { + openDroppedFiles(droppedVirtualPaths); } - }); + } else { + // Browser fallback (legacy Brackets API) + brackets.app.getDroppedFiles(function (err, paths) { + if (!err) { + openDroppedFiles(paths); + } + }); + } } } diff --git a/test/SpecRunner.html b/test/SpecRunner.html index 87200c3a8b..9d910e9beb 100644 --- a/test/SpecRunner.html +++ b/test/SpecRunner.html @@ -173,7 +173,9 @@ if(data && data.__fsError) { throw new Error(data.message); } - return data; + // fsReadFile returns binary data, decode to text + const decoder = new TextDecoder("utf-8"); + return decoder.decode(data); }) .catch(err => { console.error("First boot detected or Failed to init storage from cache." +