From 32a958ab959ffb3232df011b964d4fa146c930e5 Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Thu, 6 Feb 2020 08:41:56 -0500 Subject: [PATCH] View open source licenses in app (#1926) * View opensource licenses * Remove redundant check --- packages/insomnia-app/.electronbuilder | 5 + .../insomnia-app/app/main/window-utils.js | 7 + packages/insomnia-app/package-lock.json | 182 ++++++++++++++++++ packages/insomnia-app/package.json | 1 + packages/insomnia-app/scripts/build.js | 49 +++++ 5 files changed, 244 insertions(+) diff --git a/packages/insomnia-app/.electronbuilder b/packages/insomnia-app/.electronbuilder index 2f554dec5c..796ddf5658 100644 --- a/packages/insomnia-app/.electronbuilder +++ b/packages/insomnia-app/.electronbuilder @@ -7,6 +7,11 @@ "from": "./bin", "to": "./bin", "filter": "yarn-standalone.js" + }, + { + "from": "./build", + "to": ".", + "filter": "opensource-licenses.txt" } ], "protocols": [ diff --git a/packages/insomnia-app/app/main/window-utils.js b/packages/insomnia-app/app/main/window-utils.js index 89e595a6ac..9760fc35af 100644 --- a/packages/insomnia-app/app/main/window-utils.js +++ b/packages/insomnia-app/app/main/window-utils.js @@ -260,6 +260,13 @@ export function createWindow() { shell.showItemInFolder(directory); }, }, + { + label: 'Show Open Source Licenses', + click: (menuItem, w, e) => { + const licensePath = path.resolve(app.getAppPath(), '../opensource-licenses.txt'); + shell.openItem(licensePath); + }, + }, { label: `Insomnia ${MNEMONIC_SYM}Help`, accelerator: !isMac() ? 'F1' : null, diff --git a/packages/insomnia-app/package-lock.json b/packages/insomnia-app/package-lock.json index abce07549b..2a1a8e726c 100644 --- a/packages/insomnia-app/package-lock.json +++ b/packages/insomnia-app/package-lock.json @@ -7608,6 +7608,12 @@ "ms": "2.0.0" } }, + "debuglog": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", + "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=", + "dev": true + }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -7895,6 +7901,16 @@ } } }, + "dezalgo": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", + "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "dev": true, + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, "diffie-hellman": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", @@ -12382,6 +12398,70 @@ "type-check": "~0.3.2" } }, + "license-checker": { + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/license-checker/-/license-checker-25.0.1.tgz", + "integrity": "sha512-mET5AIwl7MR2IAKYYoVBBpV0OnkKQ1xGj2IMMeEFIs42QAkEVjRtFZGWmQ28WeU7MP779iAgOaOy93Mn44mn6g==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "debug": "^3.1.0", + "mkdirp": "^0.5.1", + "nopt": "^4.0.1", + "read-installed": "~4.0.3", + "semver": "^5.5.0", + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0", + "spdx-satisfies": "^4.0.0", + "treeify": "^1.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "lie": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", @@ -13577,6 +13657,16 @@ } } }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "dev": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -13606,6 +13696,12 @@ "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", "dev": true }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "dev": true + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -15761,6 +15857,34 @@ } } }, + "read-installed": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/read-installed/-/read-installed-4.0.3.tgz", + "integrity": "sha1-/5uLZ/GH0eTCm5/rMfayI6zRkGc=", + "dev": true, + "requires": { + "debuglog": "^1.0.1", + "graceful-fs": "^4.1.2", + "read-package-json": "^2.0.0", + "readdir-scoped-modules": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "slide": "~1.1.3", + "util-extend": "^1.0.1" + } + }, + "read-package-json": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.1.tgz", + "integrity": "sha512-dAiqGtVc/q5doFz6096CcnXhpYk0ZN8dEKVkGLU0CsASt8SrgF6SF7OTKAYubfvFhWaqofl+Y8HK19GR8jwW+A==", + "dev": true, + "requires": { + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "json-parse-better-errors": "^1.0.1", + "normalize-package-data": "^2.0.0", + "npm-normalize-package-bin": "^1.0.0" + } + }, "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", @@ -15864,6 +15988,18 @@ } } }, + "readdir-scoped-modules": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", + "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", + "dev": true, + "requires": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } + }, "readdirp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", @@ -16762,6 +16898,12 @@ "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", "dev": true }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", + "dev": true + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -17016,6 +17158,17 @@ } } }, + "spdx-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/spdx-compare/-/spdx-compare-1.0.0.tgz", + "integrity": "sha512-C1mDZOX0hnu0ep9dfmuoi03+eOdDoz2yvK79RxbcrVEG1NO1Ph35yW102DHWKN4pk80nwCgeMmSY5L25VE4D9A==", + "dev": true, + "requires": { + "array-find-index": "^1.0.2", + "spdx-expression-parse": "^3.0.0", + "spdx-ranges": "^2.0.0" + } + }, "spdx-correct": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", @@ -17048,6 +17201,23 @@ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, + "spdx-ranges": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/spdx-ranges/-/spdx-ranges-2.1.1.tgz", + "integrity": "sha512-mcdpQFV7UDAgLpXEE/jOMqvK4LBoO0uTQg0uvXUewmEFhpiZx5yJSZITHB8w1ZahKdhfZqP5GPEOKLyEq5p8XA==", + "dev": true + }, + "spdx-satisfies": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/spdx-satisfies/-/spdx-satisfies-4.0.1.tgz", + "integrity": "sha512-WVzZ/cXAzoNmjCWiEluEA3BjHp5tiUmmhn9MK+X0tBbR9sOqtC6UQwmgCNrAIZvNlMuBUYAaHYfb2oqlF9SwKA==", + "dev": true, + "requires": { + "spdx-compare": "^1.0.0", + "spdx-expression-parse": "^3.0.0", + "spdx-ranges": "^2.0.0" + } + }, "spdy": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.1.tgz", @@ -17899,6 +18069,12 @@ "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==", "dev": true }, + "treeify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz", + "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==", + "dev": true + }, "trim-newlines": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", @@ -18412,6 +18588,12 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "util-extend": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz", + "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=", + "dev": true + }, "util.promisify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", diff --git a/packages/insomnia-app/package.json b/packages/insomnia-app/package.json index ca18674c0c..9be84a9e50 100644 --- a/packages/insomnia-app/package.json +++ b/packages/insomnia-app/package.json @@ -207,6 +207,7 @@ "file-loader": "^3.0.1", "less": "^3.8.1", "less-loader": "^4.1.0", + "license-checker": "^25.0.1", "ncp": "^2.0.0", "react-hot-loader": "^4.8.3", "style-loader": "^0.23.1", diff --git a/packages/insomnia-app/scripts/build.js b/packages/insomnia-app/scripts/build.js index 99155332f7..cd51334ea7 100644 --- a/packages/insomnia-app/scripts/build.js +++ b/packages/insomnia-app/scripts/build.js @@ -1,6 +1,7 @@ const packageJson = require('../package.json'); const childProcess = require('child_process'); const webpack = require('webpack'); +const licenseChecker = require('license-checker'); const rimraf = require('rimraf'); const ncp = require('ncp').ncp; const path = require('path'); @@ -31,6 +32,8 @@ module.exports.start = async function() { await emptyDir('../build'); // Build the things + console.log('[build] Building license list'); + await buildLicenseList('../', '../build/opensource-licenses.txt'); console.log('[build] Building Webpack renderer'); await buildWebpack(configRenderer); console.log('[build] Building Webpack main'); @@ -97,6 +100,52 @@ async function copyFiles(relSource, relDest) { }); } +async function buildLicenseList(relSource, relDest) { + return new Promise((resolve, reject) => { + const source = path.resolve(__dirname, relSource); + const dest = path.resolve(__dirname, relDest); + mkdirp.sync(path.dirname(dest)); + + licenseChecker.init({ start: source, production: true }, (err, packages) => { + if (err) { + return reject(err); + } + + const out = []; + for (const pkgName of Object.keys(packages)) { + const { licenses, repository, publisher, email, licenseFile: lf } = packages[pkgName]; + const licenseFile = (lf || '').includes('README') ? null : lf; + const txt = licenseFile ? fs.readFileSync(licenseFile) : '[no license file]'; + const body = [ + '-------------------------------------------------------------------------', + '', + `PACKAGE: ${pkgName}`, + licenses ? `LICENSES: ${licenses}` : null, + repository ? `REPOSITORY: ${repository}` : null, + publisher ? `PUBLISHER: ${publisher}` : null, + email ? `EMAIL: ${email}` : null, + '\n' + txt, + ] + .filter(v => v !== null) + .join('\n'); + + out.push(`${body}\n\n`); + } + + const header = [ + 'This application bundles the following third-party packages in ', + 'accordance with the following licenses:', + '-------------------------------------------------------------------------', + '', + '', + ].join('\n'); + + fs.writeFileSync(dest, header + out.join('\n\n')); + resolve(); + }); + }); +} + async function install(relDir) { return new Promise(resolve => { const prefix = path.resolve(__dirname, relDir);