diff --git a/package-lock.json b/package-lock.json index 88c63d97..51dcde2e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,15 @@ { "name": "vscode-db2i", - "version": "0.0.6", + "version": "0.1.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "vscode-db2i", - "version": "0.0.6", + "version": "0.1.1", "dependencies": { - "@vscode/webview-ui-toolkit": "^0.8.5", + "@vscode/webview-ui-toolkit": "^1.0.0", + "csv": "^6.1.3", "node-sql-parser": "^4.1.1", "sql-formatter": "^4.0.2" }, @@ -240,27 +241,39 @@ } }, "node_modules/@microsoft/fast-element": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@microsoft/fast-element/-/fast-element-1.7.0.tgz", - "integrity": "sha512-2qpAWuiOSdQfH/XdO8ZtVhlvQVCjHlojWUPoGbvHJDizBccZib+4uGReG87RIBp2Fi0s7ngYPRUioS1Lr+Xe0A==" + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@microsoft/fast-element/-/fast-element-1.10.2.tgz", + "integrity": "sha512-Nh80AEx/caDe4jhFYNT75sTG4k6MWy1N6XfgyhmejAX0ylivYy0M78WI2JgQOqi2ZRozCiNcpAPLVhYyAVN9sA==" }, "node_modules/@microsoft/fast-foundation": { - "version": "2.32.0", - "resolved": "https://registry.npmjs.org/@microsoft/fast-foundation/-/fast-foundation-2.32.0.tgz", - "integrity": "sha512-0RK5c/xNACIXtb05vejIxUQKV1odhNfHykjd+rXeR3EaXIi0gMpzAPnFfEOLLFsjYoi5K4hzAsCAwT6NvCFkZQ==", + "version": "2.46.9", + "resolved": "https://registry.npmjs.org/@microsoft/fast-foundation/-/fast-foundation-2.46.9.tgz", + "integrity": "sha512-jgkVT7bAWIV844eDj3V9cmYFsRIcJ8vMuB4h2SlkJ9EmFbCfimvh6RyAhsHv+bC6QZSS0N0bpZHm5A5QsWgi3Q==", "dependencies": { - "@microsoft/fast-element": "^1.7.0", - "@microsoft/fast-web-utilities": "^5.0.2", + "@microsoft/fast-element": "^1.10.2", + "@microsoft/fast-web-utilities": "^5.4.1", "tabbable": "^5.2.0", "tslib": "^1.13.0" } }, + "node_modules/@microsoft/fast-react-wrapper": { + "version": "0.1.48", + "resolved": "https://registry.npmjs.org/@microsoft/fast-react-wrapper/-/fast-react-wrapper-0.1.48.tgz", + "integrity": "sha512-9NvEjru9Kn5ZKjomAMX6v+eF0DR+eDkxKDwDfi+Wb73kTbrNzcnmlwd4diN15ygH97kldgj2+lpvI4CKLQQWLg==", + "dependencies": { + "@microsoft/fast-element": "^1.9.0", + "@microsoft/fast-foundation": "^2.41.1" + }, + "peerDependencies": { + "react": ">=16.9.0" + } + }, "node_modules/@microsoft/fast-web-utilities": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@microsoft/fast-web-utilities/-/fast-web-utilities-5.0.2.tgz", - "integrity": "sha512-J8Wy64V1NWF/UjFJ1mvmJNNPChbWobsNkJ8xNaV5/M+VKOQEOheojrOS+RmOUG7DKTBlCLIbUvyXsj1YiCfwkA==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@microsoft/fast-web-utilities/-/fast-web-utilities-5.4.1.tgz", + "integrity": "sha512-ReWYncndjV3c8D8iq9tp7NcFNc1vbVHvcBFPME2nNFKNbS1XCesYZGlIlf3ot5EmuOXPlrzUHOWzQ2vFpIkqDg==", "dependencies": { - "exenv-es6": "^1.0.0" + "exenv-es6": "^1.1.1" } }, "node_modules/@tootallnate/once": { @@ -345,12 +358,16 @@ "dev": true }, "node_modules/@vscode/webview-ui-toolkit": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/@vscode/webview-ui-toolkit/-/webview-ui-toolkit-0.8.5.tgz", - "integrity": "sha512-je//PVn/sK1TyJSHiCEvCmKlWMBEhcJQaU4XWFDbCxzJaei6kfb0SSM3wgZrwRqkMY1daOcIDo4KdBKvQLF2Kw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@vscode/webview-ui-toolkit/-/webview-ui-toolkit-1.0.0.tgz", + "integrity": "sha512-/qaHYZXqvIKkao54b7bLzyNH8BC+X4rBmTUx1MvcIiCjqRMxml0BCpqJhnDpfrCb0IOxXRO8cAy1eB5ayzQfBA==", "dependencies": { - "@microsoft/fast-element": "^1.6.0", - "@microsoft/fast-foundation": "^2.21.0" + "@microsoft/fast-element": "^1.6.2", + "@microsoft/fast-foundation": "^2.38.0", + "@microsoft/fast-react-wrapper": "^0.1.18" + }, + "peerDependencies": { + "react": ">=16.9.0" } }, "node_modules/@webassemblyjs/ast": { @@ -968,6 +985,35 @@ "node": ">= 8" } }, + "node_modules/csv": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/csv/-/csv-6.1.3.tgz", + "integrity": "sha512-AO1ZWeHGHZ4rZvB0h2U4iQQwZmDHKuvNooFCz/74/CsYj7NK0H8HLsepEDRQDGjmeSTlx9JX+KVQjyWFFO0FwA==", + "dependencies": { + "csv-generate": "^4.1.0", + "csv-parse": "^5.2.0", + "csv-stringify": "^6.1.3", + "stream-transform": "^3.1.0" + }, + "engines": { + "node": ">= 0.1.90" + } + }, + "node_modules/csv-generate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/csv-generate/-/csv-generate-4.1.0.tgz", + "integrity": "sha512-Z17wI0xmDfpwzB7lShyK7INBt0YMyh5kV7svWTwsBSOa30T6Lq1fHHasmSCtf2rRTI7GnTk52HQRYBk0ToAXQQ==" + }, + "node_modules/csv-parse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-5.2.0.tgz", + "integrity": "sha512-ZuLjTp3Qx2gycoB7FKS9q11KgDL3f0wQszTlNOajS3fHa0jypN/zgjmkam+rczX5dXw5z7+KrDW2hWkM4542Ug==" + }, + "node_modules/csv-stringify": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-6.1.3.tgz", + "integrity": "sha512-jK2oj6VQafoke0uBXYqYhlwLg4d5qNYjikld+oMgdkOiSiFJygDfQJsiK67igX13Vb/DFnCJexnlhiSErjKR4g==" + }, "node_modules/debug": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", @@ -1341,9 +1387,9 @@ } }, "node_modules/exenv-es6": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/exenv-es6/-/exenv-es6-1.0.0.tgz", - "integrity": "sha512-fcG/TX8Ruv9Ma6PBaiNsUrHRJzVzuFMP6LtPn/9iqR+nr9mcLeEOGzXQGLC5CVQSXGE98HtzW2mTZkrCA3XrDg==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exenv-es6/-/exenv-es6-1.1.1.tgz", + "integrity": "sha512-vlVu3N8d6yEMpMsEm+7sUBAI81aqYYuEvfK0jNqmdb/OPXzzH7QWDDnVjMvDSY47JdHEqx/dfC/q8WkfoTmpGQ==" }, "node_modules/fast-deep-equal": { "version": "3.1.3", @@ -1878,8 +1924,7 @@ "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { "version": "3.14.1", @@ -1994,6 +2039,18 @@ "node": ">=10" } }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -2515,6 +2572,18 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -2817,6 +2886,11 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "node_modules/stream-transform": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-3.1.0.tgz", + "integrity": "sha512-ncT/rST/M2N2zGLacJmeB7TNq/XS8Ck0xqvhYX6bgLwSPTSZLVFCSvNnwTU+RYhk9fAfwzCkYH9I5kdgcDMvfw==" + }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -2904,9 +2978,9 @@ } }, "node_modules/tabbable": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.2.1.tgz", - "integrity": "sha512-40pEZ2mhjaZzK0BnI+QGNjJO8UYx9pP5v7BGe17SORTO0OEuuaAwQTkAp8whcZvqon44wKFOikD+Al11K3JICQ==" + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz", + "integrity": "sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA==" }, "node_modules/table": { "version": "6.7.2", @@ -3663,27 +3737,36 @@ } }, "@microsoft/fast-element": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@microsoft/fast-element/-/fast-element-1.7.0.tgz", - "integrity": "sha512-2qpAWuiOSdQfH/XdO8ZtVhlvQVCjHlojWUPoGbvHJDizBccZib+4uGReG87RIBp2Fi0s7ngYPRUioS1Lr+Xe0A==" + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@microsoft/fast-element/-/fast-element-1.10.2.tgz", + "integrity": "sha512-Nh80AEx/caDe4jhFYNT75sTG4k6MWy1N6XfgyhmejAX0ylivYy0M78WI2JgQOqi2ZRozCiNcpAPLVhYyAVN9sA==" }, "@microsoft/fast-foundation": { - "version": "2.32.0", - "resolved": "https://registry.npmjs.org/@microsoft/fast-foundation/-/fast-foundation-2.32.0.tgz", - "integrity": "sha512-0RK5c/xNACIXtb05vejIxUQKV1odhNfHykjd+rXeR3EaXIi0gMpzAPnFfEOLLFsjYoi5K4hzAsCAwT6NvCFkZQ==", + "version": "2.46.9", + "resolved": "https://registry.npmjs.org/@microsoft/fast-foundation/-/fast-foundation-2.46.9.tgz", + "integrity": "sha512-jgkVT7bAWIV844eDj3V9cmYFsRIcJ8vMuB4h2SlkJ9EmFbCfimvh6RyAhsHv+bC6QZSS0N0bpZHm5A5QsWgi3Q==", "requires": { - "@microsoft/fast-element": "^1.7.0", - "@microsoft/fast-web-utilities": "^5.0.2", + "@microsoft/fast-element": "^1.10.2", + "@microsoft/fast-web-utilities": "^5.4.1", "tabbable": "^5.2.0", "tslib": "^1.13.0" } }, + "@microsoft/fast-react-wrapper": { + "version": "0.1.48", + "resolved": "https://registry.npmjs.org/@microsoft/fast-react-wrapper/-/fast-react-wrapper-0.1.48.tgz", + "integrity": "sha512-9NvEjru9Kn5ZKjomAMX6v+eF0DR+eDkxKDwDfi+Wb73kTbrNzcnmlwd4diN15ygH97kldgj2+lpvI4CKLQQWLg==", + "requires": { + "@microsoft/fast-element": "^1.9.0", + "@microsoft/fast-foundation": "^2.41.1" + } + }, "@microsoft/fast-web-utilities": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@microsoft/fast-web-utilities/-/fast-web-utilities-5.0.2.tgz", - "integrity": "sha512-J8Wy64V1NWF/UjFJ1mvmJNNPChbWobsNkJ8xNaV5/M+VKOQEOheojrOS+RmOUG7DKTBlCLIbUvyXsj1YiCfwkA==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@microsoft/fast-web-utilities/-/fast-web-utilities-5.4.1.tgz", + "integrity": "sha512-ReWYncndjV3c8D8iq9tp7NcFNc1vbVHvcBFPME2nNFKNbS1XCesYZGlIlf3ot5EmuOXPlrzUHOWzQ2vFpIkqDg==", "requires": { - "exenv-es6": "^1.0.0" + "exenv-es6": "^1.1.1" } }, "@tootallnate/once": { @@ -3765,12 +3848,13 @@ "dev": true }, "@vscode/webview-ui-toolkit": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/@vscode/webview-ui-toolkit/-/webview-ui-toolkit-0.8.5.tgz", - "integrity": "sha512-je//PVn/sK1TyJSHiCEvCmKlWMBEhcJQaU4XWFDbCxzJaei6kfb0SSM3wgZrwRqkMY1daOcIDo4KdBKvQLF2Kw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@vscode/webview-ui-toolkit/-/webview-ui-toolkit-1.0.0.tgz", + "integrity": "sha512-/qaHYZXqvIKkao54b7bLzyNH8BC+X4rBmTUx1MvcIiCjqRMxml0BCpqJhnDpfrCb0IOxXRO8cAy1eB5ayzQfBA==", "requires": { - "@microsoft/fast-element": "^1.6.0", - "@microsoft/fast-foundation": "^2.21.0" + "@microsoft/fast-element": "^1.6.2", + "@microsoft/fast-foundation": "^2.38.0", + "@microsoft/fast-react-wrapper": "^0.1.18" } }, "@webassemblyjs/ast": { @@ -4261,6 +4345,32 @@ "which": "^2.0.1" } }, + "csv": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/csv/-/csv-6.1.3.tgz", + "integrity": "sha512-AO1ZWeHGHZ4rZvB0h2U4iQQwZmDHKuvNooFCz/74/CsYj7NK0H8HLsepEDRQDGjmeSTlx9JX+KVQjyWFFO0FwA==", + "requires": { + "csv-generate": "^4.1.0", + "csv-parse": "^5.2.0", + "csv-stringify": "^6.1.3", + "stream-transform": "^3.1.0" + } + }, + "csv-generate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/csv-generate/-/csv-generate-4.1.0.tgz", + "integrity": "sha512-Z17wI0xmDfpwzB7lShyK7INBt0YMyh5kV7svWTwsBSOa30T6Lq1fHHasmSCtf2rRTI7GnTk52HQRYBk0ToAXQQ==" + }, + "csv-parse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-5.2.0.tgz", + "integrity": "sha512-ZuLjTp3Qx2gycoB7FKS9q11KgDL3f0wQszTlNOajS3fHa0jypN/zgjmkam+rczX5dXw5z7+KrDW2hWkM4542Ug==" + }, + "csv-stringify": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-6.1.3.tgz", + "integrity": "sha512-jK2oj6VQafoke0uBXYqYhlwLg4d5qNYjikld+oMgdkOiSiFJygDfQJsiK67igX13Vb/DFnCJexnlhiSErjKR4g==" + }, "debug": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", @@ -4537,9 +4647,9 @@ } }, "exenv-es6": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/exenv-es6/-/exenv-es6-1.0.0.tgz", - "integrity": "sha512-fcG/TX8Ruv9Ma6PBaiNsUrHRJzVzuFMP6LtPn/9iqR+nr9mcLeEOGzXQGLC5CVQSXGE98HtzW2mTZkrCA3XrDg==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exenv-es6/-/exenv-es6-1.1.1.tgz", + "integrity": "sha512-vlVu3N8d6yEMpMsEm+7sUBAI81aqYYuEvfK0jNqmdb/OPXzzH7QWDDnVjMvDSY47JdHEqx/dfC/q8WkfoTmpGQ==" }, "fast-deep-equal": { "version": "3.1.3", @@ -4936,8 +5046,7 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { "version": "3.14.1", @@ -5031,6 +5140,15 @@ "chalk": "^4.0.0" } }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "peer": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -5422,6 +5540,15 @@ "safe-buffer": "^5.1.0" } }, + "react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "peer": true, + "requires": { + "loose-envify": "^1.1.0" + } + }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -5643,6 +5770,11 @@ } } }, + "stream-transform": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-3.1.0.tgz", + "integrity": "sha512-ncT/rST/M2N2zGLacJmeB7TNq/XS8Ck0xqvhYX6bgLwSPTSZLVFCSvNnwTU+RYhk9fAfwzCkYH9I5kdgcDMvfw==" + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -5708,9 +5840,9 @@ "dev": true }, "tabbable": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.2.1.tgz", - "integrity": "sha512-40pEZ2mhjaZzK0BnI+QGNjJO8UYx9pP5v7BGe17SORTO0OEuuaAwQTkAp8whcZvqon44wKFOikD+Al11K3JICQ==" + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz", + "integrity": "sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA==" }, "table": { "version": "6.7.2", diff --git a/package.json b/package.json index cdaf8393..b8acb8c5 100644 --- a/package.json +++ b/package.json @@ -7,13 +7,13 @@ "engines": { "vscode": "^1.61.0" }, - "icon": "media/logo.png", - "keywords": [ - "ibmi", - "as400", + "icon": "media/logo.png", + "keywords": [ + "ibmi", + "as400", "db2", "database" - ], + ], "categories": [ "Other" ], @@ -28,9 +28,9 @@ "onStartupFinished" ], "extensionDependencies": [ - "halcyontechltd.code-for-ibmi" - ], - "main": "./dist/extension.js", + "halcyontechltd.code-for-ibmi" + ], + "main": "./dist/extension.js", "contributes": { "snippets": [ { @@ -68,9 +68,25 @@ "title": "Db2 for i", "icon": "$(database)" } - ] + ], + "panel": [ + { + "id": "ibmi-panel", + "title": "IBM i", + "icon": "$(search)" + } + ] }, "views": { + "ibmi-panel": [ + { + "type": "webview", + "id": "vscode-db2i.resultset", + "name": "Results", + "when": "code-for-ibmi:connected == true", + "contextualTitle": "IBM i" + } + ], "db2-explorer": [ { "id": "schemaBrowser", @@ -86,6 +102,13 @@ "contents": "No connection found. Connect to an IBM i first." } ], + "keybindings":[ + { + "command": "vscode-db2i.runEditorStatement", + "key": "ctrl+r", + "mac": "cmd+r" + } + ], "commands": [ { "command": "vscode-db2i.refreshSchemaBrowser", @@ -122,18 +145,37 @@ "category": "Db2 for i" }, { - "command": "vscode-db2i.pasteGenerator", - "title": "Paste JSON as SQL" + "command": "vscode-db2i.pasteGenerator", + "title": "Paste JSON as SQL", + "category": "Db2 for i" + }, + { + "command": "vscode-db2i.runEditorStatement", + "title": "Run selected statement", + "category": "Db2 for i", + "icon": "$(notebook-execute)" } ], "menus": { "editor/context": [ + { + "command": "vscode-db2i.pasteGenerator", + "group": "1_sql", + "when": "editorLangId == sql" + } + ], + "editor/title": [ + { + "command": "vscode-db2i.runEditorStatement", + "when": "editorLangId == sql", + "group": "navigation@2" + }, { - "command": "vscode-db2i.pasteGenerator", - "group": "1_sql", - "when": "editorLangId == sql" - } - ], + "command": "code-for-ibmi.changeCurrentLibrary", + "when": "editorLangId == sql", + "group": "navigation@3" + } + ], "view/title": [ { "command": "vscode-db2i.addSchemaToSchemaBrowser", @@ -148,10 +190,10 @@ ], "view/item/context": [ { - "command": "vscode-db2i.setCurrentSchema", - "when": "viewItem == schema", - "group": "db2@1" - }, + "command": "vscode-db2i.setCurrentSchema", + "when": "viewItem == schema", + "group": "db2@1" + }, { "command": "vscode-db2i.generateSelect", "when": "viewItem == table || viewItem == view || viewItem == alias", @@ -160,12 +202,12 @@ { "command": "vscode-db2i.generateSQL", "when": "viewItem == table || viewItem == view || viewItem == alias || viewItem == constraint || viewItem == function || viewItem == variable || viewItem == index || viewItem == procedure || viewItem == sequence || viewItem == package || viewItem == trigger || viewItem == type", - "group": "db2@2" + "group": "db2@2" }, { "command": "vscode-db2i.removeSchemaFromSchemaBrowser", "when": "view == schemaBrowser && viewItem == schema", - "group": "db2@3" + "group": "db2@3" } ] } @@ -174,26 +216,27 @@ "lint": "eslint .", "pretest": "npm run lint", "test": "node ./test/runTest.js", - "package": "vsce package", + "package": "vsce package", "vscode:prepublish": "webpack --mode production", - "webpack": "webpack --mode development", - "webpack-dev": "webpack --mode development --watch" + "webpack": "webpack --mode development", + "webpack-dev": "webpack --mode development --watch" }, "devDependencies": { "@types/glob": "^7.1.3", "@types/mocha": "^8.2.2", "@types/node": "14.x", "@types/vscode": "^1.61.0", - "webpack": "^5.24.3", - "webpack-cli": "^4.5.0", "eslint": "^7.32.0", "glob": "^7.1.7", "mocha": "^8.4.0", "typescript": "^4.3.2", - "vscode-test": "^1.5.2" + "vscode-test": "^1.5.2", + "webpack": "^5.24.3", + "webpack-cli": "^4.5.0" }, "dependencies": { - "@vscode/webview-ui-toolkit": "^0.8.5", + "@vscode/webview-ui-toolkit": "^1.0.0", + "csv": "^6.1.3", "node-sql-parser": "^4.1.1", "sql-formatter": "^4.0.2" } diff --git a/src/extension.js b/src/extension.js index bf6bfac2..a8725da1 100644 --- a/src/extension.js +++ b/src/extension.js @@ -5,6 +5,7 @@ const schemaBrowser = require(`./views/schemaBrowser`); const JSONServices = require(`./language/json`); const languageProvider = require(`./language/provider`); +const resultsProvider = require(`./language/results`); // this method is called when your extension is activated // your extension is activated the very first time the command is executed @@ -27,6 +28,7 @@ function activate(context) { JSONServices.initialise(context); languageProvider.initialise(context); + resultsProvider.initialise(context); } // this method is called when your extension is deactivated diff --git a/src/language/results/html.js b/src/language/results/html.js new file mode 100644 index 00000000..d5659293 --- /dev/null +++ b/src/language/results/html.js @@ -0,0 +1,128 @@ +const WebToolkit = require(`@vscode/webview-ui-toolkit/dist/toolkit.min.js`); + +const head = /*html*/` + + + + `; + +exports.setLoadingText = (webview, text) => { + webview.postMessage({ + command: `loadingText`, + text, + }); +} + +exports.getLoadingHTML = () => { + return /*html*/ ` + + + + ${head} + + + +

Loading..

+
+

+ + + + `; +} + +/** + * + * @param {object[]} rows + * @returns {string} + */ +exports.generateResults = (rows) => { + const columns = Object.keys(rows[0]).map(column => ({ + title: column, + columnDataKey: column, + })); + + const inlineData = this.generateTable(`results`, columns, rows); + + return /*html*/ ` + + + + ${head} + + + + ${inlineData.html} + + + `; +} + +/** + * + * @param {{title: string, columnDataKey: string|number, transform?: (row: object) => string|number}[]} columns + * @param {object[]} rows + * @returns {{html: string, js: string}} + */ +exports.generateTable = (id, columns, rows) => { + rows.forEach(row => { + columns.forEach(column => { + if (row[column.columnDataKey] && column.transform) { + row[column.columnDataKey] = column.transform(row); + } + }); + }); + + let result = { + html: ``, + js: [ + `const ${id} = document.getElementById("${id}");`, + `${id}.columnDefinitions = ${JSON.stringify(columns)};`, + `${id}.rowsData = ${JSON.stringify(rows)};`, + ].join(``), + }; + + return result; +} \ No newline at end of file diff --git a/src/language/results/index.js b/src/language/results/index.js new file mode 100644 index 00000000..47049bd3 --- /dev/null +++ b/src/language/results/index.js @@ -0,0 +1,279 @@ +const vscode = require(`vscode`); + +const csv = require(`csv/sync`); + +const getInstance = require(`../../base`); +const html = require(`./html`); + +class ResultSetPanelProvider { + constructor() { + /** @type {vscode.WebviewView} */ + this._view = undefined; + + this.loadingState = false; + } + + /** + * + * @param {vscode.WebviewView} webviewView + * @param {vscode.WebviewViewResolveContext} context + * @param {vscode.CancellationToken} _token + */ + resolveWebviewView(webviewView, context, _token) { + this._view = webviewView; + + webviewView.webview.options = { + // Allow scripts in the webview + enableScripts: true, + }; + + webviewView.webview.html = html.getLoadingHTML(); + } + + async focus() { + if (!this._view) { + // Weird one. Kind of a hack. _view.show doesn't work yet because it's not initialized. + // But, we can call a VS Code API to focus on the tab, which then + // 1. calls resolveWebviewView + // 2. sets this._view + await vscode.commands.executeCommand(`vscode-db2i.resultset.focus`); + } + + this._view.show(true); + } + + async setLoadingText(content) { + await this.focus(); + + if (!this.loadingState) { + this._view.webview.html = html.getLoadingHTML(); + this.loadingState = true; + } + + html.setLoadingText(this._view.webview, content); + } + + /** + * @param {object[]} results + */ + setResults(results) { + this.focus(); + this.loadingState = false; + const content = html.generateResults(results); + this._view.webview.html = content; + } + + setError(error) { + // TODO: error + this._view.webview.html = `

${error}

`; + } +} + +/** + * @param {vscode.ExtensionContext} context + */ +exports.initialise = (context) => { + let resultSetProvider = new ResultSetPanelProvider(); + + context.subscriptions.push( + vscode.window.registerWebviewViewProvider(`vscode-db2i.resultset`, resultSetProvider), + + vscode.commands.registerCommand(`vscode-db2i.runEditorStatement`, async () => { + const instance = getInstance(); + const config = instance.getConfig(); + const content = instance.getContent(); + const editor = vscode.window.activeTextEditor; + + if (editor.document.languageId === `sql`) { + const statement = this.parseStatement(editor); + + if (statement.content.trim().length > 0) { + try { + if (statement.type === `cl`) { + const commandResult = await vscode.commands.executeCommand(`code-for-ibmi.runCommand`, { + command: statement.content, + environment: `ile` + }); + + if (commandResult.code === 0 || commandResult.code === null) { + vscode.window.showInformationMessage(`Command executed successfuly.`); + } else { + vscode.window.showErrorMessage(`Command failed to run.`); + } + + let output = ``; + if (commandResult.stderr.length > 0) output += `${commandResult.stderr}\n\n`; + if (commandResult.stdout.length > 0) output += `${commandResult.stdout}\n\n`; + + const textDoc = await vscode.workspace.openTextDocument({language: `txt`, content: output}); + await vscode.window.showTextDocument(textDoc, { + preserveFocus: true, + preview: true + }); + + } else { + statement.content = [ + `SET CURRENT SCHEMA = '${config.currentLibrary.toUpperCase()}'`, + statement.content + ].join(`;\n`); + + if (statement.type === `statement`) { + resultSetProvider.setLoadingText(`Executing statement...`); + } + + const data = await content.runSQL(statement.content); + + if (data.length > 0) { + switch (statement.type) { + case `statement`: + resultSetProvider.setResults(data); + break; + + case `csv`: + case `json`: + case `sql`: + let content = ``; + switch (statement.type) { + case `csv`: content = csv.stringify(data, { + header: true, + quoted_string: true, + }); break; + case `json`: content = JSON.stringify(data, null, 2); break; + + case `sql`: + const keys = Object.keys(data[0]); + + const insertStatement = [ + `insert into TABLE (`, + ` ${keys.join(`, `)}`, + `) values `, + data.map( + row => ` (${keys.map(key => { + if (row[key] === null) return `null`; + if (typeof row[key] === `string`) return `'${row[key].replace(/'/g, `''`)}'`; + return row[key]; + }).join(`, `)})` + ).join(`,\n`), + ]; + content = insertStatement.join(`\n`); + break; + } + + const textDoc = await vscode.workspace.openTextDocument({language: statement.type, content}); + await vscode.window.showTextDocument(textDoc); + break; + } + + } else { + if (statement.type === `statement`) { + resultSetProvider.setError(`Query executed with no data returned.`); + } else { + vscode.window.showInformationMessage(`Query executed with no data returned.`); + } + } + } + + } catch (e) { + let errorText; + if (typeof e === `string`) { + errorText = e.length > 0 ? e : `An error occurred when executing the statement.`; + } else { + errorText = e.message || `Error running SQL statement.`; + } + + if (statement.type === `statement`) { + resultSetProvider.setError(errorText); + } else { + vscode.window.showErrorMessage(errorText); + } + } + } + } + }), + ) +} + + +/** + * @param {vscode.TextEditor} editor + * @returns {{type: "statement"|"cl"|"json"|"csv"|"sql", content: string}} Statement + */ +exports.parseStatement = (editor) => { + const document = editor.document; + const eol = (document.eol === vscode.EndOfLine.LF ? `\n` : `\r\n`); + + let text = document.getText(editor.selection).trim(); + let content; + + /** @type {"statement"|"cl"|"json"|"sql"} */ + let type = `statement`; + + if (text.length > 0) { + content = text; + } else { + const cursor = editor.document.offsetAt(editor.selection.active); + text = document.getText(); + + let statements = []; + + let inQuote = false; + let start = 0, end = 0; + + for (const c of text) { + switch (c) { + case `'`: + inQuote = !inQuote; + break; + + case `;`: + if (!inQuote) { + statements.push({ + start, + end, + text: text.substring(start, end) + }); + + start = end+1; + } + break; + } + end++; + } + + //Add ending + statements.push({ + start, + end, + text: text.substring(start, end) + }); + + let statementData = statements.find(range => cursor >= range.start && cursor <= range.end); + content = statementData.text.trim(); + + editor.selection = new vscode.Selection(editor.document.positionAt(statementData.start), editor.document.positionAt(statementData.end)); + + // Remove blank lines and comment lines + let lines = content.split(eol).filter(line => line.trim().length > 0 && !line.trimStart().startsWith(`--`)); + + lines.forEach((line, startIndex) => { + if (type !== `statement`) return; + + [`cl`, `json`, `csv`, `sql`].forEach(mode => { + if (line.trim().toLowerCase().startsWith(mode + `:`)) { + lines = lines.slice(startIndex); + lines[0] = lines[0].substring(mode.length + 1).trim(); + + content = lines.join(` `); + + //@ts-ignore We know the type. + type = mode; + } + }); + }); + } + + return { + type, + content + }; +} \ No newline at end of file