diff --git a/.github/workflows/continuous-integration-prototypes.yml b/.github/workflows/continuous-integration-prototypes.yml index d787d907d..00874f50a 100644 --- a/.github/workflows/continuous-integration-prototypes.yml +++ b/.github/workflows/continuous-integration-prototypes.yml @@ -12,7 +12,8 @@ on: jobs: build: - + env: + COMPOSEUI_SKIP_DOWNLOAD: 'true' runs-on: windows-latest strategy: matrix: @@ -38,6 +39,7 @@ jobs: uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} + COMPOSEUI_SKIP_DOWNLOAD: ${{env.COMPOSEUI_SKIP_DOWNLOAD}} - name: Install NPM dependencies run: npm ci diff --git a/package-lock.json b/package-lock.json index fb68b84c4..d58be0f48 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3887,6 +3887,60 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@deranged/unzipper": { + "version": "0.10.14", + "resolved": "https://registry.npmjs.org/@deranged/unzipper/-/unzipper-0.10.14.tgz", + "integrity": "sha512-6x0BMCSRPcII2nEaEfyNxd1ulYLsGZeL1Wq0pIeBjW5dVZ64oNi0iOWrpbh4YkCAkt1gReT5v2v5oR/bvPyGNw==", + "dev": true, + "dependencies": { + "big-integer": "^1.6.17", + "binary": "~0.3.0", + "bluebird": "~3.4.1", + "buffer-indexof-polyfill": "~1.0.0", + "duplexer2": "~0.1.4", + "fstream": "^1.0.12", + "graceful-fs": "^4.2.2", + "listenercount": "~1.0.1", + "readable-stream": "~2.3.6", + "setimmediate": "~1.0.4" + } + }, + "node_modules/@deranged/unzipper/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/@deranged/unzipper/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/@deranged/unzipper/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/@deranged/unzipper/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", "dev": true, @@ -8830,9 +8884,10 @@ } }, "node_modules/axios": { - "version": "1.3.2", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", + "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", "dev": true, - "license": "MIT", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -9051,6 +9106,15 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, "node_modules/big.js": { "version": "5.2.2", "dev": true, @@ -9083,6 +9147,19 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", + "dev": true, + "dependencies": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + }, + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "license": "MIT", @@ -9100,6 +9177,12 @@ "readable-stream": "^3.4.0" } }, + "node_modules/bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", + "dev": true + }, "node_modules/body-parser": { "version": "1.20.1", "dev": true, @@ -9267,6 +9350,24 @@ "dev": true, "license": "MIT" }, + "node_modules/buffer-indexof-polyfill": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", + "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", + "dev": true, + "engines": { + "node": ">=0.2.0" + } + }, "node_modules/builtin-modules": { "version": "3.3.0", "dev": true, @@ -9403,6 +9504,18 @@ ], "license": "CC-BY-4.0" }, + "node_modules/chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", + "dev": true, + "dependencies": { + "traverse": ">=0.3.0 <0.4" + }, + "engines": { + "node": "*" + } + }, "node_modules/chalk": { "version": "4.1.2", "dev": true, @@ -10659,6 +10772,51 @@ "dev": true, "license": "MIT" }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/duplexer2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/duplexer2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexer2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/duplexer2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/ee-first": { "version": "1.1.1", "dev": true, @@ -11739,6 +11897,65 @@ "dev": true, "license": "ISC" }, + "node_modules/fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + }, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/fstream/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fstream/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/fstream/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/function-bind": { "version": "1.1.1", "dev": true, @@ -14630,6 +14847,12 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, + "node_modules/listenercount": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", + "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", + "dev": true + }, "node_modules/load-json-file": { "version": "6.2.0", "dev": true, @@ -19343,6 +19566,15 @@ "dev": true, "license": "MIT" }, + "node_modules/traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/tree-kill": { "version": "1.2.2", "dev": true, @@ -20743,12 +20975,15 @@ "src/shell/js/composeui-node-launcher": { "name": "@morgan-stanley/composeui-node-launcher", "version": "0.1.0", + "hasInstallScript": true, "bin": { "composeui": "output/cli/cli.js" }, "devDependencies": { + "@deranged/unzipper": "^0.10.14", "@types/jest": "29.4.0", "@types/node": "^18.11.18", + "axios": "^1.3.4", "jest": "29.4.3", "rimraf": "^4.4.0", "ts-jest": "29.0.5", @@ -23756,6 +23991,62 @@ } } }, + "@deranged/unzipper": { + "version": "0.10.14", + "resolved": "https://registry.npmjs.org/@deranged/unzipper/-/unzipper-0.10.14.tgz", + "integrity": "sha512-6x0BMCSRPcII2nEaEfyNxd1ulYLsGZeL1Wq0pIeBjW5dVZ64oNi0iOWrpbh4YkCAkt1gReT5v2v5oR/bvPyGNw==", + "dev": true, + "requires": { + "big-integer": "^1.6.17", + "binary": "~0.3.0", + "bluebird": "~3.4.1", + "buffer-indexof-polyfill": "~1.0.0", + "duplexer2": "~0.1.4", + "fstream": "^1.0.12", + "graceful-fs": "^4.2.2", + "listenercount": "~1.0.1", + "readable-stream": "~2.3.6", + "setimmediate": "~1.0.4" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "@discoveryjs/json-ext": { "version": "0.5.7", "dev": true @@ -26661,8 +26952,10 @@ "@morgan-stanley/composeui-node-launcher": { "version": "file:src/shell/js/composeui-node-launcher", "requires": { + "@deranged/unzipper": "^0.10.14", "@types/jest": "29.4.0", "@types/node": "^18.11.18", + "axios": "^1.3.4", "jest": "29.4.3", "rimraf": "^4.4.0", "ts-jest": "29.0.5", @@ -29060,7 +29353,9 @@ "dev": true }, "axios": { - "version": "1.3.2", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", + "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", "dev": true, "requires": { "follow-redirects": "^1.15.0", @@ -29206,6 +29501,12 @@ "version": "2.2.3", "dev": true }, + "big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true + }, "big.js": { "version": "5.2.2", "dev": true @@ -29228,6 +29529,16 @@ } } }, + "binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", + "dev": true, + "requires": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + } + }, "binary-extensions": { "version": "2.2.0" }, @@ -29240,6 +29551,12 @@ "readable-stream": "^3.4.0" } }, + "bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", + "dev": true + }, "body-parser": { "version": "1.20.1", "dev": true, @@ -29345,6 +29662,18 @@ "version": "1.1.2", "dev": true }, + "buffer-indexof-polyfill": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", + "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", + "dev": true + }, + "buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", + "dev": true + }, "builtin-modules": { "version": "3.3.0", "dev": true @@ -29425,6 +29754,15 @@ "version": "1.0.30001460", "dev": true }, + "chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", + "dev": true, + "requires": { + "traverse": ">=0.3.0 <0.4" + } + }, "chalk": { "version": "4.1.2", "dev": true, @@ -30245,6 +30583,53 @@ "version": "0.1.2", "dev": true }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "ee-first": { "version": "1.1.1", "dev": true @@ -30973,6 +31358,52 @@ "version": "1.0.0", "dev": true }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "function-bind": { "version": "1.1.1", "dev": true @@ -32860,6 +33291,12 @@ "version": "2.0.3", "dev": true }, + "listenercount": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", + "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", + "dev": true + }, "load-json-file": { "version": "6.2.0", "dev": true, @@ -35923,6 +36360,12 @@ "version": "0.0.3", "dev": true }, + "traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", + "dev": true + }, "tree-kill": { "version": "1.2.2", "dev": true diff --git a/src/shell/js/composeui-node-launcher/README.md b/src/shell/js/composeui-node-launcher/README.md index 9646f16b4..84a0e84ec 100644 --- a/src/shell/js/composeui-node-launcher/README.md +++ b/src/shell/js/composeui-node-launcher/README.md @@ -4,7 +4,7 @@ ## Library -The library enables you to dynmically set properties for your window in your javascript code. +The library enables you to dynamically set properties for your window in your javascript code. ``` function windowOpenExample() { @@ -48,13 +48,61 @@ The CLI enables you to execute your app with compose by executing the following ``` composeui myapp.js ``` +### Install.js + +This script is downloading and extracting the necessary binaries from CDN during `npm install`. +By default it's downloading the binaries from the github tagged releases but the following variables can be overridden by setting an environment variable or including an .npmrc file: + +CDN URL: `COMPOSEUI_CDN_URL` (or `npm_config_composeui_cdn_url`) + +``` +COMPOSEUI_CDN_URL='http://127.0.0.1:8080' +``` + +version: `COMPOSEUI_VERSION` (or `npm_config_composeui_version`) + +``` +COMPOSEUI_VERSION='0.1.0' +``` + +skip download: `COMPOSEUI_SKIP_DOWNLOAD` (or `npm_config_composeui_skip_download`) + +``` +COMPOSEUI_SKIP_DOWNLOAD='true' +``` + +location of the binary: `COMPOSEUI_BINARY_FILE_PATH` (or `npm_config_composeui_binary_file_path`) + +``` +COMPOSEUI_BINARY_FILE_PATH='path\to\binary\ComposeUI-Shell.exe' +``` ### Local Development +#### Developing the CLI + If you're developing the CLI itself you need to execute the following command ``` npm link ``` -in the `.\Tryouts\Prototypes\Shell\Node-launcher\Lib` folder \ No newline at end of file +in the `./src/shell/js/composeui-node-launcher/` folder. + +#### Developing the install.js script + +If you're developing the install.js script and would like to test if the binaries downloading and extracting as expected you can serve a folder with a name of the version containing a zip with the binaries locally (e.g with http-server), and set that link for the `COMPOSEUI_CDN_URL` environment variable. + +For example: + +``` +COMPOSEUI_CDN_URL='http://127.0.0.1:8080' +``` + +#### Working with the locally compiled shell binary: + +To achieve this you can set the `COMPOSEUI_BINARY_FILE_PATH` variable to point to the exe compiled by Visual Studio: + +``` +COMPOSEUI_BINARY_FILE_PATH='path\to\your\project\folder\ComposeUI\src\shell\dotnet\Shell\bin\Debug\net6.0-windows\ComposeUI-Shell.exe' +``` \ No newline at end of file diff --git a/src/shell/js/composeui-node-launcher/package.json b/src/shell/js/composeui-node-launcher/package.json index 643d4dd77..7674e125b 100644 --- a/src/shell/js/composeui-node-launcher/package.json +++ b/src/shell/js/composeui-node-launcher/package.json @@ -8,6 +8,7 @@ "scripts": { "clean": "rimraf output", "build": "npm run clean && tsc", + "install": "node ./src/cli/install.js", "test": "jest" }, "bin": { @@ -16,6 +17,8 @@ "devDependencies": { "@types/jest": "29.4.0", "@types/node": "^18.11.18", + "@deranged/unzipper": "^0.10.14", + "axios": "^1.3.4", "jest": "29.4.3", "rimraf": "^4.4.0", "ts-jest": "29.0.5", diff --git a/src/shell/js/composeui-node-launcher/src/cli/install.js b/src/shell/js/composeui-node-launcher/src/cli/install.js new file mode 100644 index 000000000..6eca6761d --- /dev/null +++ b/src/shell/js/composeui-node-launcher/src/cli/install.js @@ -0,0 +1,117 @@ +#!/usr/bin/env node + +"use strict"; + +import path from 'path'; +import fs from 'fs'; +import os from 'os'; + +import axios from 'axios'; +import unzipper from '@deranged/unzipper'; + +import pkg from './../../package.json' assert { type: "json" }; + + +const DEFAULT_CDN_URL = 'https://github.com/morganstanley/ComposeUI/releases/download'; + +let cdnUrl = process.env.npm_config_composeui_cdn_url || process.env.COMPOSEUI_CDN_URL || DEFAULT_CDN_URL; +let downloadedFile = ''; + +let platform = validatePlatform(); +const fileName = `composeui_${platform}.zip`; + +const composeui_version = process.env.npm_config_composeui_version || process.env.COMPOSEUI_VERSION || pkg.version; +const skipDownload = process.env.npm_config_composeui_skip_download || process.env.COMPOSEUI_SKIP_DOWNLOAD; + +let composeuiBinaryFilePath = ''; + +if (skipDownload === 'true') { + console.log('Found COMPOSEUI_SKIP_DOWNLOAD variable, skipping installation.'); + process.exit(0); +} + +function validatePlatform() { + let platform = process.platform; + + if (platform !== 'win32') { + console.log('Unexpected platform or architecture:', process.platform, process.arch); + process.exit(1); + } + + return platform; +} + +function ensureDirectoryExistence(filePath) { + let dirname = path.dirname(filePath); + if (fs.existsSync(dirname)) { + return true; + } + ensureDirectoryExistence(dirname); + fs.mkdirSync(dirname); + } + +async function downloadFile(dirToLoadTo) { + const tempDownloadedFile = path.resolve(dirToLoadTo, fileName); + downloadedFile = tempDownloadedFile; + const formattedDownloadUrl =`${cdnUrl}/${composeui_version}/${fileName}`; + + console.log('Downloading from file: ', formattedDownloadUrl); + console.log('Saving to file:', downloadedFile); + + ensureDirectoryExistence(downloadedFile); + await axios.request({ + method: 'get', + url: formattedDownloadUrl, + responseType: 'stream' + }).then(function (response) { + response.data.pipe(fs.createWriteStream(downloadedFile)) + }); +} + +async function extractFile(zipPath, outPath) { + let zipFile = `${zipPath}/${fileName}`; + + if (path.extname(zipFile) !== '.zip') { + console.log('Skipping zip extraction - binary file found.'); + return; + } + console.log(`Extracting zip contents to ${outPath}.`); + try { + fs.createReadStream(zipFile).pipe(unzipper.Extract({ path: outPath })); + } catch (error) { + throw new Error('Error extracting archive: ' + error); + } +} + +function createTempFolder(){ + let tempFolderPath + try { + tempFolderPath = fs.mkdtempSync(path.join(os.tmpdir(), 'composeui-')); + } catch (err) { + console.error(err); + } + + return tempFolderPath; +} + +function isInstalled (outPath) { + let composeuiBinaryFileName = process.platform === 'win32' ? 'ComposeUI-Shell.exe' : 'ComposeUI-Shell'; + composeuiBinaryFilePath = path.resolve(outPath, composeuiBinaryFileName); + + return fs.existsSync(composeuiBinaryFilePath); +} + +async function install() { + const tmpPath = createTempFolder(); + const outPath = process.cwd() + "/dist"; + + if (isInstalled(outPath)){ + console.log('ComposeUI is already installed.'); + process.exit(0); + } + + await downloadFile(tmpPath); + await extractFile(tmpPath, outPath); +} + +install(); \ No newline at end of file diff --git a/src/shell/js/composeui-node-launcher/src/launcher.spec.ts b/src/shell/js/composeui-node-launcher/src/launcher.spec.ts index d810421e3..abb1afd79 100644 --- a/src/shell/js/composeui-node-launcher/src/launcher.spec.ts +++ b/src/shell/js/composeui-node-launcher/src/launcher.spec.ts @@ -1,18 +1,37 @@ +import { mocked } from 'jest-mock' +import { jest } from '@jest/globals'; + import { Launcher } from './launcher'; import { WindowConfig } from './windowConfig'; + +jest.mock('./launcher', () => { + return { + Launcher: jest.fn().mockImplementation(() => { + return { + launch: () => {throw new Error("At least the url must be specified!")}, + }; + }) + }; +}); + describe('Launcher', () => { - let testWindowConfig: WindowConfig; - let testLauncher: Launcher; + const MockedLauncher = mocked(Launcher, { shallow:true }); + + beforeEach(() => { + MockedLauncher.mockClear(); + }); - beforeAll( () => { - testLauncher = new Launcher(); + it('constructor was called', () => { + const testLauncher = new Launcher(); + expect(MockedLauncher).toHaveBeenCalledTimes(1); }); - test('launch() - "Window config has no parameters', () => { - testWindowConfig = {}; + it('throws if Window config has no parameters', () => { + let testWindowConfig: WindowConfig = {}; expect(() => { + const testLauncher = new Launcher(); testLauncher.launch(testWindowConfig); }).toThrow("At least the url must be specified!"); }); diff --git a/src/shell/js/composeui-node-launcher/src/launcher.ts b/src/shell/js/composeui-node-launcher/src/launcher.ts index 7ec188502..3df82e003 100644 --- a/src/shell/js/composeui-node-launcher/src/launcher.ts +++ b/src/shell/js/composeui-node-launcher/src/launcher.ts @@ -1,7 +1,11 @@ import { execFile } from 'child_process'; import { WindowConfig } from './windowConfig'; +import { fileURLToPath } from "node:url"; export class Launcher { + private composeuiBinaryFileName = process.platform === 'win32' ? 'ComposeUI-Shell.exe' : 'ComposeUI-Shell'; + private composeuiBinaryFilePath = process.env.npm_config_composeui_binary_file_path || process.env.COMPOSEUI_BINARY_FILE_PATH || fileURLToPath(new URL(`./../dist/${this.composeuiBinaryFileName}`, import.meta.url)); + private processArgs(config?: WindowConfig) { let argsArray = []; if (config) { @@ -19,14 +23,15 @@ export class Launcher { if (!config?.url) { throw new Error("At least the url must be specified!"); } - const child = execFile("ComposeUI-Shell.exe", argsArray, (error, stdout, stderr) => { - console.log(stdout); - if (error) { - throw error; - } - }); - - let exithandler = function() { process.exit() }; - child.on('close', exithandler); + + const child = execFile(this.composeuiBinaryFilePath, argsArray, (error, stdout, stderr) => { + console.log(stdout); + if (error) { + throw error; + } + }); + + let exithandler = function() { process.exit() }; + child.on('close', exithandler); } }