diff --git a/package-lock.json b/package-lock.json index bb76e72..d22122a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vscode-materialize", - "version": "0.0.2", + "version": "0.0.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "vscode-materialize", - "version": "0.0.2", + "version": "0.0.5", "dependencies": { "@iarna/toml": "^2.2.5", "@types/express": "^4.17.17", @@ -18,6 +18,8 @@ "node-fetch": "^3.3.1", "node-jsonwebtoken": "^0.0.1", "pg": "^8.10.0", + "tar": "^6.2.0", + "tar-stream": "^3.1.6", "uuid": "^9.0.0", "vscode-languageclient": "^7.0.0" }, @@ -26,6 +28,7 @@ "@types/glob": "^8.1.0", "@types/mocha": "^10.0.1", "@types/node": "20.2.5", + "@types/tar": "^6.1.6", "@types/vscode": "^1.79.0", "@typescript-eslint/eslint-plugin": "^5.59.8", "@typescript-eslint/parser": "^5.59.8", @@ -1012,6 +1015,25 @@ "integrity": "sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==", "license": "MIT" }, + "node_modules/@types/tar": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/@types/tar/-/tar-6.1.6.tgz", + "integrity": "sha512-HQ06kiiDXz9uqtmE9ksQUn1ovcPr1gGV9EgaCWo6FGYKD0onNBCetBzL0kfcS8Kbj1EFxJWY9jL2W4ZvvtGI8Q==", + "dev": true, + "dependencies": { + "@types/node": "*", + "minipass": "^4.0.0" + } + }, + "node_modules/@types/tar/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/@types/uuid": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.2.tgz", @@ -1805,6 +1827,11 @@ "typed-rest-client": "^1.8.4" } }, + "node_modules/b4a": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", + "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -3254,6 +3281,11 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" + }, "node_modules/fast-glob": { "version": "3.2.12", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", @@ -3512,6 +3544,28 @@ "node": ">=14.14" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -4834,6 +4888,37 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "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==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -5695,6 +5780,11 @@ ], "license": "MIT" }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" + }, "node_modules/quick-lru": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", @@ -6270,6 +6360,15 @@ "node": ">= 0.8" } }, + "node_modules/streamx": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.1.tgz", + "integrity": "sha512-fQMzy2O/Q47rgwErk/eGeLu/roaFWV0jVsogDmrszM9uIw8L5OA+t+V93MgYlufNptfjmYR1tOMWhei/Eh7TQA==", + "dependencies": { + "fast-fifo": "^1.1.0", + "queue-tick": "^1.0.1" + } + }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -6368,6 +6467,22 @@ "node": ">=6" } }, + "node_modules/tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "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/tar-fs": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", @@ -6381,7 +6496,22 @@ "tar-stream": "^2.1.4" } }, - "node_modules/tar-stream": { + "node_modules/tar-fs/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tar-fs/node_modules/tar-stream": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", @@ -6398,19 +6528,33 @@ "node": ">=6" } }, - "node_modules/tar-stream/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "optional": true, + "node_modules/tar-stream": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.6.tgz", + "integrity": "sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/tar/node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "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==", + "bin": { + "mkdirp": "bin/cmd.js" }, "engines": { - "node": ">= 6" + "node": ">=10" } }, "node_modules/targz": { @@ -7930,6 +8074,24 @@ } } }, + "@types/tar": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/@types/tar/-/tar-6.1.6.tgz", + "integrity": "sha512-HQ06kiiDXz9uqtmE9ksQUn1ovcPr1gGV9EgaCWo6FGYKD0onNBCetBzL0kfcS8Kbj1EFxJWY9jL2W4ZvvtGI8Q==", + "dev": true, + "requires": { + "@types/node": "*", + "minipass": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true + } + } + }, "@types/uuid": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.2.tgz", @@ -8495,6 +8657,11 @@ "typed-rest-client": "^1.8.4" } }, + "b4a": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", + "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==" + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -9525,6 +9692,11 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" + }, "fast-glob": { "version": "3.2.12", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", @@ -9712,6 +9884,24 @@ "universalify": "^2.0.0" } }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -10669,6 +10859,30 @@ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, "mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -11267,6 +11481,11 @@ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, + "queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" + }, "quick-lru": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", @@ -11664,6 +11883,15 @@ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true }, + "streamx": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.1.tgz", + "integrity": "sha512-fQMzy2O/Q47rgwErk/eGeLu/roaFWV0jVsogDmrszM9uIw8L5OA+t+V93MgYlufNptfjmYR1tOMWhei/Eh7TQA==", + "requires": { + "fast-fifo": "^1.1.0", + "queue-tick": "^1.0.1" + } + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -11733,6 +11961,31 @@ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true }, + "tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "requires": { + "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" + }, + "dependencies": { + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + } + } + }, "tar-fs": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", @@ -11744,20 +11997,6 @@ "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" - } - }, - "tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, - "optional": true, - "requires": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" }, "dependencies": { "readable-stream": { @@ -11771,9 +12010,33 @@ "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "optional": true, + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + } } } }, + "tar-stream": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.6.tgz", + "integrity": "sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==", + "requires": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, "targz": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/targz/-/targz-1.0.1.tgz", diff --git a/package.json b/package.json index e1a60ab..8d53627 100644 --- a/package.json +++ b/package.json @@ -28,16 +28,22 @@ "pricing": "Free", "icon": "resources/icon.png", "contributes": { - "languages": [{ - "id": "materialize-sql", - "extensions": [".sql"], - "aliases": ["Materialize SQL"], - "icon": { - "light": "resources/file_icon_color.svg", - "dark": "resources/file_icon.svg" - }, - "configuration": "language-configuration.json" - }], + "languages": [ + { + "id": "materialize-sql", + "extensions": [ + ".sql" + ], + "aliases": [ + "Materialize SQL" + ], + "icon": { + "light": "resources/file_icon_color.svg", + "dark": "resources/file_icon.svg" + }, + "configuration": "language-configuration.json" + } + ], "grammars": [ { "language": "materialize-sql", @@ -167,6 +173,7 @@ "@types/glob": "^8.1.0", "@types/mocha": "^10.0.1", "@types/node": "20.2.5", + "@types/tar": "^6.1.6", "@types/vscode": "^1.79.0", "@typescript-eslint/eslint-plugin": "^5.59.8", "@typescript-eslint/parser": "^5.59.8", @@ -183,7 +190,6 @@ "vscode-extension-tester": "^5.8.0" }, "dependencies": { - "vscode-languageclient": "^7.0.0", "@iarna/toml": "^2.2.5", "@types/express": "^4.17.17", "@types/node-fetch": "^2.6.4", @@ -194,6 +200,8 @@ "node-fetch": "^3.3.1", "node-jsonwebtoken": "^0.0.1", "pg": "^8.10.0", - "uuid": "^9.0.0" + "tar": "^6.2.0", + "uuid": "^9.0.0", + "vscode-languageclient": "^7.0.0" } } diff --git a/src/clients/lsp.ts b/src/clients/lsp.ts new file mode 100644 index 0000000..415b64c --- /dev/null +++ b/src/clients/lsp.ts @@ -0,0 +1,179 @@ +import fetch from "node-fetch"; +import path from "path"; +import { + Executable, + LanguageClient, + LanguageClientOptions, + ServerOptions, +} from "vscode-languageclient/node"; +import fs from "fs"; +import zlib from "zlib"; +import tar from "tar"; +import stream from "stream"; +import os from "os"; + +// This endpoint returns a string with the latest LSP version. +const BINARIES_ENDPOINT = "https://binaries.materialize.com"; +const LATEST_VERSION_ENDPOINT = `${BINARIES_ENDPOINT}/mz-lsp-server-latest.version`; + +/// Path to the binaries dir. +const BIN_DIR_PATH: string = path.join(__dirname, "bin"); +/// Tmp dir path to place the downloaded tarball (.tar.gz) +const TMP_DIR_PATH: string = path.join(os.tmpdir()); +/// The server binary path after decompress +const SERVER_DECOMPRESS_PATH: string = path.join(os.tmpdir(), "mz", "bin", "mz-lsp-server"); +/// The final server binary path. +const SERVER_PATH: string = path.join(__dirname, "bin", "mz-lsp-server"); + +/// This class implements the Language Server Protocol (LSP) client for Materialize. +/// The LSP is downloaded for an endpoint an it is out of the bundle. Binaries are heavy-weight +/// and is preferable to download on the first activation. +/// This is only the first approach and will evolve with time. +export default class LspClient { + private client: LanguageClient | undefined; + + constructor() { + this.installLpsServer(); + } + + installLpsServer() { + if (this.isValidOs()) { + if (!fs.existsSync(SERVER_PATH)) { + fs.mkdirSync(BIN_DIR_PATH, { recursive: true }); + this.fetchLsp().then((tarballArrayBuffer) => { + console.log("[LSP]", "Decompressing LSP."); + this.decompress(tarballArrayBuffer, TMP_DIR_PATH).then(() => { + console.log("[LSP]", "Starting the client."); + fs.renameSync(SERVER_DECOMPRESS_PATH, SERVER_PATH); + this.startClient(SERVER_PATH); + }); + }).catch((err) => { + console.error("[LSP]", "Error fetching the LSP: ", err); + }); + } else { + console.log("[LSP]", "The server already exists."); + console.log("[LSP]", "Starting the client."); + this.startClient(SERVER_PATH); + } + } else { + console.error("[LSP]", "Invalid operating system."); + return; + } + } + + decompress(arrayBuffer: ArrayBuffer, path: string) { + const gunzip = zlib.createGunzip(); + const extract = tar.extract({ + cwd: path + }); + + // Pass the buffer. + const bufferStream = new stream.PassThrough(); + bufferStream.end(Buffer.from(arrayBuffer)); + return new Promise((res, rej) => { + console.log("[LSP]", "Starting pipe."); + bufferStream + .pipe(gunzip) + .pipe(extract) + .on('finish', (d: any) => { + console.log("[LSP]", "Server installed."); + res(""); + }) + .on('error', (error: any) => { + console.error("[LSP]", "Error during decompression:", error); + rej("Error during compression"); + }); + }); + } + + isMacOs() { + return process.platform === "darwin"; + } + + isLinuxOs() { + return process.platform === "linux"; + } + + isArm64() { + return process.arch === "arm64"; + } + + isX64() { + return process.arch === "x64"; + } + + getArch() { + if (process.platform === "darwin") { + return "apple-darwin"; + } else if (process.platform === "linux") { + return "unknown-linux-gnu"; + } + } + + getPlatform() { + if (process.arch === "arm64") { + return "arm64"; + } else if (process.arch === "x64") { + return "aarch64"; + } + } + + /** + * Returns the correct endpoint depending the OS. + * @param lastVersion + * @returns + */ + getEndpointByOs(latestVersion: string): string { + const arch = this.getArch(); + const platform = this.getPlatform(); + + if (!arch || !platform) { + throw new Error("Invalid operating system for the LSP."); + } + + return BINARIES_ENDPOINT + `/mz-lsp-server-v${latestVersion}-${this.getPlatform()}-${this.getArch()}.tar.gz`; + } + + async fetchLsp(): Promise { + console.log("[LSP]", "Fetching latest version number."); + const response = await fetch(LATEST_VERSION_ENDPOINT); + const lastVersion: string = await response.text(); + const endpoint = this.getEndpointByOs(lastVersion); + + console.log("[LSP]", `Fetching LSP from: ${endpoint}`); + const binaryResponse = await fetch(endpoint); + const buffer = await binaryResponse.arrayBuffer(); + + return buffer; + } + + startClient(serverPath: string) { + // Build the options + const run: Executable = { + command: serverPath, + }; + const serverOptions: ServerOptions = { + run, + debug: run, + }; + let clientOptions: LanguageClientOptions = { + documentSelector: [{ scheme: "file", language: "materialize-sql"}] + }; + + // Create the language client and start the client. + this.client = new LanguageClient("materialize-language-server", "Materialize language server", serverOptions, clientOptions); + this.client.start(); + } + + /** + * The valid operating systems so far are MacOS (Darwin) ARM64 and Linux x64. + * @returns true if it is one of both OS. + */ + isValidOs() { + return this.getArch() !== undefined && this.getPlatform() !== undefined; + } + + stop() { + this.client && this.client.stop(); + } +} \ No newline at end of file diff --git a/src/context/context.ts b/src/context/context.ts index 8aeb1ad..10c933a 100644 --- a/src/context/context.ts +++ b/src/context/context.ts @@ -4,6 +4,7 @@ import { AdminClient, CloudClient, SqlClient } from "../clients"; import { Config, NonStorableConfigProfile } from "./config"; import { MaterializeObject, MaterializeSchemaObject } from "../providers/schema"; import AppPassword from "./appPassword"; +import LspClient from "../clients/lsp"; import { Errors } from "../utilities/error"; export enum EventType { @@ -32,6 +33,7 @@ export class Context extends EventEmitter { private adminClient?: AdminClient; private cloudClient?: CloudClient; private sqlClient?: SqlClient; + private lspClient: LspClient; private environment?: Environment; @@ -39,6 +41,7 @@ export class Context extends EventEmitter { super(); this.config = new Config(); this.loaded = false; + this.lspClient = new LspClient(); this.loadContext(); } @@ -192,6 +195,10 @@ export class Context extends EventEmitter { } } + stop() { + this.lspClient.stop(); + } + async query(text: string, vals?: Array) { const client = await this.getSqlClient(); diff --git a/src/extension.ts b/src/extension.ts index 88492fd..37fc3a0 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -3,12 +3,12 @@ import { AuthProvider, ResultsProvider, DatabaseTreeProvider } from './providers import { Context, EventType } from './context'; import { randomUUID } from 'crypto'; +// User context. Contains auth information, cluster, database, schema, etc. +let context: Context; + export function activate(vsContext: vscode.ExtensionContext) { console.log("[Extension]", "Activating Materialize extension."); - - // User context. - // Contains auth information, cluster, database, schema, etc. - const context = new Context(); + context = new Context(); // Register the database explorer const databaseTreeProvider = new DatabaseTreeProvider(context); @@ -110,4 +110,5 @@ export function activate(vsContext: vscode.ExtensionContext) { export function deactivate() { console.log("[Extension]", "Deactivating Materialize extension."); + context.stop(); } \ No newline at end of file